1 /* Copyright (C) 2003-2008 Jean-Marc Valin */
4 @brief Fixed-point operations with debugging
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
11 - Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
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.
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.
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.
41 long long celt_mips=0;
43 extern long long celt_mips;
46 #define MIPS_INC celt_mips++,
48 #define MULT16_16SU(a,b) ((celt_word32_t)(celt_word16_t)(a)*(celt_word32_t)(celt_uint16_t)(b))
49 #define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
51 /** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
52 #define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
54 #define QCONST16(x,bits) ((celt_word16_t)(.5+(x)*(((celt_word32_t)1)<<(bits))))
55 #define QCONST32(x,bits) ((celt_word32_t)(.5+(x)*(((celt_word32_t)1)<<(bits))))
58 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
59 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
60 #define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
62 #define SHR(a,b) SHR32(a,b)
63 #define PSHR(a,b) PSHR32(a,b)
65 static inline short NEG16(int x)
70 fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
73 if (!VERIFY_SHORT(res))
74 fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
78 static inline int NEG32(long long x)
83 fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
87 fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
92 #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
93 static inline short _EXTRACT16(int x, char *file, int line)
98 fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
105 #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
106 static inline int _EXTEND32(int x, char *file, int line)
109 if (!VERIFY_SHORT(x))
111 fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
118 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
119 static inline short _SHR16(int a, int shift, char *file, int line)
122 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
124 fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
127 if (!VERIFY_SHORT(res))
128 fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
132 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
133 static inline short _SHL16(int a, int shift, char *file, int line)
136 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
138 fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
141 if (!VERIFY_SHORT(res))
142 fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
147 static inline int SHR32(long long a, int shift)
150 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
152 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
155 if (!VERIFY_INT(res))
157 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
162 static inline int SHL32(long long a, int shift)
165 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
167 fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
170 if (!VERIFY_INT(res))
172 fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
178 #define PSHR16(a,shift) (celt_mips--,SHR16(ADD16((a),((1<<((shift))>>1))),shift))
179 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((celt_word32_t)(1)<<((shift))>>1))),shift))
180 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
182 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
183 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
185 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
186 #define HALF32(x) (SHR32(x,1))
188 //#define SHR(a,shift) ((a) >> (shift))
189 //#define SHL(a,shift) ((a) << (shift))
191 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
192 static inline short _ADD16(int a, int b, char *file, int line)
195 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
197 fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
200 if (!VERIFY_SHORT(res))
202 fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
208 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
209 static inline short _SUB16(int a, int b, char *file, int line)
212 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
214 fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
217 if (!VERIFY_SHORT(res))
218 fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
223 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
224 static inline int _ADD32(long long a, long long b, char *file, int line)
227 if (!VERIFY_INT(a) || !VERIFY_INT(b))
229 fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
232 if (!VERIFY_INT(res))
234 fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
240 #define SUB32(a, b) _SUB32(a, b, __FILE__, __LINE__)
241 static inline int _SUB32(long long a, long long b, char *file, int line)
244 if (!VERIFY_INT(a) || !VERIFY_INT(b))
246 fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
249 if (!VERIFY_INT(res))
250 fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
256 #define UADD32(a, b) _UADD32(a, b, __FILE__, __LINE__)
257 static inline unsigned int _UADD32(unsigned long long a, unsigned long long b, char *file, int line)
260 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
262 fprintf (stderr, "UADD32: inputs are not int: %u %u in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);
265 if (!VERIFY_UINT(res))
267 fprintf (stderr, "UADD32: output is not int: %u in %s: line %d\n", (unsigned)res, file, line);
274 #define USUB32(a, b) _USUB32(a, b, __FILE__, __LINE__)
275 static inline unsigned int _USUB32(unsigned long long a, unsigned long long b, char *file, int line)
278 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
280 /*fprintf (stderr, "USUB32: inputs are not int: %llu %llu in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);*/
283 if (!VERIFY_UINT(res))
285 /*fprintf (stderr, "USUB32: output is not int: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);*/
293 /* result fits in 16 bits */
294 static inline short MULT16_16_16(int a, int b)
297 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
299 fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
302 if (!VERIFY_SHORT(res))
303 fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
308 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
309 static inline int _MULT16_16(int a, int b, char *file, int line)
312 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
314 fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
316 res = ((long long)a)*b;
317 if (!VERIFY_INT(res))
318 fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
323 #define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
324 #define MAC16_16_Q11(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
325 #define MAC16_16_Q13(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
326 #define MAC16_16_P13(c,a,b) (ADD16((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))
329 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
330 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
333 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
335 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);
337 if (ABS32(b)>=((celt_word32_t)(1)<<(15+Q)))
338 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
339 res = (((long long)a)*(long long)b) >> Q;
340 if (!VERIFY_INT(res))
341 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);
349 static inline int MULT16_32_PX(int a, long long b, int Q)
352 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
354 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
356 if (ABS32(b)>=((celt_word32_t)(1)<<(15+Q)))
357 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
358 res = ((((long long)a)*(long long)b) + (((celt_word32_t)(1)<<Q)>>1))>> Q;
359 if (!VERIFY_INT(res))
360 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
369 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
370 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
371 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
372 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
373 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
374 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
375 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
376 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
378 static inline int SATURATE(int a, int b)
388 static inline int MULT16_16_Q11_32(int a, int b)
391 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
393 fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
395 res = ((long long)a)*b;
397 if (!VERIFY_INT(res))
398 fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
402 static inline short MULT16_16_Q13(int a, int b)
405 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
407 fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
409 res = ((long long)a)*b;
411 if (!VERIFY_SHORT(res))
412 fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
416 static inline short MULT16_16_Q14(int a, int b)
419 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
421 fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
423 res = ((long long)a)*b;
425 if (!VERIFY_SHORT(res))
426 fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
430 static inline short MULT16_16_Q15(int a, int b)
433 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
435 fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
437 res = ((long long)a)*b;
439 if (!VERIFY_SHORT(res))
441 fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
447 static inline short MULT16_16_P13(int a, int b)
450 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
452 fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
454 res = ((long long)a)*b;
456 if (!VERIFY_INT(res))
457 fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
459 if (!VERIFY_SHORT(res))
460 fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
464 static inline short MULT16_16_P14(int a, int b)
467 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
469 fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
471 res = ((long long)a)*b;
473 if (!VERIFY_INT(res))
474 fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
476 if (!VERIFY_SHORT(res))
477 fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
481 static inline short MULT16_16_P15(int a, int b)
484 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
486 fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
488 res = ((long long)a)*b;
490 if (!VERIFY_INT(res))
491 fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
493 if (!VERIFY_SHORT(res))
494 fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
499 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
501 static inline int _DIV32_16(long long a, long long b, char *file, int line)
506 fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
509 if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
511 fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
514 if (!VERIFY_SHORT(res))
516 fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
526 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
527 static inline int _DIV32(long long a, long long b, char *file, int line)
532 fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
536 if (!VERIFY_INT(a) || !VERIFY_INT(b))
538 fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
541 if (!VERIFY_INT(res))
542 fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
546 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
547 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
550 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %d MIPS\n", celt_mips);} while (0);