numo-pocketfft 0.1.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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +20 -0
- data/.gitmodules +4 -0
- data/.rspec +3 -0
- data/.travis.yml +13 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +27 -0
- data/README.md +76 -0
- data/Rakefile +16 -0
- data/ext/numo/pocketfft/extconf.rb +39 -0
- data/ext/numo/pocketfft/pocketfft/.gitlab-ci.yml +12 -0
- data/ext/numo/pocketfft/pocketfft/LICENSE.md +25 -0
- data/ext/numo/pocketfft/pocketfft/README.md +55 -0
- data/ext/numo/pocketfft/pocketfft/TESTING +6 -0
- data/ext/numo/pocketfft/pocketfft/ffttest.c +96 -0
- data/ext/numo/pocketfft/pocketfft/pocketfft.c +2190 -0
- data/ext/numo/pocketfft/pocketfft/pocketfft.h +34 -0
- data/ext/numo/pocketfft/pocketfftext.c +214 -0
- data/ext/numo/pocketfft/pocketfftext.h +13 -0
- data/lib/numo/pocketfft.rb +149 -0
- data/lib/numo/pocketfft/version.rb +10 -0
- data/numo-pocketfft.gemspec +47 -0
- metadata +158 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
/*
|
2
|
+
* This file is part of pocketfft.
|
3
|
+
* Licensed under a 3-clause BSD style license - see LICENSE.md
|
4
|
+
*/
|
5
|
+
|
6
|
+
/*! \file pocketfft.h
|
7
|
+
* Public interface of the pocketfft library
|
8
|
+
*
|
9
|
+
* Copyright (C) 2008-2018 Max-Planck-Society
|
10
|
+
* \author Martin Reinecke
|
11
|
+
*/
|
12
|
+
|
13
|
+
#ifndef POCKETFFT_H
|
14
|
+
#define POCKETFFT_H
|
15
|
+
|
16
|
+
#include <stdlib.h>
|
17
|
+
|
18
|
+
struct cfft_plan_i;
|
19
|
+
typedef struct cfft_plan_i * cfft_plan;
|
20
|
+
cfft_plan make_cfft_plan (size_t length);
|
21
|
+
void destroy_cfft_plan (cfft_plan plan);
|
22
|
+
int cfft_backward(cfft_plan plan, double c[], double fct);
|
23
|
+
int cfft_forward(cfft_plan plan, double c[], double fct);
|
24
|
+
size_t cfft_length(cfft_plan plan);
|
25
|
+
|
26
|
+
struct rfft_plan_i;
|
27
|
+
typedef struct rfft_plan_i * rfft_plan;
|
28
|
+
rfft_plan make_rfft_plan (size_t length);
|
29
|
+
void destroy_rfft_plan (rfft_plan plan);
|
30
|
+
int rfft_backward(rfft_plan plan, double c[], double fct);
|
31
|
+
int rfft_forward(rfft_plan plan, double c[], double fct);
|
32
|
+
size_t rfft_length(rfft_plan plan);
|
33
|
+
|
34
|
+
#endif
|
@@ -0,0 +1,214 @@
|
|
1
|
+
#include "pocketfftext.h"
|
2
|
+
|
3
|
+
VALUE mNumo;
|
4
|
+
VALUE mPocketfft;
|
5
|
+
|
6
|
+
VALUE numo_pocketfft_fft(VALUE x_val, int is_forward)
|
7
|
+
{
|
8
|
+
narray_t* x_nary;
|
9
|
+
double* x_pt;
|
10
|
+
size_t length;
|
11
|
+
int n_dims;
|
12
|
+
int n_repeats;
|
13
|
+
int i;
|
14
|
+
int res;
|
15
|
+
double fct;
|
16
|
+
VALUE z_val;
|
17
|
+
double* z_pt;
|
18
|
+
narray_t* z_nary;
|
19
|
+
cfft_plan plan = NULL;
|
20
|
+
|
21
|
+
if (CLASS_OF(x_val) != numo_cDComplex) {
|
22
|
+
x_val = rb_funcall(numo_cDComplex, rb_intern("cast"), 1, x_val);
|
23
|
+
}
|
24
|
+
if (!RTEST(nary_check_contiguous(x_val))) {
|
25
|
+
x_val = nary_dup(x_val);
|
26
|
+
}
|
27
|
+
|
28
|
+
GetNArray(x_val, x_nary);
|
29
|
+
n_dims = NA_NDIM(x_nary);
|
30
|
+
length = NA_SHAPE(x_nary)[n_dims - 1];
|
31
|
+
x_pt = (double*)na_get_pointer_for_read(x_val);
|
32
|
+
|
33
|
+
z_val = nary_s_new_like(numo_cDComplex, x_val);
|
34
|
+
z_pt = (double*)na_get_pointer_for_write(z_val);
|
35
|
+
GetNArray(z_val, z_nary);
|
36
|
+
for (i = 0; i < (int)(NA_SIZE(z_nary) * 2); z_pt[i++] = 0.0);
|
37
|
+
|
38
|
+
fct = is_forward == 1 ? 1.0 : 1.0 / length;
|
39
|
+
plan = make_cfft_plan(length);
|
40
|
+
if (!plan) {
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
|
44
|
+
n_repeats = (int)(NA_SIZE(x_nary)) / length;
|
45
|
+
for (i = 0; i < n_repeats; i++) {
|
46
|
+
memcpy(z_pt, x_pt, 2 * length * sizeof(double));
|
47
|
+
res = is_forward == 1 ? cfft_forward(plan, z_pt, fct) : cfft_backward(plan, z_pt, fct);
|
48
|
+
if (res != 0) { break; }
|
49
|
+
z_pt += length * 2;
|
50
|
+
x_pt += length * 2;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (plan) {
|
54
|
+
destroy_cfft_plan(plan);
|
55
|
+
}
|
56
|
+
|
57
|
+
return z_val;
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* @!visibility private
|
62
|
+
*/
|
63
|
+
static VALUE numo_pocketfft_cfft(VALUE self, VALUE x_val)
|
64
|
+
{
|
65
|
+
return numo_pocketfft_fft(x_val, 1);
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @!visibility private
|
70
|
+
*/
|
71
|
+
static VALUE numo_pocketfft_icfft(VALUE self, VALUE x_val)
|
72
|
+
{
|
73
|
+
return numo_pocketfft_fft(x_val, 0);
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* @!visibility private
|
78
|
+
*/
|
79
|
+
static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val)
|
80
|
+
{
|
81
|
+
narray_t* x_nary;
|
82
|
+
double* x_pt;
|
83
|
+
int n_dims;
|
84
|
+
size_t length;
|
85
|
+
int n_repeats;
|
86
|
+
int i;
|
87
|
+
size_t* z_shape;
|
88
|
+
VALUE z_val;
|
89
|
+
narray_t* z_nary;
|
90
|
+
double* z_pt;
|
91
|
+
int z_step;
|
92
|
+
rfft_plan plan = NULL;
|
93
|
+
|
94
|
+
if (CLASS_OF(x_val) != numo_cDFloat) {
|
95
|
+
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
96
|
+
}
|
97
|
+
if (!RTEST(nary_check_contiguous(x_val))) {
|
98
|
+
x_val = nary_dup(x_val);
|
99
|
+
}
|
100
|
+
|
101
|
+
GetNArray(x_val, x_nary);
|
102
|
+
n_dims = NA_NDIM(x_nary);
|
103
|
+
length = NA_SHAPE(x_nary)[n_dims - 1];
|
104
|
+
x_pt = (double*)na_get_pointer_for_read(x_val);
|
105
|
+
|
106
|
+
plan = make_rfft_plan(length);
|
107
|
+
if (!plan) {
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
z_shape = ALLOCA_N(size_t, n_dims);
|
112
|
+
for (i = 0; i < n_dims - 1; i++) {
|
113
|
+
z_shape[i] = NA_SHAPE(x_nary)[i];
|
114
|
+
}
|
115
|
+
z_shape[n_dims - 1] = length / 2 + 1;
|
116
|
+
z_val = rb_narray_new(numo_cDComplex, n_dims, z_shape);
|
117
|
+
z_pt = (double*)na_get_pointer_for_write(z_val);
|
118
|
+
GetNArray(z_val, z_nary);
|
119
|
+
for (i = 0; i < (int)(NA_SIZE(z_nary) * 2); z_pt[i++] = 0.0);
|
120
|
+
|
121
|
+
z_step = (int)(NA_SHAPE(z_nary)[n_dims - 1]) * 2;
|
122
|
+
n_repeats = (int)(NA_SIZE(x_nary)) / length;
|
123
|
+
for (i = 0; i < n_repeats; i++) {
|
124
|
+
z_pt[z_step - 1] = 0.0;
|
125
|
+
memcpy(z_pt + 1, x_pt, length * sizeof(double));
|
126
|
+
if (rfft_forward(plan, z_pt + 1, 1.0) != 0) { break; }
|
127
|
+
z_pt[0] = z_pt[1];
|
128
|
+
z_pt[1] = 0.0;
|
129
|
+
z_pt += z_step;
|
130
|
+
x_pt += length;
|
131
|
+
}
|
132
|
+
|
133
|
+
if (plan) {
|
134
|
+
destroy_rfft_plan(plan);
|
135
|
+
}
|
136
|
+
|
137
|
+
return z_val;
|
138
|
+
}
|
139
|
+
|
140
|
+
/**
|
141
|
+
* @!visibility private
|
142
|
+
*/
|
143
|
+
static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val)
|
144
|
+
{
|
145
|
+
narray_t* x_nary;
|
146
|
+
double* x_pt;
|
147
|
+
size_t length;
|
148
|
+
int n_dims;
|
149
|
+
int n_repeats;
|
150
|
+
int i;
|
151
|
+
double fct;
|
152
|
+
size_t* z_shape;
|
153
|
+
VALUE z_val;
|
154
|
+
double* z_pt;
|
155
|
+
narray_t* z_nary;
|
156
|
+
rfft_plan plan = NULL;
|
157
|
+
|
158
|
+
if (CLASS_OF(x_val) != numo_cDComplex) {
|
159
|
+
x_val = rb_funcall(numo_cDComplex, rb_intern("cast"), 1, x_val);
|
160
|
+
}
|
161
|
+
if (!RTEST(nary_check_contiguous(x_val))) {
|
162
|
+
x_val = nary_dup(x_val);
|
163
|
+
}
|
164
|
+
|
165
|
+
GetNArray(x_val, x_nary);
|
166
|
+
n_dims = NA_NDIM(x_nary);
|
167
|
+
length = NA_SHAPE(x_nary)[n_dims - 1];
|
168
|
+
x_pt = (double*)na_get_pointer_for_read(x_val);
|
169
|
+
fct = 1.0 / length;
|
170
|
+
|
171
|
+
plan = make_rfft_plan(length);
|
172
|
+
if (!plan) {
|
173
|
+
return Qnil;
|
174
|
+
}
|
175
|
+
|
176
|
+
z_shape = ALLOCA_N(size_t, n_dims);
|
177
|
+
for (i = 0; i < n_dims - 1; i++) {
|
178
|
+
z_shape[i] = NA_SHAPE(x_nary)[i];
|
179
|
+
}
|
180
|
+
z_shape[n_dims - 1] = length;
|
181
|
+
z_val = rb_narray_new(numo_cDFloat, n_dims, z_shape);
|
182
|
+
z_pt = (double*)na_get_pointer_for_write(z_val);
|
183
|
+
GetNArray(z_val, z_nary);
|
184
|
+
for (i = 0; i < (int)NA_SIZE(z_nary); z_pt[i++] = 0.0);
|
185
|
+
|
186
|
+
n_repeats = (int)(NA_SIZE(z_nary)) / length;
|
187
|
+
for (i = 0; i < n_repeats; i++) {
|
188
|
+
memcpy(z_pt + 1, x_pt + 2, (length - 1) * sizeof(double));
|
189
|
+
z_pt[0] = x_pt[0];
|
190
|
+
if (rfft_backward(plan, z_pt, fct) != 0) { break; }
|
191
|
+
z_pt += length;
|
192
|
+
x_pt += length * 2;
|
193
|
+
}
|
194
|
+
|
195
|
+
if (plan) {
|
196
|
+
destroy_rfft_plan(plan);
|
197
|
+
}
|
198
|
+
|
199
|
+
return z_val;
|
200
|
+
}
|
201
|
+
|
202
|
+
void Init_pocketfftext()
|
203
|
+
{
|
204
|
+
rb_require("numo/narray");
|
205
|
+
|
206
|
+
mNumo = rb_define_module("Numo");
|
207
|
+
|
208
|
+
mPocketfft = rb_define_module_under(mNumo, "Pocketfft");
|
209
|
+
|
210
|
+
rb_define_module_function(mPocketfft, "ext_rfft", numo_pocketfft_rfft, 1);
|
211
|
+
rb_define_module_function(mPocketfft, "ext_irfft", numo_pocketfft_irfft, 1);
|
212
|
+
rb_define_module_function(mPocketfft, "ext_cfft", numo_pocketfft_cfft, 1);
|
213
|
+
rb_define_module_function(mPocketfft, "ext_icfft", numo_pocketfft_icfft, 1);
|
214
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'numo/narray'
|
4
|
+
require 'numo/pocketfft/version'
|
5
|
+
require 'numo/pocketfft/pocketfftext'
|
6
|
+
|
7
|
+
module Numo
|
8
|
+
module Pocketfft
|
9
|
+
module_function
|
10
|
+
|
11
|
+
# Compute the 1-dimensional discrete Fourier Transform.
|
12
|
+
# @param a [Numo::DFloat/Numo::DComplex] Real or complex 1-dimensional input array.
|
13
|
+
# @return [Numo::DComplex] Transformed data.
|
14
|
+
def fft(a)
|
15
|
+
raise ArgumentError, 'Expect input array to be one-dimensional.' unless a.ndim == 1
|
16
|
+
raw_fft(a, 0, inverse: false, real: false)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Compute the 1-dimensional inverse discrete Fourier Transform.
|
20
|
+
# @param a [Numo::DComplex] Complex 1-dimensional input array.
|
21
|
+
# @return [Numo::DComplex] Inversed transformed data.
|
22
|
+
def ifft(a)
|
23
|
+
raise ArgumentError, 'Expect input array to be one-dimensional.' unless a.ndim == 1
|
24
|
+
raw_fft(a, 0, inverse: true, real: false)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Compute the 2-dimensional discrete Fourier Transform.
|
28
|
+
# @param a [Numo::DFloat/Numo::DComplex] Real or complex 2-dimensional input array.
|
29
|
+
# @return [Numo::DComplex] Transformed data.
|
30
|
+
def fft2(a)
|
31
|
+
raise ArgumentError, 'Expect input array to be two-dimensional.' unless a.ndim == 2
|
32
|
+
fftn(a)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Compute the 2-dimensional inverse discrete Fourier Transform.
|
36
|
+
# @param a [Numo::DComplex] Complex 2-dimensional input array.
|
37
|
+
# @return [Numo::DComplex] Inversed transformed data.
|
38
|
+
def ifft2(a)
|
39
|
+
raise ArgumentError, 'Expect input array to be two-dimensional.' unless a.ndim == 2
|
40
|
+
ifftn(a)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Compute the N-dimensional discrete Fourier Transform.
|
44
|
+
# @param a [Numo::DFloat/Numo::DComplex] Real or complex input array with any-dimension.
|
45
|
+
# @return [Numo::DComplex] Transformed data.
|
46
|
+
def fftn(a)
|
47
|
+
b = a.dup
|
48
|
+
(0...b.ndim).to_a.reverse.each { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
|
49
|
+
b
|
50
|
+
end
|
51
|
+
|
52
|
+
# Compute the N-dimensional inverse discrete Fourier Transform.
|
53
|
+
# @param a [Numo::DComplex] Complex input array with any-dimension.
|
54
|
+
# @return [Numo::DComplex] Inversed transformed data.
|
55
|
+
def ifftn(a)
|
56
|
+
b = a.dup
|
57
|
+
(0...b.ndim).to_a.each { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
|
58
|
+
b
|
59
|
+
end
|
60
|
+
|
61
|
+
# Compute the 1-dimensional discrete Fourier Transform for real input.
|
62
|
+
# @param a [Numo::DFloat] Real 1-dimensional input array.
|
63
|
+
# @return [Numo::DComplex] Transformed data.
|
64
|
+
def rfft(a)
|
65
|
+
raise ArgumentError, 'Expect input array to be one-dimensional.' unless a.ndim == 1
|
66
|
+
raw_fft(a, 0, inverse: false, real: true)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Compute the inverse of the 1-dimensional discrete Fourier Transform of real input.
|
70
|
+
# @param a [Numo::DComplex] Complex 1-dimensional input array.
|
71
|
+
# @return [Numo::DFloat] Inverse transformed data.
|
72
|
+
def irfft(a)
|
73
|
+
raise ArgumentError, 'Expect input array to be one-dimensional.' unless a.ndim == 1
|
74
|
+
raw_fft(a, 0, inverse: true, real: true)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Compute the 2-dimensional discrete Fourier Transform for real input.
|
78
|
+
# @param a [Numo::DFloat] Real 2-dimensional input array.
|
79
|
+
# @return [Numo::DComplex] Transformed data.
|
80
|
+
def rfft2(a)
|
81
|
+
raise ArgumentError, 'Expect input array to be two-dimensional.' unless a.ndim == 2
|
82
|
+
rfftn(a)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Compute the inverse of the 2-dimensional discrete Fourier Transform of real input.
|
86
|
+
# @param a [Numo::DComplex] Complex 2-dimensional input array.
|
87
|
+
# @return [Numo::DFloat] Inverse transformed data.
|
88
|
+
def irfft2(a)
|
89
|
+
raise ArgumentError, 'Expect input array to be two-dimensional.' unless a.ndim == 2
|
90
|
+
irfftn(a)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Compute the N-dimensional discrete Fourier Transform for real input.
|
94
|
+
# @param a [Numo::DFloat] Real input array with any-dimension.
|
95
|
+
# @return [Numo::DComplex] Transformed data.
|
96
|
+
def rfftn(a)
|
97
|
+
last_axis_id = a.ndim - 1
|
98
|
+
b = raw_fft(a, last_axis_id, inverse: false, real: true)
|
99
|
+
(0...last_axis_id).to_a.reverse.each { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
|
100
|
+
b
|
101
|
+
end
|
102
|
+
|
103
|
+
# Compute the inverse of the N-dimensional discrete Fourier Transform of real input.
|
104
|
+
# @param a [Numo::DComplex] Complex input array with any-dimension.
|
105
|
+
# @return [Numo::DFloat] Inverse transformed data.
|
106
|
+
def irfftn(a)
|
107
|
+
last_axis_id = a.ndim - 1
|
108
|
+
b = a.dup
|
109
|
+
(0...last_axis_id).to_a.each { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
|
110
|
+
raw_fft(b, last_axis_id, inverse: true, real: true)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @!visibility private
|
114
|
+
def raw_fft(a, axis_id, inverse:, real:)
|
115
|
+
if axis_id == a.ndim - 1
|
116
|
+
if real
|
117
|
+
if inverse
|
118
|
+
# zero padding
|
119
|
+
n = (a.shape[-1] - 1) * 2
|
120
|
+
b_shape = a.shape
|
121
|
+
b_shape[-1] = n
|
122
|
+
b = Numo::DComplex.zeros(*b_shape)
|
123
|
+
b_range = [true] * b.ndim
|
124
|
+
b_range[-1] = 0...a.shape[-1]
|
125
|
+
b[*b_range] = a
|
126
|
+
# inverse of dft for real data
|
127
|
+
ext_irfft(b)
|
128
|
+
else
|
129
|
+
ext_rfft(a)
|
130
|
+
end
|
131
|
+
else
|
132
|
+
if inverse
|
133
|
+
ext_icfft(a)
|
134
|
+
else
|
135
|
+
ext_cfft(a)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
else
|
139
|
+
if inverse
|
140
|
+
ext_icfft(a.swapaxes(axis_id, -1)).swapaxes(axis_id, -1).dup
|
141
|
+
else
|
142
|
+
ext_cfft(a.swapaxes(axis_id, -1)).swapaxes(axis_id, -1).dup
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private_class_method :ext_cfft, :ext_icfft, :ext_rfft, :ext_irfft, :raw_fft
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Numo is the top level namespace of NUmerical MOdules for Ruby.
|
4
|
+
module Numo
|
5
|
+
# Numo::Pocketfft is the module that has functions for Fourier transform.
|
6
|
+
module Pocketfft
|
7
|
+
# The version of Numo::Pocketfft you are using.
|
8
|
+
VERSION = '0.1.0'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'numo/pocketfft/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'numo-pocketfft'
|
7
|
+
spec.version = Numo::Pocketfft::VERSION
|
8
|
+
spec.authors = ['yoshoku']
|
9
|
+
spec.email = ['yoshoku@outlook.com']
|
10
|
+
|
11
|
+
spec.summary = <<~MSG
|
12
|
+
Numo::Pocketfft provides functions for descrete Fourier Transform based on pocketfft.
|
13
|
+
MSG
|
14
|
+
spec.description = <<~MSG
|
15
|
+
Numo::Pocketfft provides functions for descrete Fourier Transform based on pocketfft.
|
16
|
+
MSG
|
17
|
+
spec.homepage = 'https://github.com/yoshoku/numo-pocketfft'
|
18
|
+
spec.license = 'BSD-3-Clause'
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Add files in submodule: https://gist.github.com/mattconnolly/5875987
|
27
|
+
gem_dir = __dir__ + '/'
|
28
|
+
`git submodule --quiet foreach pwd`.split($OUTPUT_RECORD_SEPARATOR).each do |submodule_path|
|
29
|
+
Dir.chdir(submodule_path) do
|
30
|
+
submodule_relative_path = submodule_path.sub gem_dir, ''
|
31
|
+
`git ls-files`.split($OUTPUT_RECORD_SEPARATOR).each do |filename|
|
32
|
+
spec.files << "#{submodule_relative_path}/#{filename}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
spec.require_paths = ['lib']
|
38
|
+
spec.extensions = ['ext/numo/pocketfft/extconf.rb']
|
39
|
+
|
40
|
+
spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
|
41
|
+
|
42
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
43
|
+
spec.add_development_dependency 'coveralls', '~> 0.8'
|
44
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
45
|
+
spec.add_development_dependency 'rake-compiler', '~> 1.0'
|
46
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
47
|
+
end
|