1 /* Copyright (C) 2005 Jean-Marc Valin */
2 /**
3    @file pseudofloat.h
4    @brief Pseudo-floating point
5  */
6 /*
7    Redistribution and use in source and binary forms, with or without
8    modification, are permitted provided that the following conditions
9    are met:
10 
11    - Redistributions of source code must retain the above copyright
12    notice, this list of conditions and the following disclaimer.
13 
14    - Redistributions in binary form must reproduce the above copyright
15    notice, this list of conditions and the following disclaimer in the
16    documentation and/or other materials provided with the distribution.
17 
18    - Neither the name of the Xiph.org Foundation nor the names of its
19    contributors may be used to endorse or promote products derived from
20    this software without specific prior written permission.
21 
22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
26    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #ifndef PSEUDOFLOAT_H
36 #define PSEUDOFLOAT_H
37 
38 #include "misc.h"
39 #include <math.h>
40 
41 #ifdef FIXED_POINT
42 
43 typedef struct {
44    spx_int16_t m;
45    spx_int16_t e;
46 } spx_float_t;
47 
48 #define FLOAT_ZERO ((spx_float_t){0,0})
49 #define FLOAT_ONE ((spx_float_t){16384,-14})
50 #define FLOAT_HALF ((spx_float_t){16384,-15})
51 
52 #define MIN(a,b) ((a)<(b)?(a):(b))
PSEUDOFLOAT(spx_int32_t x)53 static inline spx_float_t PSEUDOFLOAT(spx_int32_t x)
54 {
55    int e=0;
56    int sign=0;
57    if (x<0)
58    {
59       sign = 1;
60       x = -x;
61    }
62    if (x==0)
63       return (spx_float_t) {0,0};
64    while (x>32767)
65    {
66       x >>= 1;
67       /*x *= .5;*/
68       e++;
69    }
70    while (x<16383)
71    {
72       x <<= 1;
73       /*x *= 2;*/
74       e--;
75    }
76    if (sign)
77       return (spx_float_t) {-x,e};
78    else
79       return (spx_float_t) {x,e};
80 }
81 
REALFLOAT(spx_float_t a)82 static inline float REALFLOAT(spx_float_t a)
83 {
84    return a.m * pow(2,a.e);
85 }
86 
FLOAT_ADD(spx_float_t a,spx_float_t b)87 static spx_float_t FLOAT_ADD(spx_float_t a, spx_float_t b)
88 {
89    if (a.m==0)
90       return b;
91    else if (b.m==0)
92       return a;
93    spx_float_t r = (a).e > (b).e ? (spx_float_t) {((a).m>>1) + ((b).m>>MIN(15,(a).e-(b).e+1)),(a).e+1} : (spx_float_t) {((b).m>>1) + ((a).m>>MIN(15,(b).e-(a).e+1)),(b).e+1};
94    if (r.m>0)
95    {
96       if (r.m<16384)
97       {
98          r.m<<=1;
99          r.e-=1;
100       }
101    } else {
102       if (r.m>-16384)
103       {
104          r.m<<=1;
105          r.e-=1;
106       }
107    }
108    /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
109    return r;
110 }
111 
FLOAT_SUB(spx_float_t a,spx_float_t b)112 static spx_float_t FLOAT_SUB(spx_float_t a, spx_float_t b)
113 {
114    if (a.m==0)
115       return b;
116    else if (b.m==0)
117       return a;
118    spx_float_t r = (a).e > (b).e ? (spx_float_t) {((a).m>>1) - ((b).m>>MIN(15,(a).e-(b).e+1)),(a).e+1} : (spx_float_t) {((a).m>>MIN(15,(b).e-(a).e+1)) - ((b).m>>1) ,(b).e+1};
119    if (r.m>0)
120    {
121       if (r.m<16384)
122       {
123          r.m<<=1;
124          r.e-=1;
125       }
126    } else {
127       if (r.m>-16384)
128       {
129          r.m<<=1;
130          r.e-=1;
131       }
132    }
133    /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
134    return r;
135 }
136 
FLOAT_LT(spx_float_t a,spx_float_t b)137 static inline int FLOAT_LT(spx_float_t a, spx_float_t b)
138 {
139    if (a.m==0)
140       return b.m<0;
141    else if (b.m==0)
142       return a.m>0;
143    if ((a).e > (b).e)
144       return ((a).m>>1) < ((b).m>>MIN(15,(a).e-(b).e+1));
145    else
146       return ((b).m>>1) > ((a).m>>MIN(15,(b).e-(a).e+1));
147 
148 }
149 
FLOAT_GT(spx_float_t a,spx_float_t b)150 static inline int FLOAT_GT(spx_float_t a, spx_float_t b)
151 {
152    return FLOAT_LT(b,a);
153 }
154 
FLOAT_MULT(spx_float_t a,spx_float_t b)155 static inline spx_float_t FLOAT_MULT(spx_float_t a, spx_float_t b)
156 {
157    spx_float_t r = (spx_float_t) {(spx_int16_t)((spx_int32_t)(a).m*(b).m>>15), (a).e+(b).e+15};
158    if (r.m>0)
159    {
160       if (r.m<16384)
161       {
162          r.m<<=1;
163          r.e-=1;
164       }
165    } else {
166       if (r.m>-16384)
167       {
168          r.m<<=1;
169          r.e-=1;
170       }
171    }
172    /*printf ("%f * %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
173    return r;
174 }
175 
FLOAT_SHR(spx_float_t a,int b)176 static inline spx_float_t FLOAT_SHR(spx_float_t a, int b)
177 {
178    return (spx_float_t) {a.m,a.e-b};
179 }
180 
FLOAT_SHL(spx_float_t a,int b)181 static inline spx_float_t FLOAT_SHL(spx_float_t a, int b)
182 {
183    return (spx_float_t) {a.m,a.e+b};
184 }
185 
FLOAT_EXTRACT16(spx_float_t a)186 static inline spx_int16_t FLOAT_EXTRACT16(spx_float_t a)
187 {
188    if (a.e<0)
189       return (a.m+(1<<(-a.e-1)))>>-a.e;
190    else
191       return a.m<<a.e;
192 }
193 
FLOAT_EXTRACT32(spx_float_t a)194 static inline spx_int32_t FLOAT_EXTRACT32(spx_float_t a)
195 {
196    if (a.e<0)
197       return ((spx_int32_t)a.m+(1<<(-a.e-1)))>>-a.e;
198    else
199       return ((spx_int32_t)a.m)<<a.e;
200 }
201 
FLOAT_MUL32(spx_float_t a,spx_word32_t b)202 static inline spx_int32_t FLOAT_MUL32(spx_float_t a, spx_word32_t b)
203 {
204    if (a.e<-15)
205       return SHR32(MULT16_32_Q15(a.m, b),-a.e-15);
206    else
207       return SHL32(MULT16_32_Q15(a.m, b),15+a.e);
208 }
209 
FLOAT_MUL32U(spx_word32_t a,spx_word32_t b)210 static inline spx_float_t FLOAT_MUL32U(spx_word32_t a, spx_word32_t b)
211 {
212    int e=0;
213    /* FIXME: Handle the sign */
214    if (a==0)
215       return (spx_float_t) {0,0};
216    while (a>32767)
217    {
218       a >>= 1;
219       e++;
220    }
221    while (a<16384)
222    {
223       a <<= 1;
224       e--;
225    }
226    while (b>32767)
227    {
228       b >>= 1;
229       e++;
230    }
231    while (b<16384)
232    {
233       b <<= 1;
234       e--;
235    }
236    return (spx_float_t) {MULT16_16_Q15(a,b),e+15};
237 }
238 
FLOAT_DIV32_FLOAT(spx_word32_t a,spx_float_t b)239 static inline spx_float_t FLOAT_DIV32_FLOAT(spx_word32_t a, spx_float_t b)
240 {
241    int e=0;
242    /* FIXME: Handle the sign */
243    if (a==0)
244       return (spx_float_t) {0,0};
245    while (a<SHL32(b.m,14))
246    {
247       a <<= 1;
248       e--;
249    }
250    while (a>=SHL32(b.m-1,15))
251    {
252       a >>= 1;
253       e++;
254    }
255    return (spx_float_t) {DIV32_16(a,b.m),e-b.e};
256 }
257 
258 
FLOAT_DIV32(spx_word32_t a,spx_word32_t b)259 static inline spx_float_t FLOAT_DIV32(spx_word32_t a, spx_word32_t b)
260 {
261    int e=0;
262    /* FIXME: Handle the sign */
263    if (a==0)
264       return (spx_float_t) {0,0};
265    while (b>32767)
266    {
267       b >>= 1;
268       e--;
269    }
270    while (a<SHL32(b,14))
271    {
272       a <<= 1;
273       e--;
274    }
275    while (a>=SHL32(b-1,15))
276    {
277       a >>= 1;
278       e++;
279    }
280    return (spx_float_t) {DIV32_16(a,b),e};
281 }
282 
FLOAT_DIVU(spx_float_t a,spx_float_t b)283 static inline spx_float_t FLOAT_DIVU(spx_float_t a, spx_float_t b)
284 {
285    int e=0;
286    spx_int32_t num;
287    num = a.m;
288    while (a.m >= b.m)
289    {
290       e++;
291       a.m >>= 1;
292    }
293    num = num << (15-e);
294    return (spx_float_t) {DIV32_16(num,b.m),a.e-b.e-15+e};
295 }
296 
297 #else
298 
299 #define spx_float_t float
300 #define FLOAT_ZERO 0.f
301 #define FLOAT_ONE 1.f
302 #define FLOAT_HALF 0.5f
303 #define PSEUDOFLOAT(x) (x)
304 #define FLOAT_MULT(a,b) ((a)*(b))
305 #define FLOAT_MUL32(a,b) ((a)*(b))
306 #define FLOAT_DIV32(a,b) ((a)/(b))
307 #define FLOAT_EXTRACT16(a) (a)
308 #define FLOAT_ADD(a,b) ((a)+(b))
309 #define FLOAT_SUB(a,b) ((a)-(b))
310 #define REALFLOAT(x) (x)
311 #define FLOAT_DIV32_FLOAT(a,b) ((a)/(b))
312 #define FLOAT_MUL32U(a,b) ((a)*(b))
313 #define FLOAT_SHL(a,b) (a)
314 #define FLOAT_LT(a,b) ((a)<(b))
315 #define FLOAT_GT(a,b) ((a)>(b))
316 #define FLOAT_DIVU(a,b) ((a)/(b))
317 
318 #endif
319 
320 #endif
321