a3ec8544888933b9c9f6580c52afae1571f9e8f7
[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 shift;
39     int factors[2*MAXFACTORS];
40     celt_int16 *bitrev;
41     kiss_twiddle_cpx *twiddles;
42 };
43
44 /*
45   Explanation of macros dealing with complex math:
46
47    C_MUL(m,a,b)         : m = a*b
48    C_FIXDIV( c , div )  : if a fixed point impl., c /= div. noop otherwise
49    C_SUB( res, a,b)     : res = a - b
50    C_SUBFROM( res , a)  : res -= a
51    C_ADDTO( res , a)    : res += a
52  * */
53 #ifdef FIXED_POINT
54 #include "arch.h"
55
56 #ifdef DOUBLE_PRECISION
57
58 # define FRACBITS 31
59 # define SAMPPROD long long
60 #define SAMP_MAX 2147483647
61 #ifdef MIXED_PRECISION
62 #define TWID_MAX 32767
63 #define TRIG_UPSCALE 1
64 #else
65 #define TRIG_UPSCALE 65536
66 #define TWID_MAX 2147483647
67 #endif
68 #define EXT32(a) (a)
69
70 #else /* DOUBLE_PRECISION */
71
72 # define FRACBITS 15
73 # define SAMPPROD celt_int32 
74 #define SAMP_MAX 32767
75 #define TRIG_UPSCALE 1
76 #define EXT32(a) EXTEND32(a)
77
78 #endif /* !DOUBLE_PRECISION */
79
80 #define SAMP_MIN -SAMP_MAX
81
82 #if defined(CHECK_OVERFLOW)
83 #  define CHECK_OVERFLOW_OP(a,op,b)  \
84         if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
85                 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) );  }
86 #endif
87
88 #   define smul(a,b) ( (SAMPPROD)(a)*(b) )
89 #   define sround( x )  (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> FRACBITS )
90
91 #ifdef MIXED_PRECISION
92
93 #   define S_MUL(a,b) MULT16_32_Q15(b, a)
94
95 #   define C_MUL(m,a,b) \
96       do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
97           (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
98
99 #   define C_MULC(m,a,b) \
100       do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
101           (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
102
103 #   define C_MUL4(m,a,b) \
104       do{ (m).r = SHR(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \
105           (m).i = SHR(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }while(0)
106
107 #   define C_MULBYSCALAR( c, s ) \
108       do{ (c).r =  S_MUL( (c).r , s ) ;\
109           (c).i =  S_MUL( (c).i , s ) ; }while(0)
110
111 #   define DIVSCALAR(x,k) \
112         (x) = S_MUL(  x, (TWID_MAX-((k)>>1))/(k)+1 )
113
114 #   define C_FIXDIV(c,div) \
115         do {    DIVSCALAR( (c).r , div);  \
116                 DIVSCALAR( (c).i  , div); }while (0)
117
118 #define  C_ADD( res, a,b)\
119     do {(res).r=ADD32((a).r,(b).r);  (res).i=ADD32((a).i,(b).i); \
120     }while(0)
121 #define  C_SUB( res, a,b)\
122     do {(res).r=SUB32((a).r,(b).r);  (res).i=SUB32((a).i,(b).i); \
123     }while(0)
124 #define C_ADDTO( res , a)\
125     do {(res).r = ADD32((res).r, (a).r);  (res).i = ADD32((res).i,(a).i);\
126     }while(0)
127
128 #define C_SUBFROM( res , a)\
129     do {(res).r = ADD32((res).r,(a).r);  (res).i = SUB32((res).i,(a).i); \
130     }while(0)
131
132 #else /* MIXED_PRECISION */
133 #   define sround4( x )  (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> (FRACBITS+2) )
134
135 #   define S_MUL(a,b) sround( smul(a,b) )
136
137 #   define C_MUL(m,a,b) \
138       do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
139           (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
140 #   define C_MULC(m,a,b) \
141       do{ (m).r = sround( smul((a).r,(b).r) + smul((a).i,(b).i) ); \
142           (m).i = sround( smul((a).i,(b).r) - smul((a).r,(b).i) ); }while(0)
143
144 #   define C_MUL4(m,a,b) \
145                do{ (m).r = sround4( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
146                (m).i = sround4( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
147
148 #   define C_MULBYSCALAR( c, s ) \
149                do{ (c).r =  sround( smul( (c).r , s ) ) ;\
150                (c).i =  sround( smul( (c).i , s ) ) ; }while(0)
151
152 #   define DIVSCALAR(x,k) \
153         (x) = sround( smul(  x, SAMP_MAX/k ) )
154
155 #   define C_FIXDIV(c,div) \
156         do {    DIVSCALAR( (c).r , div);  \
157                 DIVSCALAR( (c).i  , div); }while (0)
158
159 #endif /* !MIXED_PRECISION */
160
161
162
163 #else  /* not FIXED_POINT*/
164
165 #define EXT32(a) (a)
166
167 #   define S_MUL(a,b) ( (a)*(b) )
168 #define C_MUL(m,a,b) \
169     do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
170         (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
171 #define C_MULC(m,a,b) \
172     do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
173         (m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
174
175 #define C_MUL4(m,a,b) C_MUL(m,a,b)
176
177 #   define C_FIXDIV(c,div) /* NOOP */
178 #   define C_MULBYSCALAR( c, s ) \
179     do{ (c).r *= (s);\
180         (c).i *= (s); }while(0)
181 #endif
182
183
184
185 #ifndef CHECK_OVERFLOW_OP
186 #  define CHECK_OVERFLOW_OP(a,op,b) /* noop */
187 #endif
188
189 #ifndef C_ADD
190 #define  C_ADD( res, a,b)\
191     do { \
192             CHECK_OVERFLOW_OP((a).r,+,(b).r)\
193             CHECK_OVERFLOW_OP((a).i,+,(b).i)\
194             (res).r=(a).r+(b).r;  (res).i=(a).i+(b).i; \
195     }while(0)
196 #define  C_SUB( res, a,b)\
197     do { \
198             CHECK_OVERFLOW_OP((a).r,-,(b).r)\
199             CHECK_OVERFLOW_OP((a).i,-,(b).i)\
200             (res).r=(a).r-(b).r;  (res).i=(a).i-(b).i; \
201     }while(0)
202 #define C_ADDTO( res , a)\
203     do { \
204             CHECK_OVERFLOW_OP((res).r,+,(a).r)\
205             CHECK_OVERFLOW_OP((res).i,+,(a).i)\
206             (res).r += (a).r;  (res).i += (a).i;\
207     }while(0)
208
209 #define C_SUBFROM( res , a)\
210     do {\
211             CHECK_OVERFLOW_OP((res).r,-,(a).r)\
212             CHECK_OVERFLOW_OP((res).i,-,(a).i)\
213             (res).r -= (a).r;  (res).i -= (a).i; \
214     }while(0)
215 #endif /* C_ADD defined */
216
217 #ifdef FIXED_POINT
218 /*#  define KISS_FFT_COS(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
219 #  define KISS_FFT_SIN(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
220 #  define KISS_FFT_COS(phase)  floor(.5+TWID_MAX*cos (phase))
221 #  define KISS_FFT_SIN(phase)  floor(.5+TWID_MAX*sin (phase))
222 #  define HALF_OF(x) ((x)>>1)
223 #elif defined(USE_SIMD)
224 #  define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
225 #  define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
226 #  define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
227 #else
228 #  define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
229 #  define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
230 #  define HALF_OF(x) ((x)*.5f)
231 #endif
232
233 #define  kf_cexp(x,phase) \
234         do{ \
235                 (x)->r = KISS_FFT_COS(phase);\
236                 (x)->i = KISS_FFT_SIN(phase);\
237         }while(0)
238    
239 #define  kf_cexp2(x,phase) \
240    do{ \
241       (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
242       (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
243 }while(0)
244
245
246 #endif /* KISS_FFT_GUTS_H */