convolver 2.0.0 → 4.0.0

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.
@@ -1,33 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'convolver/real_fft_shape'
4
+ require 'convolver/fft_limits'
5
+
3
6
  module Convolver
4
7
  # Calculates and validates output, extension, and FFT dimensions.
8
+ # @private
5
9
  class OperationShapes
6
10
  SIZE_MAX = (1 << ([0].pack('J').bytesize * 8)) - 1
7
11
 
8
12
  attr_reader :padding_before, :padding_after, :result_shape,
9
13
  :extended_shape, :result_size, :extended_size
10
14
 
11
- def initialize(signal_shape, kernel_shape, mode:, anchors:)
15
+ def initialize(signal_shape, kernel_shape, operation:, mode:, anchors:)
16
+ @operation = operation
12
17
  @mode = mode
13
18
  calculate_shapes(signal_shape, kernel_shape, anchors)
14
19
  validate_sizes!
15
20
  end
16
21
 
17
- def linear_fft_shape(kernel_shape)
18
- checked_shape(
19
- extended_shape.zip(kernel_shape).map { |signal_size, kernel_size| signal_size + kernel_size - 1 },
20
- 'FFT shape'
21
- )
22
+ def linear_fft_shape(kernel_shape, limits: FftLimits.new)
23
+ return [].freeze if kernel_shape.empty?
24
+
25
+ RealFftShape.new(linear_result_shape(kernel_shape), size_max: SIZE_MAX, limits:).call
22
26
  end
23
27
 
24
28
  def linear_fft_size(kernel_shape)
25
29
  checked_product(linear_fft_shape(kernel_shape), 'FFT size')
26
30
  end
27
31
 
32
+ def linear_spectrum_size(kernel_shape)
33
+ shape = linear_fft_shape(kernel_shape)
34
+ return 1 if shape.empty?
35
+
36
+ spectrum_shape = shape.dup
37
+ spectrum_shape[-1] = (spectrum_shape[-1] / 2) + 1
38
+ checked_product(spectrum_shape, 'FFT spectrum size')
39
+ end
40
+
28
41
  private
29
42
 
30
- attr_reader :mode
43
+ attr_reader :operation, :mode
31
44
 
32
45
  def calculate_shapes(signal_shape, kernel_shape, anchors)
33
46
  @padding_before, @padding_after, @result_shape = shapes_for(signal_shape, kernel_shape, anchors)
@@ -53,8 +66,15 @@ module Convolver
53
66
  end
54
67
 
55
68
  def same_shapes(signal_shape, kernel_shape, anchors)
56
- before = anchors.dup.freeze
57
- after = kernel_shape.zip(anchors).map { |kernel_size, anchor| kernel_size - 1 - anchor }.freeze
69
+ correlation_before = anchors.dup
70
+ correlation_after = kernel_shape.zip(anchors).map { |kernel_size, anchor| kernel_size - 1 - anchor }
71
+ before, after = if operation == :correlation
72
+ [correlation_before, correlation_after]
73
+ else
74
+ [correlation_after, correlation_before]
75
+ end
76
+ before.freeze
77
+ after.freeze
58
78
  [before, after, signal_shape.dup]
59
79
  end
60
80
 
@@ -90,6 +110,19 @@ module Convolver
90
110
  product * size
91
111
  end
92
112
  end
113
+
114
+ def linear_result_shape(kernel_shape)
115
+ shape = extended_shape.zip(kernel_shape).map do |signal_size, kernel_size|
116
+ checked_add(signal_size, kernel_size - 1, 'FFT shape')
117
+ end
118
+ checked_shape(shape, 'FFT shape')
119
+ end
120
+
121
+ def checked_add(left, right, description)
122
+ return left + right if right <= SIZE_MAX - left
123
+
124
+ raise RangeError, "#{description} exceeds native implementation limit"
125
+ end
93
126
  end
94
127
 
