ruby-fftw3-0.4.2/0000755000175000017500000000000012526316447014037 5ustar horinouthorinoutruby-fftw3-0.4.2/ToDo0000644000175000017500000000017112506141700014610 0ustar horinouthorinout2003/11/18 * enable users to choose FFTW_MEASURE etc * support real-to-real tranforms (esp. sine and cosine transforms) ruby-fftw3-0.4.2/lib/0000755000175000017500000000000012526316447014605 5ustar horinouthorinoutruby-fftw3-0.4.2/lib/numru/0000755000175000017500000000000012526316447015753 5ustar horinouthorinoutruby-fftw3-0.4.2/lib/numru/fftw3/0000755000175000017500000000000012526316447017004 5ustar horinouthorinoutruby-fftw3-0.4.2/lib/numru/fftw3/version.rb0000644000175000017500000000007412507177171021015 0ustar horinouthorinoutmodule NumRu module FFTW3 VERSION = "0.4.2" end end ruby-fftw3-0.4.2/lib/numru/fftw3.rb0000644000175000017500000000015412507177171017327 0ustar horinouthorinoutbegin require "rubygems" rescue LoadError end require "numru/fftw3/version" require "numru/fftw3/fftw3" ruby-fftw3-0.4.2/.gitignore0000644000175000017500000000005612507177171016026 0ustar horinouthorinout*.[oa] *~ *.so Makefile ChangeLog /pkg/ /tmp/ ruby-fftw3-0.4.2/.ChangeLog.until201104190000644000175000017500000000150312506141700017624 0ustar horinouthorinoutTue Apr 19 2011 T Horinouchi * version 0.4 released (cvs tag ruby-fftw3-0_4) * doc/ruby-fftw3.rd and doc/ruby-fftw3.html : updated * 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" * LICENSE.txt: changed --> BSD 2-clause license Thu Mar 24 2011 T Horinouchi * version 0.3 released (cvs tag ruby-fftw3-0_3) * LICENSE.txt: added Mon Jun 7 2004 T Horinouchi < T Koshiro * version 0.2 released (cvs tag ruby-fftw3-0_2) * extconf.rb: improved Mon Jun 7 2004 T Horinouchi * renamed to ruby-fftw. Started a new cvs module ruby-fftw3. Fri Nov 20 2003 T Horinouchi * version 0.1 released Thu Nov 20 2003 T Horinouchi * na_fftw3.c: debug of na_fftw3_float Tue Nov 18 2003 T Horinouchi * created. version 0.0 ruby-fftw3-0.4.2/LICENSE.txt0000644000175000017500000000326512506141700015652 0ustar horinouthorinoutRuby-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 (http://www.gfd-dennou.org/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY GFD DENNOU CLUB AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Takeshi Horinouchi and GFD Dennou Club. ruby-fftw3-0.4.2/doc/0000755000175000017500000000000012526316447014604 5ustar horinouthorinoutruby-fftw3-0.4.2/doc/ruby-fftw3.html0000644000175000017500000001161212506141700017465 0ustar horinouthorinout ruby-fftw3.rd

module NumRu::FFTW3

Fast Fourier Transforms by using FFTW Ver.3.

Takeshi Horinouchi

(C) Takeshi Horinouchi / GFD Dennou Club, 2003

NO WARRANTY

Features

Features yet to be introduced

