Skip to content

ydah/fftw3-ruby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FFTW3-Ruby

Ruby FFI bindings for FFTW3 (Fastest Fourier Transform in the West).

The gem exposes the FFTW planning and execution APIs for complex DFT, real-to-complex and complex-to-real transforms, real-to-real transforms, the advanced "many" interface, guru and guru64 planners, wisdom import/export, thread control, and runtime metadata.

Requirements

  • Ruby 3.1+
  • FFTW 3.3.x shared libraries installed on the system

Installing FFTW3

Ubuntu / Debian:

sudo apt-get install libfftw3-dev

macOS (Homebrew):

brew install fftw

Installation

Add the gem to your Gemfile:

gem "fftw3-ruby"

Then install dependencies:

bundle install

Precision Support

Runtime precision support depends on which FFTW libraries are installed.

require "fftw3"

FFTW3.available_precisions
FFTW3.double_available?
FFTW3.float_available?
FFTW3.long_double_available?
FFTW3.quad_available?

Notes:

  • Plan creation is available for any precision whose FFTW library can be loaded.
  • FFTW3::AlignedMemory#read and #write currently support :double, :float, and :long_double.
  • :quad library availability can be detected with FFTW3.quad_available?, but high-level buffer read/write helpers are not currently provided for quad buffers.

Core Types

FFTW3::AlignedMemory

Aligned buffers allocated with FFTW's allocator.

require "fftw3"

input = FFTW3::AlignedMemory.new(8, type: :complex, precision: :double)
input.write(Array.new(8) { |i| Complex(i, -i) })

input.pointer
input.read
input.free!

Options:

  • type: accepts :complex or :real
  • precision: accepts :double, :float, :long_double, or :quad

FFTW3::Plan

Factory methods return FFTW3::Plan instances. A plan can be executed in-place with the buffers it was created with, or with compatible alternate buffers via the new-array execute helpers.

FFTW3::Threads

Wrapper around FFTW thread initialization, planner thread count, optional planner locking, and the runtime thread callback hook.

FFTW3::Wisdom

Import and export FFTW wisdom through strings, files, and IO callbacks.

FFTW3::Utils

Small wrappers for FFTW global utility functions such as cleanup, set_timelimit, and alignment_of.

Quick Start

Basic 1D Complex DFT

require "fftw3"

n = 8
input = FFTW3::AlignedMemory.new(n, type: :complex, precision: :double)
output = FFTW3::AlignedMemory.new(n, type: :complex, precision: :double)

data = (0...n).map { |i| Complex(Math.sin(2 * Math::PI * i / n), 0.0) }
input.write(data)

plan = FFTW3::Plan.dft_1d(
  n,
  input,
  output,
  direction: :forward,
  flags: [:estimate]
)

plan.execute
result = output.read

puts result.map { |c| "(%.4f, %.4f)" % [c.real, c.imaginary] }

plan.destroy!
input.free!
output.free!

Real-to-Complex

require "fftw3"

n = 16
input = FFTW3::AlignedMemory.new(n, type: :real)
output = FFTW3::AlignedMemory.new((n / 2) + 1, type: :complex)

input.write(n.times.map { |i| Math.sin(2 * Math::PI * i / n) })

plan = FFTW3::Plan.dft_r2c_1d(n, input, output)
plan.execute

result = output.read

New-array Execute

require "fftw3"

n = 8
input_a = FFTW3::AlignedMemory.new(n, type: :complex)
output_a = FFTW3::AlignedMemory.new(n, type: :complex)
input_b = FFTW3::AlignedMemory.new(n, type: :complex)
output_b = FFTW3::AlignedMemory.new(n, type: :complex)

input_a.write(Array.new(n) { |i| Complex(i, 0.0) })
input_b.write(Array.new(n) { |i| Complex(0.0, i) })

plan = FFTW3::Plan.dft_1d(n, input_a, output_a, direction: :forward)

# Reuse the same plan with different buffers of the same shape.
plan.execute_dft(input_b, output_b)

plan.destroy!
input_a.free!
output_a.free!
input_b.free!
output_b.free!

Threading

Planner Thread Count

require "fftw3"

n = 1024
input = FFTW3::AlignedMemory.new(n, type: :complex)
output = FFTW3::AlignedMemory.new(n, type: :complex)

FFTW3::Threads.init
FFTW3::Threads.plan_with_nthreads(4)

plan = FFTW3::Plan.dft_1d(n, input, output, direction: :forward, flags: [:measure])
plan.execute

FFTW3::Threads.planner_nthreads
plan.destroy!
input.free!
output.free!
FFTW3::Threads.cleanup

Planner Locking

require "fftw3"

FFTW3::Threads.init
FFTW3::Threads.make_planner_thread_safe
FFTW3::Threads.cleanup

make_planner_thread_safe returns nil when the linked FFTW build does not expose that function.

Custom Thread Backend Callback

threads_set_callback is optional in FFTW. Check support before using it, and set it before creating plans.

require "fftw3"

if FFTW3::Threads.set_callback_supported?
  marker = FFI::MemoryPointer.new(:int)
  marker.write_int(7)

  FFTW3::Threads.set_callback(data: marker) do |work, jobdata, elsize, njobs, data_ptr|
    njobs.times do |index|
      work.call(jobdata + (elsize * index))
    end
  end

  # Reset to the default FFTW backend.
  FFTW3::Threads.set_callback(nil)
