ruby-fftw3 0.4a

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Tue Apr 19 2011 T Horinouchi
2
+ * version 0.4 released (cvs tag ruby-fftw3-0_4)
3
+ * doc/ruby-fftw3.rd and doc/ruby-fftw3.html : updated
4
+ * na_fftw3.c: added rb_require("narray"); -- then you do
5
+ not need to require "narray" separately.
6
+ * test/complexFFT.rb: removed the first line: require "narray"
7
+ * LICENSE.txt: changed --> BSD 2-clause license
8
+ Thu Mar 24 2011 T Horinouchi
9
+ * version 0.3 released (cvs tag ruby-fftw3-0_3)
10
+ * LICENSE.txt: added
11
+ Mon Jun 7 2004 T Horinouchi < T Koshiro
12
+ * version 0.2 released (cvs tag ruby-fftw3-0_2)
13
+ * extconf.rb: improved
14
+ Mon Jun 7 2004 T Horinouchi
15
+ * renamed to ruby-fftw. Started a new cvs module ruby-fftw3.
16
+ Fri Nov 20 2003 T Horinouchi
17
+ * version 0.1 released
18
+ Thu Nov 20 2003 T Horinouchi
19
+ * na_fftw3.c: debug of na_fftw3_float
20
+ Tue Nov 18 2003 T Horinouchi
21
+ * created. version 0.0
@@ -0,0 +1,34 @@
1
+ Ruby-FFTW3 is copyrighted free software by Takeshi Horinouchi and GFD
2
+ Dennou Club (http://www.gfd-dennou.org/).
3
+
4
+ Copyright 2001 (C) Takeshi Horinouchi and GFD Dennou Club
5
+ (http://www.gfd-dennou.org/) All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+
11
+ 1. Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+
14
+ 2. Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in
16
+ the documentation and/or other materials provided with the
17
+ distribution.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY GFD DENNOU CLUB AND CONTRIBUTORS ``AS IS''
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
23
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ The views and conclusions contained in the software and documentation
32
+ are those of the authors and should not be interpreted as representing
33
+ official policies, either expressed or implied, of Takeshi Horinouchi
34
+ and GFD Dennou Club.
@@ -0,0 +1,38 @@
1
+ require 'rake/gempackagetask'
2
+
3
+ NAME = 'ruby-fftw3'
4
+ VER = '0.4a'
5
+
6
+ PKG_FILES = FileList[
7
+ '**',
8
+ 'doc/**/*',
9
+ 'test/**/*'
10
+ ]
11
+
12
+ spec = Gem::Specification.new do |s|
13
+ s.name = NAME
14
+ s.version = VER
15
+ s.authors = ["Takeshi Horinouchi"]
16
+ s.email = ['eriko@gfd-dennou.org']
17
+ s.homepage = 'http://www.gfd-dennou.org/arch/ruby/products/ruby-fftw3/'
18
+ s.licenses = ["Takeshi Horinouchi", "GFD Dennou Club"]
19
+ s.platform = Gem::Platform::RUBY
20
+ s.summary = %q{The Ruby interface of the FFTW (ver 3) library}
21
+ s.description = %q{Fast Fourier Transforms by using FFTW Ver.3}
22
+
23
+ s.files = PKG_FILES.to_a
24
+ #s.require_paths = ['lib']
25
+ #s.test_files = Dir.glob("test/*")
26
+ #s.has_rdoc = true
27
+ s.required_ruby_version = Gem::Requirement.new(">= 1.6")
28
+ s.add_runtime_dependency(%q<narray>, [">= 0"])
29
+ #s.add_runtime_dependency(%q<narray_miss>, [">= 0"])
30
+ #s.extra_rdoc_files = ['README']
31
+
32
+ s.extensions << "extconf.rb"
33
+ end
34
+
35
+ Rake::GemPackageTask.new(spec) do |pkg|
36
+ pkg.gem_spec = spec
37
+ pkg.need_tar = true
38
+ end
data/ToDo ADDED
@@ -0,0 +1,4 @@
1
+ 2003/11/18
2
+ * enable users to choose FFTW_MEASURE etc
3
+ * support real-to-real tranforms (esp. sine and cosine transforms)
4
+
@@ -0,0 +1,116 @@
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>
@@ -0,0 +1,115 @@
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
+
@@ -0,0 +1,50 @@
1
+ require "rubygems" unless defined?(Gem)
2
+ require "mkmf"
3
+
4
+ #dir_config('narray',$sitearchdir,$sitearchdir)
5
+ hoge = Gem::GemPathSearcher.new.find("narray")
6
+ narray_fullname = hoge.full_name
7
+ narray_installpath = hoge.installation_path
8
+ narray_include = "#{narray_installpath}/gems/#{narray_fullname}/"
9
+ narray_lib = "#{narray_installpath}/gems/#{narray_fullname}/"
10
+ dir_config('narray',narray_include,narray_lib)
11
+
12
+ dir_config('fftw3','/usr/local')
13
+
14
+ if ( ! ( have_header("narray.h") && have_header("narray_config.h") ) ) then
15
+ print <<-EOS
16
+ ** configure error **
17
+ Header narray.h or narray_config.h is not found. If you have these files in
18
+ /narraydir/include, try the following:
19
+
20
+ % ruby extconf.rb --with-narray-include=/narraydir/include
21
+
22
+ EOS
23
+ exit(-1)
24
+ end
25
+
26
+ if ( ! ( have_header("fftw3.h") && have_library("fftw3") ) ) then
27
+ print <<EOS
28
+ ** configure error **
29
+ Header fftw3.h or the compiled fftw3 library is not found.
30
+ If you have the library installed under /fftw3dir (that is, fftw3.h is
31
+ in /fftw3dir/include and the library in /fftw3dir/lib/),
32
+ try the following:
33
+
34
+ % ruby extconf.rb --with-fftw3-dir=/fftw3dir
35
+
36
+ Alternatively, you can specify the two directory separately
37
+ with --with-fftw3-include and --with-fftw3-lib.
38
+ EOS
39
+ exit(-1)
40
+ end
41
+
42
+ if have_library("fftw3f")
43
+ $CFLAGS += ' -DFFTW3_HAS_SINGLE_SUPPORT'
44
+ end
45
+
46
+ if /cygwin|mingw/ =~ RUBY_PLATFORM
47
+ have_library("narray") || raise("ERROR: narray library is not found")
48
+ end
49
+
50
+ create_makefile("numru/fftw3")
@@ -0,0 +1,285 @@
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
+ }
@@ -0,0 +1,38 @@
1
+ require "numru/fftw3"
2
+ include NumRu
3
+
4
+ print "\n**TEST** all dimensions\n\n"
5
+
6
+ na = NArray.float(8,4).fill(1) # will be corced to complex
7
+ na[1,1]=5
8
+ p na
9
+ fc = FFTW3.fft(na, -1)/na.length
10
+ p fc
11
+ p fc.real
12
+
13
+ p FFTW3.fft(fc, 1).real
14
+
15
+ print "\n**TEST** single float (treated as single if lib fftw3f exits)\n"
16
+ print " --- see http://www.fftw.org/fftw3_doc/Precision.html for more info\n\n"
17
+ na = NArray.sfloat(8,4).indgen!
18
+ fc = FFTW3.fft(na, -1)/na.length
19
+ p fc
20
+ p FFTW3.fft(fc, 1).real
21
+
22
+ print "\n**TEST** dimension selection\n\n"
23
+
24
+ fc = FFTW3.fft(na, -1, 0)/na.shape[0]
25
+ p fc
26
+ p FFTW3.fft(fc, 1, 0).real
27
+ fc = FFTW3.fft(na, -1, 1)/na.shape[1]
28
+ p fc
29
+ p FFTW3.fft(fc, 1, 1).real
30
+
31
+ na = NArray.float(4,3,8,3)
32
+ na[1,1,1,0]= 1
33
+ p( fc=FFTW3.fft(na, -1, 0,2) / (na.shape[0]*na.shape[2]) )
34
+ p( fc=FFTW3.fft(na, -1, 1) / na.shape[1] )
35
+ p( fc=FFTW3.fft(na, -1, 0,1,2) / (na.shape[0]*na.shape[1]*na.shape[2]) )
36
+ p FFTW3.fft(fc, 1, 0,1,2).real
37
+
38
+
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-fftw3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 3517852
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 4a
9
+ version: 0.4a
10
+ platform: ruby
11
+ authors:
12
+ - Takeshi Horinouchi
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-06-28 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: narray
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: Fast Fourier Transforms by using FFTW Ver.3
35
+ email:
36
+ - eriko@gfd-dennou.org
37
+ executables: []
38
+
39
+ extensions:
40
+ - extconf.rb
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - Rakefile
45
+ - LICENSE.txt
46
+ - ChangeLog
47
+ - extconf.rb
48
+ - ToDo
49
+ - na_fftw3.c
50
+ - doc/ruby-fftw3.html
51
+ - doc/ruby-fftw3.rd
52
+ - test/complexFFT.rb
53
+ has_rdoc: true
54
+ homepage: http://www.gfd-dennou.org/arch/ruby/products/ruby-fftw3/
55
+ licenses:
56
+ - Takeshi Horinouchi
57
+ - GFD Dennou Club
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 1
71
+ - 6
72
+ version: "1.6"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">"
77
+ - !ruby/object:Gem::Version
78
+ hash: 25
79
+ segments:
80
+ - 1
81
+ - 3
82
+ - 1
83
+ version: 1.3.1
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.7
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: The Ruby interface of the FFTW (ver 3) library
91
+ test_files: []
92
+