xref: /aosp_15_r20/external/speex/libspeexdsp/pseudofloat.h (revision 28e138c64d234588b5cd2a8a403b584bd3036e4e)
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