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