nmatrix 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,3 +1,4 @@
1
+ #--
1
2
  # = NMatrix
2
3
  #
3
4
  # A linear algebra library for scientific computation in Ruby.
@@ -8,8 +9,8 @@
8
9
  #
9
10
  # == Copyright Information
10
11
  #
11
- # SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
12
- # NMatrix is Copyright (c) 2012, Ruby Science Foundation
12
+ # SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
13
+ # NMatrix is Copyright (c) 2013, Ruby Science Foundation
13
14
  #
14
15
  # Please see LICENSE.txt for additional copyright notices.
15
16
  #
@@ -19,9 +20,12 @@
19
20
  # our Contributor Agreement:
20
21
  #
21
22
  # * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
22
- #
23
+ #++
23
24
 
24
25
  class NMatrix
25
- VERSION = '0.0.3'
26
+ # Note that the format of the VERSION string is needed for NMatrix
27
+ # native IO. If you change the format, please make sure that native
28
+ # IO can still understand NMatrix::VERSION.
29
+ VERSION = "0.0.4"
26
30
  end
27
31
 
@@ -22,12 +22,14 @@ such as for driving a car or flying a space shuttle, you
22
22
  may wish to choose other software (for now).
23
23
 
24
24
  NMatrix requires a C compiler, and has been tested only
25
- with GCC 4.6.1. We are happy to accept contributions
25
+ with GCC 4.6+. We are happy to accept contributions
26
26
  which improve the portability of this project.
27
27
 
28
28
  Also required is ATLAS. Most Linux distributions and Mac
29
29
  versions include ATLAS, but you may wish to compile it
30
- yourself.
30
+ yourself. Rumor has it that the Ubuntu/Debian apt package
31
+ for ATLAS WILL NOT WORK with NMatrix. Please install it
32
+ manually if you are using apt.
31
33
 
32
34
  More explicit instructions for NMatrix and SciRuby should
33
35
  be available on the SciRuby website, sciruby.com, or
@@ -47,7 +49,7 @@ EOF
47
49
 
48
50
  gem.required_ruby_version = '>= 1.9.2'
49
51
 
50
- #gem.add_dependency 'csquare', '~>0.0.2'
52
+ gem.add_dependency 'rdoc', '>=4.0.1'
51
53
 
52
54
  gem.add_development_dependency 'rake', '~>0.9'
53
55
  gem.add_development_dependency 'bundler'
@@ -1,5 +1,5 @@
1
1
  #!/bin/bash
2
- VERSION="4.7.1"
2
+ VERSION="4.7.2"
3
3
  PREFIX="/usr/gcc-${VERSION}"
4
4
  LANGUAGES="c,c++,fortran"
5
5
  MAKE="make -j 4"
@@ -31,7 +31,10 @@ require File.join(File.dirname(__FILE__), "spec_helper.rb")
31
31
  describe NMatrix::BLAS do
32
32
  [:rational32, :rational64, :rational128, :float32, :float64, :complex64, :complex128].each do |dtype|
33
33
  context dtype do
34
- it "exposes cblas trsm" do
34
+ # This is not the same as "exposes cblas trsm", which would be for a version defined in blas.rb (which
35
+ # would greatly simplify the calling of cblas_trsm in terms of arguments, and which would be accessible
36
+ # as NMatrix::BLAS::trsm)
37
+ it "exposes unfriendly cblas_trsm" do
35
38
  a = NMatrix.new(:dense, 3, [4,-1.quo(2), -3.quo(4), -2, 2, -1.quo(4), -4, -2, -1.quo(2)], dtype)
36
39
  b = NVector.new(3, [-1, 17, -9], dtype)
37
40
  NMatrix::BLAS::cblas_trsm(:row, :right, :lower, :transpose, :nonunit, 1, 3, 1.0, a, 3, b, 3)
@@ -64,7 +67,7 @@ describe NMatrix::BLAS do
64
67
 
65
68
  [:float32, :float64].each do |dtype|
66
69
  context dtype do
67
- it "exposes cblas rot" do
70
+ it "exposes unfriendly cblas_rot" do
68
71
  x = NVector.new(5, [1,2,3,4,5], dtype)
69
72
  y = NVector.new(5, [-5,-4,-3,-2,-1], dtype)
70
73
  NMatrix::BLAS::cblas_rot(5, x, 1, y, -1, 0.5, Math.sqrt(3)/2)
