making codec draft more compliant with IETF submission rules
[opus.git] / libcelt / _kiss_fft_guts.h
1 /*
2 Copyright (c) 2003-2004, Mark Borgerding
3
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10     * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 */
14
15 #ifndef KISS_FFT_GUTS_H
16 #define KISS_FFT_GUTS_H
17
18 #define MIN(a,b) ((a)<(b) ? (a):(b))
19 #define MAX(a,b) ((a)>(b) ? (a):(b))
20
21 /* kiss_fft.h
22    defines kiss_fft_scalar as either short or a float type
23    and defines
24    typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
25 #include "kiss_fft.h"
26
27 #define MAXFACTORS 32
28 /* e.g. an fft of length 128 has 4 factors 
29  as far as kissfft is concerned
30  4*4*4*2
31  */
32
33 struct kiss_fft_state{
34     int nfft;
35 #ifndef FIXED_POINT
36     kiss_fft_scalar scale;
37 #endif
38     int factors[2*MAXFACTORS];
39     int *bitrev;
40     kiss_twiddle_cpx twiddles[1];
41 };
42
43 /*
44   Explanation of macros dealing with complex math:
45
46    C_MUL(m,a,b)         : m = a*b
47    C_FIXDIV( c , div )  : if a fixed point impl., c /= div. noop otherwise
48    C_SUB( res, a,b)     : res = a - b
49    C_SUBFROM( res , a)  : res -= a
50    C_ADDTO( res , a)    : res += a
51  * */
52 #ifdef FIXED_POINT
53 #include "arch.h"
54
55 #ifdef DOUBLE_PRECISION
56
57 # define FRACBITS 31
58 # define SAMPPROD celt_int64_t 
59 #define SAMP_MAX 2147483647
60 #ifdef MIXED_PRECISION
61 #define TWID_MAX 32767
62 #define TRIG_UPSCALE 1
63 #else
64 #define TRIG_UPSCALE 65536
65 #define TWID_MAX 2147483647
66 #endif
67 #define EXT32(a) (a)
68
69 #else /* DOUBLE_PRECISION */
70
71 # define FRACBITS 15
72 # define SAMPPROD celt_int32_t 
73 #define SAMP_MAX 32767
74 #define TRIG_UPSCALE 1
75 #define EXT32(a) EXTEND32(a)
76
77 #endif /* !DOUBLE_PRECISION */
78
79 #define SAMP_MIN -SAMP_MAX
80
81 #if defined(CHECK_OVERFLOW)
82 #  define CHECK_OVERFLOW_OP(a,op,b)  \
83         if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
84                 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) );  }
85 #endif
86
87 #   define smul(a,b) ( (SAMPPROD)(a)*(b) )
88 #   define sround( x )  (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> FRACBITS )
89
90 #ifdef MIXED_PRECISION
91
92 #   define S_MUL(a,b) MULT16_32_Q15(b, a)
93
94 #   define C_MUL(m,a,b) \
95       do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
96           (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
97
98 #   define C_MULC(m,a,b) \
99       do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
100           (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
101
102 #   define C_MUL4(m,a,b) \
103       do{ (m).r = SHR(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \
104           (m).i = SHR(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }while(0)
105
106 #   define C_MULBYSCALAR( c, s ) \
107       do{ (c).r =  S_MUL( (c).r , s ) ;\
108           (c).i =  S_MUL( (c).i , s ) ; }while(0)
109
110 #   define DIVSCALAR(x,k) \
111         (x) = S_MUL(  x, (TWID_MAX-((k)>>1))/(k)+1 )
112
113 #   define C_FIXDIV(c,div) \
114         do {    DIVSCALAR( (c).r , div);  \
115                 DIVSCALAR( (c).i  , div); }while (0)
116
117 #define  C_ADD( res, a,b)\
118     do {(res).r=ADD32((a).r,(b).r);  (res).i=ADD32((a).i,(b).i); \
119     }while(0)
120 #define  C_SUB( res, a,b)\
121     do {(res).r=SUB32((a).r,(b).r);  (res).i=SUB32((a).i,(b).i); \
122     }while(0)
123 #define C_ADDTO( res , a)\
124     do {(res).r = ADD32((res).r, (a).r);  (res).i = ADD32((res).i,(a).i);\
125     }while(0)
126
127 #define C_SUBFROM( res , a)\
128     do {(res).r = ADD32((res).r,(a).r);  (res).i = SUB32((res).i,(a).i); \
129     }while(0)
130
131 #else /* MIXED_PRECISION */
132 #   define sround4( x )  (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> (FRACBITS+2) )
133
134 #   define S_MUL(a,b) sround( smul(a,b) )
135
136 #   define C_MUL(m,a,b) \
137       do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
138           (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
139 #   define C_MULC(m,a,b) \
140       do{ (m).r = sround( smul((a).r,(b).r) + smul((a).i,(b).i) ); \
141           (m).i = sround( smul((a).i,(b).r) - smul((a).r,(b).i) ); }while(0)
142
143 #   define C_MUL4(m,a,b) \
144                do{ (m).r = sround4( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
145                (m).i = sround4( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
146
147 #   define C_MULBYSCALAR( c, s ) \
148                do{ (c).r =  sround( smul( (c).r , s ) ) ;\
149                (c).i =  sround( smul( (c).i , s ) ) ; }while(0)
150
151 #   define DIVSCALAR(x,k) \
152         (x) = sround( smul(  x, SAMP_MAX/k ) )
153
154 #   define C_FIXDIV(c,div) \
155         do {    DIVSCALAR( (c).r , div);  \
156                 DIVSCALAR( (c).i  , div); }while (0)
157
158 #endif /* !MIXED_PRECISION */
159
160
161
162 #else  /* not FIXED_POINT*/
163
164 #define EXT32(a) (a)
165
166 #   define S_MUL(a,b) ( (a)*(b) )
167 #define C_MUL(m,a,b) \
168     do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
169         (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
170 #define C_MULC(m,a,b) \
171     do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
172         (m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
173
174 #define C_MUL4(m,a,b) C_MUL(m,a,b)
175
176 #   define C_FIXDIV(c,div) /* NOOP */
177 #   define C_MULBYSCALAR( c, s ) \
178     do{ (c).r *= (s);\
179         (c).i *= (s); }while(0)
180 #endif
181
182
183
184 #ifndef CHECK_OVERFLOW_OP
185 #  define CHECK_OVERFLOW_OP(a,op,b) /* noop */
186 #endif
187
188 #ifndef C_ADD
189 #define  C_ADD( res, a,b)\
190     do { \
191             CHECK_OVERFLOW_OP((a).r,+,(b).r)\
192             CHECK_OVERFLOW_OP((a).i,+,(b).i)\
193             (res).r=(a).r+(b).r;  (res).i=(a).i+(b).i; \
194     }while(0)
195 #define  C_SUB( res, a,b)\
196     do { \
197             CHECK_OVERFLOW_OP((a).r,-,(b).r)\
198             CHECK_OVERFLOW_OP((a).i,-,(b).i)\
199             (res).r=(a).r-(b).r;  (res).i=(a).i-(b).i; \
200     }while(0)
201 #define C_ADDTO( res , a)\
202     do { \
203             CHECK_OVERFLOW_OP((res).r,+,(a).r)\
204             CHECK_OVERFLOW_OP((res).i,+,(a).i)\
205             (res).r += (a).r;  (res).i += (a).i;\
206     }while(0)
207
208 #define C_SUBFROM( res , a)\
209     do {\
210             CHECK_OVERFLOW_OP((res).r,-,(a).r)\
211             CHECK_OVERFLOW_OP((res).i,-,(a).i)\
212             (res).r -= (a).r;  (res).i -= (a).i; \
213     }while(0)
214 #endif /* C_ADD defined */
215
216 #ifdef FIXED_POINT
217 /*#  define KISS_FFT_COS(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
218 #  define KISS_FFT_SIN(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
219 #  define KISS_FFT_COS(phase)  floor(.5+TWID_MAX*cos (phase))
220 #  define KISS_FFT_SIN(phase)  floor(.5+TWID_MAX*sin (phase))
221 #  define HALF_OF(x) ((x)>>1)
222 #elif defined(USE_SIMD)
223 #  define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
224 #  define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
225 #  define HALF_OF(x) ((x)*_mm_set1_ps(.5))
226 #else
227 #  define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
228 #  define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
229 #  define HALF_OF(x) ((x)*.5)
230 #endif
231
232 #define  kf_cexp(x,phase) \
233         do{ \
234                 (x)->r = KISS_FFT_COS(phase);\
235                 (x)->i = KISS_FFT_SIN(phase);\
236         }while(0)
237    
238 #define  kf_cexp2(x,phase) \
239    do{ \
240       (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
241       (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
242 }while(0)
243
244
245 #endif /* KISS_FFT_GUTS_H */