nmatrix 0.0.3 → 0.0.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 (63) hide show
  1. data/.gitignore +3 -0
  2. data/CONTRIBUTING.md +66 -0
  3. data/Gemfile +1 -1
  4. data/History.txt +68 -10
  5. data/LICENSE.txt +2 -2
  6. data/Manifest.txt +2 -0
  7. data/README.rdoc +90 -69
  8. data/Rakefile +18 -9
  9. data/ext/nmatrix/data/complex.h +7 -7
  10. data/ext/nmatrix/data/data.cpp +2 -7
  11. data/ext/nmatrix/data/data.h +7 -4
  12. data/ext/nmatrix/data/rational.h +2 -2
  13. data/ext/nmatrix/data/ruby_object.h +3 -10
  14. data/ext/nmatrix/extconf.rb +79 -54
  15. data/ext/nmatrix/new_extconf.rb +11 -12
  16. data/ext/nmatrix/nmatrix.cpp +94 -125
  17. data/ext/nmatrix/nmatrix.h +38 -17
  18. data/ext/nmatrix/ruby_constants.cpp +2 -15
  19. data/ext/nmatrix/ruby_constants.h +2 -14
  20. data/ext/nmatrix/storage/common.cpp +2 -2
  21. data/ext/nmatrix/storage/common.h +2 -2
  22. data/ext/nmatrix/storage/dense.cpp +206 -31
  23. data/ext/nmatrix/storage/dense.h +5 -2
  24. data/ext/nmatrix/storage/list.cpp +52 -4
  25. data/ext/nmatrix/storage/list.h +3 -2
  26. data/ext/nmatrix/storage/storage.cpp +6 -6
  27. data/ext/nmatrix/storage/storage.h +2 -2
  28. data/ext/nmatrix/storage/yale.cpp +202 -49
  29. data/ext/nmatrix/storage/yale.h +5 -4
  30. data/ext/nmatrix/ttable_helper.rb +108 -108
  31. data/ext/nmatrix/types.h +2 -15
  32. data/ext/nmatrix/util/io.cpp +2 -2
  33. data/ext/nmatrix/util/io.h +2 -2
  34. data/ext/nmatrix/util/lapack.h +2 -2
  35. data/ext/nmatrix/util/math.cpp +14 -14
  36. data/ext/nmatrix/util/math.h +2 -2
  37. data/ext/nmatrix/util/sl_list.cpp +2 -2
  38. data/ext/nmatrix/util/sl_list.h +2 -2
  39. data/ext/nmatrix/util/util.h +2 -2
  40. data/lib/nmatrix.rb +13 -35
  41. data/lib/nmatrix/blas.rb +182 -56
  42. data/lib/nmatrix/io/market.rb +38 -14
  43. data/lib/nmatrix/io/mat5_reader.rb +393 -278
  44. data/lib/nmatrix/io/mat_reader.rb +121 -107
  45. data/lib/nmatrix/lapack.rb +59 -14
  46. data/lib/nmatrix/monkeys.rb +32 -30
  47. data/lib/nmatrix/nmatrix.rb +204 -100
  48. data/lib/nmatrix/nvector.rb +166 -57
  49. data/lib/nmatrix/shortcuts.rb +364 -231
  50. data/lib/nmatrix/version.rb +8 -4
  51. data/nmatrix.gemspec +5 -3
  52. data/scripts/mac-brew-gcc.sh +1 -1
  53. data/spec/blas_spec.rb +80 -2
  54. data/spec/math_spec.rb +78 -32
  55. data/spec/nmatrix_list_spec.rb +55 -55
  56. data/spec/nmatrix_spec.rb +60 -117
  57. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  58. data/spec/nmatrix_yale_spec.rb +214 -198
  59. data/spec/nvector_spec.rb +58 -2
  60. data/spec/shortcuts_spec.rb +156 -32
  61. data/spec/slice_spec.rb +229 -178
  62. data/spec/spec_helper.rb +2 -2
  63. metadata +71 -21
@@ -29,39 +29,49 @@
29
29
  require File.join(File.dirname(__FILE__), "spec_helper.rb")