@@ -82,6 +85,24 @@ describe NMatrix::BLAS do
82
85
  y[4].should be_within(1e-4).of(-1.3660254037844386)
83
86
  end
84
87
 
88
+ it "exposes cblas rot" do
89
+ x = NVector.new(5, [1,2,3,4,5], dtype)
90
+ y = NVector.new(5, [-5,-4,-3,-2,-1], dtype)
91
+ x, y = NMatrix::BLAS::rot(x, y, 0.5, Math.sqrt(3)/2, -1)
92
+
93
+ x[0].should be_within(1e-4).of(-0.3660254037844386)
94
+ x[1].should be_within(1e-4).of(-0.7320508075688772)
95
+ x[2].should be_within(1e-4).of(-1.098076211353316)
96
+ x[3].should be_within(1e-4).of(-1.4641016151377544)
97
+ x[4].should be_within(1e-4).of(-1.8301270189221928)
98
+
99
+ y[0].should be_within(1e-4).of(-6.830127018922193)
100
+ y[1].should be_within(1e-4).of(-5.464101615137754)
101
+ y[2].should be_within(1e-4).of(-4.098076211353316)
102
+ y[3].should be_within(1e-4).of(-2.732050807568877)
103
+ y[4].should be_within(1e-4).of(-1.3660254037844386)
104
+ end
105
+
85
106
  # FIXME: Need to write new Rational algorithm, which doesn't choke quite so often on irrational square roots (which often eventually cancel).
86
107
  it "exposes cblas rotg" do
87
108
  ab = NVector.new(2, [6,-8], dtype)
@@ -94,4 +115,61 @@ describe NMatrix::BLAS do
94
115
 
95
116
  end
96
117
  end
118
+
119
+ [:float32, :float64, :complex64, :complex128].each do |dtype|
120
+ context dtype do
121
+
122
+ # Note: this exposes gemm, not cblas_gemm (which is the unfriendly CBLAS no-error-checking version)
123
+ it "exposes gemm" do
124
+ #STDERR.puts "dtype=#{dtype.to_s}"
125
+ #STDERR.puts "1"
126
+ n = NMatrix.new([4,3], dtype)
127
+ n[0,0] = 14.0
128
+ n[0,1] = 9.0
129
+ n[0,2] = 3.0
130
+ n[1,0] = 2.0
131
+ n[1,1] = 11.0
132
+ n[1,2] = 15.0
133
+ n[2,0] = 0.0
134
+ n[2,1] = 12.0
135
+ n[2,2] = 17.0
136
+ n[3,0] = 5.0
137
+ n[3,1] = 2.0
138
+ n[3,2] = 3.0
139
+
140
+ m = NMatrix.new([3,2], dtype)
141
+
142
+ m[0,0] = 12.0
143
+ m[0,1] = 25.0
144
+ m[1,0] = 9.0
145
+ m[1,1] = 10.0
146
+ m[2,0] = 8.0
147
+ m[2,1] = 5.0
148
+
149
+ #c = NMatrix.new([4,2], dtype)
150
+ r = NMatrix::BLAS.gemm(n, m) #, c)
151
+ #c.should equal(r) # check that both are same memory address
152
+
153
+ r[0,0].should == 273.0
154
+ r[0,1].should == 455.0
155
+ r[1,0].should == 243.0
156
+ r[1,1].should == 235.0
157
+ r[2,0].should == 244.0
158
+ r[2,1].should == 205.0
159
+ r[3,0].should == 102.0
160
+ r[3,1].should == 160.0
161
+ end
162
+
163
+
164
+ it "exposes gemv" do
165
+ #a = NMatrix.random(3)
166
+ #x = NVector.random(3)
167
+ 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], :float64)
168
+ x = NVector.new(3, [2.0, 1.0, 0.0], :float64)
169
+
170
+ NMatrix::BLAS.gemv(a, x)
171
+ end
172
+
173
+ end
174
+ end
97
175
  end
@@ -56,39 +56,49 @@ describe "math" do
56
56
  end
57
57
  end
58
58
 
59
- [:float32, :float64, :complex64, :complex128].each do |dtype|
60
- context dtype do
59
+ # TODO: Get it working with ROBJ too
60
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
61
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
62
+
63
+ # Won't work if they're both 1-byte, due to overflow.
64
+ next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
61
65
 
