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