1/* libFLAC - Free Lossless Audio Codec library
2 * Copyright (C) 2004,2005,2006,2007  Josh Coalson
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#if HAVE_CONFIG_H
33#  include <config.h>
34#endif
35
36#include "FLAC/assert.h"
37
38#include "private/float.h"
39
40#ifdef FLAC__INTEGER_ONLY_LIBRARY
41
42/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
43#ifdef _MSC_VER
44#define FLAC__U64L(x) x
45#else
46#define FLAC__U64L(x) x##LLU
47#endif
48
49const FLAC__fixedpoint FLAC__FP_ZERO = 0;
50const FLAC__fixedpoint FLAC__FP_ONE_HALF = 0x00008000;
51const FLAC__fixedpoint FLAC__FP_ONE = 0x00010000;
52const FLAC__fixedpoint FLAC__FP_LN2 = 45426;
53const FLAC__fixedpoint FLAC__FP_E = 178145;
54
55/* Lookup tables for Knuth's logarithm algorithm */
56#define LOG2_LOOKUP_PRECISION 16
57static const FLAC__uint32 log2_lookup[][LOG2_LOOKUP_PRECISION] = {
58	{
59		/*
60		 * 0 fraction bits
61		 */
62		/* undefined */ 0x00000000,
63		/* lg(2/1) = */ 0x00000001,
64		/* lg(4/3) = */ 0x00000000,
65		/* lg(8/7) = */ 0x00000000,
66		/* lg(16/15) = */ 0x00000000,
67		/* lg(32/31) = */ 0x00000000,
68		/* lg(64/63) = */ 0x00000000,
69		/* lg(128/127) = */ 0x00000000,
70		/* lg(256/255) = */ 0x00000000,
71		/* lg(512/511) = */ 0x00000000,
72		/* lg(1024/1023) = */ 0x00000000,
73		/* lg(2048/2047) = */ 0x00000000,
74		/* lg(4096/4095) = */ 0x00000000,
75		/* lg(8192/8191) = */ 0x00000000,
76		/* lg(16384/16383) = */ 0x00000000,
77		/* lg(32768/32767) = */ 0x00000000
78	},
79	{
80		/*
81		 * 4 fraction bits
82		 */
83		/* undefined */ 0x00000000,
84		/* lg(2/1) = */ 0x00000010,
85		/* lg(4/3) = */ 0x00000007,
86		/* lg(8/7) = */ 0x00000003,
87		/* lg(16/15) = */ 0x00000001,
88		/* lg(32/31) = */ 0x00000001,
89		/* lg(64/63) = */ 0x00000000,
90		/* lg(128/127) = */ 0x00000000,
91		/* lg(256/255) = */ 0x00000000,
92		/* lg(512/511) = */ 0x00000000,
93		/* lg(1024/1023) = */ 0x00000000,
94		/* lg(2048/2047) = */ 0x00000000,
95		/* lg(4096/4095) = */ 0x00000000,
96		/* lg(8192/8191) = */ 0x00000000,
97		/* lg(16384/16383) = */ 0x00000000,
98		/* lg(32768/32767) = */ 0x00000000
99	},
100	{
101		/*
102		 * 8 fraction bits
103		 */
104		/* undefined */ 0x00000000,
105		/* lg(2/1) = */ 0x00000100,
106		/* lg(4/3) = */ 0x0000006a,
107		/* lg(8/7) = */ 0x00000031,
108		/* lg(16/15) = */ 0x00000018,
109		/* lg(32/31) = */ 0x0000000c,
110		/* lg(64/63) = */ 0x00000006,
111		/* lg(128/127) = */ 0x00000003,
112		/* lg(256/255) = */ 0x00000001,
113		/* lg(512/511) = */ 0x00000001,
114		/* lg(1024/1023) = */ 0x00000000,
115		/* lg(2048/2047) = */ 0x00000000,
116		/* lg(4096/4095) = */ 0x00000000,
117		/* lg(8192/8191) = */ 0x00000000,
118		/* lg(16384/16383) = */ 0x00000000,
119		/* lg(32768/32767) = */ 0x00000000
120	},
121	{
122		/*
123		 * 12 fraction bits
124		 */
125		/* undefined */ 0x00000000,
126		/* lg(2/1) = */ 0x00001000,
127		/* lg(4/3) = */ 0x000006a4,
128		/* lg(8/7) = */ 0x00000315,
129		/* lg(16/15) = */ 0x0000017d,
130		/* lg(32/31) = */ 0x000000bc,
131		/* lg(64/63) = */ 0x0000005d,
132		/* lg(128/127) = */ 0x0000002e,
133		/* lg(256/255) = */ 0x00000017,
134		/* lg(512/511) = */ 0x0000000c,
135		/* lg(1024/1023) = */ 0x00000006,
136		/* lg(2048/2047) = */ 0x00000003,
137		/* lg(4096/4095) = */ 0x00000001,
138		/* lg(8192/8191) = */ 0x00000001,
139		/* lg(16384/16383) = */ 0x00000000,
140		/* lg(32768/32767) = */ 0x00000000
141	},
142	{
143		/*
144		 * 16 fraction bits
145		 */
146		/* undefined */ 0x00000000,
147		/* lg(2/1) = */ 0x00010000,
148		/* lg(4/3) = */ 0x00006a40,
149		/* lg(8/7) = */ 0x00003151,
150		/* lg(16/15) = */ 0x000017d6,
151		/* lg(32/31) = */ 0x00000bba,
152		/* lg(64/63) = */ 0x000005d1,
153		/* lg(128/127) = */ 0x000002e6,
154		/* lg(256/255) = */ 0x00000172,
155		/* lg(512/511) = */ 0x000000b9,
156		/* lg(1024/1023) = */ 0x0000005c,
157		/* lg(2048/2047) = */ 0x0000002e,
158		/* lg(4096/4095) = */ 0x00000017,
159		/* lg(8192/8191) = */ 0x0000000c,
160		/* lg(16384/16383) = */ 0x00000006,
161		/* lg(32768/32767) = */ 0x00000003
162	},
163	{
164		/*
165		 * 20 fraction bits
166		 */
167		/* undefined */ 0x00000000,
168		/* lg(2/1) = */ 0x00100000,
169		/* lg(4/3) = */ 0x0006a3fe,
170		/* lg(8/7) = */ 0x00031513,
171		/* lg(16/15) = */ 0x00017d60,
172		/* lg(32/31) = */ 0x0000bb9d,
173		/* lg(64/63) = */ 0x00005d10,
174		/* lg(128/127) = */ 0x00002e59,
175		/* lg(256/255) = */ 0x00001721,
176		/* lg(512/511) = */ 0x00000b8e,
177		/* lg(1024/1023) = */ 0x000005c6,
178		/* lg(2048/2047) = */ 0x000002e3,
179		/* lg(4096/4095) = */ 0x00000171,
180		/* lg(8192/8191) = */ 0x000000b9,
181		/* lg(16384/16383) = */ 0x0000005c,
182		/* lg(32768/32767) = */ 0x0000002e
183	},
184	{
185		/*
186		 * 24 fraction bits
187		 */
188		/* undefined */ 0x00000000,
189		/* lg(2/1) = */ 0x01000000,
190		/* lg(4/3) = */ 0x006a3fe6,
191		/* lg(8/7) = */ 0x00315130,
192		/* lg(16/15) = */ 0x0017d605,
193		/* lg(32/31) = */ 0x000bb9ca,
194		/* lg(64/63) = */ 0x0005d0fc,
195		/* lg(128/127) = */ 0x0002e58f,
196		/* lg(256/255) = */ 0x0001720e,
197		/* lg(512/511) = */ 0x0000b8d8,
198		/* lg(1024/1023) = */ 0x00005c61,
199		/* lg(2048/2047) = */ 0x00002e2d,
200		/* lg(4096/4095) = */ 0x00001716,
201		/* lg(8192/8191) = */ 0x00000b8b,
202		/* lg(16384/16383) = */ 0x000005c5,
203		/* lg(32768/32767) = */ 0x000002e3
204	},
205	{
206		/*
207		 * 28 fraction bits
208		 */
209		/* undefined */ 0x00000000,
210		/* lg(2/1) = */ 0x10000000,
211		/* lg(4/3) = */ 0x06a3fe5c,
212		/* lg(8/7) = */ 0x03151301,
213		/* lg(16/15) = */ 0x017d6049,
214		/* lg(32/31) = */ 0x00bb9ca6,
215		/* lg(64/63) = */ 0x005d0fba,
216		/* lg(128/127) = */ 0x002e58f7,
217		/* lg(256/255) = */ 0x001720da,
218		/* lg(512/511) = */ 0x000b8d87,
219		/* lg(1024/1023) = */ 0x0005c60b,
220		/* lg(2048/2047) = */ 0x0002e2d7,
221		/* lg(4096/4095) = */ 0x00017160,
222		/* lg(8192/8191) = */ 0x0000b8ad,
223		/* lg(16384/16383) = */ 0x00005c56,
224		/* lg(32768/32767) = */ 0x00002e2b
225	}
226};
227
228#if 0
229static const FLAC__uint64 log2_lookup_wide[] = {
230	{
231		/*
232		 * 32 fraction bits
233		 */
234		/* undefined */ 0x00000000,
235		/* lg(2/1) = */ FLAC__U64L(0x100000000),
236		/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6),
237		/* lg(8/7) = */ FLAC__U64L(0x31513015),
238		/* lg(16/15) = */ FLAC__U64L(0x17d60497),
239		/* lg(32/31) = */ FLAC__U64L(0x0bb9ca65),
240		/* lg(64/63) = */ FLAC__U64L(0x05d0fba2),
241		/* lg(128/127) = */ FLAC__U64L(0x02e58f74),
242		/* lg(256/255) = */ FLAC__U64L(0x01720d9c),
243		/* lg(512/511) = */ FLAC__U64L(0x00b8d875),
244		/* lg(1024/1023) = */ FLAC__U64L(0x005c60aa),
245		/* lg(2048/2047) = */ FLAC__U64L(0x002e2d72),
246		/* lg(4096/4095) = */ FLAC__U64L(0x00171600),
247		/* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2),
248		/* lg(16384/16383) = */ FLAC__U64L(0x0005c55d),
249		/* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac)
250	},
251	{
252		/*
253		 * 48 fraction bits
254		 */
255		/* undefined */ 0x00000000,
256		/* lg(2/1) = */ FLAC__U64L(0x1000000000000),
257		/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c60429),
258		/* lg(8/7) = */ FLAC__U64L(0x315130157f7a),
259		/* lg(16/15) = */ FLAC__U64L(0x17d60496cfbb),
260		/* lg(32/31) = */ FLAC__U64L(0xbb9ca64ecac),
261		/* lg(64/63) = */ FLAC__U64L(0x5d0fba187cd),
262		/* lg(128/127) = */ FLAC__U64L(0x2e58f7441ee),
263		/* lg(256/255) = */ FLAC__U64L(0x1720d9c06a8),
264		/* lg(512/511) = */ FLAC__U64L(0xb8d8752173),
265		/* lg(1024/1023) = */ FLAC__U64L(0x5c60aa252e),
266		/* lg(2048/2047) = */ FLAC__U64L(0x2e2d71b0d8),
267		/* lg(4096/4095) = */ FLAC__U64L(0x1716001719),
268		/* lg(8192/8191) = */ FLAC__U64L(0xb8ad1de1b),
269		/* lg(16384/16383) = */ FLAC__U64L(0x5c55d640d),
270		/* lg(32768/32767) = */ FLAC__U64L(0x2e2abcf52)
271	}
272};
273#endif
274
275FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned precision)
276{
277	const FLAC__uint32 ONE = (1u << fracbits);
278	const FLAC__uint32 *table = log2_lookup[fracbits >> 2];
279
280	FLAC__ASSERT(fracbits < 32);
281	FLAC__ASSERT((fracbits & 0x3) == 0);
282
283	if(x < ONE)
284		return 0;
285
286	if(precision > LOG2_LOOKUP_PRECISION)
287		precision = LOG2_LOOKUP_PRECISION;
288
289	/* Knuth's algorithm for computing logarithms, optimized for base-2 with lookup tables */
290	{
291		FLAC__uint32 y = 0;
292		FLAC__uint32 z = x >> 1, k = 1;
293		while (x > ONE && k < precision) {
294			if (x - z >= ONE) {
295				x -= z;
296				z = x >> k;
297				y += table[k];
298			}
299			else {
300				z >>= 1;
301				k++;
302			}
303		}
304		return y;
305	}
306}
307
308#endif /* defined FLAC__INTEGER_ONLY_LIBRARY */
309