62
- # Note: this exposes gemm, not cblas_gemm (which is the unfriendly CBLAS no-error-checking version)
63
- it "exposes gemm" do
66
+ # For now, don't bother testing int-int mult.
67
+ #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
68
+ it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
64
69
  #STDERR.puts "dtype=#{dtype.to_s}"
65
- #STDERR.puts "1"
66
- n = NMatrix.new([4,3], dtype)
67
- n[0,0] = 14.0
68
- n[0,1] = 9.0
69
- n[0,2] = 3.0
70
- n[1,0] = 2.0
71
- n[1,1] = 11.0
72
- n[1,2] = 15.0
73
- n[2,0] = 0.0
74
- n[2,1] = 12.0
75
- n[2,2] = 17.0
76
- n[3,0] = 5.0
77
- n[3,1] = 2.0
78
- n[3,2] = 3.0
79
-
80
- m = NMatrix.new([3,2], dtype)
81
-
82
- m[0,0] = 12.0
83
- m[0,1] = 25.0
84
- m[1,0] = 9.0
85
- m[1,1] = 10.0
86
- m[2,0] = 8.0
87
- m[2,1] = 5.0
88
-
89
- #c = NMatrix.new([4,2], dtype)
90
- r = NMatrix::BLAS.gemm(n, m) #, c)
91
- #c.should equal(r) # check that both are same memory address
70
+ #STDERR.puts "2"
71
+
72
+ nary = if left_dtype.to_s =~ /complex/
73
+ COMPLEX_MATRIX43A_ARRAY
74
+ elsif left_dtype.to_s =~ /rational/
75
+ RATIONAL_MATRIX43A_ARRAY
76
+ else
77
+ MATRIX43A_ARRAY
78
+ end
79
+
80
+ mary = if right_dtype.to_s =~ /complex/
81
+ COMPLEX_MATRIX32A_ARRAY
82
+ elsif right_dtype.to_s =~ /rational/
83
+ RATIONAL_MATRIX32A_ARRAY
84
+ else
85
+ MATRIX32A_ARRAY
86
+ end
87
+
88
+ n = NMatrix.new([4,3], nary, left_dtype)
89
+ m = NMatrix.new([3,2], mary, right_dtype)
90
+
91
+ m.shape[0].should == 3
92
+ m.shape[1].should == 2
93
+ m.dim.should == 2
94
+
95
+ n.shape[0].should == 4
96
+ n.shape[1].should == 3
97
+ n.dim.should == 2
98
+
99
+ n.shape[1].should == m.shape[0]
100
+
101
+ r = n.dot m
92
102
 
93
103
  r[0,0].should == 273.0
94
104
  r[0,1].should == 455.0
@@ -98,8 +108,44 @@ describe "math" do
98
108
  r[2,1].should == 205.0
99
109
  r[3,0].should == 102.0
100
110
  r[3,1].should == 160.0
111
+
112
+ #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32
101
113
  end
114
+ end
115
+ end
102
116
 
117
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
118
+ [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
119
+
120
+ # Won't work if they're both 1-byte, due to overflow.
121
+ next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
122
+
123
+ it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} vector multiplication" do
124
+ #STDERR.puts "dtype=#{dtype.to_s}"
125
+ #STDERR.puts "2"
126
+ n = 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], left_dtype)
127
+
128
+ m = NVector.new(3, [2.0, 1.0, 0.0], right_dtype)
129
+
130
+ m.shape[0].should == 3
131
+ m.shape[1].should == 1
132
+
133
+ n.shape[0].should == 4
134
+ n.shape[1].should == 3
135
+ n.dim.should == 2
136
+
137
+ n.shape[1].should == m.shape[0]
138
+
139
+ r = n.dot m
140
+ # r.class.should == NVector
141
+
142
+ r[0,0].should == 4
143
+ r[1,0].should == 13
144
+ r[2,0].should == 22
145
+ r[3,0].should == 31
146
+
147
+ #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32
148
+ end
103
149
  end
104
150
  end
105
- end
151
+ end
@@ -28,68 +28,68 @@ require "./lib/nmatrix"
28
28
 
29
29
  describe NMatrix do
30
30
  context :list do
