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.
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