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