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