95
128
  private_constant :OperationShapes
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Convolver
4
+ # Shared estimates for input copies and Ruby boundary/folding work.
5
+ # @private
6
+ class PreparationCost
7
+ CONVERSION_COST = 7.5e-10
8
+ EXTENSION_COST = 1.0e-9
9
+ INDEX_COST = { nearest: 1.45e-7, reflect: 1.33e-7, mirror: 1.54e-7, wrap: 1.05e-7 }.freeze
10
+ FOLD_COST = { 1 => 3.3e-7, 2 => 3.7e-7, 3 => 5.5e-7 }.freeze
11
+
12
+ def initialize(plan)
13
+ @plan = plan
14
+ end
15
+
16
+ def conversion
17
+ CONVERSION_COST * plan.conversion_size
18
+ end
19
+
20
+ def extension
21
+ return 0.0 if plan.valid?
22
+
23
+ (EXTENSION_COST * plan.extended_size * (plan.dtype::ELEMENT_BYTE_SIZE / 4)) + indices
24
+ end
25
+
26
+ def indices
27
+ return 0.0 if plan.valid? || plan.boundary == :constant
28
+
29
+ costs = plan.cost_profile ? plan.cost_profile.fetch(:indices) : INDEX_COST
30
+ costs.fetch(plan.boundary) * plan.extended_shape.sum
31
+ end
32
+
33
+ def folding(kernel_size)
34
+ rank = plan.result_shape.length
35
+ return plan.cost_profile.fetch(:folding).fetch(rank - 1) * kernel_size if plan.cost_profile
36
+
37
+ FOLD_COST.fetch(rank, FOLD_COST.values.last) * kernel_size
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :plan
43
+ end
44
+
45
+ private_constant :PreparationCost
46
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'convolver/fft_limits'
4
+
5
+ module Convolver
6
+ # Selects a safe real-transform shape from exact/even and fast candidates.
7
+ # @private
8
+ class RealFftShape
9
+ def initialize(minimum_shape, size_max:, limits: nil)
10
+ @minimum_shape = minimum_shape
11
+ @size_max = size_max
12
+ @limits = limits
13
+ end
14
+
15
+ def call
16
+ exact_shape = even_final_axis(minimum_shape)
17
+ candidates = [exact_shape, fast_shape(exact_shape)].compact.select { |shape| admissible?(shape) }
18
+ (candidates.min_by { |shape| transform_cost(shape) } || raise_rejection).freeze
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :minimum_shape, :size_max, :limits
24
+
25
+ def admissible?(shape)
26
+ return false unless representable?(shape)
27
+
28
+ limits&.validate!(shape, real_axis: shape.length - 1)
29
+ true
30
+ rescue FftUnavailable => e
31
+ @rejection ||= e
32
+ false
33
+ end
34
+
35
+ def raise_rejection
36
+ raise @rejection if @rejection
37
+
38
+ raise_overflow
39
+ end
40
+
41
+ def fast_shape(exact_shape)
42
+ Convolver.send(:fft_fast_shape, exact_shape, size_max)
43
+ end
44
+
45
+ def even_final_axis(shape)
46
+ result = shape.dup
47
+ result[-1] = checked_add(result[-1], 1) if result[-1].odd?
48
+ result.freeze
49
+ end
50
+
51
+ def transform_cost(shape)
52
+ Convolver.send(:fft_shape_cost, shape)
53
+ end
54
+
55
+ def representable?(shape)
56
+ shape.reduce(1) do |product, size|
57
+ return false if !product.zero? && size > size_max / product
58
+
59
+ product * size
60
+ end
61
+ true
62
+ end
63
+
64
+ def checked_add(left, right)
65
+ return left + right if right <= size_max - left
66
+
67
+ raise_overflow
68
+ end
69
+
70
+ def raise_overflow
71
+ raise(limits ? FftUnavailable : RangeError, 'FFT shape exceeds native implementation limit')
72
+ end
73
+ end
74
+
75
+ private_constant :RealFftShape
76
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Convolver
4
4
  # Extends a signal according to one operation's boundary policy.
5
+ # @private
5
6
  class SignalExtension