31
- it "should compare with ==" do
32
- n = NMatrix.new(:list, [3,3,3], :int64)
33
- m = NMatrix.new(:list, [3,3,3], :int64)
34
- n.should == m
35
- n[0,0,0] = 5
36
- n.should_not == m
37
- n[0,0,1] = 52
38
- n[1,2,1] = -4
31
+ it "should compare with ==" do
32
+ n = NMatrix.new(:list, [3,3,3], :int64)
33
+ m = NMatrix.new(:list, [3,3,3], :int64)
34
+ n.should == m
35
+ n[0,0,0] = 5
36
+ n.should_not == m
37
+ n[0,0,1] = 52
38
+ n[1,2,1] = -4
39
39
 
40
- m[0,0,0] = 5
41
- m[0,0,1] = 52
42
- m[1,2,1] = -4
43
- n.should == m
44
- end
40
+ m[0,0,0] = 5
41
+ m[0,0,1] = 52
42
+ m[1,2,1] = -4
43
+ n.should == m
44
+ end
45
45
 
46
- it "should handle missing default value" do
47
- NMatrix.new(:list, 3, :int8)[0,0].should == 0
48
- NMatrix.new(:list, 4, :float64)[0,0].should == 0.0
49
- end
46
+ it "should handle missing default value" do
47
+ NMatrix.new(:list, 3, :int8)[0,0].should == 0
48
+ NMatrix.new(:list, 4, :float64)[0,0].should == 0.0
49
+ end
50
50
 
51
- it "should allow conversion to a Ruby Hash" do
52
- n = NMatrix.new(:list, 3, 1, :int64)
53
- n[0,1] = 50
54
- h = n.to_h
55
- h.size.should == 1
56
- h[0].size.should == 1
57
- h[0][1].should == 50
58
- h[0][2].should == 1
59
- h[1][0].should == 1
60
- end
51
+ it "should allow conversion to a Ruby Hash" do
52
+ n = NMatrix.new(:list, 3, 1, :int64)
53
+ n[0,1] = 50
54
+ h = n.to_h
55
+ h.size.should == 1
56
+ h[0].size.should == 1
57
+ h[0][1].should == 50
58
+ h[0][2].should == 1
59
+ h[1][0].should == 1
60
+ end
61
61
 
62
62
 
63
- ##TODO: Make this test better. It's not nearly exhaustive enough as is.
64
- it "should handle recursive removal" do
65
- n = NMatrix.new(:list, [3,3,3], 0)
66
- n[0,0,0] = 2
67
- n[1,1,1] = 1
68
- n[1,0,0] = 3
69
- n[0,0,1] = 4
63
+ ##TODO: Make this test better. It's not nearly exhaustive enough as is.
64
+ it "should handle recursive removal" do
65
+ n = NMatrix.new(:list, [3,3,3], 0)
66
+ n[0,0,0] = 2
67
+ n[1,1,1] = 1
68
+ n[1,0,0] = 3
69
+ n[0,0,1] = 4
70
70
 
71
- n[0,0,0].should == 2
72
- n[1,1,1].should == 1
73
- n[1,0,0].should == 3
74
- n[0,0,1].should == 4
71
+ n[0,0,0].should == 2
72
+ n[1,1,1].should == 1
73
+ n[1,0,0].should == 3
74
+ n[0,0,1].should == 4
75
75
 
76
- n[1,1,1] = 0
77
- n[0,0,0].should == 2
78
- n[1,1,1].should == 0
79
- n[1,0,0].should == 3
80
- n[0,0,1].should == 4
81
- end
76
+ n[1,1,1] = 0
77
+ n[0,0,0].should == 2
78
+ n[1,1,1].should == 0
79
+ n[1,0,0].should == 3
80
+ n[0,0,1].should == 4
81
+ end
82
82
 
83
- it "should correctly insert a value between the middle and last entries of a three-element list" do
84
- n = NMatrix.new(:list, 5940, 0, :float64)
85
- n[0,0] = -7.0710685196786e-01
86
- n[330,0] = 7.0710685196786e-01
87
- n[1,0] = -7.0710685196786e-01
88
- n[2,0] = -7.0710685196786e-01
89
- n[0,0].should_not == 0
90
- n[330,0].should_not == 0
91
- n[2,0].should_not == 0
92
- n[1,0].should_not == 0
93
- end
83
+ it "should correctly insert a value between the middle and last entries of a three-element list" do
84
+ n = NMatrix.new(:list, 5940, 0, :float64)
85
+ n[0,0] = -7.0710685196786e-01
86
+ n[330,0] = 7.0710685196786e-01
87
+ n[1,0] = -7.0710685196786e-01
88
+ n[2,0] = -7.0710685196786e-01
89
+ n[0,0].should_not == 0
90
+ n[330,0].should_not == 0
91
+ n[2,0].should_not == 0
92
+ n[1,0].should_not == 0
93
+ end
94
94
  end
