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