6
7
  def initialize(shapes, boundary:, fill_value:)
7
8
  @shapes = shapes
@@ -10,7 +11,7 @@ module Convolver
10
11
  end
11
12
 
12
13
  def call(signal)
13
- source = Numo::SFloat.cast(signal)
14
+ source = signal
14
15
  return constant_extension(source) if boundary == :constant
15
16
 
16
17
  source[*extension_indices]
@@ -21,7 +22,7 @@ module Convolver
21
22
  attr_reader :shapes, :boundary, :fill_value
22
23
 
23
24
  def constant_extension(source)
24
- extended = Numo::SFloat.new(*shapes.extended_shape).fill(fill_value)
25
+ extended = source.class.new(*shapes.extended_shape).fill(fill_value)
25
26
  ranges = source.shape.zip(shapes.padding_before).map do |signal_size, before|
26
27
  before...(before + signal_size)
27
28
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Convolver
4
4
  # Current gem version.
5
- VERSION = '2.0.0'
5
+ VERSION = '4.0.0'
6
6
  end
data/lib/convolver.rb CHANGED
@@ -5,153 +5,140 @@ require 'numo/pocketfft'
5
5
  require 'convolver/convolver'
6
6
  require 'convolver/version'
7
7
 
8
- # Cross-correlation operations for Numo::NArray values.
8
+ # Mathematical convolution and cross-correlation for Numo::NArray values.
9
9
  module Convolver
10
10
  # Maximum number of dimensions supported by the implementations.
11
11
  MAX_RANK = 16
12
12
 
13
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'
14
18
 
15
19
  class << self
16
- # Chooses the likely fastest cross-correlation implementation.
20
+ # Chooses the likely fastest mathematical convolution implementation.
21
+ #
22
+ # Results use the dtype selected from both inputs, unless dtype overrides it.
23
+ # Inputs must be nonempty arrays of equal rank, with at most {MAX_RANK}
24
+ # dimensions. Scalars multiply directly.
25
+ # In valid mode the kernel must fit inside the signal in every dimension.
26
+ # Full mode permits only constant boundaries; nonconstant boundaries and
27
+ # nonzero origins are supported only in same mode.
17
28
  #
18
- # @param signal [Numo::NArray] input values
19
- # @param kernel [Numo::NArray] correlation kernel
20
- # @param mode [:valid, :same, :full] returned output extent
21
- # @param boundary [:constant, :nearest, :reflect, :mirror, :wrap] signal extension
22
- # @param fill_value [Numeric] constant extension value
23
- # @param origin [Integer, Array<Integer>] kernel origin shift
24
- # @return [Numo::SFloat] cross-correlation result
25
- # @raise [ArgumentError] if inputs or options are incompatible
29
+ # @param signal [Numo::NArray] input signal
30
+ # @param kernel [Numo::NArray] convolution kernel
31
+ # @param mode [:valid, :same, :full] output extent (default: :valid)
32
+ # @param boundary [:constant, :nearest, :reflect, :mirror, :wrap]
33
+ # signal extension policy (default: :constant)
34
+ # @param fill_value [Numeric] constant boundary value (default: 0);
35
+ # valid mode requires zero, and other boundaries reject this option
36
+ # @param origin [Integer, Array<Integer>] offset from the kernel midpoint,
37
+ # shared across axes or one per axis (default: 0)
38
+ # @param dtype [Class, nil] Numo::SFloat or Numo::DFloat; nil promotes both inputs.
39
+ # Integer types of 8/16 bits select SFloat; 32/64 bits select DFloat.
40
+ # Only these concrete integer and floating classes are supported.
41
+ # @return [Numo::SFloat, Numo::DFloat] mathematical convolution result
42
+ # @raise [ArgumentError] if inputs or options are invalid
43
+ # @raise [RangeError] if planned dimensions, buffers or FFT arithmetic exceed native limits
26
44
  def convolve(signal, kernel, mode: :valid, boundary: :constant,
27
- fill_value: UNSPECIFIED_FILL, origin: 0)
28
- plan = operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
29
- options = operation_options(mode, boundary, fill_value, origin)
30
-
31
- return convolve_basic(signal, kernel, **options) if plan.extended_size < 1000 || kernel.size < 100
32
-
33
- basic_time_predicted = predict_convolve_basic_time(signal, kernel, **options)
34
- return convolve_basic(signal, kernel, **options) if basic_time_predicted < 0.1
35
-
36
- fft_time_predicted = predict_convolve_fft_time(signal, kernel, **options)
37
- return convolve_fft(signal, kernel, **options) if fft_time_predicted < 2 * basic_time_predicted
45
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
46
+ execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).automatic
47
+ end
38
48
 
