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
500static OPUS_INLINE int SATURATE(int a, int b)
501{
502   if (a>b)
503      a=b;
504   if (a<-b)
505      a = -b;
506   celt_mips+=3;
507   return a;
508}
509
510static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
511{
512   celt_mips+=3;
513   if (a>32767)
514      return 32767;
515   else if (a<-32768)
516      return -32768;
517   else return a;
518}
519
520static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
521{
522   opus_int64 res;
523   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
524   {
525      fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
526#ifdef FIXED_DEBUG_ASSERT
527      celt_assert(0);
528#endif
529   }
530   res = ((opus_int64)a)*b;
531   res >>= 11;
532   if (!VERIFY_INT(res))
533   {
534      fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
535#ifdef FIXED_DEBUG_ASSERT
536      celt_assert(0);
537#endif
538   }
539   celt_mips+=3;
540   return res;
541}
542static OPUS_INLINE short MULT16_16_Q13(int a, int b)
543{
544   opus_int64 res;
545   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
546   {
547      fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
548#ifdef FIXED_DEBUG_ASSERT
549      celt_assert(0);
550#endif
551   }
552   res = ((opus_int64)a)*b;
553   res >>= 13;
554   if (!VERIFY_SHORT(res))
555   {
556      fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
557#ifdef FIXED_DEBUG_ASSERT
558      celt_assert(0);
559#endif
560   }
561   celt_mips+=3;
562   return res;
563}
564static OPUS_INLINE short MULT16_16_Q14(int a, int b)
565{
566   opus_int64 res;
567   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
568   {
569      fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
570#ifdef FIXED_DEBUG_ASSERT
571      celt_assert(0);
572#endif
573   }
574   res = ((opus_int64)a)*b;
575   res >>= 14;
576   if (!VERIFY_SHORT(res))
577   {
578      fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
579#ifdef FIXED_DEBUG_ASSERT
580      celt_assert(0);
581#endif
582   }
583   celt_mips+=3;
584   return res;
585}
586
587#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
588static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
589{
590   opus_int64 res;
591   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
592   {
593      fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
594#ifdef FIXED_DEBUG_ASSERT
595      celt_assert(0);
596#endif
597   }
598   res = ((opus_int64)a)*b;
599   res >>= 15;
600   if (!VERIFY_SHORT(res))
601   {
602      fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
603#ifdef FIXED_DEBUG_ASSERT
604      celt_assert(0);
605#endif
606   }
607   celt_mips+=1;
608   return res;
609}
610
611static OPUS_INLINE short MULT16_16_P13(int a, int b)
612{
613   opus_int64 res;
614   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
615   {
616      fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
617#ifdef FIXED_DEBUG_ASSERT
618      celt_assert(0);
619#endif
620   }
621   res = ((opus_int64)a)*b;
622   res += 4096;
623   if (!VERIFY_INT(res))
624   {
625      fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
626#ifdef FIXED_DEBUG_ASSERT
627      celt_assert(0);
628#endif
629   }
630   res >>= 13;
631   if (!VERIFY_SHORT(res))
632   {
633      fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
634#ifdef FIXED_DEBUG_ASSERT
635      celt_assert(0);
636#endif
637   }
638   celt_mips+=4;
639   return res;
640}
641static OPUS_INLINE short MULT16_16_P14(int a, int b)
642{
643   opus_int64 res;
644   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
645   {
646      fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
647#ifdef FIXED_DEBUG_ASSERT
648      celt_assert(0);
649#endif
650   }
651   res = ((opus_int64)a)*b;
652   res += 8192;
653   if (!VERIFY_INT(res))
654   {
655      fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
656#ifdef FIXED_DEBUG_ASSERT
657      celt_assert(0);
658#endif
659   }
660   res >>= 14;
661   if (!VERIFY_SHORT(res))
662   {
663      fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
664#ifdef FIXED_DEBUG_ASSERT
665      celt_assert(0);
666#endif
667   }
668   celt_mips+=4;
669   return res;
670}
671static OPUS_INLINE short MULT16_16_P15(int a, int b)
672{
673   opus_int64 res;
674   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
675   {
676      fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
677#ifdef FIXED_DEBUG_ASSERT
678      celt_assert(0);
679#endif
680   }
681   res = ((opus_int64)a)*b;
682   res += 16384;
683   if (!VERIFY_INT(res))
684   {
685      fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
686#ifdef FIXED_DEBUG_ASSERT
687      celt_assert(0);
688#endif
689   }
690   res >>= 15;
691   if (!VERIFY_SHORT(res))
692   {
693      fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
694#ifdef FIXED_DEBUG_ASSERT
695      celt_assert(0);
696#endif
697   }
698   celt_mips+=2;
699   return res;
700}
701
702#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
703
704static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
705{
706   opus_int64 res;
707   if (b==0)
708   {
709      fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
710#ifdef FIXED_DEBUG_ASSERT
711      celt_assert(0);
712#endif
713      return 0;
714   }
715   if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
716   {
717      fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
718#ifdef FIXED_DEBUG_ASSERT
719      celt_assert(0);
720#endif
721   }
722   res = a/b;
723   if (!VERIFY_SHORT(res))
724   {
725      fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
726      if (res>32767)
727         res = 32767;
728      if (res<-32768)
729         res = -32768;
730#ifdef FIXED_DEBUG_ASSERT
731      celt_assert(0);
732#endif
733   }
734   celt_mips+=35;
735   return res;
736}
737
738#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
739static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
740{
741   opus_int64 res;
742   if (b==0)
743   {
744      fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
745#ifdef FIXED_DEBUG_ASSERT
746      celt_assert(0);
747#endif
748      return 0;
749   }
750
751   if (!VERIFY_INT(a) || !VERIFY_INT(b))
752   {
753      fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
754#ifdef FIXED_DEBUG_ASSERT
755      celt_assert(0);
756#endif
757   }
758   res = a/b;
759   if (!VERIFY_INT(res))
760   {
761      fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
762#ifdef FIXED_DEBUG_ASSERT
763      celt_assert(0);
764#endif
765   }
766   celt_mips+=70;
767   return res;
768}
769
770#undef PRINT_MIPS
771#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
772
773#endif
774