Convolver
Convolver calculates cross-correlations between multidimensional
Numo::NArray values, with
configurable output extents and signal boundary extensions. It chooses between
a direct native implementation for smaller inputs and a
Numo::Pocketfft-based
implementation for larger inputs.
Version 1.0 replaces the unmaintained narray and fftw3 gems with
numo-narray-alt and numo-pocketfft.
Installation
Add Convolver to your application's Gemfile:
gem 'convolver'
Then run:
bundle install
Alternatively, install it directly:
gem install convolver
No external FFT library is required; PocketFFT is bundled by its Ruby gem.
Usage
require 'convolver'
signal = Numo::SFloat[0.3, 0.4, 0.5]
kernel = Numo::SFloat[1.3, -0.5]
Convolver.convolve(signal, kernel)
# => Numo::SFloat#shape=[2]
# [0.19, 0.27]
With no keywords, Convolver preserves its original valid-correlation behavior: the signal and kernel must have the same rank, the kernel must be no larger than the signal in any dimension, and only positions with complete overlap are returned. The result size in each dimension is:
signal_size - kernel_size + 1
Inputs are converted to single-precision floats internally, and results are
returned as Numo::SFloat. Supplying Numo::SFloat inputs avoids conversion in
the direct implementation.
Convolver.convolve normally chooses the implementation automatically. The
implementations can also be called directly for application-specific
benchmarking:
Convolver.convolve_basic(signal, kernel)
Convolver.convolve_fft(signal, kernel)
Both implementations and the automatic method accept the same options:
Convolver.convolve(signal, kernel,
mode: :same,
boundary: :reflect,
origin: 0)
Output modes
mode: controls the returned extent independently in each dimension:
| Mode | Meaning | Result size |
|---|---|---|
:valid |
Kernel overlaps the stored signal completely | S - K + 1 |
:same |
One result aligned with each stored signal position | S |
:full |
Every kernel position with any stored-signal overlap | S + K - 1 |
:valid is the default and accepts only the default boundary: :constant,
fill_value: 0.0, and origin: 0. :full supports constant extension only.
:same supports every boundary described below. Kernels larger than the signal
are supported by :same and :full, but not by :valid. mode: and
boundary: accept only the symbols listed here.
Boundary extension
For a one-dimensional signal a b c d, boundary: selects values outside the
stored signal:
| Boundary | Extended sequence | ||
|---|---|---|---|
:constant |
`k k k k | a b c d | k k k k` |
:nearest |
`a a a a | a b c d | d d d d` |
:reflect |
`d c b a | a b c d | d c b a` |
:mirror |
`d c b | a b c d | c b a` |
:wrap |
`a b c d | a b c d | a b c d` |
fill_value: sets k for :constant and defaults to zero. It must not be
passed with another boundary. :reflect repeats the edge sample; :mirror
does not. All boundary modes work across every dimension, including
length-one axes and extensions wider than the stored signal.
Kernel origin
origin: shifts the kernel anchor for :same. It accepts one integer applied
to every dimension or an array with one integer per dimension. For a kernel
dimension of length K:
anchor = (K / 2) + origin
The anchor must remain within the kernel. Positive origins sample farther
toward lower signal indices. With the default origin, an even kernel gives the
extra boundary sample to the lower-index, or left, side: a length-four kernel
uses two samples before and one after the aligned signal position. Nonzero
origins are supported only for :same; :valid and :full require zero.
The estimator methods accept and validate the same options:
Convolver.predict_convolve_basic_time(signal, kernel, mode: :same, boundary: :nearest)
Convolver.predict_convolve_fft_time(signal, kernel, mode: :same, boundary: :wrap)
Convolver.convolve_fftw3 remains as a deprecated alias for convolve_fft to
ease migration from Convolver 0.x and forwards all options.
Contributing
Install the development dependencies, then run the main suite:
bundle install
bundle exec rake
bundle exec rubocop
bundle exec rake c:lint
The Ruby specs exercise both the Ruby API and native extension. Additional native-code checks are available:
bundle exec rake c:coverage # Requires GCC and gcovr
bundle exec rake c:sanitize # Requires Linux and GCC
c:coverage writes HTML and Cobertura reports under coverage/c. CI uploads
the reports as a c-coverage artifact. The sanitizer task uses AddressSanitizer
and UndefinedBehaviorSanitizer.
Contributors
- Dima Ermilov contributed the original Windows compilation support.