nmatrix 0.0.6 → 0.0.7

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +5 -0
  4. data/History.txt +97 -0
  5. data/Manifest.txt +34 -7
  6. data/README.rdoc +13 -13
  7. data/Rakefile +36 -26
  8. data/ext/nmatrix/data/data.cpp +15 -2
  9. data/ext/nmatrix/data/data.h +4 -0
  10. data/ext/nmatrix/data/ruby_object.h +5 -14
  11. data/ext/nmatrix/extconf.rb +3 -2
  12. data/ext/nmatrix/{util/math.cpp → math.cpp} +296 -6
  13. data/ext/nmatrix/math/asum.h +143 -0
  14. data/ext/nmatrix/math/geev.h +82 -0
  15. data/ext/nmatrix/math/gemm.h +267 -0
  16. data/ext/nmatrix/math/gemv.h +208 -0
  17. data/ext/nmatrix/math/ger.h +96 -0
  18. data/ext/nmatrix/math/gesdd.h +80 -0
  19. data/ext/nmatrix/math/gesvd.h +78 -0
  20. data/ext/nmatrix/math/getf2.h +86 -0
  21. data/ext/nmatrix/math/getrf.h +240 -0
  22. data/ext/nmatrix/math/getri.h +107 -0
  23. data/ext/nmatrix/math/getrs.h +125 -0
  24. data/ext/nmatrix/math/idamax.h +86 -0
  25. data/ext/nmatrix/{util → math}/lapack.h +60 -356
  26. data/ext/nmatrix/math/laswp.h +165 -0
  27. data/ext/nmatrix/math/long_dtype.h +52 -0
  28. data/ext/nmatrix/math/math.h +1154 -0
  29. data/ext/nmatrix/math/nrm2.h +181 -0
  30. data/ext/nmatrix/math/potrs.h +125 -0
  31. data/ext/nmatrix/math/rot.h +141 -0
  32. data/ext/nmatrix/math/rotg.h +115 -0
  33. data/ext/nmatrix/math/scal.h +73 -0
  34. data/ext/nmatrix/math/swap.h +73 -0
  35. data/ext/nmatrix/math/trsm.h +383 -0
  36. data/ext/nmatrix/nmatrix.cpp +176 -152
  37. data/ext/nmatrix/nmatrix.h +1 -2
  38. data/ext/nmatrix/ruby_constants.cpp +9 -4
  39. data/ext/nmatrix/ruby_constants.h +1 -0
  40. data/ext/nmatrix/storage/dense.cpp +57 -41
  41. data/ext/nmatrix/storage/list.cpp +52 -50
  42. data/ext/nmatrix/storage/storage.cpp +59 -43
  43. data/ext/nmatrix/storage/yale.cpp +352 -333
  44. data/ext/nmatrix/storage/yale.h +4 -0
  45. data/lib/nmatrix.rb +2 -2
  46. data/lib/nmatrix/blas.rb +4 -4
  47. data/lib/nmatrix/enumerate.rb +241 -0
  48. data/lib/nmatrix/lapack.rb +54 -1
  49. data/lib/nmatrix/math.rb +462 -0
  50. data/lib/nmatrix/nmatrix.rb +210 -486
  51. data/lib/nmatrix/nvector.rb +0 -62
  52. data/lib/nmatrix/rspec.rb +75 -0
  53. data/lib/nmatrix/shortcuts.rb +136 -108
  54. data/lib/nmatrix/version.rb +1 -1
  55. data/spec/blas_spec.rb +20 -12
  56. data/spec/elementwise_spec.rb +22 -13
  57. data/spec/io_spec.rb +1 -0
  58. data/spec/lapack_spec.rb +197 -0
  59. data/spec/nmatrix_spec.rb +39 -38
  60. data/spec/nvector_spec.rb +3 -9
  61. data/spec/rspec_monkeys.rb +29 -0
  62. data/spec/rspec_spec.rb +34 -0
  63. data/spec/shortcuts_spec.rb +14 -16
  64. data/spec/slice_spec.rb +242 -186
  65. data/spec/spec_helper.rb +19 -0
  66. metadata +33 -5
  67. data/ext/nmatrix/util/math.h +0 -2612
