1 /* Copyright (C) 2003-2008 Jean-Marc Valin
2 Copyright (C) 2007-2012 Xiph.Org Foundation */
3 /**
4 @file fixed_debug.h
5 @brief Fixed-point operations with debugging
6 */
7 /*
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11
12 - Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14
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.
18
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.
30 */
31
32 #ifndef FIXED_DEBUG_H
33 #define FIXED_DEBUG_H
34
35 #include <stdio.h>
36 #include "opus_defines.h"
37
38 #ifdef CELT_C
39 OPUS_EXPORT opus_int64 celt_mips=0;
40 #else
41 extern opus_int64 celt_mips;
42 #endif
43
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))
46
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))
49
50 #define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
51
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))))
54
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))
58
59 #define SHR(a,b) SHR32(a,b)
60 #define PSHR(a,b) PSHR32(a,b)
61
62 /** Add two 32-bit values, ignore any overflows */
63 #define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
64 /** Subtract two 32-bit values, ignore any overflows */
65 #define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
66 /* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
67 /** Negate 32-bit value, ignore any overflows */
68 #define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
69
NEG16(int x)70 static OPUS_INLINE short NEG16(int x)
71 {
72 int res;
73 if (!VERIFY_SHORT(x))
74 {
75 fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
76 #ifdef FIXED_DEBUG_ASSERT
77 celt_assert(0);
78 #endif
79 }
80 res = -x;
81 if (!VERIFY_SHORT(res))
82 {
83 fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
84 #ifdef FIXED_DEBUG_ASSERT
85 celt_assert(0);
86 #endif
87 }
88 celt_mips++;
89 return res;
90 }
NEG32(opus_int64 x)91 static OPUS_INLINE int NEG32(opus_int64 x)
92 {
93 opus_int64 res;
94 if (!VERIFY_INT(x))
95 {
96 fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
97 #ifdef FIXED_DEBUG_ASSERT
98 celt_assert(0);
99 #endif
100 }
101 res = -x;
102 if (!VERIFY_INT(res))
103 {
104 fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
105 #ifdef FIXED_DEBUG_ASSERT
106 celt_assert(0);
107 #endif
108 }
109 celt_mips+=2;
110 return res;
111 }
112
113 #define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
EXTRACT16_(int x,char * file,int line)114 static OPUS_INLINE short EXTRACT16_(int x, char *file, int line)
115 {
116 int res;
117 if (!VERIFY_SHORT(x))
118 {
119 fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
120 #ifdef FIXED_DEBUG_ASSERT
121 celt_assert(0);
122 #endif
123 }
124 res = x;
125 celt_mips++;
126 return res;
127 }
128
129 #define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
EXTEND32_(int x,char * file,int line)130 static OPUS_INLINE int EXTEND32_(int x, char *file, int line)
131 {
132 int res;
133 if (!VERIFY_SHORT(x))
134 {
135 fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
136 #ifdef FIXED_DEBUG_ASSERT
137 celt_assert(0);
138 #endif
139 }
140 res = x;
141 celt_mips++;
142 return res;
143 }
144
145 #define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
SHR16_(int a,int shift,char * file,int line)146 static OPUS_INLINE short SHR16_(int a, int shift, char *file, int line)
147 {
148 int res;
149 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
150 {
151 fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
152 #ifdef FIXED_DEBUG_ASSERT
153 celt_assert(0);
154 #endif
155 }
156 res = a>>shift;
157 if (!VERIFY_SHORT(res))
158 {
159 fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
160 #ifdef FIXED_DEBUG_ASSERT
161 celt_assert(0);
162 #endif
163 }
164 celt_mips++;
165 return res;
166 }
167 #define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
SHL16_(int a,int shift,char * file,int line)168 static OPUS_INLINE short SHL16_(int a, int shift, char *file, int line)
169 {
170 int res;
171 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
172 {
173 fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
174 #ifdef FIXED_DEBUG_ASSERT
175 celt_assert(0);
176 #endif
177 }
178 res = a<<shift;
179 if (!VERIFY_SHORT(res))
180 {
181 fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
182 #ifdef FIXED_DEBUG_ASSERT
183 celt_assert(0);
184 #endif
185 }
186 celt_mips++;
187 return res;
188 }
189
SHR32(opus_int64 a,int shift)190 static OPUS_INLINE int SHR32(opus_int64 a, int shift)
191 {
192 opus_int64 res;
193 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
194 {
195 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
196 #ifdef FIXED_DEBUG_ASSERT
197 celt_assert(0);
198 #endif
199 }
200 res = a>>shift;
201 if (!VERIFY_INT(res))
202 {
203 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
204 #ifdef FIXED_DEBUG_ASSERT
205 celt_assert(0);
206 #endif
207 }
208 celt_mips+=2;
209 return res;
210 }
211 #define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
SHL32_(opus_int64 a,int shift,char * file,int line)212 static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
213 {
214 opus_int64 res;
215 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
216 {
217 fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
218 #ifdef FIXED_DEBUG_ASSERT
219 celt_assert(0);
220 #endif
221 }
222 res = a<<shift;
223 if (!VERIFY_INT(res))
224 {
225 fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
226 #ifdef FIXED_DEBUG_ASSERT
227 celt_assert(0);
228 #endif
229 }
230 celt_mips+=2;
231 return res;
232 }
233
234 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
235 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
236
237 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
238 #define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
239
240 #define HALF16(x) (SHR16(x,1))
241 #define HALF32(x) (SHR32(x,1))
242
243 #define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
ADD16_(int a,int b,char * file,int line)244 static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
245 {
246 int res;
247 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
248 {
249 fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
250 #ifdef FIXED_DEBUG_ASSERT
251 celt_assert(0);
252 #endif
253 }
254 res = a+b;
255 if (!VERIFY_SHORT(res))
256 {
257 fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
258 #ifdef FIXED_DEBUG_ASSERT
259 celt_assert(0);
260 #endif
261 }
262 celt_mips++;
263 return res;
264 }
265
266 #define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
SUB16_(int a,int b,char * file,int line)267 static OPUS_INLINE short SUB16_(int a, int b, char *file, int line)
268 {
269 int res;
270 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
271 {
272 fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
273 #ifdef FIXED_DEBUG_ASSERT
274 celt_assert(0);
275 #endif
276 }
277 res = a-b;
278 if (!VERIFY_SHORT(res))
279 {
280 fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
281 #ifdef FIXED_DEBUG_ASSERT
282 celt_assert(0);
283 #endif
284 }
285 celt_mips++;
286 return res;
287 }
288
289 #define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
ADD32_(opus_int64 a,opus_int64 b,char * file,int line)290 static OPUS_INLINE int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
291 {
292 opus_int64 res;
293 if (!VERIFY_INT(a) || !VERIFY_INT(b))
294 {
295 fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
296 #ifdef FIXED_DEBUG_ASSERT
297 celt_assert(0);
298 #endif
299 }
300 res = a+b;
301 if (!VERIFY_INT(res))
302 {
303 fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
304 #ifdef FIXED_DEBUG_ASSERT
305 celt_assert(0);
306 #endif
307 }
308 celt_mips+=2;
309 return res;
310 }
311
312 #define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
SUB32_(opus_int64 a,opus_int64 b,char * file,int line)313 static OPUS_INLINE int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
314 {
315 opus_int64 res;
316 if (!VERIFY_INT(a) || !VERIFY_INT(b))
317 {
318 fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
319 #ifdef FIXED_DEBUG_ASSERT
320 celt_assert(0);
321 #endif
322 }
323 res = a-b;
324 if (!VERIFY_INT(res))
325 {
326 fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
327 #ifdef FIXED_DEBUG_ASSERT
328 celt_assert(0);
329 #endif
330 }
331 celt_mips+=2;
332 return res;
333 }
334
335 #undef UADD32
336 #define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
UADD32_(opus_uint64 a,opus_uint64 b,char * file,int line)337 static OPUS_INLINE unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
338 {
339 opus_uint64 res;
340 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
341 {
342 fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
343 #ifdef FIXED_DEBUG_ASSERT
344 celt_assert(0);
345 #endif
346 }
347 res = a+b;
348 if (!VERIFY_UINT(res))
349 {
350 fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", res, file, line);
351 #ifdef FIXED_DEBUG_ASSERT
352 celt_assert(0);
353 #endif
354 }
355 celt_mips+=2;
356 return res;
357 }
358
359 #undef USUB32
360 #define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
USUB32_(opus_uint64 a,opus_uint64 b,char * file,int line)361 static OPUS_INLINE unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
362 {
363 opus_uint64 res;
364 if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
365 {
366 fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
367 #ifdef FIXED_DEBUG_ASSERT
368 celt_assert(0);
369 #endif
370 }
371 if (a<b)
372 {
373 fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", a, b, file, line);
374 #ifdef FIXED_DEBUG_ASSERT
375 celt_assert(0);
376 #endif
377 }
378 res = a-b;
379 if (!VERIFY_UINT(res))
380 {
381 fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);
382 #ifdef FIXED_DEBUG_ASSERT
383 celt_assert(0);
384 #endif
385 }
386 celt_mips+=2;
387 return res;
388 }
389
390 /* result fits in 16 bits */
MULT16_16_16(int a,int b)391 static OPUS_INLINE short MULT16_16_16(int a, int b)
392 {
393 int res;
394 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
395 {
396 fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
397 #ifdef FIXED_DEBUG_ASSERT
398 celt_assert(0);
399 #endif
400 }
401 res = a*b;
402 if (!VERIFY_SHORT(res))
403 {
404 fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
405 #ifdef FIXED_DEBUG_ASSERT
406 celt_assert(0);
407 #endif
408 }
409 celt_mips++;
410 return res;
411 }
412
413 #define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
MULT16_16_(int a,int b,char * file,int line)414 static OPUS_INLINE int MULT16_16_(int a, int b, char *file, int line)
415 {
416 opus_int64 res;
417 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
418 {
419 fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
420 #ifdef FIXED_DEBUG_ASSERT
421 celt_assert(0);
422 #endif
423 }
424 res = ((opus_int64)a)*b;
425 if (!VERIFY_INT(res))
426 {
427 fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
428 #ifdef FIXED_DEBUG_ASSERT
429 celt_assert(0);
430 #endif
431 }
432 celt_mips++;
433 return res;
434 }
435
436 #define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
437
438 #define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
MULT16_32_QX_(int a,opus_int64 b,int Q,char * file,int line)439 static OPUS_INLINE int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
440 {
441 opus_int64 res;
442 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
443 {
444 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);
445 #ifdef FIXED_DEBUG_ASSERT
446 celt_assert(0);
447 #endif
448 }
449 if (ABS32(b)>=((opus_val32)(1)<<(15+Q)))
450 {
451 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
452 #ifdef FIXED_DEBUG_ASSERT
453 celt_assert(0);
454 #endif
455 }
456 res = (((opus_int64)a)*(opus_int64)b) >> Q;
457 if (!VERIFY_INT(res))
458 {
459 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);
460 #ifdef FIXED_DEBUG_ASSERT
461 celt_assert(0);
462 #endif
463 }
464 if (Q==15)
465 celt_mips+=3;
466 else
467 celt_mips+=4;
468 return res;
469 }
470
471 #define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
MULT16_32_PX_(int a,opus_int64 b,int Q,char * file,int line)472 static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
473 {
474 opus_int64 res;
475 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
476 {
477 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);
478 #ifdef FIXED_DEBUG_ASSERT
479 celt_assert(0);
480 #endif
481 }
482 if (ABS32(b)>=((opus_int64)(1)<<(15+Q)))
483 {
484 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);
485 #ifdef FIXED_DEBUG_ASSERT
486 celt_assert(0);
487 #endif
488 }
489 res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
490 if (!VERIFY_INT(res))
491 {
492 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);
493 #ifdef FIXED_DEBUG_ASSERT
494 celt_assert(0);
495 #endif
496 }
497 if (Q==15)
498 celt_mips+=4;
499 else
500 celt_mips+=5;
501 return res;
502 }
503
504 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
505 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
506 #define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b))))
507
SATURATE(int a,int b)508 static OPUS_INLINE int SATURATE(int a, int b)
509 {
510 if (a>b)
511 a=b;
512 if (a<-b)
513 a = -b;
514 celt_mips+=3;
515 return a;
516 }
517
SATURATE16(opus_int32 a)518 static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
519 {
520 celt_mips+=3;
521 if (a>32767)
522 return 32767;
523 else if (a<-32768)
524 return -32768;
525 else return a;
526 }
527
MULT16_16_Q11_32(int a,int b)528 static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
529 {
530 opus_int64 res;
531 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
532 {
533 fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
534 #ifdef FIXED_DEBUG_ASSERT
535 celt_assert(0);
536 #endif
537 }
538 res = ((opus_int64)a)*b;
539 res >>= 11;
540 if (!VERIFY_INT(res))
541 {
542 fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
543 #ifdef FIXED_DEBUG_ASSERT
544 celt_assert(0);
545 #endif
546 }
547 celt_mips+=3;
548 return res;
549 }
MULT16_16_Q13(int a,int b)550 static OPUS_INLINE short MULT16_16_Q13(int a, int b)
551 {
552 opus_int64 res;
553 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
554 {
555 fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
556 #ifdef FIXED_DEBUG_ASSERT
557 celt_assert(0);
558 #endif
559 }
560 res = ((opus_int64)a)*b;
561 res >>= 13;
562 if (!VERIFY_SHORT(res))
563 {
564 fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
565 #ifdef FIXED_DEBUG_ASSERT
566 celt_assert(0);
567 #endif
568 }
569 celt_mips+=3;
570 return res;
571 }
MULT16_16_Q14(int a,int b)572 static OPUS_INLINE short MULT16_16_Q14(int a, int b)
573 {
574 opus_int64 res;
575 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
576 {
577 fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
578 #ifdef FIXED_DEBUG_ASSERT
579 celt_assert(0);
580 #endif
581 }
582 res = ((opus_int64)a)*b;
583 res >>= 14;
584 if (!VERIFY_SHORT(res))
585 {
586 fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
587 #ifdef FIXED_DEBUG_ASSERT
588 celt_assert(0);
589 #endif
590 }
591 celt_mips+=3;
592 return res;
593 }
594
595 #define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
MULT16_16_Q15_(int a,int b,char * file,int line)596 static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
597 {
598 opus_int64 res;
599 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
600 {
601 fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
602 #ifdef FIXED_DEBUG_ASSERT
603 celt_assert(0);
604 #endif
605 }
606 res = ((opus_int64)a)*b;
607 res >>= 15;
608 if (!VERIFY_SHORT(res))
609 {
610 fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
611 #ifdef FIXED_DEBUG_ASSERT
612 celt_assert(0);
613 #endif
614 }
615 celt_mips+=1;
616 return res;
617 }
618
MULT16_16_P13(int a,int b)619 static OPUS_INLINE short MULT16_16_P13(int a, int b)
620 {
621 opus_int64 res;
622 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
623 {
624 fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
625 #ifdef FIXED_DEBUG_ASSERT
626 celt_assert(0);
627 #endif
628 }
629 res = ((opus_int64)a)*b;
630 res += 4096;
631 if (!VERIFY_INT(res))
632 {
633 fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
634 #ifdef FIXED_DEBUG_ASSERT
635 celt_assert(0);
636 #endif
637 }
638 res >>= 13;
639 if (!VERIFY_SHORT(res))
640 {
641 fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
642 #ifdef FIXED_DEBUG_ASSERT
643 celt_assert(0);
644 #endif
645 }
646 celt_mips+=4;
647 return res;
648 }
MULT16_16_P14(int a,int b)649 static OPUS_INLINE short MULT16_16_P14(int a, int b)
650 {
651 opus_int64 res;
652 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
653 {
654 fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
655 #ifdef FIXED_DEBUG_ASSERT
656 celt_assert(0);
657 #endif
658 }
659 res = ((opus_int64)a)*b;
660 res += 8192;
661 if (!VERIFY_INT(res))
662 {
663 fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
664 #ifdef FIXED_DEBUG_ASSERT
665 celt_assert(0);
666 #endif
667 }
668 res >>= 14;
669 if (!VERIFY_SHORT(res))
670 {
671 fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
672 #ifdef FIXED_DEBUG_ASSERT
673 celt_assert(0);
674 #endif
675 }
676 celt_mips+=4;
677 return res;
678 }
MULT16_16_P15(int a,int b)679 static OPUS_INLINE short MULT16_16_P15(int a, int b)
680 {
681 opus_int64 res;
682 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
683 {
684 fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
685 #ifdef FIXED_DEBUG_ASSERT
686 celt_assert(0);
687 #endif
688 }
689 res = ((opus_int64)a)*b;
690 res += 16384;
691 if (!VERIFY_INT(res))
692 {
693 fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
694 #ifdef FIXED_DEBUG_ASSERT
695 celt_assert(0);
696 #endif
697 }
698 res >>= 15;
699 if (!VERIFY_SHORT(res))
700 {
701 fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
702 #ifdef FIXED_DEBUG_ASSERT
703 celt_assert(0);
704 #endif
705 }
706 celt_mips+=2;
707 return res;
708 }
709
710 #define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
711
DIV32_16_(opus_int64 a,opus_int64 b,char * file,int line)712 static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
713 {
714 opus_int64 res;
715 if (b==0)
716 {
717 fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
718 #ifdef FIXED_DEBUG_ASSERT
719 celt_assert(0);
720 #endif
721 return 0;
722 }
723 if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
724 {
725 fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
726 #ifdef FIXED_DEBUG_ASSERT
727 celt_assert(0);
728 #endif
729 }
730 res = a/b;
731 if (!VERIFY_SHORT(res))
732 {
733 fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
734 if (res>32767)
735 res = 32767;
736 if (res<-32768)
737 res = -32768;
738 #ifdef FIXED_DEBUG_ASSERT
739 celt_assert(0);
740 #endif
741 }
742 celt_mips+=35;
743 return res;
744 }
745
746 #define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
DIV32_(opus_int64 a,opus_int64 b,char * file,int line)747 static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
748 {
749 opus_int64 res;
750 if (b==0)
751 {
752 fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
753 #ifdef FIXED_DEBUG_ASSERT
754 celt_assert(0);
755 #endif
756 return 0;
757 }
758
759 if (!VERIFY_INT(a) || !VERIFY_INT(b))
760 {
761 fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
762 #ifdef FIXED_DEBUG_ASSERT
763 celt_assert(0);
764 #endif
765 }
766 res = a/b;
767 if (!VERIFY_INT(res))
768 {
769 fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
770 #ifdef FIXED_DEBUG_ASSERT
771 celt_assert(0);
772 #endif
773 }
774 celt_mips+=70;
775 return res;
776 }
777
SIG2WORD16_generic(celt_sig x)778 static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
779 {
780 x = PSHR32(x, SIG_SHIFT);
781 x = MAX32(x, -32768);
782 x = MIN32(x, 32767);
783 return EXTRACT16(x);
784 }
785 #define SIG2WORD16(x) (SIG2WORD16_generic(x))
786
787
788 #undef PRINT_MIPS
789 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
790
791 #endif
792