convolver 1.0.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/README.md +153 -36
- data/ext/convolver/convolve_raw.c +11 -9
- data/ext/convolver/convolve_raw.h +3 -0
- data/ext/convolver/convolver.c +69 -25
- data/ext/convolver/correlate_raw.c +167 -0
- data/ext/convolver/correlate_raw.h +28 -0
- data/lib/convolver/buffer_limits.rb +39 -0
- data/lib/convolver/buffer_preparation.rb +56 -0
- data/lib/convolver/circular_fft_operation.rb +83 -0
- data/lib/convolver/fft_buffer_plan.rb +39 -0
- data/lib/convolver/fft_estimator.rb +71 -0
- data/lib/convolver/fft_limits.rb +64 -0
- data/lib/convolver/linear_fft_operation.rb +50 -0
- data/lib/convolver/operation_execution.rb +107 -0
- data/lib/convolver/operation_options.rb +118 -0
- data/lib/convolver/operation_plan.rb +63 -0
- data/lib/convolver/operation_shapes.rb +129 -0
- data/lib/convolver/real_fft_shape.rb +135 -0
- data/lib/convolver/signal_extension.rb +67 -0
- data/lib/convolver/version.rb +1 -1
- data/lib/convolver.rb +102 -71
- metadata +24 -9
data/lib/convolver.rb
CHANGED
|
@@ -5,105 +5,136 @@ require 'numo/pocketfft'
|
|
|
5
5
|
require 'convolver/convolver'
|
|
6
6
|
require 'convolver/version'
|
|
7
7
|
|
|
8
|
-
#
|
|
8
|
+
# Mathematical convolution and cross-correlation for Numo::NArray values.
|
|
9
9
|
module Convolver
|
|
10
|
-
# Maximum number of dimensions supported by the
|
|
10
|
+
# Maximum number of dimensions supported by the implementations.
|
|
11
11
|
MAX_RANK = 16
|
|
12
12
|
|
|
13
|
+
require 'convolver/operation_plan'
|
|
14
|
+
require 'convolver/linear_fft_operation'
|
|
15
|
+
require 'convolver/circular_fft_operation'
|
|
16
|
+
require 'convolver/fft_estimator'
|
|
17
|
+
require 'convolver/operation_execution'
|
|
18
|
+
|
|
13
19
|
class << self
|
|
14
|
-
# Chooses the likely fastest
|
|
15
|
-
#
|
|
16
|
-
# The inputs must have the same rank, and the kernel must not be larger than
|
|
17
|
-
# the signal in any dimension. The result shape is:
|
|
20
|
+
# Chooses the likely fastest mathematical convolution implementation.
|
|
18
21
|
#
|
|
19
|
-
#
|
|
22
|
+
# Results use single precision. Inputs must be nonempty arrays of equal
|
|
23
|
+
# rank, with at most {MAX_RANK} dimensions. Scalars multiply directly.
|
|
24
|
+
# In valid mode the kernel must fit inside the signal in every dimension.
|
|
25
|
+
# Full mode permits only constant boundaries; nonconstant boundaries and
|
|
26
|
+
# nonzero origins are supported only in same mode.
|
|
20
27
|
#
|
|
21
|
-
# @param signal [Numo::NArray] input
|
|
22
|
-
# @param kernel [Numo::NArray]
|
|
23
|
-
# @
|
|
24
|
-
# @
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
# @param signal [Numo::NArray] input signal
|
|
29
|
+
# @param kernel [Numo::NArray] convolution kernel
|
|
30
|
+
# @param mode [:valid, :same, :full] output extent (default: :valid)
|
|
31
|
+
# @param boundary [:constant, :nearest, :reflect, :mirror, :wrap]
|
|
32
|
+
# signal extension policy (default: :constant)
|
|
33
|
+
# @param fill_value [Numeric] constant boundary value (default: 0);
|
|
34
|
+
# valid mode requires zero, and other boundaries reject this option
|
|
35
|
+
# @param origin [Integer, Array<Integer>] offset from the kernel midpoint,
|
|
36
|
+
# shared across axes or one per axis (default: 0)
|
|
37
|
+
# @return [Numo::SFloat] mathematical convolution result
|
|
38
|
+
# @raise [ArgumentError] if inputs or options are invalid
|
|
39
|
+
# @raise [RangeError] if planned dimensions, buffers or FFT arithmetic exceed native limits
|
|
40
|
+
def convolve(signal, kernel, mode: :valid, boundary: :constant,
|
|
41
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
42
|
+
execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:).automatic(self)
|
|
43
|
+
end
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
# Chooses the likely fastest cross-correlation implementation.
|
|
46
|
+
# Uses the same input and option rules as {.convolve}, without reversing
|
|
47
|
+
# the kernel's orientation.
|
|
48
|
+
# @param (see convolve)
|
|
49
|
+
# @return [Numo::SFloat] cross-correlation result
|
|
50
|
+
# @raise (see convolve)
|
|
51
|
+
def correlate(signal, kernel, mode: :valid, boundary: :constant,
|
|
52
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
53
|
+
execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:).automatic(self)
|
|
54
|
+
end
|
|
31
55
|
|
|
32
|
-
|
|
33
|
-
|
|
56
|
+
# Uses the direct native mathematical convolution implementation.
|
|
57
|
+
# @param (see convolve)
|
|
58
|
+
# @return [Numo::SFloat] mathematical convolution result
|
|
59
|
+
# @raise (see convolve)
|
|
60
|
+
def convolve_basic(signal, kernel, mode: :valid, boundary: :constant,
|
|
61
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
62
|
+
execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:).basic
|
|
63
|
+
end
|
|
34
64
|
|
|
35
|
-
|
|
65
|
+
# Uses the direct native cross-correlation implementation.
|
|
66
|
+
# @param (see convolve)
|
|
67
|
+
# @return [Numo::SFloat] cross-correlation result
|
|
68
|
+
# @raise (see convolve)
|
|
69
|
+
def correlate_basic(signal, kernel, mode: :valid, boundary: :constant,
|
|
70
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
71
|
+
execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:).basic
|
|
36
72
|
end
|
|
37
73
|
|
|
38
|
-
# Uses PocketFFT to calculate
|
|
39
|
-
#
|
|
40
|
-
# @
|
|
41
|
-
# @
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
validate_inputs!(signal, kernel)
|
|
46
|
-
ranges = kernel.shape.zip(signal.shape).map { |kernel_size, signal_size| (kernel_size - 1)...signal_size }
|
|
47
|
-
full_convolution = Numo::Pocketfft.fftconvolve(signal, kernel.reverse)
|
|
48
|
-
|
|
49
|
-
Numo::SFloat.cast(full_convolution[*ranges])
|
|
74
|
+
# Uses PocketFFT to calculate mathematical convolution.
|
|
75
|
+
# @param (see convolve)
|
|
76
|
+
# @return [Numo::SFloat] mathematical convolution result
|
|
77
|
+
# @raise (see convolve)
|
|
78
|
+
def convolve_fft(signal, kernel, mode: :valid, boundary: :constant,
|
|
79
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
80
|
+
execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:).fft
|
|
50
81
|
end
|
|
51
82
|
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
# @
|
|
55
|
-
# @
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
-
|
|
83
|
+
# Uses PocketFFT to calculate cross-correlation.
|
|
84
|
+
# @param (see convolve)
|
|
85
|
+
# @return [Numo::SFloat] cross-correlation result
|
|
86
|
+
# @raise (see convolve)
|
|
87
|
+
def correlate_fft(signal, kernel, mode: :valid, boundary: :constant,
|
|
88
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
89
|
+
execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:).fft
|
|
59
90
|
end
|
|
60
91
|
|
|
61
92
|
# Estimates the relative cost of {.convolve_fft}.
|
|
62
|
-
#
|
|
63
|
-
# @param
|
|
64
|
-
# @param kernel [Numo::NArray] correlation kernel
|
|
93
|
+
# This is a heuristic for algorithm selection, not a timing measurement.
|
|
94
|
+
# @param (see convolve)
|
|
65
95
|
# @return [Float] machine-specific relative cost estimate
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
96
|
+
# @raise (see convolve)
|
|
97
|
+
def predict_convolve_fft_time(signal, kernel, mode: :valid, boundary: :constant,
|
|
98
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
99
|
+
execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:).fft_time
|
|
70
100
|
end
|
|
71
101
|
|
|
72
|
-
# Estimates the relative cost of {.
|
|
73
|
-
#
|
|
74
|
-
# @param
|
|
75
|
-
# @param kernel [Numo::NArray] correlation kernel
|
|
102
|
+
# Estimates the relative cost of {.correlate_fft}.
|
|
103
|
+
# This is a heuristic for algorithm selection, not a timing measurement.
|
|
104
|
+
# @param (see convolve)
|
|
76
105
|
# @return [Float] machine-specific relative cost estimate
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
# @raise (see convolve)
|
|
107
|
+
def predict_correlate_fft_time(signal, kernel, mode: :valid, boundary: :constant,
|
|
108
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
109
|
+
execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:).fft_time
|
|
81
110
|
end
|
|
82
111
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
112
|
+
# Estimates the relative cost of {.convolve_basic}.
|
|
113
|
+
# This is a heuristic for algorithm selection, not a timing measurement.
|
|
114
|
+
# @param (see convolve)
|
|
115
|
+
# @return [Float] machine-specific relative cost estimate
|
|
116
|
+
# @raise (see convolve)
|
|
117
|
+
def predict_convolve_basic_time(signal, kernel, mode: :valid, boundary: :constant,
|
|
118
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
119
|
+
execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:).basic_time
|
|
87
120
|
end
|
|
88
121
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
122
|
+
# Estimates the relative cost of {.correlate_basic}.
|
|
123
|
+
# This is a heuristic for algorithm selection, not a timing measurement.
|
|
124
|
+
# @param (see convolve)
|
|
125
|
+
# @return [Float] machine-specific relative cost estimate
|
|
126
|
+
# @raise (see convolve)
|
|
127
|
+
def predict_correlate_basic_time(signal, kernel, mode: :valid, boundary: :constant,
|
|
128
|
+
fill_value: UNSPECIFIED_FILL, origin: 0)
|
|
129
|
+
execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:).basic_time
|
|
92
130
|
end
|
|
93
131
|
|
|
94
|
-
|
|
95
|
-
unless signal.is_a?(Numo::NArray) && kernel.is_a?(Numo::NArray)
|
|
96
|
-
raise ArgumentError, 'signal and kernel must be Numo::NArray values'
|
|
97
|
-
end
|
|
98
|
-
raise ArgumentError, 'signal and kernel must not be empty' if signal.empty? || kernel.empty?
|
|
99
|
-
end
|
|
132
|
+
private
|
|
100
133
|
|
|
101
|
-
|
|
102
|
-
raise ArgumentError, 'signal and kernel must have equal rank' unless signal.ndim == kernel.ndim
|
|
103
|
-
raise ArgumentError, "maximum supported rank is #{MAX_RANK}" if signal.ndim > MAX_RANK
|
|
104
|
-
return if signal.shape.zip(kernel.shape).all? { |signal_size, kernel_size| signal_size >= kernel_size }
|
|
134
|
+
private :convolve_basic_valid, :correlate_basic_valid
|
|
105
135
|
|
|
106
|
-
|
|
136
|
+
def execution(operation, signal, kernel, mode:, boundary:, fill_value:, origin:)
|
|
137
|
+
OperationExecution.new(operation, signal, kernel, mode:, boundary:, fill_value:, origin:)
|
|
107
138
|
end
|
|
108
139
|
end
|
|
109
140
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: convolver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Neil Slater
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
version: 0.9.9
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '0.
|
|
21
|
+
version: '0.12'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -28,14 +28,14 @@ dependencies:
|
|
|
28
28
|
version: 0.9.9
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: '0.
|
|
31
|
+
version: '0.12'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: numo-pocketfft
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
|
36
36
|
- - ">="
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version:
|
|
38
|
+
version: 0.7.0
|
|
39
39
|
- - "<"
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '0.8'
|
|
@@ -45,12 +45,12 @@ dependencies:
|
|
|
45
45
|
requirements:
|
|
46
46
|
- - ">="
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
|
-
version:
|
|
48
|
+
version: 0.7.0
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
51
|
version: '0.8'
|
|
52
|
-
description: Fast
|
|
53
|
-
with
|
|
52
|
+
description: Fast mathematical convolution and cross-correlation for multidimensional
|
|
53
|
+
Numo::NArray values, with configurable output and boundary modes.
|
|
54
54
|
email:
|
|
55
55
|
- slobo777@gmail.com
|
|
56
56
|
executables: []
|
|
@@ -64,8 +64,23 @@ files:
|
|
|
64
64
|
- ext/convolver/convolve_raw.c
|
|
65
65
|
- ext/convolver/convolve_raw.h
|
|
66
66
|
- ext/convolver/convolver.c
|
|
67
|
+
- ext/convolver/correlate_raw.c
|
|
68
|
+
- ext/convolver/correlate_raw.h
|
|
67
69
|
- ext/convolver/extconf.rb
|
|
68
70
|
- lib/convolver.rb
|
|
71
|
+
- lib/convolver/buffer_limits.rb
|
|
72
|
+
- lib/convolver/buffer_preparation.rb
|
|
73
|
+
- lib/convolver/circular_fft_operation.rb
|
|
74
|
+
- lib/convolver/fft_buffer_plan.rb
|
|
75
|
+
- lib/convolver/fft_estimator.rb
|
|
76
|
+
- lib/convolver/fft_limits.rb
|
|
77
|
+
- lib/convolver/linear_fft_operation.rb
|
|
78
|
+
- lib/convolver/operation_execution.rb
|
|
79
|
+
- lib/convolver/operation_options.rb
|
|
80
|
+
- lib/convolver/operation_plan.rb
|
|
81
|
+
- lib/convolver/operation_shapes.rb
|
|
82
|
+
- lib/convolver/real_fft_shape.rb
|
|
83
|
+
- lib/convolver/signal_extension.rb
|
|
69
84
|
- lib/convolver/version.rb
|
|
70
85
|
homepage: https://github.com/neilslater/convolver
|
|
71
86
|
licenses:
|
|
@@ -80,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
80
95
|
requirements:
|
|
81
96
|
- - ">="
|
|
82
97
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: '3.
|
|
98
|
+
version: '3.3'
|
|
84
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
100
|
requirements:
|
|
86
101
|
- - ">="
|
|
@@ -89,5 +104,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
89
104
|
requirements: []
|
|
90
105
|
rubygems_version: 4.0.16
|
|
91
106
|
specification_version: 4
|
|
92
|
-
summary: Fast cross-correlation for Numo::NArray
|
|
107
|
+
summary: Fast convolution and cross-correlation for Numo::NArray
|
|
93
108
|
test_files: []
|