ooura_fft 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +17 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +82 -0
- data/Rakefile +19 -0
- data/ext/ooura_fft/abi/fftsg/fftsg.c +3528 -0
- data/ext/ooura_fft/abi/fftsg/fftsg.h +307 -0
- data/ext/ooura_fft/abi/fftsg/readme.txt +167 -0
- data/ext/ooura_fft/extconf.rb +18 -0
- data/ext/ooura_fft/fft.c +307 -0
- data/ext/ooura_fft/internal/setting/ooura_fft.h +17 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/cdft.h +52 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/ddct.h +47 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/ddst.h +47 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/dfct.h +55 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/dfst.h +52 -0
- data/ext/ooura_fft/internal/solver/ooura_fft/rdft.h +47 -0
- data/ext/ooura_fft/missing/ispow2l.c +9 -0
- data/ext/ooura_fft/missing/missing.h +21 -0
- data/ext/ooura_fft/ooura_fft/api.h +13 -0
- data/ext/ooura_fft/ooura_fft/ext_extern.h +18 -0
- data/ext/ooura_fft/ooura_fft/globals.h +9 -0
- data/ext/ooura_fft/ooura_fft.c +56 -0
- data/lib/ooura_fft/version.rb +6 -0
- data/lib/ooura_fft.rb +6 -0
- data/sig/ooura_fft.rbs +4 -0
- metadata +116 -0
data/ext/ooura_fft/fft.c
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
/*******************************************************************************
|
2
|
+
fft.c -- FFT
|
3
|
+
|
4
|
+
$author$
|
5
|
+
*******************************************************************************/
|
6
|
+
#include <ruby.h>
|
7
|
+
#include "ooura_fft/globals.h"
|
8
|
+
#include "ooura_fft/api.h"
|
9
|
+
#include "internal/setting/ooura_fft.h"
|
10
|
+
#include "missing/missing.h"
|
11
|
+
#include "abi/fftsg/fftsg.h"
|
12
|
+
|
13
|
+
|
14
|
+
static void InitVM_FFTMain(void);
|
15
|
+
void
|
16
|
+
InitVM_FFT(void)
|
17
|
+
{
|
18
|
+
InitVM(FFTMain);
|
19
|
+
}
|
20
|
+
|
21
|
+
int
|
22
|
+
opts_inversion_p(VALUE opts)
|
23
|
+
{
|
24
|
+
static ID kwds[1];
|
25
|
+
VALUE inversion;
|
26
|
+
if (!kwds[0]) {
|
27
|
+
kwds[0] = rb_intern_const("inversion");
|
28
|
+
}
|
29
|
+
rb_get_kwargs(opts, kwds, 0, 1, &inversion);
|
30
|
+
switch (inversion) {
|
31
|
+
case Qtrue: case Qfalse:
|
32
|
+
break;
|
33
|
+
case Qundef:
|
34
|
+
return 0;
|
35
|
+
default:
|
36
|
+
rb_raise(rb_eArgError, "true or false is expected as inversion: %+"PRIsVALUE,
|
37
|
+
inversion);
|
38
|
+
}
|
39
|
+
|
40
|
+
return inversion == Qtrue;
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE
|
44
|
+
fft_callback(int argc, VALUE *argv, VALUE (*callback_func)(VALUE, int))
|
45
|
+
{
|
46
|
+
VALUE ary, opts = Qnil;
|
47
|
+
rb_scan_args(argc, argv, "11", &ary, &opts);
|
48
|
+
int invertible = opts_inversion_p(opts) ? -1 : 1;
|
49
|
+
|
50
|
+
Check_Type(ary, T_ARRAY);
|
51
|
+
|
52
|
+
return callback_func(ary, invertible);
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
#include "internal/solver/ooura_fft/cdft.h" // fft_cdft_inline()
|
57
|
+
/*
|
58
|
+
*
|
59
|
+
* Document-method: cdft
|
60
|
+
*
|
61
|
+
* call-seq:
|
62
|
+
* OouraFFT.cdft(ary) -> [*Complex]
|
63
|
+
* OouraFFT.cdft(ary, inversion: true) -> [*Complex]
|
64
|
+
*
|
65
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
66
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
67
|
+
*
|
68
|
+
* [Function type] Complex Discrete Fourier Transform
|
69
|
+
* [Definition]
|
70
|
+
* [case1] <tt>X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n</tt>
|
71
|
+
* [case2] <tt>X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n</tt>
|
72
|
+
* notes:: <tt>sum_j=0^n-1 is a summation from j=0 to n-1</tt>
|
73
|
+
* [+ary+ sequence type] All +Complex+
|
74
|
+
* [Array size requirement] n >= 1, n = power of 2
|
75
|
+
*
|
76
|
+
* def sinewave(amp, f0, fs, n)
|
77
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
78
|
+
* end
|
79
|
+
*
|
80
|
+
* OouraFFT.cdft(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
81
|
+
* #=> [(1.1441462984511075+0.0i),
|
82
|
+
* #=> (-0.21410561232180816-0.3229641637954819i),
|
83
|
+
* #=> (-0.14986404592245728-0.12744889477603982i),
|
84
|
+
* #=> (-0.13944777827146557-0.05236611372238342i),
|
85
|
+
* #=> (-0.13731142541964547+0.0i),
|
86
|
+
* #=> (-0.13944777827146557+0.05236611372238342i),
|
87
|
+
* #=> (-0.14986404592245728+0.12744889477603982i),
|
88
|
+
* #=> (-0.21410561232180816+0.3229641637954819i)]
|
89
|
+
*/
|
90
|
+
static VALUE
|
91
|
+
fft_cdft(int argc, VALUE *argv, VALUE unused_obj)
|
92
|
+
{
|
93
|
+
return fft_callback(argc, argv, fft_cdft_inline);
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
#include "internal/solver/ooura_fft/rdft.h" // fft_rdft_inline()
|
98
|
+
/*
|
99
|
+
* Document-method: rdft
|
100
|
+
*
|
101
|
+
* call-seq:
|
102
|
+
* OouraFFT.rdft(ary) -> [*Float]
|
103
|
+
* OouraFFT.rdft(ary, inversion: true) -> [*Float]
|
104
|
+
*
|
105
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
106
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
107
|
+
*
|
108
|
+
* [Function type] Real Discrete Fourier Transform
|
109
|
+
* [Definition]
|
110
|
+
* case1:: RDFT
|
111
|
+
* :: <tt>R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2</tt>
|
112
|
+
* :: <tt>I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2</tt>
|
113
|
+
* case2:: IRDFT (excluding scale)
|
114
|
+
* :: <tt>a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n</tt>
|
115
|
+
* [+ary+ sequence type] All +Float+
|
116
|
+
* [Array size requirement] n >= 2, n = power of 2
|
117
|
+
*
|
118
|
+
* def sinewave(amp, f0, fs, n)
|
119
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
120
|
+
* end
|
121
|
+
*
|
122
|
+
* OouraFFT.rdft(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
123
|
+
* # => [1.1441462984511075,
|
124
|
+
* # => -0.13731142541964547,
|
125
|
+
* # => -0.21410561232180816,
|
126
|
+
* # => -0.3229641637954819,
|
127
|
+
* # => -0.14986404592245728,
|
128
|
+
* # => -0.12744889477603982,
|
129
|
+
* # => -0.13944777827146557,
|
130
|
+
* # => -0.052366113722383416]
|
131
|
+
*/
|
132
|
+
static VALUE
|
133
|
+
fft_rdft(int argc, VALUE *argv, VALUE unused_obj)
|
134
|
+
{
|
135
|
+
return fft_callback(argc, argv, fft_rdft_inline);
|
136
|
+
}
|
137
|
+
|
138
|
+
|
139
|
+
#include "internal/solver/ooura_fft/ddct.h" // fft_ddct_inline()
|
140
|
+
/*
|
141
|
+
* Document-method: ddct
|
142
|
+
*
|
143
|
+
* call-seq:
|
144
|
+
* OouraFFT.ddct(ary) -> [*Float]
|
145
|
+
* OouraFFT.ddct(ary, inversion: true) -> [*Float]
|
146
|
+
*
|
147
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
148
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
149
|
+
*
|
150
|
+
* [Function type] Discrete Cosine Transform
|
151
|
+
* [Definition]
|
152
|
+
* case1:: IDCT (excluding scale)
|
153
|
+
* :: <tt>C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n</tt>
|
154
|
+
* case2:: DCT
|
155
|
+
* :: <tt>C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n</tt>
|
156
|
+
* [+ary+ sequence type] All +Float+
|
157
|
+
* [Array size requirement] n >= 2, n = power of 2
|
158
|
+
*
|
159
|
+
* def sinewave(amp, f0, fs, n)
|
160
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
161
|
+
* end
|
162
|
+
*
|
163
|
+
* OouraFFT.ddct(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
164
|
+
* #=> [0.6284174365157309,
|
165
|
+
* #=> -0.6284174365157309,
|
166
|
+
* #=> 0.18707572033318604,
|
167
|
+
* #=> -0.18707572033318612,
|
168
|
+
* #=> 0.08352232973991239,
|
169
|
+
* #=> -0.08352232973991236,
|
170
|
+
* #=> 0.02486404592245728,
|
171
|
+
* #=> -0.024864045922457167]
|
172
|
+
*/
|
173
|
+
static VALUE
|
174
|
+
fft_ddct(int argc, VALUE *argv, VALUE unused_obj)
|
175
|
+
{
|
176
|
+
return fft_callback(argc, argv, fft_ddct_inline);
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
#include "internal/solver/ooura_fft/ddst.h" // fft_ddst_inline()
|
181
|
+
/*
|
182
|
+
* Document-method: ddst
|
183
|
+
*
|
184
|
+
* call-seq:
|
185
|
+
* OouraFFT.ddst(ary) -> [*Float]
|
186
|
+
* OouraFFT.ddst(ary, inversion: true) -> [*Float]
|
187
|
+
*
|
188
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
189
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
190
|
+
*
|
191
|
+
* [Function type] Discrete Sine Transform
|
192
|
+
* [Definition]
|
193
|
+
* case1:: IDST (excluding scale)
|
194
|
+
* :: <tt>S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n</tt>
|
195
|
+
* case2:: DST
|
196
|
+
* :: <tt>S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n</tt>
|
197
|
+
* [+ary+ sequence type] All +Float+
|
198
|
+
* [Array size requirement] n >= 2, n = power of 2
|
199
|
+
*
|
200
|
+
* def sinewave(amp, f0, fs, n)
|
201
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
202
|
+
* end
|
203
|
+
*
|
204
|
+
* OouraFFT.ddst(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
205
|
+
* #=> [0.875,
|
206
|
+
* #=> 0.12500000000000003,
|
207
|
+
* #=> -0.12499999999999997,
|
208
|
+
* #=> 0.125,
|
209
|
+
* #=> -0.125,
|
210
|
+
* #=> 0.12500000000000006,
|
211
|
+
* #=> -0.12499999999999994,
|
212
|
+
* #=> 0.12499999999999994]
|
213
|
+
|
214
|
+
*/
|
215
|
+
static VALUE
|
216
|
+
fft_ddst(int argc, VALUE *argv, VALUE unused_obj)
|
217
|
+
{
|
218
|
+
return fft_callback(argc, argv, fft_ddst_inline);
|
219
|
+
}
|
220
|
+
|
221
|
+
|
222
|
+
#include "internal/solver/ooura_fft/dfct.h" // fft_dfct_inline()
|
223
|
+
/*
|
224
|
+
* Document-method: dfct
|
225
|
+
*
|
226
|
+
* call-seq:
|
227
|
+
* OouraFFT.dfct(ary) -> [*Float]
|
228
|
+
* OouraFFT.dfct(ary, inversion: true) -> [*Float]
|
229
|
+
*
|
230
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
231
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
232
|
+
*
|
233
|
+
* [Function type] Cosine Transform of RDFT (Real Symmetric DFT)
|
234
|
+
* [Definition] <tt>C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n</tt>
|
235
|
+
* [+ary+ sequence type] All +Float+
|
236
|
+
* [Array size requirement] n >= 2, n = power of 2
|
237
|
+
*
|
238
|
+
* def sinewave(amp, f0, fs, n)
|
239
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
240
|
+
* end
|
241
|
+
*
|
242
|
+
* OouraFFT.dfct(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
243
|
+
* #=> [1.1441462984511075,
|
244
|
+
* #=> -0.30353826116690874,
|
245
|
+
* #=> -0.21410561232180816,
|
246
|
+
* #=> 0.08422719461241164,
|
247
|
+
* #=> -0.14986404592245728,
|
248
|
+
* #=> 0.10711452157013322,
|
249
|
+
* #=> -0.13944777827146557,
|
250
|
+
* #=> 0.11219654498436385]
|
251
|
+
*/
|
252
|
+
static VALUE
|
253
|
+
fft_dfct(int argc, VALUE *argv, VALUE unused_obj)
|
254
|
+
{
|
255
|
+
return fft_callback(argc, argv, fft_dfct_inline);
|
256
|
+
}
|
257
|
+
|
258
|
+
|
259
|
+
#include "internal/solver/ooura_fft/dfst.h" // fft_dfst_inline()
|
260
|
+
/*
|
261
|
+
* Document-method: dfst
|
262
|
+
*
|
263
|
+
* call-seq:
|
264
|
+
* OouraFFT.dfst(ary) -> [*Float]
|
265
|
+
* OouraFFT.dfst(ary, inversion: true) -> [*Float]
|
266
|
+
*
|
267
|
+
* Perform FFT with the first argument +ary+ as a numerical sequence.<br>
|
268
|
+
* If the keyword argument +inversion+ is +true+, perform an inverse FFT.
|
269
|
+
*
|
270
|
+
* [Function type] Sine Transform of RDFT (Real Anti-symmetric DFT)
|
271
|
+
* [Definition] <tt>S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n</tt>
|
272
|
+
* [+ary+ sequence type] All +Float+
|
273
|
+
* [Array size requirement] n >= 2, n = power of 2
|
274
|
+
*
|
275
|
+
* def sinewave(amp, f0, fs, n)
|
276
|
+
* amp * Math.sin(2 * Math::PI * f0 * n / fs)
|
277
|
+
* end
|
278
|
+
*
|
279
|
+
* OouraFFT.dfst(Array.new(8){|n| sinewave(0.25, 250.0, 8000, n)})
|
280
|
+
* #=> [0.0,
|
281
|
+
* #=> 0.8406080372841989,
|
282
|
+
* #=> -0.3229641637954819,
|
283
|
+
* #=> 0.19308574608608534,
|
284
|
+
* #=> -0.12744889477603982,
|
285
|
+
* #=> 0.08469937042371564,
|
286
|
+
* #=> -0.05236611372238342,
|
287
|
+
* #=> 0.025114880435281595]
|
288
|
+
*/
|
289
|
+
static VALUE
|
290
|
+
fft_dfst(int argc, VALUE *argv, VALUE unused_obj)
|
291
|
+
{
|
292
|
+
return fft_callback(argc, argv, fft_dfst_inline);
|
293
|
+
|
294
|
+
}
|
295
|
+
|
296
|
+
static void
|
297
|
+
InitVM_FFTMain(void)
|
298
|
+
{
|
299
|
+
rb_define_module_function(rb_mOouraFFT, "cdft", fft_cdft, -1);
|
300
|
+
rb_define_module_function(rb_mOouraFFT, "rdft", fft_rdft, -1);
|
301
|
+
rb_define_module_function(rb_mOouraFFT, "ddct", fft_ddct, -1);
|
302
|
+
rb_define_module_function(rb_mOouraFFT, "ddst", fft_ddst, -1);
|
303
|
+
rb_define_module_function(rb_mOouraFFT, "dfct", fft_dfct, -1);
|
304
|
+
rb_define_module_function(rb_mOouraFFT, "dfst", fft_dfst, -1);
|
305
|
+
/* The using thread model name. Supports in Windows and POSIX. */
|
306
|
+
rb_define_const(rb_mOouraFFT, "USING_THREAD", rb_str_new_cstr((const char *)USING_THREAD));
|
307
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef INTERNAL_SETTING_OOURAFFT_H
|
2
|
+
#define INTERNAL_SETTING_OOURAFFT_H
|
3
|
+
|
4
|
+
// Ooura's FFT Thread Use Setting
|
5
|
+
#if defined(HAVE_CREATETHREAD) && \
|
6
|
+
defined(HAVE_WAITFORSINGLEOBJECT) && \
|
7
|
+
defined(HAVE_CLOSEHANDLE)
|
8
|
+
# define USE_CDFT_WINTHREADS
|
9
|
+
# define USING_THREAD "Windows"
|
10
|
+
#elif defined(HAVE_PTHREAD_CREATE) && defined(HAVE_PTHREAD_JOIN)
|
11
|
+
# define USE_CDFT_PTHREADS
|
12
|
+
# define USING_THREAD "POSIX"
|
13
|
+
#else
|
14
|
+
# define USING_THREAD NULL
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#endif /* INTERNAL_SETTING_OOURAFFT_H */
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_CDFT_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_CDFT_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_cdft_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long sz = RARRAY_LEN(ary);
|
9
|
+
int *ip;
|
10
|
+
double *a, *w;
|
11
|
+
|
12
|
+
if ((INT_MAX / 2) < sz)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (sz < 1)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 1, was %ld)", sz);
|
16
|
+
else if (!ispow2l(sz))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, sz*2);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(sz)));
|
21
|
+
w = ALLOC_N(double, sz/2);
|
22
|
+
|
23
|
+
for (volatile long i = 0; i < sz; i++)
|
24
|
+
{
|
25
|
+
VALUE elem = rb_ary_entry(ary, i);
|
26
|
+
if (TYPE(elem) != T_COMPLEX)
|
27
|
+
elem = rb_Complex1(elem);
|
28
|
+
const double real = NUM2DBL(rb_complex_real(elem));
|
29
|
+
const double imag = NUM2DBL(rb_complex_imag(elem));
|
30
|
+
a[2*i] = real;
|
31
|
+
a[2*i+1] = imag;
|
32
|
+
}
|
33
|
+
|
34
|
+
ip[0] = 0;
|
35
|
+
|
36
|
+
cdft(2*sz, invertible, a, ip, w);
|
37
|
+
|
38
|
+
retval = rb_ary_new2(sz);
|
39
|
+
|
40
|
+
for (volatile long i = 0; i < sz; i++)
|
41
|
+
{
|
42
|
+
rb_ary_store(retval, i, rb_dbl_complex_new(a[2*i], a[2*i+1]));
|
43
|
+
}
|
44
|
+
|
45
|
+
xfree(a);
|
46
|
+
xfree(ip);
|
47
|
+
xfree(w);
|
48
|
+
|
49
|
+
return retval;
|
50
|
+
}
|
51
|
+
|
52
|
+
#endif /* INTERNAL_SOLVER_FFT_CDFT */
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_DDCT_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_DDCT_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_ddct_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long sz = RARRAY_LEN(ary);
|
9
|
+
int *ip;
|
10
|
+
double *a, *w;
|
11
|
+
|
12
|
+
if (INT_MAX < sz)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (sz < 2)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 2, was %ld)", sz);
|
16
|
+
else if (!ispow2l(sz))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, sz);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(sz/2)));
|
21
|
+
w = ALLOC_N(double, sz*5/4);
|
22
|
+
|
23
|
+
for (volatile long i = 0; i < sz; i++)
|
24
|
+
{
|
25
|
+
VALUE elem = rb_ary_entry(ary, i);
|
26
|
+
a[i] = NUM2DBL(elem);
|
27
|
+
}
|
28
|
+
|
29
|
+
ip[0] = 0;
|
30
|
+
|
31
|
+
ddct(sz, invertible, a, ip, w);
|
32
|
+
|
33
|
+
retval = rb_ary_new2(sz);
|
34
|
+
|
35
|
+
for (volatile long i = 0; i < sz; i++)
|
36
|
+
{
|
37
|
+
rb_ary_store(retval, i, DBL2NUM(a[i]));
|
38
|
+
}
|
39
|
+
|
40
|
+
xfree(a);
|
41
|
+
xfree(ip);
|
42
|
+
xfree(w);
|
43
|
+
|
44
|
+
return retval;
|
45
|
+
}
|
46
|
+
|
47
|
+
#endif /* INTERNAL_SOLVER_FFT_DDCT */
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_DDST_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_DDST_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_ddst_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long sz = RARRAY_LEN(ary);
|
9
|
+
int *ip;
|
10
|
+
double *a, *w;
|
11
|
+
|
12
|
+
if (INT_MAX < sz)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (sz < 2)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 2, was %ld)", sz);
|
16
|
+
else if (!ispow2l(sz))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, sz);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(sz/2)));
|
21
|
+
w = ALLOC_N(double, sz*5/4);
|
22
|
+
|
23
|
+
for (volatile long i = 0; i < sz; i++)
|
24
|
+
{
|
25
|
+
VALUE elem = rb_ary_entry(ary, i);
|
26
|
+
a[i] = NUM2DBL(elem);
|
27
|
+
}
|
28
|
+
|
29
|
+
ip[0] = 0;
|
30
|
+
|
31
|
+
ddst(sz, invertible, a, ip, w);
|
32
|
+
|
33
|
+
retval = rb_ary_new2(sz);
|
34
|
+
|
35
|
+
for (volatile long i = 0; i < sz; i++)
|
36
|
+
{
|
37
|
+
rb_ary_store(retval, i, DBL2NUM(a[i]));
|
38
|
+
}
|
39
|
+
|
40
|
+
xfree(a);
|
41
|
+
xfree(ip);
|
42
|
+
xfree(w);
|
43
|
+
|
44
|
+
return retval;
|
45
|
+
}
|
46
|
+
|
47
|
+
#endif /* INTERNAL_SOLVER_FFT_DDST */
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_DFCT_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_DFCT_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_dfct_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long n = RARRAY_LEN(ary), sz = n + 1;
|
9
|
+
int *ip;
|
10
|
+
double *a, *w, *t;
|
11
|
+
|
12
|
+
if (INT_MAX < n)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (n < 2)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 2, was %ld)", n);
|
16
|
+
else if (!ispow2l(n))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, sz);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(n/4)));
|
21
|
+
t = ALLOC_N(double, sz/2);
|
22
|
+
w = ALLOC_N(double, n*5/8);
|
23
|
+
|
24
|
+
for (volatile long i = 0; i < n; i++)
|
25
|
+
{
|
26
|
+
VALUE elem = rb_ary_entry(ary, i);
|
27
|
+
if (invertible == -1)
|
28
|
+
a[i] = NUM2DBL(elem) * 0.5;
|
29
|
+
else
|
30
|
+
a[i] = NUM2DBL(elem);
|
31
|
+
}
|
32
|
+
|
33
|
+
ip[0] = 0;
|
34
|
+
|
35
|
+
dfct(n, a, t, ip, w);
|
36
|
+
|
37
|
+
retval = rb_ary_new2(n);
|
38
|
+
|
39
|
+
for (volatile long i = 0; i < n; i++)
|
40
|
+
{
|
41
|
+
if (invertible == -1)
|
42
|
+
rb_ary_store(retval, i, DBL2NUM(a[i] * 2.0 / n));
|
43
|
+
else
|
44
|
+
rb_ary_store(retval, i, DBL2NUM(a[i]));
|
45
|
+
}
|
46
|
+
|
47
|
+
xfree(a);
|
48
|
+
xfree(ip);
|
49
|
+
xfree(t);
|
50
|
+
xfree(w);
|
51
|
+
|
52
|
+
return retval;
|
53
|
+
}
|
54
|
+
|
55
|
+
#endif /* INTERNAL_SOLVER_FFT_DFCT */
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_DFST_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_DFST_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_dfst_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long n = RARRAY_LEN(ary);
|
9
|
+
int *ip;
|
10
|
+
double *a, *w, *t;
|
11
|
+
|
12
|
+
if (INT_MAX < n)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (n < 2)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 2, was %ld)", n);
|
16
|
+
else if (!ispow2l(n))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, n);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(n/4)));
|
21
|
+
t = ALLOC_N(double, n/2);
|
22
|
+
w = ALLOC_N(double, n*5/8);
|
23
|
+
|
24
|
+
for (volatile long i = 0; i < n; i++)
|
25
|
+
{
|
26
|
+
VALUE elem = rb_ary_entry(ary, i);
|
27
|
+
a[i] = NUM2DBL(elem);
|
28
|
+
}
|
29
|
+
|
30
|
+
ip[0] = 0;
|
31
|
+
|
32
|
+
dfst(n, a, t, ip, w);
|
33
|
+
|
34
|
+
retval = rb_ary_new2(n);
|
35
|
+
|
36
|
+
for (volatile long i = 0; i < n; i++)
|
37
|
+
{
|
38
|
+
if (invertible == -1)
|
39
|
+
rb_ary_store(retval, i, DBL2NUM(a[i] * 2.0 / n));
|
40
|
+
else
|
41
|
+
rb_ary_store(retval, i, DBL2NUM(a[i]));
|
42
|
+
}
|
43
|
+
|
44
|
+
xfree(a);
|
45
|
+
xfree(ip);
|
46
|
+
xfree(t);
|
47
|
+
xfree(w);
|
48
|
+
|
49
|
+
return retval;
|
50
|
+
}
|
51
|
+
|
52
|
+
#endif /* INTERNAL_SOLVER_FFT_DFST */
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#ifndef INTERNAL_SOLVER_FFT_RDFT_H
|
2
|
+
#define INTERNAL_SOLVER_FFT_RDFT_H
|
3
|
+
|
4
|
+
static inline VALUE
|
5
|
+
fft_rdft_inline(VALUE ary, int invertible)
|
6
|
+
{
|
7
|
+
VALUE retval;
|
8
|
+
long sz = RARRAY_LEN(ary);
|
9
|
+
int *ip;
|
10
|
+
double *a, *w;
|
11
|
+
|
12
|
+
if (INT_MAX < sz)
|
13
|
+
rb_raise(rb_eRangeError, "biggest array size");
|
14
|
+
else if (sz < 2)
|
15
|
+
rb_raise(rb_eRangeError, "unavailable array size (n >= 2, was %ld)", sz);
|
16
|
+
else if (!ispow2l(sz))
|
17
|
+
rb_raise(rb_eRangeError, "size must be 2^m");
|
18
|
+
|
19
|
+
a = ALLOC_N(double, sz);
|
20
|
+
ip = ALLOC_N(int, (int)(2+sqrt(sz/2)));
|
21
|
+
w = ALLOC_N(double, sz/2);
|
22
|
+
|
23
|
+
for (volatile long i = 0; i < sz; i++)
|
24
|
+
{
|
25
|
+
VALUE elem = rb_ary_entry(ary, i);
|
26
|
+
a[i] = NUM2DBL(elem);
|
27
|
+
}
|
28
|
+
|
29
|
+
ip[0] = 0;
|
30
|
+
|
31
|
+
rdft(sz, invertible, a, ip, w);
|
32
|
+
|
33
|
+
retval = rb_ary_new2(sz);
|
34
|
+
|
35
|
+
for (volatile long i = 0; i < sz; i++)
|
36
|
+
{
|
37
|
+
rb_ary_store(retval, i, DBL2NUM(a[i]));
|
38
|
+
}
|
39
|
+
|
40
|
+
xfree(a);
|
41
|
+
xfree(ip);
|
42
|
+
xfree(w);
|
43
|
+
|
44
|
+
return retval;
|
45
|
+
}
|
46
|
+
|
47
|
+
#endif /* INTERNAL_SOLVER_FFT_RDFT */
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#ifndef FFT_MISSING_H
|
2
|
+
#define FFT_MISSING_H
|
3
|
+
|
4
|
+
#if defined(__cplusplus)
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
// C2X newer library
|
9
|
+
#ifdef HAVE_STDBIT_H
|
10
|
+
# include <stdbit.h>
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#ifndef HAVE_ISPOW2L
|
14
|
+
extern bool ispow2l(long);
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#if defined(__cplusplus)
|
18
|
+
}
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#endif /* FFT_MISSING_H */
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef RB_OOURAFFT_API_H_INCLUDED
|
2
|
+
#define RB_OOURAFFT_API_H_INCLUDED
|
3
|
+
|
4
|
+
#include <ruby/internal/value.h> // VALUE
|
5
|
+
|
6
|
+
VALUE rb_oourafft_cdft(VALUE, int);
|
7
|
+
VALUE rb_oourafft_rdft(VALUE, int);
|
8
|
+
VALUE rb_oourafft_ddct(VALUE, int);
|
9
|
+
VALUE rb_oourafft_ddst(VALUE, int);
|
10
|
+
VALUE rb_oourafft_dfct(VALUE, int);
|
11
|
+
VALUE rb_oourafft_dfst(VALUE, int);
|
12
|
+
|
13
|
+
#endif /* RB_OOURAFFT_API_H_INCLUDED */
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef RUBY_EXT_EXTERN_H_INCLUDED
|
2
|
+
#define RUBY_EXT_EXTERN_H_INCLUDED
|
3
|
+
|
4
|
+
#if defined(__cplusplus)
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#ifdef USE_GLOBAL_VARIABLE
|
9
|
+
# define RUBY_EXT_EXTERN
|
10
|
+
#else
|
11
|
+
# define RUBY_EXT_EXTERN extern
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#if defined(__cplusplus)
|
15
|
+
}
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#endif /* RUBY_EXT_EXTERN_H_INCLUDED */
|