Mercurial > hg > sv-dependency-builds
comparison src/opus-1.3/celt/fixed_debug.h @ 69:7aeed7906520
Add Opus sources and macOS builds
author | Chris Cannam |
---|---|
date | Wed, 23 Jan 2019 13:48:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
68:85d5306e114e | 69:7aeed7906520 |
---|---|
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 | |
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 } | |
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__) | |
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__) | |
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__) | |
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__) | |
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 | |
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__) | |
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__) | |
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__) | |
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__) | |
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__) | |
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__) | |
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__) | |
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 */ | |
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__) | |
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__) | |
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__) | |
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 | |
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 | |
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 | |
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 } | |
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 } | |
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__) | |
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 | |
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 } | |
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 } | |
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 | |
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__) | |
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 | |
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 |