1 /* Copyright (C) 2003-2008 Jean-Marc Valin
2 Copyright (C) 2007-2009 Xiph.Org Foundation */
5 @brief Fixed-point operations with debugging
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
12 - Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
15 - Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
19 - Neither the name of the Xiph.org Foundation nor the names of its
20 contributors may be used to endorse or promote products derived from
21 this software without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 long long celt_mips=0;
44 extern long long celt_mips;
47 #define MIPS_INC celt_mips++,
49 #define MULT16_16SU(a,b) ((celt_word32)(celt_word16)(a)*(celt_word32)(celt_uint16)(b))
50 #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))
52 /** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
53 #define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
55 #define QCONST16(x,bits) ((celt_word16)(.5+(x)*(((celt_word32)1)<<(bits))))
56 #define QCONST32(x,bits) ((celt_word32)(.5+(x)*(((celt_word32)1)<<(bits))))
59 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
60 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
61 #define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
63 #define SHR(a,b) SHR32(a,b)
64 #define PSHR(a,b) PSHR32(a,b)
66 static inline short NEG16(int x)
71 fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
74 if (!VERIFY_SHORT(res))
75 fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
79 static inline int NEG32(long long x)
84 fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
88 fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
93 #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
94 static inline short _EXTRACT16(int x, char *file, int line)
99 fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
106 #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
107 static inline int _EXTEND32(int x, char *file, int line)
110 if (!VERIFY_SHORT(x))
112 fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
119 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
120 static inline short _SHR16(int a, int shift, char *file, int line)
123 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
125 fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
128 if (!VERIFY_SHORT(res))
129 fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
133 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
134 static inline short _SHL16(int a, int shift, char *file, int line)
137 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
139 fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
142 if (!VERIFY_SHORT(res))
143 fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
148 static inline int SHR32(long long a, int shift)
151 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
153 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
156 if (!VERIFY_INT(res))
158 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
163 static inline int SHL32(long long a, int shift)
166 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
168 fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
171 if (!VERIFY_INT(res))
173 fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
179 #define PSHR16(a,shift) (celt_mips--,SHR16(ADD16((a),((1<<((shift))>>1))),shift))
180 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((celt_word32)(1)<<((shift))>>1))),shift))
181 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
183 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
184 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
186 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
187 #define HALF32(x) (SHR32(x,1))
189 //#define SHR(a,shift) ((a) >> (shift))
190 //#define SHL(a,shift) ((a) << (shift))
192 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
193 static inline short _ADD16(int a, int b, char *file, int line)
196 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
198 fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
201 if (!VERIFY_SHORT(res))
203 fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
209 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
210 static inline short _SUB16(int a, int b, char *file, int line)
213 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
215 fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
218 if (!VERIFY_SHORT(res))
219 fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
224 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
225 static inline int _ADD32(long long a, long long b, char *file, int line)
228 if (!VERIFY_INT(a) || !VERIFY_INT(b))
230 fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
233 if (!VERIFY_INT(res))
235 fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
241 #define SUB32(a, b) _SUB32(a, b, __FILE__, __LINE__)
242 static inline int _SUB32(long long a, long long b, char *file, int line)
245 if (!VERIFY_INT(a) || !VERIFY_INT(b))
247 fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
250 if (!VERIFY_INT(res))
251 fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
257 #define UADD32(a, b) _UADD32(a, b, __FILE__, __LINE__)
258 static inline unsigned int _UADD32(unsigned long long a, unsigned long long b, char *file, int line)
261 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
263 fprintf (stderr, "UADD32: inputs are not int: %u %u in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);
266 if (!VERIFY_UINT(res))
268 fprintf (stderr, "UADD32: output is not int: %u in %s: line %d\n", (unsigned)res, file, line);
275 #define USUB32(a, b) _USUB32(a, b, __FILE__, __LINE__)
276 static inline unsigned int _USUB32(unsigned long long a, unsigned long long b, char *file, int line)
279 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
281 /*fprintf (stderr, "USUB32: inputs are not int: %llu %llu in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);*/
284 if (!VERIFY_UINT(res))
286 /*fprintf (stderr, "USUB32: output is not int: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);*/
294 /* result fits in 16 bits */
295 static inline short MULT16_16_16(int a, int b)
298 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
300 fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
303 if (!VERIFY_SHORT(res))
304 fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
309 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
310 static inline int _MULT16_16(int a, int b, char *file, int line)
313 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
315 fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
317 res = ((long long)a)*b;
318 if (!VERIFY_INT(res))
319 fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
324 #define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
325 #define MAC16_16_Q11(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
326 #define MAC16_16_Q13(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
327 #define MAC16_16_P13(c,a,b) (ADD16((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))
330 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
331 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
334 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
336 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);
338 if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
339 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
340 res = (((long long)a)*(long long)b) >> Q;
341 if (!VERIFY_INT(res))
342 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);
350 static inline int MULT16_32_PX(int a, long long b, int Q)
353 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
355 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
357 if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
358 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
359 res = ((((long long)a)*(long long)b) + (((celt_word32)(1)<<Q)>>1))>> Q;
360 if (!VERIFY_INT(res))
361 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
370 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
371 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
372 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
373 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
374 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
375 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
376 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
377 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
379 static inline int SATURATE(int a, int b)
389 static inline int MULT16_16_Q11_32(int a, int b)
392 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
394 fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
396 res = ((long long)a)*b;
398 if (!VERIFY_INT(res))
399 fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
403 static inline short MULT16_16_Q13(int a, int b)
406 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
408 fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
410 res = ((long long)a)*b;
412 if (!VERIFY_SHORT(res))
413 fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
417 static inline short MULT16_16_Q14(int a, int b)
420 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
422 fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
424 res = ((long long)a)*b;
426 if (!VERIFY_SHORT(res))
427 fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
432 #define MULT16_16_Q15(a, b) _MULT16_16_Q15(a, b, __FILE__, __LINE__)
433 static inline short _MULT16_16_Q15(int a, int b, char *file, int line)
436 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
438 fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
440 res = ((long long)a)*b;
442 if (!VERIFY_SHORT(res))
444 fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
450 static inline short MULT16_16_P13(int a, int b)
453 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
455 fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
457 res = ((long long)a)*b;
459 if (!VERIFY_INT(res))
460 fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
462 if (!VERIFY_SHORT(res))
463 fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
467 static inline short MULT16_16_P14(int a, int b)
470 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
472 fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
474 res = ((long long)a)*b;
476 if (!VERIFY_INT(res))
477 fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
479 if (!VERIFY_SHORT(res))
480 fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
484 static inline short MULT16_16_P15(int a, int b)
487 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
489 fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
491 res = ((long long)a)*b;
493 if (!VERIFY_INT(res))
494 fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
496 if (!VERIFY_SHORT(res))
497 fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
502 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
504 static inline int _DIV32_16(long long a, long long b, char *file, int line)
509 fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
512 if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
514 fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
517 if (!VERIFY_SHORT(res))
519 fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
529 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
530 static inline int _DIV32(long long a, long long b, char *file, int line)
535 fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
539 if (!VERIFY_INT(a) || !VERIFY_INT(b))
541 fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
544 if (!VERIFY_INT(res))
545 fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
549 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
550 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
553 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);