Further simplifications to the forward mdct
[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 /** 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),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
49
50 #define QCONST16(x,bits) ((celt_word16_t)(.5+(x)*(((celt_word32_t)1)<<(bits))))
51 #define QCONST32(x,bits) ((celt_word32_t)(.5+(x)*(((celt_word32_t)1)<<(bits))))
52
53
54 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
55 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
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++;
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++;
155    return res;
156 }
157 static inline int SHL32(long long a, int shift) 
158 {
159    long long  res;
160    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
161    {
162       fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
163    }
164    res = a<<shift;
165    if (!VERIFY_INT(res))
166    {
167       fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
168    }
169    celt_mips++;
170    return res;
171 }
172
173 #define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
174 #define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift))
175 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
176
177 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
178 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
179
180 #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
181 #define HALF32(x)  (SHR32(x,1))
182
183 //#define SHR(a,shift) ((a) >> (shift))
184 //#define SHL(a,shift) ((a) << (shift))
185
186 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
187 static inline short _ADD16(int a, int b, char *file, int line) 
188 {
189    int res;
190    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
191    {
192       fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
193    }
194    res = a+b;
195    if (!VERIFY_SHORT(res))
196    {
197       fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
198    }
199    celt_mips++;
200    return res;
201 }
202
203 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
204 static inline short _SUB16(int a, int b, char *file, int line) 
205 {
206    int res;
207    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
208    {
209       fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
210    }
211    res = a-b;
212    if (!VERIFY_SHORT(res))
213       fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
214    celt_mips++;
215    return res;
216 }
217
218 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
219 static inline int _ADD32(long long a, long long b, char *file, int line) 
220 {
221    long long res;
222    if (!VERIFY_INT(a) || !VERIFY_INT(b))
223    {
224       fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
225    }
226    res = a+b;
227    if (!VERIFY_INT(res))
228    {
229       fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
230    }
231    celt_mips++;
232    return res;
233 }
234
235 static inline int SUB32(long long a, long long b) 
236 {
237    long long res;
238    if (!VERIFY_INT(a) || !VERIFY_INT(b))
239    {
240       fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
241    }
242    res = a-b;
243    if (!VERIFY_INT(res))
244       fprintf (stderr, "SUB32: output is not int: %d\n", (int)res);
245    celt_mips++;
246    return res;
247 }
248
249 #define ADD64(a,b) (MIPS_INC(a)+(b))
250
251 /* result fits in 16 bits */
252 static inline short MULT16_16_16(int a, int b) 
253 {
254    int res;
255    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
256    {
257       fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
258    }
259    res = a*b;
260    if (!VERIFY_SHORT(res))
261       fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
262    celt_mips++;
263    return res;
264 }
265
266 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
267 static inline int _MULT16_16(int a, int b, char *file, int line) 
268 {
269    long long res;
270    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
271    {
272       fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
273    }
274    res = ((long long)a)*b;
275    if (!VERIFY_INT(res))
276       fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
277    celt_mips++;
278    return res;
279 }
280
281 #define MAC16_16(c,a,b)     (celt_mips--,ADD32((c),MULT16_16((a),(b))))
282 #define MAC16_16_Q11(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11)))))
283 #define MAC16_16_Q13(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13)))))
284 #define MAC16_16_P13(c,a,b)     (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13))))
285
286
287 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
288 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
289 {
290    long long res;
291    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
292    {
293       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);
294    }
295    if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
296       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
297    res = (((long long)a)*(long long)b) >> Q;
298    if (!VERIFY_INT(res))
299       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);
300    celt_mips+=5;
301    return res;
302 }
303
304 static inline int MULT16_32_PX(int a, long long b, int Q)
305 {
306    long long res;
307    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
308    {
309       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
310    }
311    if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
312       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
313    res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q;
314    if (!VERIFY_INT(res))
315       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
316    celt_mips+=5;
317    return res;
318 }
319
320
321 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
322 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
323 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
324 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
325 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
326 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
327 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
328 #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
329
330 static inline int SATURATE(int a, int b)
331 {
332    if (a>b)
333       a=b;
334    if (a<-b)
335       a = -b;
336    return a;
337 }
338
339 static inline int MULT16_16_Q11_32(int a, int b) 
340 {
341    long long res;
342    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
343    {
344       fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
345    }
346    res = ((long long)a)*b;
347    res >>= 11;
348    if (!VERIFY_INT(res))
349       fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
350    celt_mips+=3;
351    return res;
352 }
353 static inline short MULT16_16_Q13(int a, int b) 
354 {
355    long long res;
356    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
357    {
358       fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
359    }
360    res = ((long long)a)*b;
361    res >>= 13;
362    if (!VERIFY_SHORT(res))
363       fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
364    celt_mips+=3;
365    return res;
366 }
367 static inline short MULT16_16_Q14(int a, int b) 
368 {
369    long long res;
370    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
371    {
372       fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
373    }
374    res = ((long long)a)*b;
375    res >>= 14;
376    if (!VERIFY_SHORT(res))
377       fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
378    celt_mips+=3;
379    return res;
380 }
381 static inline short MULT16_16_Q15(int a, int b) 
382 {
383    long long res;
384    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
385    {
386       fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
387    }
388    res = ((long long)a)*b;
389    res >>= 15;
390    if (!VERIFY_SHORT(res))
391    {
392       fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
393    }
394    celt_mips+=3;
395    return res;
396 }
397
398 static inline short MULT16_16_P13(int a, int b) 
399 {
400    long long res;
401    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
402    {
403       fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
404    }
405    res = ((long long)a)*b;
406    res += 4096;
407    if (!VERIFY_INT(res))
408       fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
409    res >>= 13;
410    if (!VERIFY_SHORT(res))
411       fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
412    celt_mips+=4;
413    return res;
414 }
415 static inline short MULT16_16_P14(int a, int b) 
416 {
417    long long res;
418    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
419    {
420       fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
421    }
422    res = ((long long)a)*b;
423    res += 8192;
424    if (!VERIFY_INT(res))
425       fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
426    res >>= 14;
427    if (!VERIFY_SHORT(res))
428       fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
429    celt_mips+=4;
430    return res;
431 }
432 static inline short MULT16_16_P15(int a, int b) 
433 {
434    long long res;
435    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
436    {
437       fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
438    }
439    res = ((long long)a)*b;
440    res += 16384;
441    if (!VERIFY_INT(res))
442       fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
443    res >>= 15;
444    if (!VERIFY_SHORT(res))
445       fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
446    celt_mips+=4;
447    return res;
448 }
449
450 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
451
452 static inline int _DIV32_16(long long a, long long b, char *file, int line) 
453 {
454    long long res;
455    if (b==0)
456    {
457       fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
458       return 0;
459    }
460    if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
461    {
462       fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
463    }
464    res = a/b;
465    if (!VERIFY_SHORT(res))
466    {
467       fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
468       if (res>32767)
469          res = 32767;
470       if (res<-32768)
471          res = -32768;
472    }
473    celt_mips+=20;
474    return res;
475 }
476
477 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
478 static inline int _DIV32(long long a, long long b, char *file, int line) 
479 {
480    long long res;
481    if (b==0)
482    {
483       fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
484       return 0;
485    }
486
487    if (!VERIFY_INT(a) || !VERIFY_INT(b))
488    {
489       fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
490    }
491    res = a/b;
492    if (!VERIFY_INT(res))
493       fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
494    celt_mips+=36;
495    return res;
496 }
497 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
498 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
499
500 #endif