95
95
  end
@@ -42,14 +42,14 @@ describe NMatrix do
42
42
 
43
43
  it "allows stype casting of a dim 2 matrix between dense, sparse, and list (different dtypes)" do
44
44
  m = NMatrix.new(:dense, [3,3], [0,0,1,0,2,0,3,4,5], :int64).
45
- cast(:yale, :int32).
46
- cast(:dense, :float64).
47
- cast(:list, :int32).
48
- cast(:dense, :int16).
49
- cast(:list, :int32).
50
- cast(:yale, :int64) #.
51
- #cast(:list, :int32).
52
- #cast(:dense, :int16)
45
+ cast(:yale, :int32).
46
+ cast(:dense, :float64).
47
+ cast(:list, :int32).
48
+ cast(:dense, :int16).
49
+ cast(:list, :int32).
50
+ cast(:yale, :int64) #.
51
+ #cast(:list, :int32).
52
+ #cast(:dense, :int16)
53
53
  #m.should.equal?(original)
54
54
  # For some reason this causes some weird garbage collector problems when we uncomment these. The above lines won't
55
55
  # work at all in IRB, but work fine when run in a regular Ruby session.
@@ -139,99 +139,6 @@ describe NMatrix do
139
139
  n.pretty_print
140
140
  end
141
141
 
142
- # TODO: Get it working with ROBJ too
143
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
144
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
145
-
146
- # Won't work if they're both 1-byte, due to overflow.
147
- next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
148
-
149
- # For now, don't bother testing int-int mult.
150
- #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype)
151
- it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do
152
- #STDERR.puts "dtype=#{dtype.to_s}"
153
- #STDERR.puts "2"
154
-
155
- nary = if left_dtype.to_s =~ /complex/
156
- COMPLEX_MATRIX43A_ARRAY
157
- elsif left_dtype.to_s =~ /rational/
158
- RATIONAL_MATRIX43A_ARRAY
159
- else
160
- MATRIX43A_ARRAY
161
- end
162
-
163
- mary = if right_dtype.to_s =~ /complex/
164
- COMPLEX_MATRIX32A_ARRAY
165
- elsif right_dtype.to_s =~ /rational/
166
- RATIONAL_MATRIX32A_ARRAY
167
- else
168
- MATRIX32A_ARRAY
169
- end
170
-
171
- n = NMatrix.new([4,3], nary, left_dtype)
172
- m = NMatrix.new([3,2], mary, right_dtype)
173
-
174
- m.shape[0].should == 3
175
- m.shape[1].should == 2
176
- m.dim.should == 2
177
-
178
- n.shape[0].should == 4
179
- n.shape[1].should == 3
180
- n.dim.should == 2
181
-
182
- n.shape[1].should == m.shape[0]
183
-
184
- r = n.dot m
185
-
186
- r[0,0].should == 273.0
187
- r[0,1].should == 455.0
188
- r[1,0].should == 243.0
189
- r[1,1].should == 235.0
190
- r[2,0].should == 244.0
191
- r[2,1].should == 205.0
192
- r[3,0].should == 102.0
193
- r[3,1].should == 160.0
194
-
195
- #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32
196
- end
197
- end
198
- end
199
-
200
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |left_dtype|
201
- [:byte,:int8,:int16,:int32,:int64,:float32,:float64,:rational64,:rational128].each do |right_dtype|
202
-
203
- # Won't work if they're both 1-byte, due to overflow.
204
- next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype)
205
-
206
- it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} vector multiplication" do
207
- #STDERR.puts "dtype=#{dtype.to_s}"
208
- #STDERR.puts "2"
209
- n = 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], left_dtype)
210
-
211
- m = NVector.new(3, [2.0, 1.0, 0.0], right_dtype)
212
-
213
- m.shape[0].should == 3
214
- m.shape[1].should == 1
215
-
216
- n.shape[0].should == 4
217
- n.shape[1].should == 3
218
- n.dim.should == 2
219
-
220
- n.shape[1].should == m.shape[0]
221
-
222
- r = n.dot m
223
- # r.class.should == NVector
224
-
225
- r[0,0].should == 4
226
- r[1,0].should == 13
227
- r[2,0].should == 22
228
- r[3,0].should == 31
229
-
230
- #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32
231
- end
232
- end
233
- end
234
-
235
142
 