39
- convolve_basic(signal, kernel, **options)
49
+ # Chooses the likely fastest cross-correlation implementation.
50
+ # Uses the same input and option rules as {.convolve}, without reversing
51
+ # the kernel's orientation.
52
+ # @param (see convolve)
53
+ # @return [Numo::SFloat, Numo::DFloat] cross-correlation result
54
+ # @raise (see convolve)
55
+ def correlate(signal, kernel, mode: :valid, boundary: :constant,
56
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
57
+ execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).automatic
40
58
  end
41
59
 
42
- # Uses the direct native valid primitive after applying the requested signal
43
- # extension in Ruby.
44
- #
45
- # @return [Numo::SFloat] cross-correlation result
60
+ # Uses the direct native mathematical convolution implementation.
61
+ # @param (see convolve)
62
+ # @return [Numo::SFloat, Numo::DFloat] mathematical convolution result
63
+ # @raise (see convolve)
46
64
  def convolve_basic(signal, kernel, mode: :valid, boundary: :constant,
47
- fill_value: UNSPECIFIED_FILL, origin: 0)
48
- plan = operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
49
- convolve_basic_valid(plan.extend_signal(signal), kernel)
65
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
66
+ execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).basic
50
67
  end
51
68
 
52
- # Uses PocketFFT to calculate the requested cross-correlation.
53
- #
54
- # Periodic same-sized results use a circular transform. Other combinations
55
- # use the shared extension plan and PocketFFT's linear convolution.
56
- #
57
- # @return [Numo::SFloat] cross-correlation result
58
- def convolve_fft(signal, kernel, mode: :valid, boundary: :constant,
59
- fill_value: UNSPECIFIED_FILL, origin: 0)
60
- plan = operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
61
- return convolve_fft_wrap(signal, kernel, plan) if plan.wrap?
69
+ # Uses the direct native cross-correlation implementation.
70
+ # @param (see convolve)
71
+ # @return [Numo::SFloat, Numo::DFloat] cross-correlation result
72
+ # @raise (see convolve)
73
+ def correlate_basic(signal, kernel, mode: :valid, boundary: :constant,
74
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
75
+ execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).basic
76
+ end
62
77
 
63
- convolve_fft_valid(plan.extend_signal(signal), kernel)
78
+ # Uses PocketFFT to calculate mathematical convolution.
79
+ # @param (see convolve)
80
+ # @return [Numo::SFloat, Numo::DFloat] mathematical convolution result
81
+ # @raise (see convolve)
82
+ def convolve_fft(signal, kernel, mode: :valid, boundary: :constant,
83
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
84
+ execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).fft
64
85
  end
65
86
 
66
- # Compatibility alias for the former FFTW3-backed implementation.
67
- #
68
- # @deprecated Use {.convolve_fft}; Convolver no longer uses FFTW3.
69
- # @return [Numo::SFloat] cross-correlation result
70
- def convolve_fftw3(signal, kernel, mode: :valid, boundary: :constant,
71
- fill_value: UNSPECIFIED_FILL, origin: 0)
72
- warn 'Convolver.convolve_fftw3 is deprecated; use .convolve_fft instead', uplevel: 1
73
- options = operation_options(mode, boundary, fill_value, origin)
74
- convolve_fft(signal, kernel, **options)
87
+ # Uses PocketFFT to calculate cross-correlation.
88
+ # @param (see convolve)
89
+ # @return [Numo::SFloat, Numo::DFloat] cross-correlation result
90
+ # @raise (see convolve)
91
+ def correlate_fft(signal, kernel, mode: :valid, boundary: :constant,
92
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
93
+ execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).fft
75
94
  end
