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.
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +1 -1
- data/History.txt +68 -10
- data/LICENSE.txt +2 -2
- data/Manifest.txt +2 -0
- data/README.rdoc +90 -69
- data/Rakefile +18 -9
- data/ext/nmatrix/data/complex.h +7 -7
- data/ext/nmatrix/data/data.cpp +2 -7
- data/ext/nmatrix/data/data.h +7 -4
- data/ext/nmatrix/data/rational.h +2 -2
- data/ext/nmatrix/data/ruby_object.h +3 -10
- data/ext/nmatrix/extconf.rb +79 -54
- data/ext/nmatrix/new_extconf.rb +11 -12
- data/ext/nmatrix/nmatrix.cpp +94 -125
- data/ext/nmatrix/nmatrix.h +38 -17
- data/ext/nmatrix/ruby_constants.cpp +2 -15
- data/ext/nmatrix/ruby_constants.h +2 -14
- data/ext/nmatrix/storage/common.cpp +2 -2
- data/ext/nmatrix/storage/common.h +2 -2
- data/ext/nmatrix/storage/dense.cpp +206 -31
- data/ext/nmatrix/storage/dense.h +5 -2
- data/ext/nmatrix/storage/list.cpp +52 -4
- data/ext/nmatrix/storage/list.h +3 -2
- data/ext/nmatrix/storage/storage.cpp +6 -6
- data/ext/nmatrix/storage/storage.h +2 -2
- data/ext/nmatrix/storage/yale.cpp +202 -49
- data/ext/nmatrix/storage/yale.h +5 -4
- data/ext/nmatrix/ttable_helper.rb +108 -108
- data/ext/nmatrix/types.h +2 -15
- data/ext/nmatrix/util/io.cpp +2 -2
- data/ext/nmatrix/util/io.h +2 -2
- data/ext/nmatrix/util/lapack.h +2 -2
- data/ext/nmatrix/util/math.cpp +14 -14
- data/ext/nmatrix/util/math.h +2 -2
- data/ext/nmatrix/util/sl_list.cpp +2 -2
- data/ext/nmatrix/util/sl_list.h +2 -2
- data/ext/nmatrix/util/util.h +2 -2
- data/lib/nmatrix.rb +13 -35
- data/lib/nmatrix/blas.rb +182 -56
- data/lib/nmatrix/io/market.rb +38 -14
- data/lib/nmatrix/io/mat5_reader.rb +393 -278
- data/lib/nmatrix/io/mat_reader.rb +121 -107
- data/lib/nmatrix/lapack.rb +59 -14
- data/lib/nmatrix/monkeys.rb +32 -30
- data/lib/nmatrix/nmatrix.rb +204 -100
- data/lib/nmatrix/nvector.rb +166 -57
- data/lib/nmatrix/shortcuts.rb +364 -231
- data/lib/nmatrix/version.rb +8 -4
- data/nmatrix.gemspec +5 -3
- data/scripts/mac-brew-gcc.sh +1 -1
- data/spec/blas_spec.rb +80 -2
- data/spec/math_spec.rb +78 -32
- data/spec/nmatrix_list_spec.rb +55 -55
- data/spec/nmatrix_spec.rb +60 -117
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +214 -198
- data/spec/nvector_spec.rb +58 -2
- data/spec/shortcuts_spec.rb +156 -32
- data/spec/slice_spec.rb +229 -178
- data/spec/spec_helper.rb +2 -2
- metadata +71 -21
data/lib/nmatrix/version.rb
CHANGED
@@ -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 -
|
12
|
-
# NMatrix is Copyright (c)
|
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
|
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
|
|
data/nmatrix.gemspec
CHANGED
@@ -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
|
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
|
-
|
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'
|
data/scripts/mac-brew-gcc.sh
CHANGED
data/spec/blas_spec.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
data/spec/math_spec.rb
CHANGED
@@ -56,39 +56,49 @@ describe "math" do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
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
|
-
#
|
63
|
-
|
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 "
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
m[
|
85
|
-
|
86
|
-
m[
|
87
|
-
m[
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
data/spec/nmatrix_list_spec.rb
CHANGED
@@ -28,68 +28,68 @@ require "./lib/nmatrix"
|
|
28
28
|
|
29
29
|
describe NMatrix do
|
30
30
|
context :list do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
data/spec/nmatrix_spec.rb
CHANGED
@@ -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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|