Module: NumRu::FFTW3
- Defined in:
- lib/numru/fftw3.rb,
lib/numru/fftw3/version.rb,
ext/numru/fftw3/na_fftw3.c
Overview
Ruby wrapper of FFTW3, a fast discrete Fourier transform library. www.fftw.org
Features
-
Uses NArray (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 www.fftw.org/fftw3_doc/ (www.fftw.org/fftw3.pdf). Virtually all kinds are supported!
Constant Summary collapse
- VERSION =
"1.0.2"
- SUPPORT_BIGMEM =
Qfalse
- FORWARD =
INT2NUM(FFTW_FORWARD)
- BACKWARD =
Specifier of backward complex FFT. Integer equal to 1.
INT2NUM(FFTW_BACKWARD)
- R2HC =
Specifier of real FFT kind. real to “halfcomplex”
INT2NUM(FFTW_R2HC)
- HC2R =
Specifier of real FFT kind. “halfcomplex” to real
INT2NUM(FFTW_HC2R)
- DHT =
Specifier of real FFT kind. Discrete Hartley Transform
INT2NUM(FFTW_DHT)
- REDFT00 =
Specifier of real FFT kind. cosine (even) transform;
logical data length 2*(n-1); inverse is itself
INT2NUM(FFTW_REDFT00)
- REDFT01 =
Specifier of real FFT kind. cosine (even) transform; logical data length 2*n; inverse is REDFT10
INT2NUM(FFTW_REDFT01)
- REDFT10 =
Specifier of real FFT kind. cosine (even) transform; logical data length 2*n; inverse is REDFT01
INT2NUM(FFTW_REDFT10)
- REDFT11 =
Specifier of real FFT kind. cosine (even) transform; logical data length 2*n; inverse is itself
INT2NUM(FFTW_REDFT11)
- RODFT00 =
Specifier of real FFT kind. sine (odd) transform; logical data length 2*(n+1); inverse is itself
INT2NUM(FFTW_RODFT00)
- RODFT01 =
Specifier of real FFT kind. sine (odd) transform; logical data length 2*n; inverse is RODFT10
INT2NUM(FFTW_RODFT01)
- RODFT10 =
Specifier of real FFT kind. sine (odd) transform; logical data length 2*n; inverse is RODFT01
INT2NUM(FFTW_RODFT10)
- RODFT11 =
Specifier of real FFT kind. sine (odd) transform; logical data length 2*n; inverse is itself
INT2NUM(FFTW_RODFT11)
Class Method Summary collapse
-
.fft(narray, dir[, dim, dim, ...]) ⇒ Object
Conducts complex FFT (unnormalized).
-
.fft_bk(na, *dims) ⇒ Object
Backward complex FFT.
-
.fft_fw(na, *dims) ⇒ Object
Forward complex FFT with normalization.
-
.fft_r2r(narray, kind[, dim, dim, ...]) ⇒ Object
Conducts real FFT (unnormalized).
Class Method Details
.fft(narray, dir[, dim, dim, ...]) ⇒ Object
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*narray.shape). Likewise, the result of FFTW.fft(narray, -1) (FFT for all dimensions) can be normalized by narray.length.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'ext/numru/fftw3/na_fftw3.c', line 293
static VALUE
na_fftw3(int argc, VALUE *argv, VALUE self)
{
VALUE val;
volatile VALUE v1;
struct NARRAY *a1;
if (argc<2){
rb_raise(rb_eArgError, "Usage: fft(narray, direction [,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_float(argc, argv, self) );
} else {
return( na_fftw3_double(argc, argv, self) );
}
}
|
.fft_bk(na, *dims) ⇒ Object
Backward complex FFT
This method simply calls FFW3.fft(na, FFW3::BACKWARD, *dims)
113 114 115 |
# File 'lib/numru/fftw3.rb', line 113 def fft_bk(na, *dims) fft(na, BACKWARD, *dims) end |
.fft_fw(na, *dims) ⇒ Object
Forward complex FFT with normalization
This calls FFW3.fft(na, FFW3::FORWARD, *dims) and normalizes the result by dividing by the length
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/numru/fftw3.rb', line 97 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 |
.fft_r2r(narray, kind[, dim, dim, ...]) ⇒ Object
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 www.fftw.org/fftw3_doc/ (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.
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'ext/numru/fftw3/na_fftw3.c', line 625
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) );
}
}
|