76
95
 
77
- # Estimates the relative cost of {.convolve_fft} for the requested options.
78
- #
96
+ # Estimates the relative cost of {.convolve_fft}.
97
+ # This is a heuristic for algorithm selection, not a timing measurement.
98
+ # @param (see convolve)
79
99
  # @return [Float] machine-specific relative cost estimate
100
+ # @raise (see convolve)
80
101
  def predict_convolve_fft_time(signal, kernel, mode: :valid, boundary: :constant,
81
- fill_value: UNSPECIFIED_FILL, origin: 0)
82
- plan = operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
83
- transform_size = plan.wrap? ? signal.size : plan.linear_fft_size(kernel.shape)
84
- transform_cost = 16 * 4.55e-08 * transform_size * Math.log(transform_size)
85
- transform_cost + (4.55e-08 * fft_preparation_size(plan, signal, kernel))
102
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
103
+ execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).fft_time
86
104
  end
87
105
 
88
- # Estimates the relative cost of {.convolve_basic} for the requested options.
89
- #
106
+ # Estimates the relative cost of {.correlate_fft}.
107
+ # This is a heuristic for algorithm selection, not a timing measurement.
108
+ # @param (see convolve)
90
109
  # @return [Float] machine-specific relative cost estimate
91
- def predict_convolve_basic_time(signal, kernel, mode: :valid, boundary: :constant,
92
- fill_value: UNSPECIFIED_FILL, origin: 0)
93
- plan = operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
94
- operations = plan.result_size * plan.extended_size * kernel.size
95
- operations += plan.extended_size unless plan.valid?
96
- 4.54e-12 * operations
110
+ # @raise (see convolve)
111
+ def predict_correlate_fft_time(signal, kernel, mode: :valid, boundary: :constant,
112
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
113
+ execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).fft_time
97
114
  end
98
115
 
