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 QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
44 #define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
45
46
47 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
48 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
49
NEG16(int x)50 static inline short NEG16(int x)
51 {
52 int res;
53 if (!VERIFY_SHORT(x))
54 {
55 fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
56 }
57 res = -x;
58 if (!VERIFY_SHORT(res))
59 fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
60 spx_mips++;
61 return res;
62 }
NEG32(long long x)63 static inline int NEG32(long long x)
64 {
65 long long res;
66 if (!VERIFY_INT(x))
67 {
68 fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
69 }
70 res = -x;
71 if (!VERIFY_INT(res))
72 fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
73 spx_mips++;
74 return res;
75 }
76
77 #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
_EXTRACT16(int x,char * file,int line)78 static inline short _EXTRACT16(int x, char *file, int line)
79 {
80 int res;
81 if (!VERIFY_SHORT(x))
82 {
83 fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
84 }
85 res = x;
86 spx_mips++;
87 return res;
88 }
89
90 #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
_EXTEND32(int x,char * file,int line)91 static inline int _EXTEND32(int x, char *file, int line)
92 {
93 int res;
94 if (!VERIFY_SHORT(x))
95 {
96 fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
97 }
98 res = x;
99 spx_mips++;
100 return res;
101 }
102
103 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
_SHR16(int a,int shift,char * file,int line)104 static inline short _SHR16(int a, int shift, char *file, int line)
105 {
106 int res;
107 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
108 {
109 fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
110 }
111 res = a>>shift;
112 if (!VERIFY_SHORT(res))
113 fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
114 spx_mips++;
115 return res;
116 }
117 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
_SHL16(int a,int shift,char * file,int line)118 static inline short _SHL16(int a, int shift, char *file, int line)
119 {
120 int res;
121 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
122 {
123 fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
124 }
125 res = a<<shift;
126 if (!VERIFY_SHORT(res))
127 fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
128 spx_mips++;
129 return res;
130 }
131
SHR32(long long a,int shift)132 static inline int SHR32(long long a, int shift)
133 {
134 long long res;
135 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
136 {
137 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
138 }
139 res = a>>shift;
140 if (!VERIFY_INT(res))
141 {
142 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
143 }
144 spx_mips++;
145 return res;
146 }
SHL32(long long a,int shift)147 static inline int SHL32(long long a, int shift)
148 {
149 long long res;
150 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
151 {
152 fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
153 }
154 res = a<<shift;
155 if (!VERIFY_INT(res))
156 {
157 fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
158 }
159 spx_mips++;
160 return res;
161 }
162
163 #define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
164 #define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift))
165 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
166
167 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
168 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
169
170 //#define SHR(a,shift) ((a) >> (shift))
171 //#define SHL(a,shift) ((a) << (shift))
172
173 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
_ADD16(int a,int b,char * file,int line)174 static inline short _ADD16(int a, int b, char *file, int line)
175 {
176 int res;
177 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
178 {
179 fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
180 }
181 res = a+b;
182 if (!VERIFY_SHORT(res))
183 {
184 fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
185 }
186 spx_mips++;
187 return res;
188 }
189
190 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
_SUB16(int a,int b,char * file,int line)191 static inline short _SUB16(int a, int b, char *file, int line)
192 {
193 int res;
194 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
195 {
196 fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
197 }
198 res = a-b;
199 if (!VERIFY_SHORT(res))
200 fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
201 spx_mips++;
202 return res;
203 }
204
205 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
_ADD32(long long a,long long b,char * file,int line)206 static inline int _ADD32(long long a, long long b, char *file, int line)
207 {
208 long long res;
209 if (!VERIFY_INT(a) || !VERIFY_INT(b))
210 {
211 fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
212 }
213 res = a+b;
214 if (!VERIFY_INT(res))
215 {
216 fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
217 }
218 spx_mips++;
219 return res;
220 }
221
SUB32(long long a,long long b)222 static inline int SUB32(long long a, long long b)
223 {
224 long long res;
225 if (!VERIFY_INT(a) || !VERIFY_INT(b))
226 {
227 fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
228 }
229 res = a-b;
230 if (!VERIFY_INT(res))
231 fprintf (stderr, "SUB32: output is not int: %d\n", (int)res);
232 spx_mips++;
233 return res;
234 }
235
236 #define ADD64(a,b) (MIPS_INC(a)+(b))
237
238 /* result fits in 16 bits */
MULT16_16_16(int a,int b)239 static inline short MULT16_16_16(int a, int b)
240 {
241 int res;
242 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
243 {
244 fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
245 }
246 res = a*b;
247 if (!VERIFY_SHORT(res))
248 fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
249 spx_mips++;
250 return res;
251 }
252
253 /* result fits in 32 bits */
MULT16_32_32(int a,long long b)254 static inline int MULT16_32_32(int a, long long b)
255 {
256 long long res;
257 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
258 {
259 fprintf (stderr, "MULT16_32_32: inputs are not short+int: %d %d\n", a, (int)b);
260 }
261 res = a*b;
262 if (!VERIFY_INT(res))
263 fprintf (stderr, "MULT16_32_32: output is not int: %d\n", (int)res);
264 spx_mips++;
265 return res;
266 }
267
268 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
_MULT16_16(int a,int b,char * file,int line)269 static inline int _MULT16_16(int a, int b, char *file, int line)
270 {
271 long long res;
272 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
273 {
274 fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
275 }
276 res = ((long long)a)*b;
277 if (!VERIFY_INT(res))
278 fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
279 spx_mips++;
280 return res;
281 }
282
283 #define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b))))
284 #define MAC16_16_Q11(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11)))))
285 #define MAC16_16_Q13(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13)))))
286 #define MAC16_16_P13(c,a,b) (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13))))
287
288
289 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
_MULT16_32_QX(int a,long long b,int Q,char * file,int line)290 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
291 {
292 long long res;
293 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
294 {
295 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);
296 }
297 if (ABS(b)>>(16+Q))
298 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
299 res = (((long long)a)*(long long)b) >> Q;
300 if (!VERIFY_INT(res))
301 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);
302 spx_mips+=5;
303 return res;
304 }
305
MULT16_32_PX(int a,long long b,int Q)306 static inline int MULT16_32_PX(int a, long long b, int Q)
307 {
308 long long res;
309 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
310 {
311 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
312 }
313 if (ABS(b)>>(16+Q))
314 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
315 res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q;
316 if (!VERIFY_INT(res))
317 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
318 spx_mips+=5;
319 return res;
320 }
321
322
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
SATURATE(int a,int b)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
MULT16_16_Q11_32(int a,int b)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 spx_mips+=3;
348 return res;
349 }
MULT16_16_Q13(int a,int b)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 spx_mips+=3;
362 return res;
363 }
MULT16_16_Q14(int a,int b)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 spx_mips+=3;
376 return res;
377 }
MULT16_16_Q15(int a,int b)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 spx_mips+=3;
392 return res;
393 }
394
MULT16_16_P13(int a,int b)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 spx_mips+=4;
410 return res;
411 }
MULT16_16_P14(int a,int b)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 spx_mips+=4;
427 return res;
428 }
MULT16_16_P15(int a,int b)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 spx_mips+=4;
444 return res;
445 }
446
447 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
448
_DIV32_16(long long a,long long b,char * file,int line)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 spx_mips+=20;
471 return res;
472 }
473
474 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
_DIV32(long long a,long long b,char * file,int 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 spx_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
498