data/spec/nvector_spec.rb CHANGED
@@ -49,13 +49,6 @@ describe NVector do
49
49
  v[0].should == 1.555
50
50
  end
51
51
 
52
- it "transpose!() changes destructively its raw and column stored structure" do
53
- v = NVector.new 5, :float64
54
- v.transpose!
55
- v.shape[0].should == 5
56
- v.shape[1].should == 1
57
- end
58
-
59
52
  it "dot() multiples itself by another NVector" do
60
53
  v1 = NVector.new(2, :float64)
61
54
  v2 = NVector.new(2, :float64).transpose
@@ -63,10 +56,11 @@ describe NVector do
63
56
  v1[1] = 2.3
64
57
  v2[0] = 1.3
65
58
  v2[1] = 2.5
66
- v1.dot(v2).should == 12.0
59
+ v1.dot(v2).should be_within(0.000000001).of(7.7)
67
60
  end
68
61
 
69
62
  it "dot!() multiples itself destructively by another NVector" do
63
+ pending "dot! not yet implemented"
70
64
  v1 = NVector.new 2, :float64
71
65
  v2 = NVector.new(2, :float64).transpose
72
66
  v1[0] = 1.5
@@ -74,7 +68,7 @@ describe NVector do
74
68
  v2[0] = 1.3
75
69
  v2[1] = 2.5
76
70
  v1.dot!(v2)
77
- v1.should == 12.0
71
+ v1.should be_within(0.000000001).of(7.7)
78
72
  end
79
73
 
80
74
  it "pretty_print() prints values to standard output with a pretty format" do
@@ -0,0 +1,29 @@
1
+ module RSpec::Matchers::BuiltIn
2
+ class BeWithin
3
+
4
+ def of(expected)
5
+ @expected = expected
6
+ @unit = ''
7
+ if expected.is_a?(NMatrix)
8
+ @tolerance = if @delta.is_a?(NMatrix)
9
+ @delta.clone
10
+ elsif @delta.is_a?(Array)
11
+ NMatrix.new(:dense, expected.shape, @delta, expected.dtype)
12
+ else
13
+ NMatrix.ones_like(expected) * @delta
14
+ end
15
+ else
16
+ @tolerance = @delta
17
+ end
18
+
19
+ self
20
+ end
21
+
22
+ def percent_of(expected)
23
+ @expected = expected
24
+ @unit = '%'
25
+ @tolerance = @expected.abs * @delta / 100.0 # <- only change is to reverse abs and @delta
26
+ self
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
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 - 2012, Ruby Science Foundation
12
+ # NMatrix is Copyright (c) 2012, 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
+ # == rspec_spec.rb
24
+ #
25
+ # A spec for testing monkey patches to RSpec for NMatrix.
26
+ #
27
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
28
+
29
+ describe "RSpec" do
30
+ it "should permit #be_within to be used on a dense NMatrix" do
31
+ (NMatrix.new(:dense, [4,1], 1.0, :complex128) / 10000.0).should be_within(0.00000001).of(NMatrix.new(:dense, [4,1], 0.0001, :float64))
32
+ (NMatrix.new(:dense, [4,1], 1.0, :complex128) / 10000.0).should_not be_within(0.00000001).of(NMatrix.new(:dense, [4,1], 1.0, :float64))
33
+ end
34
+ end
@@ -165,29 +165,27 @@ describe NMatrix do
165
165
  m.column(2).is_a?(NMatrix).should be_true
166
166
  end
167
167
 
168
- it "column() accepts a second parameter (only :copy or :reference)" do
169
- m = NMatrix.random(3)
170
-
171
- expect { m.column(1, :copy) }.to_not raise_error
172
- expect { m.column(1, :reference) }.to_not raise_error
173
-
174
- expect { m.column(1, :derp) }.to raise_error
175
- end
176
-
177
168
  it "row() returns a NMatrix" do
