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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/ext/nmatrix/data/complex.h +388 -0
  3. data/ext/nmatrix/data/data.h +652 -0
  4. data/ext/nmatrix/data/meta.h +64 -0
  5. data/ext/nmatrix/data/ruby_object.h +389 -0
  6. data/ext/nmatrix/math/asum.h +120 -0
  7. data/ext/nmatrix/math/cblas_enums.h +36 -0
  8. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  9. data/ext/nmatrix/math/gemm.h +241 -0
  10. data/ext/nmatrix/math/gemv.h +178 -0
  11. data/ext/nmatrix/math/getrf.h +255 -0
  12. data/ext/nmatrix/math/getrs.h +121 -0
  13. data/ext/nmatrix/math/imax.h +79 -0
  14. data/ext/nmatrix/math/laswp.h +165 -0
  15. data/ext/nmatrix/math/long_dtype.h +49 -0
  16. data/ext/nmatrix/math/math.h +745 -0
  17. data/ext/nmatrix/math/nrm2.h +160 -0
  18. data/ext/nmatrix/math/rot.h +117 -0
  19. data/ext/nmatrix/math/rotg.h +106 -0
  20. data/ext/nmatrix/math/scal.h +71 -0
  21. data/ext/nmatrix/math/trsm.h +332 -0
  22. data/ext/nmatrix/math/util.h +148 -0
  23. data/ext/nmatrix/nm_memory.h +60 -0
  24. data/ext/nmatrix/nmatrix.h +438 -0
  25. data/ext/nmatrix/ruby_constants.h +106 -0
  26. data/ext/nmatrix/storage/common.h +177 -0
  27. data/ext/nmatrix/storage/dense/dense.h +129 -0
  28. data/ext/nmatrix/storage/list/list.h +138 -0
  29. data/ext/nmatrix/storage/storage.h +99 -0
  30. data/ext/nmatrix/storage/yale/class.h +1139 -0
  31. data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
  32. data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
  33. data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
  34. data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
  35. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
  36. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
  37. data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
  38. data/ext/nmatrix/storage/yale/yale.h +203 -0
  39. data/ext/nmatrix/types.h +55 -0
  40. data/ext/nmatrix/util/io.h +115 -0
  41. data/ext/nmatrix/util/sl_list.h +144 -0
  42. data/ext/nmatrix/util/util.h +78 -0
  43. data/ext/nmatrix_fftw/extconf.rb +122 -0
  44. data/ext/nmatrix_fftw/nmatrix_fftw.cpp +274 -0
  45. data/lib/nmatrix/fftw.rb +343 -0
  46. data/spec/00_nmatrix_spec.rb +736 -0
  47. data/spec/01_enum_spec.rb +190 -0
  48. data/spec/02_slice_spec.rb +389 -0
  49. data/spec/03_nmatrix_monkeys_spec.rb +78 -0
  50. data/spec/2x2_dense_double.mat +0 -0
  51. data/spec/4x4_sparse.mat +0 -0
  52. data/spec/4x5_dense.mat +0 -0
  53. data/spec/blas_spec.rb +193 -0
  54. data/spec/elementwise_spec.rb +303 -0
  55. data/spec/homogeneous_spec.rb +99 -0
  56. data/spec/io/fortran_format_spec.rb +88 -0
  57. data/spec/io/harwell_boeing_spec.rb +98 -0
  58. data/spec/io/test.rua +9 -0
  59. data/spec/io_spec.rb +149 -0
  60. data/spec/lapack_core_spec.rb +482 -0
  61. data/spec/leakcheck.rb +16 -0
  62. data/spec/math_spec.rb +807 -0
  63. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  64. data/spec/nmatrix_yale_spec.rb +286 -0
  65. data/spec/plugins/fftw/fftw_spec.rb +348 -0
  66. data/spec/rspec_monkeys.rb +56 -0
  67. data/spec/rspec_spec.rb +34 -0
  68. data/spec/shortcuts_spec.rb +310 -0
  69. data/spec/slice_set_spec.rb +157 -0
  70. data/spec/spec_helper.rb +149 -0
  71. data/spec/stat_spec.rb +203 -0
  72. data/spec/test.pcd +20 -0
  73. data/spec/utm5940.mtx +83844 -0
  74. 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