convolver 0.4.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c83dcadafabcbb8a971258601e61697a35d73afc28e7341bbe9d6f5fee887e3
4
- data.tar.gz: dfc6018d6b2ae5a9ea7570036874f036961e9925c18e41116b481b4604f0cc56
3
+ metadata.gz: 4c27f2aa98b988627391d0a9812c6b8e0a59e65cf4a506592d95f43d1a02e3ae
4
+ data.tar.gz: ede25a5203ed707bd3ca726eb513ceb44746bc5a04c294396d368ab3785b2c4c
5
5
  SHA512:
6
- metadata.gz: 41b62c830ba924ddc25abcf92363fcf474477d806e4040d7c694496ed1eda15d3929e4bfeea2597b7ee372baa28c44991d69c9941cfa7db753070ca8bac7b90c
7
- data.tar.gz: 0fd4024a1a4eb0c1b0a6059e6f606508e048dc4a6e56d5499e0c5b94d85669ba17831472a0c3167e1361b8b25ec299d665cab3a4bc38162c363c756dddb60ecc
6
+ metadata.gz: aaf0fc6ab38eedbe06c2082b8ffaa2cdbfab45b3340aadf7c87839d28aa97dbb3be1e22a99c3aef25207b656741c69763bb177003d74e440ce7d6653be22aff8
7
+ data.tar.gz: 20b127fa09a8c6b449e74183da3fa91a93603bc17701b4991543de6095ae64023ef217c166d5a7ef999a241de125c7278e6f1e2b3d895f5ec0d0fe2665188bd5
data/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-07-21
9
+
10
+ ### Added
11
+
12
+ - Native C quality tasks for strict compiler warnings (`c:lint`), GCC/gcovr
13
+ coverage (`c:coverage`), and ASan/UBSan checks (`c:sanitize`).
14
+ - GitHub Actions reporting and downloadable HTML and Cobertura artifacts for C
15
+ coverage.
16
+ - RuboCop checks with Rake and RSpec plugins.
17
+ - SimpleCov reporting for the Ruby test suite.
18
+ - Support for Ruby 4.0 in the CI test matrix.
19
+ - Monthly scheduled CI runs to detect dependency and toolchain regressions.
20
+ - Ruby branch-coverage reporting and additional coverage of native input
21
+ validation.
22
+
23
+ ### Changed
24
+
25
+ - **Breaking:** Replaced the unmaintained `narray` dependency with
26
+ `numo-narray-alt`. Public methods now accept `Numo::NArray` values and return
27
+ `Numo::SFloat` results instead of legacy `NArray` values.
28
+ - **Breaking:** Raised the minimum supported Ruby version to 3.2.
29
+ - Replaced the `fftw3` gem and external FFTW library with `numo-pocketfft`,
30
+ removing the system FFTW installation requirement.
31
+ - Renamed the FFT-backed implementation from `convolve_fftw3` to
32
+ `convolve_fft`. The old name remains as a deprecated compatibility alias.
33
+ - Clarified that the operations calculate valid cross-correlation and expanded
34
+ the README and YARD documentation for input, output, and shape behaviour.
35
+ - Replaced the retired Travis CI configuration with GitHub Actions.
36
+ - Improved gem metadata and limited packaged files to the library, native
37
+ extension, documentation, and licence.
38
+
39
+ ### Fixed
40
+
41
+ - Reject non-Numo inputs, empty arrays, unequal ranks, kernels larger than their
42
+ signals, and ranks unsupported by the native implementation with descriptive
43
+ `ArgumentError` messages.
44
+ - Updated the native extension to use the maintained Numo C API and removed the
45
+ legacy untyped-data compatibility code.
46
+
47
+ [1.0.0]: https://github.com/neilslater/convolver/compare/v0.3.2...v1.0.0
data/README.md CHANGED
@@ -1,86 +1,99 @@
1
1
  # Convolver
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/convolver.png)](http://badge.fury.io/rb/convolver)
4
- [![Build Status](https://api.travis-ci.com/neilslater/convolver.png?branch=master)](https://travis-ci.com/github/neilslater/convolver)
5
- [![Coverage Status](https://coveralls.io/repos/neilslater/convolver/badge.png?branch=master)](https://coveralls.io/r/neilslater/convolver?branch=master)
6
- [![Code Climate](https://codeclimate.com/github/neilslater/convolver.png)](https://codeclimate.com/github/neilslater/convolver)
3
+ [![Gem Version](https://badge.fury.io/rb/convolver.svg)](https://badge.fury.io/rb/convolver)
7
4
 
8
- Calculates discrete convolution between two multi-dimensional arrays of floats.
9
- See http://en.wikipedia.org/wiki/Convolution
5
+ Convolver calculates valid cross-correlations between multidimensional
6
+ [`Numo::NArray`](https://github.com/yoshoku/numo-narray-alt) values. It chooses
7
+ between a direct native implementation for smaller inputs and a
8
+ [`Numo::Pocketfft`](https://github.com/yoshoku/numo-pocketfft)-based
9
+ implementation for larger inputs.
10
10
 
11
- ## Installation
11
+ Version 1.0 replaces the unmaintained `narray` and `fftw3` gems with
12
+ `numo-narray-alt` and `numo-pocketfft`.
12
13
 
13
- ### Dependency: FFTW3
14
+ ## Installation
14
15
 
15
- Before you install *convolver*, you should install the FFTW3 library on your system.
16
- See http://www.fftw.org/ for details.
16
+ Add Convolver to your application's Gemfile:
17
17
 
18
- On macOS with Homebrew, the `fftw3` Ruby gem needs to be told where Homebrew
19
- installed the headers and libraries:
18
+ ```ruby
19
+ gem 'convolver'
20
+ ```
20
21
 
21
- brew install fftw
22
- bundle config set --local build.fftw3 "--with-fftw3-dir=$(brew --prefix fftw)"
23
- bundle install
22
+ Then run:
24
23
 
25
- The local Bundler setting is written to `.bundle/config`, which is intentionally
26
- not committed because the Homebrew prefix depends on the machine.
24
+ ```sh
25
+ bundle install
26
+ ```
27
27
 
28
- ### Known warning with Ruby 3.4
28
+ Alternatively, install it directly:
29
29
 
30
- The first use of `NArray` may emit this warning:
30
+ ```sh
31
+ gem install convolver
32
+ ```
31
33
 
32
- warning: undefining the allocator of T_DATA class NArray
34
+ No external FFT library is required; PocketFFT is bundled by its Ruby gem.
33
35
 
34
- This comes from the legacy native allocation API used by `narray` 0.6.1.2. Ruby
35
- disables the inherited allocator when the first native NArray object is created.
36
- The warning does not affect convolver's results; removing it properly requires a
37
- fix in `narray` or a future migration to a maintained NArray implementation.
36
+ ## Usage
38
37
 
39
- ### Installing the gem
38
+ ```ruby
39
+ require 'convolver'
40
40
 
41
- Add this line to your application's Gemfile:
41
+ signal = Numo::SFloat[0.3, 0.4, 0.5]
42
+ kernel = Numo::SFloat[1.3, -0.5]
42
43
 
43
- gem 'convolver'
44
+ Convolver.convolve(signal, kernel)
45
+ # => Numo::SFloat#shape=[2]
46
+ # [0.19, 0.27]
47
+ ```
44
48
 
45
- And then execute:
49
+ The signal and kernel must have the same rank, and the kernel must be no larger
50
+ than the signal in any dimension. Convolver returns only positions at which the
51
+ kernel overlaps the signal completely. The result size in each dimension is:
46
52
 
47
- $ bundle
53
+ ```ruby
54
+ signal_size - kernel_size + 1
55
+ ```
48
56
 
49
- Or install it yourself as:
57
+ Inputs are converted to single-precision floats internally, and results are
58
+ returned as `Numo::SFloat`. Supplying `Numo::SFloat` inputs avoids conversion in
59
+ the direct implementation.
50
60
 
51
- $ gem install convolver
61
+ `Convolver.convolve` normally chooses the implementation automatically. The
62
+ implementations can also be called directly for application-specific
63
+ benchmarking:
52
64
 
53
- ## Usage
65
+ ```ruby
66
+ Convolver.convolve_basic(signal, kernel)
67
+ Convolver.convolve_fft(signal, kernel)
68
+ ```
54
69
 
55
- Basic convolution:
70
+ `Convolver.convolve_fftw3` remains as a deprecated alias for `convolve_fft` to
71
+ ease migration from Convolver 0.x.
56
72
 
57
- a = NArray[0.3,0.4,0.5]
58
- b = NArray[1.3, -0.5]
59
- c = Convolver.convolve( a, b )
60
- => NArray.float(2): [ 0.19, 0.27 ]
61
-
62
- * Convolver only works on single-precision floats internally. It will cast NArray types to this, if
63
- possible, prior to calculating. For best speed, use NArray.sfloat arrays.
73
+ ## Contributing
64
74
 
65
- * The output is smaller than the input, it only contains fully-calculated values. The output size
66
- is the original size, minus the kernel size, plus 1, in each dimension.
75
+ Install the development dependencies, then run the main suite:
67
76
 
68
- * Convolver expects input a and kernel b to have the same rank, and for the kernel to be same size
69
- or smaller in all dimensions as the input.
77
+ ```sh
78
+ bundle install
79
+ bundle exec rake
80
+ bundle exec rubocop
81
+ bundle exec rake c:lint
82
+ ```
70
83
 
71
- * Convolver.convolve will try to choose the faster of two approaches it has coded. In general,
72
- small convolutions are processed directly by multiplying out all combinations and summing them,
73
- and large convolutions are processed using FFTW3 to convert to frequency space where convolution
74
- is simpler and faster to calculate, then convert back.
84
+ The Ruby specs exercise both the Ruby API and native extension. Additional
85
+ native-code checks are available:
75
86
 
76
- ## Contributing
87
+ ```sh
88
+ bundle exec rake c:coverage # Requires GCC and gcovr
89
+ bundle exec rake c:sanitize # Requires Linux and GCC
90
+ ```
77
91
 
78
- 1. Fork it
79
- 2. Create your feature branch (`git checkout -b my-new-feature`)
80
- 3. Commit your changes (`git commit -am 'Add some feature'`)
81
- 4. Push to the branch (`git push origin my-new-feature`)
82
- 5. Create new Pull Request
92
+ `c:coverage` writes HTML and Cobertura reports under `coverage/c`. CI uploads
93
+ the reports as a `c-coverage` artifact. The sanitizer task uses AddressSanitizer
94
+ and UndefinedBehaviorSanitizer.
83
95
 
84
96
  ## Contributors
85
97
 
86
- * [Dima Ermilov](https://github.com/adworse) contributed fix to support compiling under Windows.
98
+ - [Dima Ermilov](https://github.com/adworse) contributed the original Windows
99
+ compilation support.
@@ -2,7 +2,7 @@
2
2
 
3
3
  #include "convolve_raw.h"
4
4
 
5
- inline int size_from_shape( int rank, int *shape ) {
5
+ static inline int size_from_shape( int rank, int *shape ) {
6
6
  int size = 1;
7
7
  int i;
8
8
  for ( i = 0; i < rank; i++ ) { size *= shape[i]; }
@@ -10,15 +10,16 @@ inline int size_from_shape( int rank, int *shape ) {
10
10
  }
11
11
 
12
12
  // Sets reverse indices
13
- inline void corner_reset( int rank, int *shape, int *rev_indices ) {
13
+ static inline void corner_reset( int rank, int *shape, int *rev_indices ) {
14
14
  int i;
15
15
  for ( i = 0; i < rank; i++ ) { rev_indices[i] = shape[i] - 1; }
16
16
  return;
17
17
  }
18
18
 
19
19
  // Counts indices down, returns number of ranks that reset
20
- inline int corner_dec( int rank, int *shape, int *rev_indices ) {
20
+ static inline int corner_dec( int rank, int *shape, int *rev_indices ) {
21
21
  int i = 0;
22
+ (void) rank;
22
23
  while ( ! rev_indices[i]-- ) {
23
24
  rev_indices[i] = shape[i] - 1;
24
25
  i++;
@@ -27,7 +28,7 @@ inline int corner_dec( int rank, int *shape, int *rev_indices ) {
27
28
  }
28
29
 
29
30
  // Generates co-increment steps by rank boundaries crossed, for the outer position as inner position is incremented by 1
30
- inline void calc_co_increment( int rank, int *outer_shape, int *inner_shape, int *co_increment ) {
31
+ static inline void calc_co_increment( int rank, int *outer_shape, int *inner_shape, int *co_increment ) {
31
32
  int i, factor;
32
33
  co_increment[0] = 1; // co-increment is always 1 in lowest rank
33
34
  factor = 1;
@@ -48,12 +49,11 @@ void convolve_raw(
48
49
  int in_rank, int *in_shape, float *in_ptr,
49
50
  int kernel_rank, int *kernel_shape, float *kernel_ptr,
50
51
  int out_rank, int *out_shape, float *out_ptr ) {
51
- int i, j, in_size, kernel_size, kernel_aligned, out_size, offset;
52
+ int i, j, kernel_size, kernel_aligned, out_size, offset;
52
53
  int out_co_incr[LARGEST_RANK], kernel_co_incr[LARGEST_RANK];
53
54
  int ker_q[LARGEST_RANK], out_q[LARGEST_RANK];
54
55
  int *kernel_co_incr_cache;
55
56
 
56
- in_size = size_from_shape( in_rank, in_shape );
57
57
  kernel_size = size_from_shape( kernel_rank, kernel_shape );
58
58
  kernel_aligned = 4 * (kernel_size/4);
59
59
  out_size = size_from_shape( out_rank, out_shape );
@@ -15,8 +15,6 @@
15
15
  #else
16
16
  #define CONVOLVER_USE_SSE 0
17
17
  #endif
18
- #include "narray_shared.h"
19
-
20
18
  #define LARGEST_RANK 16
21
19
 
22
20
  void convolve_raw(
@@ -1,118 +1,89 @@
1
- // ext/convolver/convolver.c
2
-
1
+ #include <limits.h>
3
2
  #include <ruby.h>
4
- #include "narray.h"
5
- #include <stdio.h>
3
+ #include <numo/narray.h>
4
+ #include <numo/intern.h>
6
5
 
7
- #include "narray_shared.h"
8
6
  #include "convolve_raw.h"
9
7
 
10
- ////////////////////////////////////////////////////////////////////////////////////////////////////
11
-
12
- // To hold the module object
13
- VALUE Convolver = Qnil;
14
-
15
- /* @overload fit_kernel_backwards( fft_temp_space, kernel )
16
- * @!visibility private
17
- * Over-writes fft_temp_space at edges with a reversed copy of kernel, in such a way that
18
- * an FFTW3-based convolve has a result set in an easy-to-extract position later. This is
19
- * implemented as a native extension for convenience and speed - to do this with methods provided
20
- * by narray gem would take several complex steps and be inefficient.
21
- * @param [NArray<sfloat>] fft_temp_space target array for pre-fft copy of kernel, is over-written
22
- * @param [NArray] kernel must be same size or smaller than fft_temp_space in each dimension
23
- * @return [nil]
24
- */
25
- static VALUE narray_fit_backwards( VALUE self, VALUE a, VALUE b ) {
26
- struct NARRAY *na_a, *na_b;
27
- volatile VALUE val_a, val_b;
28
- int target_rank, i;
29
- int shift_by[LARGEST_RANK];
30
-
31
- val_a = na_cast_object(a, NA_SFLOAT);
32
- GetNArray( val_a, na_a );
33
-
34
- val_b = na_cast_object(b, NA_SFLOAT);
35
- GetNArray( val_b, na_b );
36
-
37
- if ( na_a->rank != na_b->rank ) {
38
- rb_raise( rb_eArgError, "narray a must have equal rank to narray b (a rank %d, b rank %d)", na_a->rank, na_b->rank );
39
- }
40
-
41
- if ( na_a->rank > LARGEST_RANK ) {
42
- rb_raise( rb_eArgError, "exceeded maximum narray rank for convolve of %d", LARGEST_RANK );
43
- }
8
+ static VALUE mConvolver;
44
9
 
45
- target_rank = na_a->rank;
10
+ static void copy_shape(int rank, const size_t *source, int *target) {
11
+ int i;
46
12
 
47
- for ( i = 0; i < target_rank; i++ ) {
48
- if ( ( na_a->shape[i] - na_b->shape[i] ) < 0 ) {
49
- rb_raise( rb_eArgError, "no space for backward fit" );
13
+ for (i = 0; i < rank; i++) {
14
+ if (source[rank - i - 1] > INT_MAX) {
15
+ rb_raise(rb_eArgError, "array dimension exceeds native implementation limit");
50
16
  }
51
- shift_by[i] = na_b->shape[i] >> 1;
17
+ target[i] = (int)source[rank - i - 1];
52
18
  }
53
-
54
- fit_backwards_raw(
55
- target_rank,
56
- na_a->shape, (float*) na_a->ptr,
57
- na_b->shape, (float*) na_b->ptr,
58
- shift_by );
59
-
60
- return Qnil;
61
19
  }
62
20
 
63
-
64
- /* @overload convolve_basic( signal, kernel )
65
- * Calculates convolution of an array of floats representing a signal, with a second array representing
66
- * a kernel. The two parameters must have the same rank. The output has same rank, its size in each dimension d is given by
67
- * signal.shape[d] - kernel.shape[d] + 1
68
- * @param [NArray] signal must be same size or larger than kernel in each dimension
69
- * @param [NArray] kernel must be same size or smaller than signal in each dimension
70
- * @return [NArray] result of convolving signal with kernel
21
+ /*
22
+ * Calculates a valid cross-correlation using the direct native implementation.
23
+ *
24
+ * @overload convolve_basic(signal, kernel)
25
+ * @param signal [Numo::NArray] input values
26
+ * @param kernel [Numo::NArray] correlation kernel
27
+ * @return [Numo::SFloat] valid cross-correlation result
71
28
  */
72
- static VALUE narray_convolve( VALUE self, VALUE a, VALUE b ) {
73
- struct NARRAY *na_a, *na_b, *na_c;
74
- volatile VALUE val_a, val_b, val_c;
75
- int target_rank, i;
76
- int target_shape[LARGEST_RANK];
77
-
78
- val_a = na_cast_object(a, NA_SFLOAT);
79
- GetNArray( val_a, na_a );
29
+ static VALUE convolver_convolve_basic(VALUE self, VALUE signal, VALUE kernel) {
30
+ volatile VALUE signal_value;
31
+ volatile VALUE kernel_value;
32
+ volatile VALUE result_value;
33
+ narray_t *signal_narray;
34
+ narray_t *kernel_narray;
35
+ int rank;
36
+ int i;
37
+ int signal_shape[LARGEST_RANK];
38
+ int kernel_shape[LARGEST_RANK];
39
+ int result_shape[LARGEST_RANK];
40
+ size_t numo_result_shape[LARGEST_RANK];
41
+
42
+ (void)self;
43
+
44
+ if (!rb_obj_is_kind_of(signal, numo_cNArray) || !rb_obj_is_kind_of(kernel, numo_cNArray)) {
45
+ rb_raise(rb_eArgError, "signal and kernel must be Numo::NArray values");
46
+ }
80
47
 
81
- val_b = na_cast_object(b, NA_SFLOAT);
82
- GetNArray( val_b, na_b );
48
+ signal_value = rb_funcall(numo_cSFloat, rb_intern("cast"), 1, signal);
49
+ kernel_value = rb_funcall(numo_cSFloat, rb_intern("cast"), 1, kernel);
50
+ GetNArray(signal_value, signal_narray);
51
+ GetNArray(kernel_value, kernel_narray);
83
52
 
84
- if ( na_a->rank != na_b->rank ) {
85
- rb_raise( rb_eArgError, "narray a must have equal rank to narray b (a rack %d, b rank %d)", na_a->rank, na_b->rank );
53
+ if (signal_narray->size == 0 || kernel_narray->size == 0) {
54
+ rb_raise(rb_eArgError, "signal and kernel must not be empty");
86
55
  }
87
56
 
88
- if ( na_a->rank > LARGEST_RANK ) {
89
- rb_raise( rb_eArgError, "exceeded maximum narray rank for convolve of %d", LARGEST_RANK );
57
+ if (signal_narray->ndim != kernel_narray->ndim) {
58
+ rb_raise(rb_eArgError, "signal and kernel must have equal rank");
59
+ }
60
+ if (signal_narray->ndim > LARGEST_RANK) {
61
+ rb_raise(rb_eArgError, "maximum supported rank is %d", LARGEST_RANK);
90
62
  }
91
63
 
92
- target_rank = na_a->rank;
64
+ rank = signal_narray->ndim;
65
+ copy_shape(rank, signal_narray->shape, signal_shape);
66
+ copy_shape(rank, kernel_narray->shape, kernel_shape);
93
67
 
94
- for ( i = 0; i < target_rank; i++ ) {
95
- target_shape[i] = na_a->shape[i] - na_b->shape[i] + 1;
96
- if ( target_shape[i] < 1 ) {
97
- rb_raise( rb_eArgError, "narray b is bigger in one or more dimensions than narray a" );
68
+ for (i = 0; i < rank; i++) {
69
+ result_shape[i] = signal_shape[i] - kernel_shape[i] + 1;
70
+ if (result_shape[i] < 1) {
71
+ rb_raise(rb_eArgError, "kernel must not be larger than signal in any dimension");
98
72
  }
73
+ numo_result_shape[rank - i - 1] = (size_t)result_shape[i];
99
74
  }
100
75
 
101
- val_c = na_make_object( NA_SFLOAT, target_rank, target_shape, CLASS_OF( val_a ) );
102
- GetNArray( val_c, na_c );
103
-
76
+ result_value = nary_new(numo_cSFloat, rank, numo_result_shape);
104
77
  convolve_raw(
105
- target_rank, na_a->shape, (float*) na_a->ptr,
106
- target_rank, na_b->shape, (float*) na_b->ptr,
107
- target_rank, target_shape, (float*) na_c->ptr );
78
+ rank, signal_shape, (float *)na_get_pointer_for_read(signal_value),
79
+ rank, kernel_shape, (float *)na_get_pointer_for_read(kernel_value),
80
+ rank, result_shape, (float *)na_get_pointer_for_write(result_value)
81
+ );
108
82
 
109
- return val_c;
83
+ return result_value;
110
84
  }
111
85
 
112
- void Init_convolver() {
113
- Convolver = rb_define_module( "Convolver" );
114
- rb_define_singleton_method( Convolver, "convolve_basic", narray_convolve, 2 );
115
-
116
- // private method
117
- rb_define_singleton_method( Convolver, "fit_kernel_backwards", narray_fit_backwards, 2 );
86
+ void Init_convolver(void) {
87
+ mConvolver = rb_define_module("Convolver");
88
+ rb_define_singleton_method(mConvolver, "convolve_basic", convolver_convolve_basic, 2);
118
89
  }
@@ -1,37 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # ext/convolver/extconf.rb
4
3
  require 'mkmf'
5
- require 'rubygems'
4
+ require 'numo/narray/alt'
6
5
 
7
- # Following code stolen shamelessly from fftw3 gem:
8
- narray_dir = begin
9
- File.dirname(Gem.find_files('narray.h').first)
10
- rescue StandardError
11
- $sitearchdir
12
- end
13
- if /cygwin|mingw/ =~ RUBY_PLATFORM
14
- dir_config('narray', narray_dir, "#{narray_dir}/src")
15
- else
16
- dir_config('narray', narray_dir, narray_dir)
6
+ $LOAD_PATH.each do |load_path|
7
+ next unless File.exist?(File.join(load_path, 'numo/numo/narray.h'))
8
+
9
+ $INCFLAGS = "-I#{File.join(load_path, 'numo')} #{$INCFLAGS}"
10
+ break
17
11
  end
18
12
 
19
- unless have_header('narray.h') && have_header('narray_config.h')
20
- print <<-ERROR_MESSAGE
21
- ** configure error **
22
- Header narray.h or narray_config.h is not found. If you have these files in
23
- /narraydir/include, try the following:
13
+ abort 'numo/narray.h not found' unless have_header('numo/narray.h')
24
14
 
25
- % ruby extconf.rb --with-narray-include=/narraydir/include
15
+ if RUBY_PLATFORM.match?(/mswin|cygwin|mingw/)
16
+ $LOAD_PATH.each do |load_path|
17
+ next unless File.exist?(File.join(load_path, 'numo/narray/libnarray.a'))
26
18
 
27
- ERROR_MESSAGE
28
- exit(-1)
19
+ $LDFLAGS = "-L#{File.join(load_path, 'numo/narray')} #{$LDFLAGS}"
20
+ break
21
+ end
22
+ abort 'libnarray.a not found' unless have_library('narray', 'nary_new')
29
23
  end
30
24
 
31
- # This also stolen from fftw3 gem (and not confirmed for Windows platforms - please let me know if it works!)
32
- if /cygwin|mingw/ =~ RUBY_PLATFORM
33
- have_library('narray') || raise('ERROR: narray library is not found')
25
+ if RUBY_PLATFORM.include?('darwin') && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.1') &&
26
+ try_link('int main(void) { return 0; }', '-Wl,-undefined,dynamic_lookup')
27
+ $LDFLAGS << ' -Wl,-undefined,dynamic_lookup'
28
+ end
29
+
30
+ case ENV.fetch('CONVOLVER_NATIVE_MODE', 'release')
31
+ when 'release'
32
+ $CFLAGS << ' -O3 -funroll-loops'
33
+ when 'lint'
34
+ $CFLAGS << ' -std=gnu2x -O0 -g -Wall -Wextra -Wpedantic -Wformat=2 -Werror'
35
+ if RbConfig::CONFIG.fetch('CC').match?(/clang/) || RbConfig::CONFIG.fetch('host_os').match?(/darwin/)
36
+ $CFLAGS << ' -Wno-c23-extensions -Wno-strict-prototypes -Wno-unused-parameter'
37
+ $CFLAGS << ' -Wno-default-const-init-field-unsafe'
38
+ end
39
+ when 'coverage'
40
+ $CFLAGS << ' -O0 -g --coverage'
41
+ $LDFLAGS << ' --coverage'
42
+ when 'sanitize'
43
+ sanitizer_flags = ' -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer'
44
+ $CFLAGS << sanitizer_flags
45
+ $LDFLAGS << ' -fsanitize=address,undefined'
46
+ else
47
+ abort "Unknown CONVOLVER_NATIVE_MODE: #{ENV.fetch('CONVOLVER_NATIVE_MODE', nil)}"
34
48
  end
35
49
 
36
- $CFLAGS << ' -O3 -funroll-loops'
37
50
  create_makefile('convolver/convolver')
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Convolver
4
- VERSION = '0.4.0'
4
+ # Current gem version.
5
+ VERSION = '1.0.0'
5
6
  end