178
169
  m = NMatrix.random(3)
179
170
 
180
171
  m.row(2).is_a?(NMatrix).should be_true
181
172
  end
182
173
 
183
- it "row() accepts a second parameter (only :copy or :reference)" do
184
- m = NMatrix.random(3)
185
-
186
- expect { m.row(1, :copy) }.to_not raise_error
187
- expect { m.row(1, :reference) }.to_not raise_error
174
+ it "diagonals() creates an NMatrix" do
175
+ arr = [1,2,3,4]
176
+ m = NMatrix.diagonals(arr)
177
+ m.is_a?(NMatrix).should be_true
178
+ end
188
179
 
189
- expect { m.row(1, :derp) }.to raise_error
180
+ it "diagonals() contains the seeded values on the diagonal" do
181
+ arr = [1,2,3,4]
182
+ m = NMatrix.diagonals(arr)
183
+ m[0,0].should eq(arr[0])
184
+ m[1,1].should eq(arr[1])
185
+ m[2,2].should eq(arr[2])
186
+ m[3,3].should eq(arr[3])
190
187
  end
188
+
191
189
  end
192
190
 
193
191
  describe "NVector" do
@@ -261,7 +259,7 @@ describe "Inline constructor" do
261
259
 
262
260
  it "creates a NMatrix with the given values" do
263
261
  m = NMatrix.new([2, 2], [1, 4, 6, 7])
264
- n = N[[1, 4], [6, 7]]
262
+ n = NMatrix[[1, 4], [6, 7]]
265
263
 
266
264
  m.should.eql? n
267
265
  end
data/spec/slice_spec.rb CHANGED
@@ -27,29 +27,118 @@
27
27
  require File.dirname(__FILE__) + "/spec_helper.rb"
28
28
 
29
29
  describe "Slice operation" do
30
+
30
31
  [:dense, :list, :yale].each do |stype|
31
32
  context "for #{stype}" do
32
33
  before :each do
33
34
  @m = create_matrix(stype)
34
35
  end
35
36
 
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)
37
+ if stype == :yale
38
+ it "should binary search for the left boundary of a partial row of stored indices correctly" do
39
+ n = NMatrix.new(:yale, 10, :int32)
40
+ n[3,0] = 1
41
+ #n[3,2] = 2
42
+ n[3,3] = 3
43
+ n[3,4] = 4
44
+ n[3,6] = 5
45
+ n[3,8] = 6
46
+ n[3,9] = 7
47
+ vs = []
48
+ is = []
49
+ js = []
50
+ n[3,1..9].each_stored_with_indices do |v,i,j|
51
+ vs << v
52
+ is << i
53
+ js << j
54
+ end
40
55
 
56
+ vs.should == [3,4,5,6,7]
57
+ js.should == [2,3,5,7,8]
58
+ is.should == [0,0,0,0,0]
59
+ end
60
+ elsif stype == :list
61
+ it "should iterate across a partial row of stored indices" do
62
+ vs = []
63
+ is = []
64
+ js = []
65
+
66
+ STDERR.puts("now") if stype == :yale
67
+ @m[2,1..2].each_stored_with_indices do |v,i,j|
68
+ vs << v
69
+ is << i
70
+ js << j
71
+ end
41
72
 
42
- @m.is_ref?.should be_false
43
- a.is_ref?.should be_true
44
- b.is_ref?.should be_false
73
+ vs.should == [7,8]
74
+ is.should == [0,0]
75
+ js.should == [0,1]
45
76
  end
77
+ end
78
+
79
+ unless stype == :dense
80
+ it "should iterate across a row of stored indices" do
81
+
82
+ vs = []
83
+ is = []
84
+ js = []
85
+ @m[2,0..2].each_stored_with_indices do |v,i,j|
86
+ vs << v
87
+ is << i
88
+ js << j
89
+ end
90
+ vs.should == (stype == :yale ? [8,6,7] : [6,7,8])
91
+ is.should == [0,0,0]
92
+ js.should == (stype == :yale ? [2,0,1] : [0,1,2])
93
+ end
94
+
95
+ it "should iterate across a submatrix of stored indices" do
96
+ vs = []
97
+ is = []
98
+ js = []
99
+ @m[0..1,1..2].each_stored_with_indices do |v,i,j|
100
+ vs << v
101
+ is << i
102
+ js << j
103
+ end
46
104
 
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]
105
+ vs.should == (stype == :yale ? [4,1,2,5] : [1,2,4,5])
106
+ is.should == (stype == :yale ? [1,0,0,1] : [0,0,1,1])
107
+ js.should == (stype == :yale ? [0,0,1,1] : [0,1,0,1])
51
108
  end
52
- end # unless stype == :yale
109
+ end
110
+
111
+ it "should return correct shape and 1st-order supershape" do
112
+ x = NMatrix.random([10,12])
113
+ y = x[0...8,5...12]
114
+ y.shape.should == [8,7]
115
+ y.supershape.should == [10,12]
116
+ end
117
+
118
+ it "should return correct 1st- and 2nd-order supershape" do
119
+ pending "Not yet sure if we ever want to enable reference slices of reference slices"
120
+ x = NMatrix.random([10,12])
121
+ y = x[0...8,5...12]
122
+ z = y[0...3,0...4]
123
+ z.supershape(2).should == y.supershape(1)
124
+ z.supershape(1).should == [8,7]
125
+ end
126
+
127
+ it "should have #is_ref? method" do
128
+ a = @m[0..1, 0..1]
129
+ b = @m.slice(0..1, 0..1)
130
+
131
+
132
+ @m.is_ref?.should be_false
133
+ a.is_ref?.should be_true
134
+ b.is_ref?.should be_false
135
+ end
136
+
137
+ it "reference should compare with non-reference" do
138
+ @m.slice(1..2,0..1).should == @m[1..2, 0..1]
139
+ @m[1..2,0..1].should == @m.slice(1..2, 0..1)
140
+ @m[1..2,0..1].should == @m[1..2, 0..1]
141
+ end
53
142
 
54
143
  context "with copying" do
55
144
  it 'should return an NMatrix' do
@@ -66,7 +155,7 @@ describe "Slice operation" do
66
155
  @m[2,1].should eql(7)
67
156
  end
68
157
 
69
- it 'should return a 1x2 vector with refs to self elements' do
158
+ it 'should return a 1x2 matrix with refs to self elements' do
70
159
  n = @m.slice(0,1..2)
71
160
  n.shape.should eql([1,2])
72
161
 
@@ -105,211 +194,178 @@ describe "Slice operation" do
105
194
  end
106
195
  end
107
196
 
108
-
109
-
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
197
+ # Yale:
198
+ #context "by copy" do
199
+ #it "should correctly preserve zeros" do
200
+ # @m = NMatrix.new(:yale, 3, :int64)
201
+ # column_slice = @m.column(2, :copy)
202
+ # column_slice[0].should == 0
203
+ # column_slice[1].should == 0
204
+ # column_slice[2].should == 0
205
+ #end
206
+ #end
207
+
208
+ context "by reference" do
209
+ it 'should return an NMatrix' do
210
+ n = @m[0..1,0..1]
211
+ nm_eql(n, NMatrix.new([2,2], [0,1,3,4], :int32)).should be_true
115
212
  end
116
213
 
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].should == 0
122
- column_slice[1].should == 0
123
- column_slice[2].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
214
+ it 'should return a 2x2 matrix with refs to self elements' do
215
+ n = @m[1..2,0..1]
216
+ n.shape.should eql([2,2])
132
217
 
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])
218
+ n[0,0].should == @m[1,0]
219
+ n[0,0] = -9
220
+ @m[1,0].should eql(-9)
221
+ end
136
222
 
137
- n[0,0].should == @m[1,0]
138
- n[0,0] = -9
139
- @m[1,0].should eql(-9)
140
- end
223
+ it 'should return a 1x2 vector with refs to self elements' do
224
+ n = @m[0,1..2]
225
+ n.shape.should eql([1,2])
141
226
 
142
- it 'should return a 1x2 vector with refs to self elements' do
143
- n = @m[0,1..2]
144
- n.shape.should eql([1,2])
227
+ n[0].should == @m[0,1]
228
+ n[0] = -9
229
+ @m[0,1].should eql(-9)
230
+ end
145
231
 
146
- n[0].should == @m[0,1]
147
- n[0] = -9
148
- @m[0,1].should eql(-9)
149
- end
232
+ it 'should return a 2x1 vector with refs to self elements' do
233
+ n = @m[0..1,1]
234
+ n.shape.should eql([2,1])
150
235
 
151
- it 'should return a 2x1 vector with refs to self elements' do
152
- n = @m[0..1,1]
153
- n.shape.should eql([2,1])
236
+ n[0].should == @m[0,1]
237
+ n[0] = -9
238
+ @m[0,1].should eql(-9)
239
+ end
154
240
 
155
- n[0].should == @m[0,1]
156
- n[0] = -9
157
- @m[0,1].should eql(-9)
158
- end
241
+ it 'should slice again' do
242
+ n = @m[1..2, 1..2]
243
+ nm_eql(n[1,0..1], NVector.new(2, [7,8], :int32).transpose).should be_true
244
+ end
159
245
 
160
- it 'should slice again' do
161
- n = @m[1..2, 1..2]
162
- nm_eql(n[1,0..1], NVector.new(2, [7,8], :int32).transpose).should be_true
163
- end
246
+ it 'should be correct slice for range 0..2 and 0...3' do
247
+ @m[0..2,0..2].should == @m[0...3,0...3]
248
+ end
164
249
 
165
- it 'should be correct slice for range 0..2 and 0...3' do
166
- @m[0..2,0..2].should == @m[0...3,0...3]
167
- end
250
+ if stype == :dense
251
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
252
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
253
+
254
+ # Won't work if they're both 1-byte, due to overflow.
255
+ next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
256
+
257
+ # For now, don't bother testing int-int mult.
258
+ #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
259
+ it "handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
260
+ #STDERR.puts "dtype=#{dtype.to_s}"
261
+ #STDERR.puts "2"
262
+
263
+ nary = if left_dtype.to_s =~ /complex/
264
+ COMPLEX_MATRIX43A_ARRAY
265
+ elsif left_dtype.to_s =~ /rational/
266
+ RATIONAL_MATRIX43A_ARRAY
267
+ else
268
+ MATRIX43A_ARRAY
269
+ end
270
+
271
+ mary = if right_dtype.to_s =~ /complex/
272
+ COMPLEX_MATRIX32A_ARRAY
273
+ elsif right_dtype.to_s =~ /rational/
274
+ RATIONAL_MATRIX32A_ARRAY
275
+ else
276
+ MATRIX32A_ARRAY
277
+ end
278
+
279
+ n = NMatrix.new([4,3], nary, left_dtype)[1..3,1..2]
280
+ m = NMatrix.new([3,2], mary, right_dtype)[1..2,0..1]
281
+
282
+ r = n.dot m
283
+ r.shape.should eql([3,2])
284
+
285
+ r[0,0].should == 219.0
286
+ r[0,1].should == 185.0
287
+ r[1,0].should == 244.0
288
+ r[1,1].should == 205.0
289
+ r[2,0].should == 42.0
290
+ r[2,1].should == 35.0
168
291
 
169
- if stype == :dense
170
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
171
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
172
-
173
- # Won't work if they're both 1-byte, due to overflow.
174
- next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
175
-
176
- # For now, don't bother testing int-int mult.
177
- #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
178
- it "handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
179
- #STDERR.puts "dtype=#{dtype.to_s}"
180
- #STDERR.puts "2"
181
-
182
- nary = if left_dtype.to_s =~ /complex/
183
- COMPLEX_MATRIX43A_ARRAY
184
- elsif left_dtype.to_s =~ /rational/
185
- RATIONAL_MATRIX43A_ARRAY
186
- else
187
- MATRIX43A_ARRAY
188
- end
189
-
190
- mary = if right_dtype.to_s =~ /complex/
191
- COMPLEX_MATRIX32A_ARRAY
192
- elsif right_dtype.to_s =~ /rational/
193
- RATIONAL_MATRIX32A_ARRAY
194
- else
195
- MATRIX32A_ARRAY
196
- end
197
-
198
- n = NMatrix.new([4,3], nary, left_dtype)[1..3,1..2]
199
- m = NMatrix.new([3,2], mary, right_dtype)[1..2,0..1]
200
-
201
- r = n.dot m
202
- r.shape.should eql([3,2])
203
-
204
- r[0,0].should == 219.0
205
- r[0,1].should == 185.0
206
- r[1,0].should == 244.0
207
- r[1,1].should == 205.0
208
- r[2,0].should == 42.0
209
- r[2,1].should == 35.0
210
-
211
- end
212
292
  end
213
293
  end
294
+ end
214
295
 
215
- context "operations" do
216
-
217
- it "correctly transposes slices" do
218
- @m[0...3,0].transpose.should eq N[[0, 3, 6]]
219
- end
296
+ context "operations" do
220
297
 
221
- it "adds slices" do
222
- (N[[0,0,0]] + @m[1,0..2]).should eq N[[3, 4, 5]]
223
- end
298
+ it "correctly transposes slices" do
299
+ @m[0...3,0].transpose.should eq NMatrix[[0, 3, 6]]
300
+ end
224
301
 
225
- it "scalar adds to slices" do
226
- (@m[1,0..2]+1).should eq N[[4, 5, 6]]
227
- end
302
+ it "adds slices" do
303
+ (NMatrix[[0,0,0]] + @m[1,0..2]).should eq NMatrix[[3, 4, 5]]
304
+ end
228
305
 
229
- it "compares slices to scalars" do
230
- (@m[1, 0..2] > 2).each { |e| (e != 0).should be_true }
231
- end
306
+ it "scalar adds to slices" do
307
+ (@m[1,0..2]+1).should eq NMatrix[[4, 5, 6]]
308
+ end
232
309
 
233
- it "iterates only over elements in the slice" do
234
- els = []
235
- @m[1, 0..2].each { |e| els << e }
236
- els.size.should eq 3
237
- els[0].should eq 3
238
- els[1].should eq 4
239
- els[2].should eq 5
240
- end
310
+ it "compares slices to scalars" do
311
+ (@m[1, 0..2] > 2).each { |e| (e != 0).should be_true }
312
+ end
241
313
 
242
- it "iterates with index only over elements in the slice" do
243
- els = []
244
- @m[1, 0..2].each_stored_with_indices { |a| els << a }
245
- els.size.should eq 3
246
- els[0].should eq [3, 0, 0]
247
- els[1].should eq [4, 0, 1]
248
- els[2].should eq [5, 0, 2]
249
- end
314
+ it "iterates only over elements in the slice" do
315
+ els = []
316
+ @m[1, 0..2].each { |e| els << e }
317
+ els.size.should eq 3
318
+ els[0].should eq 3
319
+ els[1].should eq 4
320
+ els[2].should eq 5
321
+ end
250
322
 
323
+ it "iterates with index only over elements in the slice" do
324
+ els = []
325
+ @m[1, 0..2].each_stored_with_indices { |a| els << a }
326
+ els.size.should eq 3
327
+ els[0].should eq [3, 0, 0]
328
+ els[1].should eq [4, 0, 1]
329
+ els[2].should eq [5, 0, 2]
251
330
  end
252
331
 
253
332
  end
254
333
 
