nmatrix 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +5 -0
- data/History.txt +97 -0
- data/Manifest.txt +34 -7
- data/README.rdoc +13 -13
- data/Rakefile +36 -26
- data/ext/nmatrix/data/data.cpp +15 -2
- data/ext/nmatrix/data/data.h +4 -0
- data/ext/nmatrix/data/ruby_object.h +5 -14
- data/ext/nmatrix/extconf.rb +3 -2
- data/ext/nmatrix/{util/math.cpp → math.cpp} +296 -6
- data/ext/nmatrix/math/asum.h +143 -0
- data/ext/nmatrix/math/geev.h +82 -0
- data/ext/nmatrix/math/gemm.h +267 -0
- data/ext/nmatrix/math/gemv.h +208 -0
- data/ext/nmatrix/math/ger.h +96 -0
- data/ext/nmatrix/math/gesdd.h +80 -0
- data/ext/nmatrix/math/gesvd.h +78 -0
- data/ext/nmatrix/math/getf2.h +86 -0
- data/ext/nmatrix/math/getrf.h +240 -0
- data/ext/nmatrix/math/getri.h +107 -0
- data/ext/nmatrix/math/getrs.h +125 -0
- data/ext/nmatrix/math/idamax.h +86 -0
- data/ext/nmatrix/{util → math}/lapack.h +60 -356
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +52 -0
- data/ext/nmatrix/math/math.h +1154 -0
- data/ext/nmatrix/math/nrm2.h +181 -0
- data/ext/nmatrix/math/potrs.h +125 -0
- data/ext/nmatrix/math/rot.h +141 -0
- data/ext/nmatrix/math/rotg.h +115 -0
- data/ext/nmatrix/math/scal.h +73 -0
- data/ext/nmatrix/math/swap.h +73 -0
- data/ext/nmatrix/math/trsm.h +383 -0
- data/ext/nmatrix/nmatrix.cpp +176 -152
- data/ext/nmatrix/nmatrix.h +1 -2
- data/ext/nmatrix/ruby_constants.cpp +9 -4
- data/ext/nmatrix/ruby_constants.h +1 -0
- data/ext/nmatrix/storage/dense.cpp +57 -41
- data/ext/nmatrix/storage/list.cpp +52 -50
- data/ext/nmatrix/storage/storage.cpp +59 -43
- data/ext/nmatrix/storage/yale.cpp +352 -333
- data/ext/nmatrix/storage/yale.h +4 -0
- data/lib/nmatrix.rb +2 -2
- data/lib/nmatrix/blas.rb +4 -4
- data/lib/nmatrix/enumerate.rb +241 -0
- data/lib/nmatrix/lapack.rb +54 -1
- data/lib/nmatrix/math.rb +462 -0
- data/lib/nmatrix/nmatrix.rb +210 -486
- data/lib/nmatrix/nvector.rb +0 -62
- data/lib/nmatrix/rspec.rb +75 -0
- data/lib/nmatrix/shortcuts.rb +136 -108
- data/lib/nmatrix/version.rb +1 -1
- data/spec/blas_spec.rb +20 -12
- data/spec/elementwise_spec.rb +22 -13
- data/spec/io_spec.rb +1 -0
- data/spec/lapack_spec.rb +197 -0
- data/spec/nmatrix_spec.rb +39 -38
- data/spec/nvector_spec.rb +3 -9
- data/spec/rspec_monkeys.rb +29 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +14 -16
- data/spec/slice_spec.rb +242 -186
- data/spec/spec_helper.rb +19 -0
- metadata +33 -5
- data/ext/nmatrix/util/math.h +0 -2612
data/spec/blas_spec.rb
CHANGED
@@ -55,7 +55,7 @@ describe NMatrix::BLAS do
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
[:rational32,:rational64,:rational128
|
58
|
+
[:rational32,:rational64,:rational128].each do |dtype|
|
59
59
|
context dtype do
|
60
60
|
it "exposes cblas rot"
|
61
61
|
end
|
@@ -65,13 +65,13 @@ describe NMatrix::BLAS do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
[:float32, :float64].each do |dtype|
|
68
|
+
[:float32, :float64, :complex64, :complex128, :object].each do |dtype|
|
69
69
|
context dtype do
|
70
70
|
|
71
71
|
it "exposes cblas rot" do
|
72
72
|
x = NVector.new(5, [1,2,3,4,5], dtype)
|
73
73
|
y = NVector.new(5, [-5,-4,-3,-2,-1], dtype)
|
74
|
-
x, y = NMatrix::BLAS::rot(x, y,
|
74
|
+
x, y = NMatrix::BLAS::rot(x, y, 1.quo(2), Math.sqrt(3).quo(2), -1)
|
75
75
|
|
76
76
|
x[0].should be_within(1e-4).of(-0.3660254037844386)
|
77
77
|
x[1].should be_within(1e-4).of(-0.7320508075688772)
|
@@ -86,21 +86,29 @@ describe NMatrix::BLAS do
|
|
86
86
|
y[4].should be_within(1e-4).of(-1.3660254037844386)
|
87
87
|
end
|
88
88
|
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
[:float32, :float64, :complex64, :complex128, :object].each do |dtype|
|
93
|
+
context dtype do
|
94
|
+
|
89
95
|
it "exposes cblas rotg" do
|
96
|
+
pending("broken for :object") if dtype == :object
|
90
97
|
ab = NVector.new(2, [6,-8], dtype)
|
91
98
|
c,s = NMatrix::BLAS::rotg(ab)
|
92
|
-
|
93
|
-
|
94
|
-
|
99
|
+
|
100
|
+
if [:float32, :float64].include?(dtype)
|
101
|
+
ab[0].should be_within(1e-6).of(-10)
|
102
|
+
ab[1].should be_within(1e-6).of(-5.quo(3))
|
103
|
+
c.should be_within(1e-6).of(-3.quo(5))
|
104
|
+
else
|
105
|
+
ab[0].should be_within(1e-6).of(10)
|
106
|
+
ab[1].should be_within(1e-6).of(5.quo(3))
|
107
|
+
c.should be_within(1e-6).of(3.quo(5))
|
108
|
+
end
|
95
109
|
s.should be_within(1e-6).of(4.quo(5))
|
96
110
|
end
|
97
111
|
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
[:float32, :float64, :complex64, :complex128].each do |dtype|
|
102
|
-
context dtype do
|
103
|
-
|
104
112
|
# Note: this exposes gemm, not cblas_gemm (which is the unfriendly CBLAS no-error-checking version)
|
105
113
|
it "exposes gemm" do
|
106
114
|
#STDERR.puts "dtype=#{dtype.to_s}"
|
data/spec/elementwise_spec.rb
CHANGED
@@ -65,11 +65,7 @@ describe NMatrix do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
it "should perform element-wise addition" do
|
68
|
-
|
69
|
-
r[0,0] = 52
|
70
|
-
r[1,1] = -8
|
71
|
-
q = @n + @m
|
72
|
-
q.should == r
|
68
|
+
(@n+@m).should == NMatrix.new(:dense, 3, [52,30,0,0,-8,0,6,0,0], :int64).cast(:yale, :int64)
|
73
69
|
end
|
74
70
|
|
75
71
|
it "should perform element-wise subtraction" do
|
@@ -213,6 +209,21 @@ describe NMatrix do
|
|
213
209
|
end
|
214
210
|
|
215
211
|
context "dense" do
|
212
|
+
context "scalar arithmetic" do
|
213
|
+
before :each do
|
214
|
+
@n = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "works for integers" do
|
218
|
+
(@n+1).should == NMatrix.new(:dense, 2, [2,3,4,5], :int64)
|
219
|
+
end
|
220
|
+
|
221
|
+
#it "works for complex64" do
|
222
|
+
# n = @n.cast(:dtype => :complex64)
|
223
|
+
# (n + 10.0).to_a.should == [Complex(11.0), Complex(12.0), Complex(13.0), Complex(14.0)]
|
224
|
+
#end
|
225
|
+
end
|
226
|
+
|
216
227
|
context "elementwise arithmetic" do
|
217
228
|
before :each do
|
218
229
|
@n = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
@@ -241,16 +252,14 @@ describe NMatrix do
|
|
241
252
|
r.should == NMatrix.new(:dense, [2,2], [-1, -2, 1, 0], :int64)
|
242
253
|
end
|
243
254
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
255
|
+
it "exponentiates" do
|
256
|
+
r = @n ** 2
|
257
|
+
# TODO: We might have problems with the dtype.
|
258
|
+
r.should == NMatrix.new(:dense, [2,2], [1, 4, 9, 16], :int64)
|
259
|
+
end
|
249
260
|
|
250
261
|
it "modulo" do
|
251
|
-
|
252
|
-
r = @n % @m
|
253
|
-
r.should == NMatrix.new(:dense, [2,2], [0, 1, 2, 3], :int64)
|
262
|
+
(@n % (@m + 2)).should == NMatrix.new(:dense, [2,2], [-1, 0, 1, 4], :int64)
|
254
263
|
end
|
255
264
|
end
|
256
265
|
|
data/spec/io_spec.rb
CHANGED
@@ -65,6 +65,7 @@ describe NMatrix::IO do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
it "loads and saves MatrixMarket .mtx file containing a single large sparse double matrix" do
|
68
|
+
pending "spec disabled because it's so slow"
|
68
69
|
n = NMatrix::IO::Market.load("spec/utm5940.mtx")
|
69
70
|
NMatrix::IO::Market.save(n, "spec/utm5940.saved.mtx")
|
70
71
|
`wc -l spec/utm5940.mtx`.split[0].should == `wc -l spec/utm5940.saved.mtx`.split[0]
|
data/spec/lapack_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'pry'
|
1
2
|
# = NMatrix
|
2
3
|
#
|
3
4
|
# A linear algebra library for scientific computation in Ruby.
|
@@ -38,6 +39,17 @@ describe NMatrix::LAPACK do
|
|
38
39
|
b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype)
|
39
40
|
a.should == b
|
40
41
|
end
|
42
|
+
|
43
|
+
it "exposes NMatrix#permute_columns and #permute_columns! (user-friendly laswp)" do
|
44
|
+
a = NMatrix.new(:dense, [3,4], [1,2,3,4,5,6,7,8,9,10,11,12], dtype)
|
45
|
+
b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype)
|
46
|
+
piv = [2,1,3,0]
|
47
|
+
r = a.permute_columns(piv)
|
48
|
+
r.should_not == a
|
49
|
+
r.should == b
|
50
|
+
a.permute_columns!(piv)
|
51
|
+
a.should == b
|
52
|
+
end
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
@@ -114,7 +126,192 @@ describe NMatrix::LAPACK do
|
|
114
126
|
end
|
115
127
|
end
|
116
128
|
|
129
|
+
it "exposes gesdd" do
|
130
|
+
if [:float32, :float64].include? dtype
|
131
|
+
a = NMatrix.new([5,6], %w|8.79 9.93 9.83 5.45 3.16
|
132
|
+
6.11 6.91 5.04 -0.27 7.98
|
133
|
+
-9.15 -7.93 4.86 4.85 3.01
|
134
|
+
9.57 1.64 8.83 0.74 5.80
|
135
|
+
-3.49 4.02 9.80 10.00 4.27
|
136
|
+
9.84 0.15 -8.99 -6.02 -5.31|.map(&:to_f), dtype)
|
137
|
+
s_true = NMatrix.new([1,5], [27.468732418221848, 22.643185009774697, 8.558388228482576, 5.985723201512133, 2.014899658715756], dtype)
|
138
|
+
right_true = NMatrix.new([5,6], [0.5911423764124365, 0.2631678147140568, 0.35543017386282716, 0.3142643627269275, 0.2299383153647484, 0.0, 0.39756679420242547, 0.24379902792633046, -0.22239000068544604, -0.7534661509534584, -0.36358968669749664, 0.0, 0.03347896906244727, -0.6002725806935828, -0.45083926892230763, 0.23344965724471425, -0.3054757327479317, 0.0, 0.4297069031370182, 0.23616680628112555, -0.6858628638738117, 0.3318600182003095, 0.1649276348845103, 0.0, 0.4697479215666587, -0.350891398883702, 0.38744460309967327, 0.15873555958215635, -0.5182574373535355, 0.0, -0.29335875846440357, 0.57626211913389, -0.020852917980871258, 0.3790776670601607, -0.6525516005923976, 0.0], dtype)
|
139
|
+
#right_true = NMatrix.new([5,6],
|
140
|
+
# %w|-0.59 0.26 0.36 0.31 0.23
|
141
|
+
# -0.40 0.24 -0.22 -0.75 -0.36
|
142
|
+
# -0.03 -0.60 -0.45 0.23 -0.31
|
143
|
+
# -0.43 0.24 -0.69 0.33 0.16
|
144
|
+
# -0.47 -0.35 0.39 0.16 -0.52
|
145
|
+
# 0.29 0.58 -0.02 0.38 -0.65|.map(&:to_f),
|
146
|
+
# dtype)
|
147
|
+
left_true = NMatrix.new([5,5], [0.25138279272049635, 0.3968455517769292, 0.6921510074703637, 0.3661704447722309, 0.4076352386533525, 0.814836686086339, 0.3586615001880027, -0.24888801115928438, -0.3685935379446176, -0.09796256926688672, -0.2606185055842211, 0.7007682094072526, -0.22081144672043734, 0.38593848318854174, -0.49325014285102375, 0.3967237771305971, -0.4507112412166429, 0.2513211496937535, 0.4342486014366711, -0.6226840720358049, -0.21802776368654594, 0.14020994987112056, 0.5891194492399431, -0.6265282503648172, -0.4395516923423326], dtype)
|
148
|
+
#left_true = NMatrix.new([5,5],
|
149
|
+
# %w|-0.25 -0.40 -0.69 -0.37 -0.41
|
150
|
+
# 0.81 0.36 -0.25 -0.37 -0.10
|
151
|
+
# -0.26 0.70 -0.22 0.39 -0.49
|
152
|
+
# 0.40 -0.45 0.25 0.43 -0.62
|
153
|
+
# -0.22 0.14 0.59 -0.63 -0.44|.map(&:to_f),
|
154
|
+
# dtype)
|
155
|
+
s = NMatrix.new([5,1], 0, dtype)
|
156
|
+
u = NMatrix.new([5,5], 0, dtype)
|
157
|
+
ldu = 5
|
158
|
+
vt = NMatrix.new([6,6], 0, dtype)
|
159
|
+
ldvt= 6
|
160
|
+
elsif [:complex64, :complex128].include? dtype
|
161
|
+
#http://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/cgesvd_ex.c.htm
|
162
|
+
pending "Example may be wrong"
|
163
|
+
else
|
164
|
+
a = NMatrix.new([4,3], dtype)
|
165
|
+
end
|
166
|
+
err = case dtype
|
167
|
+
when :float32, :complex64
|
168
|
+
1e-6
|
169
|
+
when :float64, :complex128
|
170
|
+
1e-15
|
171
|
+
else
|
172
|
+
1e-64 # FIXME: should be 0, but be_within(0) does not work.
|
173
|
+
end
|
174
|
+
err = err *5e1
|
175
|
+
begin
|
117
176
|
|
177
|
+
info = NMatrix::LAPACK::lapack_gesvd(:a, :a, a.shape[0], a.shape[1], a, a.shape[0], s, u, ldu, vt, ldvt, 500)
|
178
|
+
|
179
|
+
rescue NotImplementedError => e
|
180
|
+
pending e.to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
u.should be_within(err).of(left_true)
|
184
|
+
#FIXME: Is the next line correct?
|
185
|
+
vt[0...right_true.shape[0], 0...right_true.shape[1]-1].should be_within(err).of(right_true[0...right_true.shape[0],0...right_true.shape[1]-1])
|
186
|
+
s.transpose.should be_within(err).of(s_true.row(0))
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
it "exposes gesvd" do
|
191
|
+
# http://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgesvd_ex.c.htm
|
192
|
+
if [:float32, :float64].include? dtype
|
193
|
+
a = NMatrix.new([5,6], %w|8.79 9.93 9.83 5.45 3.16
|
194
|
+
6.11 6.91 5.04 -0.27 7.98
|
195
|
+
-9.15 -7.93 4.86 4.85 3.01
|
196
|
+
9.57 1.64 8.83 0.74 5.80
|
197
|
+
-3.49 4.02 9.80 10.00 4.27
|
198
|
+
9.84 0.15 -8.99 -6.02 -5.31|.map(&:to_f), dtype)
|
199
|
+
s_true = NMatrix.new([1,5], [27.468732418221848, 22.643185009774697, 8.558388228482576, 5.985723201512133, 2.014899658715756], dtype)
|
200
|
+
right_true = NMatrix.new([5,6], [0.5911423764124365, 0.2631678147140568, 0.35543017386282716, 0.3142643627269275, 0.2299383153647484, 0.0, 0.39756679420242547, 0.24379902792633046, -0.22239000068544604, -0.7534661509534584, -0.36358968669749664, 0.0, 0.03347896906244727, -0.6002725806935828, -0.45083926892230763, 0.23344965724471425, -0.3054757327479317, 0.0, 0.4297069031370182, 0.23616680628112555, -0.6858628638738117, 0.3318600182003095, 0.1649276348845103, 0.0, 0.4697479215666587, -0.350891398883702, 0.38744460309967327, 0.15873555958215635, -0.5182574373535355, 0.0, -0.29335875846440357, 0.57626211913389, -0.020852917980871258, 0.3790776670601607, -0.6525516005923976, 0.0], dtype)
|
201
|
+
#right_true = NMatrix.new([5,6],
|
202
|
+
# %w|-0.59 0.26 0.36 0.31 0.23
|
203
|
+
# -0.40 0.24 -0.22 -0.75 -0.36
|
204
|
+
# -0.03 -0.60 -0.45 0.23 -0.31
|
205
|
+
# -0.43 0.24 -0.69 0.33 0.16
|
206
|
+
# -0.47 -0.35 0.39 0.16 -0.52
|
207
|
+
# 0.29 0.58 -0.02 0.38 -0.65|.map(&:to_f),
|
208
|
+
# dtype)
|
209
|
+
left_true = NMatrix.new([5,5], [0.25138279272049635, 0.3968455517769292, 0.6921510074703637, 0.3661704447722309, 0.4076352386533525, 0.814836686086339, 0.3586615001880027, -0.24888801115928438, -0.3685935379446176, -0.09796256926688672, -0.2606185055842211, 0.7007682094072526, -0.22081144672043734, 0.38593848318854174, -0.49325014285102375, 0.3967237771305971, -0.4507112412166429, 0.2513211496937535, 0.4342486014366711, -0.6226840720358049, -0.21802776368654594, 0.14020994987112056, 0.5891194492399431, -0.6265282503648172, -0.4395516923423326], dtype)
|
210
|
+
#left_true = NMatrix.new([5,5],
|
211
|
+
# %w|-0.25 -0.40 -0.69 -0.37 -0.41
|
212
|
+
# 0.81 0.36 -0.25 -0.37 -0.10
|
213
|
+
# -0.26 0.70 -0.22 0.39 -0.49
|
214
|
+
# 0.40 -0.45 0.25 0.43 -0.62
|
215
|
+
# -0.22 0.14 0.59 -0.63 -0.44|.map(&:to_f),
|
216
|
+
# dtype)
|
217
|
+
s = NMatrix.new([5,1], 0, dtype)
|
218
|
+
u = NMatrix.new([5,5], 0, dtype)
|
219
|
+
ldu = 5
|
220
|
+
vt = NMatrix.new([6,6], 0, dtype)
|
221
|
+
ldvt= 6
|
222
|
+
elsif [:complex64, :complex128].include? dtype
|
223
|
+
#http://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/cgesvd_ex.c.htm
|
224
|
+
pending "Example may be wrong"
|
225
|
+
a = NMatrix.new([4,3], [[ 5.91, -5.69], [ 7.09, 2.72], [ 7.78, -4.06], [ -0.79, -7.21], [ -3.15, -4.08], [ -1.89, 3.27], [ 4.57, -2.07], [ -3.88, -3.30], [ -4.89, 4.20], [ 4.10, -6.70], [ 3.28, -3.84], [ 3.84, 1.19]].map {|e| Complex(*e) } , dtype)
|
226
|
+
s_true = NMatrix.new([3,1], [17.63, 11.61, 6.78], dtype)
|
227
|
+
left_true = NMatrix.new([4,4], [[-0.86, 0.0], [0.4, 0.0], [0.32, 0.0], [-0.35, 0.13], [-0.24, -0.21], [-0.63, 0.6], [0.15, 0.32], [0.61, 0.61], [-0.36, 0.1]].map {|e| Complex(*e)}, dtype)
|
228
|
+
right_true = NMatrix.new([4,3], [[ -0.22, 0.51], [ -0.37, -0.32], [ -0.53, 0.11], [ 0.15, 0.38], [ 0.31, 0.31], [ 0.09, -0.57], [ 0.18, -0.39], [ 0.38, -0.39], [ 0.53, 0.24], [ 0.49, 0.28], [ -0.47, -0.25], [ -0.15, 0.19]].map {|e| Complex *e} , dtype)
|
229
|
+
|
230
|
+
s = NMatrix.new([3,1], 0, dtype)
|
231
|
+
u = NMatrix.new([4,4], 0, dtype)
|
232
|
+
ldu = 4
|
233
|
+
vt = NMatrix.new([3,3], 0, dtype)
|
234
|
+
ldvt= 3
|
235
|
+
else
|
236
|
+
a = NMatrix.new([4,3], dtype)
|
237
|
+
end
|
238
|
+
err = case dtype
|
239
|
+
when :float32, :complex64
|
240
|
+
1e-6
|
241
|
+
when :float64, :complex128
|
242
|
+
1e-15
|
243
|
+
else
|
244
|
+
1e-64 # FIXME: should be 0, but be_within(0) does not work.
|
245
|
+
end
|
246
|
+
err = err *5e1
|
247
|
+
begin
|
248
|
+
|
249
|
+
info = NMatrix::LAPACK::lapack_gesvd(:a, :a, a.shape[0], a.shape[1], a, a.shape[0], s, u, ldu, vt, ldvt, 500)
|
250
|
+
|
251
|
+
rescue NotImplementedError => e
|
252
|
+
pending e.to_s
|
253
|
+
end
|
254
|
+
|
255
|
+
u.should be_within(err).of(left_true)
|
256
|
+
#FIXME: Is the next line correct?
|
257
|
+
vt[0...right_true.shape[0], 0...right_true.shape[1]-1].should be_within(err).of(right_true[0...right_true.shape[0],0...right_true.shape[1]-1])
|
258
|
+
s.transpose.should be_within(err).of(s_true.row(0))
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
it "exposes geev" do
|
264
|
+
pending("needs rational implementation") if dtype.to_s =~ /rational/
|
265
|
+
ary = %w|-1.01 0.86 -4.60 3.31 -4.81
|
266
|
+
3.98 0.53 -7.04 5.29 3.55
|
267
|
+
3.30 8.26 -3.89 8.20 -1.51
|
268
|
+
4.43 4.96 -7.66 -7.33 6.18
|
269
|
+
7.31 -6.43 -6.16 2.47 5.58|
|
270
|
+
ary = dtype.to_s =~ /complex/ ? ary.map(&:to_c) : ary.map(&:to_f)
|
271
|
+
|
272
|
+
a = NMatrix.new(:dense, 5, ary, dtype).transpose
|
273
|
+
lda = 5
|
274
|
+
n = 5
|
275
|
+
|
276
|
+
wr = NMatrix.new(:dense, [n,1], 0, dtype)
|
277
|
+
wi = dtype.to_s =~ /complex/ ? nil : NMatrix.new(:dense, [n,1], 0, dtype)
|
278
|
+
vl = NMatrix.new(:dense, n, 0, dtype)
|
279
|
+
vr = NMatrix.new(:dense, n, 0, dtype)
|
280
|
+
ldvr = n
|
281
|
+
ldvl = n
|
282
|
+
|
283
|
+
info = NMatrix::LAPACK::lapack_geev(:left, :right, n, a.clone, lda, wr.clone, wi.nil? ? nil : wi.clone, vl.clone, ldvl, vr.clone, ldvr, -1)
|
284
|
+
info.should == 0
|
285
|
+
|
286
|
+
info = NMatrix::LAPACK::lapack_geev(:left, :right, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, 2*n)
|
287
|
+
|
288
|
+
# Negate these and we get a correct result:
|
289
|
+
vr = vr.transpose
|
290
|
+
vl = vl.transpose
|
291
|
+
|
292
|
+
pending("Need complex example") if dtype.to_s =~ /complex/
|
293
|
+
vl_true = NMatrix.new(:dense, 5, [0.04, 0.29, 0.13, 0.33, -0.04,
|
294
|
+
0.62, 0.0, -0.69, 0.0, -0.56,
|
295
|
+
-0.04, -0.58, 0.39, 0.07, 0.13,
|
296
|
+
0.28, 0.01, 0.02, 0.19, 0.80,
|
297
|
+
-0.04, 0.34, 0.40, -0.22, -0.18 ], :float64)
|
298
|
+
|
299
|
+
vl.abs.should be_within(1e-2).of(vl_true.abs)
|
300
|
+
# Not checking vr_true.
|
301
|
+
# Example from:
|
302
|
+
# http://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/lapacke_dgeev_row.c.htm
|
303
|
+
#
|
304
|
+
# This is what the result should look like:
|
305
|
+
# [
|
306
|
+
# [0.10806497186422348, 0.16864821314811707, 0.7322341203689575, 0.0, -0.46064677834510803]
|
307
|
+
# [0.40631288290023804, -0.25900983810424805, -0.02646319754421711, -0.01694658398628235, -0.33770373463630676]
|
308
|
+
# [0.10235744714736938, -0.5088024139404297, 0.19164878129959106, -0.29256555438041687, -0.3087439239025116]
|
309
|
+
# [0.39863115549087524, -0.0913335531949997, -0.07901126891374588, -0.07807594537734985, 0.7438457012176514]
|
310
|
+
# [ 0.5395349860191345, 0.0, -0.29160499572753906, -0.49310219287872314, -0.15852922201156616]
|
311
|
+
# ]
|
312
|
+
#
|
313
|
+
|
314
|
+
end
|
118
315
|
end
|
119
316
|
end
|
120
317
|
end
|
data/spec/nmatrix_spec.rb
CHANGED
@@ -29,6 +29,12 @@ require File.dirname(__FILE__) + "/spec_helper.rb"
|
|
29
29
|
|
30
30
|
describe NMatrix do
|
31
31
|
|
32
|
+
it "adequately requires information to access a single entry of a dense matrix" do
|
33
|
+
n = NMatrix.new(:dense, 4, [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], :float64)
|
34
|
+
n[0,0].should == 0
|
35
|
+
expect { n[0] }.should raise_error(ArgumentError)
|
36
|
+
end
|
37
|
+
|
32
38
|
it "calculates exact determinants on small square matrices" do
|
33
39
|
a = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
34
40
|
a.det_exact.should == -2
|
@@ -145,11 +151,6 @@ describe NMatrix do
|
|
145
151
|
m.dtype.should == :float64
|
146
152
|
end
|
147
153
|
|
148
|
-
it "dense pretty_prints complex values" do
|
149
|
-
n = NMatrix.new([4,3], COMPLEX_MATRIX43A_ARRAY, :complex128)
|
150
|
-
n.pretty_print
|
151
|
-
end
|
152
|
-
|
153
154
|
|
154
155
|
[:dense, :list, :yale].each do |storage_type|
|
155
156
|
context storage_type do
|
@@ -172,9 +173,9 @@ describe NMatrix do
|
|
172
173
|
end
|
173
174
|
|
174
175
|
it "enforces shape boundaries" do
|
175
|
-
|
176
|
-
|
177
|
-
|
176
|
+
expect { NMatrix.new(storage_type, [1,10], storage_type == :yale ? :int8 : 0)[-1,0] }.should raise_error
|
177
|
+
expect { NMatrix.new(storage_type, [1,10], storage_type == :yale ? :int8 : 0)[1,0] }.should raise_error(RangeError)
|
178
|
+
expect { NMatrix.new(storage_type, [1,10], storage_type == :yale ? :int8 : 0)[0,10] }.should raise_error(RangeError)
|
178
179
|
end
|
179
180
|
|
180
181
|
it "sets and gets" do
|
@@ -359,53 +360,53 @@ describe NMatrix do
|
|
359
360
|
context "mapping and reduction related functions" do
|
360
361
|
|
361
362
|
before :each do
|
362
|
-
@nm_1d =
|
363
|
-
@nm_2d =
|
363
|
+
@nm_1d = NMatrix[5.0,0.0,1.0,2.0,3.0]
|
364
|
+
@nm_2d = NMatrix[[0.0,1.0],[2.0,3.0]]
|
364
365
|
end
|
365
366
|
|
366
367
|
it "behaves like Enumerable#reduce with no argument to reduce" do
|
367
368
|
@nm_1d.reduce_along_dim(0) { |acc, el| acc + el }.to_f.should eq 11
|
368
|
-
@nm_2d.reduce_along_dim(1) { |acc, el| acc + el }.should eq
|
369
|
+
@nm_2d.reduce_along_dim(1) { |acc, el| acc + el }.should eq NMatrix[[1, 5]]
|
369
370
|
end
|
370
371
|
|
371
372
|
it "should calculate the mean along the specified dimension" do
|
372
|
-
@nm_1d.mean.should eq
|
373
|
-
@nm_2d.mean.should eq
|
373
|
+
@nm_1d.mean.should eq NMatrix[2.2]
|
374
|
+
@nm_2d.mean.should eq NMatrix[[1.0,2.0]]
|
374
375
|
end
|
375
376
|
|
376
377
|
it "should calculate the minimum along the specified dimension" do
|
377
378
|
@nm_1d.min.should eq 0.0
|
378
|
-
@nm_2d.min.should eq
|
379
|
-
@nm_2d.min(1).should eq
|
379
|
+
@nm_2d.min.should eq NMatrix[[0.0, 1.0]]
|
380
|
+
@nm_2d.min(1).should eq NMatrix[[0.0], [2.0]]
|
380
381
|
end
|
381
382
|
|
382
383
|
it "should calculate the maximum along the specified dimension" do
|
383
384
|
@nm_1d.max.should eq 5.0
|
384
|
-
@nm_2d.max.should eq
|
385
|
+
@nm_2d.max.should eq NMatrix[[2.0, 3.0]]
|
385
386
|
end
|
386
387
|
|
387
388
|
it "should calculate the variance along the specified dimension" do
|
388
|
-
@nm_1d.variance.should eq
|
389
|
-
@nm_2d.variance(1).should eq
|
389
|
+
@nm_1d.variance.should eq NMatrix[3.7]
|
390
|
+
@nm_2d.variance(1).should eq NMatrix[[0.5], [0.5]]
|
390
391
|
end
|
391
392
|
|
392
393
|
it "should calculate the sum along the specified dimension" do
|
393
|
-
@nm_1d.sum.should eq
|
394
|
-
@nm_2d.sum.should eq
|
394
|
+
@nm_1d.sum.should eq NMatrix[11]
|
395
|
+
@nm_2d.sum.should eq NMatrix[[2], [4]]
|
395
396
|
end
|
396
397
|
|
397
398
|
it "should calculate the standard deviation along the specified dimension" do
|
398
|
-
@nm_1d.std.should eq
|
399
|
-
@nm_2d.std(1).should eq
|
399
|
+
@nm_1d.std.should eq NMatrix[Math.sqrt(3.7)]
|
400
|
+
@nm_2d.std(1).should eq NMatrix[[Math.sqrt(0.5)], [Math.sqrt(0.5)]]
|
400
401
|
end
|
401
402
|
|
402
403
|
it "should raise an ArgumentError when any invalid dimension is provided" do
|
403
|
-
expect { @nm_1d.mean(3) }.to raise_exception(
|
404
|
+
expect { @nm_1d.mean(3) }.to raise_exception(RangeError)
|
404
405
|
end
|
405
406
|
|
406
407
|
it "should convert to float if it contains only a single element" do
|
407
|
-
|
408
|
-
|
408
|
+
NMatrix[4.0].to_f.should eq 4.0
|
409
|
+
NMatrix[[[[4.0]]]].to_f.should eq 4.0
|
409
410
|
end
|
410
411
|
|
411
412
|
it "should raise an index error if it contains more than a single element" do
|
@@ -413,8 +414,8 @@ describe NMatrix do
|
|
413
414
|
end
|
414
415
|
|
415
416
|
it "should map a block to all elements" do
|
416
|
-
@nm_1d.map { |e| e ** 2 }.should eq
|
417
|
-
@nm_2d.map { |e| e ** 2 }.should eq
|
417
|
+
@nm_1d.map { |e| e ** 2 }.should eq NMatrix[25.0,0.0,1.0,4.0,9.0]
|
418
|
+
@nm_2d.map { |e| e ** 2 }.should eq NMatrix[[0.0,1.0],[4.0,9.0]]
|
418
419
|
end
|
419
420
|
|
420
421
|
it "should map! a block to all elements in place" do
|
@@ -450,7 +451,7 @@ describe NMatrix do
|
|
450
451
|
en = @nm_1d.reduce_along_dim(0, 1.0)
|
451
452
|
en.each { |a, e| a+e }.to_f.should eq 12
|
452
453
|
en = @nm_2d.reduce_along_dim(1, 1.0)
|
453
|
-
en.each { |a, e| a+e }.should eq
|
454
|
+
en.each { |a, e| a+e }.should eq NMatrix[[2.0],[6.0]]
|
454
455
|
end
|
455
456
|
|
456
457
|
it "should iterate correctly for each_along_dim without a block" do
|
@@ -462,7 +463,7 @@ describe NMatrix do
|
|
462
463
|
res = NMatrix.zeros_like (@nm_2d[0...2, 0])
|
463
464
|
en = @nm_2d.each_along_dim(1)
|
464
465
|
en.each { |e| res += e }
|
465
|
-
res.should eq
|
466
|
+
res.should eq NMatrix[[1.0], [5.0]]
|
466
467
|
end
|
467
468
|
|
468
469
|
it "should yield matrices of matching dtype for each_along_dim" do
|
@@ -487,13 +488,13 @@ describe NMatrix do
|
|
487
488
|
end
|
488
489
|
|
489
490
|
it "should allow overriding the dtype for reduce_along_dim" do
|
490
|
-
m =
|
491
|
+
m = NMatrix[[1,2,3], [3,4,5], :complex128]
|
491
492
|
m.reduce_along_dim(1, 0.0, :float64) do |acc, sub_m|
|
492
493
|
acc.dtype.should eq :float64
|
493
494
|
acc
|
494
495
|
end
|
495
496
|
|
496
|
-
m =
|
497
|
+
m = NMatrix[[1,2,3], [3,4,5], :complex128]
|
497
498
|
m.reduce_along_dim(1, nil, :float64) do |acc, sub_m|
|
498
499
|
acc.dtype.should eq :float64
|
499
500
|
acc
|
@@ -501,30 +502,30 @@ describe NMatrix do
|
|
501
502
|
end
|
502
503
|
|
503
504
|
it "should convert integer dtypes to float when calculating mean" do
|
504
|
-
m =
|
505
|
+
m = NMatrix[[1,2,3], [3,4,5], :int32]
|
505
506
|
m.mean(0).dtype.should eq :float64
|
506
507
|
end
|
507
508
|
|
508
509
|
it "should convert integer dtypes to float when calculating variance" do
|
509
|
-
m =
|
510
|
+
m = NMatrix[[1,2,3], [3,4,5], :int32]
|
510
511
|
m.variance(0).dtype.should eq :float64
|
511
512
|
end
|
512
513
|
|
513
514
|
it "should convert integer dtypes to float when calculating standard deviation" do
|
514
|
-
m =
|
515
|
+
m = NMatrix[[1,2,3], [3,4,5], :int32]
|
515
516
|
m.std(0).dtype.should eq :float64
|
516
517
|
end
|
517
518
|
|
518
519
|
context "_like constructors" do
|
519
520
|
|
520
521
|
it "should create an nmatrix of ones with dimensions and type the same as its argument" do
|
521
|
-
NMatrix.ones_like(@nm_1d).should eq
|
522
|
-
NMatrix.ones_like(@nm_2d).should eq
|
522
|
+
NMatrix.ones_like(@nm_1d).should eq NMatrix[1.0, 1.0, 1.0, 1.0, 1.0]
|
523
|
+
NMatrix.ones_like(@nm_2d).should eq NMatrix[[1.0, 1.0], [1.0, 1.0]]
|
523
524
|
end
|
524
525
|
|
525
526
|
it "should create an nmatrix of zeros with dimensions and type the same as its argument" do
|
526
|
-
NMatrix.zeros_like(@nm_1d).should eq
|
527
|
-
NMatrix.zeros_like(@nm_2d).should eq
|
527
|
+
NMatrix.zeros_like(@nm_1d).should eq NMatrix[0.0, 0.0, 0.0, 0.0, 0.0]
|
528
|
+
NMatrix.zeros_like(@nm_2d).should eq NMatrix[[0.0, 0.0], [0.0, 0.0]]
|
528
529
|
end
|
529
530
|
end
|
530
531
|
end
|