Implements CELT_SET_LOSS_PERC
[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)(celt_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 HALF32(x)  (SHR32(x,1))
184
185 //#define SHR(a,shift) ((a) >> (shift))
186 //#define SHL(a,shift) ((a) << (shift))
187
188 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
189 static inline short _ADD16(int a, int b, char *file, int line) 
190 {
191    int res;
192    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
193    {
194       fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
195    }
196    res = a+b;
197    if (!VERIFY_SHORT(res))
198    {
199       fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
200    }
201    celt_mips++;
202    return res;
203 }
204
205 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
206 static inline short _SUB16(int a, int b, char *file, int line) 
207 {
208    int res;
209    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
210    {
211       fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
212    }
213    res = a-b;
214    if (!VERIFY_SHORT(res))
215       fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
216    celt_mips++;
217    return res;
218 }
219
220 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
221 static inline int _ADD32(long long a, long long b, char *file, int line) 
222 {
223    long long res;
224    if (!VERIFY_INT(a) || !VERIFY_INT(b))
225    {
226       fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
227    }
228    res = a+b;
229    if (!VERIFY_INT(res))
230    {
231       fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
232    }
233    celt_mips+=2;
234    return res;
235 }
236
237 #define SUB32(a, b) _SUB32(a, b, __FILE__, __LINE__)
238 static inline int _SUB32(long long a, long long b, char *file, int line) 
239 {
240    long long res;
241    if (!VERIFY_INT(a) || !VERIFY_INT(b))
242    {
243       fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
244    }
245    res = a-b;
246    if (!VERIFY_INT(res))
247       fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
248    celt_mips+=2;
249    return res;
250 }
251
252 #undef UADD32
253 #define UADD32(a, b) _UADD32(a, b, __FILE__, __LINE__)
254 static inline unsigned int _UADD32(unsigned long long a, unsigned long long b, char *file, int line) 
255 {
256    long long res;
257    if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
258    {
259       fprintf (stderr, "UADD32: inputs are not int: %u %u in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);
260    }
261    res = a+b;
262    if (!VERIFY_UINT(res))
263    {
264       fprintf (stderr, "UADD32: output is not int: %u in %s: line %d\n", (unsigned)res, file, line);
265    }
266    celt_mips+=2;
267    return res;
268 }
269
270 #undef USUB32
271 #define USUB32(a, b) _USUB32(a, b, __FILE__, __LINE__)
272 static inline unsigned int _USUB32(unsigned long long a, unsigned long long b, char *file, int line) 
273 {
274    long long res;
275    if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
276    {
277       /*fprintf (stderr, "USUB32: inputs are not int: %llu %llu in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);*/
278    }
279    res = a-b;
280    if (!VERIFY_UINT(res))
281    {
282       /*fprintf (stderr, "USUB32: output is not int: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);*/
283    }
284    celt_mips+=2;
285    return res;
286 }
287
288
289
290 /* result fits in 16 bits */
291 static inline short MULT16_16_16(int a, int b) 
292 {
293    int res;
294    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
295    {
296       fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
297    }
298    res = a*b;
299    if (!VERIFY_SHORT(res))
300       fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
301    celt_mips++;
302    return res;
303 }
304
305 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
306 static inline int _MULT16_16(int a, int b, char *file, int line) 
307 {
308    long long res;
309    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
310    {
311       fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
312    }
313    res = ((long long)a)*b;
314    if (!VERIFY_INT(res))
315       fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
316    celt_mips++;
317    return res;
318 }
319
320 #define MAC16_16(c,a,b)     (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
321 #define MAC16_16_Q11(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
322 #define MAC16_16_Q13(c,a,b)     (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
323 #define MAC16_16_P13(c,a,b)     (ADD16((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))
324
325
326 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
327 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
328 {
329    long long res;
330    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
331    {
332       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);
333    }
334    if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
335       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
336    res = (((long long)a)*(long long)b) >> Q;
337    if (!VERIFY_INT(res))
338       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);
339    if (Q==15)
340       celt_mips+=3;
341    else
342       celt_mips+=4;
343    return res;
344 }
345
346 static inline int MULT16_32_PX(int a, long long b, int Q)
347 {
348    long long res;
349    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
350    {
351       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
352    }
353    if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
354       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
355    res = ((((long long)a)*(long long)b) + (((celt_word32)(1)<<Q)>>1))>> Q;
356    if (!VERIFY_INT(res))
357       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
358    if (Q==15)
359       celt_mips+=4;
360    else
361       celt_mips+=5;
362    return res;
363 }
364
365
366 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
367 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
368 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
369 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
370 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
371 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
372 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
373 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
374
375 static inline int SATURATE(int a, int b)
376 {
377    if (a>b)
378       a=b;
379    if (a<-b)
380       a = -b;
381    celt_mips+=3;
382    return a;
383 }
384
385 static inline int MULT16_16_Q11_32(int a, int b) 
386 {
387    long long res;
388    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
389    {
390       fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
391    }
392    res = ((long long)a)*b;
393    res >>= 11;
394    if (!VERIFY_INT(res))
395       fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
396    celt_mips+=3;
397    return res;
398 }
399 static inline short MULT16_16_Q13(int a, int b) 
400 {
401    long long res;
402    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
403    {
404       fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
405    }
406    res = ((long long)a)*b;
407    res >>= 13;
408    if (!VERIFY_SHORT(res))
409       fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
410    celt_mips+=3;
411    return res;
412 }
413 static inline short MULT16_16_Q14(int a, int b) 
414 {
415    long long res;
416    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
417    {
418       fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
419    }
420    res = ((long long)a)*b;
421    res >>= 14;
422    if (!VERIFY_SHORT(res))
423       fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
424    celt_mips+=3;
425    return res;
426 }
427
428 #define MULT16_16_Q15(a, b) _MULT16_16_Q15(a, b, __FILE__, __LINE__)
429 static inline short _MULT16_16_Q15(int a, int b, char *file, int line) 
430 {
431    long long res;
432    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
433    {
434       fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
435    }
436    res = ((long long)a)*b;
437    res >>= 15;
438    if (!VERIFY_SHORT(res))
439    {
440       fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
441    }
442    celt_mips+=1;
443    return res;
444 }
445
446 static inline short MULT16_16_P13(int a, int b) 
447 {
448    long long res;
449    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
450    {
451       fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
452    }
453    res = ((long long)a)*b;
454    res += 4096;
455    if (!VERIFY_INT(res))
456       fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
457    res >>= 13;
458    if (!VERIFY_SHORT(res))
459       fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
460    celt_mips+=4;
461    return res;
462 }
463 static inline short MULT16_16_P14(int a, int b) 
464 {
465    long long res;
466    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
467    {
468       fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
469    }
470    res = ((long long)a)*b;
471    res += 8192;
472    if (!VERIFY_INT(res))
473       fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
474    res >>= 14;
475    if (!VERIFY_SHORT(res))
476       fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
477    celt_mips+=4;
478    return res;
479 }
480 static inline short MULT16_16_P15(int a, int b) 
481 {
482    long long res;
483    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
484    {
485       fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
486    }
487    res = ((long long)a)*b;
488    res += 16384;
489    if (!VERIFY_INT(res))
490       fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
491    res >>= 15;
492    if (!VERIFY_SHORT(res))
493       fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
494    celt_mips+=2;
495    return res;
496 }
497
498 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
499
500 static inline int _DIV32_16(long long a, long long b, char *file, int line) 
501 {
502    long long res;
503    if (b==0)
504    {
505       fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
506       return 0;
507    }
508    if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
509    {
510       fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
511    }
512    res = a/b;
513    if (!VERIFY_SHORT(res))
514    {
515       fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
516       if (res>32767)
517          res = 32767;
518       if (res<-32768)
519          res = -32768;
520    }
521    celt_mips+=35;
522    return res;
523 }
524
525 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
526 static inline int _DIV32(long long a, long long b, char *file, int line) 
527 {
528    long long res;
529    if (b==0)
530    {
531       fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
532       return 0;
533    }
534
535    if (!VERIFY_INT(a) || !VERIFY_INT(b))
536    {
537       fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
538    }
539    res = a/b;
540    if (!VERIFY_INT(res))
541       fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
542    celt_mips+=70;
543    return res;
544 }
545 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
546 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
547
548 #undef PRINT_MIPS
549 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
550
551 #endif