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