30
30
 
31
31
  describe NMatrix do
32
-
32
+
33
33
  it "zeros() creates a matrix of zeros" do
34
34
  m = NMatrix.zeros(3)
35
35
  n = NMatrix.new([3, 3], 0)
36
-
36
+
37
37
  m.should.eql? n
38
38
  end
39
-
39
+
40
40
  it "ones() creates a matrix of ones" do
41
41
  m = NMatrix.ones(3)
42
42
  n = NMatrix.new([3, 3], 1)
43
-
44
- m.should.eql? n
43
+
44
+ m.should.eql? n
45
45
  end
46
-
46
+
47
47
  it "eye() creates an identity matrix" do
48
48
  m = NMatrix.eye(3)
49
49
  identity3 = NMatrix.new([3, 3], [1, 0, 0, 0, 1, 0, 0, 0, 1])
50
-
50
+
51
51
  m.should.eql? identity3
52
52
  end
53
-
53
+
54
54
  it "random() creates a matrix of random numbers" do
55
55
  m = NMatrix.random(2)
56
-
56
+
57
+ m.stype.should == :dense
58
+ m.dtype.should == :float64
59
+ end
60
+
61
+ it "random() only accepts an integer or an array as dimension" do
62
+ m = NMatrix.random([2, 2])
63
+
57
64
  m.stype.should == :dense
58
65
  m.dtype.should == :float64
66
+
67
+ expect { NMatrix.random(2.0) }.to raise_error
68
+ expect { NMatrix.random("not an array or integer") }.to raise_error
59
69
  end
60
-
70
+
61
71
  it "seq() creates a matrix of integers, sequentially" do
62
72
  m = NMatrix.seq(2) # 2x2 matrix.
63
73
  value = 0
64
-
74
+
65
75
  2.times do |i|
66
76
  2.times do |j|
67
77
  m[i, j].should == value
@@ -69,86 +79,200 @@ describe NMatrix do
69
79
  end
70
80
  end
71
81
  end
72
-
82
+
73
83
  it "seq() only accepts an integer or a 2-element array as dimension" do
84
+ m = NMatrix.seq([2, 2])
85
+ value = 0
86
+
87
+ 2.times do |i|
88
+ 2.times do |j|
89
+ m[i, j].should == value
90
+ value += 1
91
+ end
92
+ end
93
+
74
94
  expect { NMatrix.seq([1, 2, 3]) }.to raise_error
75
95
  expect { NMatrix.seq("not an array or integer") }.to raise_error
76
96
  end
77
-
97
+
98
+ it "indgen() creates a matrix of integers as well as seq()" do
99
+ m = NMatrix.indgen(2) # 2x2 matrix.
100
+ value = 0
101
+
102
+ 2.times do |i|
103
+ 2.times do |j|
104
+ m[i, j].should == value
105
+ value += 1
106
+ end
107
+ end
108
+ end
109
+
110
+ it "findgen creates a matrix of floats, sequentially" do
111
+ m = NMatrix.findgen(2) # 2x2 matrix.
112
+ value = 0
113
+
114
+ 2.times do |i|
115
+ 2.times do |j|
116
+ (m[i, j]/10).should be_within(Float::EPSILON).of(value.to_f/10)
117
+ value += 1
118
+ end
119
+ end
120
+ end
121
+
122
+ it "bindgen() creates a matrix of bytes" do
123
+ m = NMatrix.bindgen(2) # 2x2 matrix.
124
+ value = 0
125
+
126
+ 2.times do |i|
127
+ 2.times do |j|
128
+ m[i, j].should == value
129
+ value += 1
130
+ end
131
+ end
132
+ end
133
+
134
+ it "cindgen() creates a matrix of complexes" do
135
+ m = NMatrix.cindgen(2) # 2x2 matrix.
136
+ value = 0
137
+
138
+ 2.times do |i|
139
+ 2.times do |j|
140
+ m[i, j].real.should be_within(Float::EPSILON).of(value)
141
+ m[i, j].imag.should be_within(Float::EPSILON).of(0.0)
142
+ value += 1
143
+ end
144
+ end
145
+ end
146
+
78
147
  it "column() returns a NMatrix" do
