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