ooura_fft 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,307 @@
1
+ /*******************************************************************************
2
+ Fast Fourier/Cosine/Sine Transform
3
+ dimension :one
4
+ data length :power of 2
5
+ decimation :frequency
6
+ radix :split-radix
7
+ data :inplace
8
+ table :use
9
+ functions
10
+ cdft: Complex Discrete Fourier Transform
11
+ rdft: Real Discrete Fourier Transform
12
+ ddct: Discrete Cosine Transform
13
+ ddst: Discrete Sine Transform
14
+ dfct: Cosine Transform of RDFT (Real Symmetric DFT)
15
+ dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
16
+ function prototypes
17
+ void cdft(int, int, double *, int *, double *);
18
+ void rdft(int, int, double *, int *, double *);
19
+ void ddct(int, int, double *, int *, double *);
20
+ void ddst(int, int, double *, int *, double *);
21
+ void dfct(int, double *, double *, int *, double *);
22
+ void dfst(int, double *, double *, int *, double *);
23
+ macro definitions
24
+ USE_CDFT_PTHREADS : default=not defined
25
+ CDFT_THREADS_BEGIN_N : must be >= 512, default=8192
26
+ CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536
27
+ USE_CDFT_WINTHREADS : default=not defined
28
+ CDFT_THREADS_BEGIN_N : must be >= 512, default=32768
29
+ CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288
30
+ *******************************************************************************/
31
+ #ifndef OOURA_FFTSG_H
32
+ #define OOURA_FFTSG_H
33
+
34
+ #if defined(__cplusplus)
35
+ extern "C" {
36
+ #endif
37
+
38
+ /*
39
+ -------- Complex DFT (Discrete Fourier Transform) --------
40
+ [definition]
41
+ <case1>
42
+ X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n
43
+ <case2>
44
+ X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n
45
+ (notes: sum_j=0^n-1 is a summation from j=0 to n-1)
46
+ [usage]
47
+ <case1>
48
+ ip[0] = 0; // first time only
49
+ cdft(2*n, 1, a, ip, w);
50
+ <case2>
51
+ ip[0] = 0; // first time only
52
+ cdft(2*n, -1, a, ip, w);
53
+ [parameters]
54
+ 2*n :data length (int)
55
+ n >= 1, n = power of 2
56
+ a[0...2*n-1] :input/output data (double *)
57
+ input data
58
+ a[2*j] = Re(x[j]),
59
+ a[2*j+1] = Im(x[j]), 0<=j<n
60
+ output data
61
+ a[2*k] = Re(X[k]),
62
+ a[2*k+1] = Im(X[k]), 0<=k<n
63
+ ip[0...*] :work area for bit reversal (int *)
64
+ length of ip >= 2+sqrt(n)
65
+ strictly,
66
+ length of ip >=
67
+ 2+(1<<(int)(log(n+0.5)/log(2))/2).
68
+ ip[0],ip[1] are pointers of the cos/sin table.
69
+ w[0...n/2-1] :cos/sin table (double *)
70
+ w[],ip[] are initialized if ip[0] == 0.
71
+ [remark]
72
+ Inverse of
73
+ cdft(2*n, -1, a, ip, w);
74
+ is
75
+ cdft(2*n, 1, a, ip, w);
76
+ for (j = 0; j <= 2 * n - 1; j++) {
77
+ a[j] *= 1.0 / n;
78
+ }
79
+ .
80
+ */
81
+ extern void cdft(int n, int isgn, double *a, int *ip, double *w);
82
+
83
+ /*
84
+ -------- Real DFT / Inverse of Real DFT --------
85
+ [definition]
86
+ <case1> RDFT
87
+ R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2
88
+ I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2
89
+ <case2> IRDFT (excluding scale)
90
+ a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
91
+ sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
92
+ sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
93
+ [usage]
94
+ <case1>
95
+ ip[0] = 0; // first time only
96
+ rdft(n, 1, a, ip, w);
97
+ <case2>
98
+ ip[0] = 0; // first time only
99
+ rdft(n, -1, a, ip, w);
100
+ [parameters]
101
+ n :data length (int)
102
+ n >= 2, n = power of 2
103
+ a[0...n-1] :input/output data (double *)
104
+ <case1>
105
+ output data
106
+ a[2*k] = R[k], 0<=k<n/2
107
+ a[2*k+1] = I[k], 0<k<n/2
108
+ a[1] = R[n/2]
109
+ <case2>
110
+ input data
111
+ a[2*j] = R[j], 0<=j<n/2
112
+ a[2*j+1] = I[j], 0<j<n/2
113
+ a[1] = R[n/2]
114
+ ip[0...*] :work area for bit reversal (int *)
115
+ length of ip >= 2+sqrt(n/2)
116
+ strictly,
117
+ length of ip >=
118
+ 2+(1<<(int)(log(n/2+0.5)/log(2))/2).
119
+ ip[0],ip[1] are pointers of the cos/sin table.
120
+ w[0...n/2-1] :cos/sin table (double *)
121
+ w[],ip[] are initialized if ip[0] == 0.
122
+ [remark]
123
+ Inverse of
124
+ rdft(n, 1, a, ip, w);
125
+ is
126
+ rdft(n, -1, a, ip, w);
127
+ for (j = 0; j <= n - 1; j++) {
128
+ a[j] *= 2.0 / n;
129
+ }
130
+ .
131
+ */
132
+ extern void rdft(int n, int isgn, double *a, int *ip, double *w);
133
+
134
+ /*
135
+ -------- DCT (Discrete Cosine Transform) / Inverse of DCT --------
136
+ [definition]
137
+ <case1> IDCT (excluding scale)
138
+ C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n
139
+ <case2> DCT
140
+ C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n
141
+ [usage]
142
+ <case1>
143
+ ip[0] = 0; // first time only
144
+ ddct(n, 1, a, ip, w);
145
+ <case2>
146
+ ip[0] = 0; // first time only
147
+ ddct(n, -1, a, ip, w);
148
+ [parameters]
149
+ n :data length (int)
150
+ n >= 2, n = power of 2
151
+ a[0...n-1] :input/output data (double *)
152
+ output data
153
+ a[k] = C[k], 0<=k<n
154
+ ip[0...*] :work area for bit reversal (int *)
155
+ length of ip >= 2+sqrt(n/2)
156
+ strictly,
157
+ length of ip >=
158
+ 2+(1<<(int)(log(n/2+0.5)/log(2))/2).
159
+ ip[0],ip[1] are pointers of the cos/sin table.
160
+ w[0...n*5/4-1] :cos/sin table (double *)
161
+ w[],ip[] are initialized if ip[0] == 0.
162
+ [remark]
163
+ Inverse of
164
+ ddct(n, -1, a, ip, w);
165
+ is
166
+ a[0] *= 0.5;
167
+ ddct(n, 1, a, ip, w);
168
+ for (j = 0; j <= n - 1; j++) {
169
+ a[j] *= 2.0 / n;
170
+ }
171
+ .
172
+ */
173
+ extern void ddct(int n, int isgn, double *a, int *ip, double *w);
174
+
175
+ /*
176
+ -------- DST (Discrete Sine Transform) / Inverse of DST --------
177
+ [definition]
178
+ <case1> IDST (excluding scale)
179
+ S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n
180
+ <case2> DST
181
+ S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n
182
+ [usage]
183
+ <case1>
184
+ ip[0] = 0; // first time only
185
+ ddst(n, 1, a, ip, w);
186
+ <case2>
187
+ ip[0] = 0; // first time only
188
+ ddst(n, -1, a, ip, w);
189
+ [parameters]
190
+ n :data length (int)
191
+ n >= 2, n = power of 2
192
+ a[0...n-1] :input/output data (double *)
193
+ <case1>
194
+ input data
195
+ a[j] = A[j], 0<j<n
196
+ a[0] = A[n]
197
+ output data
198
+ a[k] = S[k], 0<=k<n
199
+ <case2>
200
+ output data
201
+ a[k] = S[k], 0<k<n
202
+ a[0] = S[n]
203
+ ip[0...*] :work area for bit reversal (int *)
204
+ length of ip >= 2+sqrt(n/2)
205
+ strictly,
206
+ length of ip >=
207
+ 2+(1<<(int)(log(n/2+0.5)/log(2))/2).
208
+ ip[0],ip[1] are pointers of the cos/sin table.
209
+ w[0...n*5/4-1] :cos/sin table (double *)
210
+ w[],ip[] are initialized if ip[0] == 0.
211
+ [remark]
212
+ Inverse of
213
+ ddst(n, -1, a, ip, w);
214
+ is
215
+ a[0] *= 0.5;
216
+ ddst(n, 1, a, ip, w);
217
+ for (j = 0; j <= n - 1; j++) {
218
+ a[j] *= 2.0 / n;
219
+ }
220
+ .
221
+ */
222
+ extern void ddst(int n, int isgn, double *a, int *ip, double *w);
223
+
224
+ /*
225
+ -------- Cosine Transform of RDFT (Real Symmetric DFT) --------
226
+ [definition]
227
+ C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
228
+ [usage]
229
+ ip[0] = 0; // first time only
230
+ dfct(n, a, t, ip, w);
231
+ [parameters]
232
+ n :data length - 1 (int)
233
+ n >= 2, n = power of 2
234
+ a[0...n] :input/output data (double *)
235
+ output data
236
+ a[k] = C[k], 0<=k<=n
237
+ t[0...n/2] :work area (double *)
238
+ ip[0...*] :work area for bit reversal (int *)
239
+ length of ip >= 2+sqrt(n/4)
240
+ strictly,
241
+ length of ip >=
242
+ 2+(1<<(int)(log(n/4+0.5)/log(2))/2).
243
+ ip[0],ip[1] are pointers of the cos/sin table.
244
+ w[0...n*5/8-1] :cos/sin table (double *)
245
+ w[],ip[] are initialized if ip[0] == 0.
246
+ [remark]
247
+ Inverse of
248
+ a[0] *= 0.5;
249
+ a[n] *= 0.5;
250
+ dfct(n, a, t, ip, w);
251
+ is
252
+ a[0] *= 0.5;
253
+ a[n] *= 0.5;
254
+ dfct(n, a, t, ip, w);
255
+ for (j = 0; j <= n; j++) {
256
+ a[j] *= 2.0 / n;
257
+ }
258
+ .
259
+ */
260
+ extern void dfct(int n, double *a, double *t, int *ip, double *w);
261
+
262
+ /*
263
+ -------- Sine Transform of RDFT (Real Anti-symmetric DFT) --------
264
+ [definition]
265
+ S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
266
+ [usage]
267
+ ip[0] = 0; // first time only
268
+ dfst(n, a, t, ip, w);
269
+ [parameters]
270
+ n :data length + 1 (int)
271
+ n >= 2, n = power of 2
272
+ a[0...n-1] :input/output data (double *)
273
+ output data
274
+ a[k] = S[k], 0<k<n
275
+ (a[0] is used for work area)
276
+ t[0...n/2-1] :work area (double *)
277
+ ip[0...*] :work area for bit reversal (int *)
278
+ length of ip >= 2+sqrt(n/4)
279
+ strictly,
280
+ length of ip >=
281
+ 2+(1<<(int)(log(n/4+0.5)/log(2))/2).
282
+ ip[0],ip[1] are pointers of the cos/sin table.
283
+ w[0...n*5/8-1] :cos/sin table (double *)
284
+ w[],ip[] are initialized if ip[0] == 0.
285
+ [remark]
286
+ Inverse of
287
+ dfst(n, a, t, ip, w);
288
+ is
289
+ dfst(n, a, t, ip, w);
290
+ for (j = 1; j <= n - 1; j++) {
291
+ a[j] *= 2.0 / n;
292
+ }
293
+ .
294
+ */
295
+ extern void dfst(int n, double *a, double *t, int *ip, double *w);
296
+
297
+ /*
298
+ Appendix :
299
+ The cos/sin table is recalculated when the larger table required.
300
+ w[] and ip[] are compatible with all routines.
301
+ */
302
+
303
+ #if defined(__cplusplus)
304
+ }
305
+ #endif
306
+
307
+ #endif /* OOURA_FFTSG_H */
@@ -0,0 +1,167 @@
1
+ General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
2
+
3
+ Description:
4
+ A package to calculate Discrete Fourier/Cosine/Sine Transforms of
5
+ 1-dimensional sequences of length 2^N.
6
+
7
+ Files:
8
+ fft4g.c : FFT Package in C - Fast Version I (radix 4,2)
9
+ fft4g.f : FFT Package in Fortran - Fast Version I (radix 4,2)
10
+ fft4g_h.c : FFT Package in C - Simple Version I (radix 4,2)
11
+ fft8g.c : FFT Package in C - Fast Version II (radix 8,4,2)
12
+ fft8g.f : FFT Package in Fortran - Fast Version II (radix 8,4,2)
13
+ fft8g_h.c : FFT Package in C - Simple Version II (radix 8,4,2)
14
+ fftsg.c : FFT Package in C - Fast Version III (Split-Radix)
15
+ fftsg.f : FFT Package in Fortran - Fast Version III (Split-Radix)
16
+ fftsg_h.c : FFT Package in C - Simple Version III (Split-Radix)
17
+ readme.txt : Readme File
18
+ sample1/ : Test Directory
19
+ Makefile : for gcc, cc
20
+ Makefile.f77: for Fortran
21
+ testxg.c : Test Program for "fft*g.c"
22
+ testxg.f : Test Program for "fft*g.f"
23
+ testxg_h.c : Test Program for "fft*g_h.c"
24
+ sample2/ : Benchmark Directory
25
+ Makefile : for gcc, cc
26
+ Makefile.pth: POSIX Thread version
27
+ pi_fft.c : PI(= 3.1415926535897932384626...) Calculation Program
28
+ for a Benchmark Test for "fft*g.c"
29
+
30
+ Difference of the Files:
31
+ C and Fortran versions are equal and
32
+ the same routines are in each version.
33
+ "fft4g*.*" are optimized for most machines.
34
+ "fft8g*.*" are fast on the UltraSPARC.
35
+ "fftsg*.*" are optimized for the machines that
36
+ have the multi-level (L1,L2,etc) cache.
37
+ The simple versions "fft*g_h.c" use no work area, but
38
+ the fast versions "fft*g.*" use work areas.
39
+ The fast versions "fft*g.*" have the same specification.
40
+
41
+ Routines in the Package:
42
+ cdft: Complex Discrete Fourier Transform
43
+ rdft: Real Discrete Fourier Transform
44
+ ddct: Discrete Cosine Transform
45
+ ddst: Discrete Sine Transform
46
+ dfct: Cosine Transform of RDFT (Real Symmetric DFT)
47
+ dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
48
+
49
+ Usage:
50
+ Please refer to the comments in the "fft**.*" file which
51
+ you want to use. Brief explanations are in the block
52
+ comments of each package. The examples are also given in
53
+ the test programs.
54
+
55
+ Method:
56
+ -------- cdft --------
57
+ fft4g*.*, fft8g*.*:
58
+ A method of in-place, radix 2^M, Sande-Tukey (decimation in
59
+ frequency). Index of the butterfly loop is in bit
60
+ reverse order to keep continuous memory access.
61
+ fftsg*.*:
62
+ A method of in-place, Split-Radix, recursive fast
63
+ algorithm.
64
+ -------- rdft --------
65
+ A method with a following butterfly operation appended to "cdft".
66
+ In forward transform :
67
+ A[k] = sum_j=0^n-1 a[j]*W(n)^(j*k), 0<=k<=n/2,
68
+ W(n) = exp(2*pi*i/n),
69
+ this routine makes an array x[] :
70
+ x[j] = a[2*j] + i*a[2*j+1], 0<=j<n/2
71
+ and calls "cdft" of length n/2 :
72
+ X[k] = sum_j=0^n/2-1 x[j] * W(n/2)^(j*k), 0<=k<n.
73
+ The result A[k] are :
74
+ A[k] = X[k] - (1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k])),
75
+ A[n/2-k] = X[n/2-k] +
76
+ conjg((1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k]))),
77
+ 0<=k<=n/2
78
+ (notes: conjg() is a complex conjugate, X[n/2]=X[0]).
79
+ -------- ddct --------
80
+ A method with a following butterfly operation appended to "rdft".
81
+ In backward transform :
82
+ C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n,
83
+ this routine makes an array r[] :
84
+ r[0] = a[0],
85
+ r[j] = Re((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
86
+ r[n-j] = Im((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
87
+ 0<j<=n/2
88
+ and calls "rdft" of length n :
89
+ A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
90
+ W(n) = exp(2*pi*i/n).
91
+ The result C[k] are :
92
+ C[2*k] = Re(A[k] * (1-i)),
93
+ C[2*k-1] = -Im(A[k] * (1-i)).
94
+ -------- ddst --------
95
+ A method with a following butterfly operation appended to "rdft".
96
+ In backward transform :
97
+ S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n,
98
+ this routine makes an array r[] :
99
+ r[0] = a[0],
100
+ r[j] = Im((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
101
+ r[n-j] = Re((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
102
+ 0<j<=n/2
103
+ and calls "rdft" of length n :
104
+ A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
105
+ W(n) = exp(2*pi*i/n).
106
+ The result S[k] are :
107
+ S[2*k] = Re(A[k] * (1+i)),
108
+ S[2*k-1] = -Im(A[k] * (1+i)).
109
+ -------- dfct --------
110
+ A method to split into "dfct" and "ddct" of half length.
111
+ The transform :
112
+ C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
113
+ is divided into :
114
+ C[2*k] = sum'_j=0^n/2 (a[j]+a[n-j])*cos(pi*j*k/(n/2)),
115
+ C[2*k+1] = sum_j=0^n/2-1 (a[j]-a[n-j])*cos(pi*j*(k+1/2)/(n/2))
116
+ (sum' is a summation whose last term multiplies 1/2).
117
+ This routine uses "ddct" recursively.
118
+ To keep the in-place operation, the data in fft*g_h.*
119
+ are sorted in bit reversal order.
120
+ -------- dfst --------
121
+ A method to split into "dfst" and "ddst" of half length.
122
+ The transform :
123
+ S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
124
+ is divided into :
125
+ S[2*k] = sum_j=1^n/2-1 (a[j]-a[n-j])*sin(pi*j*k/(n/2)),
126
+ S[2*k+1] = sum'_j=1^n/2 (a[j]+a[n-j])*sin(pi*j*(k+1/2)/(n/2))
127
+ (sum' is a summation whose last term multiplies 1/2).
128
+ This routine uses "ddst" recursively.
129
+ To keep the in-place operation, the data in fft*g_h.*
130
+ are sorted in bit reversal order.
131
+
132
+ Reference:
133
+ * Masatake MORI, Makoto NATORI, Tatuo TORII: Suchikeisan,
134
+ Iwanamikouzajyouhoukagaku18, Iwanami, 1982 (Japanese)
135
+ * Henri J. Nussbaumer: Fast Fourier Transform and Convolution
136
+ Algorithms, Springer Verlag, 1982
137
+ * C. S. Burrus, Notes on the FFT (with large FFT paper list)
138
+ http://www-dsp.rice.edu/research/fft/fftnote.asc
139
+
140
+ Copyright:
141
+ Copyright(C) 1996-2001 Takuya OOURA
142
+ email: ooura@mmm.t.u-tokyo.ac.jp
143
+ download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
144
+ You may use, copy, modify this code for any purpose and
145
+ without fee. You may distribute this ORIGINAL package.
146
+
147
+ History:
148
+ ...
149
+ Dec. 1995 : Edit the General Purpose FFT
150
+ Mar. 1996 : Change the specification
151
+ Jun. 1996 : Change the method of trigonometric function table
152
+ Sep. 1996 : Modify the documents
153
+ Feb. 1997 : Change the butterfly loops
154
+ Dec. 1997 : Modify the documents
155
+ Dec. 1997 : Add "fft4g.*"
156
+ Jul. 1998 : Fix some bugs in the documents
157
+ Jul. 1998 : Add "fft8g.*" and delete "fft4f.*"
158
+ Jul. 1998 : Add a benchmark program "pi_fft.c"
159
+ Jul. 1999 : Add a simple version "fft*g_h.c"
160
+ Jul. 1999 : Add a Split-Radix FFT package "fftsg*.c"
161
+ Sep. 1999 : Reduce the memory operation (minor optimization)
162
+ Oct. 1999 : Change the butterfly structure of "fftsg*.c"
163
+ Oct. 1999 : Save the code size
164
+ Sep. 2001 : Add "fftsg.f"
165
+ Sep. 2001 : Add Pthread & Win32thread routines to "fftsg*.c"
166
+ Dec. 2006 : Fix a minor bug in "fftsg.f"
167
+
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'mkmf'
3
+
4
+ have_header('windows.h')
5
+ have_header('pthread.h')
6
+
7
+ have_func('pthread_create', 'pthread.h')
8
+ have_func('pthread_join', 'pthread.h')
9
+ have_func('CreateThread', 'windows.h')
10
+ have_func('WaitForSingleObject', 'windows.h')
11
+ have_func('CloseHandle', 'windows.h')
12
+
13
+ have_header('stdbit.h')
14
+ have_func('ispow2l', 'stdbit.h')
15
+
16
+ $INSTALLFILES = Dir.glob(%w[ooura_fft/*.h]).map{|x| [x,'$(archdir)'] }
17
+
18
+ create_makefile('ooura_fft/ooura_fft')