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 opus_int32 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 = (opus_int32)((opus_uint32)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", (long long)a, shift, file, line);
218 #ifdef FIXED_DEBUG_ASSERT
219 celt_assert(0);
220 #endif
221 }
222 res = (opus_int64)((opus_uint64)a<<shift);
223 if (!VERIFY_INT(res))
224 {
225 fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", (long long)a, shift, (long long)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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)a, (unsigned long long)b, (unsigned long long)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 /* result fits in 32 bits */
MULT32_32_32(opus_int64 a,opus_int64 b)414 static OPUS_INLINE int MULT32_32_32(opus_int64 a, opus_int64 b)
415 {
416 opus_int64 res;
417 if (!VERIFY_INT(a) || !VERIFY_INT(b))
418 {
419 fprintf (stderr, "MULT32_32_32: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
420 #ifdef FIXED_DEBUG_ASSERT
421 celt_assert(0);
422 #endif
423 }
424 res = a*b;
425 if (!VERIFY_INT(res))
426 {
427 fprintf (stderr, "MULT32_32_32: output is not int: %lld\n", (long long)res);
428 #ifdef FIXED_DEBUG_ASSERT
429 celt_assert(0);
430 #endif
431 }
432 celt_mips+=5;
433 return res;
434 }
435
MULT32_32_Q16(opus_int64 a,opus_int64 b)436 static OPUS_INLINE int MULT32_32_Q16(opus_int64 a, opus_int64 b)
437 {
438 opus_int64 res;
439 if (!VERIFY_INT(a) || !VERIFY_INT(b))
440 {
441 fprintf (stderr, "MULT32_32_Q16: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
442 #ifdef FIXED_DEBUG_ASSERT
443 celt_assert(0);
444 #endif
445 }
446 res = ((opus_int64)(a)*(opus_int64)(b)) >> 16;
447 if (!VERIFY_INT(res))
448 {
449 fprintf (stderr, "MULT32_32_Q16: output is not int: %lld*%lld=%lld\n", (long long)a, (long long)b, (long long)res);
450 #ifdef FIXED_DEBUG_ASSERT
451 celt_assert(0);
452 #endif
453 }
454 celt_mips+=5;
455 return res;
456 }
457
458 #define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
MULT16_16_(int a,int b,char * file,int line)459 static OPUS_INLINE int MULT16_16_(int a, int b, char *file, int line)
460 {
461 opus_int64 res;
462 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
463 {
464 fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
465 #ifdef FIXED_DEBUG_ASSERT
466 celt_assert(0);
467 #endif
468 }
469 res = ((opus_int64)a)*b;
470 if (!VERIFY_INT(res))
471 {
472 fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
473 #ifdef FIXED_DEBUG_ASSERT
474 celt_assert(0);
475 #endif
476 }
477 celt_mips++;
478 return res;
479 }
480
481 #define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
482
483 #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)484 static OPUS_INLINE int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
485 {
486 opus_int64 res;
487 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
488 {
489 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);
490 #ifdef FIXED_DEBUG_ASSERT
491 celt_assert(0);
492 #endif
493 }
494 if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
495 {
496 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
497 #ifdef FIXED_DEBUG_ASSERT
498 celt_assert(0);
499 #endif
500 }
501 res = (((opus_int64)a)*(opus_int64)b) >> Q;
502 if (!VERIFY_INT(res))
503 {
504 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);
505 #ifdef FIXED_DEBUG_ASSERT
506 celt_assert(0);
507 #endif
508 }
509 if (Q==15)
510 celt_mips+=3;
511 else
512 celt_mips+=4;
513 return res;
514 }
515
516 #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)517 static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
518 {
519 opus_int64 res;
520 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
521 {
522 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);
523 #ifdef FIXED_DEBUG_ASSERT
524 celt_assert(0);
525 #endif
526 }
527 if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
528 {
529 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);
530 #ifdef FIXED_DEBUG_ASSERT
531 celt_assert(0);
532 #endif
533 }
534 res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
535 if (!VERIFY_INT(res))
536 {
537 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);
538 #ifdef FIXED_DEBUG_ASSERT
539 celt_assert(0);
540 #endif
541 }
542 if (Q==15)
543 celt_mips+=4;
544 else
545 celt_mips+=5;
546 return res;
547 }
548
549 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
550 #define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
551 #define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b))))
552
SATURATE(int a,int b)553 static OPUS_INLINE int SATURATE(int a, int b)
554 {
555 if (a>b)
556 a=b;
557 if (a<-b)
558 a = -b;
559 celt_mips+=3;
560 return a;
561 }
562
SATURATE16(opus_int32 a)563 static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
564 {
565 celt_mips+=3;
566 if (a>32767)
567 return 32767;
568 else if (a<-32768)
569 return -32768;
570 else return a;
571 }
572
MULT16_16_Q11_32(int a,int b)573 static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
574 {
575 opus_int64 res;
576 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
577 {
578 fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
579 #ifdef FIXED_DEBUG_ASSERT
580 celt_assert(0);
581 #endif
582 }
583 res = ((opus_int64)a)*b;
584 res >>= 11;
585 if (!VERIFY_INT(res))
586 {
587 fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
588 #ifdef FIXED_DEBUG_ASSERT
589 celt_assert(0);
590 #endif
591 }
592 celt_mips+=3;
593 return res;
594 }
MULT16_16_Q13(int a,int b)595 static OPUS_INLINE short MULT16_16_Q13(int a, int b)
596 {
597 opus_int64 res;
598 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
599 {
600 fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
601 #ifdef FIXED_DEBUG_ASSERT
602 celt_assert(0);
603 #endif
604 }
605 res = ((opus_int64)a)*b;
606 res >>= 13;
607 if (!VERIFY_SHORT(res))
608 {
609 fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
610 #ifdef FIXED_DEBUG_ASSERT
611 celt_assert(0);
612 #endif
613 }
614 celt_mips+=3;
615 return res;
616 }
MULT16_16_Q14(int a,int b)617 static OPUS_INLINE short MULT16_16_Q14(int a, int b)
618 {
619 opus_int64 res;
620 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
621 {
622 fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
623 #ifdef FIXED_DEBUG_ASSERT
624 celt_assert(0);
625 #endif
626 }
627 res = ((opus_int64)a)*b;
628 res >>= 14;
629 if (!VERIFY_SHORT(res))
630 {
631 fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
632 #ifdef FIXED_DEBUG_ASSERT
633 celt_assert(0);
634 #endif
635 }
636 celt_mips+=3;
637 return res;
638 }
639
640 #define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
MULT16_16_Q15_(int a,int b,char * file,int line)641 static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
642 {
643 opus_int64 res;
644 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
645 {
646 fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
647 #ifdef FIXED_DEBUG_ASSERT
648 celt_assert(0);
649 #endif
650 }
651 res = ((opus_int64)a)*b;
652 res >>= 15;
653 if (!VERIFY_SHORT(res))
654 {
655 fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
656 #ifdef FIXED_DEBUG_ASSERT
657 celt_assert(0);
658 #endif
659 }
660 celt_mips+=1;
661 return res;
662 }
663
MULT16_16_P13(int a,int b)664 static OPUS_INLINE short MULT16_16_P13(int a, int b)
665 {
666 opus_int64 res;
667 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
668 {
669 fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
670 #ifdef FIXED_DEBUG_ASSERT
671 celt_assert(0);
672 #endif
673 }
674 res = ((opus_int64)a)*b;
675 res += 4096;
676 if (!VERIFY_INT(res))
677 {
678 fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
679 #ifdef FIXED_DEBUG_ASSERT
680 celt_assert(0);
681 #endif
682 }
683 res >>= 13;
684 if (!VERIFY_SHORT(res))
685 {
686 fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
687 #ifdef FIXED_DEBUG_ASSERT
688 celt_assert(0);
689 #endif
690 }
691 celt_mips+=4;
692 return res;
693 }
MULT16_16_P14(int a,int b)694 static OPUS_INLINE short MULT16_16_P14(int a, int b)
695 {
696 opus_int64 res;
697 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
698 {
699 fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
700 #ifdef FIXED_DEBUG_ASSERT
701 celt_assert(0);
702 #endif
703 }
704 res = ((opus_int64)a)*b;
705 res += 8192;
706 if (!VERIFY_INT(res))
707 {
708 fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
709 #ifdef FIXED_DEBUG_ASSERT
710 celt_assert(0);
711 #endif
712 }
713 res >>= 14;
714 if (!VERIFY_SHORT(res))
715 {
716 fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
717 #ifdef FIXED_DEBUG_ASSERT
718 celt_assert(0);
719 #endif
720 }
721 celt_mips+=4;
722 return res;
723 }
MULT16_16_P15(int a,int b)724 static OPUS_INLINE short MULT16_16_P15(int a, int b)
725 {
726 opus_int64 res;
727 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
728 {
729 fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
730 #ifdef FIXED_DEBUG_ASSERT
731 celt_assert(0);
732 #endif
733 }
734 res = ((opus_int64)a)*b;
735 res += 16384;
736 if (!VERIFY_INT(res))
737 {
738 fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
739 #ifdef FIXED_DEBUG_ASSERT
740 celt_assert(0);
741 #endif
742 }
743 res >>= 15;
744 if (!VERIFY_SHORT(res))
745 {
746 fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
747 #ifdef FIXED_DEBUG_ASSERT
748 celt_assert(0);
749 #endif
750 }
751 celt_mips+=2;
752 return res;
753 }
754
755 #define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
756
DIV32_16_(opus_int64 a,opus_int64 b,char * file,int line)757 static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
758 {
759 opus_int64 res;
760 if (b==0)
761 {
762 fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
763 #ifdef FIXED_DEBUG_ASSERT
764 celt_assert(0);
765 #endif
766 return 0;
767 }
768 if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
769 {
770 fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
771 #ifdef FIXED_DEBUG_ASSERT
772 celt_assert(0);
773 #endif
774 }
775 res = a/b;
776 if (!VERIFY_SHORT(res))
777 {
778 fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
779 if (res>32767)
780 res = 32767;
781 if (res<-32768)
782 res = -32768;
783 #ifdef FIXED_DEBUG_ASSERT
784 celt_assert(0);
785 #endif
786 }
787 celt_mips+=35;
788 return res;
789 }
790
791 #define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
DIV32_(opus_int64 a,opus_int64 b,char * file,int line)792 static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
793 {
794 opus_int64 res;
795 if (b==0)
796 {
797 fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
798 #ifdef FIXED_DEBUG_ASSERT
799 celt_assert(0);
800 #endif
801 return 0;
802 }
803
804 if (!VERIFY_INT(a) || !VERIFY_INT(b))
805 {
806 fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
807 #ifdef FIXED_DEBUG_ASSERT
808 celt_assert(0);
809 #endif
810 }
811 res = a/b;
812 if (!VERIFY_INT(res))
813 {
814 fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
815 #ifdef FIXED_DEBUG_ASSERT
816 celt_assert(0);
817 #endif
818 }
819 celt_mips+=70;
820 return res;
821 }
822
SIG2WORD16_generic(celt_sig x)823 static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
824 {
825 x = PSHR32(x, SIG_SHIFT);
826 x = MAX32(x, -32768);
827 x = MIN32(x, 32767);
828 return EXTRACT16(x);
829 }
830 #define SIG2WORD16(x) (SIG2WORD16_generic(x))
831
832
833 #undef PRINT_MIPS
834 #define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", (unsigned long long)celt_mips);} while (0);
835
836 #endif
837