[DRE-commits] [ruby-fftw3] 02/07: Imported Upstream version 1.0.1
Youhei SASAKI
uwabami-guest at moszumanska.debian.org
Thu Jul 21 06:26:34 UTC 2016
This is an automated email from the git hooks/post-receive script.
uwabami-guest pushed a commit to branch master
in repository ruby-fftw3.
commit 51b808f9fc3eac34a6e9f60c1ab96f9ed592cf90
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date: Thu Jul 21 14:41:08 2016 +0900
Imported Upstream version 1.0.1
---
.gitignore | 1 -
ChangeLog | 228 ++++++++++++++++++++++++
LICENSE.txt | 2 +-
Rakefile | 6 +-
doc/ruby-fftw3.html | 116 -------------
doc/ruby-fftw3.rd | 115 -------------
ext/numru/fftw3/extconf.rb | 40 ++++-
ext/numru/fftw3/na_fftw3.c | 421 ++++++++++++++++++++++++++++++++++++++++++++-
lib/numru/fftw3.rb | 109 ++++++++++++
lib/numru/fftw3/version.rb | 2 +-
test/complexFFT.rb | 85 +++++----
test/r2rFFT.rb | 77 +++++++++
12 files changed, 919 insertions(+), 283 deletions(-)
diff --git a/.gitignore b/.gitignore
index 68242b8..cdc8549 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,5 @@
*~
*.so
Makefile
-ChangeLog
/pkg/
/tmp/
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..70af2ac
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,228 @@
+2016-07-16 Takeshi Horinouchi (HEAD, master)
+Updated the numru/narray support
+
+M ext/numru/fftw3/na_fftw3.c
+M lib/numru/fftw3.rb
+
+2016-07-16 Takeshi Horinouchi
+To update to ver. 1.0.1
+
+M lib/numru/fftw3/version.rb
+
+2016-07-16 Takeshi Horinouchi
+Not to ignore ChangeLog
+
+M .gitignore
+
+2016-07-16 Takeshi Horinouchi
+deleted old (unused) part related windows
+
+M ext/numru/fftw3/extconf.rb
+
+2016-07-16 Takeshi Horinouchi (v1.0.0, origin/master, origin/HEAD)
+Updated the year range
+
+M LICENSE.txt
+
+2016-07-16 Takeshi Horinouchi
+deleted old document
+
+D doc/ruby-fftw3.html
+D doc/ruby-fftw3.rd
+
+2016-07-15 Takeshi Horinouchi
+Document slightly updated
+
+M ext/numru/fftw3/na_fftw3.c
+M lib/numru/fftw3.rb
+
+2016-07-15 Takeshi Horinouchi
+Supported NumRu::NArray
+
+M ext/numru/fftw3/extconf.rb
+
+2016-07-15 Takeshi Horinouchi
+Added RDoc document
+
+M ext/numru/fftw3/na_fftw3.c
+M lib/numru/fftw3.rb
+
+2016-07-15 Takeshi Horinouchi
+ceased to create ruby-fftw3-bigmem
+
+M Rakefile
+
+2016-07-02 Takeshi Horinouchi
+to require rubygems if needed
+
+M ext/numru/fftw3/extconf.rb
+
+2015-12-03 Takeshi Horinouchi
+Added new module functions fft_fw and fft_bk for user-friendliness (forward complex FFT with normalization / backward complex FFT)
+
+M lib/numru/fftw3.rb
+M test/complexFFT.rb
+
+2015-12-03 Takeshi Horinouchi
+Updated vergion # to 1.0.0
+
+M lib/numru/fftw3/version.rb
+
+2015-12-03 Takeshi Horinouchi
+Created. (test of real to real FFTs)
+
+A test/r2rFFT.rb
+
+2015-12-03 Takeshi Horinouchi
+Revised to use test/unit
+
+M test/complexFFT.rb
+
+2015-12-03 Takeshi Horinouchi
+Supported real2real FFTs (e.g. sine trans) / Added some constants (e.g. FORWARD)
+
+M ext/numru/fftw3/na_fftw3.c
+
+2015-05-21 Takeshi Horinouchi
+Created gemspec to depend on narray-bigmem
+
+M Rakefile
+M ext/numru/fftw3/extconf.rb
+A ruby-fftw3-bigmem.gemspec
+
+2015-03-31 Eriko Nishimoto (origin/rubygems)
+Modified git ignore list
+
+Added pkg and tmp folder
+
+M .gitignore
+
+2015-03-31 Eriko Nishimoto
+Modified test/complexFFT.rb
+
+* Required rubygems for ruby1.8
+* Required narray for rake test
+
+M test/complexFFT.rb
+
+2015-03-31 Eriko Nishimoto
+Changed lib path for extesion task
+
+To make fftw3.so under numru/fftw3/ directory.
+
+M Rakefile
+
+2015-03-31 Eriko Nishimoto
+Modified extconf.rb
+
+* To search narray.h in gem folder if it is isnstalled by gem
+* To create makefile numru/fftw3/fftw3
+
+M ext/numru/fftw3/extconf.rb
+
+2015-03-31 Eriko Nishimoto
+Moved extensional files to ext/numru/fftw3/
+
+A ext/numru/fftw3/extconf.rb
+A ext/numru/fftw3/na_fftw3.c
+D extconf.rb
+D na_fftw3.c
+
+2015-03-31 Eriko Nishimoto
+Made lib folder
+
+Placed lib/numru/fftw3.rb, which requires lib/numru/fftw3/version.rb and
+ext/numru/fftw3/fftw3.so
+
+A lib/numru/fftw3.rb
+A lib/numru/fftw3/version.rb
+
+2015-03-31 Eriko Nishimoto
+Added setting files for making rubygems
+
+A Gemfile
+A Rakefile
+A ruby-fftw3.gemspec
+
+2015-03-30 Takeshi Horinouchi
+Renamed the current ChangeLog to back up.
+
+A .ChangeLog.until20110419
+D ChangeLog
+
+2015-03-30 Takeshi Horinouchi
+Registered files (patterns) to ignore in the repository
+
+A .gitignore
+
+2011-04-19 Takeshi Horinouchi (ruby-fftw3-0_4)
+ * doc/ruby-fftw3.rd and doc/ruby-fftw3.html : updated
+
+M ChangeLog
+M doc/ruby-fftw3.html
+M doc/ruby-fftw3.rd
+
+2011-04-19 Takeshi Horinouchi
+Tue Apr 19 2011 T Horinouchi
+ * version 0.4 released (cvs tag ruby-fftw3-0_4)
+
+M ChangeLog
+
+2011-04-19 Takeshi Horinouchi
+Tue Apr 19 2011 T Horinouchi
+ * na_fftw3.c: added rb_require("narray"); -- then you do
+ not need to require "narray" separately.
+ * test/complexFFT.rb: removed the first line: require "narray"
+
+M ChangeLog
+M na_fftw3.c
+M test/complexFFT.rb
+
+2011-04-19 Takeshi Horinouchi
+Tue Apr 19 2011 T Horinouchi
+ * LICENSE.txt: changed --> BSD 2-clause license
+
+M ChangeLog
+M LICENSE.txt
+
+2011-04-12 Takeshi Horinouchi
+Tue Apr 12 2011 T Horinouchi
+ * LICENSE.txt: changed
+
+M ChangeLog
+M LICENSE.txt
+
+2011-03-24 Takeshi Horinouchi (ruby-fftw3-0_3)
+Thu Mar 24 2011 T Horinouchi
+ * version 0.3 released (cvs tag ruby-fftw3-0_3)
+ * LICENSE.txt: added
+
+M ChangeLog
+A LICENSE.txt
+
+2004-06-07 Takeshi Horinouchi (ruby-fftw3-0_2)
+*** empty log message ***
+
+D doc/fftw3.html
+D doc/fftw3.rd
+A doc/ruby-fftw3.html
+A doc/ruby-fftw3.rd
+
+2004-06-07 Takeshi Horinouchi
+Mon Jun 7 2004 T Horinouchi < T Koshiro
+ * version 0.2 released (cvs tag ruby-fftw3-0_2)
+ * extconf.rb: improved
+
+M ChangeLog
+M extconf.rb
+
+2004-06-07 Takeshi Horinouchi
+Initial revision
+
+A ChangeLog
+A ToDo
+A doc/fftw3.html
+A doc/fftw3.rd
+A extconf.rb
+A na_fftw3.c
+A test/complexFFT.rb
diff --git a/LICENSE.txt b/LICENSE.txt
index 3552ccb..a5cac98 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,7 +1,7 @@
Ruby-FFTW3 is copyrighted free software by Takeshi Horinouchi and GFD
Dennou Club (http://www.gfd-dennou.org/).
-Copyright 2001 (C) Takeshi Horinouchi and GFD Dennou Club
+Copyright 2001-2016 (C) Takeshi Horinouchi and GFD Dennou Club
(http://www.gfd-dennou.org/) All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/Rakefile b/Rakefile
index 4b0575c..6e5e6d1 100644
--- a/Rakefile
+++ b/Rakefile
@@ -3,11 +3,15 @@ require 'rake/testtask'
require 'rake/extensiontask'
require 'rake/packagetask'
begin
- require 'bundler/gem_tasks'
+ require 'bundler/gem_helper' # instead of 'bundler/gem_tasks' -> need manual
+ # calls of install_tasks (see below)
rescue LoadError
puts 'If you want to create gem, You must install Bundler'
end
+Bundler::GemHelper.install_tasks(name: "ruby-fftw3")
+##Bundler::GemHelper.install_tasks(name: "ruby-fftw3-bigmem")
+
require './lib/numru/fftw3/version.rb'
def version
NumRu::FFTW3::VERSION
diff --git a/doc/ruby-fftw3.html b/doc/ruby-fftw3.html
deleted file mode 100644
index 119534e..0000000
--- a/doc/ruby-fftw3.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>ruby-fftw3.rd</title>
-</head>
-<body>
-<h1><a name="label-0" id="label-0">module NumRu::FFTW3</a></h1><!-- RDLabel: "module NumRu::FFTW3" -->
-<p>Fast Fourier Transforms by using <a href="http://www.fftw.org">FFTW</a> Ver.3.</p>
-<p>Takeshi Horinouchi</p>
-<p>(C) Takeshi Horinouchi / GFD Dennou Club,
-2003</p>
-<p>NO WARRANTY</p>
-<h2><a name="label-1" id="label-1">Features</a></h2><!-- RDLabel: "Features" -->
-<ul>
-<li>Uses <a href="http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray">NArray</a>.</li>
-<li>Multi-dimensional complex FFT. (Real data are coerced to complex).</li>
-<li>Supports both double and single float transforms.</li>
-<li>Not normalized as in FFTW</li>
-</ul>
-<h2><a name="label-2" id="label-2">Features yet to be introduced</a></h2><!-- RDLabel: "Features yet to be introduced" -->
-<ul>
-<li>Sine / cosine transforms</li>
-<li>User choice of optimization levels (i.e., FFTW_MEASURE etc in
- addition to FFTW_ESTIMATE).</li>
-<li>Multi-threaded FFT3 support -- don't know whether it's really feasible.</li>
-</ul>
-<h2><a name="label-3" id="label-3">Installation</a></h2><!-- RDLabel: "Installation" -->
-<ul>
-<li>Install <a href="http://www.fftw.org">FFTW</a> Ver.3.
-<ul>
-<li>NOTE:
- To activate the single-float transform, you have to install FFTW3 with
- the single-float compilation, in addition to the default double-float
- version. This can be done by configuring FFTW3 with
- the --enable-float option, and install it again. The single-float
- version will coexist with the double-float version.
- If you do not install the single-float version, FFT is always done
- with the double precision, which is not bad if you are not time- and
- memory-conscious.</li>
-</ul></li>
-<li>Install <a href="http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray">NArray</a>.</li>
-<li><p>Then, install this library as follows (replace "version" with
- the actual version number):</p>
-<pre>% tar xvzf fftw3-version.tar.gz
-% cd fftw3-version
-% ruby extconf.rb
-% make
-% make site-install</pre>
-<p>Or</p>
-<pre>% make install</pre>
-<p>(If you are using Ruby 1.8, make install is the same make site-install.)</p></li>
-</ul>
-<h2><a name="label-4" id="label-4">How to use</a></h2><!-- RDLabel: "How to use" -->
-<p>See the following peice of code. (Install this library and copy and
-paste the following to the interactive shell irb).</p>
-<pre>require "numru/fftw3"
-include NumRu
-
-na = NArray.float(8,6) # float -> will be corced to complex
-na[1,1]=1
-
-# <example 1>
-fc = FFTW3.fft(na, -1)/na.length # forward 2D FFT and normalization
-nc = FFTW3.fft(fc, 1) # backward 2D FFT (complex) -->
-nb = nc.real # should be equal to na except round errors
-
-# <example 2>
-fc = FFTW3.fft(na, -1, 0) / na.shape[0] # forward FFT with the first dim
-
-# <example 3>
-fc = FFTW3.fft(na, -1, 1) / na.shape[1] # forward FFT with the second dim</pre>
-<h2><a name="label-5" id="label-5">API Reference</a></h2><!-- RDLabel: "API Reference" -->
-<h3><a name="label-6" id="label-6">Module methods</a></h3><!-- RDLabel: "Module methods" -->
-<dl>
-<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" -->
-<dd>
-<p>Complex FFT.</p>
-<p>The 3rd, 4th,... arguments are optional.</p>
-<p>ARGUMENTS</p>
-<ul>
-<li>narray (NArray or NArray-compatible Array) : array to be
- transformed. If real, coerced to complex before transformation.
- If narray is single-precision and the single-precision
- version of FFTW3 is installed (before installing this module),
- this method does a single-precision transform.
- Otherwise, a double-precision transform is used.</li>
-<li>dir (-1 or 1) : forward transform if -1; backward transform if 1.</li>
-<li>optional 3rd, 4th,... arguments (Integer) : Specifies dimensions
- to apply FFT. For example, if 0, the first dimension is
- transformed (1D FFT); If -1, the last dimension is used (1D FFT);
- If 0,2,4, the first, third, and fifth dimensions
- are transformed (3D FFT); If entirely omitted, ALL DIMENSIONS
- ARE SUBJECT TO FFT, so 3D FFT is done with a 3D array.</li>
-</ul>
-<p>RETURN VALUE</p>
-<ul>
-<li>a complex NArray</li>
-</ul>
-<p>NOTE</p>
-<ul>
-<li>As in FFTW, return value is NOT normalized. Thus, a consecutive
- forward and backward transform would multiply the size of
- data used for transform. You can normalize, for example,
- the forward transform FFTW.fft(narray, -1, 0, 1)
- (FFT regarding the first (dim 0) & second (dim 1) dimensions) by
- dividing with (narray.shape[0]*narray.shape[1]). Likewise,
- the result of FFTW.fft(narray, -1) (FFT for all dimensions)
- can be normalized by narray.length.</li>
-</ul></dd>
-</dl>
-
-</body>
-</html>
diff --git a/doc/ruby-fftw3.rd b/doc/ruby-fftw3.rd
deleted file mode 100644
index 226b8e5..0000000
--- a/doc/ruby-fftw3.rd
+++ /dev/null
@@ -1,115 +0,0 @@
-=module NumRu::FFTW3
-
-Fast Fourier Transforms by using ((<FFTW|URL:http://www.fftw.org>)) Ver.3.
-
-Takeshi Horinouchi
-
-(C) Takeshi Horinouchi / GFD Dennou Club,
-2003
-
-NO WARRANTY
-
-==Features
-
-* Uses ((<NArray|URL:http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray>)).
-* Multi-dimensional complex FFT. (Real data are coerced to complex).
-* Supports both double and single float transforms.
-* Not normalized as in FFTW
-
-==Features yet to be introduced
-
-* Sine / cosine transforms
-* User choice of optimization levels (i.e., FFTW_MEASURE etc in
- addition to FFTW_ESTIMATE).
-* Multi-threaded FFT3 support -- don't know whether it's really feasible.
-
-==Installation
-
-* Install ((<FFTW|URL:http://www.fftw.org>)) Ver.3.
-
- * NOTE:
- To activate the single-float transform, you have to install FFTW3 with
- the single-float compilation, in addition to the default double-float
- version. This can be done by configuring FFTW3 with
- the --enable-float option, and install it again. The single-float
- version will coexist with the double-float version.
- If you do not install the single-float version, FFT is always done
- with the double precision, which is not bad if you are not time- and
- memory-conscious.
-
-* Install ((<NArray|URL:http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray>)).
-
-* Then, install this library as follows (replace "version" with
- the actual version number):
-
- % tar xvzf fftw3-version.tar.gz
- % cd fftw3-version
- % ruby extconf.rb
- % make
- % make site-install
- Or
- % make install
- (If you are using Ruby 1.8, make install is the same make site-install.)
-
-==How to use
-
-See the following peice of code. (Install this library and copy and
-paste the following to the interactive shell irb).
-
- require "numru/fftw3"
- include NumRu
-
- na = NArray.float(8,6) # float -> will be corced to complex
- na[1,1]=1
-
- # <example 1>
- fc = FFTW3.fft(na, -1)/na.length # forward 2D FFT and normalization
- nc = FFTW3.fft(fc, 1) # backward 2D FFT (complex) -->
- nb = nc.real # should be equal to na except round errors
-
- # <example 2>
- fc = FFTW3.fft(na, -1, 0) / na.shape[0] # forward FFT with the first dim
-
- # <example 3>
- fc = FFTW3.fft(na, -1, 1) / na.shape[1] # forward FFT with the second dim
-
-==API Reference
-
-===Module methods
-
----fft(narray, dir [,dim,dim,...])
-
- Complex FFT.
-
- The 3rd, 4th,... arguments are optional.
-
- ARGUMENTS
- * narray (NArray or NArray-compatible Array) : array to be
- transformed. If real, coerced to complex before transformation.
- If narray is single-precision and the single-precision
- version of FFTW3 is installed (before installing this module),
- this method does a single-precision transform.
- Otherwise, a double-precision transform is used.
- * dir (-1 or 1) : forward transform if -1; backward transform if 1.
- * optional 3rd, 4th,... arguments (Integer) : Specifies dimensions
- to apply FFT. For example, if 0, the first dimension is
- transformed (1D FFT); If -1, the last dimension is used (1D FFT);
- If 0,2,4, the first, third, and fifth dimensions
- are transformed (3D FFT); If entirely omitted, ALL DIMENSIONS
- ARE SUBJECT TO FFT, so 3D FFT is done with a 3D array.
-
- RETURN VALUE
- * a complex NArray
-
- NOTE
- * As in FFTW, return value is NOT normalized. Thus, a consecutive
- forward and backward transform would multiply the size of
- data used for transform. You can normalize, for example,
- the forward transform FFTW.fft(narray, -1, 0, 1)
- (FFT regarding the first (dim 0) & second (dim 1) dimensions) by
- dividing with (narray.shape[0]*narray.shape[1]). Likewise,
- the result of FFTW.fft(narray, -1) (FFT for all dimensions)
- can be normalized by narray.length.
-
-
-
diff --git a/ext/numru/fftw3/extconf.rb b/ext/numru/fftw3/extconf.rb
index eec092e..fe5835d 100644
--- a/ext/numru/fftw3/extconf.rb
+++ b/ext/numru/fftw3/extconf.rb
@@ -1,12 +1,38 @@
require "mkmf"
+require "rubygems" unless defined?(Gem)
-gem_narray_path=File::dirname(`gem which narray`)
-narray_include=gem_narray_path
-narray_lib=gem_narray_path
-dir_config('narray',narray_include,narray_lib)
-
dir_config('fftw3','/usr/local')
+require "rbconfig"
+so = RbConfig::CONFIG["DLEXT"]
+
+raise("Your gem is too old") unless Gem.respond_to?(:find_files)
+
+env = ENV['NARRAY_TYPE']
+if env == "NArray" || env == "narray"
+ na_type = "narray"
+elsif env == "NumRu::NArray" || env == "numru-narray"
+ na_type = "numru-narray"
+elsif !env.nil?
+ raise "Unsupported value for the environment variable NARRAY_TYPE: #{env}"
+else
+ if Gem.find_files("narray.h").length > 0
+ na_type = "narray"
+ elsif Gem.find_files("numru/narray/narray.h").length > 0
+ na_type = "numru-narray"
+ end
+end
+
+case na_type
+when "narray"
+ narray_include = File.expand_path(File.dirname(Gem.find_files("narray.h")[0]))
+ narray_lib = File.expand_path(File.dirname(Gem.find_files("narray." + so)[0]))
+when "numru-narray"
+ narray_include = File.expand_path(File.dirname(Gem.find_files("numru/narray/narray.h")[0]))
+ narray_lib = File.expand_path(File.dirname(Gem.find_files("numru/narray/narray." + so)[0]))
+end
+
+dir_config('narray', narray_include, narray_lib)
if ( ! ( have_header("narray.h") && have_header("narray_config.h") ) ) then
print <<-EOS
** configure error **
@@ -39,8 +65,4 @@ if have_library("fftw3f")
$CFLAGS += ' -DFFTW3_HAS_SINGLE_SUPPORT'
end
-if /cygwin|mingw/ =~ RUBY_PLATFORM
- have_library("narray") || raise("ERROR: narray library is not found")
-end
-
create_makefile("numru/fftw3/fftw3")
diff --git a/ext/numru/fftw3/na_fftw3.c b/ext/numru/fftw3/na_fftw3.c
index 276dea2..5cf7b7d 100644
--- a/ext/numru/fftw3/na_fftw3.c
+++ b/ext/numru/fftw3/na_fftw3.c
@@ -32,7 +32,7 @@ na_fftw3(int argc, VALUE *argv, VALUE self)
volatile VALUE v1, v2;
if (argc<2){
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
+ rb_raise(rb_eArgError, "Usage: fft(narray, direction [,dim0,dim1,...])");
}
val = argv[0];
vdir = argv[1];
@@ -60,7 +60,7 @@ na_fftw3(int argc, VALUE *argv, VALUE self)
} else {
/* apply FFT to selected dimensions (by using the Guru interface) */
{ /* introduce a new scope for additonal local variables */
- int fft_rank, howmany_rank, ib, j, jf, je, dim;
+ int fft_rank, howmany_rank, j, jf, je, dim;
fftw_iodim *fft_dims, *howmany_dims;
int *dimids;
fft_rank = argc - 2;
@@ -151,7 +151,7 @@ na_fftw3_float(int argc, VALUE *argv, VALUE self)
volatile VALUE v1, v2;
if (argc<2){
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
+ rb_raise(rb_eArgError, "Usage: fft(narray, direction [,dim0,dim1,...])");
}
val = argv[0];
vdir = argv[1];
@@ -179,7 +179,7 @@ na_fftw3_float(int argc, VALUE *argv, VALUE self)
} else {
/* apply FFT to selected dimensions (by using the Guru interface) */
{ /* introduce a new scope for additonal local variables */
- int fft_rank, howmany_rank, ib, j, jf, je, dim;
+ int fft_rank, howmany_rank, j, jf, je, dim;
fftw_iodim *fft_dims, *howmany_dims;
int *dimids;
fft_rank = argc - 2;
@@ -252,6 +252,44 @@ na_fftw3_float(int argc, VALUE *argv, VALUE self)
return v2;
}
+/*
+ * call-seq:
+ * FFTW3.fft(narray, dir [, dim, dim, ...])
+ *
+ * Conducts complex FFT (unnormalized). You can use more user-friendly wrappers
+ * fft_fw and fft_bk.
+ *
+ * ARGUMENTS
+ * * narray (NArray or NArray-compatible Array) : array to be
+ * transformed. If real, coerced to complex before transformation.
+ * If narray is single-precision and the single-precision
+ * version of FFTW3 is installed (before installing this module),
+ * this method does a single-precision transform.
+ * Otherwise, a double-precision transform is used.
+ * * dir (FORWARD (which is simply equal to -1;
+ * referable as NumRu::FFTW3::FORWARD) or BACKWARD
+ * (which is simply 1) ) : the direction of FFT,
+ * forward if FORWARD and backward if BACKWARD.
+ * * optional 3rd, 4th,... arguments (Integer) : Specifies dimensions
+ * to apply FFT. For example, if 0, the first dimension is
+ * transformed (1D FFT); If -1, the last dimension is used (1D FFT);
+ * If 0,2,4, the first, third, and fifth dimensions
+ * are transformed (3D FFT); If entirely omitted, ALL DIMENSIONS
+ * ARE SUBJECT TO FFT, so 3D FFT is done with a 3D array.
+ *
+ * RETURN VALUE
+ * * a complex NArray
+ *
+ * NOTE
+ * * As in FFTW, return value is NOT normalized. Thus, a consecutive
+ * forward and backward transform would multiply the size of
+ * data used for transform. You can normalize, for example,
+ * the forward transform FFTW.fft(narray, -1, 0, 1)
+ * (FFT regarding the first (dim 0) & second (dim 1) dimensions) by
+ * dividing with (narray.shape[0]*narray.shape[1]). Likewise,
+ * the result of FFTW.fft(narray, -1) (FFT for all dimensions)
+ * can be normalized by narray.length.
+ */
static VALUE
na_fftw3(int argc, VALUE *argv, VALUE self)
{
@@ -260,7 +298,7 @@ na_fftw3(int argc, VALUE *argv, VALUE self)
struct NARRAY *a1;
if (argc<2){
- rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])");
+ rb_raise(rb_eArgError, "Usage: fft(narray, direction [,dim0,dim1,...])");
}
val = argv[0];
v1 = na_to_narray(val);
@@ -275,11 +313,382 @@ na_fftw3(int argc, VALUE *argv, VALUE self)
#endif
+static VALUE
+#ifdef FFTW3_HAS_SINGLE_SUPPORT
+na_fftw3_r2r_double(int argc, VALUE *argv, VALUE self)
+ /* to be called by na_fftw3_r2r */
+#else
+na_fftw3_r2r(int argc, VALUE *argv, VALUE self)
+ /* to be called directly */
+#endif
+{
+ VALUE val, vkinds;
+ struct NARRAY *a1, *a2;
+ int i, *shape, *bucket, len;
+ fftw_r2r_kind *kinds;
+ fftw_plan p;
+ double *in, *out;
+ volatile VALUE v1, v2;
+
+ if (argc<2){
+ rb_raise(rb_eArgError, "Usage: fft_r2r(narray, kinds [,dim0,dim1,...])");
+ }
+ val = argv[0];
+ vkinds = argv[1];
+
+ v1 = na_cast_object(val, NA_DFLOAT);
+ GetNArray(v1,a1);
+ v2 = na_make_object( NA_DFLOAT, a1->rank, a1->shape, CLASS_OF(v1) );
+ GetNArray(v2,a2);
+
+ shape = ALLOCA_N(int, a2->rank);
+ for (i=0; i<a2->rank; i++){
+ shape[i] = a2->shape[a2->rank-1-i];
+ }
+ in = (double*)a1->ptr;
+ out = (double*)a2->ptr;
+
+ switch (TYPE(vkinds)) {
+ case T_ARRAY:
+ len = RARRAY_LEN(vkinds);
+ kinds = ALLOCA_N(fftw_r2r_kind, len);
+ for (i = 0; i < len; i++) {
+ kinds[i] = NUM2INT(RARRAY_PTR(vkinds)[len-1-i]);//column- to row-major
+ }
+ break;
+ case T_FIXNUM:
+ if (argc == 2) {
+ len = a1->rank;
+ } else {
+ len = argc-2;
+ }
+ kinds = ALLOCA_N(fftw_r2r_kind, len);
+ for (i = 0; i < len; i++) {
+ kinds[i] = NUM2INT(vkinds);
+ }
+ break;
+ default:
+ rb_raise(rb_eTypeError, "unsupported kinds type");
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ if ( kinds[i] < FFTW_R2HC || kinds[i] > FFTW_RODFT11 ){
+ rb_raise(rb_eArgError, "unsupported kind (%d).", kinds[i]);
+ }
+ }
+
+ if (argc==2) {
+ /* apply FFT to all dimensions */
+ p = fftw_plan_r2r( a2->rank, shape,
+ in, out, kinds, FFTW_ESTIMATE );
+ } else {
+ /* apply FFT to selected dimensions (by using the Guru interface) */
+ { /* introduce a new scope for additonal local variables */
+ int fft_rank, howmany_rank, j, jf, je, dim;
+ fftw_iodim *fft_dims, *howmany_dims;
+ int *dimids;
+ fft_rank = argc - 2;
+ fft_dims = ALLOCA_N(fftw_iodim, fft_rank);
+ dimids = ALLOCA_N(int, fft_rank);
+ howmany_rank = fft_rank + 1;
+ howmany_dims = ALLOCA_N(fftw_iodim, howmany_rank);
+
+ for (i=2;i<argc;i++){
+ dim = NUM2INT(argv[i]);
+ if (dim<0) dim += a2->rank; /* negative: count from the end */
+ if (dim<0 || dim>=a2->rank){
+ rb_raise(rb_eArgError, "dimension < 0 or >= rank");
+ }
+ dimids[i-2] = a2->rank - 1 - dim;
+ if ( i>2 && dimids[i-2] == dimids[i-3] ){
+ rb_raise(rb_eArgError, "redundant -- a same dimension is reppeated");
+ }
+ }
+
+ /* bukcet sort in increasing order */
+ bucket = ALLOCA_N(int,a2->rank);
+ for(j=0; j<a2->rank; j++) bucket[j] = 0; /* initialize */
+ for(i=0; i<fft_rank; i++) bucket[ dimids[i] ] = 1;
+ for(j=0,i=0; j<a2->rank; j++) {
+ if (bucket[j]==1){
+ dimids[i] = j;
+ i++;
+ }
+ }
+
+ for(j=0; j<fft_rank; j++){
+ fft_dims[j].n = shape[ dimids[j] ];
+ fft_dims[j].is = 1;
+ for (i=dimids[j]+1 ; i<a2->rank ; i++){
+ fft_dims[j].is *= shape[i];
+ }
+ fft_dims[j].os = fft_dims[j].is;
+ /* printf("fft_ %d n:%d is:%d\n",j,
+ fft_dims[j].n,fft_dims[j].is);*/
+ }
+ for(j=0; j<=fft_rank; j++){
+ howmany_dims[j].n = 1;
+ jf = (j==0) ? 0 : (dimids[j-1]+1) ;
+ je = (j==fft_rank) ? a2->rank : (dimids[j]) ;
+ for (i=jf; i<je; i++){
+ howmany_dims[j].n *= shape[i];
+ }
+ howmany_dims[j].is = 1;
+ if (j<fft_rank){
+ for (i=dimids[j]; i<a2->rank; i++){
+ howmany_dims[j].is *= shape[i];
+ }
+ }
+ howmany_dims[j].os = howmany_dims[j].is;
+ /* printf("how_ %d n:%d is:%d\n",j,
+ howmany_dims[j].n,howmany_dims[j].is); */
+ }
+
+ p = fftw_plan_guru_r2r( fft_rank, fft_dims,
+ howmany_rank, howmany_dims,
+ in, out, kinds, FFTW_ESTIMATE );
+
+ }
+ }
+
+ fftw_execute(p);
+ fftw_destroy_plan(p);
+
+ return v2;
+}
+
+static VALUE
+#ifdef FFTW3_HAS_SINGLE_SUPPORT
+na_fftw3_r2r_float(int argc, VALUE *argv, VALUE self)
+ /* to be called by na_fftw3_r2r */
+{
+ VALUE val, vkinds;
+ struct NARRAY *a1, *a2;
+ int i, *shape, *bucket, len;
+ fftwf_r2r_kind *kinds;
+ fftwf_plan p;
+ float *in, *out;
+ volatile VALUE v1, v2;
+
+ if (argc<2){
+ rb_raise(rb_eArgError, "Usage: fft_r2r(narray, kinds [,dim0,dim1,...])");
+ }
+ val = argv[0];
+ vkinds = argv[1];
+
+ v1 = na_cast_object(val, NA_SFLOAT);
+ GetNArray(v1,a1);
+ v2 = na_make_object( NA_SFLOAT, a1->rank, a1->shape, CLASS_OF(v1) );
+ GetNArray(v2,a2);
+
+ shape = ALLOCA_N(int, a2->rank);
+ for (i=0; i<a2->rank; i++){
+ shape[i] = a2->shape[a2->rank-1-i];
+ }
+ in = (float*)a1->ptr;
+ out = (float*)a2->ptr;
+
+ switch (TYPE(vkinds)) {
+ case T_ARRAY:
+ len = RARRAY_LEN(vkinds);
+ kinds = ALLOCA_N(fftwf_r2r_kind, len);
+ for (i = 0; i < len; i++) {
+ kinds[i] = NUM2INT(RARRAY_PTR(vkinds)[len-1-i]);//column- to row-major
+ }
+ break;
+ case T_FIXNUM:
+ if (argc == 2) {
+ len = a1->rank;
+ } else {
+ len = argc-2;
+ }
+ kinds = ALLOCA_N(fftwf_r2r_kind, len);
+ for (i = 0; i < len; i++) {
+ kinds[i] = NUM2INT(vkinds);
+ }
+ break;
+ default:
+ rb_raise(rb_eTypeError, "unsupported kinds type");
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ if ( kinds[i] < FFTW_R2HC || kinds[i] > FFTW_RODFT11 ){
+ rb_raise(rb_eArgError, "unsupported kind (%d).", kinds[i]);
+ }
+ }
+
+ if (argc==2) {
+ /* apply FFT to all dimensions */
+ p = fftwf_plan_r2r( a2->rank, shape,
+ in, out, kinds, FFTW_ESTIMATE );
+ } else {
+ /* apply FFT to selected dimensions (by using the Guru interface) */
+ { /* introduce a new scope for additonal local variables */
+ int fft_rank, howmany_rank, j, jf, je, dim;
+ fftwf_iodim *fft_dims, *howmany_dims;
+ int *dimids;
+ fft_rank = argc - 2;
+ fft_dims = ALLOCA_N(fftwf_iodim, fft_rank);
+ dimids = ALLOCA_N(int, fft_rank);
+ howmany_rank = fft_rank + 1;
+ howmany_dims = ALLOCA_N(fftwf_iodim, howmany_rank);
+
+ for (i=2;i<argc;i++){
+ dim = NUM2INT(argv[i]);
+ if (dim<0) dim += a2->rank; /* negative: count from the end */
+ if (dim<0 || dim>=a2->rank){
+ rb_raise(rb_eArgError, "dimension < 0 or >= rank");
+ }
+ dimids[i-2] = a2->rank - 1 - dim;
+ if ( i>2 && dimids[i-2] == dimids[i-3] ){
+ rb_raise(rb_eArgError, "redundant -- a same dimension is reppeated");
+ }
+ }
+
+ /* bukcet sort in increasing order */
+ bucket = ALLOCA_N(int,a2->rank);
+ for(j=0; j<a2->rank; j++) bucket[j] = 0; /* initialize */
+ for(i=0; i<fft_rank; i++) bucket[ dimids[i] ] = 1;
+ for(j=0,i=0; j<a2->rank; j++) {
+ if (bucket[j]==1){
+ dimids[i] = j;
+ i++;
+ }
+ }
+
+ for(j=0; j<fft_rank; j++){
+ fft_dims[j].n = shape[ dimids[j] ];
+ fft_dims[j].is = 1;
+ for (i=dimids[j]+1 ; i<a2->rank ; i++){
+ fft_dims[j].is *= shape[i];
+ }
+ fft_dims[j].os = fft_dims[j].is;
+ /* printf("fft_ %d n:%d is:%d\n",j,
+ fft_dims[j].n,fft_dims[j].is);*/
+ }
+ for(j=0; j<=fft_rank; j++){
+ howmany_dims[j].n = 1;
+ jf = (j==0) ? 0 : (dimids[j-1]+1) ;
+ je = (j==fft_rank) ? a2->rank : (dimids[j]) ;
+ for (i=jf; i<je; i++){
+ howmany_dims[j].n *= shape[i];
+ }
+ howmany_dims[j].is = 1;
+ if (j<fft_rank){
+ for (i=dimids[j]; i<a2->rank; i++){
+ howmany_dims[j].is *= shape[i];
+ }
+ }
+ howmany_dims[j].os = howmany_dims[j].is;
+ /* printf("how_ %d n:%d is:%d\n",j,
+ howmany_dims[j].n,howmany_dims[j].is); */
+ }
+
+ p = fftwf_plan_guru_r2r( fft_rank, fft_dims,
+ howmany_rank, howmany_dims,
+ in, out, kinds, FFTW_ESTIMATE );
+
+ }
+ }
+
+ fftwf_execute(p);
+ fftwf_destroy_plan(p);
+
+ return v2;
+}
+
+/*
+ * call-seq:
+ * FFTW3.fft_r2r(narray, kind [, dim, dim, ...])
+ *
+ * Conducts real FFT (unnormalized).
+ *
+ * ARGUMENTS
+ * * narray (NArray or NArray-compatible Array) : array to be
+ * transformed. Cannot be complex.
+ * * kind : specifies the kind of FFT. One of the following:
+ * R2HC, HC2R, DHT, REDFT00, REDFT01, REDFT10, REDFT11, RODFT00, RODFT01,
+ * RODFT10, or RODFT11 (referable as NumRu::FFTW3::REDFT10). See Ch.2 of
+ * http://www.fftw.org/fftw3_doc/ (http://www.fftw.org/fftw3.pdf).
+ * * optional 3rd, 4th,... arguments (Integer) : See FFTW3.fft.
+ *
+ *
+ * RETURN VALUE
+ * * a real NArray
+ *
+ * NOTE
+ * * As in FFTW, return value is NOT normalized, and the length needed
+ * normalize is different for each kind.
+ */
+static VALUE
+na_fftw3_r2r(int argc, VALUE *argv, VALUE self)
+{
+ VALUE val;
+ volatile VALUE v1;
+ struct NARRAY *a1;
+
+ if (argc<2){
+ rb_raise(rb_eArgError, "Usage: fft_r2r(narray, kinds [,dim0,dim1,...])");
+ }
+ val = argv[0];
+ v1 = na_to_narray(val);
+ GetNArray(v1,a1);
+ if(a1->type <= NA_SFLOAT || a1->type == NA_SCOMPLEX ){
+ return( na_fftw3_r2r_float(argc, argv, self) );
+ } else {
+ return( na_fftw3_r2r_double(argc, argv, self) );
+ }
+
+}
+
+#endif
+
void
Init_fftw3()
{
- rb_require("narray");
mNumRu = rb_define_module("NumRu");
rb_mFFTW3 = rb_define_module_under(mNumRu, "FFTW3");
rb_define_module_function(rb_mFFTW3, "fft", na_fftw3, -1);
+ rb_define_module_function(rb_mFFTW3, "fft_r2r", na_fftw3_r2r, -1);
+ /* Specifier of forward complex FFT. Integer equal to -1. */
+#ifdef NARRAY_BIGMEM
+ rb_define_const(rb_mFFTW3, "SUPPORT_BIGMEM", Qtrue);
+#else
+ rb_define_const(rb_mFFTW3, "SUPPORT_BIGMEM", Qfalse);
+#endif
+ rb_define_const(rb_mFFTW3, "FORWARD", INT2NUM(FFTW_FORWARD));
+ /* Specifier of backward complex FFT. Integer equal to 1. */
+ rb_define_const(rb_mFFTW3, "BACKWARD", INT2NUM(FFTW_BACKWARD));
+ /* Specifier of real FFT kind. real to "halfcomplex" */
+ rb_define_const(rb_mFFTW3, "R2HC", INT2NUM(FFTW_R2HC));
+ /* Specifier of real FFT kind. "halfcomplex" to real */
+ rb_define_const(rb_mFFTW3, "HC2R", INT2NUM(FFTW_HC2R));
+ /* Specifier of real FFT kind. Discrete Hartley Transform */
+ rb_define_const(rb_mFFTW3, "DHT", INT2NUM(FFTW_DHT));
+ /* Specifier of real FFT kind. cosine (even) transform;
+ logical data length 2*(n-1); inverse is itself */
+ rb_define_const(rb_mFFTW3, "REDFT00", INT2NUM(FFTW_REDFT00));
+ /* Specifier of real FFT kind. cosine (even) transform;
+ * logical data length 2*n; inverse is REDFT10 */
+ rb_define_const(rb_mFFTW3, "REDFT01", INT2NUM(FFTW_REDFT01));
+ /* Specifier of real FFT kind. cosine (even) transform;
+ * logical data length 2*n; inverse is REDFT01 */
+ rb_define_const(rb_mFFTW3, "REDFT10", INT2NUM(FFTW_REDFT10));
+ /* Specifier of real FFT kind. cosine (even) transform;
+ * logical data length 2*n; inverse is itself */
+ rb_define_const(rb_mFFTW3, "REDFT11", INT2NUM(FFTW_REDFT11));
+ /* Specifier of real FFT kind. sine (odd) transform;
+ * logical data length 2*(n+1); inverse is itself */
+ rb_define_const(rb_mFFTW3, "RODFT00", INT2NUM(FFTW_RODFT00));
+ /* Specifier of real FFT kind. sine (odd) transform;
+ * logical data length 2*n; inverse is RODFT10 */
+ rb_define_const(rb_mFFTW3, "RODFT01", INT2NUM(FFTW_RODFT01));
+ /* Specifier of real FFT kind. sine (odd) transform;
+ * logical data length 2*n; inverse is RODFT01 */
+ rb_define_const(rb_mFFTW3, "RODFT10", INT2NUM(FFTW_RODFT10));
+ /* Specifier of real FFT kind. sine (odd) transform;
+ * logical data length 2*n; inverse is itself */
+ rb_define_const(rb_mFFTW3, "RODFT11", INT2NUM(FFTW_RODFT11));
}
diff --git a/lib/numru/fftw3.rb b/lib/numru/fftw3.rb
index 84f48bb..2ced096 100644
--- a/lib/numru/fftw3.rb
+++ b/lib/numru/fftw3.rb
@@ -6,3 +6,112 @@ end
require "numru/fftw3/version"
require "numru/fftw3/fftw3"
+if NumRu::FFTW3::SUPPORT_BIGMEM
+ if Object.const_defined?(:NArray)
+ raise "Incompatibility found. The loaded NumRu::FFTW3 was compiled to " +
+ "use NumRu::NArray, but here NArray has already been loaded."
+ end
+ require("numru/narray");
+else
+ if ( RUBY_VERSION>="1.9" ? NumRu.const_defined?(:NArray,false) :
+ NumRu.const_defined?(:NArray) )
+ raise "Incompatibility found. The loaded NumRu::FFTW3 was compiled to " +
+ "use NArray, but here NumRu::NArray has already been loaded."
+ end
+ require("narray");
+end
+
+module NumRu
+
+ # Ruby wrapper of FFTW3, a fast discrete Fourier transform library. http://www.fftw.org
+ #
+ # ==Features
+ #
+ # * Uses NArray (https://github.com/masa16/narray). (Also it supports
+ # NumRu::NArray as well, if this library is compiled to use it).
+ # * Multi-dimensional complex and real FFT.
+ # * Supports both double and single float transforms.
+ #
+ # ==How to use
+ #
+ # Copy and paste the following code line-by-line using irb.
+ # Or you can run it by saving it in a file fftw3test.rb (say)
+ # and executing "ruby fftw3test.rb".
+ #
+ # require "numru/fftw3"
+ # include NumRu
+ #
+ # na = NArray.float(8,6) # float -> will be coerced to complex
+ # na[1,1]=1
+ #
+ # # <example 1: complex FFT on all dimensions >
+ #
+ # fc = FFTW3.fft(na, FFTW3::FORWARD)/na.length # forward 2D FFT and normalization
+ # nc = FFTW3.fft(fc, FFTW3::BACKWARD) # backward 2D FFT (complex) -->
+ # nb = nc.real # should be equal to na except round errors
+ # p (nb - na).abs.max # => 8.970743058303247e-17 (sufficiently small)
+ #
+ # # <example 2: complex FFT on all dimensions >
+ # # Same as example 1 but using more user-friendly wrapper of FFTW3.fft
+ #
+ # fc = FFTW3.fft_fw(na) # forward 2D FFT and normalization
+ # nc = FFTW3.fft_bk(fc) # backward 2D FFT (complex) -->
+ # nb = nc.real # should be equal to na except round errors
+ # p (nb - na).abs.max # => 8.970743058303247e-17 (sufficiently small)
+ #
+ # # <example 3: complex FFT along a dimension >
+ # fc = FFTW3.fft_fw(na, 0) # forward 1D FFT along the first dim
+ # nc = FFTW3.fft_bk(fc, 0) # backward 1D FFT along the first dim
+ # p (nc.real - na).abs.max # => 1.1102230246251565e-16 (sufficiently small)
+ #
+ # # <example 4: complex FFT along a dimension >
+ # fc = FFTW3.fft_fw(na, 1) # forward 1D FFT along the second dim
+ #
+ # # <example 5: real FFT along a dimension >
+ #
+ # fc = FFTW3.fft_r2r(na, FFTW3::RODFT00, 0) # not normalized sine transform along the 1st dim
+ # len = 2*(na.shape[0]+1) # this is the supposed length of this transformation
+ # nc = FFTW3.fft_r2r(fc/len, FFTW3::RODFT00, 0) # forward==backward transformation
+ # p (nc-na).abs.max # => 2.220446049250313e-16 (sufficiently small)
+ #
+ # # <example 5b: real FFT on all dimensions >
+ #
+ # fc = FFTW3.fft_r2r(na, FFTW3::REDFT11) # unnormalized cosine transform
+ # len = 4*na.length # from (2*na.shape[0]) * (2*na.shape[1])
+ # nc = FFTW3.fft_r2r(fc/len, FFTW3::REDFT11) # forward==backward transformation
+ # p (nc-na).abs.max # => 6.228190483314256e-17 (sufficiently small)
+ #
+ # See the FFTW3 manual for the kinds of supported real FFTs. See Ch.2 of
+ # http://www.fftw.org/fftw3_doc/ (http://www.fftw.org/fftw3.pdf).
+ # Virtually all kinds are supported!
+ #
+ module FFTW3
+
+ module_function
+
+ # Forward complex FFT with normalization
+ #
+ # This calls FFW3.fft(na, FFW3::FORWARD, *dims) and normalizes the result
+ # by dividing by the length
+ #
+ def fft_fw(na, *dims)
+ fc = fft(na, FORWARD, *dims)
+ if dims.length == 0
+ len = na.total
+ else
+ len = 1
+ shape = na.shape
+ dims.each{|d| len *= shape[d]}
+ end
+ fc / len
+ end
+
+ # Backward complex FFT
+ #
+ # This method simply calls FFW3.fft(na, FFW3::BACKWARD, *dims)
+ #
+ def fft_bk(na, *dims)
+ fft(na, BACKWARD, *dims)
+ end
+ end
+end
diff --git a/lib/numru/fftw3/version.rb b/lib/numru/fftw3/version.rb
index 775d97e..4fb22fe 100644
--- a/lib/numru/fftw3/version.rb
+++ b/lib/numru/fftw3/version.rb
@@ -1,5 +1,5 @@
module NumRu
module FFTW3
- VERSION = "0.4.2"
+ VERSION = "1.0.1"
end
end
diff --git a/test/complexFFT.rb b/test/complexFFT.rb
index e8dde6d..9875bce 100644
--- a/test/complexFFT.rb
+++ b/test/complexFFT.rb
@@ -4,40 +4,59 @@ rescue LoadError
end
require "narray" # This line is needed for rake test when making a gem package.
require "numru/fftw3"
+require "test/unit"
include NumRu
-print "\n**TEST** all dimensions\n\n"
-
-na = NArray.float(8,4).fill(1) # will be corced to complex
-na[1,1]=5
-p na
-fc = FFTW3.fft(na, -1)/na.length
-p fc
-p fc.real
-
-p FFTW3.fft(fc, 1).real
-
-print "\n**TEST** single float (treated as single if lib fftw3f exits)\n"
-print " --- see http://www.fftw.org/fftw3_doc/Precision.html for more info\n\n"
-na = NArray.sfloat(8,4).indgen!
-fc = FFTW3.fft(na, -1)/na.length
-p fc
-p FFTW3.fft(fc, 1).real
-
-print "\n**TEST** dimension selection\n\n"
-
-fc = FFTW3.fft(na, -1, 0)/na.shape[0]
-p fc
-p FFTW3.fft(fc, 1, 0).real
-fc = FFTW3.fft(na, -1, 1)/na.shape[1]
-p fc
-p FFTW3.fft(fc, 1, 1).real
-
-na = NArray.float(4,3,8,3)
-na[1,1,1,0]= 1
-p( fc=FFTW3.fft(na, -1, 0,2) / (na.shape[0]*na.shape[2]) )
-p( fc=FFTW3.fft(na, -1, 1) / na.shape[1] )
-p( fc=FFTW3.fft(na, -1, 0,1,2) / (na.shape[0]*na.shape[1]*na.shape[2]) )
-p FFTW3.fft(fc, 1, 0,1,2).real
+class FFTW3Test < Test::Unit::TestCase
+ def setup
+ @eps = 1e-10
+ @seps = 1e-6
+ end
+
+ def test_fft_fw_bk
+ na = NArray.float(8,4).fill(1) # will be corced to complex
+ na[1,1]=5
+ fc = FFTW3.fft_fw(na)
+ nb = FFTW3.fft_bk(fc).real
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_fw(na,1)
+ nb = FFTW3.fft_bk(fc,1).real
+ assert( (na-nb).abs.max < @eps )
+ end
+
+ def test_real_all_dims
+ na = NArray.float(8,4).fill(1) # will be corced to complex
+ na[1,1]=5
+ fc = FFTW3.fft(na, FFTW3::FORWARD)/na.length
+ nb = FFTW3.fft(fc, FFTW3::BACKWARD).real
+ assert( (na-nb).abs.max < @eps )
+ end
+
+ def test_complex_all_dims
+ na = NArray.complex(8,4).fill(1) * Complex::I
+ na[1,1]=5
+ fc = FFTW3.fft(na, -1)/na.length
+ nb = FFTW3.fft(fc, 1)
+ assert( (na-nb).abs.max < @eps )
+ end
+
+ def test_dim_selection
+ na = NArray.float(8,4).indgen!
+ fc = FFTW3.fft(na, FFTW3::FORWARD, 0)
+ fc = FFTW3.fft(fc, FFTW3::FORWARD, 1)
+ fc2 = FFTW3.fft(na, FFTW3::FORWARD)
+ assert( (fc-fc2).abs.max < @eps )
+ end
+
+ # TEST: single float (treated as single if lib fftw3f exits).
+ # see http://www.fftw.org/fftw3_doc/Precision.html for more info
+ def test_single_float
+ na = NArray.sfloat(8,4).indgen!
+ fc = FFTW3.fft(na, -1)/na.length
+ nb = FFTW3.fft(fc, 1).real
+ assert( (na-nb).abs.max < @seps )
+ end
+end
diff --git a/test/r2rFFT.rb b/test/r2rFFT.rb
new file mode 100644
index 0000000..96954a0
--- /dev/null
+++ b/test/r2rFFT.rb
@@ -0,0 +1,77 @@
+require "narray" # This line is needed for rake test when making a gem package.
+require "numru/fftw3"
+require "test/unit"
+include NumRu
+
+class FFTW3_R2R_Test < Test::Unit::TestCase
+ def setup
+ @eps = 1e-10
+ @seps = 1e-5
+ end
+
+ def test_r2r_all_dims
+ nx = 8
+ ny = 4
+ na = NArray.float(nx,ny).indgen!
+
+ fc = FFTW3.fft_r2r(na, FFTW3::REDFT00) # cosine trans at 0, 1, 2,...
+ c = 1.0 / (2*(nx-1)) / (2*(ny-1))
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::REDFT00)
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(na, FFTW3::REDFT11) # cosine trans at 1/2, 1+1/2,...
+ c = 1.0 / (2*nx) / (2*ny)
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::REDFT11)
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(na, FFTW3::REDFT01)
+ c = 1.0 / (2*nx) / (2*ny)
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::REDFT10)
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(na, FFTW3::RODFT00) # sine trans at 1, 2,...
+ c = 1.0 / (2*(nx+1)) / (2*(ny+1))
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::RODFT00)
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(na, FFTW3::RODFT11) # sine trans at 1/2, 1+1/2,...
+ c = 1.0 / (2*nx) / (2*ny)
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::RODFT11)
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(na, FFTW3::RODFT01) # sine trans
+ c = 1.0 / (2*nx) / (2*ny)
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::RODFT10)
+ assert( (na-nb).abs.max < @eps )
+
+ end
+
+ def test_r2r_sigle
+ nx = 8
+ ny = 4
+ na = NArray.sfloat(nx,ny).indgen!
+
+ fc = FFTW3.fft_r2r(na, FFTW3::REDFT00) # cosine trans at 0, 1, 2,...
+ c = 1.0 / (2*(nx-1)) / (2*(ny-1))
+ nb = FFTW3.fft_r2r(fc*c, FFTW3::REDFT00)
+ assert( (na-nb).abs.max < @seps )
+ end
+
+
+ def test_r2r_some_dims
+ nx = 8
+ ny = 4
+ na = NArray.float(nx,ny).indgen!
+
+ fc = FFTW3.fft_r2r(na, FFTW3::REDFT00, 0)
+ nb = FFTW3.fft_r2r(fc, FFTW3::REDFT00, 0) / (2*(nx-1))
+ assert( (na-nb).abs.max < @eps )
+
+ fc = FFTW3.fft_r2r(fc, FFTW3::RODFT11, 1)
+ fc2 = FFTW3.fft_r2r(na, [FFTW3::REDFT00, FFTW3::RODFT11])
+ fc3 = FFTW3.fft_r2r(na, [FFTW3::REDFT00, FFTW3::RODFT11], 0, 1)
+ assert( (fc-fc2).abs.max < @eps )
+ assert( (fc-fc3).abs.max < @eps )
+ end
+
+end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-fftw3.git
More information about the Pkg-ruby-extras-commits
mailing list