spec/math_spec.rb in nmatrix-fftw-0.2.3 vs spec/math_spec.rb in nmatrix-fftw-0.2.4
- old
+ new
@@ -97,18 +97,18 @@
@a = @m.to_a.flatten
end
[:asin, :acos, :atan, :atanh].each do |atf|
it "should correctly apply elementwise #{atf}" do
- expect(@m.send(atf)).to eq N.new(@size,
+ expect(@m.send(atf)).to eq N.new(@size,
@a.map{ |e| Math.send(atf, e) },
dtype: :float64, stype: stype)
end
end
it "should correctly apply elementtwise atan2" do
- expect(@m.atan2(@m*0+1)).to eq N.new(@size,
+ expect(@m.atan2(@m*0+1)).to eq N.new(@size,
@a.map { |e| Math.send(:atan2, e, 1) }, dtype: :float64, stype: stype)
end
it "should correctly apply elementwise atan2 with a scalar first arg" do
expect(Math.atan2(1, @m)).to eq N.new(@size, @a.map { |e| Math.send(:atan2, 1, e) }, dtype: :float64, stype: stype)
@@ -118,25 +118,26 @@
expect(@m.atan2(1)).to eq N.new(@size, @a.map { |e| Math.send(:atan2, e, 1) }, dtype: :float64, stype: stype)
end
end
end
end
-
- context "Floor and ceil for #{stype}" do
+ context "Floor and ceil for #{stype}" do
+
[:floor, :ceil].each do |meth|
ALL_DTYPES.each do |dtype|
context dtype do
before :each do
@size = [2,2]
- @m = NMatrix.seq(@size, dtype: dtype, stype: stype)+1
+ @m = NMatrix.seq(@size, dtype: dtype, stype: stype)+1 unless jruby? and dtype == :object
@a = @m.to_a.flatten
end
if dtype.to_s.match(/int/) or [:byte, :object].include?(dtype)
it "should return #{dtype} for #{dtype}" do
-
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+
expect(@m.send(meth)).to eq N.new(@size, @a.map { |e| e.send(meth) }, dtype: dtype, stype: stype)
if dtype == :object
expect(@m.send(meth).dtype).to eq :object
else
@@ -145,15 +146,16 @@
end
elsif dtype.to_s.match(/float/)
it "should return dtype int64 for #{dtype}" do
expect(@m.send(meth)).to eq N.new(@size, @a.map { |e| e.send(meth) }, dtype: dtype, stype: stype)
-
+
expect(@m.send(meth).dtype).to eq :int64
end
- elsif dtype.to_s.match(/complex/)
+ elsif dtype.to_s.match(/complex/)
it "should properly calculate #{meth} for #{dtype}" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
expect(@m.send(meth)).to eq N.new(@size, @a.map { |e| e = Complex(e.real.send(meth), e.imag.send(meth)) }, dtype: dtype, stype: stype)
expect(@m.send(meth).dtype).to eq :complex64 if dtype == :complex64
expect(@m.send(meth).dtype).to eq :complex128 if dtype == :complex128
@@ -167,45 +169,48 @@
context "#round for #{stype}" do
ALL_DTYPES.each do |dtype|
context dtype do
before :each do
@size = [2,2]
- @mat = NMatrix.new @size, [1.33334, 0.9998, 1.9999, -8.9999],
+ @mat = NMatrix.new @size, [1.33334, 0.9998, 1.9999, -8.9999],
dtype: dtype, stype: stype
- @ans = @mat.to_a.flatten
+ @ans = @mat.to_a.flatten unless jruby? and dtype == :object
end
it "rounds" do
- expect(@mat.round).to eq(N.new(@size, @ans.map { |a| a.round},
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+ expect(@mat.round).to eq(N.new(@size, @ans.map { |a| a.round},
dtype: dtype, stype: stype))
end unless(/complex/ =~ dtype)
it "rounds with args" do
- expect(@mat.round(2)).to eq(N.new(@size, @ans.map { |a| a.round(2)},
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ expect(@mat.round(2)).to eq(N.new(@size, @ans.map { |a| a.round(2)},
dtype: dtype, stype: stype))
end unless(/complex/ =~ dtype)
it "rounds complex with args" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
puts @mat.round(2)
- expect(@mat.round(2)).to be_within(0.0001).of(N.new [2,2], @ans.map {|a|
+ expect(@mat.round(2)).to be_within(0.0001).of(N.new [2,2], @ans.map {|a|
Complex(a.real.round(2), a.imag.round(2))},dtype: dtype, stype: stype)
end if(/complex/ =~ dtype)
it "rounds complex" do
- expect(@mat.round).to eq(N.new [2,2], @ans.map {|a|
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ expect(@mat.round).to eq(N.new [2,2], @ans.map {|a|
Complex(a.real.round, a.imag.round)},dtype: dtype, stype: stype)
end if(/complex/ =~ dtype)
end
end
end
-
+
end
end
end
NON_INTEGER_DTYPES.each do |dtype|
- next if dtype == :object
context dtype do
before do
@m = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype)
@err = case dtype
when :float32, :complex64
@@ -215,15 +220,20 @@
end
end
#haven't check this spec yet. Also it doesn't check all the elements of the matrix.
it "should correctly factorize a matrix" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
a = @m.factorize_lu
expect(a).to be_within(@err).of(NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype))
end
it "also returns the permutation matrix" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+
a, p = @m.factorize_lu perm_matrix: true
expect(a).to be_within(@err).of(NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype))
p_true = NMatrix.new([3,3], [0,0,1,1,0,0,0,1,0], dtype: dtype)
@@ -231,21 +241,22 @@
end
end
end
NON_INTEGER_DTYPES.each do |dtype|
- next if dtype == :object
context dtype do
it "calculates cholesky decomposition using potrf (lower)" do
#a = NMatrix.new([3,3],[1,1,1, 1,2,2, 1,2,6], dtype: dtype)
# We use the matrix
# 1 1 1
# 1 2 2
# 1 2 6
# which is symmetric and positive-definite as required, but
# we need only store the lower-half of the matrix.
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ pending("not yet implemented for :object dtype") if dtype == :object
a = NMatrix.new([3,3],[1,0,0, 1,2,0, 1,2,6], dtype: dtype)
begin
r = a.potrf!(:lower)
b = NMatrix.new([3,3],[1,0,0, 1,1,0, 1,1,2], dtype: dtype)
@@ -255,10 +266,13 @@
pending "potrf! not implemented without plugins"
end
end
it "calculates cholesky decomposition using potrf (upper)" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+
a = NMatrix.new([3,3],[1,1,1, 0,2,2, 0,0,6], dtype: dtype)
begin
r = a.potrf!(:upper)
b = NMatrix.new([3,3],[1,1,1, 0,1,1, 0,0,2], dtype: dtype)
@@ -268,10 +282,11 @@
pending "potrf! not implemented without plugins"
end
end
it "calculates cholesky decomposition using #factorize_cholesky" do
+ pending("not yet implemented for :object dtype") if dtype == :object
a = NMatrix.new([3,3],[1,2,1, 2,13,5, 1,5,6], dtype: dtype)
begin
u,l = a.factorize_cholesky
l_true = NMatrix.new([3,3],[1,0,0, 2,3,0, 1,1,2], dtype: dtype)
@@ -284,140 +299,143 @@
end
end
end
NON_INTEGER_DTYPES.each do |dtype|
- next if dtype == :object
context dtype do
-
- it "calculates QR decomposition using factorize_qr for a square matrix" do
- a = NMatrix.new(3, [12.0, -51.0, 4.0,
- 6.0, 167.0, -68.0,
+ it "calculates QR decomposition using factorize_qr for a square matrix" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ a = NMatrix.new(3, [12.0, -51.0, 4.0,
+ 6.0, 167.0, -68.0,
-4.0, 24.0, -41.0] , dtype: dtype)
-
+
q_solution = NMatrix.new([3,3], Q_SOLUTION_ARRAY_2, dtype: dtype)
- r_solution = NMatrix.new([3,3], [-14.0, -21.0, 14,
- 0.0, -175, 70,
+ r_solution = NMatrix.new([3,3], [-14.0, -21.0, 14,
+ 0.0, -175, 70,
0.0, 0.0, -35] , dtype: dtype)
err = case dtype
when :float32, :complex64
1e-4
when :float64, :complex128
1e-13
end
-
+
begin
q,r = a.factorize_qr
-
+
expect(q).to be_within(err).of(q_solution)
expect(r).to be_within(err).of(r_solution)
-
+
rescue NotImplementedError
pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
end
end
it "calculates QR decomposition using factorize_qr for a tall and narrow rectangular matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ pending("not yet implemented for :object dtype") if dtype == :object
- a = NMatrix.new([4,2], [34.0, 21.0,
- 23.0, 53.0,
- 26.0, 346.0,
+ a = NMatrix.new([4,2], [34.0, 21.0,
+ 23.0, 53.0,
+ 26.0, 346.0,
23.0, 121.0] , dtype: dtype)
-
+
q_solution = NMatrix.new([4,4], Q_SOLUTION_ARRAY_1, dtype: dtype)
- r_solution = NMatrix.new([4,2], [-53.75872022286244, -255.06559574252242,
- 0.0, 269.34836526051555,
- 0.0, 0.0,
+ r_solution = NMatrix.new([4,2], [-53.75872022286244, -255.06559574252242,
+ 0.0, 269.34836526051555,
+ 0.0, 0.0,
0.0, 0.0] , dtype: dtype)
err = case dtype
when :float32, :complex64
1e-4
when :float64, :complex128
1e-13
end
-
+
begin
q,r = a.factorize_qr
-
+
expect(q).to be_within(err).of(q_solution)
expect(r).to be_within(err).of(r_solution)
-
+
rescue NotImplementedError
pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
end
end
it "calculates QR decomposition using factorize_qr for a short and wide rectangular matrix" do
-
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ pending("not yet implemented for :object dtype") if dtype == :object
+
a = NMatrix.new([3,4], [123,31,57,81,92,14,17,36,42,34,11,28], dtype: dtype)
-
+
q_solution = NMatrix.new([3,3], Q_SOLUTION_ARRAY_3, dtype: dtype)
r_solution = NMatrix.new([3,4], R_SOLUTION_ARRAY, dtype: dtype)
err = case dtype
when :float32, :complex64
1e-4
when :float64, :complex128
1e-13
end
-
+
begin
q,r = a.factorize_qr
-
+
expect(q).to be_within(err).of(q_solution)
expect(r).to be_within(err).of(r_solution)
-
+
rescue NotImplementedError
pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
end
end
-
- it "calculates QR decomposition such that A - QR ~ 0" do
- a = NMatrix.new([3,3], [ 9.0, 0.0, 26.0,
- 12.0, 0.0, -7.0,
+ it "calculates QR decomposition such that A - QR ~ 0" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ a = NMatrix.new([3,3], [ 9.0, 0.0, 26.0,
+ 12.0, 0.0, -7.0,
0.0, 4.0, 0.0] , dtype: dtype)
-
+
err = case dtype
when :float32, :complex64
1e-4
when :float64, :complex128
1e-13
end
-
+
begin
q,r = a.factorize_qr
- a_expected = q.dot(r)
-
+ a_expected = q.dot(r)
+
expect(a_expected).to be_within(err).of(a)
-
+
rescue NotImplementedError
pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
end
end
it "calculates the orthogonal matrix Q in QR decomposition" do
-
+ pending("not yet implemented for :object dtype") if dtype == :object
a = N.new([2,2], [34.0, 21, 23, 53] , dtype: dtype)
err = case dtype
when :float32, :complex64
1e-4
when :float64, :complex128
1e-13
end
-
+
begin
q,r = a.factorize_qr
-
+
#Q is orthogonal if Q x Q.transpose = I
product = q.dot(q.transpose)
expect(product[0,0]).to be_within(err).of(1)
expect(product[1,0]).to be_within(err).of(0)
@@ -431,24 +449,24 @@
end
end
ALL_DTYPES.each do |dtype|
next if dtype == :byte #doesn't work for unsigned types
- next if dtype == :object
context dtype do
err = case dtype
when :float32, :complex64
1e-4
else #integer matrices will return :float64
1e-13
end
it "should correctly invert a matrix in place (bang)" do
- a = NMatrix.new(:dense, 5, [1, 8,-9, 7, 5,
- 0, 1, 0, 4, 4,
- 0, 0, 1, 2, 5,
+ pending("not yet implemented for :object dtype") if dtype == :object
+ a = NMatrix.new(:dense, 5, [1, 8,-9, 7, 5,
+ 0, 1, 0, 4, 4,
+ 0, 0, 1, 2, 5,
0, 0, 0, 1,-5,
0, 0, 0, 0, 1 ], dtype)
b = NMatrix.new(:dense, 5, [1,-8, 9, 7, 17,
0, 1, 0,-4,-24,
0, 0, 1,-2,-15,
@@ -462,37 +480,115 @@
expect(a).to be_within(err).of(b)
expect(r).to be_within(err).of(b)
end
end
- it "should correctly invert a matrix out-of-place" do
+
+ it "should correctly invert a dense matrix out-of-place" do
+ pending("not yet implemented for :object dtype") if dtype == :object
a = NMatrix.new(:dense, 3, [1,2,3,0,1,4,5,6,0], dtype)
if a.integer_dtype?
b = NMatrix.new(:dense, 3, [-24,18,5,20,-15,-4,-5,4,1], :float64)
else
b = NMatrix.new(:dense, 3, [-24,18,5,20,-15,-4,-5,4,1], dtype)
end
expect(a.invert).to be_within(err).of(b)
end
+
+ it "should correctly find exact inverse" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ a = NMatrix.new(:dense, 3, [1,2,3,0,1,4,5,6,0], dtype)
+ b = NMatrix.new(:dense, 3, [-24,18,5,20,-15,-4,-5,4,1], dtype)
+
+ expect(a.exact_inverse).to be_within(err).of(b)
+ end
+
+ it "should correctly find exact inverse" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ a = NMatrix.new(:dense, 2, [1,3,3,8], dtype)
+ b = NMatrix.new(:dense, 2, [-8,3,3,-1], dtype)
+
+ expect(a.exact_inverse).to be_within(err).of(b)
+ end
end
end
+ NON_INTEGER_DTYPES.each do |dtype|
+ context dtype do
+ err = Complex(1e-3, 1e-3)
+ it "should correctly invert a 2x2 matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ pending("not yet implemented for :object dtype") if dtype == :object
+ if dtype == :complex64 || dtype == :complex128
+ a = NMatrix.new([2, 2], [Complex(16, 81), Complex(91, 51), \
+ Complex(13, 54), Complex(71, 24)], dtype: dtype)
+ b = NMatrix.identity(2, dtype: dtype)
+
+ begin
+ expect(a.dot(a.pinv)).to be_within(err).of(b)
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the atlas plugin is not available"
+ end
+
+ else
+ a = NMatrix.new([2, 2], [141, 612, 9123, 654], dtype: dtype)
+ b = NMatrix.identity(2, dtype: dtype)
+
+ begin
+ expect(a.dot(a.pinv)).to be_within(err).of(b)
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the atlas plugin is not available"
+ end
+ end
+ end
+
+ it "should verify a.dot(b.dot(a)) == a and b.dot(a.dot(b)) == b" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ pending("not yet implemented for :object dtype") if dtype == :object
+ if dtype == :complex64 || dtype == :complex128
+ a = NMatrix.new([3, 2], [Complex(94, 11), Complex(87, 51), Complex(82, 39), \
+ Complex(45, 16), Complex(25, 32), Complex(91, 43) ], dtype: dtype)
+
+ begin
+ b = a.pinv # pseudo inverse
+ expect(a.dot(b.dot(a))).to be_within(err).of(a)
+ expect(b.dot(a.dot(b))).to be_within(err).of(b)
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the atlas plugin is not available"
+ end
+
+ else
+ a = NMatrix.new([3, 3], [9, 4, 52, 12, 52, 1, 3, 55, 6], dtype: dtype)
+
+ begin
+ b = a.pinv # pseudo inverse
+ expect(a.dot(b.dot(a))).to be_within(err).of(a)
+ expect(b.dot(a.dot(b))).to be_within(err).of(b)
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the atlas plugin is not available"
+ end
+ end
+ end
+ end
+ end
+
+
ALL_DTYPES.each do |dtype|
next if dtype == :byte #doesn't work for unsigned types
- next if dtype == :object
context dtype do
err = case dtype
when :float32, :complex64
1e-4
else #integer matrices will return :float64
1e-13
end
it "should correctly find adjugate a matrix in place (bang)" do
+ pending("not yet implemented for :object dtype") if dtype == :object
a = NMatrix.new(:dense, 2, [2, 3, 3, 5], dtype)
b = NMatrix.new(:dense, 2, [5, -3, -3, 2], dtype)
if a.integer_dtype?
expect{a.adjugate!}.to raise_error(DataTypeError)
@@ -504,10 +600,11 @@
end
end
it "should correctly find adjugate of a matrix out-of-place" do
+ pending("not yet implemented for :object dtype") if dtype == :object
a = NMatrix.new(:dense, 3, [-3, 2, -5, -1, 0, -2, 3, -4, 1], dtype)
if a.integer_dtype?
b = NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], :float64)
else
@@ -519,10 +616,11 @@
end
end
end
+
# TODO: Get it working with ROBJ too
[:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |left_dtype|
[:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |right_dtype|
# Won't work if they're both 1-byte, due to overflow.
@@ -611,60 +709,63 @@
end
ALL_DTYPES.each do |dtype|
next if integer_dtype?(dtype)
context "#cov dtype #{dtype}" do
- before do
+ before do
@n = NMatrix.new( [5,3], [4.0,2.0,0.60,
4.2,2.1,0.59,
3.9,2.0,0.58,
4.3,2.1,0.62,
4.1,2.2,0.63], dtype: dtype)
end
- it "calculates variance co-variance matrix (sample)" do
- expect(@n.cov).to be_within(0.0001).of(NMatrix.new([3,3],
+ it "calculates sample covariance matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+ expect(@n.cov).to be_within(0.0001).of(NMatrix.new([3,3],
[0.025 , 0.0075, 0.00175,
0.0075, 0.007 , 0.00135,
0.00175, 0.00135 , 0.00043 ], dtype: dtype)
)
end
- it "calculates variance co-variance matrix (population)" do
- expect(@n.cov(for_sample_data: false)).to be_within(0.0001).of(NMatrix.new([3,3],
+ it "calculates population covariance matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+ expect(@n.cov(for_sample_data: false)).to be_within(0.0001).of(NMatrix.new([3,3],
[2.0000e-02, 6.0000e-03, 1.4000e-03,
6.0000e-03, 5.6000e-03, 1.0800e-03,
1.4000e-03, 1.0800e-03, 3.4400e-04], dtype: dtype)
)
end
end
context "#corr #{dtype}" do
it "calculates the correlation matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
n = NMatrix.new([5,3], [4.0,2.0,0.60,
4.2,2.1,0.59,
3.9,2.0,0.58,
4.3,2.1,0.62,
4.1,2.2,0.63], dtype: dtype)
- expect(n.corr).to be_within(0.001).of(NMatrix.new([3,3],
+ expect(n.corr).to be_within(0.001).of(NMatrix.new([3,3],
[1.00000, 0.56695, 0.53374,
0.56695, 1.00000, 0.77813,
0.53374, 0.77813, 1.00000], dtype: dtype))
end unless dtype =~ /complex/
end
context "#symmetric? for #{dtype}" do
- it "should return true for symmetric matrix" do
+ it "should return true for symmetric matrix" do
n = NMatrix.new([3,3], [1.00000, 0.56695, 0.53374,
0.56695, 1.00000, 0.77813,
0.53374, 0.77813, 1.00000], dtype: dtype)
expect(n.symmetric?).to be_truthy
end
end
context "#hermitian? for #{dtype}" do
- it "should return true for complex hermitian or non-complex symmetric matrix" do
+ it "should return true for complex hermitian or non-complex symmetric matrix" do
n = NMatrix.new([3,3], [1.00000, 0.56695, 0.53374,
0.56695, 1.00000, 0.77813,
0.53374, 0.77813, 1.00000], dtype: dtype) unless dtype =~ /complex/
n = NMatrix.new([3,3], [1.1, Complex(1.2,1.3), Complex(1.4,1.5),
Complex(1.2,-1.3), 1.9, Complex(1.8,1.7),
@@ -673,10 +774,11 @@
end
end
context "#permute_columns for #{dtype}" do
it "check that #permute_columns works correctly by considering every premutation of a 3x3 matrix" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
n = NMatrix.new([3,3], [1,0,0,
0,2,0,
0,0,3], dtype: dtype)
expect(n.permute_columns([0,1,2], {convention: :intuitive})).to eq(NMatrix.new([3,3], [1,0,0,
0,2,0,
@@ -714,10 +816,11 @@
expect(n.permute_columns([2,1,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [0,0,1,
0,2,0,
3,0,0], dtype: dtype))
end
it "additional tests for #permute_columns with convention :intuitive" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
m = NMatrix.new([1,4], [0,1,2,3], dtype: dtype)
perm = [1,0,3,2]
expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1,4], perm, dtype: dtype))
m = NMatrix.new([1,5], [0,1,2,3,4], dtype: dtype)
@@ -739,20 +842,24 @@
end
end
context "#solve" do
NON_INTEGER_DTYPES.each do |dtype|
- next if dtype == :object # LU factorization doesnt work for :object yet
it "solves linear equation for dtype #{dtype}" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
a = NMatrix.new [2,2], [3,1,1,2], dtype: dtype
b = NMatrix.new [2,1], [9,8], dtype: dtype
expect(a.solve(b)).to eq(NMatrix.new [2,1], [2,3], dtype: dtype)
end
it "solves linear equation for #{dtype} (non-symmetric matrix)" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+
a = NMatrix.new [3,3], [1,1,1, -1,0,1, 3,4,6], dtype: dtype
b = NMatrix.new [3,1], [6,2,29], dtype: dtype
err = case dtype
when :float32, :complex64
@@ -763,10 +870,13 @@
expect(a.solve(b)).to be_within(err).of(NMatrix.new([3,1], [1,2,3], dtype: dtype))
end
it "solves linear equation for dtype #{dtype} (non-vector rhs)" do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+
a = NMatrix.new [3,3], [1,0,0, -1,0,1, 2,1,1], dtype: dtype
b = NMatrix.new [3,2], [1,0, 1,2, 4,2], dtype: dtype
expect(a.solve(b)).to eq(NMatrix.new [3,2], [1,0, 0,0, 2,2], dtype: dtype)
end
@@ -775,24 +885,27 @@
FLOAT_DTYPES.each do |dtype|
context "when form: :lower_tri" do
let(:a) { NMatrix.new([3,3], [1, 0, 0, 2, 0.5, 0, 3, 3, 9], dtype: dtype) }
it "solves a lower triangular linear system A * x = b with vector b" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,1], [1,2,3], dtype: dtype)
x = a.solve(b, form: :lower_tri)
r = a.dot(x) - b
expect(r.abs.max).to be_within(1e-6).of(0.0)
end
it "solves a lower triangular linear system A * X = B with narrow B" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,2], [1,2,3,4,5,6], dtype: dtype)
x = a.solve(b, form: :lower_tri)
r = (a.dot(x) - b).abs.to_flat_a
expect(r.max).to be_within(1e-6).of(0.0)
end
it "solves a lower triangular linear system A * X = B with wide B" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,5], (1..15).to_a, dtype: dtype)
x = a.solve(b, form: :lower_tri)
r = (a.dot(x) - b).abs.to_flat_a
expect(r.max).to be_within(1e-6).of(0.0)
end
@@ -800,24 +913,27 @@
context "when form: :upper_tri" do
let(:a) { NMatrix.new([3,3], [3, 2, 1, 0, 2, 0.5, 0, 0, 9], dtype: dtype) }
it "solves an upper triangular linear system A * x = b with vector b" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,1], [1,2,3], dtype: dtype)
x = a.solve(b, form: :upper_tri)
r = a.dot(x) - b
expect(r.abs.max).to be_within(1e-6).of(0.0)
end
it "solves an upper triangular linear system A * X = B with narrow B" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,2], [1,2,3,4,5,6], dtype: dtype)
x = a.solve(b, form: :upper_tri)
r = (a.dot(x) - b).abs.to_flat_a
expect(r.max).to be_within(1e-6).of(0.0)
end
it "solves an upper triangular linear system A * X = B with a wide B" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
b = NMatrix.new([3,5], (1..15).to_a, dtype: dtype)
x = a.solve(b, form: :upper_tri)
r = (a.dot(x) - b).abs.to_flat_a
expect(r.max).to be_within(1e-6).of(0.0)
end
@@ -826,20 +942,22 @@
context "when form: :pos_def" do
let(:a) { NMatrix.new([3,3], [4, 1, 2, 1, 5, 3, 2, 3, 6], dtype: dtype) }
it "solves a linear system A * X = b with positive definite A and vector b" do
b = NMatrix.new([3,1], [6,4,8], dtype: dtype)
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
begin
x = a.solve(b, form: :pos_def)
expect(x).to be_within(1e-6).of(NMatrix.new([3,1], [1,0,1], dtype: dtype))
rescue NotImplementedError
"Suppressing a NotImplementedError when the lapacke or atlas plugin is not available"
end
end
-
+
it "solves a linear system A * X = B with positive definite A and matrix B" do
b = NMatrix.new([3,2], [8,3,14,13,14,19], dtype: dtype)
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
begin
x = a.solve(b, form: :pos_def)
expect(x).to be_within(1e-6).of(NMatrix.new([3,2], [1,-1,2,1,1,3], dtype: dtype))
rescue NotImplementedError
"Suppressing a NotImplementedError when the lapacke or atlas plugin is not available"
@@ -847,24 +965,55 @@
end
end
end
end
+ context "#least_squares" do
+ it "finds the least squares approximation to the equation A * X = B" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ a = NMatrix.new([3,2], [2.0, 0, -1, 1, 0, 2])
+ b = NMatrix.new([3,1], [1.0, 0, -1])
+ solution = NMatrix.new([2,1], [1.0 / 3 , -1.0 / 3], dtype: :float64)
+
+ begin
+ least_squares = a.least_squares(b)
+ expect(least_squares).to be_within(0.0001).of solution
+ rescue NotImplementedError
+ "Suppressing a NotImplementedError when the lapacke or atlas plugin is not available"
+ end
+ end
+
+ it "finds the least squares approximation to the equation A * X = B with high tolerance" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ a = NMatrix.new([4,2], [1.0, 1, 1, 2, 1, 3,1,4])
+ b = NMatrix.new([4,1], [6.0, 5, 7, 10])
+ solution = NMatrix.new([2,1], [3.5 , 1.4], dtype: :float64)
+
+ begin
+ least_squares = a.least_squares(b, tolerance: 10e-5)
+ expect(least_squares).to be_within(0.0001).of solution
+ rescue NotImplementedError
+ "Suppressing a NotImplementedError when the lapacke or atlas plugin is not available"
+ end
+ end
+ end
+
context "#hessenberg" do
FLOAT_DTYPES.each do |dtype|
context dtype do
before do
- @n = NMatrix.new [5,5],
+ @n = NMatrix.new [5,5],
[0, 2, 0, 1, 1,
2, 2, 3, 2, 2,
4,-3, 0, 1, 3,
6, 1,-6,-5, 4,
5, 6, 4, 1, 5], dtype: dtype
end
it "transforms a matrix to Hessenberg form" do
- expect(@n.hessenberg).to be_within(0.0001).of(NMatrix.new([5,5],
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ expect(@n.hessenberg).to be_within(0.0001).of(NMatrix.new([5,5],
[0.00000,-1.66667, 0.79432,-0.45191,-1.54501,
-9.00000, 2.95062,-6.89312, 3.22250,-0.19012,
0.00000,-8.21682,-0.57379, 5.26966,-1.69976,
0.00000, 0.00000,-3.74630,-0.80893, 3.99708,
0.00000, 0.00000, 0.00000, 0.04102, 0.43211], dtype: dtype))
@@ -875,80 +1024,86 @@
ALL_DTYPES.each do |dtype|
[:dense, :yale].each do |stype|
answer_dtype = integer_dtype?(dtype) ? :int64 : dtype
next if dtype == :byte
-
+
context "#pow #{dtype} #{stype}" do
- before do
+ before do
@n = NMatrix.new [4,4], [0, 2, 0, 1,
2, 2, 3, 2,
4,-3, 0, 1,
6, 1,-6,-5], dtype: dtype, stype: stype
end
it "raises a square matrix to even power" do
- expect(@n.pow(4)).to eq(NMatrix.new([4,4], [292, 28,-63, -42,
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+ expect(@n.pow(4)).to eq(NMatrix.new([4,4], [292, 28,-63, -42,
360, 96, 51, -14,
448,-231,-24,-87,
- -1168, 595,234, 523],
+ -1168, 595,234, 523],
dtype: answer_dtype,
stype: stype))
end
it "raises a square matrix to odd power" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
expect(@n.pow(9)).to eq(NMatrix.new([4,4],[-275128, 279917, 176127, 237451,
-260104, 394759, 166893, 296081,
-704824, 285700, 186411, 262002,
3209256,-1070870,-918741,-1318584],
dtype: answer_dtype, stype: stype))
end
it "raises a sqaure matrix to negative power" do
expect(@n.pow(-3)).to be_within(0.00001).of (NMatrix.new([4,4],
[1.0647e-02, 4.2239e-04,-6.2281e-05, 2.7680e-03,
- -1.6415e-02, 2.1296e-02, 1.0718e-02, 4.8589e-03,
+ -1.6415e-02, 2.1296e-02, 1.0718e-02, 4.8589e-03,
8.6956e-03,-8.6569e-03, 2.8993e-02, 7.2015e-03,
- 5.0034e-02,-1.7500e-02,-3.6777e-02,-1.2128e-02], dtype: answer_dtype,
- stype: stype))
+ 5.0034e-02,-1.7500e-02,-3.6777e-02,-1.2128e-02], dtype: answer_dtype,
+ stype: stype))
end unless stype =~ /yale/ or dtype == :object or ALL_DTYPES.grep(/int/).include? dtype
it "raises a square matrix to zero" do
- expect(@n.pow(0)).to eq(NMatrix.eye([4,4], dtype: answer_dtype,
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
+ expect(@n.pow(0)).to eq(NMatrix.eye([4,4], dtype: answer_dtype,
stype: stype))
end
it "raises a square matrix to one" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
expect(@n.pow(1)).to eq(@n)
end
end
end
end
ALL_DTYPES.each do |dtype|
[:dense, :yale].each do |stype|
context "#kron_prod #{dtype} #{stype}" do
- before do
+ before do
@a = NMatrix.new([2,2], [1,2,
3,4], dtype: dtype, stype: stype)
@b = NMatrix.new([2,3], [1,1,1,
1,1,1], dtype: dtype, stype: stype)
@c = NMatrix.new([4,6], [1, 1, 1, 2, 2, 2,
1, 1, 1, 2, 2, 2,
3, 3, 3, 4, 4, 4,
- 3, 3, 3, 4, 4, 4], dtype: dtype, stype: stype)
+ 3, 3, 3, 4, 4, 4], dtype: dtype, stype: stype)
end
- it "Compute the Kronecker product of two NMatrix" do
+ it "computes the Kronecker product of two NMatrix objects" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
expect(@a.kron_prod(@b)).to eq(@c)
end
end
end
end
context "determinants" do
ALL_DTYPES.each do |dtype|
context dtype do
+ pending("not yet implemented for :object dtype") if dtype == :object
before do
@a = NMatrix.new([2,2], [1,2,
3,4], dtype: dtype)
@b = NMatrix.new([3,3], [1,2,3,
5,0,1,
@@ -965,71 +1120,160 @@
else
1e-64 # FIXME: should be 0, but be_within(0) does not work.
end
end
it "computes the determinant of 2x2 matrix" do
- if dtype != :object
- expect(@a.det).to be_within(@err).of(-2)
- end
+ pending("not yet implemented for :object dtype") if dtype == :object
+ expect(@a.det).to be_within(@err).of(-2)
end
it "computes the determinant of 3x3 matrix" do
- if dtype != :object
- expect(@b.det).to be_within(@err).of(-8)
- end
+ pending("not yet implemented for :object dtype") if dtype == :object
+ expect(@b.det).to be_within(@err).of(-8)
end
it "computes the determinant of 4x4 matrix" do
- if dtype != :object
- expect(@c.det).to be_within(@err).of(-18)
- end
+ pending("not yet implemented for :object dtype") if dtype == :object
+ expect(@c.det).to be_within(@err).of(-18)
end
it "computes the exact determinant of 2x2 matrix" do
+ pending("not yet implemented for :object dtype") if dtype == :object
if dtype == :byte
expect{@a.det_exact}.to raise_error(DataTypeError)
else
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
expect(@a.det_exact).to be_within(@err).of(-2)
end
end
it "computes the exact determinant of 3x3 matrix" do
+ pending("not yet implemented for :object dtype") if dtype == :objectx
if dtype == :byte
expect{@a.det_exact}.to raise_error(DataTypeError)
else
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object
expect(@b.det_exact).to be_within(@err).of(-8)
end
end
end
end
end
context "#scale and #scale!" do
[:dense,:list,:yale].each do |stype|
ALL_DTYPES.each do |dtype|
- next if dtype == :object
context "for #{dtype}" do
before do
@m = NMatrix.new([3, 3], [0, 1, 2,
3, 4, 5,
6, 7, 8], stype: stype, dtype: dtype)
end
+
it "scales the matrix by a given factor and return the result" do
+ pending("not yet implemented for :object dtype") if dtype == :object
if integer_dtype? dtype
expect{@m.scale 2.0}.to raise_error(DataTypeError)
else
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and (dtype == :complex64 || dtype == :complex128)
expect(@m.scale 2.0).to eq(NMatrix.new([3, 3], [0, 2, 4,
6, 8, 10,
12, 14, 16], stype: stype, dtype: dtype))
end
end
+
it "scales the matrix in place by a given factor" do
- if dtype == :int8
- expect{@m.scale! 2}.to raise_error(DataTypeError)
- else
- @m.scale! 2
- expect(@m).to eq(NMatrix.new([3, 3], [0, 2, 4,
- 6, 8, 10,
- 12, 14, 16], stype: stype, dtype: dtype))
- end
+ pending("not yet implemented for :object dtype") if dtype == :object
+ if dtype == :int8
+ expect{@m.scale! 2}.to raise_error(DataTypeError)
+ else
+ pending("not yet implemented for NMatrix-JRuby") if jruby? and (dtype == :complex64 || dtype == :complex128)
+ @m.scale! 2
+ expect(@m).to eq(NMatrix.new([3, 3], [0, 2, 4,
+ 6, 8, 10,
+ 12, 14, 16], stype: stype, dtype: dtype))
+ end
end
end
end
end
+ end
+ context "matrix_norm" do
+ ALL_DTYPES.each do |dtype|
+ context dtype do
+ pending("not yet implemented for :object dtype") if dtype == :object
+ before do
+ @n = NMatrix.new([3,3], [-4,-3,-2,
+ -1, 0, 1,
+ 2, 3, 4], dtype: dtype)
+
+ @matrix_norm_TOLERANCE = 1.0e-10
+ end
+
+ it "should default to 2-matrix_norm" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ if(dtype == :byte)
+ expect{@n.matrix_norm}.to raise_error(ArgumentError)
+ else
+ begin
+ expect(@n.matrix_norm).to be_within(@matrix_norm_TOLERANCE).of(7.348469228349535)
+
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
+ end
+ end
+ end
+
+ it "should reject invalid arguments" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+
+ expect{@n.matrix_norm(0.5)}.to raise_error(ArgumentError)
+ end
+
+ it "should calculate 1 and 2(minus) matrix_norms correctly" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ if(dtype == :byte)
+ expect{@n.matrix_norm(1)}.to raise_error(ArgumentError)
+ expect{@n.matrix_norm(-2)}.to raise_error(ArgumentError)
+ expect{@n.matrix_norm(-1)}.to raise_error(ArgumentError)
+ else
+ expect(@n.matrix_norm(1)).to eq(7)
+ begin
+
+ #FIXME: change to the correct value when overflow issue is resolved
+ #expect(@n.matrix_norm(-2)).to eq(1.8628605857884395e-07)
+ expect(@n.matrix_norm(-2)).to be_within(@matrix_norm_TOLERANCE).of(0.0)
+ rescue NotImplementedError
+ pending "Suppressing a NotImplementedError when the lapacke plugin is not available"
+ end
+ expect(@n.matrix_norm(-1)).to eq(6)
+ end
+ end
+
+ it "should calculate infinity matrix_norms correctly" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ if(dtype == :byte)
+ expect{@n.matrix_norm(:inf)}.to raise_error(ArgumentError)
+ expect{@n.matrix_norm(:'-inf')}.to raise_error(ArgumentError)
+ else
+ expect(@n.matrix_norm(:inf)).to eq(9)
+ expect(@n.matrix_norm(:'-inf')).to eq(2)
+ end
+ end
+
+ it "should calculate frobenius matrix_norms correctly" do
+ pending("not yet implemented for NMatrix-JRuby") if jruby?
+ if(dtype == :byte)
+ expect{@n.matrix_norm(:fro)}.to raise_error(ArgumentError)
+ else
+ expect(@n.matrix_norm(:fro)).to be_within(@matrix_norm_TOLERANCE).of(7.745966692414834)
+ end
+ end
+ end
+ end
+ end
+
+ context "#positive_definite?" do
+ it "should return true for positive_definite? matrix" do
+ n = NMatrix.new([3,3], [2, -1, -1,
+ -1, 2, -1,
+ -1, -1, 3])
+ expect(n.positive_definite?).to be_truthy
+ end
end
end