Merge branch 'cwrs_speedup'
[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_t)(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 static inline short MULT16_16_Q15(int a, int b) 
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\n", a, b);
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\n", (int)res);
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 = %d MIPS\n", celt_mips);} while (0);
551
552 #endif