1*28e138c6SAndroid Build Coastguard Worker /* Copyright (C) 2005 Jean-Marc Valin */
2*28e138c6SAndroid Build Coastguard Worker /**
3*28e138c6SAndroid Build Coastguard Worker @file pseudofloat.h
4*28e138c6SAndroid Build Coastguard Worker @brief Pseudo-floating point
5*28e138c6SAndroid Build Coastguard Worker * This header file provides a lightweight floating point type for
6*28e138c6SAndroid Build Coastguard Worker * use on fixed-point platforms when a large dynamic range is
7*28e138c6SAndroid Build Coastguard Worker * required. The new type is not compatible with the 32-bit IEEE format,
8*28e138c6SAndroid Build Coastguard Worker * it is not even remotely as accurate as 32-bit floats, and is not
9*28e138c6SAndroid Build Coastguard Worker * even guaranteed to produce even remotely correct results for code
10*28e138c6SAndroid Build Coastguard Worker * other than Speex. It makes all kinds of shortcuts that are acceptable
11*28e138c6SAndroid Build Coastguard Worker * for Speex, but may not be acceptable for your application. You're
12*28e138c6SAndroid Build Coastguard Worker * quite welcome to reuse this code and improve it, but don't assume
13*28e138c6SAndroid Build Coastguard Worker * it works out of the box. Most likely, it doesn't.
14*28e138c6SAndroid Build Coastguard Worker */
15*28e138c6SAndroid Build Coastguard Worker /*
16*28e138c6SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without
17*28e138c6SAndroid Build Coastguard Worker modification, are permitted provided that the following conditions
18*28e138c6SAndroid Build Coastguard Worker are met:
19*28e138c6SAndroid Build Coastguard Worker
20*28e138c6SAndroid Build Coastguard Worker - Redistributions of source code must retain the above copyright
21*28e138c6SAndroid Build Coastguard Worker notice, this list of conditions and the following disclaimer.
22*28e138c6SAndroid Build Coastguard Worker
23*28e138c6SAndroid Build Coastguard Worker - Redistributions in binary form must reproduce the above copyright
24*28e138c6SAndroid Build Coastguard Worker notice, this list of conditions and the following disclaimer in the
25*28e138c6SAndroid Build Coastguard Worker documentation and/or other materials provided with the distribution.
26*28e138c6SAndroid Build Coastguard Worker
27*28e138c6SAndroid Build Coastguard Worker - Neither the name of the Xiph.org Foundation nor the names of its
28*28e138c6SAndroid Build Coastguard Worker contributors may be used to endorse or promote products derived from
29*28e138c6SAndroid Build Coastguard Worker this software without specific prior written permission.
30*28e138c6SAndroid Build Coastguard Worker
31*28e138c6SAndroid Build Coastguard Worker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*28e138c6SAndroid Build Coastguard Worker ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*28e138c6SAndroid Build Coastguard Worker LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34*28e138c6SAndroid Build Coastguard Worker A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
35*28e138c6SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36*28e138c6SAndroid Build Coastguard Worker EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37*28e138c6SAndroid Build Coastguard Worker PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38*28e138c6SAndroid Build Coastguard Worker PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39*28e138c6SAndroid Build Coastguard Worker LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40*28e138c6SAndroid Build Coastguard Worker NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41*28e138c6SAndroid Build Coastguard Worker SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42*28e138c6SAndroid Build Coastguard Worker */
43*28e138c6SAndroid Build Coastguard Worker
44*28e138c6SAndroid Build Coastguard Worker #ifndef PSEUDOFLOAT_H
45*28e138c6SAndroid Build Coastguard Worker #define PSEUDOFLOAT_H
46*28e138c6SAndroid Build Coastguard Worker
47*28e138c6SAndroid Build Coastguard Worker #include "arch.h"
48*28e138c6SAndroid Build Coastguard Worker #include "os_support.h"
49*28e138c6SAndroid Build Coastguard Worker #include "math_approx.h"
50*28e138c6SAndroid Build Coastguard Worker #include <math.h>
51*28e138c6SAndroid Build Coastguard Worker
52*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
53*28e138c6SAndroid Build Coastguard Worker
54*28e138c6SAndroid Build Coastguard Worker typedef struct {
55*28e138c6SAndroid Build Coastguard Worker spx_int16_t m;
56*28e138c6SAndroid Build Coastguard Worker spx_int16_t e;
57*28e138c6SAndroid Build Coastguard Worker } spx_float_t;
58*28e138c6SAndroid Build Coastguard Worker
59*28e138c6SAndroid Build Coastguard Worker static const spx_float_t FLOAT_ZERO = {0,0};
60*28e138c6SAndroid Build Coastguard Worker static const spx_float_t FLOAT_ONE = {16384,-14};
61*28e138c6SAndroid Build Coastguard Worker static const spx_float_t FLOAT_HALF = {16384,-15};
62*28e138c6SAndroid Build Coastguard Worker
63*28e138c6SAndroid Build Coastguard Worker #define MIN(a,b) ((a)<(b)?(a):(b))
PSEUDOFLOAT(spx_int32_t x)64*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t PSEUDOFLOAT(spx_int32_t x)
65*28e138c6SAndroid Build Coastguard Worker {
66*28e138c6SAndroid Build Coastguard Worker int e=0;
67*28e138c6SAndroid Build Coastguard Worker int sign=0;
68*28e138c6SAndroid Build Coastguard Worker if (x<0)
69*28e138c6SAndroid Build Coastguard Worker {
70*28e138c6SAndroid Build Coastguard Worker sign = 1;
71*28e138c6SAndroid Build Coastguard Worker x = -x;
72*28e138c6SAndroid Build Coastguard Worker }
73*28e138c6SAndroid Build Coastguard Worker if (x==0)
74*28e138c6SAndroid Build Coastguard Worker {
75*28e138c6SAndroid Build Coastguard Worker spx_float_t r = {0,0};
76*28e138c6SAndroid Build Coastguard Worker return r;
77*28e138c6SAndroid Build Coastguard Worker }
78*28e138c6SAndroid Build Coastguard Worker e = spx_ilog2(ABS32(x))-14;
79*28e138c6SAndroid Build Coastguard Worker x = VSHR32(x, e);
80*28e138c6SAndroid Build Coastguard Worker if (sign)
81*28e138c6SAndroid Build Coastguard Worker {
82*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
83*28e138c6SAndroid Build Coastguard Worker r.m = -x;
84*28e138c6SAndroid Build Coastguard Worker r.e = e;
85*28e138c6SAndroid Build Coastguard Worker return r;
86*28e138c6SAndroid Build Coastguard Worker }
87*28e138c6SAndroid Build Coastguard Worker else
88*28e138c6SAndroid Build Coastguard Worker {
89*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
90*28e138c6SAndroid Build Coastguard Worker r.m = x;
91*28e138c6SAndroid Build Coastguard Worker r.e = e;
92*28e138c6SAndroid Build Coastguard Worker return r;
93*28e138c6SAndroid Build Coastguard Worker }
94*28e138c6SAndroid Build Coastguard Worker }
95*28e138c6SAndroid Build Coastguard Worker
96*28e138c6SAndroid Build Coastguard Worker
FLOAT_ADD(spx_float_t a,spx_float_t b)97*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_ADD(spx_float_t a, spx_float_t b)
98*28e138c6SAndroid Build Coastguard Worker {
99*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
100*28e138c6SAndroid Build Coastguard Worker if (a.m==0)
101*28e138c6SAndroid Build Coastguard Worker return b;
102*28e138c6SAndroid Build Coastguard Worker else if (b.m==0)
103*28e138c6SAndroid Build Coastguard Worker return a;
104*28e138c6SAndroid Build Coastguard Worker if ((a).e > (b).e)
105*28e138c6SAndroid Build Coastguard Worker {
106*28e138c6SAndroid Build Coastguard Worker r.m = ((a).m>>1) + ((b).m>>MIN(15,(a).e-(b).e+1));
107*28e138c6SAndroid Build Coastguard Worker r.e = (a).e+1;
108*28e138c6SAndroid Build Coastguard Worker }
109*28e138c6SAndroid Build Coastguard Worker else
110*28e138c6SAndroid Build Coastguard Worker {
111*28e138c6SAndroid Build Coastguard Worker r.m = ((b).m>>1) + ((a).m>>MIN(15,(b).e-(a).e+1));
112*28e138c6SAndroid Build Coastguard Worker r.e = (b).e+1;
113*28e138c6SAndroid Build Coastguard Worker }
114*28e138c6SAndroid Build Coastguard Worker if (r.m>0)
115*28e138c6SAndroid Build Coastguard Worker {
116*28e138c6SAndroid Build Coastguard Worker if (r.m<16384)
117*28e138c6SAndroid Build Coastguard Worker {
118*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
119*28e138c6SAndroid Build Coastguard Worker r.e-=1;
120*28e138c6SAndroid Build Coastguard Worker }
121*28e138c6SAndroid Build Coastguard Worker } else {
122*28e138c6SAndroid Build Coastguard Worker if (r.m>-16384)
123*28e138c6SAndroid Build Coastguard Worker {
124*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
125*28e138c6SAndroid Build Coastguard Worker r.e-=1;
126*28e138c6SAndroid Build Coastguard Worker }
127*28e138c6SAndroid Build Coastguard Worker }
128*28e138c6SAndroid Build Coastguard Worker /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
129*28e138c6SAndroid Build Coastguard Worker return r;
130*28e138c6SAndroid Build Coastguard Worker }
131*28e138c6SAndroid Build Coastguard Worker
FLOAT_SUB(spx_float_t a,spx_float_t b)132*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_SUB(spx_float_t a, spx_float_t b)
133*28e138c6SAndroid Build Coastguard Worker {
134*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
135*28e138c6SAndroid Build Coastguard Worker if (a.m==0)
136*28e138c6SAndroid Build Coastguard Worker return b;
137*28e138c6SAndroid Build Coastguard Worker else if (b.m==0)
138*28e138c6SAndroid Build Coastguard Worker return a;
139*28e138c6SAndroid Build Coastguard Worker if ((a).e > (b).e)
140*28e138c6SAndroid Build Coastguard Worker {
141*28e138c6SAndroid Build Coastguard Worker r.m = ((a).m>>1) - ((b).m>>MIN(15,(a).e-(b).e+1));
142*28e138c6SAndroid Build Coastguard Worker r.e = (a).e+1;
143*28e138c6SAndroid Build Coastguard Worker }
144*28e138c6SAndroid Build Coastguard Worker else
145*28e138c6SAndroid Build Coastguard Worker {
146*28e138c6SAndroid Build Coastguard Worker r.m = ((a).m>>MIN(15,(b).e-(a).e+1)) - ((b).m>>1);
147*28e138c6SAndroid Build Coastguard Worker r.e = (b).e+1;
148*28e138c6SAndroid Build Coastguard Worker }
149*28e138c6SAndroid Build Coastguard Worker if (r.m>0)
150*28e138c6SAndroid Build Coastguard Worker {
151*28e138c6SAndroid Build Coastguard Worker if (r.m<16384)
152*28e138c6SAndroid Build Coastguard Worker {
153*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
154*28e138c6SAndroid Build Coastguard Worker r.e-=1;
155*28e138c6SAndroid Build Coastguard Worker }
156*28e138c6SAndroid Build Coastguard Worker } else {
157*28e138c6SAndroid Build Coastguard Worker if (r.m>-16384)
158*28e138c6SAndroid Build Coastguard Worker {
159*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
160*28e138c6SAndroid Build Coastguard Worker r.e-=1;
161*28e138c6SAndroid Build Coastguard Worker }
162*28e138c6SAndroid Build Coastguard Worker }
163*28e138c6SAndroid Build Coastguard Worker /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
164*28e138c6SAndroid Build Coastguard Worker return r;
165*28e138c6SAndroid Build Coastguard Worker }
166*28e138c6SAndroid Build Coastguard Worker
FLOAT_LT(spx_float_t a,spx_float_t b)167*28e138c6SAndroid Build Coastguard Worker static inline int FLOAT_LT(spx_float_t a, spx_float_t b)
168*28e138c6SAndroid Build Coastguard Worker {
169*28e138c6SAndroid Build Coastguard Worker if (a.m==0)
170*28e138c6SAndroid Build Coastguard Worker return b.m>0;
171*28e138c6SAndroid Build Coastguard Worker else if (b.m==0)
172*28e138c6SAndroid Build Coastguard Worker return a.m<0;
173*28e138c6SAndroid Build Coastguard Worker if ((a).e > (b).e)
174*28e138c6SAndroid Build Coastguard Worker return ((a).m>>1) < ((b).m>>MIN(15,(a).e-(b).e+1));
175*28e138c6SAndroid Build Coastguard Worker else
176*28e138c6SAndroid Build Coastguard Worker return ((b).m>>1) > ((a).m>>MIN(15,(b).e-(a).e+1));
177*28e138c6SAndroid Build Coastguard Worker
178*28e138c6SAndroid Build Coastguard Worker }
179*28e138c6SAndroid Build Coastguard Worker
FLOAT_GT(spx_float_t a,spx_float_t b)180*28e138c6SAndroid Build Coastguard Worker static inline int FLOAT_GT(spx_float_t a, spx_float_t b)
181*28e138c6SAndroid Build Coastguard Worker {
182*28e138c6SAndroid Build Coastguard Worker return FLOAT_LT(b,a);
183*28e138c6SAndroid Build Coastguard Worker }
184*28e138c6SAndroid Build Coastguard Worker
FLOAT_MULT(spx_float_t a,spx_float_t b)185*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_MULT(spx_float_t a, spx_float_t b)
186*28e138c6SAndroid Build Coastguard Worker {
187*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
188*28e138c6SAndroid Build Coastguard Worker r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15);
189*28e138c6SAndroid Build Coastguard Worker r.e = (a).e+(b).e+15;
190*28e138c6SAndroid Build Coastguard Worker if (r.m>0)
191*28e138c6SAndroid Build Coastguard Worker {
192*28e138c6SAndroid Build Coastguard Worker if (r.m<16384)
193*28e138c6SAndroid Build Coastguard Worker {
194*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
195*28e138c6SAndroid Build Coastguard Worker r.e-=1;
196*28e138c6SAndroid Build Coastguard Worker }
197*28e138c6SAndroid Build Coastguard Worker } else {
198*28e138c6SAndroid Build Coastguard Worker if (r.m>-16384)
199*28e138c6SAndroid Build Coastguard Worker {
200*28e138c6SAndroid Build Coastguard Worker r.m<<=1;
201*28e138c6SAndroid Build Coastguard Worker r.e-=1;
202*28e138c6SAndroid Build Coastguard Worker }
203*28e138c6SAndroid Build Coastguard Worker }
204*28e138c6SAndroid Build Coastguard Worker /*printf ("%f * %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
205*28e138c6SAndroid Build Coastguard Worker return r;
206*28e138c6SAndroid Build Coastguard Worker }
207*28e138c6SAndroid Build Coastguard Worker
FLOAT_AMULT(spx_float_t a,spx_float_t b)208*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_AMULT(spx_float_t a, spx_float_t b)
209*28e138c6SAndroid Build Coastguard Worker {
210*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
211*28e138c6SAndroid Build Coastguard Worker r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15);
212*28e138c6SAndroid Build Coastguard Worker r.e = (a).e+(b).e+15;
213*28e138c6SAndroid Build Coastguard Worker return r;
214*28e138c6SAndroid Build Coastguard Worker }
215*28e138c6SAndroid Build Coastguard Worker
216*28e138c6SAndroid Build Coastguard Worker
FLOAT_SHL(spx_float_t a,int b)217*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_SHL(spx_float_t a, int b)
218*28e138c6SAndroid Build Coastguard Worker {
219*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
220*28e138c6SAndroid Build Coastguard Worker r.m = a.m;
221*28e138c6SAndroid Build Coastguard Worker r.e = a.e+b;
222*28e138c6SAndroid Build Coastguard Worker return r;
223*28e138c6SAndroid Build Coastguard Worker }
224*28e138c6SAndroid Build Coastguard Worker
FLOAT_EXTRACT16(spx_float_t a)225*28e138c6SAndroid Build Coastguard Worker static inline spx_int16_t FLOAT_EXTRACT16(spx_float_t a)
226*28e138c6SAndroid Build Coastguard Worker {
227*28e138c6SAndroid Build Coastguard Worker if (a.e<0)
228*28e138c6SAndroid Build Coastguard Worker return EXTRACT16((EXTEND32(a.m)+(EXTEND32(1)<<(-a.e-1)))>>-a.e);
229*28e138c6SAndroid Build Coastguard Worker else
230*28e138c6SAndroid Build Coastguard Worker return a.m<<a.e;
231*28e138c6SAndroid Build Coastguard Worker }
232*28e138c6SAndroid Build Coastguard Worker
FLOAT_EXTRACT32(spx_float_t a)233*28e138c6SAndroid Build Coastguard Worker static inline spx_int32_t FLOAT_EXTRACT32(spx_float_t a)
234*28e138c6SAndroid Build Coastguard Worker {
235*28e138c6SAndroid Build Coastguard Worker if (a.e<0)
236*28e138c6SAndroid Build Coastguard Worker return (EXTEND32(a.m)+(EXTEND32(1)<<(-a.e-1)))>>-a.e;
237*28e138c6SAndroid Build Coastguard Worker else
238*28e138c6SAndroid Build Coastguard Worker return EXTEND32(a.m)<<a.e;
239*28e138c6SAndroid Build Coastguard Worker }
240*28e138c6SAndroid Build Coastguard Worker
FLOAT_MUL32(spx_float_t a,spx_word32_t b)241*28e138c6SAndroid Build Coastguard Worker static inline spx_int32_t FLOAT_MUL32(spx_float_t a, spx_word32_t b)
242*28e138c6SAndroid Build Coastguard Worker {
243*28e138c6SAndroid Build Coastguard Worker return VSHR32(MULT16_32_Q15(a.m, b),-a.e-15);
244*28e138c6SAndroid Build Coastguard Worker }
245*28e138c6SAndroid Build Coastguard Worker
FLOAT_MUL32U(spx_word32_t a,spx_word32_t b)246*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_MUL32U(spx_word32_t a, spx_word32_t b)
247*28e138c6SAndroid Build Coastguard Worker {
248*28e138c6SAndroid Build Coastguard Worker int e1, e2;
249*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
250*28e138c6SAndroid Build Coastguard Worker if (a==0 || b==0)
251*28e138c6SAndroid Build Coastguard Worker {
252*28e138c6SAndroid Build Coastguard Worker return FLOAT_ZERO;
253*28e138c6SAndroid Build Coastguard Worker }
254*28e138c6SAndroid Build Coastguard Worker e1 = spx_ilog2(ABS32(a));
255*28e138c6SAndroid Build Coastguard Worker a = VSHR32(a, e1-14);
256*28e138c6SAndroid Build Coastguard Worker e2 = spx_ilog2(ABS32(b));
257*28e138c6SAndroid Build Coastguard Worker b = VSHR32(b, e2-14);
258*28e138c6SAndroid Build Coastguard Worker r.m = MULT16_16_Q15(a,b);
259*28e138c6SAndroid Build Coastguard Worker r.e = e1+e2-13;
260*28e138c6SAndroid Build Coastguard Worker return r;
261*28e138c6SAndroid Build Coastguard Worker }
262*28e138c6SAndroid Build Coastguard Worker
263*28e138c6SAndroid Build Coastguard Worker /* Do NOT attempt to divide by a negative number */
FLOAT_DIV32_FLOAT(spx_word32_t a,spx_float_t b)264*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_DIV32_FLOAT(spx_word32_t a, spx_float_t b)
265*28e138c6SAndroid Build Coastguard Worker {
266*28e138c6SAndroid Build Coastguard Worker int e=0;
267*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
268*28e138c6SAndroid Build Coastguard Worker if (a==0)
269*28e138c6SAndroid Build Coastguard Worker {
270*28e138c6SAndroid Build Coastguard Worker return FLOAT_ZERO;
271*28e138c6SAndroid Build Coastguard Worker }
272*28e138c6SAndroid Build Coastguard Worker e = spx_ilog2(ABS32(a))-spx_ilog2(b.m-1)-15;
273*28e138c6SAndroid Build Coastguard Worker a = VSHR32(a, e);
274*28e138c6SAndroid Build Coastguard Worker if (ABS32(a)>=SHL32(EXTEND32(b.m-1),15))
275*28e138c6SAndroid Build Coastguard Worker {
276*28e138c6SAndroid Build Coastguard Worker a >>= 1;
277*28e138c6SAndroid Build Coastguard Worker e++;
278*28e138c6SAndroid Build Coastguard Worker }
279*28e138c6SAndroid Build Coastguard Worker r.m = DIV32_16(a,b.m);
280*28e138c6SAndroid Build Coastguard Worker r.e = e-b.e;
281*28e138c6SAndroid Build Coastguard Worker return r;
282*28e138c6SAndroid Build Coastguard Worker }
283*28e138c6SAndroid Build Coastguard Worker
284*28e138c6SAndroid Build Coastguard Worker
285*28e138c6SAndroid Build Coastguard Worker /* Do NOT attempt to divide by a negative number */
FLOAT_DIV32(spx_word32_t a,spx_word32_t b)286*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_DIV32(spx_word32_t a, spx_word32_t b)
287*28e138c6SAndroid Build Coastguard Worker {
288*28e138c6SAndroid Build Coastguard Worker int e0=0,e=0;
289*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
290*28e138c6SAndroid Build Coastguard Worker if (a==0)
291*28e138c6SAndroid Build Coastguard Worker {
292*28e138c6SAndroid Build Coastguard Worker return FLOAT_ZERO;
293*28e138c6SAndroid Build Coastguard Worker }
294*28e138c6SAndroid Build Coastguard Worker if (b>32767)
295*28e138c6SAndroid Build Coastguard Worker {
296*28e138c6SAndroid Build Coastguard Worker e0 = spx_ilog2(b)-14;
297*28e138c6SAndroid Build Coastguard Worker b = VSHR32(b, e0);
298*28e138c6SAndroid Build Coastguard Worker e0 = -e0;
299*28e138c6SAndroid Build Coastguard Worker }
300*28e138c6SAndroid Build Coastguard Worker e = spx_ilog2(ABS32(a))-spx_ilog2(b-1)-15;
301*28e138c6SAndroid Build Coastguard Worker a = VSHR32(a, e);
302*28e138c6SAndroid Build Coastguard Worker if (ABS32(a)>=SHL32(EXTEND32(b-1),15))
303*28e138c6SAndroid Build Coastguard Worker {
304*28e138c6SAndroid Build Coastguard Worker a >>= 1;
305*28e138c6SAndroid Build Coastguard Worker e++;
306*28e138c6SAndroid Build Coastguard Worker }
307*28e138c6SAndroid Build Coastguard Worker e += e0;
308*28e138c6SAndroid Build Coastguard Worker r.m = DIV32_16(a,b);
309*28e138c6SAndroid Build Coastguard Worker r.e = e;
310*28e138c6SAndroid Build Coastguard Worker return r;
311*28e138c6SAndroid Build Coastguard Worker }
312*28e138c6SAndroid Build Coastguard Worker
313*28e138c6SAndroid Build Coastguard Worker /* Do NOT attempt to divide by a negative number */
FLOAT_DIVU(spx_float_t a,spx_float_t b)314*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_DIVU(spx_float_t a, spx_float_t b)
315*28e138c6SAndroid Build Coastguard Worker {
316*28e138c6SAndroid Build Coastguard Worker int e=0;
317*28e138c6SAndroid Build Coastguard Worker spx_int32_t num;
318*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
319*28e138c6SAndroid Build Coastguard Worker if (b.m<=0)
320*28e138c6SAndroid Build Coastguard Worker {
321*28e138c6SAndroid Build Coastguard Worker speex_warning_int("Attempted to divide by", b.m);
322*28e138c6SAndroid Build Coastguard Worker return FLOAT_ONE;
323*28e138c6SAndroid Build Coastguard Worker }
324*28e138c6SAndroid Build Coastguard Worker num = a.m;
325*28e138c6SAndroid Build Coastguard Worker a.m = ABS16(a.m);
326*28e138c6SAndroid Build Coastguard Worker while (a.m >= b.m)
327*28e138c6SAndroid Build Coastguard Worker {
328*28e138c6SAndroid Build Coastguard Worker e++;
329*28e138c6SAndroid Build Coastguard Worker a.m >>= 1;
330*28e138c6SAndroid Build Coastguard Worker }
331*28e138c6SAndroid Build Coastguard Worker num = num << (15-e);
332*28e138c6SAndroid Build Coastguard Worker r.m = DIV32_16(num,b.m);
333*28e138c6SAndroid Build Coastguard Worker r.e = a.e-b.e-15+e;
334*28e138c6SAndroid Build Coastguard Worker return r;
335*28e138c6SAndroid Build Coastguard Worker }
336*28e138c6SAndroid Build Coastguard Worker
FLOAT_SQRT(spx_float_t a)337*28e138c6SAndroid Build Coastguard Worker static inline spx_float_t FLOAT_SQRT(spx_float_t a)
338*28e138c6SAndroid Build Coastguard Worker {
339*28e138c6SAndroid Build Coastguard Worker spx_float_t r;
340*28e138c6SAndroid Build Coastguard Worker spx_int32_t m;
341*28e138c6SAndroid Build Coastguard Worker m = SHL32(EXTEND32(a.m), 14);
342*28e138c6SAndroid Build Coastguard Worker r.e = a.e - 14;
343*28e138c6SAndroid Build Coastguard Worker if (r.e & 1)
344*28e138c6SAndroid Build Coastguard Worker {
345*28e138c6SAndroid Build Coastguard Worker r.e -= 1;
346*28e138c6SAndroid Build Coastguard Worker m <<= 1;
347*28e138c6SAndroid Build Coastguard Worker }
348*28e138c6SAndroid Build Coastguard Worker r.e >>= 1;
349*28e138c6SAndroid Build Coastguard Worker r.m = spx_sqrt(m);
350*28e138c6SAndroid Build Coastguard Worker return r;
351*28e138c6SAndroid Build Coastguard Worker }
352*28e138c6SAndroid Build Coastguard Worker
353*28e138c6SAndroid Build Coastguard Worker #else
354*28e138c6SAndroid Build Coastguard Worker
355*28e138c6SAndroid Build Coastguard Worker #define spx_float_t float
356*28e138c6SAndroid Build Coastguard Worker #define FLOAT_ZERO 0.f
357*28e138c6SAndroid Build Coastguard Worker #define FLOAT_ONE 1.f
358*28e138c6SAndroid Build Coastguard Worker #define FLOAT_HALF 0.5f
359*28e138c6SAndroid Build Coastguard Worker #define PSEUDOFLOAT(x) (x)
360*28e138c6SAndroid Build Coastguard Worker #define FLOAT_MULT(a,b) ((a)*(b))
361*28e138c6SAndroid Build Coastguard Worker #define FLOAT_AMULT(a,b) ((a)*(b))
362*28e138c6SAndroid Build Coastguard Worker #define FLOAT_MUL32(a,b) ((a)*(b))
363*28e138c6SAndroid Build Coastguard Worker #define FLOAT_DIV32(a,b) ((a)/(b))
364*28e138c6SAndroid Build Coastguard Worker #define FLOAT_EXTRACT16(a) (a)
365*28e138c6SAndroid Build Coastguard Worker #define FLOAT_EXTRACT32(a) (a)
366*28e138c6SAndroid Build Coastguard Worker #define FLOAT_ADD(a,b) ((a)+(b))
367*28e138c6SAndroid Build Coastguard Worker #define FLOAT_SUB(a,b) ((a)-(b))
368*28e138c6SAndroid Build Coastguard Worker #define REALFLOAT(x) (x)
369*28e138c6SAndroid Build Coastguard Worker #define FLOAT_DIV32_FLOAT(a,b) ((a)/(b))
370*28e138c6SAndroid Build Coastguard Worker #define FLOAT_MUL32U(a,b) ((a)*(b))
371*28e138c6SAndroid Build Coastguard Worker #define FLOAT_SHL(a,b) (a)
372*28e138c6SAndroid Build Coastguard Worker #define FLOAT_LT(a,b) ((a)<(b))
373*28e138c6SAndroid Build Coastguard Worker #define FLOAT_GT(a,b) ((a)>(b))
374*28e138c6SAndroid Build Coastguard Worker #define FLOAT_DIVU(a,b) ((a)/(b))
375*28e138c6SAndroid Build Coastguard Worker #define FLOAT_SQRT(a) (spx_sqrt(a))
376*28e138c6SAndroid Build Coastguard Worker
377*28e138c6SAndroid Build Coastguard Worker #endif
378*28e138c6SAndroid Build Coastguard Worker
379*28e138c6SAndroid Build Coastguard Worker #endif
380