79
148
  m = NMatrix.random(3)
80
-
149
+
81
150
  m.column(2).is_a?(NMatrix).should be_true
82
151
  end
83
-
152
+
84
153
  it "column() accepts a second parameter (only :copy or :reference)" do
85
154
  m = NMatrix.random(3)
86
-
155
+
87
156
  expect { m.column(1, :copy) }.to_not raise_error
88
157
  expect { m.column(1, :reference) }.to_not raise_error
89
-
158
+
90
159
  expect { m.column(1, :derp) }.to raise_error
91
160
  end
161
+
162
+ it "row() returns a NMatrix" do
163
+ m = NMatrix.random(3)
164
+
165
+ m.row(2).is_a?(NMatrix).should be_true
166
+ end
167
+
168
+ it "row() accepts a second parameter (only :copy or :reference)" do
169
+ m = NMatrix.random(3)
170
+
171
+ expect { m.row(1, :copy) }.to_not raise_error
172
+ expect { m.row(1, :reference) }.to_not raise_error
173
+
174
+ expect { m.row(1, :derp) }.to raise_error
175
+ end
92
176
  end
93
177
 
94
178
  describe "NVector" do
95
-
179
+
96
180
  it "zeros() creates a vector of zeros" do
97
181
  v = NVector.zeros(4)
98
-
182
+
99
183
  4.times do |i|
100
184
  v[i].should == 0
101
185
  end
102
186
  end
103
-
187
+
104
188
  it "ones() creates a vector of ones" do
105
189
  v = NVector.ones(3)
106
-
190
+
107
191
  3.times do |i|
108
192
  v[i].should == 1
109
193
  end
110
194
  end
111
-
195
+
112
196
  it "random() creates a vector of random numbers" do
113
- v = NVector.zeros(4)
197
+ v = NVector.random(4)
114
198
  v.dtype.should == :float64
115
199
  v.stype.should == :dense
116
200
  end
117
-
201
+
118
202
  it "seq() creates a vector of integers, sequentially" do
119
203
  v = NVector.seq(7)
120
204
  i = 0
121
-
205
+
122
206
  v.each do |elem|
123
207
  elem.should == i
124
208
  i += 1
125
209
  end
126
210
  end
127
-
211
+
128
212
  it "seq() only accepts integers as dimension" do
129
213
  expect { NVector.seq(3) }.to_not raise_error
130
214
 
131
215
  expect { NVector.seq([1, 3]) }.to raise_error
132
216
  expect { NVector.seq(:wtf) }.to raise_error
133
217
  end
134
-
218
+
219
+ it "indgen() creates a vector of integers as well as seq()" do
220
+ v = NVector.indgen(7)
221
+ i = 0
222
+
223
+ v.each do |elem|
224
+ elem.should == i
225
+ i += 1
226
+ end
227
+ end
228
+
229
+ it "findgen creates a vector of floats, sequentially" do
230
+ v = NVector.findgen(2)
231
+
232
+ 2.times do |i|
233
+ (v[i]/10).should be_within(Float::EPSILON).of(i.to_f/10)
234
+ end
235
+ end
236
+
237
+ it "bindgen() creates a vector of bytes, sequentially" do
238
+ v = NVector.bindgen(7)
239
+ i = 0
240
+
241
+ v.each do |elem|
242
+ elem.should == i
243
+ i += 1
244
+ end
245
+ end
246
+
247
+ it "cindgen() creates a vector of complexes, sequentially" do
248
+ v = NVector.cindgen(2)
249
+ value = 0
250
+
251
+ 2.times do |i|
252
+ v[i].real.should be_within(Float::EPSILON).of(value)
253
+ v[i].imag.should be_within(Float::EPSILON).of(0.0)
254
+ value += 1
255
+ end
256
+ end
257
+
258
+
135
259
  it "linspace() creates a vector with n values equally spaced between a and b" do
