pnmatrix 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/ext/nmatrix/binary_format.txt +53 -0
  3. data/ext/nmatrix/data/complex.h +388 -0
  4. data/ext/nmatrix/data/data.cpp +274 -0
  5. data/ext/nmatrix/data/data.h +651 -0
  6. data/ext/nmatrix/data/meta.h +64 -0
  7. data/ext/nmatrix/data/ruby_object.h +386 -0
  8. data/ext/nmatrix/extconf.rb +70 -0
  9. data/ext/nmatrix/math/asum.h +99 -0
  10. data/ext/nmatrix/math/cblas_enums.h +36 -0
  11. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  12. data/ext/nmatrix/math/gemm.h +241 -0
  13. data/ext/nmatrix/math/gemv.h +178 -0
  14. data/ext/nmatrix/math/getrf.h +255 -0
  15. data/ext/nmatrix/math/getrs.h +121 -0
  16. data/ext/nmatrix/math/imax.h +82 -0
  17. data/ext/nmatrix/math/laswp.h +165 -0
  18. data/ext/nmatrix/math/long_dtype.h +62 -0
  19. data/ext/nmatrix/math/magnitude.h +54 -0
  20. data/ext/nmatrix/math/math.h +751 -0
  21. data/ext/nmatrix/math/nrm2.h +165 -0
  22. data/ext/nmatrix/math/rot.h +117 -0
  23. data/ext/nmatrix/math/rotg.h +106 -0
  24. data/ext/nmatrix/math/scal.h +71 -0
  25. data/ext/nmatrix/math/trsm.h +336 -0
  26. data/ext/nmatrix/math/util.h +162 -0
  27. data/ext/nmatrix/math.cpp +1368 -0
  28. data/ext/nmatrix/nm_memory.h +60 -0
  29. data/ext/nmatrix/nmatrix.cpp +285 -0
  30. data/ext/nmatrix/nmatrix.h +476 -0
  31. data/ext/nmatrix/ruby_constants.cpp +151 -0
  32. data/ext/nmatrix/ruby_constants.h +106 -0
  33. data/ext/nmatrix/ruby_nmatrix.c +3130 -0
  34. data/ext/nmatrix/storage/common.cpp +77 -0
  35. data/ext/nmatrix/storage/common.h +183 -0
  36. data/ext/nmatrix/storage/dense/dense.cpp +1096 -0
  37. data/ext/nmatrix/storage/dense/dense.h +129 -0
  38. data/ext/nmatrix/storage/list/list.cpp +1628 -0
  39. data/ext/nmatrix/storage/list/list.h +138 -0
  40. data/ext/nmatrix/storage/storage.cpp +730 -0
  41. data/ext/nmatrix/storage/storage.h +99 -0
  42. data/ext/nmatrix/storage/yale/class.h +1139 -0
  43. data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
  44. data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
  45. data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
  46. data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
  47. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
  48. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
  49. data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
  50. data/ext/nmatrix/storage/yale/yale.cpp +2074 -0
  51. data/ext/nmatrix/storage/yale/yale.h +203 -0
  52. data/ext/nmatrix/types.h +55 -0
  53. data/ext/nmatrix/util/io.cpp +279 -0
  54. data/ext/nmatrix/util/io.h +115 -0
  55. data/ext/nmatrix/util/sl_list.cpp +627 -0
  56. data/ext/nmatrix/util/sl_list.h +144 -0
  57. data/ext/nmatrix/util/util.h +78 -0
  58. data/lib/nmatrix/blas.rb +378 -0
  59. data/lib/nmatrix/cruby/math.rb +744 -0
  60. data/lib/nmatrix/enumerate.rb +253 -0
  61. data/lib/nmatrix/homogeneous.rb +241 -0
  62. data/lib/nmatrix/io/fortran_format.rb +138 -0
  63. data/lib/nmatrix/io/harwell_boeing.rb +221 -0
  64. data/lib/nmatrix/io/market.rb +263 -0
  65. data/lib/nmatrix/io/point_cloud.rb +189 -0
  66. data/lib/nmatrix/jruby/decomposition.rb +24 -0
  67. data/lib/nmatrix/jruby/enumerable.rb +13 -0
  68. data/lib/nmatrix/jruby/error.rb +4 -0
  69. data/lib/nmatrix/jruby/math.rb +501 -0
  70. data/lib/nmatrix/jruby/nmatrix_java.rb +840 -0
  71. data/lib/nmatrix/jruby/operators.rb +283 -0
  72. data/lib/nmatrix/jruby/slice.rb +264 -0
  73. data/lib/nmatrix/lapack_core.rb +181 -0
  74. data/lib/nmatrix/lapack_plugin.rb +44 -0
  75. data/lib/nmatrix/math.rb +953 -0
  76. data/lib/nmatrix/mkmf.rb +100 -0
  77. data/lib/nmatrix/monkeys.rb +137 -0
  78. data/lib/nmatrix/nmatrix.rb +1172 -0
  79. data/lib/nmatrix/rspec.rb +75 -0
  80. data/lib/nmatrix/shortcuts.rb +1163 -0
  81. data/lib/nmatrix/version.rb +39 -0
  82. data/lib/nmatrix/yale_functions.rb +118 -0
  83. data/lib/nmatrix.rb +28 -0
  84. data/spec/00_nmatrix_spec.rb +892 -0
  85. data/spec/01_enum_spec.rb +196 -0
  86. data/spec/02_slice_spec.rb +407 -0
  87. data/spec/03_nmatrix_monkeys_spec.rb +80 -0
  88. data/spec/2x2_dense_double.mat +0 -0
  89. data/spec/4x4_sparse.mat +0 -0
  90. data/spec/4x5_dense.mat +0 -0
  91. data/spec/blas_spec.rb +215 -0
  92. data/spec/elementwise_spec.rb +311 -0
  93. data/spec/homogeneous_spec.rb +100 -0
  94. data/spec/io/fortran_format_spec.rb +88 -0
  95. data/spec/io/harwell_boeing_spec.rb +98 -0
  96. data/spec/io/test.rua +9 -0
  97. data/spec/io_spec.rb +159 -0
  98. data/spec/lapack_core_spec.rb +482 -0
  99. data/spec/leakcheck.rb +16 -0
  100. data/spec/math_spec.rb +1363 -0
  101. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  102. data/spec/nmatrix_yale_spec.rb +286 -0
  103. data/spec/rspec_monkeys.rb +56 -0
  104. data/spec/rspec_spec.rb +35 -0
  105. data/spec/shortcuts_spec.rb +474 -0
  106. data/spec/slice_set_spec.rb +162 -0
  107. data/spec/spec_helper.rb +172 -0
  108. data/spec/stat_spec.rb +214 -0
  109. data/spec/test.pcd +20 -0
  110. data/spec/utm5940.mtx +83844 -0
  111. 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