1 /* Copyright (C) 2003 Jean-Marc Valin */
2 /**
3    @file fixed_debug.h
4    @brief Fixed-point operations with debugging
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 FIXED_DEBUG_H
36 #define FIXED_DEBUG_H
37 
38 #include <stdio.h>
39 
40 extern long long spx_mips;
41 #define MIPS_INC spx_mips++,
42 
43 #define QCONST16(x,bits) ((spx_word16_t)((x)*(1<<(bits))+(1<<((bits)-1))))
44 #define QCONST32(x,bits) ((spx_word32_t)((x)*(1<<(bits))+(1<<((bits)-1))))
45 
46 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
47 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
48 
NEG16(int x)49 static inline short NEG16(int x)
50 {
51    int res;
52    if (!VERIFY_SHORT(x))
53    {
54       fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
55    }
56    res = -x;
57    if (!VERIFY_SHORT(res))
58       fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
59    spx_mips++;
60    return res;
61 }
NEG32(long long x)62 static inline int NEG32(long long x)
63 {
64    long long res;
65    if (!VERIFY_INT(x))
66    {
67       fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
68    }
69    res = -x;
70    if (!VERIFY_INT(res))
71       fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
72    spx_mips++;
73    return res;
74 }
75 
EXTRACT16(int x)76 static inline short EXTRACT16(int x)
77 {
78    int res;
79    if (!VERIFY_SHORT(x))
80    {
81       fprintf (stderr, "EXTRACT16: input is not short: %d\n", x);
82    }
83    res = x;
84    spx_mips++;
85    return res;
86 }
87 
EXTEND32(int x)88 static inline int EXTEND32(int x)
89 {
90    int res;
91    if (!VERIFY_SHORT(x))
92    {
93       fprintf (stderr, "EXTRACT16: input is not short: %d\n", x);
94    }
95    res = x;
96    spx_mips++;
97    return res;
98 }
99 
SHR16(int a,int shift)100 static inline short SHR16(int a, int shift)
101 {
102    int res;
103    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
104    {
105       fprintf (stderr, "SHR16: inputs are not short: %d %d\n", a, shift);
106    }
107    res = a>>shift;
108    if (!VERIFY_SHORT(res))
109       fprintf (stderr, "SHR16: output is not short: %d\n", res);
110    spx_mips++;
111    return res;
112 }
SHL16(int a,int shift)113 static inline short SHL16(int a, int shift)
114 {
115    int res;
116    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
117    {
118       fprintf (stderr, "SHR16: inputs are not short: %d %d\n", a, shift);
119    }
120    res = a<<shift;
121    if (!VERIFY_SHORT(res))
122       fprintf (stderr, "SHR16: output is not short: %d\n", res);
123    spx_mips++;
124    return res;
125 }
126 
SHR32(long long a,int shift)127 static inline int SHR32(long long a, int shift)
128 {
129    long long  res;
130    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
131    {
132       fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
133    }
134    res = a>>shift;
135    if (!VERIFY_INT(res))
136       fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
137    spx_mips++;
138    return res;
139 }
SHL32(long long a,int shift)140 static inline int SHL32(long long a, int shift)
141 {
142    long long  res;
143    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
144    {
145       fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
146    }
147    res = a<<shift;
148    if (!VERIFY_INT(res))
149       fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
150    spx_mips++;
151    return res;
152 }
153 
154 
155 #define PSHR16(a,shift) (SHR16(ADD16(a,(1<<((shift)-1))),shift))
156 #define PSHR32(a,shift) (SHR32(ADD32(a,(1<<((shift)-1))),shift))
157 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
158 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
159 
160 #define SHR(a,shift) ((a) >> (shift))
161 #define SHL(a,shift) ((a) << (shift))
162 
ADD16(int a,int b)163 static inline short ADD16(int a, int b)
164 {
165    int res;
166    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
167    {
168       fprintf (stderr, "ADD16: inputs are not short: %d %d\n", a, b);
169    }
170    res = a+b;
171    if (!VERIFY_SHORT(res))
172       fprintf (stderr, "ADD16: output is not short: %d\n", res);
173    spx_mips++;
174    return res;
175 }
SUB16(int a,int b)176 static inline short SUB16(int a, int b)
177 {
178    int res;
179    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
180    {
181       fprintf (stderr, "SUB16: inputs are not short: %d %d\n", a, b);
182    }
183    res = a-b;
184    if (!VERIFY_SHORT(res))
185       fprintf (stderr, "SUB16: output is not short: %d\n", res);
186    spx_mips++;
187    return res;
188 }
189 
ADD32(long long a,long long b)190 static inline int ADD32(long long a, long long b)
191 {
192    long long res;
193    if (!VERIFY_INT(a) || !VERIFY_INT(b))
194    {
195       fprintf (stderr, "ADD32: inputs are not int: %d %d\n", (int)a, (int)b);
196    }
197    res = a+b;
198    if (!VERIFY_INT(res))
199       fprintf (stderr, "ADD32: output is not int: %d\n", (int)res);
200    spx_mips++;
201    return res;
202 }
203 
SUB32(long long a,long long b)204 static inline int SUB32(long long a, long long b)
205 {
206    long long res;
207    if (!VERIFY_INT(a) || !VERIFY_INT(b))
208    {
209       fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
210    }
211    res = a-b;
212    if (!VERIFY_INT(res))
213       fprintf (stderr, "SUB32: output is not int: %d\n", (int)res);
214    spx_mips++;
215    return res;
216 }
217 
218 #define ADD64(a,b) (MIPS_INC(a)+(b))
219 
220 #define PSHR(a,shift) (SHR((a)+(1<<((shift)-1)),shift))
221 
222 /* result fits in 16 bits */
MULT16_16_16(int a,int b)223 static inline short MULT16_16_16(int a, int b)
224 {
225    int res;
226    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
227    {
228       fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
229    }
230    res = a*b;
231    if (!VERIFY_SHORT(res))
232       fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
233    spx_mips++;
234    return res;
235 }
236 
MULT16_16(int a,int b)237 static inline int MULT16_16(int a, int b)
238 {
239    long long res;
240    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
241    {
242       fprintf (stderr, "MULT16_16: inputs are not short: %d %d\n", a, b);
243    }
244    res = ((long long)a)*b;
245    if (!VERIFY_INT(res))
246       fprintf (stderr, "MULT16_16: output is not int: %d\n", (int)res);
247    spx_mips++;
248    return res;
249 }
250 
251 #define MAC16_16(c,a,b)     (spx_mips--,ADD32((c),MULT16_16((a),(b))))
252 #define MAC16_16_Q11(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
253 #define MAC16_16_Q13(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
254 
MULT16_32_QX(int a,long long b,int Q)255 static inline int MULT16_32_QX(int a, long long b, int Q)
256 {
257    long long res;
258    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
259    {
260       fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
261    }
262    res = (((long long)a)*(long long)b) >> Q;
263    if (!VERIFY_INT(res))
264       fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
265    spx_mips+=5;
266    return res;
267 }
268 
269 
270 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
271 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
272 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
273 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
274 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
275 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
276 #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
277 
SATURATE(int a,int b)278 static inline int SATURATE(int a, int b)
279 {
280    if (a>b)
281       a=b;
282    if (a<-b)
283       a = -b;
284    return a;
285 }
286 
MULT16_16_Q11_32(int a,int b)287 static inline int MULT16_16_Q11_32(int a, int b)
288 {
289    long long res;
290    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
291    {
292       fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
293    }
294    res = ((long long)a)*b;
295    res >>= 11;
296    if (!VERIFY_INT(res))
297       fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
298    spx_mips+=3;
299    return res;
300 }
MULT16_16_Q13(int a,int b)301 static inline short MULT16_16_Q13(int a, int b)
302 {
303    long long res;
304    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
305    {
306       fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
307    }
308    res = ((long long)a)*b;
309    res >>= 13;
310    if (!VERIFY_SHORT(res))
311       fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
312    spx_mips+=3;
313    return res;
314 }
MULT16_16_Q14(int a,int b)315 static inline short MULT16_16_Q14(int a, int b)
316 {
317    long long res;
318    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
319    {
320       fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
321    }
322    res = ((long long)a)*b;
323    res >>= 14;
324    if (!VERIFY_SHORT(res))
325       fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
326    spx_mips+=3;
327    return res;
328 }
MULT16_16_Q15(int a,int b)329 static inline short MULT16_16_Q15(int a, int b)
330 {
331    long long res;
332    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
333    {
334       fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
335    }
336    res = ((long long)a)*b;
337    res >>= 15;
338    if (!VERIFY_SHORT(res))
339       fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
340    spx_mips+=3;
341    return res;
342 }
343 
MULT16_16_P13(int a,int b)344 static inline short MULT16_16_P13(int a, int b)
345 {
346    long long res;
347    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
348    {
349       fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
350    }
351    res = ((long long)a)*b;
352    res += 4096;
353    if (!VERIFY_INT(res))
354       fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
355    res >>= 13;
356    if (!VERIFY_SHORT(res))
357       fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
358    spx_mips+=4;
359    return res;
360 }
MULT16_16_P14(int a,int b)361 static inline short MULT16_16_P14(int a, int b)
362 {
363    long long res;
364    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
365    {
366       fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
367    }
368    res = ((long long)a)*b;
369    res += 8192;
370    if (!VERIFY_INT(res))
371       fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
372    res >>= 14;
373    if (!VERIFY_SHORT(res))
374       fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
375    spx_mips+=4;
376    return res;
377 }
MULT16_16_P15(int a,int b)378 static inline short MULT16_16_P15(int a, int b)
379 {
380    long long res;
381    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
382    {
383       fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
384    }
385    res = ((long long)a)*b;
386    res += 16384;
387    if (!VERIFY_INT(res))
388       fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
389    res >>= 15;
390    if (!VERIFY_SHORT(res))
391       fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
392    spx_mips+=4;
393    return res;
394 }
395 
396 
DIV32_16(long long a,long long b)397 static inline int DIV32_16(long long a, long long b)
398 {
399    long long res;
400    if (b==0)
401    {
402       fprintf(stderr, "DIV32_16: divide by zero: %d/%d\n", (int)a, (int)b);
403       return 0;
404    }
405    if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
406    {
407       fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d\n", (int)a, (int)b);
408    }
409    res = a/b;
410    if (!VERIFY_SHORT(res))
411    {
412       fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d\n", (int)a,(int)b,(int)res);
413       if (res>32767)
414          res = 32767;
415       if (res<-32768)
416          res = -32768;
417    }
418    spx_mips+=20;
419    return res;
420 }
DIV32(long long a,long long b)421 static inline int DIV32(long long a, long long b)
422 {
423    long long res;
424    if (b==0)
425    {
426       fprintf(stderr, "DIV32: divide by zero: %d/%d\n", (int)a, (int)b);
427       return 0;
428    }
429 
430    if (!VERIFY_INT(a) || !VERIFY_INT(b))
431    {
432       fprintf (stderr, "DIV32: inputs are not int/short: %d %d\n", (int)a, (int)b);
433    }
434    res = a/b;
435    if (!VERIFY_INT(res))
436       fprintf (stderr, "DIV32: output is not int: %d\n", (int)res);
437    spx_mips+=36;
438    return res;
439 }
440 
441 
442 
443 #endif
444