136
260
  v = NVector.linspace(0, 2, 5)
137
261
  i = 0
138
-
262
+
139
263
  v.each do |elem|
140
264
  elem.should == i * 0.5
141
265
  i += 1
142
266
  end
143
- end
267
+ end
144
268
  end
145
269
 
146
270
  describe "Inline constructor" do
147
-
271
+
148
272
  it "creates a NMatrix with the given values" do
149
273
  m = NMatrix.new([2, 2], [1, 4, 6, 7])
150
274
  n = N[[1, 4], [6, 7]]
151
-
152
- m.should.eql? n
275
+
276
+ m.should.eql? n
153
277
  end
154
278
  end
@@ -20,226 +20,277 @@
20
20
  #
21
21
  # * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
22
22
  #
23
- # == slec_spec.rb
23
+ # == slice_spec.rb
24
24
  #
25
- # Test of slice operations.
25
+ # Test of slice operations.
26
26
  #
27
27
  require File.dirname(__FILE__) + "/spec_helper.rb"
28
28
 
29
29
  describe "Slice operation" do
30
30
  [:dense, :list, :yale].each do |stype|
31
- context "for #{stype}" do
32
- before :each do
33
- @m = create_matrix(stype)
34
- end
31
+ context "for #{stype}" do
32
+ before :each do
33
+ @m = create_matrix(stype)
34
+ end
35
35
 
36
- unless stype == :yale
37
- it "should have #is_ref? method" do
38
- a = @m[0..1, 0..1]
39
- b = @m.slice(0..1, 0..1)
36
+ unless stype == :yale
37
+ it "should have #is_ref? method" do
38
+ a = @m[0..1, 0..1]
39
+ b = @m.slice(0..1, 0..1)
40
40
 
41
41
 
42
- @m.is_ref?.should be_false
43
- a.is_ref?.should be_true
44
- b.is_ref?.should be_false
45
- end
42
+ @m.is_ref?.should be_false
43
+ a.is_ref?.should be_true
44
+ b.is_ref?.should be_false
45
+ end
46
46
 
47
- it "reference should compare with non-reference" do
48
- @m.slice(1..2,0..1).should == @m[1..2, 0..1]
49
- @m[1..2,0..1].should == @m.slice(1..2, 0..1)
50
- @m[1..2,0..1].should == @m[1..2, 0..1]
51
- end
52
- end # unless stype == :yale
47
+ it "reference should compare with non-reference" do
48
+ @m.slice(1..2,0..1).should == @m[1..2, 0..1]
49
+ @m[1..2,0..1].should == @m.slice(1..2, 0..1)
50
+ @m[1..2,0..1].should == @m[1..2, 0..1]
51
+ end
52
+ end # unless stype == :yale
53
53
 
54
- context "with copying" do
55
- it 'should return an NMatrix' do
56
- n = @m.slice(0..1,0..1)
57
- nm_eql(n, NMatrix.new([2,2], [0,1,3,4], :int32)).should be_true
58
- end
54
+ context "with copying" do
55
+ it 'should return an NMatrix' do
56
+ n = @m.slice(0..1,0..1)
57
+ nm_eql(n, NMatrix.new([2,2], [0,1,3,4], :int32)).should be_true
58
+ end
59
59
 
60
- it 'should return a copy of 2x2 matrix to self elements' do
61
- n = @m.slice(1..2,0..1)
62
- n.shape.should eql([2,2])
60
+ it 'should return a copy of 2x2 matrix to self elements' do
61
+ n = @m.slice(1..2,0..1)
62
+ n.shape.should eql([2,2])
63
63
 
64
- n[1,1].should == @m[2,1]
65
- n[1,1] = -9
66
- @m[2,1].should eql(7)
67
- end
64
+ n[1,1].should == @m[2,1]
65
+ n[1,1] = -9
66
+ @m[2,1].should eql(7)
67
+ end
68
68
 
