From 6d4a96b889b65cb08ec8a9edfcf1f7ef45c6e55e Mon Sep 17 00:00:00 2001 From: fenrir Date: Wed, 20 May 2026 00:25:59 +0900 Subject: [PATCH 01/10] Update Rakefile to add compile and yard tasks --- Rakefile | 19 +++++++++++-------- ext/numo/fftw/depend | 11 +---------- numo-fftw.gemspec | 6 ++++-- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Rakefile b/Rakefile index 8fd75b9..ddd51ec 100644 --- a/Rakefile +++ b/Rakefile @@ -1,13 +1,16 @@ require "bundler/gem_tasks" -task :doc do - dir = "ext/numo/fftw" - src = %w[fftw.c] - path = src.map{|s| File.join(dir,s)} - sh "cd #{dir}; ruby extconf.rb; make #{src.join(' ')}" - sh "rm -rf yard .yardoc; yard doc -o yard -m markdown -r README.md #{path.join(' ')}" +require "rake/extensiontask" +Rake::ExtensionTask.new("numo/fftw") do |ext| + ext.lib_dir = "lib/numo" end -task :cleandoc do - rm_rf %w[yard .yardoc] +require "yard" +YARD::Rake::YardocTask.new do |t| + t.before = proc{ + Rake::Task["compile:numo/fftw"].invoke + } + t.files = Dir['**/numo/fftw/**/fftw.c', __dir__] + t.options = ['--embed-mixins'] + #t.stats_options = ['--list-undoc'] end diff --git a/ext/numo/fftw/depend b/ext/numo/fftw/depend index decf83a..6e08e58 100644 --- a/ext/numo/fftw/depend +++ b/ext/numo/fftw/depend @@ -2,13 +2,4 @@ CLEANOBJS = *.o */*.o *.bak *~ ERB = erb -T- fftw.c: fftw.erb.c - $(ERB) fftw.erb.c > fftw.c - -doc : fftw.c - yard doc -o yard -m markdown $< - -clean: cleansrc cleandoc -cleansrc: - -$(Q)$(RM) fftw.c -cleandoc: - -$(Q)$(RM_RF) yard .yardoc + $(ERB) $^ > $@ \ No newline at end of file diff --git a/numo-fftw.gemspec b/numo-fftw.gemspec index efa3586..bea208a 100644 --- a/numo-fftw.gemspec +++ b/numo-fftw.gemspec @@ -27,7 +27,9 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.extensions = ["ext/numo/fftw/extconf.rb"] - spec.add_development_dependency "bundler", "~> 1.3" - spec.add_development_dependency "rake", "~> 0" + spec.add_development_dependency "bundler", ">= 1.3" + spec.add_development_dependency "rake" + spec.add_development_dependency "rake-compiler" + spec.add_development_dependency "yard" spec.add_runtime_dependency "numo-narray", ">= 0.9.0.8" end From 553308b6dfb0334528d209707aeee72bf05c0179 Mon Sep 17 00:00:00 2001 From: fenrir Date: Wed, 20 May 2026 00:34:50 +0900 Subject: [PATCH 02/10] Add Gemfile for bundler --- Gemfile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Gemfile diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..2e7431b --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# Specify your gem's dependencies in gps_pvt.gemspec +gemspec From 91bc195179f70d5602ffc3b7f295e1a4237db623 Mon Sep 17 00:00:00 2001 From: fenrir Date: Thu, 21 May 2026 14:37:26 +0900 Subject: [PATCH 03/10] Unuse mNumo which has been externally defined. --- ext/numo/fftw/fftw.erb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/numo/fftw/fftw.erb.c b/ext/numo/fftw/fftw.erb.c index 209f9fe..4aa96a9 100644 --- a/ext/numo/fftw/fftw.erb.c +++ b/ext/numo/fftw/fftw.erb.c @@ -150,10 +150,10 @@ numo_fftw_<%=func%>(VALUE mod, VALUE vna, VALUE vsign) void Init_fftw() { - VALUE mNumo,mFFTW; + VALUE /*mNumo,*/ mFFTW; // CAUTION: mNumo is already defined in narray.h rb_require("numo/narray"); - mNumo = rb_define_module("Numo"); + //mNumo = rb_define_module("Numo"); mFFTW = rb_define_module_under(mNumo,"FFTW"); <% $funcs.each do |f| %> From 763a73d21153ffbdb6104c6140ac232850b46176 Mon Sep 17 00:00:00 2001 From: fenrir Date: Thu, 21 May 2026 22:12:40 +0900 Subject: [PATCH 04/10] Move require "numo/narray.so" to fftw.rb to load before Init_fftw() --- ext/numo/fftw/fftw.erb.c | 2 +- lib/numo/fftw.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 lib/numo/fftw.rb diff --git a/ext/numo/fftw/fftw.erb.c b/ext/numo/fftw/fftw.erb.c index 4aa96a9..89a10ba 100644 --- a/ext/numo/fftw/fftw.erb.c +++ b/ext/numo/fftw/fftw.erb.c @@ -152,7 +152,7 @@ Init_fftw() { VALUE /*mNumo,*/ mFFTW; // CAUTION: mNumo is already defined in narray.h - rb_require("numo/narray"); + //rb_require("numo/narray"); // move to fftw.rb because numo/narray.so should be loaded before Init_fftw() //mNumo = rb_define_module("Numo"); mFFTW = rb_define_module_under(mNumo,"FFTW"); diff --git a/lib/numo/fftw.rb b/lib/numo/fftw.rb new file mode 100644 index 0000000..6d3e55d --- /dev/null +++ b/lib/numo/fftw.rb @@ -0,0 +1,2 @@ +require "numo/narray" +require "numo/fftw.#{RbConfig::CONFIG['DLEXT']}" From bd2a88c844289e57571e111f92e5306b47047a58 Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 00:03:35 +0900 Subject: [PATCH 05/10] Add rspec tests porting from numru-fftw3 --- Rakefile | 3 ++ numo-fftw.gemspec | 1 + spec/complexFFT_spec.rb | 76 +++++++++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 13 +++++++ 4 files changed, 93 insertions(+) create mode 100644 spec/complexFFT_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/Rakefile b/Rakefile index ddd51ec..3f96a5d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,8 @@ require "bundler/gem_tasks" +require "rspec/core/rake_task" +RSpec::Core::RakeTask.new(:spec) + require "rake/extensiontask" Rake::ExtensionTask.new("numo/fftw") do |ext| ext.lib_dir = "lib/numo" diff --git a/numo-fftw.gemspec b/numo-fftw.gemspec index bea208a..4dbb4ef 100644 --- a/numo-fftw.gemspec +++ b/numo-fftw.gemspec @@ -30,6 +30,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler", ">= 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "rake-compiler" + spec.add_development_dependency "rspec" spec.add_development_dependency "yard" spec.add_runtime_dependency "numo-narray", ">= 0.9.0.8" end diff --git a/spec/complexFFT_spec.rb b/spec/complexFFT_spec.rb new file mode 100644 index 0000000..3edab94 --- /dev/null +++ b/spec/complexFFT_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +# port from numru-fftw3/test/complexFFT.rb + +require 'rspec' + +require "numo/fftw" + +module Numo::FFTW + FORWARD = -1 + BACKWARD = 1 + singleton_methods.each{|func| + slice = (/(\d)d/ =~ func.to_s) ? $1.to_i : 0 + {:fw => FORWARD, :bk => BACKWARD}.each{|dir, sign| + define_singleton_method("#{func}_#{dir}".to_sym){|na| + res = send(func, na, sign) + (dir == :bk) ? (res / res.shape[-slice..-1].inject(:*)) : res + } + } + } +end + +RSpec::describe Numo::FFTW do + let(:fftw){described_class} + let(:eps){1e-10} + let(:seps){1e-6} + + it 'can perform forward and backward FFT' do # test_fft_fw_bk + na = Numo::DFloat::new(8,4).fill(1) # will be corced to complex + na[1,1]=5 + fc = fftw.dft_fw(na) + nb = fftw.dft_bk(fc).real + expect((na-nb).abs.max).to be < eps + + fc = fftw.dft_1d_fw(na) + nb = fftw.dft_1d_bk(fc).real + expect((na-nb).abs.max).to be < eps + end + + it 'can perform real forward FFT' do # test_real_all_dims + na = Numo::DFloat::new(8,4).fill(1) # will be corced to complex + na[1,1]=5 + fc = fftw.dft(na, fftw::FORWARD)/na.length + nb = fftw.dft(fc, fftw::BACKWARD).real + expect((na-nb).abs.max).to be < eps + end + + it 'can perform complex forward FFT' do # test_complex_all_dims + na = Numo::DComplex::new(8,4).fill(1) * Complex::I + na[1,1]=5 + fc = fftw.dft(na, fftw::FORWARD)/na.length + nb = fftw.dft(fc, fftw::BACKWARD) + expect((na-nb).abs.max).to be < eps + end + + it 'can perform single precision forward FFT' do # test_single_float + # single float (treated as single if lib fftw3f exits). + # see http://www.fftw.org/fftw3_doc/Precision.html for more info + na = Numo::SFloat::new(8,4).indgen + fc = fftw.dft(na, fftw::FORWARD)/na.length + nb = fftw.dft(fc, fftw::BACKWARD).real + expect((na-nb).abs.max).to be < eps + end +end + +__END__ +# TODO: +class FFTW3Test < Test::Unit::TestCase + 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 +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..b960d8c --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end From 743cb0dcc1a1e23a21b618ac7e15b9826af51405 Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 00:06:24 +0900 Subject: [PATCH 06/10] Add github actions --- .github/workflows/main.yml | 48 ++++++++++++++++++++++++++++++++++++++ Rakefile | 2 ++ 2 files changed, 50 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..d53ff62 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,48 @@ +name: Ruby + +on: [push, pull_request] + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: [2.3, 2.4, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, 3.4, '4.0'] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v6 + - name: before_setup + shell: bash + run: | + case ${{ matrix.os }} in + ubuntu-latest) + sudo apt-get update && sudo apt-get install -yq libfftw3-dev + ;; + windows-latest) + vcpkg install fftw3 --triplet=x64-mingw-static + # find $(cygpath -u "$VCPKG_INSTALLATION_ROOT")/packages -name "*fftw3*" + echo "BUNDLE_BUILD__NUMO___FFTW=\"--with-fftw-dir=$(cygpath -m ${VCPKG_INSTALLATION_ROOT})/packages/fftw3_x64-mingw-static\"" >> $GITHUB_ENV + ;; + esac + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + id: ruby-inst + env: + BUNDLE_BUILD__NUMO___NARRAY: --with-cflags=-std=c17 + BUNDLE_BUILD__NUMO___FFTW: ${{ env.BUNDLE_BUILD__NUMO___FFTW }} + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run the default task + run: bundle exec rake + - name: Upload artifact for error reproduction when failure + if: ${{ failure() }} + uses: actions/upload-artifact@v7 + with: + name: gem-build-logs.${{ matrix.os }}_${{ matrix.ruby }} + path: | + ${{ github.workspace }}/vendor/bundle/ruby/**/gems/ + ${{ github.workspace }}/vendor/bundle/ruby/**/mkmf.log \ No newline at end of file diff --git a/Rakefile b/Rakefile index 3f96a5d..edee9bb 100644 --- a/Rakefile +++ b/Rakefile @@ -17,3 +17,5 @@ YARD::Rake::YardocTask.new do |t| t.options = ['--embed-mixins'] #t.stats_options = ['--list-undoc'] end + +task :default => [:compile, :spec] From a0118536acaf2e849e30d8af67792cca7261c1f8 Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 00:26:50 +0900 Subject: [PATCH 07/10] Add .rspec to show rspec test progress --- .rspec | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .rspec diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..34c5164 --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--require spec_helper From fad24fc35f8bac8b642218e4ac4539213197d8a6 Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 00:38:02 +0900 Subject: [PATCH 08/10] Fix workflow to tell rake right fftw3 location --- .github/workflows/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d53ff62..08a7f47 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,12 +32,13 @@ jobs: id: ruby-inst env: BUNDLE_BUILD__NUMO___NARRAY: --with-cflags=-std=c17 - BUNDLE_BUILD__NUMO___FFTW: ${{ env.BUNDLE_BUILD__NUMO___FFTW }} with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run the default task - run: bundle exec rake + run: | + bundle exec rake compile -- ${{ env.BUNDLE_BUILD__NUMO___FFTW }} + bundle exec rake spec - name: Upload artifact for error reproduction when failure if: ${{ failure() }} uses: actions/upload-artifact@v7 From 821902867920edfccb481097c14c09ee47a1ab0e Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 00:57:41 +0900 Subject: [PATCH 09/10] Fix narray build option to remove -std=c17 for Ruby 2.3 --- .github/workflows/main.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 08a7f47..ffdd249 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,11 +27,18 @@ jobs: echo "BUNDLE_BUILD__NUMO___FFTW=\"--with-fftw-dir=$(cygpath -m ${VCPKG_INSTALLATION_ROOT})/packages/fftw3_x64-mingw-static\"" >> $GITHUB_ENV ;; esac + case ${{ matrix.ruby }} in + '2.3') + ;; + *) + echo "BUNDLE_BUILD__NUMO___NARRAY=\"--with-cflags=-std=c17\"" >> $GITHUB_ENV + ;; + esac - name: Set up Ruby uses: ruby/setup-ruby@v1 id: ruby-inst env: - BUNDLE_BUILD__NUMO___NARRAY: --with-cflags=-std=c17 + BUNDLE_BUILD__NUMO___NARRAY: ${{ env.BUNDLE_BUILD__NUMO___NARRAY }} with: ruby-version: ${{ matrix.ruby }} bundler-cache: true From d89821146b5cfe7103844610fe08f8faf911b4b8 Mon Sep 17 00:00:00 2001 From: fenrir Date: Fri, 22 May 2026 01:07:49 +0900 Subject: [PATCH 10/10] Remove windows-latest/2.3 because of RubyGems bug. --- .github/workflows/main.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ffdd249..a2e8532 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,6 +10,9 @@ jobs: os: [ubuntu-latest, windows-latest] # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' ruby: [2.3, 2.4, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, 3.4, '4.0'] + exclude: + - os: windows-latest + ruby: 2.3 runs-on: ${{ matrix.os }} steps: @@ -27,18 +30,11 @@ jobs: echo "BUNDLE_BUILD__NUMO___FFTW=\"--with-fftw-dir=$(cygpath -m ${VCPKG_INSTALLATION_ROOT})/packages/fftw3_x64-mingw-static\"" >> $GITHUB_ENV ;; esac - case ${{ matrix.ruby }} in - '2.3') - ;; - *) - echo "BUNDLE_BUILD__NUMO___NARRAY=\"--with-cflags=-std=c17\"" >> $GITHUB_ENV - ;; - esac - name: Set up Ruby uses: ruby/setup-ruby@v1 id: ruby-inst env: - BUNDLE_BUILD__NUMO___NARRAY: ${{ env.BUNDLE_BUILD__NUMO___NARRAY }} + BUNDLE_BUILD__NUMO___NARRAY: --with-cflags=-std=c17 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true