DOUBLE_PRECISION and MIXED_PRECISION no longer need to be defined
[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 #define DOUBLE_PRECISION
57
58 #ifdef DOUBLE_PRECISION
59
60 # define FRACBITS 31
61 # define SAMPPROD long long
62 #define SAMP_MAX 2147483647
63 #define TWID_MAX 32767
64 #define TRIG_UPSCALE 1
65 #define EXT32(a) (a)
66
67 #else /* DOUBLE_PRECISION */
68
69 # define FRACBITS 15
70 # define SAMPPROD celt_int32 
71 #define SAMP_MAX 32767
72 #define TRIG_UPSCALE 1
73 #define EXT32(a) EXTEND32(a)
74
75 #endif /* !DOUBLE_PRECISION */
76
77 #define SAMP_MIN -SAMP_MAX
78
79 #if defined(CHECK_OVERFLOW)
80 #  define CHECK_OVERFLOW_OP(a,op,b)  \
81         if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
82                 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) );  }
83 #endif
84
85 #   define smul(a,b) ( (SAMPPROD)(a)*(b) )
86 #   define sround( x )  (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> FRACBITS )
87
88
89 #   define S_MUL(a,b) MULT16_32_Q15(b, a)
90
91 #   define C_MUL(m,a,b) \
92       do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
93           (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
94
95 #   define C_MULC(m,a,b) \
96       do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
97           (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
98
99 #   define C_MUL4(m,a,b) \
100       do{ (m).r = SHR(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \
101           (m).i = SHR(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }while(0)
102
103 #   define C_MULBYSCALAR( c, s ) \
104       do{ (c).r =  S_MUL( (c).r , s ) ;\
105           (c).i =  S_MUL( (c).i , s ) ; }while(0)
106
107 #   define DIVSCALAR(x,k) \
108         (x) = S_MUL(  x, (TWID_MAX-((k)>>1))/(k)+1 )
109
110 #   define C_FIXDIV(c,div) \
111         do {    DIVSCALAR( (c).r , div);  \
112                 DIVSCALAR( (c).i  , div); }while (0)
113
114 #define  C_ADD( res, a,b)\
115     do {(res).r=ADD32((a).r,(b).r);  (res).i=ADD32((a).i,(b).i); \
116     }while(0)
117 #define  C_SUB( res, a,b)\
118     do {(res).r=SUB32((a).r,(b).r);  (res).i=SUB32((a).i,(b).i); \
119     }while(0)
120 #define C_ADDTO( res , a)\
121     do {(res).r = ADD32((res).r, (a).r);  (res).i = ADD32((res).i,(a).i);\
122     }while(0)
123
124 #define C_SUBFROM( res , a)\
125     do {(res).r = ADD32((res).r,(a).r);  (res).i = SUB32((res).i,(a).i); \
126     }while(0)
127
128
129
130
131 #else  /* not FIXED_POINT*/
132
133 #define EXT32(a) (a)
134
135 #   define S_MUL(a,b) ( (a)*(b) )
136 #define C_MUL(m,a,b) \
137     do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
138         (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
139 #define C_MULC(m,a,b) \
140     do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
141         (m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
142
143 #define C_MUL4(m,a,b) C_MUL(m,a,b)
144
145 #   define C_FIXDIV(c,div) /* NOOP */
146 #   define C_MULBYSCALAR( c, s ) \
147     do{ (c).r *= (s);\
148         (c).i *= (s); }while(0)
149 #endif
150
151
152
153 #ifndef CHECK_OVERFLOW_OP
154 #  define CHECK_OVERFLOW_OP(a,op,b) /* noop */
155 #endif
156
157 #ifndef C_ADD
158 #define  C_ADD( res, a,b)\
159     do { \
160             CHECK_OVERFLOW_OP((a).r,+,(b).r)\
161             CHECK_OVERFLOW_OP((a).i,+,(b).i)\
162             (res).r=(a).r+(b).r;  (res).i=(a).i+(b).i; \
163     }while(0)
164 #define  C_SUB( res, a,b)\
165     do { \
166             CHECK_OVERFLOW_OP((a).r,-,(b).r)\
167             CHECK_OVERFLOW_OP((a).i,-,(b).i)\
168             (res).r=(a).r-(b).r;  (res).i=(a).i-(b).i; \
169     }while(0)
170 #define C_ADDTO( res , a)\
171     do { \
172             CHECK_OVERFLOW_OP((res).r,+,(a).r)\
173             CHECK_OVERFLOW_OP((res).i,+,(a).i)\
174             (res).r += (a).r;  (res).i += (a).i;\
175     }while(0)
176
177 #define C_SUBFROM( res , a)\
178     do {\
179             CHECK_OVERFLOW_OP((res).r,-,(a).r)\
180             CHECK_OVERFLOW_OP((res).i,-,(a).i)\
181             (res).r -= (a).r;  (res).i -= (a).i; \
182     }while(0)
183 #endif /* C_ADD defined */
184
185 #ifdef FIXED_POINT
186 /*#  define KISS_FFT_COS(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
187 #  define KISS_FFT_SIN(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
188 #  define KISS_FFT_COS(phase)  floor(.5+TWID_MAX*cos (phase))
189 #  define KISS_FFT_SIN(phase)  floor(.5+TWID_MAX*sin (phase))
190 #  define HALF_OF(x) ((x)>>1)
191 #elif defined(USE_SIMD)
192 #  define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
193 #  define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
194 #  define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
195 #else
196 #  define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
197 #  define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
198 #  define HALF_OF(x) ((x)*.5f)
199 #endif
200
201 #define  kf_cexp(x,phase) \
202         do{ \
203                 (x)->r = KISS_FFT_COS(phase);\
204                 (x)->i = KISS_FFT_SIN(phase);\
205         }while(0)
206    
207 #define  kf_cexp2(x,phase) \
208    do{ \
209       (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
210       (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
211 }while(0)
212
213
214 #endif /* KISS_FFT_GUTS_H */