69
- it 'should return a 1x2 matrix with refs to self elements' do
70
- n = @m.slice(0,1..2)
71
- n.shape.should eql([1,2])
69
+ it 'should return a 1x2 matrix with refs to self elements' do
70
+ n = @m.slice(0,1..2)
71
+ n.shape.should eql([1,2])
72
72
 
73
- n[0,0].should == @m[0,1]
74
- n[0,0] = -9
75
- @m[0,1].should eql(1)
76
- end
73
+ n[0,0].should == @m[0,1]
74
+ n[0,0] = -9
75
+ @m[0,1].should eql(1)
76
+ end
77
77
 
78
- it 'should return a 2x1 matrix with refs to self elements' do
79
- n = @m.slice(0..1,1)
80
- n.shape.should eql([2,1])
78
+ it 'should return a 2x1 matrix with refs to self elements' do
79
+ n = @m.slice(0..1,1)
80
+ n.shape.should eql([2,1])
81
81
 
82
- n[0,0].should == @m[0,1]
83
- n[0,0] = -9
84
- @m[0,1].should eql(1)
85
- end
82
+ n[0,0].should == @m[0,1]
83
+ n[0,0] = -9
84
+ @m[0,1].should eql(1)
85
+ end
86
86
 
87
- it 'should be correct slice for range 0..2 and 0...3' do
88
- @m.slice(0..2,0..2).should == @m.slice(0...3,0...3)
89
- end
90
-
91
- [:dense, :list, :yale].each do |cast_type|
92
- it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
93
- nm_eql(@m.slice(1..2, 1..2).cast(cast_type, :int32), @m.slice(1..2,1..2)).should be_true
94
- nm_eql(@m.slice(0..1, 1..2).cast(cast_type, :int32), @m.slice(0..1,1..2)).should be_true
95
- nm_eql(@m.slice(1..2, 0..1).cast(cast_type, :int32), @m.slice(1..2,0..1)).should be_true
96
- nm_eql(@m.slice(0..1, 0..1).cast(cast_type, :int32), @m.slice(0..1,0..1)).should be_true
97
-
98
- # Non square
99
- nm_eql(@m.slice(0..2, 1..2).cast(cast_type, :int32), @m.slice(0..2,1..2)).should be_true
100
- nm_eql(@m.slice(1..2, 0..2).cast(cast_type, :int32), @m.slice(1..2,0..2)).should be_true
101
-
102
- # Full
103
- nm_eql(@m.slice(0..2, 0..2).cast(cast_type, :int32), @m).should be_true
87
+ it 'should be correct slice for range 0..2 and 0...3' do
88
+ @m.slice(0..2,0..2).should == @m.slice(0...3,0...3)
104
89
  end
105
- end
106
- end
107
90
 
108
- if stype == :yale
109
- context "by reference" do
110
- it "should be raise error" do
111
- expect{ @m[1..2,1..2] }.to raise_error(NotImplementedError)
112
- end
113
- end
114
- else
115
- context "by reference" do
116
- it 'should return an NMatrix' do
117
- n = @m[0..1,0..1]
118
- nm_eql(n, NMatrix.new([2,2], [0,1,3,4], :int32)).should be_true
119
- end
91
+ [:dense, :list, :yale].each do |cast_type|
92
+ it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
93
+ nm_eql(@m.slice(1..2, 1..2).cast(cast_type, :int32), @m.slice(1..2,1..2)).should be_true
94
+ nm_eql(@m.slice(0..1, 1..2).cast(cast_type, :int32), @m.slice(0..1,1..2)).should be_true
95
+ nm_eql(@m.slice(1..2, 0..1).cast(cast_type, :int32), @m.slice(1..2,0..1)).should be_true
96
+ nm_eql(@m.slice(0..1, 0..1).cast(cast_type, :int32), @m.slice(0..1,0..1)).should be_true
120
97
 
121
- it 'should return a 2x2 matrix with refs to self elements' do
122
- n = @m[1..2,0..1]
123
- n.shape.should eql([2,2])
98
+ # Non square
99
+ nm_eql(@m.slice(0..2, 1..2).cast(cast_type, :int32), @m.slice(0..2,1..2)).should be_true
100
+ nm_eql(@m.slice(1..2, 0..2).cast(cast_type, :int32), @m.slice(1..2,0..2)).should be_true
124
101
 