Installation

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.
ruby-fftw3-0.4.2/doc/ruby-fftw3.rd0000644000175000017500000000736112506141700017134 0ustar horinouthorinout=module NumRu::FFTW3 Fast Fourier Transforms by using (()) Ver.3. Takeshi Horinouchi (C) Takeshi Horinouchi / GFD Dennou Club, 2003 NO WARRANTY ==Features * Uses (()). * 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 (()) 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 (()). * 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 # 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 # fc = FFTW3.fft(na, -1, 0) / na.shape[0] # forward FFT with the first dim # 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. ruby-fftw3-0.4.2/Rakefile0000644000175000017500000000130612507177171015502 0ustar horinouthorinout# -* coding: utf-8 -*- require 'rake/testtask' require 'rake/extensiontask' require 'rake/packagetask' begin require 'bundler/gem_tasks' rescue LoadError puts 'If you want to create gem, You must install Bundler' end require './lib/numru/fftw3/version.rb' def version NumRu::FFTW3::VERSION end task :default => :test task :test => :compile Rake::TestTask.new do |t| t.libs << 'lib' << 'test' t.test_files = FileList['test/*.rb'] end Rake::ExtensionTask.new do |ext| ext.name = 'fftw3' ext.ext_dir = 'ext/numru/fftw3' ext.lib_dir = 'lib/numru/fftw3' end Rake::PackageTask.new('ruby-fftw3', "#{version}") do |t| t.need_tar_gz = true t.package_files.include `git ls-files`.split("\n") end ruby-fftw3-0.4.2/ext/0000755000175000017500000000000012526316447014637 5ustar horinouthorinoutruby-fftw3-0.4.2/ext/numru/0000755000175000017500000000000012526316447016005 5ustar horinouthorinoutruby-fftw3-0.4.2/ext/numru/fftw3/0000755000175000017500000000000012526316447017036 5ustar horinouthorinoutruby-fftw3-0.4.2/ext/numru/fftw3/na_fftw3.c0000644000175000017500000001643012507177171020713 0ustar horinouthorinout/* na_fftw3.c FFT using FFTW Ver.3 (www.fftw.org) (C) Takeshi Horinouchi NO WARRANTY. */ #include #include "narray.h" #include VALUE rb_mFFTW3; VALUE mNumRu; static VALUE #ifdef FFTW3_HAS_SINGLE_SUPPORT na_fftw3_double(int argc, VALUE *argv, VALUE self) /* to be called by na_fftw3 */ #else na_fftw3(int argc, VALUE *argv, VALUE self) /* to be called directly */ #endif { VALUE val, vdir; struct NARRAY *a1, *a2; int i, dir, *shape, *bucket; fftw_plan p; fftw_complex *in, *out; volatile VALUE v1, v2; if (argc<2){ rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])"); } val = argv[0]; vdir = argv[1]; dir = NUM2INT(vdir); if ( dir != 1 && dir != -1 ){ rb_raise(rb_eArgError, "direction should be 1 or -1"); } v1 = na_cast_object(val, NA_DCOMPLEX); GetNArray(v1,a1); v2 = na_make_object( NA_DCOMPLEX, a1->rank, a1->shape, CLASS_OF(v1) ); GetNArray(v2,a2); shape = ALLOCA_N(int, a2->rank); for (i=0; irank; i++){ shape[i] = a2->shape[a2->rank-1-i]; } in = (fftw_complex*)a1->ptr; out = (fftw_complex*)a2->ptr; if (argc==2) { /* apply FFT to all dimensions */ p = fftw_plan_dft( a2->rank, shape, in, out, dir, 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, ib, 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;irank; /* 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; jrank; j++) bucket[j] = 0; /* initialize */ for(i=0; irank; j++) { if (bucket[j]==1){ dimids[i] = j; i++; } } for(j=0; jrank ; 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; irank; 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_dft( fft_rank, fft_dims, howmany_rank, howmany_dims, in, out, dir, FFTW_ESTIMATE ); } } fftw_execute(p); fftw_destroy_plan(p); return v2; } #ifdef FFTW3_HAS_SINGLE_SUPPORT /* sourse code generation of na_fftw3_float: Copy na_fftw3_double, and replace fftw --> fftwf DCOMPLEX --> SCOMPLEX */ static VALUE na_fftw3_float(int argc, VALUE *argv, VALUE self) { VALUE val, vdir; struct NARRAY *a1, *a2; int i, dir, *shape, *bucket; fftwf_plan p; fftwf_complex *in, *out; volatile VALUE v1, v2; if (argc<2){ rb_raise(rb_eArgError, "Usage: fftw(narray, direction [,dim0,dim1,...])"); } val = argv[0]; vdir = argv[1]; dir = NUM2INT(vdir); if ( dir != 1 && dir != -1 ){ rb_raise(rb_eArgError, "direction should be 1 or -1"); } v1 = na_cast_object(val, NA_SCOMPLEX); GetNArray(v1,a1); v2 = na_make_object( NA_SCOMPLEX, a1->rank, a1->shape, CLASS_OF(v1) ); GetNArray(v2,a2); shape = ALLOCA_N(int, a2->rank); for (i=0; irank; i++){ shape[i] = a2->shape[a2->rank-1-i]; } in = (fftwf_complex*)a1->ptr; out = (fftwf_complex*)a2->ptr; if (argc==2) { /* apply FFT to all dimensions */ p = fftwf_plan_dft( a2->rank, shape, in, out, dir, 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, ib, 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;irank; /* 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; jrank; j++) bucket[j] = 0; /* initialize */ for(i=0; irank; j++) { if (bucket[j]==1){ dimids[i] = j; i++; } } for(j=0; jrank ; 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; irank; 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_dft( fft_rank, fft_dims, howmany_rank, howmany_dims, in, out, dir, FFTW_ESTIMATE ); } } fftwf_execute(p); fftwf_destroy_plan(p); return v2; } 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: fftw(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) ); } } #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); } ruby-fftw3-0.4.2/ext/numru/fftw3/extconf.rb0000644000175000017500000000236212507177171021032 0ustar horinouthorinoutrequire "mkmf" 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') if ( ! ( have_header("narray.h") && have_header("narray_config.h") ) ) then print <<-EOS ** configure error ** Header narray.h or narray_config.h is not found. If you have these files in /narraydir/include, try the following: % ruby extconf.rb --with-narray-include=/narraydir/include EOS exit(-1) end if ( ! ( have_header("fftw3.h") && have_library("fftw3") ) ) then print <= 1.8") spec.add_runtime_dependency(%q, [">= 0"]) spec.extensions << "ext/numru/fftw3/extconf.rb" end ruby-fftw3-0.4.2/Gemfile0000644000175000017500000000013712507177171015331 0ustar horinouthorinoutsource 'https://rubygems.org' # Specify your gem's dependencies in ruby-fftw3.gemspec gemspec