Removed the _t from all the celt*_t types to avoid clashing with POSIX
[opus.git] / libcelt / fixed_debug.h
1 /* Copyright (C) 2003-2008 Jean-Marc Valin
2    Copyright (C) 2007-2009 Xiph.Org Foundation */
3 /**
4    @file fixed_debug.h
5    @brief Fixed-point operations with debugging
6 */
7 /*
8    Redistribution and use in source and binary forms, with or without
9    modification, are permitted provided that the following conditions
10    are met:
11    
12    - Redistributions of source code must retain the above copyright
13    notice, this list of conditions and the following disclaimer.
14    
15    - Redistributions in binary form must reproduce the above copyright
16    notice, this list of conditions and the following disclaimer in the
17    documentation and/or other materials provided with the distribution.
18    
19    - Neither the name of the Xiph.org Foundation nor the names of its
20    contributors may be used to endorse or promote products derived from
21    this software without specific prior written permission.
22    
23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
27    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #ifndef FIXED_DEBUG_H
37 #define FIXED_DEBUG_H
38
39 #include <stdio.h>
40
41 #ifdef CELT_C
42 long long celt_mips=0;
43 #else
44 extern long long celt_mips;
45 #endif
46
47 #define MIPS_INC celt_mips++,
48
49 #define MULT16_16SU(a,b) ((celt_word32)(celt_word16)(a)*(celt_word32)(celt_uint16)(b))
50 #define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
51
52 /** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
53 #define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
54
55 #define QCONST16(x,bits) ((celt_word16)(.5+(x)*(((celt_word32)1)<<(bits))))
56 #define QCONST32(x,bits) ((celt_word32)(.5+(x)*(((celt_word32)1)<<(bits))))
57
58
59 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
60 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
61 #define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
62
63 #define SHR(a,b) SHR32(a,b)
64 #define PSHR(a,b) PSHR32(a,b)
65
66 static inline short NEG16(int x)
67 {
68    int res;
69    if (!VERIFY_SHORT(x))
70    {
71       fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
72    }
73    res = -x;
74    if (!VERIFY_SHORT(res))
75       fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
76    celt_mips++;
77    return res;
78 }
79 static inline int NEG32(long long x)
80 {
81    long long res;
82    if (!VERIFY_INT(x))
83    {
84       fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
85    }
86    res = -x;
87    if (!VERIFY_INT(res))
88       fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
89    celt_mips+=2;
90    return res;
91 }
92
93 #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
94 static inline short _EXTRACT16(int x, char *file, int line)
95 {
96    int res;
97    if (!VERIFY_SHORT(x))
98    {
99       fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
100    }
101    res = x;
102    celt_mips++;
103    return res;
104 }
105
106 #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
107 static inline int _EXTEND32(int x, char *file, int line)
108 {
109    int res;
110    if (!VERIFY_SHORT(x))
111    {
112       fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
113    }
114    res = x;
115    celt_mips++;
116    return res;
117 }
118
119 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
120 static inline short _SHR16(int a, int shift, char *file, int line) 
121 {
122    int res;
123    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
124    {
125       fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
126    }
127    res = a>>shift;
128    if (!VERIFY_SHORT(res))
129       fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
130    celt_mips++;
131    return res;
132 }
133 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
134 static inline short _SHL16(int a, int shift, char *file, int line) 
135 {
136    int res;
137    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
138    {
139       fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
140    }
141    res = a<<shift;
142    if (!VERIFY_SHORT(res))
143       fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
144    celt_mips++;
145    return res;
146 }
147
148 static inline int SHR32(long long a, int shift) 
149 {
150    long long  res;
151    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
152    {
153       fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
154    }
155    res = a>>shift;
156    if (!VERIFY_INT(res))
157    {
158       fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
159    }
160    celt_mips+=2;
161    return res;
162 }
163 static inline int SHL32(long long a, int shift) 
164 {
165    long long  res;
166    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
167    {
168       fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
169    }
170    res = a<<shift;
171    if (!VERIFY_INT(res))
172    {
173       fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
174    }
175    celt_mips+=2;
176    return res;
177 }
178
179 #define PSHR16(a,shift) (celt_mips--,SHR16(ADD16((a),((1<<((shift))>>1))),shift))
180 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((celt_word32)(1)<<((shift))>>1))),shift))
181 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
182
183 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
184 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
185
186 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
187 #define HALF32(x)  (SHR32(x,1))
188
189 //#define SHR(a,shift) ((a) >> (shift))
190 //#define SHL(a,shift) ((a) << (shift))
191
192 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
193 static inline short _ADD16(int a, int b, char *file, int line) 
194 {
195    int res;
196    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
197    {
198       fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
199    }
200    res = a+b;
201    if (!VERIFY_SHORT(res))
202    {
203       fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
204    }
205    celt_mips++;
206    return res;
207 }
208
209 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
210 static inline short _SUB16(int a, int b, char *file, int line) 
211 {
212    int res;
213    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
214    {
215       fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
216    }
217    res = a-b;
218    if (!VERIFY_SHORT(res))
219       fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
220    celt_mips++;
221    return res;
222 }
223
224 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
225 static inline int _ADD32(long long a, long long b, char *file, int line) 
226 {
227    long long res;
228    if (!VERIFY_INT(a) || !VERIFY_INT(b))
229    {
230       fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
231    }
232    res = a+b;
233    if (!VERIFY_INT(res))
234    {
235       fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
236    }
237    celt_mips+=2;
238    return res;
239 }
240
241 #define SUB32(a, b) _SUB32(a, b, __FILE__, __LINE__)
242 static inline int _SUB32(long long a, long long b, char *file, int line) 
243 {
244    long long res;
245    if (!VERIFY_INT(a) || !VERIFY_INT(b))
246    {
247       fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
248    }
249    res = a-b;
250    if (!VERIFY_INT(res))
251       fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
252    celt_mips+=2;
253    return res;
254 }
255
256 #undef UADD32
257 #define UADD32(a, b) _UADD32(a, b, __FILE__, __LINE__)
258 static inline unsigned int _UADD32(unsigned long long a, unsigned long long b, char *file, int line) 
259 {
260    long long res;
261    if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
262    {
263       fprintf (stderr, "UADD32: inputs are not int: %u %u in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);
264    }
265    res = a+b;
266    if (!VERIFY_UINT(res))
267    {
268       fprintf (stderr, "UADD32: output is not int: %u in %s: line %d\n", (unsigned)res, file, line);
269    }
270    celt_mips+=2;
271    return res;
272 }
273
274 #undef USUB32
275 #define USUB32(a, b) _USUB32(a, b, __FILE__, __LINE__)
276 static inline unsigned int _USUB32(unsigned long long a, unsigned long long b, char *file, int line) 
277 {
278    long long res;
279    if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
280    {
281       /*fprintf (stderr, "USUB32: inputs are not int: %llu %llu in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);*/
282    }
283    res = a-b;
284    if (!VERIFY_UINT(res))
285    {
286       /*fprintf (stderr, "USUB32: output is not int: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);*/
287    }
288    celt_mips+=2;
289    return res;
290 }
291
292
293
294 /* result fits in 16 bits */
295 static inline short MULT16_16_16(int a, int b) 
296 {
297    int res;
298    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
299    {
300       fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
301    }
302    res = a*b;
303    if (!VERIFY_SHORT(res))
304       fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
305    celt_mips++;
306    return res;
307 }
308
309 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
310 static inline int _MULT16_16(int a, int b, char *file, int line) 
311 {
312    long long res;
313    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
314    {
315       fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
316    }
317    res = ((long long)a)*b;
318    if (!VERIFY_INT(res))
319       fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
320    celt_mips++;
321    return res;
322 }
323
324 #define MAC16_16(c,a,b)     (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
325 #define MAC16_16_Q11(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
326 #define MAC16_16_Q13(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
327 #define MAC16_16_P13(c,a,b)     (ADD16((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))
328
329
330 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
331 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
332 {
333    long long res;
334    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
335    {
336       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);
337    }
338    if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
339       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
340    res = (((long long)a)*(long long)b) >> Q;
341    if (!VERIFY_INT(res))
342       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);
343    if (Q==15)
344       celt_mips+=3;
345    else
346       celt_mips+=4;
347    return res;
348 }
349
350 static inline int MULT16_32_PX(int a, long long b, int Q)
351 {
352    long long res;
353    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
354    {
355       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
356    }
357    if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
358       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
359    res = ((((long long)a)*(long long)b) + (((celt_word32)(1)<<Q)>>1))>> Q;
360    if (!VERIFY_INT(res))
361       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
362    if (Q==15)
363       celt_mips+=4;
364    else
365       celt_mips+=5;
366    return res;
367 }
368
369
370 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
371 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
372 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
373 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
374 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
375 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
376 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
377 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
378
379 static inline int SATURATE(int a, int b)
380 {
381    if (a>b)
382       a=b;
383    if (a<-b)
384       a = -b;
385    celt_mips+=3;
386    return a;
387 }
388
389 static inline int MULT16_16_Q11_32(int a, int b) 
390 {
391    long long res;
392    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
393    {
394       fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
395    }
396    res = ((long long)a)*b;
397    res >>= 11;
398    if (!VERIFY_INT(res))
399       fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
400    celt_mips+=3;
401    return res;
402 }
403 static inline short MULT16_16_Q13(int a, int b) 
404 {
405    long long res;
406    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
407    {
408       fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
409    }
410    res = ((long long)a)*b;
411    res >>= 13;
412    if (!VERIFY_SHORT(res))
413       fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
414    celt_mips+=3;
415    return res;
416 }
417 static inline short MULT16_16_Q14(int a, int b) 
418 {
419    long long res;
420    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
421    {
422       fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
423    }
424    res = ((long long)a)*b;
425    res >>= 14;
426    if (!VERIFY_SHORT(res))
427       fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
428    celt_mips+=3;
429    return res;
430 }
431
432 #define MULT16_16_Q15(a, b) _MULT16_16_Q15(a, b, __FILE__, __LINE__)
433 static inline short _MULT16_16_Q15(int a, int b, char *file, int line) 
434 {
435    long long res;
436    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
437    {
438       fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
439    }
440    res = ((long long)a)*b;
441    res >>= 15;
442    if (!VERIFY_SHORT(res))
443    {
444       fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
445    }
446    celt_mips+=1;
447    return res;
448 }
449
450 static inline short MULT16_16_P13(int a, int b) 
451 {
452    long long res;
453    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
454    {
455       fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
456    }
457    res = ((long long)a)*b;
458    res += 4096;
459    if (!VERIFY_INT(res))
460       fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
461    res >>= 13;
462    if (!VERIFY_SHORT(res))
463       fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
464    celt_mips+=4;
465    return res;
466 }
467 static inline short MULT16_16_P14(int a, int b) 
468 {
469    long long res;
470    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
471    {
472       fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
473    }
474    res = ((long long)a)*b;
475    res += 8192;
476    if (!VERIFY_INT(res))
477       fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
478    res >>= 14;
479    if (!VERIFY_SHORT(res))
480       fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
481    celt_mips+=4;
482    return res;
483 }
484 static inline short MULT16_16_P15(int a, int b) 
485 {
486    long long res;
487    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
488    {
489       fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
490    }
491    res = ((long long)a)*b;
492    res += 16384;
493    if (!VERIFY_INT(res))
494       fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
495    res >>= 15;
496    if (!VERIFY_SHORT(res))
497       fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
498    celt_mips+=2;
499    return res;
500 }
501
502 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
503
504 static inline int _DIV32_16(long long a, long long b, char *file, int line) 
505 {
506    long long res;
507    if (b==0)
508    {
509       fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
510       return 0;
511    }
512    if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
513    {
514       fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
515    }
516    res = a/b;
517    if (!VERIFY_SHORT(res))
518    {
519       fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
520       if (res>32767)
521          res = 32767;
522       if (res<-32768)
523          res = -32768;
524    }
525    celt_mips+=35;
526    return res;
527 }
528
529 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
530 static inline int _DIV32(long long a, long long b, char *file, int line) 
531 {
532    long long res;
533    if (b==0)
534    {
535       fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
536       return 0;
537    }
538
539    if (!VERIFY_INT(a) || !VERIFY_INT(b))
540    {
541       fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
542    }
543    res = a/b;
544    if (!VERIFY_INT(res))
545       fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
546    celt_mips+=70;
547    return res;
548 }
549 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
550 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
551
552 #undef PRINT_MIPS
553 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
554
555 #endif