125
- n[0,0].should == @m[1,0]
126
- n[0,0] = -9
127
- @m[1,0].should eql(-9)
102
+ # Full
103
+ nm_eql(@m.slice(0..2, 0..2).cast(cast_type, :int32), @m).should be_true
104
+ end
105
+ end
128
106
  end
129
107
 
130
- it 'should return a 1x2 matrix with refs to self elements' do
131
- n = @m[0,1..2]
132
- n.shape.should eql([1,2])
133
108
 
134
- n[0,0].should == @m[0,1]
135
- n[0,0] = -9
136
- @m[0,1].should eql(-9)
137
- end
138
109
 
139
- it 'should return a 2x1 matrix with refs to self elements' do
140
- n = @m[0..1,1]
141
- n.shape.should eql([2,1])
110
+ if stype == :yale
111
+ context "by reference" do
112
+ it "should raise an error" do
113
+ expect{ @m[1..2,1..2] }.to raise_error(NotImplementedError)
114
+ end
115
+ end
142
116
 
143
- n[0,0].should == @m[0,1]
144
- n[0,0] = -9
145
- @m[0,1].should eql(-9)
146
- end
117
+ context "by copy" do
118
+ it "should correctly preserve zeros" do
119
+ @m = NMatrix.new(:yale, 3, :int64)
120
+ column_slice = @m.column(2, :copy)
121
+ column_slice[0,0].should == 0
122
+ column_slice[1,0].should == 0
123
+ column_slice[2,0].should == 0
124
+ end
125
+ end
126
+ else
127
+ context "by reference" do
128
+ it 'should return an NMatrix' do
129
+ n = @m[0..1,0..1]
130
+ nm_eql(n, NMatrix.new([2,2], [0,1,3,4], :int32)).should be_true
131
+ end
147
132
 
148
- it 'should set value from NMatrix'
133
+ it 'should return a 2x2 matrix with refs to self elements' do
134
+ n = @m[1..2,0..1]
135
+ n.shape.should eql([2,2])
149
136
 
150
- it 'should slice again' do
151
- n = @m[1..2, 1..2]
152
- nm_eql(n[1,0..1], NMatrix.new([1,2], [7,8])).should be_true
153
- end
137
+ n[0,0].should == @m[1,0]
138
+ n[0,0] = -9
139
+ @m[1,0].should eql(-9)
140
+ end
154
141
 
155
- it 'should be correct slice for range 0..2 and 0...3' do
156
- @m[0..2,0..2].should == @m[0...3,0...3]
157
- end
142
+ it 'should return a 1x2 matrix with refs to self elements' do
143
+ n = @m[0,1..2]
144
+ n.shape.should eql([1,2])
145
+
146
+ n[0,0].should == @m[0,1]
147
+ n[0,0] = -9
148
+ @m[0,1].should eql(-9)
149
+ end
150
+
151
+ it 'should return a 2x1 matrix with refs to self elements' do
152
+ n = @m[0..1,1]
153
+ n.shape.should eql([2,1])
154
+
155
+ n[0,0].should == @m[0,1]
156
+ n[0,0] = -9
157
+ @m[0,1].should eql(-9)
158
+ end
159
+
160
+ it 'should set value from NMatrix'
161
+
162
+ it 'should slice again' do
163
+ n = @m[1..2, 1..2]
164
+ nm_eql(n[1,0..1], NMatrix.new([1,2], [7,8])).should be_true
165
+ end
166
+
167
+ it 'should be correct slice for range 0..2 and 0...3' do
168
+ @m[0..2,0..2].should == @m[0...3,0...3]
169
+ end
170
+
171
+ if stype == :dense
172
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
173
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
174
+
175
+ # Won't work if they're both 1-byte, due to overflow.
176
+ next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
177
+
178
+ # For now, don't bother testing int-int mult.
179
+ #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
180
+ it "handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
181
+ #STDERR.puts "dtype=#{dtype.to_s}"
182
+ #STDERR.puts "2"
183
+
184
+ nary = if left_dtype.to_s =~ /complex/
185
+ COMPLEX_MATRIX43A_ARRAY
186
+ elsif left_dtype.to_s =~ /rational/
187
+ RATIONAL_MATRIX43A_ARRAY
188
+ else
189
+ MATRIX43A_ARRAY
190
+ end
191
+
192
+ mary = if right_dtype.to_s =~ /complex/
193
+ COMPLEX_MATRIX32A_ARRAY
194
+ elsif right_dtype.to_s =~ /rational/
195
+ RATIONAL_MATRIX32A_ARRAY
196
+ else
197
+ MATRIX32A_ARRAY
198
+ end
199
+
200
+ n = NMatrix.new([4,3], nary, left_dtype)[1..3,1..2]
201
+ m = NMatrix.new([3,2], mary, right_dtype)[1..2,0..1]
202
+
203
+ r = n.dot m
204
+ r.shape.should eql([3,2])
205
+
206
+ r[0,0].should == 219.0
207
+ r[0,1].should == 185.0
208
+ r[1,0].should == 244.0
209
+ r[1,1].should == 205.0
210
+ r[2,0].should == 42.0
211
+ r[2,1].should == 35.0
212
+
213
+ end
214
+ end
215
+ end
158
216
 
