numo-pocketfft 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|