1/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Copyright (C) 2012 Xiph.Org Foundation
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions
6are met:
7- Redistributions of source code must retain the above copyright notice,
8this list of conditions and the following disclaimer.
9- Redistributions in binary form must reproduce the above copyright
10notice, this list of conditions and the following disclaimer in the
11documentation and/or other materials provided with the distribution.
12- Neither the name of Internet Society, IETF or IETF Trust, nor the
13names of specific contributors, may be used to endorse or promote
14products derived from this software without specific prior written
15permission.
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27***********************************************************************/
28
29#ifndef MACRO_DEBUG_H
30#define MACRO_DEBUG_H
31
32/* Redefine macro functions with extensive assertion in DEBUG mode.
33   As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
34
35#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT)
36
37#undef silk_ADD16
38#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__)
39static OPUS_INLINE opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){
40    opus_int16 ret;
41
42    ret = a + b;
43    if ( ret != silk_ADD_SAT16( a, b ) )
44    {
45        fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line);
46#ifdef FIXED_DEBUG_ASSERT
47        silk_assert( 0 );
48#endif
49    }
50    return ret;
51}
52
53#undef silk_ADD32
54#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__)
55static OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){
56    opus_int32 ret;
57
58    ret = a + b;
59    if ( ret != silk_ADD_SAT32( a, b ) )
60    {
61        fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line);
62#ifdef FIXED_DEBUG_ASSERT
63        silk_assert( 0 );
64#endif
65    }
66    return ret;
67}
68
69#undef silk_ADD64
70#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__)
71static OPUS_INLINE opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){
72    opus_int64 ret;
73
74    ret = a + b;
75    if ( ret != silk_ADD_SAT64( a, b ) )
76    {
77        fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
78#ifdef FIXED_DEBUG_ASSERT
79        silk_assert( 0 );
80#endif
81    }
82    return ret;
83}
84
85#undef silk_SUB16
86#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__)
87static OPUS_INLINE opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){
88    opus_int16 ret;
89
90    ret = a - b;
91    if ( ret != silk_SUB_SAT16( a, b ) )
92    {
93        fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line);
94#ifdef FIXED_DEBUG_ASSERT
95        silk_assert( 0 );
96#endif
97    }
98    return ret;
99}
100
101#undef silk_SUB32
102#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__)
103static OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){
104    opus_int32 ret;
105
106    ret = a - b;
107    if ( ret != silk_SUB_SAT32( a, b ) )
108    {
109        fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line);
110#ifdef FIXED_DEBUG_ASSERT
111        silk_assert( 0 );
112#endif
113    }
114    return ret;
115}
116
117#undef silk_SUB64
118#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__)
119static OPUS_INLINE opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){
120    opus_int64 ret;
121
122    ret = a - b;
123    if ( ret != silk_SUB_SAT64( a, b ) )
124    {
125        fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
126#ifdef FIXED_DEBUG_ASSERT
127        silk_assert( 0 );
128#endif
129    }
130    return ret;
131}
132
133#undef silk_ADD_SAT16
134#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__)
135static OPUS_INLINE opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) {
136    opus_int16 res;
137    res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
138    if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) )
139    {
140        fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
141#ifdef FIXED_DEBUG_ASSERT
142        silk_assert( 0 );
143#endif
144    }
145    return res;
146}
147
148#undef silk_ADD_SAT32
149#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__)
150static OPUS_INLINE opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){
151    opus_int32 res;
152    res =   ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ?       \
153            ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
154            ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
155    if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) )
156    {
157        fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
158#ifdef FIXED_DEBUG_ASSERT
159        silk_assert( 0 );
160#endif
161    }
162    return res;
163}
164
165#undef silk_ADD_SAT64
166#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__)
167static OPUS_INLINE opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) {
168    opus_int64 res;
169    int        fail = 0;
170    res =   ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                 \
171            ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
172            ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
173    if( res != a64 + b64 ) {
174        /* Check that we saturated to the correct extreme value */
175        if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
176               ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) )
177        {
178            fail = 1;
179        }
180    } else {
181        /* Saturation not necessary */
182        fail = res != a64 + b64;
183    }
184    if ( fail )
185    {
186        fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
187#ifdef FIXED_DEBUG_ASSERT
188        silk_assert( 0 );
189#endif
190    }
191    return res;
192}
193
194#undef silk_SUB_SAT16
195#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__)
196static OPUS_INLINE opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) {
197    opus_int16 res;
198    res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
199    if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) )
200    {
201        fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
202#ifdef FIXED_DEBUG_ASSERT
203        silk_assert( 0 );
204#endif
205    }
206    return res;
207}
208
209#undef silk_SUB_SAT32
210#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__)
211static OPUS_INLINE opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) {
212    opus_int32 res;
213    res =   ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ?                \
214            (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
215            ((((a32)^0x80000000) & (b32)  & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
216    if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) )
217    {
218        fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
219#ifdef FIXED_DEBUG_ASSERT
220        silk_assert( 0 );
221#endif
222    }
223    return res;
224}
225
226#undef silk_SUB_SAT64
227#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__)
228static OPUS_INLINE opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) {
229    opus_int64 res;
230    int        fail = 0;
231    res =   ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                    \
232            (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
233            ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
234    if( res != a64 - b64 ) {
235        /* Check that we saturated to the correct extreme value */
236        if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
237              ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ))
238        {
239            fail = 1;
240        }
241    } else {
242        /* Saturation not necessary */
243        fail = res != a64 - b64;
244    }
245    if ( fail )
246    {
247        fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
248#ifdef FIXED_DEBUG_ASSERT
249        silk_assert( 0 );
250#endif
251    }
252    return res;
253}
254
255#undef silk_MUL
256#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__)
257static OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){
258    opus_int32 ret;
259    opus_int64 ret64;
260    ret = a32 * b32;
261    ret64 = (opus_int64)a32 * (opus_int64)b32;
262    if ( (opus_int64)ret != ret64 )
263    {
264        fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line);
265#ifdef FIXED_DEBUG_ASSERT
266        silk_assert( 0 );
267#endif
268    }
269    return ret;
270}
271
272#undef silk_MUL_uint
273#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__)
274static OPUS_INLINE opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){
275    opus_uint32 ret;
276    ret = a32 * b32;
277    if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 )
278    {
279        fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line);
280#ifdef FIXED_DEBUG_ASSERT
281        silk_assert( 0 );
282#endif
283    }
284    return ret;
285}
286
287#undef silk_MLA
288#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__)
289static OPUS_INLINE opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
290    opus_int32 ret;
291    ret = a32 + b32 * c32;
292    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
293    {
294        fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
295#ifdef FIXED_DEBUG_ASSERT
296        silk_assert( 0 );
297#endif
298    }
299    return ret;
300}
301
302#undef silk_MLA_uint
303#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__)
304static OPUS_INLINE opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){
305    opus_uint32 ret;
306    ret = a32 + b32 * c32;
307    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
308    {
309        fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
310#ifdef FIXED_DEBUG_ASSERT
311        silk_assert( 0 );
312#endif
313    }
314    return ret;
315}
316
317#undef silk_SMULWB
318#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__)
319static OPUS_INLINE opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){
320    opus_int32 ret;
321    ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
322    if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 )
323    {
324        fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line);
325#ifdef FIXED_DEBUG_ASSERT
326        silk_assert( 0 );
327#endif
328    }
329    return ret;
330}
331
332#undef silk_SMLAWB
333#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__)
334static OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
335    opus_int32 ret;
336    ret = silk_ADD32( a32, silk_SMULWB( b32, c32 ) );
337    if ( silk_ADD32( a32, silk_SMULWB( b32, c32 ) ) != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) )
338    {
339        fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
340#ifdef FIXED_DEBUG_ASSERT
341        silk_assert( 0 );
342#endif
343    }
344    return ret;
345}
346
347#undef silk_SMULWT
348#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__)
349static OPUS_INLINE opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){
350    opus_int32 ret;
351    ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
352    if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 )
353    {
354        fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
355#ifdef FIXED_DEBUG_ASSERT
356        silk_assert( 0 );
357#endif
358    }
359    return ret;
360}
361
362#undef silk_SMLAWT
363#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__)
364static OPUS_INLINE opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
365    opus_int32 ret;
366    ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
367    if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) )
368    {
369        fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
370#ifdef FIXED_DEBUG_ASSERT
371        silk_assert( 0 );
372#endif
373    }
374    return ret;
375}
376
377#undef silk_SMULL
378#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__)
379static OPUS_INLINE opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){
380    opus_int64 ret64;
381    int        fail = 0;
382    ret64 = a64 * b64;
383    if( b64 != 0 ) {
384        fail = a64 != (ret64 / b64);
385    } else if( a64 != 0 ) {
386        fail = b64 != (ret64 / a64);
387    }
388    if ( fail )
389    {
390        fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
391#ifdef FIXED_DEBUG_ASSERT
392        silk_assert( 0 );
393#endif
394    }
395    return ret64;
396}
397
398/* no checking needed for silk_SMULBB */
399#undef silk_SMLABB
400#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__)
401static OPUS_INLINE opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
402    opus_int32 ret;
403    ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
404    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 )
405    {
406        fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
407#ifdef FIXED_DEBUG_ASSERT
408        silk_assert( 0 );
409#endif
410    }
411    return ret;
412}
413
414/* no checking needed for silk_SMULBT */
415#undef silk_SMLABT
416#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__)
417static OPUS_INLINE opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
418    opus_int32 ret;
419    ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
420    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) )
421    {
422        fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
423#ifdef FIXED_DEBUG_ASSERT
424        silk_assert( 0 );
425#endif
426    }
427    return ret;
428}
429
430/* no checking needed for silk_SMULTT */
431#undef silk_SMLATT
432#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__)
433static OPUS_INLINE opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
434    opus_int32 ret;
435    ret = a32 + (b32 >> 16) * (c32 >> 16);
436    if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) )
437    {
438        fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
439#ifdef FIXED_DEBUG_ASSERT
440        silk_assert( 0 );
441#endif
442    }
443    return ret;
444}
445
446#undef silk_SMULWW
447#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__)
448static OPUS_INLINE opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){
449    opus_int32 ret, tmp1, tmp2;
450    opus_int64 ret64;
451    int        fail = 0;
452
453    ret  = silk_SMULWB( a32, b32 );
454    tmp1 = silk_RSHIFT_ROUND( b32, 16 );
455    tmp2 = silk_MUL( a32, tmp1 );
456
457    fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1;
458
459    tmp1 = ret;
460    ret  = silk_ADD32( tmp1, tmp2 );
461    fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 );
462
463    ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
464    fail |= (opus_int64)ret != ret64;
465
466    if ( fail )
467    {
468        fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
469#ifdef FIXED_DEBUG_ASSERT
470        silk_assert( 0 );
471#endif
472    }
473
474    return ret;
475}
476
477#undef silk_SMLAWW
478#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__)
479static OPUS_INLINE opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
480    opus_int32 ret, tmp;
481
482    tmp = silk_SMULWW( b32, c32 );
483    ret = silk_ADD32( a32, tmp );
484    if ( ret != silk_ADD_SAT32( a32, tmp ) )
485    {
486        fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
487#ifdef FIXED_DEBUG_ASSERT
488        silk_assert( 0 );
489#endif
490    }
491    return ret;
492}
493
494/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
495#undef  silk_MLA_ovflw
496#define silk_MLA_ovflw(a32, b32, c32)    ((a32) + ((b32) * (c32)))
497#undef  silk_SMLABB_ovflw
498#define silk_SMLABB_ovflw(a32, b32, c32)    ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
499
500/* no checking needed for silk_SMULL
501   no checking needed for silk_SMLAL
502   no checking needed for silk_SMLALBB
503   no checking needed for SigProcFIX_CLZ16
504   no checking needed for SigProcFIX_CLZ32*/
505
506#undef silk_DIV32
507#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__)
508static OPUS_INLINE opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){
509    if ( b32 == 0 )
510    {
511        fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line);
512#ifdef FIXED_DEBUG_ASSERT
513        silk_assert( 0 );
514#endif
515    }
516    return a32 / b32;
517}
518
519#undef silk_DIV32_16
520#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__)
521static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){
522    int fail = 0;
523    fail |= b32 == 0;
524    fail |= b32 > silk_int16_MAX;
525    fail |= b32 < silk_int16_MIN;
526    if ( fail )
527    {
528        fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line);
529#ifdef FIXED_DEBUG_ASSERT
530        silk_assert( 0 );
531#endif
532    }
533    return a32 / b32;
534}
535
536/* no checking needed for silk_SAT8
537   no checking needed for silk_SAT16
538   no checking needed for silk_SAT32
539   no checking needed for silk_POS_SAT32
540   no checking needed for silk_ADD_POS_SAT8
541   no checking needed for silk_ADD_POS_SAT16
542   no checking needed for silk_ADD_POS_SAT32
543   no checking needed for silk_ADD_POS_SAT64 */
544
545#undef silk_LSHIFT8
546#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
547static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
548    opus_int8 ret;
549    int       fail = 0;
550    ret = a << shift;
551    fail |= shift < 0;
552    fail |= shift >= 8;
553    fail |= (opus_int64)ret != ((opus_int64)a) << shift;
554    if ( fail )
555    {
556        fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line);
557#ifdef FIXED_DEBUG_ASSERT
558        silk_assert( 0 );
559#endif
560    }
561    return ret;
562}
563
564#undef silk_LSHIFT16
565#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__)
566static OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
567    opus_int16 ret;
568    int        fail = 0;
569    ret = a << shift;
570    fail |= shift < 0;
571    fail |= shift >= 16;
572    fail |= (opus_int64)ret != ((opus_int64)a) << shift;
573    if ( fail )
574    {
575        fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line);
576#ifdef FIXED_DEBUG_ASSERT
577        silk_assert( 0 );
578#endif
579    }
580    return ret;
581}
582
583#undef silk_LSHIFT32
584#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__)
585static OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
586    opus_int32 ret;
587    int        fail = 0;
588    ret = a << shift;
589    fail |= shift < 0;
590    fail |= shift >= 32;
591    fail |= (opus_int64)ret != ((opus_int64)a) << shift;
592    if ( fail )
593    {
594        fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line);
595#ifdef FIXED_DEBUG_ASSERT
596        silk_assert( 0 );
597#endif
598    }
599    return ret;
600}
601
602#undef silk_LSHIFT64
603#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__)
604static OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){
605    opus_int64 ret;
606    int        fail = 0;
607    ret = a << shift;
608    fail |= shift < 0;
609    fail |= shift >= 64;
610    fail |= (ret>>shift) != ((opus_int64)a);
611    if ( fail )
612    {
613        fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
614#ifdef FIXED_DEBUG_ASSERT
615        silk_assert( 0 );
616#endif
617    }
618    return ret;
619}
620
621#undef silk_LSHIFT_ovflw
622#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__)
623static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){
624    if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */
625    {
626        fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line);
627#ifdef FIXED_DEBUG_ASSERT
628        silk_assert( 0 );
629#endif
630    }
631    return a << shift;
632}
633
634#undef silk_LSHIFT_uint
635#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__)
636static OPUS_INLINE opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
637    opus_uint32 ret;
638    ret = a << shift;
639    if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift))
640    {
641        fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
642#ifdef FIXED_DEBUG_ASSERT
643        silk_assert( 0 );
644#endif
645    }
646    return ret;
647}
648
649#undef silk_RSHIFT8
650#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__)
651static OPUS_INLINE opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
652    if ( (shift < 0) || (shift>=8) )
653    {
654        fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line);
655#ifdef FIXED_DEBUG_ASSERT
656        silk_assert( 0 );
657#endif
658    }
659    return a >> shift;
660}
661
662#undef silk_RSHIFT16
663#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__)
664static OPUS_INLINE opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
665    if ( (shift < 0) || (shift>=16) )
666    {
667        fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line);
668#ifdef FIXED_DEBUG_ASSERT
669        silk_assert( 0 );
670#endif
671    }
672    return a >> shift;
673}
674
675#undef silk_RSHIFT32
676#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__)
677static OPUS_INLINE opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
678    if ( (shift < 0) || (shift>=32) )
679    {
680        fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line);
681#ifdef FIXED_DEBUG_ASSERT
682        silk_assert( 0 );
683#endif
684    }
685    return a >> shift;
686}
687
688#undef silk_RSHIFT64
689#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__)
690static OPUS_INLINE opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){
691    if ( (shift < 0) || (shift>=64) )
692    {
693        fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line);
694#ifdef FIXED_DEBUG_ASSERT
695        silk_assert( 0 );
696#endif
697    }
698    return a >> shift;
699}
700
701#undef silk_RSHIFT_uint
702#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__)
703static OPUS_INLINE opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
704    if ( (shift < 0) || (shift>32) )
705    {
706        fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
707#ifdef FIXED_DEBUG_ASSERT
708        silk_assert( 0 );
709#endif
710    }
711    return a >> shift;
712}
713
714#undef silk_ADD_LSHIFT
715#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__)
716static OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){
717    opus_int16 ret;
718    ret = a + (b << shift);
719    if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
720    {
721        fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
722#ifdef FIXED_DEBUG_ASSERT
723        silk_assert( 0 );
724#endif
725    }
726    return ret;                /* shift >= 0 */
727}
728
729#undef silk_ADD_LSHIFT32
730#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
731static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
732    opus_int32 ret;
733    ret = a + (b << shift);
734    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
735    {
736        fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
737#ifdef FIXED_DEBUG_ASSERT
738        silk_assert( 0 );
739#endif
740    }
741    return ret;                /* shift >= 0 */
742}
743
744#undef silk_ADD_LSHIFT_uint
745#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
746static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
747    opus_uint32 ret;
748    ret = a + (b << shift);
749    if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
750    {
751        fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
752#ifdef FIXED_DEBUG_ASSERT
753        silk_assert( 0 );
754#endif
755    }
756    return ret;                /* shift >= 0 */
757}
758
759#undef silk_ADD_RSHIFT
760#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__)
761static OPUS_INLINE int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){
762    opus_int16 ret;
763    ret = a + (b >> shift);
764    if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
765    {
766        fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
767#ifdef FIXED_DEBUG_ASSERT
768        silk_assert( 0 );
769#endif
770    }
771    return ret;                /* shift  > 0 */
772}
773
774#undef silk_ADD_RSHIFT32
775#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
776static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
777    opus_int32 ret;
778    ret = a + (b >> shift);
779    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
780    {
781        fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
782#ifdef FIXED_DEBUG_ASSERT
783        silk_assert( 0 );
784#endif
785    }
786    return ret;                /* shift  > 0 */
787}
788
789#undef silk_ADD_RSHIFT_uint
790#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
791static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
792    opus_uint32 ret;
793    ret = a + (b >> shift);
794    if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
795    {
796        fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
797#ifdef FIXED_DEBUG_ASSERT
798        silk_assert( 0 );
799#endif
800    }
801    return ret;                /* shift  > 0 */
802}
803
804#undef silk_SUB_LSHIFT32
805#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
806static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
807    opus_int32 ret;
808    ret = a - (b << shift);
809    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) << shift)) )
810    {
811        fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
812#ifdef FIXED_DEBUG_ASSERT
813        silk_assert( 0 );
814#endif
815    }
816    return ret;                /* shift >= 0 */
817}
818
819#undef silk_SUB_RSHIFT32
820#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
821static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
822    opus_int32 ret;
823    ret = a - (b >> shift);
824    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) )
825    {
826        fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
827#ifdef FIXED_DEBUG_ASSERT
828        silk_assert( 0 );
829#endif
830    }
831    return ret;                /* shift  > 0 */
832}
833
834#undef silk_RSHIFT_ROUND
835#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__)
836static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){
837    opus_int32 ret;
838    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
839    /* the marco definition can't handle a shift of zero */
840    if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) )
841    {
842        fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line);
843#ifdef FIXED_DEBUG_ASSERT
844        silk_assert( 0 );
845#endif
846    }
847    return ret;
848}
849
850#undef silk_RSHIFT_ROUND64
851#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__)
852static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){
853    opus_int64 ret;
854    /* the marco definition can't handle a shift of zero */
855    if ( (shift <= 0) || (shift>=64) )
856    {
857        fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
858#ifdef FIXED_DEBUG_ASSERT
859        silk_assert( 0 );
860#endif
861    }
862    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
863    return ret;
864}
865
866/* silk_abs is used on floats also, so doesn't work... */
867/*#undef silk_abs
868static OPUS_INLINE opus_int32 silk_abs(opus_int32 a){
869    silk_assert(a != 0x80000000);
870    return (((a) >  0)  ? (a) : -(a));            // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
871}*/
872
873#undef silk_abs_int64
874#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__)
875static OPUS_INLINE opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){
876    if ( a == silk_int64_MIN )
877    {
878        fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line);
879#ifdef FIXED_DEBUG_ASSERT
880        silk_assert( 0 );
881#endif
882    }
883    return (((a) >  0)  ? (a) : -(a));            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
884}
885
886#undef silk_abs_int32
887#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__)
888static OPUS_INLINE opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){
889    if ( a == silk_int32_MIN )
890    {
891        fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line);
892#ifdef FIXED_DEBUG_ASSERT
893        silk_assert( 0 );
894#endif
895    }
896    return silk_abs(a);
897}
898
899#undef silk_CHECK_FIT8
900#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__)
901static OPUS_INLINE opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){
902    opus_int8 ret;
903    ret = (opus_int8)a;
904    if ( (opus_int64)ret != a )
905    {
906        fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line);
907#ifdef FIXED_DEBUG_ASSERT
908        silk_assert( 0 );
909#endif
910    }
911    return( ret );
912}
913
914#undef silk_CHECK_FIT16
915#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__)
916static OPUS_INLINE opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){
917    opus_int16 ret;
918    ret = (opus_int16)a;
919    if ( (opus_int64)ret != a )
920    {
921        fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line);
922#ifdef FIXED_DEBUG_ASSERT
923        silk_assert( 0 );
924#endif
925    }
926    return( ret );
927}
928
929#undef silk_CHECK_FIT32
930#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__)
931static OPUS_INLINE opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){
932    opus_int32 ret;
933    ret = (opus_int32)a;
934    if ( (opus_int64)ret != a )
935    {
936        fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line);
937#ifdef FIXED_DEBUG_ASSERT
938        silk_assert( 0 );
939#endif
940    }
941    return( ret );
942}
943
944/* no checking for silk_NSHIFT_MUL_32_32
945   no checking for silk_NSHIFT_MUL_16_16
946   no checking needed for silk_min
947   no checking needed for silk_max
948   no checking needed for silk_sign
949*/
950
951#endif
952#endif /* MACRO_DEBUG_H */
953