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