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