end

Wisdom

String and File APIs

require "fftw3"

wisdom = FFTW3::Wisdom.export_to_string
FFTW3::Wisdom.import_from_string(wisdom)

FFTW3::Wisdom.export_to_file("wisdom.fftw")
FFTW3::Wisdom.import_from_file("wisdom.fftw")

IO Callback APIs

require "fftw3"
require "stringio"

io = StringIO.new
FFTW3::Wisdom.export_to_io(io)
FFTW3::Wisdom.import_from_io(StringIO.new(io.string))

System Wisdom

require "fftw3"

FFTW3::Wisdom.import_system
FFTW3::Wisdom.forget!

Runtime Metadata and Utilities

require "fftw3"

input = FFTW3::AlignedMemory.new(8, type: :complex)

FFTW3.version
FFTW3.compiler
FFTW3.codelet_optimizations

FFTW3::Utils.set_timelimit(0.25)
FFTW3::Utils.alignment_of(input.pointer)
FFTW3::Utils.cleanup
input.free!

API Reference

Top-level FFTW3

Method Description
available_precisions Returns the precisions whose FFTW libraries can be loaded
double_available? / float_available? / long_double_available? / quad_available? Per-precision availability checks
version Linked FFTW version string
compiler Linked FFTW compiler string
codelet_optimizations Linked FFTW codelet optimization string

FFTW3::Plan Factory Methods

Method group Methods
Complex DFT dft_1d, dft_2d, dft_3d, dft
Real-to-complex dft_r2c_1d, dft_r2c_2d, dft_r2c_3d, dft_r2c
Complex-to-real dft_c2r_1d, dft_c2r_2d, dft_c2r_3d, dft_c2r
Real-to-real r2r_1d, r2r_2d, r2r_3d, r2r
Advanced / batched many_dft, many_dft_r2c, many_dft_c2r, many_r2r
Guru guru_dft, guru_split_dft, guru_dft_r2c, guru_split_dft_r2c, guru_dft_c2r, guru_split_dft_c2r, guru_r2r
Guru64 guru64_dft, guru64_split_dft, guru64_dft_r2c, guru64_split_dft_r2c, guru64_dft_c2r, guru64_split_dft_c2r, guru64_r2r

Notes:

  • dft_* and many_dft use direction:.
  • guru_dft and guru64_dft use sign:.
  • Guru and guru64 dimension arrays use hashes shaped like { n:, is:, os: }.

FFTW3::Plan Instance Methods

Method Description
execute Execute with the buffers used to create the plan
execute_dft New-array execute for complex DFT
execute_dft_r2c New-array execute for real-to-complex DFT
execute_dft_c2r New-array execute for complex-to-real DFT
execute_r2r New-array execute for real-to-real transforms
execute_split_dft New-array execute for split-complex guru DFT
execute_split_dft_r2c New-array execute for split real-to-complex guru DFT
execute_split_dft_c2r New-array execute for split complex-to-real guru DFT
flops Returns { add:, mul:, fma: }
cost FFTW plan cost
estimate_cost FFTW estimated plan cost
to_s / description String representation of the plan
print(io = $stdout) Write the plan description to an IO object
destroy! Destroy the underlying FFTW plan

FFTW3::Threads

Method Description
init Initialize FFTW thread support
plan_with_nthreads(n) Set planner and execution thread count
cleanup Release FFTW thread state
planner_nthreads Read configured thread count when supported
make_planner_thread_safe Enable FFTW's optional planner lock when supported
set_callback_supported? Check whether threads_set_callback is available
set_callback(callback = nil, data: nil, &block) Install or clear FFTW's runtime threading callback

FFTW3::Wisdom

Method Description
export_to_string / import_from_string Wisdom through Ruby strings
export_to_file / import_from_file Wisdom through filesystem paths
export_to_io / import_from_io Wisdom through Ruby IO callbacks
import_system Best-effort import from the system wisdom store
forget! Clear loaded wisdom

FFTW3::Utils

Method Description
cleanup Call FFTW global cleanup
set_timelimit(seconds) Set the FFTW planner time limit
alignment_of(pointer) Query FFTW's alignment classification for a pointer

Constants

Planner flags:

  • FFTW3::ESTIMATE
  • FFTW3::MEASURE
  • FFTW3::PATIENT
  • FFTW3::EXHAUSTIVE
  • FFTW3::PRESERVE_INPUT
  • FFTW3::DESTROY_INPUT
  • FFTW3::WISDOM_ONLY
  • Additional exported flags such as FFTW3::ESTIMATE_PATIENT, FFTW3::ALLOW_PRUNING, and FFTW3::NO_SIMD

Direction constants:

  • FFTW3::FORWARD
  • FFTW3::BACKWARD
  • :forward and :backward are also accepted where direction symbols are supported

R2R kinds:

  • FFTW3::R2HC
  • FFTW3::HC2R
  • FFTW3::DHT
  • FFTW3::REDFT00, REDFT01, REDFT10, REDFT11
  • FFTW3::RODFT00, RODFT01, RODFT10, RODFT11

Development

bundle install
bundle exec rake spec

License

The gem is available as open source under the terms of the MIT License.

FFTW3 itself is licensed under GPLv2+. Using this gem requires an installed FFTW3 library.

About

Ruby FFI bindings for FFTW3 (Fastest Fourier Transform in the West).

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages