nmatrix-fftw 0.2.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 +7 -0
- data/ext/nmatrix/data/complex.h +388 -0
- data/ext/nmatrix/data/data.h +652 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +389 -0
- data/ext/nmatrix/math/asum.h +120 -0
- data/ext/nmatrix/math/cblas_enums.h +36 -0
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +241 -0
- data/ext/nmatrix/math/gemv.h +178 -0
- data/ext/nmatrix/math/getrf.h +255 -0
- data/ext/nmatrix/math/getrs.h +121 -0
- data/ext/nmatrix/math/imax.h +79 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +49 -0
- data/ext/nmatrix/math/math.h +745 -0
- data/ext/nmatrix/math/nrm2.h +160 -0
- data/ext/nmatrix/math/rot.h +117 -0
- data/ext/nmatrix/math/rotg.h +106 -0
- data/ext/nmatrix/math/scal.h +71 -0
- data/ext/nmatrix/math/trsm.h +332 -0
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.h +438 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/storage/common.h +177 -0
- data/ext/nmatrix/storage/dense/dense.h +129 -0
- data/ext/nmatrix/storage/list/list.h +138 -0
- data/ext/nmatrix/storage/storage.h +99 -0
- data/ext/nmatrix/storage/yale/class.h +1139 -0
- data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
- data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
- data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
- data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
- data/ext/nmatrix/storage/yale/yale.h +203 -0
- data/ext/nmatrix/types.h +55 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.h +144 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/ext/nmatrix_fftw/extconf.rb +122 -0
- data/ext/nmatrix_fftw/nmatrix_fftw.cpp +274 -0
- data/lib/nmatrix/fftw.rb +343 -0
- data/spec/00_nmatrix_spec.rb +736 -0
- data/spec/01_enum_spec.rb +190 -0
- data/spec/02_slice_spec.rb +389 -0
- data/spec/03_nmatrix_monkeys_spec.rb +78 -0
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +193 -0
- data/spec/elementwise_spec.rb +303 -0
- data/spec/homogeneous_spec.rb +99 -0
- data/spec/io/fortran_format_spec.rb +88 -0
- data/spec/io/harwell_boeing_spec.rb +98 -0
- data/spec/io/test.rua +9 -0
- data/spec/io_spec.rb +149 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +807 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/plugins/fftw/fftw_spec.rb +348 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +310 -0
- data/spec/slice_set_spec.rb +157 -0
- data/spec/spec_helper.rb +149 -0
- data/spec/stat_spec.rb +203 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +151 -0
@@ -0,0 +1,286 @@
|
|
1
|
+
# = NMatrix
|
2
|
+
#
|
3
|
+
# A linear algebra library for scientific computation in Ruby.
|
4
|
+
# NMatrix is part of SciRuby.
|
5
|
+
#
|
6
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
7
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
8
|
+
#
|
9
|
+
# == Copyright Information
|
10
|
+
#
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
12
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
13
|
+
#
|
14
|
+
# Please see LICENSE.txt for additional copyright notices.
|
15
|
+
#
|
16
|
+
# == Contributing
|
17
|
+
#
|
18
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
19
|
+
# our Contributor Agreement:
|
20
|
+
#
|
21
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
22
|
+
#
|
23
|
+
# == nmatrix_yale_spec.rb
|
24
|
+
#
|
25
|
+
# Basic tests for NMatrix's Yale storage type.
|
26
|
+
#
|
27
|
+
require 'spec_helper'
|
28
|
+
require "./lib/nmatrix"
|
29
|
+
|
30
|
+
describe NMatrix do
|
31
|
+
context :yale do
|
32
|
+
|
33
|
+
it "compares two empty matrices" do
|
34
|
+
n = NMatrix.new(4, stype: :yale, dtype: :float64)
|
35
|
+
m = NMatrix.new(4, stype: :yale, dtype: :float64)
|
36
|
+
expect(n).to eq(m)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "compares two matrices following basic assignments" do
|
40
|
+
n = NMatrix.new(2, stype: :yale, dtype: :float64)
|
41
|
+
m = NMatrix.new(2, stype: :yale, dtype: :float64)
|
42
|
+
|
43
|
+
m[0,0] = 1
|
44
|
+
m[0,1] = 1
|
45
|
+
expect(n).not_to eq(m)
|
46
|
+
n[0,0] = 1
|
47
|
+
expect(n).not_to eq(m)
|
48
|
+
n[0,1] = 1
|
49
|
+
expect(n).to eq(m)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "compares two matrices following elementwise operations" do
|
53
|
+
n = NMatrix.new(2, stype: :yale, dtype: :float64)
|
54
|
+
m = NMatrix.new(2, stype: :yale, dtype: :float64)
|
55
|
+
n[0,1] = 1
|
56
|
+
m[0,1] = -1
|
57
|
+
x = n+m
|
58
|
+
expect(n+m).to eq(NMatrix.new(2, 0.0, stype: :yale))
|
59
|
+
end
|
60
|
+
|
61
|
+
it "sets diagonal values" do
|
62
|
+
n = NMatrix.new([2,3], stype: :yale, dtype: :float64)
|
63
|
+
n.extend(NMatrix::YaleFunctions)
|
64
|
+
n[1,1] = 0.1
|
65
|
+
n[0,0] = 0.2
|
66
|
+
expect(n.yale_d).to eq([0.2, 0.1])
|
67
|
+
end
|
68
|
+
|
69
|
+
it "gets non-diagonal rows as hashes" do
|
70
|
+
n = NMatrix.new([4,6], stype: :yale, dtype: :float64)
|
71
|
+
n.extend(NMatrix::YaleFunctions)
|
72
|
+
n[0,0] = 0.1
|
73
|
+
n[0,2] = 0.2
|
74
|
+
n[0,3] = 0.3
|
75
|
+
n[1,5] = 0.4
|
76
|
+
h = n.yale_nd_row(0, :hash)
|
77
|
+
expect(h).to eq({2 => 0.2, 3 => 0.3})
|
78
|
+
end
|
79
|
+
|
80
|
+
it "gets non-diagonal occupied column indices for a given row" do
|
81
|
+
n = NMatrix.new([4,6], stype: :yale, dtype: :float64)
|
82
|
+
n.extend(NMatrix::YaleFunctions)
|
83
|
+
n[0,0] = 0.1
|
84
|
+
n[0,2] = 0.2
|
85
|
+
n[0,3] = 0.3
|
86
|
+
n[1,5] = 0.4
|
87
|
+
a = n.yale_nd_row(0, :array)
|
88
|
+
expect(a).to eq([2,3])
|
89
|
+
end
|
90
|
+
|
91
|
+
it "does not resize until necessary" do
|
92
|
+
n = NMatrix.new([2,3], stype: :yale, dtype: :float64)
|
93
|
+
n.extend(NMatrix::YaleFunctions)
|
94
|
+
expect(n.yale_size).to eq(3)
|
95
|
+
expect(n.capacity).to eq(5)
|
96
|
+
n[0,0] = 0.1
|
97
|
+
n[0,1] = 0.2
|
98
|
+
n[1,0] = 0.3
|
99
|
+
expect(n.yale_size).to eq(5)
|
100
|
+
expect(n.capacity).to eq(5)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
it "sets when not resizing" do
|
105
|
+
n = NMatrix.new([2,3], stype: :yale, dtype: :float64)
|
106
|
+
n.extend(NMatrix::YaleFunctions)
|
107
|
+
n[0,0] = 0.1
|
108
|
+
n[0,1] = 0.2
|
109
|
+
n[1,0] = 0.3
|
110
|
+
expect(n.yale_a).to eq([0.1, 0.0, 0.0, 0.2, 0.3])
|
111
|
+
expect(n.yale_ija).to eq([3,4,5,1,0])
|
112
|
+
end
|
113
|
+
|
114
|
+
it "sets when resizing" do
|
115
|
+
n = NMatrix.new([2,3], stype: :yale, dtype: :float64)
|
116
|
+
n.extend(NMatrix::YaleFunctions)
|
117
|
+
n[0,0] = 0.01
|
118
|
+
n[1,1] = 0.1
|
119
|
+
n[0,1] = 0.2
|
120
|
+
n[1,0] = 0.3
|
121
|
+
n[1,2] = 0.4
|
122
|
+
expect(n.yale_d).to eq([0.01, 0.1])
|
123
|
+
expect(n.yale_ia).to eq([3,4,6])
|
124
|
+
expect(n.yale_ja).to eq([1,0,2,nil])
|
125
|
+
expect(n.yale_lu).to eq([0.2, 0.3, 0.4, nil])
|
126
|
+
end
|
127
|
+
|
128
|
+
it "resizes without erasing values" do
|
129
|
+
require 'yaml'
|
130
|
+
|
131
|
+
associations = File.open('spec/nmatrix_yale_resize_test_associations.yaml') { |y| YAML::load(y) }
|
132
|
+
|
133
|
+
n = NMatrix.new([618,2801], stype: :yale, dtype: :byte, capacity: associations.size)
|
134
|
+
#n = NMatrix.new(:yale, [618, 2801], associations.size, :byte)
|
135
|
+
|
136
|
+
associations.each_pair do |j,i|
|
137
|
+
n[i,j] = 1
|
138
|
+
expect(n[i,j]).to be(1), "Value at #{i},#{j} not inserted correctly!"
|
139
|
+
end
|
140
|
+
|
141
|
+
associations.each_pair do |j,i|
|
142
|
+
expect(n[i,j]).to be(1), "Value at #{i},#{j} erased during resize!"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it "sets values within rows" do
|
147
|
+
n = NMatrix.new([3,20], stype: :yale, dtype: :float64)
|
148
|
+
n.extend(NMatrix::YaleFunctions)
|
149
|
+
n[2,1] = 1.0
|
150
|
+
n[2,0] = 1.5
|
151
|
+
n[2,15] = 2.0
|
152
|
+
expect(n.yale_lu).to eq([1.5, 1.0, 2.0])
|
153
|
+
expect(n.yale_ja).to eq([0, 1, 15])
|
154
|
+
end
|
155
|
+
|
156
|
+
it "gets values within rows" do
|
157
|
+
n = NMatrix.new([3,20], stype: :yale, dtype: :float64)
|
158
|
+
n[2,1] = 1.0
|
159
|
+
n[2,0] = 1.5
|
160
|
+
n[2,15] = 2.0
|
161
|
+
expect(n[2,1]).to eq(1.0)
|
162
|
+
expect(n[2,0]).to eq(1.5)
|
163
|
+
expect(n[2,15]).to eq(2.0)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "sets values within large rows" do
|
167
|
+
n = NMatrix.new([10,300], stype: :yale, dtype: :float64)
|
168
|
+
n.extend(NMatrix::YaleFunctions)
|
169
|
+
n[5,1] = 1.0
|
170
|
+
n[5,0] = 1.5
|
171
|
+
n[5,15] = 2.0
|
172
|
+
n[5,291] = 3.0
|
173
|
+
n[5,292] = 4.0
|
174
|
+
n[5,289] = 5.0
|
175
|
+
n[5,290] = 6.0
|
176
|
+
n[5,293] = 2.0
|
177
|
+
n[5,299] = 7.0
|
178
|
+
n[5,100] = 8.0
|
179
|
+
expect(n.yale_lu).to eq([1.5, 1.0, 2.0, 8.0, 5.0, 6.0, 3.0, 4.0, 2.0, 7.0])
|
180
|
+
expect(n.yale_ja).to eq([0, 1, 15, 100, 289, 290, 291, 292, 293, 299])
|
181
|
+
end
|
182
|
+
|
183
|
+
it "gets values within large rows" do
|
184
|
+
n = NMatrix.new([10,300], stype: :yale, dtype: :float64)
|
185
|
+
n.extend(NMatrix::YaleFunctions)
|
186
|
+
n[5,1] = 1.0
|
187
|
+
n[5,0] = 1.5
|
188
|
+
n[5,15] = 2.0
|
189
|
+
n[5,291] = 3.0
|
190
|
+
n[5,292] = 4.0
|
191
|
+
n[5,289] = 5.0
|
192
|
+
n[5,290] = 6.0
|
193
|
+
n[5,293] = 2.0
|
194
|
+
n[5,299] = 7.0
|
195
|
+
n[5,100] = 8.0
|
196
|
+
|
197
|
+
n.yale_ja.each_index do |idx|
|
198
|
+
j = n.yale_ja[idx]
|
199
|
+
expect(n[5,j]).to eq(n.yale_lu[idx])
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it "dots two identical matrices" do
|
204
|
+
a = NMatrix.new(4, stype: :yale, dtype: :float64)
|
205
|
+
a[0,1] = 4.0
|
206
|
+
a[1,2] = 1.0
|
207
|
+
a[1,3] = 1.0
|
208
|
+
a[3,1] = 2.0
|
209
|
+
|
210
|
+
b = a.dup
|
211
|
+
c = a.dot b
|
212
|
+
|
213
|
+
d = NMatrix.new(4, [0,0,4,4, 0,2,0,0, 0,0,0,0, 0,0,2,2], dtype: :float64, stype: :yale)
|
214
|
+
|
215
|
+
expect(c).to eq(d)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "dots two identical matrices where a positive and negative partial sum cancel on the diagonal" do
|
219
|
+
a = NMatrix.new(4, 0.0, stype: :yale)
|
220
|
+
|
221
|
+
a[0,0] = 1.0
|
222
|
+
a[0,1] = 4.0
|
223
|
+
a[1,2] = 2.0
|
224
|
+
a[1,3] = -4.0
|
225
|
+
a[3,1] = 4.0
|
226
|
+
a[3,3] = 4.0
|
227
|
+
|
228
|
+
b = a.dup
|
229
|
+
c = a.dot b
|
230
|
+
|
231
|
+
c.extend(NMatrix::YaleFunctions)
|
232
|
+
|
233
|
+
expect(c.yale_ija.reject { |i| i.nil? }).to eq([5,8,9,9,11,1,2,3,3,1,2])
|
234
|
+
expect(c.yale_a.reject { |i| i.nil? }).to eq([1.0, -16.0, 0.0, 0.0, 0.0, 4.0, 8.0, -16.0, -16.0, 16.0, 8.0])
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
it "dots two vectors" do
|
239
|
+
n = NMatrix.new([16,1], 0, stype: :yale)
|
240
|
+
m = NMatrix.new([1,16], 0, stype: :yale)
|
241
|
+
|
242
|
+
n[0] = m[0] = 1
|
243
|
+
n[1] = m[1] = 2
|
244
|
+
n[2] = m[2] = 3
|
245
|
+
n[3] = m[3] = 4
|
246
|
+
n[4] = m[4] = 5
|
247
|
+
n[5] = m[5] = 6
|
248
|
+
n[6] = m[6] = 7
|
249
|
+
n[7] = m[7] = 8
|
250
|
+
n[8] = m[8] = 9
|
251
|
+
n[15] = m[15] = 16
|
252
|
+
|
253
|
+
nm = n.dot(m)
|
254
|
+
|
255
|
+
# Perform the same multiplication with dense
|
256
|
+
nmr = n.cast(:dense, :int64).dot(m.cast(:dense, :int64)).cast(:yale, :int64)
|
257
|
+
|
258
|
+
nm.extend(NMatrix::YaleFunctions)
|
259
|
+
nmr.extend(NMatrix::YaleFunctions)
|
260
|
+
|
261
|
+
# We want to do a structure comparison to ensure multiplication is occurring properly, but more importantly, to
|
262
|
+
# ensure that insertion sort is occurring as it should. If the row has more than four entries, it'll run quicksort
|
263
|
+
# instead. Quicksort calls insertion sort for small rows, so we test both with this particular multiplication.
|
264
|
+
expect(nm.yale_ija[0...107]).to eq(nmr.yale_ija[0...107])
|
265
|
+
expect(nm.yale_a[0...107]).to eq(nmr.yale_a[0...107])
|
266
|
+
|
267
|
+
mn = m.dot(n)
|
268
|
+
expect(mn[0,0]).to eq(541)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "calculates the row key intersections of two matrices" do
|
272
|
+
a = NMatrix.new([3,9], [0,1], stype: :yale, dtype: :byte, default: 0)
|
273
|
+
b = NMatrix.new([3,9], [0,0,1,0,1], stype: :yale, dtype: :byte, default: 0)
|
274
|
+
a.extend NMatrix::YaleFunctions
|
275
|
+
b.extend NMatrix::YaleFunctions
|
276
|
+
|
277
|
+
(0...3).each do |ai|
|
278
|
+
(0...3).each do |bi|
|
279
|
+
STDERR.puts (a.yale_ja_d_keys_at(ai) & b.yale_ja_d_keys_at(bi)).inspect
|
280
|
+
expect(a.yale_ja_d_keys_at(ai) & b.yale_ja_d_keys_at(bi)).to eq(a.yale_row_keys_intersection(ai, b, bi))
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
@@ -0,0 +1,348 @@
|
|
1
|
+
# = NMatrix
|
2
|
+
#
|
3
|
+
# A linear algebra library for scientific computation in Ruby.
|
4
|
+
# NMatrix is part of SciRuby.
|
5
|
+
#
|
6
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
7
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
8
|
+
#
|
9
|
+
# == Copyright Information
|
10
|
+
#
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
12
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
13
|
+
#
|
14
|
+
# Please see LICENSE.txt for additional copyright notices.
|
15
|
+
#
|
16
|
+
# == Contributing
|
17
|
+
#
|
18
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
19
|
+
# our Contributor Agreement:
|
20
|
+
#
|
21
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
22
|
+
#
|
23
|
+
# == fftw_spec.rb
|
24
|
+
#
|
25
|
+
# Tests for interfaces that are only exposed by nmatrix-fftw
|
26
|
+
#
|
27
|
+
|
28
|
+
require 'spec_helper'
|
29
|
+
require "./lib/nmatrix/fftw"
|
30
|
+
|
31
|
+
describe NMatrix do
|
32
|
+
context "#fft" do
|
33
|
+
before do
|
34
|
+
@answer = NMatrix.new([10],
|
35
|
+
[
|
36
|
+
Complex(330.3200,0.0000) , Complex(-8.4039 ,-150.3269),
|
37
|
+
Complex(-99.4807,-68.6579) , Complex(-143.6861, -20.4273),
|
38
|
+
Complex(67.6207 , 8.5236), Complex(130.7800 , 0.0000),
|
39
|
+
Complex(67.6207 , -8.5236), Complex(-143.6861, 20.4273),
|
40
|
+
Complex(-99.4807 , 68.6579), Complex(-8.4039 ,150.3269)
|
41
|
+
], dtype: :complex128)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "computes an FFT of a complex NMatrix" do
|
45
|
+
nm = NMatrix.new([10],
|
46
|
+
[
|
47
|
+
Complex(9.32,0), Complex(44,0), Complex(125,0), Complex(34,0),
|
48
|
+
Complex(31,0), Complex(44,0), Complex(12,0), Complex(1,0),
|
49
|
+
Complex(53.23,0),Complex(-23.23,0)], dtype: :complex128)
|
50
|
+
expect(nm.fft.round(4)).to eq(@answer)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "#fft2" do
|
55
|
+
it "computes 2D FFT if NMatrix has such shape" do
|
56
|
+
input = NMatrix.new([2,2],
|
57
|
+
[
|
58
|
+
Complex(9.3200,0), Complex(43.0000,0),
|
59
|
+
Complex(3.2000,0), Complex(4.0000,0)
|
60
|
+
], dtype: :complex128
|
61
|
+
)
|
62
|
+
output = NMatrix.new([2,2],
|
63
|
+
[
|
64
|
+
Complex(59.520,0), Complex(-34.480,0),
|
65
|
+
Complex(45.120,0), Complex(-32.880,0),
|
66
|
+
], dtype: :complex128
|
67
|
+
)
|
68
|
+
expect(input.fft2.round(4)).to eq(output)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe NMatrix::FFTW, focus: true do
|
74
|
+
describe NMatrix::FFTW::Plan do
|
75
|
+
context ".new" do
|
76
|
+
it "creates a new plan for default DFT (complex input/complex output)" do
|
77
|
+
plan = NMatrix::FFTW::Plan.new(4)
|
78
|
+
# TODO: Figure a way to test internal C data structures.
|
79
|
+
|
80
|
+
expect(plan.shape) .to eq([4])
|
81
|
+
expect(plan.size) .to eq(4)
|
82
|
+
expect(plan.dim) .to eq(1)
|
83
|
+
expect(plan.flags) .to eq([:estimate])
|
84
|
+
expect(plan.direction).to eq(:forward)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "creates a new plan for multi dimensional DFT with options" do
|
88
|
+
plan = NMatrix::FFTW::Plan.new([10,5,8],
|
89
|
+
direction: :backward, flags: [:exhaustive, :estimate], dim: 3)
|
90
|
+
|
91
|
+
expect(plan.shape) .to eq([10,5,8])
|
92
|
+
expect(plan.size) .to eq(10*5*8)
|
93
|
+
expect(plan.dim) .to eq(3)
|
94
|
+
expect(plan.flags) .to eq([:exhaustive, :estimate])
|
95
|
+
expect(plan.direction).to eq(:backward)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "creates a new plan for real input/complex output" do
|
99
|
+
plan = NMatrix::FFTW::Plan.new([5,20,10,4,2],
|
100
|
+
direction: :forward, flags: [:patient, :exhaustive], dim: 5,
|
101
|
+
type: :real_complex)
|
102
|
+
|
103
|
+
expect(plan.shape) .to eq([5,20,10,4,2])
|
104
|
+
expect(plan.size) .to eq(5*20*10*4*2)
|
105
|
+
expect(plan.dim) .to eq(5)
|
106
|
+
expect(plan.flags) .to eq([:patient, :exhaustive])
|
107
|
+
expect(plan.type) .to eq(:real_complex)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "raises error for plan with incompatible shape and dimension" do
|
111
|
+
expect {
|
112
|
+
NMatrix::FFTW::Plan.new([9], dim: 2, type: :real_complex)
|
113
|
+
}.to raise_error(ArgumentError)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "creates a new plan for real input/real output" do
|
117
|
+
plan = NMatrix::FFTW::Plan.new([30,30], type: :real_real,
|
118
|
+
real_real_kind: [:rodft00, :redft10], dim: 2)
|
119
|
+
|
120
|
+
expect(plan.shape).to eq([30,30])
|
121
|
+
expect(plan.size) .to eq(30*30)
|
122
|
+
expect(plan.dim) .to eq(2)
|
123
|
+
expect(plan.flags).to eq([:estimate])
|
124
|
+
expect(plan.type) .to eq(:real_real)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "creates a new plan for complex input/real output" do
|
128
|
+
plan = NMatrix::FFTW::Plan.new([30,400], type: :complex_real,
|
129
|
+
dim: 2, flags: [:patient, :exhaustive])
|
130
|
+
|
131
|
+
expect(plan.shape).to eq([30,400])
|
132
|
+
expect(plan.size) .to eq(30*400)
|
133
|
+
expect(plan.dim) .to eq(2)
|
134
|
+
expect(plan.flags).to eq([:patient, :exhaustive])
|
135
|
+
expect(plan.type) .to eq(:complex_real)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "#set_input" do
|
140
|
+
it "accepts nothing but complex128 input for the default or complex_real plan" do
|
141
|
+
plan = NMatrix::FFTW::Plan.new(4)
|
142
|
+
input = NMatrix.new([4], [23.54,52.34,52.345,64], dtype: :float64)
|
143
|
+
expect {
|
144
|
+
plan.set_input(input)
|
145
|
+
}.to raise_error(ArgumentError)
|
146
|
+
|
147
|
+
plan = NMatrix::FFTW::Plan.new(4, type: :complex_real)
|
148
|
+
expect {
|
149
|
+
plan.set_input input
|
150
|
+
}.to raise_error(ArgumentError)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "accepts nothing but float64 input for real_complex or real_real plan" do
|
154
|
+
plan = NMatrix::FFTW::Plan.new(4, type: :real_complex)
|
155
|
+
input = NMatrix.new([4], [1,2,3,4], dtype: :int32)
|
156
|
+
|
157
|
+
expect {
|
158
|
+
plan.set_input(input)
|
159
|
+
}.to raise_error(ArgumentError)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "#execute" do
|
164
|
+
it "calculates a basic 1D DFT" do
|
165
|
+
input = NMatrix.new([10],
|
166
|
+
[
|
167
|
+
Complex(9.32,0),
|
168
|
+
Complex(44,0),
|
169
|
+
Complex(125,0),
|
170
|
+
Complex(34,0),
|
171
|
+
Complex(31,0),
|
172
|
+
Complex(44,0),
|
173
|
+
Complex(12,0),
|
174
|
+
Complex(1,0),
|
175
|
+
Complex(53.23,0),
|
176
|
+
Complex(-23.23,0),
|
177
|
+
], dtype: :complex128)
|
178
|
+
|
179
|
+
output = NMatrix.new([10],
|
180
|
+
[
|
181
|
+
Complex(330.3200,0.0000),
|
182
|
+
Complex(-8.4039 ,-150.3269),
|
183
|
+
Complex(-99.4807 , -68.6579),
|
184
|
+
Complex(-143.6861, -20.4273),
|
185
|
+
Complex(67.6207 , 8.5236),
|
186
|
+
Complex(130.7800 , 0.0000),
|
187
|
+
Complex(67.6207 , -8.5236),
|
188
|
+
Complex(-143.6861, 20.4273),
|
189
|
+
Complex(-99.4807 , 68.6579),
|
190
|
+
Complex(-8.4039 ,150.3269)
|
191
|
+
], dtype: :complex128)
|
192
|
+
|
193
|
+
plan = NMatrix::FFTW::Plan.new(10)
|
194
|
+
plan.set_input input
|
195
|
+
expect(plan.execute).to eq(true)
|
196
|
+
expect(plan.output.round(4)).to eq(output)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "calculates 2D DFT with options" do
|
200
|
+
input = NMatrix.new([2,2],
|
201
|
+
[
|
202
|
+
Complex(9.3200,0), Complex(43.0000,0),
|
203
|
+
Complex(3.2000,0), Complex(4.0000,0)
|
204
|
+
], dtype: :complex128
|
205
|
+
)
|
206
|
+
|
207
|
+
output = NMatrix.new([2,2],
|
208
|
+
[
|
209
|
+
Complex(59.520,0), Complex(-34.480,0),
|
210
|
+
Complex(45.120,0), Complex(-32.880,0),
|
211
|
+
], dtype: :complex128
|
212
|
+
)
|
213
|
+
|
214
|
+
plan = NMatrix::FFTW::Plan.new([2,2],
|
215
|
+
direction: :forward, flags: :estimate, dim: 2)
|
216
|
+
plan.set_input input
|
217
|
+
expect(plan.execute).to eq(true)
|
218
|
+
expect(plan.output).to eq(output)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "calculates ND DFT with options" do
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
it "calculates 1D real input/complex output DFT" do
|
226
|
+
input = NMatrix.new([4], [3.10, 1.73, 1.04, 2.83], dtype: :float64)
|
227
|
+
output = NMatrix.new([3],
|
228
|
+
[Complex(8.70, 0), Complex(2.06, 1.1), Complex(-0.42, 0)], dtype: :complex128)
|
229
|
+
plan = NMatrix::FFTW::Plan.new([4], type: :real_complex)
|
230
|
+
plan.set_input input
|
231
|
+
expect(plan.execute).to eq(true)
|
232
|
+
expect(plan.output).to eq(output)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "calculates 2D real input/complex output DFT" do
|
236
|
+
input = NMatrix.new([16], [
|
237
|
+
1 , 5,54 ,656,
|
238
|
+
4.3,1.32,-43.34,14 ,
|
239
|
+
1 , 5, 54,656,
|
240
|
+
4.3,1.32,-43.34,14
|
241
|
+
], dtype: :float64)
|
242
|
+
output = NMatrix.new([9],
|
243
|
+
[
|
244
|
+
Complex(1384.56, 0.0),
|
245
|
+
Complex(-10.719999999999999, 1327.36),
|
246
|
+
Complex(-1320.72, 0.0),
|
247
|
+
Complex(0.0, 0.0),
|
248
|
+
Complex(0.0, 0.0),
|
249
|
+
Complex(0.0, 0.0),
|
250
|
+
Complex(1479.44, 0.0),
|
251
|
+
Complex(-201.28, 1276.64),
|
252
|
+
Complex(-1103.28, 0.0)
|
253
|
+
], dtype: :complex128
|
254
|
+
)
|
255
|
+
|
256
|
+
plan = NMatrix::FFTW::Plan.new([4,4], type: :real_complex, dim: 2)
|
257
|
+
plan.set_input input
|
258
|
+
expect(plan.execute).to eq(true)
|
259
|
+
expect(plan.output).to eq(output)
|
260
|
+
end
|
261
|
+
|
262
|
+
it "calculates 1D complex input/real output DFT" do
|
263
|
+
input = NMatrix.new([8],
|
264
|
+
[
|
265
|
+
Complex(9.32,0),
|
266
|
+
Complex(43.0,0),
|
267
|
+
Complex(3.20,0),
|
268
|
+
Complex(4.00,0),
|
269
|
+
Complex(5.32,0),
|
270
|
+
Complex(3.20,0),
|
271
|
+
Complex(4.00,0),
|
272
|
+
Complex(5.32,0)
|
273
|
+
], dtype: :complex128)
|
274
|
+
|
275
|
+
output = NMatrix.new([8], [
|
276
|
+
115.04,59.1543,8.24,-51.1543,-72.96,-51.1543,8.24,59.1543
|
277
|
+
], dtype: :float64)
|
278
|
+
|
279
|
+
plan = NMatrix::FFTW::Plan.new([8], type: :complex_real)
|
280
|
+
plan.set_input input
|
281
|
+
expect(plan.execute).to eq(true)
|
282
|
+
expect(plan.output.round(4)).to eq(output)
|
283
|
+
end
|
284
|
+
|
285
|
+
it "calculates 2D complex input/real output DFT" do
|
286
|
+
input = NMatrix.new([9],
|
287
|
+
[
|
288
|
+
Complex(9.32,0),
|
289
|
+
Complex(43.0,0),
|
290
|
+
Complex(3.20,0),
|
291
|
+
Complex(4.00,0),
|
292
|
+
Complex(5.32,0),
|
293
|
+
Complex(3.20,0),
|
294
|
+
Complex(4.00,0),
|
295
|
+
Complex(5.32,0),
|
296
|
+
Complex(45.32,0)
|
297
|
+
], dtype: :complex128)
|
298
|
+
output = NMatrix.new([9], [
|
299
|
+
118.24,-32.36,-32.36,83.86,-35.54,-33.14,83.86,-33.14,-35.54
|
300
|
+
], dtype: :float64)
|
301
|
+
|
302
|
+
plan = NMatrix::FFTW::Plan.new([3,3], type: :complex_real, dim: 2)
|
303
|
+
plan.set_input input
|
304
|
+
expect(plan.execute).to eq(true)
|
305
|
+
expect(plan.output.round(2)) .to eq(output)
|
306
|
+
end
|
307
|
+
|
308
|
+
it "calculates basic 1D real input/real output DFT of kind RODFT00" do
|
309
|
+
input = NMatrix.new([9],
|
310
|
+
[9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64)
|
311
|
+
output = NMatrix.new([9],
|
312
|
+
[126.56,28.77,165.67,-24.76,105.52,-110.31,-1.23,-116.45,-14.44],
|
313
|
+
dtype: :float64)
|
314
|
+
plan = NMatrix::FFTW::Plan.new([9], type: :real_real, real_real_kind: [:rodft00])
|
315
|
+
plan.set_input input
|
316
|
+
expect(plan.execute).to eq(true)
|
317
|
+
expect(plan.output.round(2)).to eq(output)
|
318
|
+
end
|
319
|
+
|
320
|
+
it "calculates basic 1D real input/real output DFT of kind REDFT10" do
|
321
|
+
input = NMatrix.new([9],
|
322
|
+
[9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64)
|
323
|
+
output = NMatrix.new([9],
|
324
|
+
[245.36,-6.12,126.84,-62.35,35.00,-109.42,-38.24,-92.49,-21.20],
|
325
|
+
dtype: :float64)
|
326
|
+
|
327
|
+
plan = NMatrix::FFTW::Plan.new([9], type: :real_real, real_real_kind: [:redft10])
|
328
|
+
plan.set_input input
|
329
|
+
expect(plan.execute).to eq(true)
|
330
|
+
expect(plan.output.round(2)).to eq(output)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "calculates 2D DFT for real input/real output of kind REDFT10, REDFT11" do
|
334
|
+
input = NMatrix.new([9],
|
335
|
+
[9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64)
|
336
|
+
output = NMatrix.new([9],
|
337
|
+
[272.181,-249.015,66.045,72.334,23.907,-228.463,85.368,-105.331,30.836],
|
338
|
+
dtype: :float64)
|
339
|
+
|
340
|
+
plan = NMatrix::FFTW::Plan.new([3,3], type: :real_real,
|
341
|
+
real_real_kind: [:redft10, :redft11], dim: 2)
|
342
|
+
plan.set_input input
|
343
|
+
expect(plan.execute).to eq(true)
|
344
|
+
expect(plan.output.round(3)) .to eq(output)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|