159
- if stype == :dense
160
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
161
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
162
-
163
- # Won't work if they're both 1-byte, due to overflow.
164
- next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
165
-
166
- # For now, don't bother testing int-int mult.
167
- #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
168
- it "handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
169
- #STDERR.puts "dtype=#{dtype.to_s}"
170
- #STDERR.puts "2"
171
-
172
- nary = if left_dtype.to_s =~ /complex/
173
- COMPLEX_MATRIX43A_ARRAY
174
- elsif left_dtype.to_s =~ /rational/
175
- RATIONAL_MATRIX43A_ARRAY
176
- else
177
- MATRIX43A_ARRAY
178
- end
179
-
180
- mary = if right_dtype.to_s =~ /complex/
181
- COMPLEX_MATRIX32A_ARRAY
182
- elsif right_dtype.to_s =~ /rational/
183
- RATIONAL_MATRIX32A_ARRAY
184
- else
185
- MATRIX32A_ARRAY
186
- end
187
-
188
- n = NMatrix.new([4,3], nary, left_dtype)[1..3,1..2]
189
- m = NMatrix.new([3,2], mary, right_dtype)[1..2,0..1]
190
-
191
- r = n.dot m
192
- r.shape.should eql([3,2])
193
-
194
- r[0,0].should == 219.0
195
- r[0,1].should == 185.0
196
- r[1,0].should == 244.0
197
- r[1,1].should == 205.0
198
- r[2,0].should == 42.0
199
- r[2,1].should == 35.0
217
+ context "operations" do
218
+
219
+ it "correctly transposes slices" do
220
+ @m[0...3,0].transpose.should eq N[[0, 3, 6]]
221
+ end
222
+
223
+ it "adds slices" do
224
+ (N[[0,0,0]] + @m[1,0..2]).should eq N[[3, 4, 5]]
225
+ end
226
+
227
+ it "scalar adds to slices" do
228
+ (@m[1,0..2]+1).should eq N[[4, 5, 6]]
229
+ end
230
+
231
+ it "compares slices to scalars" do
232
+ (@m[1, 0..2] > 2).each { |e| (e != 0).should be_true }
233
+ end
234
+
235
+ it "iterates only over elements in the slice" do
236
+ els = []
237
+ @m[1, 0..2].each { |e| els << e }
238
+ els.size.should eq 3
239
+ els[0].should eq 3
240
+ els[1].should eq 4
241
+ els[2].should eq 5
242
+ end
243
+
244
+ it "iterates with index only over elements in the slice" do
245
+ els = []
246
+ @m[1, 0..2].each_stored_with_indices { |a| els << a }
247
+ els.size.should eq 3
248
+ els[0].should eq [3, 0, 0]
249
+ els[1].should eq [4, 0, 1]
250
+ els[2].should eq [5, 0, 2]
251
+ end
200
252
 