255
- it 'should be cleaned up by garbage collector without errors' do
256
- 1.times do
257
- n = @m[1..2,0..1]
258
- end
259
- GC.start
260
- @m.should == NMatrix.new(:dense, [3,3], (0..9).to_a, :int32).cast(stype, :int32)
261
- n = nil
262
- 1.times do
263
- m = NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
264
- n = m[0..1,0..1]
265
- end
266
- GC.start
267
- n.should == NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
334
+ end
335
+
336
+ it 'should be cleaned up by garbage collector without errors' do
337
+ 1.times do
338
+ n = @m[1..2,0..1]
339
+ end
340
+ GC.start
341
+ @m.should == NMatrix.new(:dense, [3,3], (0..9).to_a, :int32).cast(stype, :int32)
342
+ n = nil
343
+ 1.times do
344
+ m = NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
345
+ n = m[0..1,0..1]
268
346
  end
347
+ GC.start
348
+ n.should == NMatrix.new(:dense, [2,2], [1,2,3,4]).cast(stype, :int32)
349
+ end
269
350
 
270
- [:dense, :list, :yale].each do |cast_type|
271
- it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
272
- nm_eql(@m[1..2, 1..2].cast(cast_type, :int32), @m[1..2,1..2]).should be_true
273
- nm_eql(@m[0..1, 1..2].cast(cast_type, :int32), @m[0..1,1..2]).should be_true
274
- nm_eql(@m[1..2, 0..1].cast(cast_type, :int32), @m[1..2,0..1]).should be_true
275
- nm_eql(@m[0..1, 0..1].cast(cast_type, :int32), @m[0..1,0..1]).should be_true
351
+ [:dense, :list, :yale].each do |cast_type|
352
+ it "should cast from #{stype.upcase} to #{cast_type.upcase}" do
276
353
 
277
- # Non square
278
- nm_eql(@m[0..2, 1..2].cast(cast_type, :int32), @m[0..2,1..2]).should be_true
279
- nm_eql(@m[1..2, 0..2].cast(cast_type, :int32), @m[1..2,0..2]).should be_true
354
+ nm_eql(@m[1..2, 1..2].cast(cast_type), @m[1..2,1..2]).should be_true
355
+ nm_eql(@m[0..1, 1..2].cast(cast_type), @m[0..1,1..2]).should be_true
356
+ nm_eql(@m[1..2, 0..1].cast(cast_type), @m[1..2,0..1]).should be_true
357
+ nm_eql(@m[0..1, 0..1].cast(cast_type), @m[0..1,0..1]).should be_true
280
358
 
281
- # Full
282
- nm_eql(@m[0..2, 0..2].cast(cast_type, :int32), @m).should be_true
283
- end
284
- end
285
- end
286
- end
287
- end # unless stype == :yale
288
- end
359
+ # Non square
360
+ nm_eql(@m[0..2, 1..2].cast(cast_type), @m[0..2,1..2]).should be_true
361
+ nm_eql(@m[1..2, 0..2].cast(cast_type), @m[1..2,0..2]).should be_true
289
362
 
290
- # Stupid but independent comparison
291
- def nm_eql(n, m) #:nodoc:
292
- if n.shape != m.shape
293
- false
294
- elsif n.is_a?(NVector)
295
- return false unless m.is_a?(NVector) # don't compare NV to NM
296
- long_shape = n.shape[0] == 1 ? n.shape[1] : n.shape[0]
297
- long_shape.times do |j|
298
- if n[j] != m[j]
299
- puts "n[#{j}] != m[#{j}] (#{n[j]} != #{m[j]})"
300
- return false
301
- end
302
- end
303
- else # NMatrix
304
- n.shape[0].times do |i|
305
- n.shape[1].times do |j|
306
- if n[i,j] != m[i,j]
307
- puts "n[#{i},#{j}] != m[#{i},#{j}] (#{n[i,j]} != #{m[i,j]})"
308
- return false
363
+ # Full
364
+ nm_eql(@m[0..2, 0..2].cast(cast_type), @m).should be_true
309
365
  end
310
366
  end
311
367
  end
368
+
312
369
  end
313
- true
314
370
  end
315
371
  end