ruby-fftw3 0.4.2 → 1.0.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.
@@ -1,3 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
data/README.rd DELETED
File without changes
@@ -1,116 +0,0 @@
1
- <?xml version="1.0" ?>
2
- <!DOCTYPE html
3
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
- <html xmlns="http://www.w3.org/1999/xhtml">
6
- <head>
7
- <title>ruby-fftw3.rd</title>
8
- </head>
9
- <body>
10
- <h1><a name="label-0" id="label-0">module NumRu::FFTW3</a></h1><!-- RDLabel: "module NumRu::FFTW3" -->
11
- <p>Fast Fourier Transforms by using <a href="http://www.fftw.org">FFTW</a> Ver.3.</p>
12
- <p>Takeshi Horinouchi</p>
13
- <p>(C) Takeshi Horinouchi / GFD Dennou Club,
14
- 2003</p>
15
- <p>NO WARRANTY</p>
16
- <h2><a name="label-1" id="label-1">Features</a></h2><!-- RDLabel: "Features" -->
17
- <ul>
18
- <li>Uses <a href="http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray">NArray</a>.</li>
19
- <li>Multi-dimensional complex FFT. (Real data are coerced to complex).</li>
20
- <li>Supports both double and single float transforms.</li>
21
- <li>Not normalized as in FFTW</li>
22
- </ul>
23
- <h2><a name="label-2" id="label-2">Features yet to be introduced</a></h2><!-- RDLabel: "Features yet to be introduced" -->
24
- <ul>
25
- <li>Sine / cosine transforms</li>
26
- <li>User choice of optimization levels (i.e., FFTW_MEASURE etc in
27
- addition to FFTW_ESTIMATE).</li>
28
- <li>Multi-threaded FFT3 support -- don't know whether it's really feasible.</li>
29
- </ul>
30
- <h2><a name="label-3" id="label-3">Installation</a></h2><!-- RDLabel: "Installation" -->
31
- <ul>
32
- <li>Install <a href="http://www.fftw.org">FFTW</a> Ver.3.
33
- <ul>
34
- <li>NOTE:
35
- To activate the single-float transform, you have to install FFTW3 with
36
- the single-float compilation, in addition to the default double-float
37
- version. This can be done by configuring FFTW3 with
38
- the --enable-float option, and install it again. The single-float
39
- version will coexist with the double-float version.
40
- If you do not install the single-float version, FFT is always done
41
- with the double precision, which is not bad if you are not time- and
42
- memory-conscious.</li>
43
- </ul></li>
44
- <li>Install <a href="http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray">NArray</a>.</li>
45
- <li><p>Then, install this library as follows (replace "version" with
46
- the actual version number):</p>
47
- <pre>% tar xvzf fftw3-version.tar.gz
48
- % cd fftw3-version
49
- % ruby extconf.rb
50
- % make
51
- % make site-install</pre>
52
- <p>Or</p>
53
- <pre>% make install</pre>
54
- <p>(If you are using Ruby 1.8, make install is the same make site-install.)</p></li>
55
- </ul>
56
- <h2><a name="label-4" id="label-4">How to use</a></h2><!-- RDLabel: "How to use" -->
57
- <p>See the following peice of code. (Install this library and copy and
58
- paste the following to the interactive shell irb).</p>
59
- <pre>require "numru/fftw3"
60
- include NumRu
61
-
62
- na = NArray.float(8,6) # float -&gt; will be corced to complex
63
- na[1,1]=1
64
-
65
- # &lt;example 1&gt;
66
- fc = FFTW3.fft(na, -1)/na.length # forward 2D FFT and normalization
67
- nc = FFTW3.fft(fc, 1) # backward 2D FFT (complex) --&gt;
68
- nb = nc.real # should be equal to na except round errors
69
-
70
- # &lt;example 2&gt;
71
- fc = FFTW3.fft(na, -1, 0) / na.shape[0] # forward FFT with the first dim
72
-
73
- # &lt;example 3&gt;
74
- fc = FFTW3.fft(na, -1, 1) / na.shape[1] # forward FFT with the second dim</pre>
75
- <h2><a name="label-5" id="label-5">API Reference</a></h2><!-- RDLabel: "API Reference" -->
76
- <h3><a name="label-6" id="label-6">Module methods</a></h3><!-- RDLabel: "Module methods" -->
77
- <dl>
78
- <dt><a name="label-7" id="label-7"><code>fft(<var>narray</var>, <var>dir</var> [,<var>dim</var>,<var>dim</var>,...])</code></a></dt><!-- RDLabel: "fft" -->
79
- <dd>
80
- <p>Complex FFT.</p>
81
- <p>The 3rd, 4th,... arguments are optional.</p>
82
- <p>ARGUMENTS</p>
83
- <ul>
84
- <li>narray (NArray or NArray-compatible Array) : array to be
85
- transformed. If real, coerced to complex before transformation.
86
- If narray is single-precision and the single-precision
87
- version of FFTW3 is installed (before installing this module),
88
- this method does a single-precision transform.
89
- Otherwise, a double-precision transform is used.</li>
90
- <li>dir (-1 or 1) : forward transform if -1; backward transform if 1.</li>
91
- <li>optional 3rd, 4th,... arguments (Integer) : Specifies dimensions
92
- to apply FFT. For example, if 0, the first dimension is
93
- transformed (1D FFT); If -1, the last dimension is used (1D FFT);
94
- If 0,2,4, the first, third, and fifth dimensions
95
- are transformed (3D FFT); If entirely omitted, ALL DIMENSIONS
96
- ARE SUBJECT TO FFT, so 3D FFT is done with a 3D array.</li>
97
- </ul>
98
- <p>RETURN VALUE</p>
99
- <ul>
100
- <li>a complex NArray</li>
101
- </ul>
102
- <p>NOTE</p>
103
- <ul>
104
- <li>As in FFTW, return value is NOT normalized. Thus, a consecutive
105
- forward and backward transform would multiply the size of
106
- data used for transform. You can normalize, for example,
107
- the forward transform FFTW.fft(narray, -1, 0, 1)
108
- (FFT regarding the first (dim 0) &amp; second (dim 1) dimensions) by
109
- dividing with (narray.shape[0]*narray.shape[1]). Likewise,
110
- the result of FFTW.fft(narray, -1) (FFT for all dimensions)
111
- can be normalized by narray.length.</li>
112
- </ul></dd>
113
- </dl>
114
-
115
- </body>
116
- </html>
@@ -1,115 +0,0 @@
1
- =module NumRu::FFTW3
2
-
3
- Fast Fourier Transforms by using ((<FFTW|URL:http://www.fftw.org>)) Ver.3.
4
-
5
- Takeshi Horinouchi
6
-
7
- (C) Takeshi Horinouchi / GFD Dennou Club,
8
- 2003
9
-
10
- NO WARRANTY
11
-
12
- ==Features
13
-
14
- * Uses ((<NArray|URL:http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray>)).
15
- * Multi-dimensional complex FFT. (Real data are coerced to complex).
16
- * Supports both double and single float transforms.
17
- * Not normalized as in FFTW
18
-
19
- ==Features yet to be introduced
20
-
21
- * Sine / cosine transforms
22
- * User choice of optimization levels (i.e., FFTW_MEASURE etc in
23
- addition to FFTW_ESTIMATE).
24
- * Multi-threaded FFT3 support -- don't know whether it's really feasible.
25
-
26
- ==Installation
27
-
28
- * Install ((<FFTW|URL:http://www.fftw.org>)) Ver.3.
29
-
30
- * NOTE:
31
- To activate the single-float transform, you have to install FFTW3 with
32
- the single-float compilation, in addition to the default double-float
33
- version. This can be done by configuring FFTW3 with
34
- the --enable-float option, and install it again. The single-float
35
- version will coexist with the double-float version.
36
- If you do not install the single-float version, FFT is always done
37
- with the double precision, which is not bad if you are not time- and
38
- memory-conscious.
39
-
40
- * Install ((<NArray|URL:http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray>)).
41
-
42
- * Then, install this library as follows (replace "version" with
43
- the actual version number):
44
-
45
- % tar xvzf fftw3-version.tar.gz
46
- % cd fftw3-version
47
- % ruby extconf.rb
48
- % make
49
- % make site-install
50
- Or
51
- % make install
52
- (If you are using Ruby 1.8, make install is the same make site-install.)
53
-
54
- ==How to use
55
-
56
- See the following peice of code. (Install this library and copy and
57
- paste the following to the interactive shell irb).
58
-
59
- require "numru/fftw3"
60
- include NumRu
61
-
62
- na = NArray.float(8,6) # float -> will be corced to complex
63
- na[1,1]=1
64
-
65
- # <example 1>
66
- fc = FFTW3.fft(na, -1)/na.length # forward 2D FFT and normalization
67
- nc = FFTW3.fft(fc, 1) # backward 2D FFT (complex) -->
68
- nb = nc.real # should be equal to na except round errors
69
-
70
- # <example 2>
71
- fc = FFTW3.fft(na, -1, 0) / na.shape[0] # forward FFT with the first dim
72
-
73
- # <example 3>
74
- fc = FFTW3.fft(na, -1, 1) / na.shape[1] # forward FFT with the second dim
75
-
76
- ==API Reference
77
-
78
- ===Module methods
79
-
80
- ---fft(narray, dir [,dim,dim,...])
81
-
82
- Complex FFT.
83
-
84
- The 3rd, 4th,... arguments are optional.
85
-
86
- ARGUMENTS
87
- * narray (NArray or NArray-compatible Array) : array to be
88
- transformed. If real, coerced to complex before transformation.
89
- If narray is single-precision and the single-precision
90
- version of FFTW3 is installed (before installing this module),
91
- this method does a single-precision transform.
92
- Otherwise, a double-precision transform is used.
93
- * dir (-1 or 1) : forward transform if -1; backward transform if 1.
94
- * optional 3rd, 4th,... arguments (Integer) : Specifies dimensions
95
- to apply FFT. For example, if 0, the first dimension is
96
- transformed (1D FFT); If -1, the last dimension is used (1D FFT);
97
- If 0,2,4, the first, third, and fifth dimensions
98
- are transformed (3D FFT); If entirely omitted, ALL DIMENSIONS
99
- ARE SUBJECT TO FFT, so 3D FFT is done with a 3D array.
100
-
101
- RETURN VALUE
102
- * a complex NArray
103
-
104
- NOTE
105
- * As in FFTW, return value is NOT normalized. Thus, a consecutive
106
- forward and backward transform would multiply the size of
107
- data used for transform. You can normalize, for example,
108
- the forward transform FFTW.fft(narray, -1, 0, 1)
109
- (FFT regarding the first (dim 0) & second (dim 1) dimensions) by
110
- dividing with (narray.shape[0]*narray.shape[1]). Likewise,
111
- the result of FFTW.fft(narray, -1) (FFT for all dimensions)
112
- can be normalized by narray.length.
113
-
114
-
115
-
data/na_fftw3.c DELETED
@@ -1,285 +0,0 @@
1
- /*
2
- na_fftw3.c
3
-
4
- FFT using FFTW Ver.3 (www.fftw.org)
5
-
6
- (C) Takeshi Horinouchi
7
- NO WARRANTY.
8
-
9
- */
10
-
11
- #include <ruby.h>
12
- #include "narray.h"
13
- #include <fftw3.h>
14
-
15
- VALUE rb_mFFTW3;
16
- VALUE mNumRu;
17
-
18
- static VALUE
19
- #ifdef FFTW3_HAS_SINGLE_SUPPORT
20
- na_fftw3_double(int argc, VALUE *argv, VALUE self)
21
- /* to be called by na_fftw3 */
22
- #else
23
- na_fftw3(int argc, VALUE *argv, VALUE self)
24
- /* to be called directly */
25
- #endif
26
- {
27
- VALUE val, vdir;
28
- struct NARRAY *a1, *a2;
29
- int i, dir, *shape, *bucket;
30
- fftw_plan p;
31
- fftw_complex *in, *out;
32
- volatile VALUE v1, v2;
33
-
34
- if (argc<2){
35
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
36
- }
37
- val = argv[0];
38
- vdir = argv[1];
39
-
40
- dir = NUM2INT(vdir);
41
- if ( dir != 1 && dir != -1 ){
42
- rb_raise(rb_eArgError, "direction should be 1 or -1");
43
- }
44
- v1 = na_cast_object(val, NA_DCOMPLEX);
45
- GetNArray(v1,a1);
46
- v2 = na_make_object( NA_DCOMPLEX, a1->rank, a1->shape, CLASS_OF(v1) );
47
- GetNArray(v2,a2);
48
-
49
- shape = ALLOCA_N(int, a2->rank);
50
- for (i=0; i<a2->rank; i++){
51
- shape[i] = a2->shape[a2->rank-1-i];
52
- }
53
- in = (fftw_complex*)a1->ptr;
54
- out = (fftw_complex*)a2->ptr;
55
-
56
- if (argc==2) {
57
- /* apply FFT to all dimensions */
58
- p = fftw_plan_dft( a2->rank, shape,
59
- in, out, dir, FFTW_ESTIMATE );
60
- } else {
61
- /* apply FFT to selected dimensions (by using the Guru interface) */
62
- { /* introduce a new scope for additonal local variables */
63
- int fft_rank, howmany_rank, ib, j, jf, je, dim;
64
- fftw_iodim *fft_dims, *howmany_dims;
65
- int *dimids;
66
- fft_rank = argc - 2;
67
- fft_dims = ALLOCA_N(fftw_iodim, fft_rank);
68
- dimids = ALLOCA_N(int, fft_rank);
69
- howmany_rank = fft_rank + 1;
70
- howmany_dims = ALLOCA_N(fftw_iodim, howmany_rank);
71
-
72
- for (i=2;i<argc;i++){
73
- dim = NUM2INT(argv[i]);
74
- if (dim<0) dim += a2->rank; /* negative: count from the end */
75
- if (dim<0 || dim>=a2->rank){
76
- rb_raise(rb_eArgError, "dimension < 0 or >= rank");
77
- }
78
- dimids[i-2] = a2->rank - 1 - dim;
79
- if ( i>2 && dimids[i-2] == dimids[i-3] ){
80
- rb_raise(rb_eArgError, "redundant -- a same dimension is reppeated");
81
- }
82
- }
83
-
84
- /* bukcet sort in increasing order */
85
- bucket = ALLOCA_N(int,a2->rank);
86
- for(j=0; j<a2->rank; j++) bucket[j] = 0; /* initialize */
87
- for(i=0; i<fft_rank; i++) bucket[ dimids[i] ] = 1;
88
- for(j=0,i=0; j<a2->rank; j++) {
89
- if (bucket[j]==1){
90
- dimids[i] = j;
91
- i++;
92
- }
93
- }
94
-
95
- for(j=0; j<fft_rank; j++){
96
- fft_dims[j].n = shape[ dimids[j] ];
97
- fft_dims[j].is = 1;
98
- for (i=dimids[j]+1 ; i<a2->rank ; i++){
99
- fft_dims[j].is *= shape[i];
100
- }
101
- fft_dims[j].os = fft_dims[j].is;
102
- /* printf("fft_ %d n:%d is:%d\n",j,
103
- fft_dims[j].n,fft_dims[j].is);*/
104
- }
105
- for(j=0; j<=fft_rank; j++){
106
- howmany_dims[j].n = 1;
107
- jf = (j==0) ? 0 : (dimids[j-1]+1) ;
108
- je = (j==fft_rank) ? a2->rank : (dimids[j]) ;
109
- for (i=jf; i<je; i++){
110
- howmany_dims[j].n *= shape[i];
111
- }
112
- howmany_dims[j].is = 1;
113
- if (j<fft_rank){
114
- for (i=dimids[j]; i<a2->rank; i++){
115
- howmany_dims[j].is *= shape[i];
116
- }
117
- }
118
- howmany_dims[j].os = howmany_dims[j].is;
119
- /* printf("how_ %d n:%d is:%d\n",j,
120
- howmany_dims[j].n,howmany_dims[j].is); */
121
- }
122
-
123
- p = fftw_plan_guru_dft( fft_rank, fft_dims,
124
- howmany_rank, howmany_dims,
125
- in, out, dir, FFTW_ESTIMATE );
126
-
127
- }
128
- }
129
-
130
- fftw_execute(p);
131
- fftw_destroy_plan(p);
132
-
133
- return v2;
134
- }
135
-
136
- #ifdef FFTW3_HAS_SINGLE_SUPPORT
137
-
138
- /* sourse code generation of na_fftw3_float:
139
- Copy na_fftw3_double, and replace
140
- fftw --> fftwf
141
- DCOMPLEX --> SCOMPLEX
142
- */
143
- static VALUE
144
- na_fftw3_float(int argc, VALUE *argv, VALUE self)
145
- {
146
- VALUE val, vdir;
147
- struct NARRAY *a1, *a2;
148
- int i, dir, *shape, *bucket;
149
- fftwf_plan p;
150
- fftwf_complex *in, *out;
151
- volatile VALUE v1, v2;
152
-
153
- if (argc<2){
154
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
155
- }
156
- val = argv[0];
157
- vdir = argv[1];
158
-
159
- dir = NUM2INT(vdir);
160
- if ( dir != 1 && dir != -1 ){
161
- rb_raise(rb_eArgError, "direction should be 1 or -1");
162
- }
163
- v1 = na_cast_object(val, NA_SCOMPLEX);
164
- GetNArray(v1,a1);
165
- v2 = na_make_object( NA_SCOMPLEX, a1->rank, a1->shape, CLASS_OF(v1) );
166
- GetNArray(v2,a2);
167
-
168
- shape = ALLOCA_N(int, a2->rank);
169
- for (i=0; i<a2->rank; i++){
170
- shape[i] = a2->shape[a2->rank-1-i];
171
- }
172
- in = (fftwf_complex*)a1->ptr;
173
- out = (fftwf_complex*)a2->ptr;
174
-
175
- if (argc==2) {
176
- /* apply FFT to all dimensions */
177
- p = fftwf_plan_dft( a2->rank, shape,
178
- in, out, dir, FFTW_ESTIMATE );
179
- } else {
180
- /* apply FFT to selected dimensions (by using the Guru interface) */
181
- { /* introduce a new scope for additonal local variables */
182
- int fft_rank, howmany_rank, ib, j, jf, je, dim;
183
- fftw_iodim *fft_dims, *howmany_dims;
184
- int *dimids;
185
- fft_rank = argc - 2;
186
- fft_dims = ALLOCA_N(fftw_iodim, fft_rank);
187
- dimids = ALLOCA_N(int, fft_rank);
188
- howmany_rank = fft_rank + 1;
189
- howmany_dims = ALLOCA_N(fftw_iodim, howmany_rank);
190
-
191
- for (i=2;i<argc;i++){
192
- dim = NUM2INT(argv[i]);
193
- if (dim<0) dim += a2->rank; /* negative: count from the end */
194
- if (dim<0 || dim>=a2->rank){
195
- rb_raise(rb_eArgError, "dimension < 0 or >= rank");
196
- }
197
- dimids[i-2] = a2->rank - 1 - dim;
198
- if ( i>2 && dimids[i-2] == dimids[i-3] ){
199
- rb_raise(rb_eArgError, "redundant -- a same dimension is reppeated");
200
- }
201
- }
202
-
203
- /* bukcet sort in increasing order */
204
- bucket = ALLOCA_N(int,a2->rank);
205
- for(j=0; j<a2->rank; j++) bucket[j] = 0; /* initialize */
206
- for(i=0; i<fft_rank; i++) bucket[ dimids[i] ] = 1;
207
- for(j=0,i=0; j<a2->rank; j++) {
208
- if (bucket[j]==1){
209
- dimids[i] = j;
210
- i++;
211
- }
212
- }
213
-
214
- for(j=0; j<fft_rank; j++){
215
- fft_dims[j].n = shape[ dimids[j] ];
216
- fft_dims[j].is = 1;
217
- for (i=dimids[j]+1 ; i<a2->rank ; i++){
218
- fft_dims[j].is *= shape[i];
219
- }
220
- fft_dims[j].os = fft_dims[j].is;
221
- /* printf("fft_ %d n:%d is:%d\n",j,
222
- fft_dims[j].n,fft_dims[j].is);*/
223
- }
224
- for(j=0; j<=fft_rank; j++){
225
- howmany_dims[j].n = 1;
226
- jf = (j==0) ? 0 : (dimids[j-1]+1) ;
227
- je = (j==fft_rank) ? a2->rank : (dimids[j]) ;
228
- for (i=jf; i<je; i++){
229
- howmany_dims[j].n *= shape[i];
230
- }
231
- howmany_dims[j].is = 1;
232
- if (j<fft_rank){
233
- for (i=dimids[j]; i<a2->rank; i++){
234
- howmany_dims[j].is *= shape[i];
235
- }
236
- }
237
- howmany_dims[j].os = howmany_dims[j].is;
238
- /* printf("how_ %d n:%d is:%d\n",j,
239
- howmany_dims[j].n,howmany_dims[j].is); */
240
- }
241
-
242
- p = fftwf_plan_guru_dft( fft_rank, fft_dims,
243
- howmany_rank, howmany_dims,
244
- in, out, dir, FFTW_ESTIMATE );
245
-
246
- }
247
- }
248
-
249
- fftwf_execute(p);
250
- fftwf_destroy_plan(p);
251
-
252
- return v2;
253
- }
254
-
255
- static VALUE
256
- na_fftw3(int argc, VALUE *argv, VALUE self)
257
- {
258
- VALUE val;
259
- volatile VALUE v1;
260
- struct NARRAY *a1;
261
-
262
- if (argc<2){
263
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
264
- }
265
- val = argv[0];
266
- v1 = na_to_narray(val);
267
- GetNArray(v1,a1);
268
- if(a1->type <= NA_SFLOAT || a1->type == NA_SCOMPLEX ){
269
- return( na_fftw3_float(argc, argv, self) );
270
- } else {
271
- return( na_fftw3_double(argc, argv, self) );
272
- }
273
-
274
- }
275
-
276
- #endif
277
-
278
- void
279
- Init_fftw3()
280
- {
281
- rb_require("narray");
282
- mNumRu = rb_define_module("NumRu");
283
- rb_mFFTW3 = rb_define_module_under(mNumRu, "FFTW3");
284
- rb_define_module_function(rb_mFFTW3, "fft", na_fftw3, -1);
285
- }