1 /* Copyright (C) 2003-2008 Jean-Marc Valin
2 Copyright (C) 2007-2012 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 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "opus_defines.h"
39 OPUS_EXPORT opus_int64 celt_mips
=0;
41 extern opus_int64 celt_mips
;
44 #define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
45 #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))
47 /** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
48 #define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
50 #define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
52 #define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
53 #define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
55 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
56 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
57 #define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
59 #define SHR(a,b) SHR32(a,b)
60 #define PSHR(a,b) PSHR32(a,b)
62 static OPUS_INLINE
short NEG16(int x
)
67 fprintf (stderr
, "NEG16: input is not short: %d\n", (int)x
);
68 #ifdef FIXED_DEBUG_ASSERT
73 if (!VERIFY_SHORT(res
))
75 fprintf (stderr
, "NEG16: output is not short: %d\n", (int)res
);
76 #ifdef FIXED_DEBUG_ASSERT
83 static OPUS_INLINE
int NEG32(opus_int64 x
)
88 fprintf (stderr
, "NEG16: input is not int: %d\n", (int)x
);
89 #ifdef FIXED_DEBUG_ASSERT
96 fprintf (stderr
, "NEG16: output is not int: %d\n", (int)res
);
97 #ifdef FIXED_DEBUG_ASSERT
105 #define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
106 static OPUS_INLINE
short EXTRACT16_(int x
, char *file
, int line
)
109 if (!VERIFY_SHORT(x
))
111 fprintf (stderr
, "EXTRACT16: input is not short: %d in %s: line %d\n", x
, file
, line
);
112 #ifdef FIXED_DEBUG_ASSERT
121 #define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
122 static OPUS_INLINE
int EXTEND32_(int x
, char *file
, int line
)
125 if (!VERIFY_SHORT(x
))
127 fprintf (stderr
, "EXTEND32: input is not short: %d in %s: line %d\n", x
, file
, line
);
128 #ifdef FIXED_DEBUG_ASSERT
137 #define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
138 static OPUS_INLINE
short SHR16_(int a
, int shift
, char *file
, int line
)
141 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(shift
))
143 fprintf (stderr
, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a
, shift
, file
, line
);
144 #ifdef FIXED_DEBUG_ASSERT
149 if (!VERIFY_SHORT(res
))
151 fprintf (stderr
, "SHR16: output is not short: %d in %s: line %d\n", res
, file
, line
);
152 #ifdef FIXED_DEBUG_ASSERT
159 #define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
160 static OPUS_INLINE
short SHL16_(int a
, int shift
, char *file
, int line
)
163 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(shift
))
165 fprintf (stderr
, "SHL16: inputs are not short: %d %d in %s: line %d\n", a
, shift
, file
, line
);
166 #ifdef FIXED_DEBUG_ASSERT
171 if (!VERIFY_SHORT(res
))
173 fprintf (stderr
, "SHL16: output is not short: %d in %s: line %d\n", res
, file
, line
);
174 #ifdef FIXED_DEBUG_ASSERT
182 static OPUS_INLINE
int SHR32(opus_int64 a
, int shift
)
185 if (!VERIFY_INT(a
) || !VERIFY_SHORT(shift
))
187 fprintf (stderr
, "SHR32: inputs are not int: %d %d\n", (int)a
, shift
);
188 #ifdef FIXED_DEBUG_ASSERT
193 if (!VERIFY_INT(res
))
195 fprintf (stderr
, "SHR32: output is not int: %d\n", (int)res
);
196 #ifdef FIXED_DEBUG_ASSERT
203 #define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
204 static OPUS_INLINE
int SHL32_(opus_int64 a
, int shift
, char *file
, int line
)
207 if (!VERIFY_INT(a
) || !VERIFY_SHORT(shift
))
209 fprintf (stderr
, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a
, shift
, file
, line
);
210 #ifdef FIXED_DEBUG_ASSERT
215 if (!VERIFY_INT(res
))
217 fprintf (stderr
, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a
, shift
, res
, file
, line
);
218 #ifdef FIXED_DEBUG_ASSERT
226 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
227 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
229 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
230 #define HALF16(x) (SHR16(x,1))
231 #define HALF32(x) (SHR32(x,1))
233 //#define SHR(a,shift) ((a) >> (shift))
234 //#define SHL(a,shift) ((a) << (shift))
236 #define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
237 static OPUS_INLINE
short ADD16_(int a
, int b
, char *file
, int line
)
240 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
242 fprintf (stderr
, "ADD16: inputs are not short: %d %d in %s: line %d\n", a
, b
, file
, line
);
243 #ifdef FIXED_DEBUG_ASSERT
248 if (!VERIFY_SHORT(res
))
250 fprintf (stderr
, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a
,b
,res
, file
, line
);
251 #ifdef FIXED_DEBUG_ASSERT
259 #define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
260 static OPUS_INLINE
short SUB16_(int a
, int b
, char *file
, int line
)
263 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
265 fprintf (stderr
, "SUB16: inputs are not short: %d %d in %s: line %d\n", a
, b
, file
, line
);
266 #ifdef FIXED_DEBUG_ASSERT
271 if (!VERIFY_SHORT(res
))
273 fprintf (stderr
, "SUB16: output is not short: %d in %s: line %d\n", res
, file
, line
);
274 #ifdef FIXED_DEBUG_ASSERT
282 #define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
283 static OPUS_INLINE
int ADD32_(opus_int64 a
, opus_int64 b
, char *file
, int line
)
286 if (!VERIFY_INT(a
) || !VERIFY_INT(b
))
288 fprintf (stderr
, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
289 #ifdef FIXED_DEBUG_ASSERT
294 if (!VERIFY_INT(res
))
296 fprintf (stderr
, "ADD32: output is not int: %d in %s: line %d\n", (int)res
, file
, line
);
297 #ifdef FIXED_DEBUG_ASSERT
305 #define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
306 static OPUS_INLINE
int SUB32_(opus_int64 a
, opus_int64 b
, char *file
, int line
)
309 if (!VERIFY_INT(a
) || !VERIFY_INT(b
))
311 fprintf (stderr
, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
312 #ifdef FIXED_DEBUG_ASSERT
317 if (!VERIFY_INT(res
))
319 fprintf (stderr
, "SUB32: output is not int: %d in %s: line %d\n", (int)res
, file
, line
);
320 #ifdef FIXED_DEBUG_ASSERT
329 #define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
330 static OPUS_INLINE
unsigned int UADD32_(opus_uint64 a
, opus_uint64 b
, char *file
, int line
)
333 if (!VERIFY_UINT(a
) || !VERIFY_UINT(b
))
335 fprintf (stderr
, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a
, b
, file
, line
);
336 #ifdef FIXED_DEBUG_ASSERT
341 if (!VERIFY_UINT(res
))
343 fprintf (stderr
, "UADD32: output is not uint32: %llu in %s: line %d\n", res
, file
, line
);
344 #ifdef FIXED_DEBUG_ASSERT
353 #define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
354 static OPUS_INLINE
unsigned int USUB32_(opus_uint64 a
, opus_uint64 b
, char *file
, int line
)
357 if (!VERIFY_UINT(a
) || !VERIFY_UINT(b
))
359 fprintf (stderr
, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a
, b
, file
, line
);
360 #ifdef FIXED_DEBUG_ASSERT
366 fprintf (stderr
, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", a
, b
, file
, line
);
367 #ifdef FIXED_DEBUG_ASSERT
372 if (!VERIFY_UINT(res
))
374 fprintf (stderr
, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", a
, b
, res
, file
, line
);
375 #ifdef FIXED_DEBUG_ASSERT
383 /* result fits in 16 bits */
384 static OPUS_INLINE
short MULT16_16_16(int a
, int b
)
387 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
389 fprintf (stderr
, "MULT16_16_16: inputs are not short: %d %d\n", a
, b
);
390 #ifdef FIXED_DEBUG_ASSERT
395 if (!VERIFY_SHORT(res
))
397 fprintf (stderr
, "MULT16_16_16: output is not short: %d\n", res
);
398 #ifdef FIXED_DEBUG_ASSERT
406 #define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
407 static OPUS_INLINE
int MULT16_16_(int a
, int b
, char *file
, int line
)
410 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
412 fprintf (stderr
, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a
, b
, file
, line
);
413 #ifdef FIXED_DEBUG_ASSERT
417 res
= ((opus_int64
)a
)*b
;
418 if (!VERIFY_INT(res
))
420 fprintf (stderr
, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res
, file
, line
);
421 #ifdef FIXED_DEBUG_ASSERT
429 #define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
431 #define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
432 static OPUS_INLINE
int MULT16_32_QX_(int a
, opus_int64 b
, int Q
, char *file
, int line
)
435 if (!VERIFY_SHORT(a
) || !VERIFY_INT(b
))
437 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
);
438 #ifdef FIXED_DEBUG_ASSERT
442 if (ABS32(b
)>=((opus_val32
)(1)<<(15+Q
)))
444 fprintf (stderr
, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q
, (int)a
, (int)b
, file
, line
);
445 #ifdef FIXED_DEBUG_ASSERT
449 res
= (((opus_int64
)a
)*(opus_int64
)b
) >> Q
;
450 if (!VERIFY_INT(res
))
452 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
);
453 #ifdef FIXED_DEBUG_ASSERT
464 #define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
465 static OPUS_INLINE
int MULT16_32_PX_(int a
, opus_int64 b
, int Q
, char *file
, int line
)
468 if (!VERIFY_SHORT(a
) || !VERIFY_INT(b
))
470 fprintf (stderr
, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q
, (int)a
, (int)b
, file
, line
);
471 #ifdef FIXED_DEBUG_ASSERT
475 if (ABS32(b
)>=((opus_int64
)(1)<<(15+Q
)))
477 fprintf (stderr
, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q
, (int)a
, (int)b
,file
, line
);
478 #ifdef FIXED_DEBUG_ASSERT
482 res
= ((((opus_int64
)a
)*(opus_int64
)b
) + (((opus_val32
)(1)<<Q
)>>1))>> Q
;
483 if (!VERIFY_INT(res
))
485 fprintf (stderr
, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q
, (int)a
, (int)b
,(int)res
, file
, line
);
486 #ifdef FIXED_DEBUG_ASSERT
497 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
498 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
500 static OPUS_INLINE
int SATURATE(int a
, int b
)
510 static OPUS_INLINE opus_int16
SATURATE16(opus_int32 a
)
520 static OPUS_INLINE
int MULT16_16_Q11_32(int a
, int b
)
523 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
525 fprintf (stderr
, "MULT16_16_Q11: inputs are not short: %d %d\n", a
, b
);
526 #ifdef FIXED_DEBUG_ASSERT
530 res
= ((opus_int64
)a
)*b
;
532 if (!VERIFY_INT(res
))
534 fprintf (stderr
, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a
, (int)b
, (int)res
);
535 #ifdef FIXED_DEBUG_ASSERT
542 static OPUS_INLINE
short MULT16_16_Q13(int a
, int b
)
545 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
547 fprintf (stderr
, "MULT16_16_Q13: inputs are not short: %d %d\n", a
, b
);
548 #ifdef FIXED_DEBUG_ASSERT
552 res
= ((opus_int64
)a
)*b
;
554 if (!VERIFY_SHORT(res
))
556 fprintf (stderr
, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a
, b
, (int)res
);
557 #ifdef FIXED_DEBUG_ASSERT
564 static OPUS_INLINE
short MULT16_16_Q14(int a
, int b
)
567 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
569 fprintf (stderr
, "MULT16_16_Q14: inputs are not short: %d %d\n", a
, b
);
570 #ifdef FIXED_DEBUG_ASSERT
574 res
= ((opus_int64
)a
)*b
;
576 if (!VERIFY_SHORT(res
))
578 fprintf (stderr
, "MULT16_16_Q14: output is not short: %d\n", (int)res
);
579 #ifdef FIXED_DEBUG_ASSERT
587 #define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
588 static OPUS_INLINE
short MULT16_16_Q15_(int a
, int b
, char *file
, int line
)
591 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
593 fprintf (stderr
, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a
, b
, file
, line
);
594 #ifdef FIXED_DEBUG_ASSERT
598 res
= ((opus_int64
)a
)*b
;
600 if (!VERIFY_SHORT(res
))
602 fprintf (stderr
, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res
, file
, line
);
603 #ifdef FIXED_DEBUG_ASSERT
611 static OPUS_INLINE
short MULT16_16_P13(int a
, int b
)
614 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
616 fprintf (stderr
, "MULT16_16_P13: inputs are not short: %d %d\n", a
, b
);
617 #ifdef FIXED_DEBUG_ASSERT
621 res
= ((opus_int64
)a
)*b
;
623 if (!VERIFY_INT(res
))
625 fprintf (stderr
, "MULT16_16_P13: overflow: %d*%d=%d\n", a
, b
, (int)res
);
626 #ifdef FIXED_DEBUG_ASSERT
631 if (!VERIFY_SHORT(res
))
633 fprintf (stderr
, "MULT16_16_P13: output is not short: %d*%d=%d\n", a
, b
, (int)res
);
634 #ifdef FIXED_DEBUG_ASSERT
641 static OPUS_INLINE
short MULT16_16_P14(int a
, int b
)
644 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
646 fprintf (stderr
, "MULT16_16_P14: inputs are not short: %d %d\n", a
, b
);
647 #ifdef FIXED_DEBUG_ASSERT
651 res
= ((opus_int64
)a
)*b
;
653 if (!VERIFY_INT(res
))
655 fprintf (stderr
, "MULT16_16_P14: overflow: %d*%d=%d\n", a
, b
, (int)res
);
656 #ifdef FIXED_DEBUG_ASSERT
661 if (!VERIFY_SHORT(res
))
663 fprintf (stderr
, "MULT16_16_P14: output is not short: %d*%d=%d\n", a
, b
, (int)res
);
664 #ifdef FIXED_DEBUG_ASSERT
671 static OPUS_INLINE
short MULT16_16_P15(int a
, int b
)
674 if (!VERIFY_SHORT(a
) || !VERIFY_SHORT(b
))
676 fprintf (stderr
, "MULT16_16_P15: inputs are not short: %d %d\n", a
, b
);
677 #ifdef FIXED_DEBUG_ASSERT
681 res
= ((opus_int64
)a
)*b
;
683 if (!VERIFY_INT(res
))
685 fprintf (stderr
, "MULT16_16_P15: overflow: %d*%d=%d\n", a
, b
, (int)res
);
686 #ifdef FIXED_DEBUG_ASSERT
691 if (!VERIFY_SHORT(res
))
693 fprintf (stderr
, "MULT16_16_P15: output is not short: %d*%d=%d\n", a
, b
, (int)res
);
694 #ifdef FIXED_DEBUG_ASSERT
702 #define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
704 static OPUS_INLINE
int DIV32_16_(opus_int64 a
, opus_int64 b
, char *file
, int line
)
709 fprintf(stderr
, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
710 #ifdef FIXED_DEBUG_ASSERT
715 if (!VERIFY_INT(a
) || !VERIFY_SHORT(b
))
717 fprintf (stderr
, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
718 #ifdef FIXED_DEBUG_ASSERT
723 if (!VERIFY_SHORT(res
))
725 fprintf (stderr
, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a
,(int)b
,(int)res
, file
, line
);
730 #ifdef FIXED_DEBUG_ASSERT
738 #define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
739 static OPUS_INLINE
int DIV32_(opus_int64 a
, opus_int64 b
, char *file
, int line
)
744 fprintf(stderr
, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
745 #ifdef FIXED_DEBUG_ASSERT
751 if (!VERIFY_INT(a
) || !VERIFY_INT(b
))
753 fprintf (stderr
, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a
, (int)b
, file
, line
);
754 #ifdef FIXED_DEBUG_ASSERT
759 if (!VERIFY_INT(res
))
761 fprintf (stderr
, "DIV32: output is not int: %d in %s: line %d\n", (int)res
, file
, line
);
762 #ifdef FIXED_DEBUG_ASSERT
771 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);