ruby-fftw3 0.4.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{ChangeLog → .ChangeLog.until20110419} +0 -0
- data/.gitignore +5 -6
- data/LICENSE.txt +1 -1
- data/Rakefile +35 -1
- data/{extconf.rb → ext/numru/fftw3/extconf.rb} +32 -6
- data/ext/numru/fftw3/na_fftw3.c +690 -0
- data/lib/numru/fftw3.rb +102 -0
- data/lib/numru/fftw3/version.rb +2 -2
- data/ruby-fftw3-bigmem.gemspec +25 -0
- data/ruby-fftw3.gemspec +5 -12
- data/test/complexFFT.rb +57 -34
- data/test/r2rFFT.rb +77 -0
- metadata +19 -22
- data/.rspec +0 -2
- data/.travis.yml +0 -3
- data/README.rd +0 -0
- data/doc/ruby-fftw3.html +0 -116
- data/doc/ruby-fftw3.rd +0 -115
- data/na_fftw3.c +0 -285
- data/spec/ruby/fftw3_spec.rb +0 -11
- data/spec/spec_helper.rb +0 -2
data/.travis.yml
DELETED
data/README.rd
DELETED
File without changes
|
data/doc/ruby-fftw3.html
DELETED
@@ -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 -> 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</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) & 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>
|
data/doc/ruby-fftw3.rd
DELETED
@@ -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
|
-
}
|