pnmatrix 1.2.4
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/binary_format.txt +53 -0
- data/ext/nmatrix/data/complex.h +388 -0
- data/ext/nmatrix/data/data.cpp +274 -0
- data/ext/nmatrix/data/data.h +651 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +386 -0
- data/ext/nmatrix/extconf.rb +70 -0
- data/ext/nmatrix/math/asum.h +99 -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 +82 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +62 -0
- data/ext/nmatrix/math/magnitude.h +54 -0
- data/ext/nmatrix/math/math.h +751 -0
- data/ext/nmatrix/math/nrm2.h +165 -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 +336 -0
- data/ext/nmatrix/math/util.h +162 -0
- data/ext/nmatrix/math.cpp +1368 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.cpp +285 -0
- data/ext/nmatrix/nmatrix.h +476 -0
- data/ext/nmatrix/ruby_constants.cpp +151 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/ruby_nmatrix.c +3130 -0
- data/ext/nmatrix/storage/common.cpp +77 -0
- data/ext/nmatrix/storage/common.h +183 -0
- data/ext/nmatrix/storage/dense/dense.cpp +1096 -0
- data/ext/nmatrix/storage/dense/dense.h +129 -0
- data/ext/nmatrix/storage/list/list.cpp +1628 -0
- data/ext/nmatrix/storage/list/list.h +138 -0
- data/ext/nmatrix/storage/storage.cpp +730 -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.cpp +2074 -0
- data/ext/nmatrix/storage/yale/yale.h +203 -0
- data/ext/nmatrix/types.h +55 -0
- data/ext/nmatrix/util/io.cpp +279 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.cpp +627 -0
- data/ext/nmatrix/util/sl_list.h +144 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/lib/nmatrix/blas.rb +378 -0
- data/lib/nmatrix/cruby/math.rb +744 -0
- data/lib/nmatrix/enumerate.rb +253 -0
- data/lib/nmatrix/homogeneous.rb +241 -0
- data/lib/nmatrix/io/fortran_format.rb +138 -0
- data/lib/nmatrix/io/harwell_boeing.rb +221 -0
- data/lib/nmatrix/io/market.rb +263 -0
- data/lib/nmatrix/io/point_cloud.rb +189 -0
- data/lib/nmatrix/jruby/decomposition.rb +24 -0
- data/lib/nmatrix/jruby/enumerable.rb +13 -0
- data/lib/nmatrix/jruby/error.rb +4 -0
- data/lib/nmatrix/jruby/math.rb +501 -0
- data/lib/nmatrix/jruby/nmatrix_java.rb +840 -0
- data/lib/nmatrix/jruby/operators.rb +283 -0
- data/lib/nmatrix/jruby/slice.rb +264 -0
- data/lib/nmatrix/lapack_core.rb +181 -0
- data/lib/nmatrix/lapack_plugin.rb +44 -0
- data/lib/nmatrix/math.rb +953 -0
- data/lib/nmatrix/mkmf.rb +100 -0
- data/lib/nmatrix/monkeys.rb +137 -0
- data/lib/nmatrix/nmatrix.rb +1172 -0
- data/lib/nmatrix/rspec.rb +75 -0
- data/lib/nmatrix/shortcuts.rb +1163 -0
- data/lib/nmatrix/version.rb +39 -0
- data/lib/nmatrix/yale_functions.rb +118 -0
- data/lib/nmatrix.rb +28 -0
- data/spec/00_nmatrix_spec.rb +892 -0
- data/spec/01_enum_spec.rb +196 -0
- data/spec/02_slice_spec.rb +407 -0
- data/spec/03_nmatrix_monkeys_spec.rb +80 -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 +215 -0
- data/spec/elementwise_spec.rb +311 -0
- data/spec/homogeneous_spec.rb +100 -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 +159 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +1363 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +35 -0
- data/spec/shortcuts_spec.rb +474 -0
- data/spec/slice_set_spec.rb +162 -0
- data/spec/spec_helper.rb +172 -0
- data/spec/stat_spec.rb +214 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +295 -0
data/spec/blas_spec.rb
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
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
|
+
# == blas_spec.rb
|
|
24
|
+
#
|
|
25
|
+
# Tests for properly exposed BLAS functions.
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
require 'spec_helper'
|
|
29
|
+
|
|
30
|
+
describe NMatrix::BLAS do
|
|
31
|
+
[:byte, :int8, :int16, :int32, :int64,
|
|
32
|
+
:float32, :float64, :complex64, :complex128,
|
|
33
|
+
:object
|
|
34
|
+
].each do |dtype|
|
|
35
|
+
context dtype do
|
|
36
|
+
it "exposes cblas_scal" do
|
|
37
|
+
x = NMatrix.new([3, 1], [1, 2, 3], dtype: dtype)
|
|
38
|
+
NMatrix::BLAS.cblas_scal(3, 2, x, 1)
|
|
39
|
+
expect(x).to eq(NMatrix.new([3, 1], [2, 4, 6], dtype: dtype))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "exposes cblas_imax" do
|
|
43
|
+
u = NMatrix.new([3,1], [1, 4, 3], dtype: dtype)
|
|
44
|
+
index = NMatrix::BLAS.cblas_imax(3, u, 1)
|
|
45
|
+
expect(index).to eq(1)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
[:float32, :float64, :complex64, :complex128].each do |dtype|
|
|
51
|
+
context dtype do
|
|
52
|
+
# This is not the same as "exposes cblas trsm", which would be for a version defined in blas.rb (which
|
|
53
|
+
# would greatly simplify the calling of cblas_trsm in terms of arguments, and which would be accessible
|
|
54
|
+
# as NMatrix::BLAS::trsm)
|
|
55
|
+
it "exposes unfriendly cblas_trsm" do
|
|
56
|
+
a = NMatrix.new(3, [4,-1.0/2, -3.0/4, -2, 2, -1.0/4, -4, -2, -1.0/2], dtype: dtype)
|
|
57
|
+
b = NMatrix.new([3,1], [-1, 17, -9], dtype: dtype)
|
|
58
|
+
NMatrix::BLAS::cblas_trsm(:row, :right, :lower, :transpose, :nonunit, 1, 3, 1.0, a, 3, b, 3)
|
|
59
|
+
|
|
60
|
+
# These test results all come from actually running a matrix through BLAS. We use them to ensure that NMatrix's
|
|
61
|
+
# version of these functions give similar results.
|
|
62
|
+
|
|
63
|
+
expect(b[0]).to eq(-1.0/4)
|
|
64
|
+
expect(b[1]).to eq(33.0/4)
|
|
65
|
+
expect(b[2]).to eq(-13)
|
|
66
|
+
|
|
67
|
+
NMatrix::BLAS::cblas_trsm(:row, :right, :upper, :transpose, :unit, 1, 3, 1.0, a, 3, b, 3)
|
|
68
|
+
|
|
69
|
+
expect(b[0]).to eq(-15.0/2)
|
|
70
|
+
expect(b[1]).to eq(5)
|
|
71
|
+
expect(b[2]).to eq(-13)
|
|
72
|
+
|
|
73
|
+
NMatrix::BLAS::cblas_trsm(:row, :left, :lower, :transpose, :nounit, 3, 1, 1.0, a, 3, b, 1)
|
|
74
|
+
|
|
75
|
+
expect(b[0]).to eq(307.0/8)
|
|
76
|
+
expect(b[1]).to eq(57.0/2)
|
|
77
|
+
expect(b[2]).to eq(26.0)
|
|
78
|
+
|
|
79
|
+
NMatrix::BLAS::cblas_trsm(:row, :left, :upper, :transpose, :unit, 3, 1, 1.0, a, 3, b, 1)
|
|
80
|
+
|
|
81
|
+
expect(b[0]).to eq(307.0/8)
|
|
82
|
+
expect(b[1]).to eq(763.0/16)
|
|
83
|
+
expect(b[2]).to eq(4269.0/64)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# trmm multiplies two matrices, where one of the two is required to be
|
|
87
|
+
# triangular
|
|
88
|
+
it "exposes cblas_trmm" do
|
|
89
|
+
a = NMatrix.new([3,3], [1,1,1, 0,1,2, 0,0,-1], dtype: dtype)
|
|
90
|
+
b = NMatrix.new([3,3], [1,2,3, 4,5,6, 7,8,9], dtype: dtype)
|
|
91
|
+
|
|
92
|
+
begin
|
|
93
|
+
NMatrix::BLAS.cblas_trmm(:row, :left, :upper, false, :not_unit, 3, 3, 1, a, 3, b, 3)
|
|
94
|
+
rescue NotImplementedError => e
|
|
95
|
+
pending e.to_s
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
product = NMatrix.new([3,3], [12,15,18, 18,21,24, -7,-8,-9], dtype: dtype)
|
|
99
|
+
expect(b).to eq(product)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#should have a separate test for complex
|
|
105
|
+
[:float32, :float64, :complex64, :complex128, :object].each do |dtype|
|
|
106
|
+
context dtype do
|
|
107
|
+
|
|
108
|
+
it "exposes cblas rot" do
|
|
109
|
+
x = NMatrix.new([5,1], [1,2,3,4,5], dtype: dtype)
|
|
110
|
+
y = NMatrix.new([5,1], [-5,-4,-3,-2,-1], dtype: dtype)
|
|
111
|
+
x, y = NMatrix::BLAS::rot(x, y, 1.0/2, Math.sqrt(3)/2, -1)
|
|
112
|
+
|
|
113
|
+
expect(x).to be_within(1e-4).of(
|
|
114
|
+
NMatrix.new([5,1], [-0.3660254037844386, -0.7320508075688772, -1.098076211353316, -1.4641016151377544, -1.8301270189221928], dtype: dtype)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
expect(y).to be_within(1e-4).of(
|
|
118
|
+
NMatrix.new([5,1], [-6.830127018922193, -5.464101615137754, -4.098076211353316, -2.732050807568877, -1.3660254037844386], dtype: dtype)
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
[:float32, :float64, :complex64, :complex128, :object].each do |dtype|
|
|
126
|
+
context dtype do
|
|
127
|
+
|
|
128
|
+
it "exposes cblas rotg" do
|
|
129
|
+
pending("broken for :object") if dtype == :object
|
|
130
|
+
|
|
131
|
+
ab = NMatrix.new([2,1], [6,-8], dtype: dtype)
|
|
132
|
+
begin
|
|
133
|
+
c,s = NMatrix::BLAS::rotg(ab)
|
|
134
|
+
rescue NotImplementedError => e
|
|
135
|
+
pending e.to_s
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if [:float32, :float64].include?(dtype)
|
|
139
|
+
expect(ab[0]).to be_within(1e-6).of(-10)
|
|
140
|
+
expect(ab[1]).to be_within(1e-6).of(-5.0/3)
|
|
141
|
+
expect(c).to be_within(1e-6).of(-3.0/5)
|
|
142
|
+
else
|
|
143
|
+
pending "need correct test cases"
|
|
144
|
+
expect(ab[0]).to be_within(1e-6).of(10)
|
|
145
|
+
expect(ab[1]).to be_within(1e-6).of(5.0/3)
|
|
146
|
+
expect(c).to be_within(1e-6).of(3.0/5)
|
|
147
|
+
end
|
|
148
|
+
expect(s).to be_within(1e-6).of(4.0/5)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Note: this exposes gemm, not cblas_gemm (which is the unfriendly CBLAS no-error-checking version)
|
|
152
|
+
it "exposes gemm" do
|
|
153
|
+
n = NMatrix.new([4,3], [14.0,9.0,3.0, 2.0,11.0,15.0, 0.0,12.0,17.0, 5.0,2.0,3.0], dtype: dtype)
|
|
154
|
+
m = NMatrix.new([3,2], [12.0,25.0, 9.0,10.0, 8.0,5.0], dtype: dtype)
|
|
155
|
+
|
|
156
|
+
#c = NMatrix.new([4,2], dtype)
|
|
157
|
+
r = NMatrix::BLAS.gemm(n, m) #, c)
|
|
158
|
+
#c.should equal(r) # check that both are same memory address
|
|
159
|
+
|
|
160
|
+
expect(r).to eq(NMatrix.new([4,2], [273,455,243,235,244,205,102,160], dtype: dtype))
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "exposes gemv" do
|
|
164
|
+
a = NMatrix.new([4,3], [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0], dtype: dtype)
|
|
165
|
+
x = NMatrix.new([3,1], [2.0, 1.0, 0.0], dtype: dtype)
|
|
166
|
+
y = NMatrix::BLAS.gemv(a, x)
|
|
167
|
+
expect(y).to eq(NMatrix.new([4,1],[4.0,13.0,22.0,31.0],dtype: dtype))
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "exposes asum" do
|
|
171
|
+
pending("broken for :object") if dtype == :object
|
|
172
|
+
|
|
173
|
+
x = NMatrix.new([4,1], [-1,2,3,4], dtype: dtype)
|
|
174
|
+
expect(NMatrix::BLAS.asum(x)).to eq(10)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "exposes asum for single element" do
|
|
178
|
+
if [:complex64,:complex128].include?(dtype)
|
|
179
|
+
x = NMatrix.new([1], [Complex(-3,2)], dtype: dtype)
|
|
180
|
+
expect(x.asum).to eq(5.0)
|
|
181
|
+
else
|
|
182
|
+
x = NMatrix.new([1], [-1], dtype: dtype)
|
|
183
|
+
expect(x.asum).to eq(1.0)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "exposes nrm2" do
|
|
188
|
+
pending("broken for :object") if dtype == :object
|
|
189
|
+
|
|
190
|
+
if dtype =~ /complex/
|
|
191
|
+
x = NMatrix.new([3,1], [Complex(1,2),Complex(3,4),Complex(0,6)], dtype: dtype)
|
|
192
|
+
y = NMatrix.new([3,1], [Complex(0,0),Complex(0,0),Complex(0,0)], dtype: dtype)
|
|
193
|
+
nrm2 = 8.12403840463596
|
|
194
|
+
else
|
|
195
|
+
x = NMatrix.new([4,1], [2,-4,3,5], dtype: dtype)
|
|
196
|
+
y = NMatrix.new([3,1], [0,0,0], dtype: dtype)
|
|
197
|
+
nrm2 = 5.385164807134504
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
err = case dtype
|
|
201
|
+
when :float32, :complex64
|
|
202
|
+
1e-6
|
|
203
|
+
when :float64, :complex128
|
|
204
|
+
1e-14
|
|
205
|
+
else
|
|
206
|
+
1e-14
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
expect(NMatrix::BLAS.nrm2(x, 1, 3)).to be_within(err).of(nrm2)
|
|
210
|
+
expect(NMatrix::BLAS.nrm2(y, 1, 3)).to be_within(err).of(0)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -0,0 +1,311 @@
|
|
|
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_spec.rb
|
|
24
|
+
#
|
|
25
|
+
# Element-wise operation tests.
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
require 'spec_helper'
|
|
29
|
+
|
|
30
|
+
describe NMatrix do
|
|
31
|
+
context "yale" do
|
|
32
|
+
before :each do
|
|
33
|
+
@n = NMatrix.new(3, stype: :yale, dtype: :int64)
|
|
34
|
+
@n.extend NMatrix::YaleFunctions unless jruby?
|
|
35
|
+
@m = NMatrix.new(3, stype: :yale, dtype: :int64)
|
|
36
|
+
@n[0,0] = 52
|
|
37
|
+
@n[0,2] = 5
|
|
38
|
+
@n[1,1] = 40
|
|
39
|
+
@n[0,1] = 30
|
|
40
|
+
@n[2,0] = 6
|
|
41
|
+
@m[1,1] = -48
|
|
42
|
+
@m[0,2] = -5
|
|
43
|
+
@n.extend NMatrix::YaleFunctions unless jruby?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should perform scalar math" do
|
|
47
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
48
|
+
x = @n * 3
|
|
49
|
+
expect(x[0,0]).to eq(52 * 3)
|
|
50
|
+
expect(x[0,1]).to eq(30 * 3)
|
|
51
|
+
expect(x[0,2]).to eq(5 * 3)
|
|
52
|
+
expect(x[1,1]).to eq(40 * 3)
|
|
53
|
+
expect(x[2,0]).to eq(6 * 3)
|
|
54
|
+
|
|
55
|
+
r = NMatrix.new(3, stype: :yale, dtype: :int64)
|
|
56
|
+
y = r + 3
|
|
57
|
+
expect(y[0,0]).to eq(3)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should refuse to perform a dot operation on a yale with non-zero default" do
|
|
61
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
62
|
+
r = NMatrix.new(3, stype: :yale, dtype: :int64)
|
|
63
|
+
y = r + 3
|
|
64
|
+
expect { y.dot(r) }.to raise_error
|
|
65
|
+
expect { r.dot(y) }.to raise_error
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should perform element-wise addition" do
|
|
69
|
+
expect(@n+@m).to eq(NMatrix.new(:dense, 3, [52,30,0,0,-8,0,6,0,0], :int64).cast(:yale, :int64))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should perform element-wise subtraction" do
|
|
73
|
+
expect(@n-@m).to eq(NMatrix.new(:dense, 3, [52,30,10,0,88,0,6,0,0], :int64).cast(:yale, :int64))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should perform element-wise multiplication" do
|
|
77
|
+
r = NMatrix.new(:dense, 3, [0,0,-25,0,-1920,0,0,0,0], :int64).cast(:yale, :int64)
|
|
78
|
+
m = NMatrix.new(2, stype: :yale, dtype: :int64)
|
|
79
|
+
expect(@n*@m).to eq(r)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should perform element-wise division" do
|
|
83
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
84
|
+
r = NMatrix.new(:dense, 3, [52, 30, -2, 0, -1, 0, 6, 0, 0], :int64).cast(:yale, :int64)
|
|
85
|
+
expect(@n/(@m+1)).to eq(r)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should perform element-wise modulo" do
|
|
89
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
90
|
+
m = NMatrix.new(3, stype: :yale, dtype: :int64, default: 0) + 5
|
|
91
|
+
expect(@n % m).to eq(NMatrix.new(:dense, 3, [2,0,0,0,0,0,1,0,0], :int64).cast(:yale, :int64))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should handle element-wise equality (=~)" do
|
|
95
|
+
expect(@n =~ @m).to eq(NMatrix.new(:dense, 3, [false,false,false,true,false,true,false,true,true], :object).cast(:yale, :object, false))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should handle element-wise inequality (!~)" do
|
|
99
|
+
expect(@n !~ @m).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, true))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should handle element-wise less-than (<)" do
|
|
103
|
+
expect(@m < @n).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, true))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should handle element-wise greater-than (>)" do
|
|
107
|
+
expect(@n > @m).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, false))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should handle element-wise greater-than-or-equals (>=)" do
|
|
111
|
+
expect(@n >= @m).to eq(NMatrix.new(:dense, 3, true, :object).cast(:yale,:object, true))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should handle element-wise less-than-or-equals (<=)" do
|
|
115
|
+
r = NMatrix.new(:dense, 3, [false,false,false,true,false,true,false,true,true], :object).cast(:yale, :object, false)
|
|
116
|
+
expect(@n <= @m).to eq(r)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
context "list" do
|
|
122
|
+
before :each do
|
|
123
|
+
@n = NMatrix.new(:list, 2, 0, :int64)
|
|
124
|
+
@m = NMatrix.new(:list, 2, 0, :int64)
|
|
125
|
+
@n[0,0] = 52
|
|
126
|
+
@m[1,1] = -48
|
|
127
|
+
@n[1,1] = 40
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "should perform scalar math" do
|
|
131
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
132
|
+
x = @n * 3
|
|
133
|
+
expect(x[0,0]).to eq(52 * 3)
|
|
134
|
+
expect(x[1,1]).to eq(40 * 3)
|
|
135
|
+
expect(x[0,1]).to eq(0)
|
|
136
|
+
|
|
137
|
+
r = NMatrix.new(3, stype: :list, default: 1)
|
|
138
|
+
y = r + 3
|
|
139
|
+
expect(y[0,0]).to eq(4)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should perform element-wise addition" do
|
|
143
|
+
r = NMatrix.new(2, stype: :list, dtype: :int64, default: 0)
|
|
144
|
+
r[0,0] = 52
|
|
145
|
+
r[1,1] = -8
|
|
146
|
+
q = @n + @m
|
|
147
|
+
expect(q).to eq(r)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should perform element-wise subtraction" do
|
|
151
|
+
r = NMatrix.new(:dense, 2, [52, 0, 0, 88], :int64).cast(:list, :int64)
|
|
152
|
+
expect(@n-@m).to eq(r)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should perform element-wise multiplication" do
|
|
156
|
+
r = NMatrix.new(:dense, 2, [52, 0, 0, -1920], :int64).cast(:list, :int64)
|
|
157
|
+
m = NMatrix.new(:list, 2, 1, :int64)
|
|
158
|
+
m[1,1] = -48
|
|
159
|
+
expect(@n*m).to eq(r)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should perform element-wise division" do
|
|
163
|
+
m = NMatrix.new(:list, 2, 1, :int64)
|
|
164
|
+
m[1,1] = 2
|
|
165
|
+
r = NMatrix.new(:dense, 2, [52, 0, 0, 20], :int64).cast(:list, :int64)
|
|
166
|
+
expect(@n/m).to eq(r)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "should perform element-wise modulo" do
|
|
170
|
+
pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby?
|
|
171
|
+
m = NMatrix.new(:list, 2, 1, :int64)
|
|
172
|
+
m[0,0] = 50
|
|
173
|
+
m[1,1] = 40
|
|
174
|
+
(@n % m)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "should handle element-wise equality (=~)" do
|
|
178
|
+
r = NMatrix.new(:list, 2, false, :object)
|
|
179
|
+
r[0,1] = true
|
|
180
|
+
r[1,0] = true
|
|
181
|
+
|
|
182
|
+
expect(@n =~ @m).to eq(r)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it "should handle element-wise inequality (!~)" do
|
|
186
|
+
r = NMatrix.new(:list, 2, false, :object)
|
|
187
|
+
r[0,0] = true
|
|
188
|
+
r[1,1] = true
|
|
189
|
+
|
|
190
|
+
expect(@n !~ @m).to eq(r)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "should handle element-wise less-than (<)" do
|
|
194
|
+
expect(@n < @m).to eq(NMatrix.new(:list, 2, false, :object))
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should handle element-wise greater-than (>)" do
|
|
198
|
+
r = NMatrix.new(:list, 2, false, :object)
|
|
199
|
+
r[0,0] = true
|
|
200
|
+
r[1,1] = true
|
|
201
|
+
expect(@n > @m).to eq(r)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should handle element-wise greater-than-or-equals (>=)" do
|
|
205
|
+
expect(@n >= @m).to eq(NMatrix.new(:list, 2, true, :object))
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "should handle element-wise less-than-or-equals (<=)" do
|
|
209
|
+
r = NMatrix.new(:list, 2, false, :object)
|
|
210
|
+
r[0,1] = true
|
|
211
|
+
r[1,0] = true
|
|
212
|
+
expect(@n <= @m).to eq(r)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
context "dense" do
|
|
217
|
+
context "scalar arithmetic" do
|
|
218
|
+
before :each do
|
|
219
|
+
@n = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "works for integers" do
|
|
223
|
+
expect(@n+1).to eq(NMatrix.new(:dense, 2, [2,3,4,5], :int64))
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
#it "works for complex64" do
|
|
227
|
+
# n = @n.cast(:dtype => :complex64)
|
|
228
|
+
# (n + 10.0).to_a.should == [Complex(11.0), Complex(12.0), Complex(13.0), Complex(14.0)]
|
|
229
|
+
#end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "elementwise arithmetic" do
|
|
233
|
+
before :each do
|
|
234
|
+
@n = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
|
235
|
+
@m = NMatrix.new(:dense, 2, [-4,-1,0,66], :int64)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "adds" do
|
|
239
|
+
r = @n+@m
|
|
240
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [-3, 1, 3, 70], :int64))
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "subtracts" do
|
|
244
|
+
r = @n-@m
|
|
245
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [5, 3, 3, -62], :int64))
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "multiplies" do
|
|
249
|
+
r = @n*@m
|
|
250
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [-4, -2, 0, 264], :int64))
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "divides in the Ruby way" do
|
|
254
|
+
pending("not yet implemented int dtype for NMatrix-JRuby") if jruby?
|
|
255
|
+
m = @m.clone
|
|
256
|
+
m[1,0] = 3
|
|
257
|
+
r = @n/m
|
|
258
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [-1, -2, 1, 0], :int64))
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "exponentiates" do
|
|
262
|
+
r = @n ** 2
|
|
263
|
+
# TODO: We might have problems with the dtype.
|
|
264
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [1, 4, 9, 16], :int64))
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "modulo" do
|
|
268
|
+
pending("not yet implemented int dtype for NMatrix-JRuby") if jruby?
|
|
269
|
+
expect(@n % (@m + 2)).to eq(NMatrix.new(:dense, [2,2], [-1, 0, 1, 4], :int64))
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
context "elementwise comparisons" do
|
|
274
|
+
before :each do
|
|
275
|
+
@n = NMatrix.new(:dense, 2, [1,2,3,4], :int64)
|
|
276
|
+
@m = NMatrix.new(:dense, 2, [-4,-1,3,2], :int64)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "equals" do
|
|
280
|
+
r = @n =~ @m
|
|
281
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [false, false, true, false], :object))
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it "is not equal" do
|
|
285
|
+
r = @n !~ @m
|
|
286
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object))
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "is less than" do
|
|
290
|
+
r = @n < @m
|
|
291
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], false, :object))
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it "is greater than" do
|
|
295
|
+
r = @n > @m
|
|
296
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object))
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it "is less than or equal to" do
|
|
300
|
+
r = @n <= @m
|
|
301
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [false, false, true, false], :object))
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it "is greater than or equal to" do
|
|
305
|
+
n = NMatrix.new(:dense, [2,2], [1, 2, 2, 4], :int64)
|
|
306
|
+
r = n >= @m
|
|
307
|
+
expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object))
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
# == homogeneous_spec.rb
|
|
24
|
+
#
|
|
25
|
+
# Specs for the homogeneous transformation matrix methods.
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
require 'spec_helper'
|
|
29
|
+
require "./lib/nmatrix/homogeneous.rb"
|
|
30
|
+
|
|
31
|
+
require 'pry'
|
|
32
|
+
|
|
33
|
+
describe 'NMatrix' do
|
|
34
|
+
context ".x_rotation" do
|
|
35
|
+
it "should generate a matrix representing a rotation about the x axis" do
|
|
36
|
+
x = NMatrix.x_rotation(Math::PI/6)
|
|
37
|
+
expect(x).to be_within(1e-8).of(NMatrix.new([4,4], [1.0, 0.0, 0.0, 0.0,
|
|
38
|
+
0.0, Math.cos(Math::PI/6), -0.5, 0.0,
|
|
39
|
+
0.0, 0.5, Math.cos(Math::PI/6), 0.0,
|
|
40
|
+
0.0, 0.0, 0.0, 1.0] ))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
context ".y_rotation" do
|
|
46
|
+
it "should generate a matrix representing a rotation about the y axis" do
|
|
47
|
+
y = NMatrix.y_rotation(Math::PI/6)
|
|
48
|
+
expect(y).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), 0.0, 0.5, 0.0,
|
|
49
|
+
0.0, 1.0, 0.0, 0.0,
|
|
50
|
+
-0.5, 0.0, Math.cos(Math::PI/6), 0.0,
|
|
51
|
+
0.0, 0.0, 0.0, 1.0] ))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context ".z_rotation" do
|
|
56
|
+
it "should generate a matrix representing a rotation about the z axis" do
|
|
57
|
+
z = NMatrix.z_rotation(Math::PI/6)
|
|
58
|
+
expect(z).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), -0.5, 0.0, 0.0,
|
|
59
|
+
0.5, Math.cos(Math::PI/6), 0.0, 0.0,
|
|
60
|
+
0.0, 0.0, 1.0, 0.0,
|
|
61
|
+
0.0, 0.0, 0.0, 1.0] ))
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context ".translation" do
|
|
66
|
+
it "should generate a translation matrix from an Array" do
|
|
67
|
+
t = NMatrix.translation([4,5,6])
|
|
68
|
+
expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
|
|
69
|
+
0, 1, 0, 5,
|
|
70
|
+
0, 0, 1, 6,
|
|
71
|
+
0, 0, 0, 1] ))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should generate a translation matrix from x, y, and z values" do
|
|
75
|
+
t = NMatrix.translation(4,5,6)
|
|
76
|
+
expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
|
|
77
|
+
0, 1, 0, 5,
|
|
78
|
+
0, 0, 1, 6,
|
|
79
|
+
0, 0, 0, 1] ))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should generate a translation matrix from an NMatrix with correctly inferred dtype" do
|
|
83
|
+
pending("not yet implemented for NMatrix-JRuby") if jruby?
|
|
84
|
+
t = NMatrix.translation(NMatrix.new([3,1], [4,5,6], dtype: :float64) )
|
|
85
|
+
expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4,
|
|
86
|
+
0, 1, 0, 5,
|
|
87
|
+
0, 0, 1, 6,
|
|
88
|
+
0, 0, 0, 1] ))
|
|
89
|
+
expect(t.dtype).to be(:float64)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "#quaternion" do
|
|
94
|
+
it "should generate a singularity-free quaternion" do
|
|
95
|
+
transform = NMatrix.new([4,4], [-0.9995825,-0.02527934,-0.0139845,50.61761,-0.02732551,0.9844284,0.1736463,-22.95566,0.009376526,0.1739562,-0.9847089,7.1521,0,0,0,1])
|
|
96
|
+
q = transform.quaternion
|
|
97
|
+
expect(Math.sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)).to be_within(1e-6).of(1.0)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|