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