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