99
- private
100
-
101
- private :convolve_basic_valid
102
-
103
- def operation_plan(signal, kernel, mode:, boundary:, fill_value:, origin:)
104
- OperationPlan.new(signal, kernel, mode:, boundary:, fill_value:, origin:)
105
- end
106
-
107
- def operation_options(mode, boundary, fill_value, origin)
108
- options = { mode:, boundary:, origin: }
109
- options[:fill_value] = fill_value unless fill_value.equal?(UNSPECIFIED_FILL)
110
- options
111
- end
112
-
113
- def convolve_fft_valid(signal, kernel)
114
- ranges = kernel.shape.zip(signal.shape).map do |kernel_size, signal_size|
115
- (kernel_size - 1)...signal_size
116
- end
117
- full_convolution = Numo::Pocketfft.fftconvolve(signal, kernel.reverse)
118
-
119
- Numo::SFloat.cast(full_convolution[*ranges])
120
- end
121
-
122
- def convolve_fft_wrap(signal, kernel, plan)
123
- signal_value = Numo::DFloat.cast(signal)
124
- folded_kernel = fold_kernel(Numo::DFloat.cast(kernel), signal.shape, plan.anchors)
125
- spectrum = Numo::Pocketfft.fftn(signal_value) * Numo::Pocketfft.fftn(folded_kernel).conj
126
-
127
- Numo::SFloat.cast(Numo::Pocketfft.ifftn(spectrum).real)
116
+ # Estimates the relative cost of {.convolve_basic}.
117
+ # This is a heuristic for algorithm selection, not a timing measurement.
118
+ # @param (see convolve)
119
+ # @return [Float] machine-specific relative cost estimate
120
+ # @raise (see convolve)
121
+ def predict_convolve_basic_time(signal, kernel, mode: :valid, boundary: :constant,
122
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
123
+ execution(:convolution, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).basic_time
128
124
  end
129
125
 
130
- def fold_kernel(kernel, signal_shape, anchors)
131
- folded = Numo::DFloat.zeros(*signal_shape)
132
- kernel.flatten.each_with_index do |value, flat_index|
133
- target = folded_kernel_target(flat_index, kernel.shape, signal_shape, anchors)
134
- folded[*target] = folded[*target] + value
135
- end
136
- folded
126
+ # Estimates the relative cost of {.correlate_basic}.
127
+ # This is a heuristic for algorithm selection, not a timing measurement.
128
+ # @param (see convolve)
129
+ # @return [Float] machine-specific relative cost estimate
130
+ # @raise (see convolve)
131
+ def predict_correlate_basic_time(signal, kernel, mode: :valid, boundary: :constant,
132
+ fill_value: UNSPECIFIED_FILL, origin: 0, dtype: nil)
133
+ execution(:correlation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:).basic_time
137
134
  end
138
135
 
139
- def folded_kernel_target(flat_index, kernel_shape, signal_shape, anchors)
140
- remainder = flat_index
141
- Array.new(kernel_shape.length).tap do |target|
142
- (kernel_shape.length - 1).downto(0) do |axis|
143
- coordinate = remainder % kernel_shape[axis]
144
- remainder /= kernel_shape[axis]
145
- target[axis] = (coordinate - anchors[axis]) % signal_shape[axis]
146
- end
147
- end
148
- end
136
+ private
149
137
 
150
- def fft_preparation_size(plan, signal, kernel)
151
- return signal.size + kernel.size if plan.wrap?
152
- return 0 if plan.valid?
138
+ private :convolve_basic_valid, :correlate_basic_valid, :fft_fast_shape, :fft_shape_cost
153
139
 
154
- plan.extended_size
140
+ def execution(operation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:)
141
+ OperationExecution.new(operation, signal, kernel, mode:, boundary:, fill_value:, origin:, dtype:)
155
142
  end
156
143
  end
157
144
  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: 2.0.0
4
+ version: 4.0.0
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.11'
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.11'
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: '0.6'
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: '0.6'
48
+ version: 0.7.0
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: '0.8'
52
- description: Fast cross-correlation for multidimensional Numo::NArray values, with
53
- configurable output and boundary modes.
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,11 +64,31 @@ 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
70
+ - ext/convolver/fft_shape.c
71
+ - ext/convolver/fft_shape.h
72
+ - ext/convolver/raw_config.h
73
+ - ext/convolver/raw_helpers.h
74
+ - ext/convolver/raw_loop.h
68
75
  - lib/convolver.rb
76
+ - lib/convolver/buffer_limits.rb
77
+ - lib/convolver/buffer_preparation.rb
78
+ - lib/convolver/circular_fft_operation.rb
79
+ - lib/convolver/cost_profiles.rb
80
+ - lib/convolver/fft_buffer_plan.rb
81
+ - lib/convolver/fft_cost.rb
82
+ - lib/convolver/fft_estimator.rb
83
+ - lib/convolver/fft_limits.rb
84
+ - lib/convolver/linear_fft_operation.rb
85
+ - lib/convolver/operation_dtype.rb
86
+ - lib/convolver/operation_execution.rb
69
87
  - lib/convolver/operation_options.rb
70
88
  - lib/convolver/operation_plan.rb
71
89
  - lib/convolver/operation_shapes.rb
90
+ - lib/convolver/preparation_cost.rb
91
+ - lib/convolver/real_fft_shape.rb
72
92
  - lib/convolver/signal_extension.rb
73
93
  - lib/convolver/version.rb
74
94
  homepage: https://github.com/neilslater/convolver
@@ -93,5 +113,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
113
  requirements: []
94
114
  rubygems_version: 4.0.16
95
115
  specification_version: 4
96
- summary: Fast cross-correlation for Numo::NArray
116
+ summary: Fast convolution and cross-correlation for Numo::NArray
97
117
  test_files: []