236
143
  [:dense, :list, :yale].each do |storage_type|
237
144
  context storage_type do
@@ -274,6 +181,51 @@ describe NMatrix do
274
181
  n[0,1].should == 1
275
182
  end
276
183
 
184
+ # Tests Ruby object versus any C dtype (in this case we use :int64)
185
+ [:object, :int64].each do |dtype|
186
+ c = dtype == :object ? "Ruby object" : "non-Ruby object"
187
+ context c do
188
+ it "allows iteration of matrices" do
189
+ pending("yale and list not implemented yet") unless storage_type == :dense
190
+ n = NMatrix.new(:dense, [3,3], [1,2,3,4,5,6,7,8,9], dtype)
191
+ n.each do |x|
192
+ puts x
193
+ end
194
+ end
195
+
196
+ it "allows storage-based iteration of matrices" do
197
+ n = storage_type == :yale ? NMatrix.new(storage_type, [3,3], dtype) : NMatrix.new(storage_type, [3,3], 0, dtype)
198
+ n[0,0] = 1
199
+ n[0,1] = 2
200
+ n[2,2] = 3
201
+ n[2,1] = 4
202
+
203
+ values = []
204
+ is = []
205
+ js = []
206
+ n.each_stored_with_indices do |v,i,j|
207
+ values << v
208
+ is << i
209
+ js << j
210
+ end
211
+
212
+ if storage_type == :yale
213
+ values.should == [1,0,3,2,4]
214
+ is.should == [0,1,2,0,2]
215
+ js.should == [0,1,2,1,1]
216
+ elsif storage_type == :list
217
+ values.should == [1,2,4,3]
218
+ is.should == [0,0,2,2]
219
+ js.should == [0,1,1,2]
220
+ elsif storage_type == :dense
221
+ values.should == [1,2,0,0,0,0,0,4,3]
222
+ is.should == [0,0,0,1,1,1,2,2,2]
223
+ js.should == [0,1,2,0,1,2,0,1,2]
224
+ end
225
+ end
226
+ end
227
+ end
228
+
277
229
  end
278
230
 
279
231
  # dense and list, not yale
@@ -288,7 +240,7 @@ describe NMatrix do
288
240
  NMatrix.new(storage_type, [3,2,8], 0).shape.should == [3,2,8]
289
241
  NMatrix.new(storage_type, [3,2,8], 0).dim.should == 3
290
242
  end
291
-
243
+
292
244
  it "returns number of rows and columns" do
293
245
  NMatrix.new(storage_type, [7, 4], 3).rows.should == 7
294
246
  NMatrix.new(storage_type, [7, 4], 3).cols.should == 4
@@ -302,20 +254,6 @@ describe NMatrix do
302
254
  lambda { NMatrix.new(3,:int8)[1,1] }.should_not raise_error
303
255
  end
304
256
 
305
- it "allows iteration of Ruby object matrices" do
306
- n = NMatrix.new(:dense, [3,3], [1,2,3,4,5,6,7,8,9], :object)
307
- n.each do |x|
308
- puts x
309
- end
310
- end
311
-
312
- it "allows iteration of non-Ruby object matrices" do
313
- n = NMatrix.new(:dense, [3,3], [1,2,3,4,5,6,7,8,9], :int64)
314
- n.each do |x|
315
- puts x
316
- end
317
- end
318
-
319
257
  it "calculates the complex conjugate in-place" do
320
258
  n = NMatrix.new(:dense, 3, [1,2,3,4,5,6,7,8,9], :complex128)
321
259
  n.complex_conjugate!
@@ -324,7 +262,7 @@ describe NMatrix do
324
262
 
325
263
  it "converts from list to yale properly" do
326
264
  m = NMatrix.new(:list, 3, 0)
327
- m[0,2] = 333
265
+ m[0,2] = 333
328
266
  m[2,2] = 777
329
267
  n = m.cast(:yale, :int32)
330
268
  puts n.capacity
@@ -353,4 +291,9 @@ describe NMatrix do
353
291
  rescue StopIteration
354
292
  end
355
293
  end
294
+
295
+ it "should iterate through element 256 without a segfault" do
296
+ t = NVector.random(256)
297
+ t.each { |x| x + 0 }
298
+ end
356
299
  end