201
253
  end
254
+
202
255
  end
203
- end
204
- end
205
256
 
206
- it 'should be cleaned up by garbage collector without errors' do
207
- 1.times do
208
- n = @m[1..2,0..1]
209
- end
210
- GC.start
211
- @m.should == NMatrix.new(:dense, [3,3], (0..9).to_a, :int32).cast(stype, :int32)
212
- n = nil
213
- 1.times do
214
- m = NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
215
- n = m[0..1,0..1]
216
- end
217
- GC.start
218
- n.should == NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
219
- end
257
+ it 'should be cleaned up by garbage collector without errors' do
258
+ 1.times do
259
+ n = @m[1..2,0..1]
260
+ end
261
+ GC.start
262
+ @m.should == NMatrix.new(:dense, [3,3], (0..9).to_a, :int32).cast(stype, :int32)
263
+ n = nil
264
+ 1.times do
265
+ m = NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
266
+ n = m[0..1,0..1]
267
+ end
268
+ GC.start
269
+ n.should == NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
270
+ end
220
271
 
221
- [:dense, :list, :yale].each do |cast_type|
222
- it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
223
- nm_eql(@m[1..2, 1..2].cast(cast_type, :int32), @m[1..2,1..2]).should be_true
224
- nm_eql(@m[0..1, 1..2].cast(cast_type, :int32), @m[0..1,1..2]).should be_true
225
- nm_eql(@m[1..2, 0..1].cast(cast_type, :int32), @m[1..2,0..1]).should be_true
226
- nm_eql(@m[0..1, 0..1].cast(cast_type, :int32), @m[0..1,0..1]).should be_true
272
+ [:dense, :list, :yale].each do |cast_type|
273
+ it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
274
+ nm_eql(@m[1..2, 1..2].cast(cast_type, :int32), @m[1..2,1..2]).should be_true
275
+ nm_eql(@m[0..1, 1..2].cast(cast_type, :int32), @m[0..1,1..2]).should be_true
276
+ nm_eql(@m[1..2, 0..1].cast(cast_type, :int32), @m[1..2,0..1]).should be_true
277
+ nm_eql(@m[0..1, 0..1].cast(cast_type, :int32), @m[0..1,0..1]).should be_true
227
278
 
228
- # Non square
229
- nm_eql(@m[0..2, 1..2].cast(cast_type, :int32), @m[0..2,1..2]).should be_true
230
- nm_eql(@m[1..2, 0..2].cast(cast_type, :int32), @m[1..2,0..2]).should be_true
279
+ # Non square
280
+ nm_eql(@m[0..2, 1..2].cast(cast_type, :int32), @m[0..2,1..2]).should be_true
281
+ nm_eql(@m[1..2, 0..2].cast(cast_type, :int32), @m[1..2,0..2]).should be_true
231
282
 
232
- # Full
233
- nm_eql(@m[0..2, 0..2].cast(cast_type, :int32), @m).should be_true
283
+ # Full
284
+ nm_eql(@m[0..2, 0..2].cast(cast_type, :int32), @m).should be_true
285
+ end
286
+ end
234
287
  end
235
288
  end
236
- end
237
- end
238
289
  end # unless stype == :yale
239
290
  end
240
291
 
241
292
  # Stupid but independent comparison
242
- def nm_eql(n, m)
293
+ def nm_eql(n, m) #:nodoc:
243
294
  if n.shape != m.shape
244
295
  false
245
296
  else
@@ -247,11 +298,11 @@ describe "Slice operation" do
247
298
  n.shape[1].times do |j|
248
299
  if n[i,j] != m[i,j]
249
300
  puts "n[#{i},#{j}] != m[#{i},#{j}] (#{n[i,j]} != #{m[i,j]})"
250
- return false
301
+ return false
251
302
  end
252
303
  end
253
304
  end
254
305
  true
255
- end
306
+ end
256
307
  end
257
308
  end