From 9a8c82151d21fdae78e4f6b89a7999f6ac033545 Mon Sep 17 00:00:00 2001 From: Mohamed Ziata Date: Wed, 3 Apr 2019 22:50:29 +0200 Subject: [PATCH] :art: Standarize code ./spec directory --- spec/00_nmatrix_spec.rb | 609 +++++++++--------- spec/01_enum_spec.rb | 77 ++- spec/02_slice_spec.rb | 322 +++++----- spec/03_nmatrix_monkeys_spec.rb | 31 +- spec/blas_spec.rb | 113 ++-- spec/elementwise_spec.rb | 155 +++-- spec/homogeneous_spec.rb | 69 +- spec/io/fortran_format_spec.rb | 22 +- spec/io/harwell_boeing_spec.rb | 58 +- spec/io_spec.rb | 56 +- spec/lapack_core_spec.rb | 248 ++++---- spec/leakcheck.rb | 14 +- spec/math_spec.rb | 912 +++++++++++++-------------- spec/nmatrix_yale_spec.rb | 204 +++--- spec/plugins/atlas/atlas_spec.rb | 148 ++--- spec/plugins/fftw/fftw_spec.rb | 215 +++---- spec/plugins/lapacke/lapacke_spec.rb | 424 +++++++------ spec/rspec_monkeys.rb | 25 +- spec/rspec_spec.rb | 6 +- spec/shortcuts_spec.rb | 158 +++-- spec/slice_set_spec.rb | 97 ++- spec/spec_helper.rb | 139 ++-- spec/stat_spec.rb | 50 +- 23 files changed, 2049 insertions(+), 2103 deletions(-) diff --git a/spec/00_nmatrix_spec.rb b/spec/00_nmatrix_spec.rb index 8ff0f3d7..c8eb81a6 100644 --- a/spec/00_nmatrix_spec.rb +++ b/spec/00_nmatrix_spec.rb @@ -25,188 +25,188 @@ # Basic tests for NMatrix. These should load first, as they're # essential to NMatrix operation. # -require 'spec_helper' +require "spec_helper" describe NMatrix do it "creates a matrix with the new constructor" do - n = NMatrix.new([2,2], [0,1,2,3], dtype: :int64) - expect(n.shape).to eq([2,2]) - expect(n.entries).to eq([0,1,2,3]) + n = NMatrix.new([2, 2], [0, 1, 2, 3], dtype: :int64) + expect(n.shape).to eq([2, 2]) + expect(n.entries).to eq([0, 1, 2, 3]) expect(n.dtype).to eq(:int64) end it "adequately requires information to access a single entry of a dense matrix" do - n = NMatrix.new(:dense, 4, [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], :float64) - expect(n[0,0]).to eq(0) + n = NMatrix.new(:dense, 4, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], :float64) + expect(n[0, 0]).to eq(0) expect { n[0] }.to raise_error(ArgumentError) end it "calculates exact determinants on small dense matrices" do - expect(NMatrix.new(2, [1,2,3,4], stype: :dense, dtype: :int64).det_exact).to eq(-2) - expect(NMatrix.new(3, [1,2,3,0,5,6,7,8,0], stype: :dense, dtype: :int64) + expect(NMatrix.new(2, [1, 2, 3, 4], stype: :dense, dtype: :int64).det_exact).to eq(-2) + expect(NMatrix.new(3, [1, 2, 3, 0, 5, 6, 7, 8, 0], stype: :dense, dtype: :int64) .det_exact).to eq(-69) end it "calculates exact determinants on small yale square matrices" do - expect(NMatrix.new(2, [1,2,3,4], stype: :yale, dtype: :int64).det_exact).to eq(-2) - expect(NMatrix.new(3, [1,2,3,0,5,6,7,8,0], stype: :yale, dtype: :int64) + expect(NMatrix.new(2, [1, 2, 3, 4], stype: :yale, dtype: :int64).det_exact).to eq(-2) + expect(NMatrix.new(3, [1, 2, 3, 0, 5, 6, 7, 8, 0], stype: :yale, dtype: :int64) .det_exact).to eq(-69) end it "calculates exact determinants on small list square matrices" do - expect(NMatrix.new(2, [1,2,3,4], stype: :list, dtype: :int64).det_exact).to eq(-2) - expect(NMatrix.new(3, [1,2,3,0,5,6,7,8,0], stype: :list, dtype: :int64) + expect(NMatrix.new(2, [1, 2, 3, 4], stype: :list, dtype: :int64).det_exact).to eq(-2) + expect(NMatrix.new(3, [1, 2, 3, 0, 5, 6, 7, 8, 0], stype: :list, dtype: :int64) .det_exact).to eq(-69) end it "calculates inverse exact determinants on small dense matrices" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new(3, [1,2,3,0,1,4,5,6,0], stype: :dense, dtype: :int64) + a = NMatrix.new(3, [1, 2, 3, 0, 1, 4, 5, 6, 0], stype: :dense, dtype: :int64) inversed = a.method(:__inverse_exact__).call(a.clone, 3, 3) - b = NMatrix.new(3, [-24,18,5,20,-15,-4,-5,4,1], stype: :dense, dtype: :int64) + b = NMatrix.new(3, [-24, 18, 5, 20, -15, -4, -5, 4, 1], stype: :dense, dtype: :int64) expect(inversed).to eq(b) - c = NMatrix.new(3, [1,0,3,0,0,1,0,6,0], stype: :dense, dtype: :int64) + c = NMatrix.new(3, [1, 0, 3, 0, 0, 1, 0, 6, 0], stype: :dense, dtype: :int64) inversed = c.method(:__inverse_exact__).call(c.clone, 3, 3) - d = NMatrix.new(3, [1,-3,0,0,0,0,0,1,0], stype: :dense, dtype: :int64) + d = NMatrix.new(3, [1, -3, 0, 0, 0, 0, 0, 1, 0], stype: :dense, dtype: :int64) expect(inversed).to eq(d) - e = NMatrix.new(2, [3,1,2,1], stype: :dense, dtype: :int64) + e = NMatrix.new(2, [3, 1, 2, 1], stype: :dense, dtype: :int64) inversed = e.method(:__inverse_exact__).call(e.clone, 2, 2) - f = NMatrix.new(2, [1,-1,-2,3], stype: :dense, dtype: :int64) + f = NMatrix.new(2, [1, -1, -2, 3], stype: :dense, dtype: :int64) expect(inversed).to eq(f) end it "calculates inverse exact determinants on small yale matrices" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new(3, [1,2,3,0,1,4,5,6,0], stype: :yale, dtype: :int64) + a = NMatrix.new(3, [1, 2, 3, 0, 1, 4, 5, 6, 0], stype: :yale, dtype: :int64) inversed = a.method(:__inverse_exact__).call(a.clone, 3, 3) - b = NMatrix.new(3, [-24,18,5,20,-15,-4,-5,4,1], stype: :yale, dtype: :int64) + b = NMatrix.new(3, [-24, 18, 5, 20, -15, -4, -5, 4, 1], stype: :yale, dtype: :int64) expect(inversed).to eq(b) - c = NMatrix.new(3, [1,0,3,0,0,1,0,6,0], stype: :yale, dtype: :int64) + c = NMatrix.new(3, [1, 0, 3, 0, 0, 1, 0, 6, 0], stype: :yale, dtype: :int64) inversed = c.method(:__inverse_exact__).call(c.clone, 3, 3) - d = NMatrix.new(3, [1,-3,0,0,0,0,0,1,0], stype: :yale, dtype: :int64) + d = NMatrix.new(3, [1, -3, 0, 0, 0, 0, 0, 1, 0], stype: :yale, dtype: :int64) expect(inversed).to eq(d) - e = NMatrix.new(2, [3,1,2,1], stype: :yale, dtype: :int64) + e = NMatrix.new(2, [3, 1, 2, 1], stype: :yale, dtype: :int64) inversed = e.method(:__inverse_exact__).call(e.clone, 2, 2) - f = NMatrix.new(2, [1,-1,-2,3], stype: :yale, dtype: :int64) + f = NMatrix.new(2, [1, -1, -2, 3], stype: :yale, dtype: :int64) expect(inversed).to eq(f) end it "calculates inverse exact determinants on small list matrices" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new(3, [1,2,3,0,1,4,5,6,0], stype: :list, dtype: :int64) + a = NMatrix.new(3, [1, 2, 3, 0, 1, 4, 5, 6, 0], stype: :list, dtype: :int64) inversed = a.method(:__inverse_exact__).call(a.clone, 3, 3) - b = NMatrix.new(3, [-24,18,5,20,-15,-4,-5,4,1], stype: :list, dtype: :int64) + b = NMatrix.new(3, [-24, 18, 5, 20, -15, -4, -5, 4, 1], stype: :list, dtype: :int64) expect(inversed).to eq(b) - c = NMatrix.new(2, [3,1,2,1], stype: :list, dtype: :int64) + c = NMatrix.new(2, [3, 1, 2, 1], stype: :list, dtype: :int64) inversed = c.method(:__inverse_exact__).call(c.clone, 2, 2) - d = NMatrix.new(2, [1,-1,-2,3], stype: :list, dtype: :int64) + d = NMatrix.new(2, [1, -1, -2, 3], stype: :list, dtype: :int64) expect(inversed).to eq(d) end it "calculates determinants" do - expect(NMatrix.new(3, [-2,2,3,-1,1,3,2,0,-1], stype: :dense, dtype: :int64).det).to eq(6) + expect(NMatrix.new(3, [-2, 2, 3, -1, 1, 3, 2, 0, -1], stype: :dense, dtype: :int64).det).to eq(6) end it "allows casting to Ruby objects" do - m = NMatrix.new([3,3], [0,0,1,0,2,0,3,4,5], dtype: :int64, stype: :dense) + m = NMatrix.new([3, 3], [0, 0, 1, 0, 2, 0, 3, 4, 5], dtype: :int64, stype: :dense) n = m.cast(:dense, :object) expect(n).to eq(m) end it "allows casting from Ruby objects" do pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix.new(:dense, [3,3], [0,0,1,0,2,0,3,4,5], :object) + m = NMatrix.new(:dense, [3, 3], [0, 0, 1, 0, 2, 0, 3, 4, 5], :object) n = m.cast(:dense, :int64) expect(m).to eq(n) end it "allows stype casting of a dim 2 matrix between dense, sparse, and list (different dtypes)" do - m = NMatrix.new(:dense, [3,3], [0,0,1,0,2,0,3,4,5], :int64). - cast(:yale, :int32). - cast(:dense, :float64). - cast(:list, :object). - cast(:dense, :int16). - cast(:list, :int32). - cast(:yale, :int64) #. - #cast(:list, :int32). - #cast(:dense, :int16) - #m.should.equal?(original) + m = NMatrix.new(:dense, [3, 3], [0, 0, 1, 0, 2, 0, 3, 4, 5], :int64) + .cast(:yale, :int32) + .cast(:dense, :float64) + .cast(:list, :object) + .cast(:dense, :int16) + .cast(:list, :int32) + .cast(:yale, :int64) # . + # cast(:list, :int32). + # cast(:dense, :int16) + # m.should.equal?(original) # For some reason this causes some weird garbage collector problems when we uncomment these. The above lines won't # work at all in IRB, but work fine when run in a regular Ruby session. end it "fills dense Ruby object matrix with nil" do - n = NMatrix.new([4,3], dtype: :object) + n = NMatrix.new([4, 3], dtype: :object) pending("not yet implemented for object dtype for NMatrix-JRuby") if jruby? - expect(n[0,0]).to eq(nil) + expect(n[0, 0]).to eq(nil) end it "fills dense with individual assignments" do - n = NMatrix.new([4,3], dtype: :float64) - n[0,0] = 14.0 - n[0,1] = 9.0 - n[0,2] = 3.0 - n[1,0] = 2.0 - n[1,1] = 11.0 - n[1,2] = 15.0 - n[2,0] = 0.0 - n[2,1] = 12.0 - n[2,2] = 17.0 - n[3,0] = 5.0 - n[3,1] = 2.0 - n[3,2] = 3.0 - - expect(n[0,0]).to eq(14.0) - expect(n[0,1]).to eq(9.0) - expect(n[0,2]).to eq(3.0) - expect(n[1,0]).to eq(2.0) - expect(n[1,1]).to eq(11.0) - expect(n[1,2]).to eq(15.0) - expect(n[2,0]).to eq(0.0) - expect(n[2,1]).to eq(12.0) - expect(n[2,2]).to eq(17.0) - expect(n[3,0]).to eq(5.0) - expect(n[3,1]).to eq(2.0) - expect(n[3,2]).to eq(3.0) + n = NMatrix.new([4, 3], dtype: :float64) + n[0, 0] = 14.0 + n[0, 1] = 9.0 + n[0, 2] = 3.0 + n[1, 0] = 2.0 + n[1, 1] = 11.0 + n[1, 2] = 15.0 + n[2, 0] = 0.0 + n[2, 1] = 12.0 + n[2, 2] = 17.0 + n[3, 0] = 5.0 + n[3, 1] = 2.0 + n[3, 2] = 3.0 + + expect(n[0, 0]).to eq(14.0) + expect(n[0, 1]).to eq(9.0) + expect(n[0, 2]).to eq(3.0) + expect(n[1, 0]).to eq(2.0) + expect(n[1, 1]).to eq(11.0) + expect(n[1, 2]).to eq(15.0) + expect(n[2, 0]).to eq(0.0) + expect(n[2, 1]).to eq(12.0) + expect(n[2, 2]).to eq(17.0) + expect(n[3, 0]).to eq(5.0) + expect(n[3, 1]).to eq(2.0) + expect(n[3, 2]).to eq(3.0) end it "fills dense with a single mass assignment" do - n = NMatrix.new([4,3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0]) - - expect(n[0,0]).to eq(14.0) - expect(n[0,1]).to eq(9.0) - expect(n[0,2]).to eq(3.0) - expect(n[1,0]).to eq(2.0) - expect(n[1,1]).to eq(11.0) - expect(n[1,2]).to eq(15.0) - expect(n[2,0]).to eq(0.0) - expect(n[2,1]).to eq(12.0) - expect(n[2,2]).to eq(17.0) - expect(n[3,0]).to eq(5.0) - expect(n[3,1]).to eq(2.0) - expect(n[3,2]).to eq(3.0) + n = NMatrix.new([4, 3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0]) + + expect(n[0, 0]).to eq(14.0) + expect(n[0, 1]).to eq(9.0) + expect(n[0, 2]).to eq(3.0) + expect(n[1, 0]).to eq(2.0) + expect(n[1, 1]).to eq(11.0) + expect(n[1, 2]).to eq(15.0) + expect(n[2, 0]).to eq(0.0) + expect(n[2, 1]).to eq(12.0) + expect(n[2, 2]).to eq(17.0) + expect(n[3, 0]).to eq(5.0) + expect(n[3, 1]).to eq(2.0) + expect(n[3, 2]).to eq(3.0) end it "fills dense with a single mass assignment, with dtype specified" do - m = NMatrix.new([4,3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0], dtype: :float32) - - expect(m[0,0]).to eq(14.0) - expect(m[0,1]).to eq(9.0) - expect(m[0,2]).to eq(3.0) - expect(m[1,0]).to eq(2.0) - expect(m[1,1]).to eq(11.0) - expect(m[1,2]).to eq(15.0) - expect(m[2,0]).to eq(0.0) - expect(m[2,1]).to eq(12.0) - expect(m[2,2]).to eq(17.0) - expect(m[3,0]).to eq(5.0) - expect(m[3,1]).to eq(2.0) - expect(m[3,2]).to eq(3.0) + m = NMatrix.new([4, 3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0], dtype: :float32) + + expect(m[0, 0]).to eq(14.0) + expect(m[0, 1]).to eq(9.0) + expect(m[0, 2]).to eq(3.0) + expect(m[1, 0]).to eq(2.0) + expect(m[1, 1]).to eq(11.0) + expect(m[1, 2]).to eq(15.0) + expect(m[2, 0]).to eq(0.0) + expect(m[2, 1]).to eq(12.0) + expect(m[2, 2]).to eq(17.0) + expect(m[3, 0]).to eq(5.0) + expect(m[3, 1]).to eq(2.0) + expect(m[3, 2]).to eq(3.0) end it "dense handles missing initialization value" do @@ -222,44 +222,44 @@ [:dense, :list, :yale].each do |storage_type| context storage_type do - it "can be duplicated" do - n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64) + it "can be duplicated" do + n = NMatrix.new([2, 3], 1.1, stype: storage_type, dtype: :float64) # FIXME - pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? #and storage_type != :dense + pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? # and storage_type != :dense expect(n.stype).to eq(storage_type) - n[0,0] = 0.0 - n[0,1] = 0.1 - n[1,0] = 1.0 + n[0, 0] = 0.0 + n[0, 1] = 0.1 + n[1, 0] = 1.0 m = n.dup expect(m.shape).to eq(n.shape) expect(m.dim).to eq(n.dim) expect(m.object_id).not_to eq(n.object_id) expect(m.stype).to eq(storage_type) - expect(m[0,0]).to eq(n[0,0]) - m[0,0] = 3.0 - expect(m[0,0]).not_to eq(n[0,0]) + expect(m[0, 0]).to eq(n[0, 0]) + m[0, 0] = 3.0 + expect(m[0, 0]).not_to eq(n[0, 0]) end it "enforces shape boundaries" do - expect { NMatrix.new([1,10], 0, dtype: :int8, stype: storage_type, default: 0)[1,0] }.to raise_error(RangeError) - expect { NMatrix.new([1,10], 0, dtype: :int8, stype: storage_type, default: 0)[0,10] }.to raise_error(RangeError) + expect { NMatrix.new([1, 10], 0, dtype: :int8, stype: storage_type, default: 0)[1, 0] }.to raise_error(RangeError) + expect { NMatrix.new([1, 10], 0, dtype: :int8, stype: storage_type, default: 0)[0, 10] }.to raise_error(RangeError) end it "sets and gets" do n = NMatrix.new(2, 0, stype: storage_type, dtype: :int8) - n[0,1] = 1 - expect(n[0,0]).to eq(0) - expect(n[1,0]).to eq(0) - expect(n[0,1]).to eq(1) - expect(n[1,1]).to eq(0) + n[0, 1] = 1 + expect(n[0, 0]).to eq(0) + expect(n[1, 0]).to eq(0) + expect(n[0, 1]).to eq(1) + expect(n[1, 1]).to eq(0) end it "sets and gets references" do n = NMatrix.new(2, stype: storage_type, dtype: :int8, default: 0) - expect(n[0,1] = 1).to eq(1) - expect(n[0,1]).to eq(1) + expect(n[0, 1] = 1).to eq(1) + expect(n[0, 1]).to eq(1) end # Tests Ruby object versus any C dtype (in this case we use :int64) @@ -269,13 +269,13 @@ it "allows iteration of matrices" do n = nil if storage_type == :dense - n = NMatrix.new(:dense, [3,3], [1,2,3,4,5,6,7,8,9], dtype) + n = NMatrix.new(:dense, [3, 3], [1, 2, 3, 4, 5, 6, 7, 8, 9], dtype) else - n = NMatrix.new([3,4], 0, stype: storage_type, dtype: dtype) - n[0,0] = 1 - n[0,1] = 2 - n[2,3] = 4 - n[2,0] = 3 + n = NMatrix.new([3, 4], 0, stype: storage_type, dtype: dtype) + n[0, 0] = 1 + n[0, 1] = 2 + n[2, 3] = 4 + n[2, 0] = 3 end ary = [] @@ -284,45 +284,45 @@ end if storage_type == :dense - expect(ary).to eq([1,2,3,4,5,6,7,8,9]) + expect(ary).to eq([1, 2, 3, 4, 5, 6, 7, 8, 9]) else - expect(ary).to eq([1,2,0,0,0,0,0,0,3,0,0,4]) + expect(ary).to eq([1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4]) end end it "allows storage-based iteration of matrices" do - pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? and storage_type != :dense + pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? && (storage_type != :dense) STDERR.puts storage_type.inspect STDERR.puts dtype.inspect - n = NMatrix.new([3,3], 0, stype: storage_type, dtype: dtype) - n[0,0] = 1 - n[0,1] = 2 - n[2,0] = 5 if storage_type == :yale - n[2,1] = 4 - n[2,2] = 3 + n = NMatrix.new([3, 3], 0, stype: storage_type, dtype: dtype) + n[0, 0] = 1 + n[0, 1] = 2 + n[2, 0] = 5 if storage_type == :yale + n[2, 1] = 4 + n[2, 2] = 3 values = [] is = [] js = [] - n.each_stored_with_indices do |v,i,j| + n.each_stored_with_indices do |v, i, j| values << v is << i js << j end if storage_type == :yale - expect(is).to eq([0,1,2,0,2,2]) - expect(js).to eq([0,1,2,1,0,1]) - expect(values).to eq([1,0,3,2,5,4]) + expect(is).to eq([0, 1, 2, 0, 2, 2]) + expect(js).to eq([0, 1, 2, 1, 0, 1]) + expect(values).to eq([1, 0, 3, 2, 5, 4]) elsif storage_type == :list - expect(values).to eq([1,2,4,3]) - expect(is).to eq([0,0,2,2]) - expect(js).to eq([0,1,1,2]) + expect(values).to eq([1, 2, 4, 3]) + expect(is).to eq([0, 0, 2, 2]) + expect(js).to eq([0, 1, 1, 2]) elsif storage_type == :dense - expect(values).to eq([1,2,0,0,0,0,0,4,3]) - expect(is).to eq([0,0,0,1,1,1,2,2,2]) - expect(js).to eq([0,1,2,0,1,2,0,1,2]) + expect(values).to eq([1, 2, 0, 0, 0, 0, 0, 4, 3]) + expect(is).to eq([0, 0, 0, 1, 1, 1, 2, 2, 2]) + expect(js).to eq([0, 1, 2, 0, 1, 2, 0, 1, 2]) end end end @@ -330,61 +330,61 @@ end # dense and list, not yale - context "(storage: #{storage_type})" do - it "gets default value" do - pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - expect(NMatrix.new(3, 0, stype: storage_type)[1,1]).to eq(0) - expect(NMatrix.new(3, 0.1, stype: storage_type)[1,1]).to eq(0.1) - expect(NMatrix.new(3, 1, stype: storage_type)[1,1]).to eq(1) - - end - it "returns shape and dim" do - expect(NMatrix.new([3,2,8], 0, stype: storage_type).shape).to eq([3,2,8]) - expect(NMatrix.new([3,2,8], 0, stype: storage_type).dim).to eq(3) - end + unless storage_type == :yale + context "(storage: #{storage_type})" do + it "gets default value" do + pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? + expect(NMatrix.new(3, 0, stype: storage_type)[1, 1]).to eq(0) + expect(NMatrix.new(3, 0.1, stype: storage_type)[1, 1]).to eq(0.1) + expect(NMatrix.new(3, 1, stype: storage_type)[1, 1]).to eq(1) + end + it "returns shape and dim" do + expect(NMatrix.new([3, 2, 8], 0, stype: storage_type).shape).to eq([3, 2, 8]) + expect(NMatrix.new([3, 2, 8], 0, stype: storage_type).dim).to eq(3) + end - it "returns number of rows and columns" do - expect(NMatrix.new([7, 4], 3, stype: storage_type).rows).to eq(7) - expect(NMatrix.new([7, 4], 3, stype: storage_type).cols).to eq(4) + it "returns number of rows and columns" do + expect(NMatrix.new([7, 4], 3, stype: storage_type).rows).to eq(7) + expect(NMatrix.new([7, 4], 3, stype: storage_type).cols).to eq(4) + end end - end unless storage_type == :yale + end end - it "handles dense construction" do - expect(NMatrix.new(3,0)[1,1]).to eq(0) - expect(lambda { NMatrix.new(3,dtype: :int8)[1,1] }).to_not raise_error + expect(NMatrix.new(3, 0)[1, 1]).to eq(0) + expect(lambda { NMatrix.new(3, dtype: :int8)[1, 1] }).to_not raise_error end it "converts from list to yale properly" do m = NMatrix.new(3, 0, stype: :list) - m[0,2] = 333 - m[2,2] = 777 + m[0, 2] = 333 + m[2, 2] = 777 n = m.cast(:yale, :int32) - #puts n.capacity - #n.extend NMatrix::YaleFunctions - #puts n.yale_ija.inspect - #puts n.yale_a.inspect - - expect(n[0,0]).to eq(0) - expect(n[0,1]).to eq(0) - expect(n[0,2]).to eq(333) - expect(n[1,0]).to eq(0) - expect(n[1,1]).to eq(0) - expect(n[1,2]).to eq(0) - expect(n[2,0]).to eq(0) - expect(n[2,1]).to eq(0) - expect(n[2,2]).to eq(777) + # puts n.capacity + # n.extend NMatrix::YaleFunctions + # puts n.yale_ija.inspect + # puts n.yale_a.inspect + + expect(n[0, 0]).to eq(0) + expect(n[0, 1]).to eq(0) + expect(n[0, 2]).to eq(333) + expect(n[1, 0]).to eq(0) + expect(n[1, 1]).to eq(0) + expect(n[1, 2]).to eq(0) + expect(n[2, 0]).to eq(0) + expect(n[2, 1]).to eq(0) + expect(n[2, 2]).to eq(777) end it "should return an enumerator when each is called without a block" do a = NMatrix.new(2, 1) - b = NMatrix.new(2, [-1,0,1,0]) + b = NMatrix.new(2, [-1, 0, 1, 0]) enums = [a.each, b.each] begin atans = [] - atans << Math.atan2(*enums.map(&:next)) while true + loop { atans << Math.atan2(*enums.map(&:next)) } rescue StopIteration end end @@ -401,7 +401,7 @@ it "should return the matrix being iterated over when each_stored_with_indices is called with a block" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new(2,1) + a = NMatrix.new(2, 1) val = (a.each_stored_with_indices { }) expect(val).to eq(a) end @@ -411,14 +411,14 @@ context storage_type do it "should return the matrix being iterated over when each_stored_with_indices is called with a block" do pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64, default: 0) + n = NMatrix.new([2, 3], 1.1, stype: storage_type, dtype: :float64, default: 0) val = (n.each_stored_with_indices { }) expect(val).to eq(n) end it "should return an enumerator when each_stored_with_indices is called without a block" do pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], 1.1, stype: storage_type, dtype: :float64, default: 0) + n = NMatrix.new([2, 3], 1.1, stype: storage_type, dtype: :float64, default: 0) val = n.each_stored_with_indices expect(val).to be_a Enumerator end @@ -431,50 +431,49 @@ end end - -describe 'NMatrix' do +describe "NMatrix" do context "#upper_triangle" do it "should create a copy with the lower corner set to zero" do - n = NMatrix.seq(4)+1 - expect(n.upper_triangle).to eq(NMatrix.new(4, [1,2,3,4,0,6,7,8,0,0,11,12,0,0,0,16])) - expect(n.upper_triangle(2)).to eq(NMatrix.new(4, [1,2,3,4,5,6,7,8,9,10,11,12,0,14,15,16])) + n = NMatrix.seq(4) + 1 + expect(n.upper_triangle).to eq(NMatrix.new(4, [1, 2, 3, 4, 0, 6, 7, 8, 0, 0, 11, 12, 0, 0, 0, 16])) + expect(n.upper_triangle(2)).to eq(NMatrix.new(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 14, 15, 16])) end end context "#lower_triangle" do it "should create a copy with the lower corner set to zero" do - n = NMatrix.seq(4)+1 - expect(n.lower_triangle).to eq(NMatrix.new(4, [1,0,0,0,5,6,0,0,9,10,11,0,13,14,15,16])) - expect(n.lower_triangle(2)).to eq(NMatrix.new(4, [1,2,3,0,5,6,7,8,9,10,11,12,13,14,15,16])) + n = NMatrix.seq(4) + 1 + expect(n.lower_triangle).to eq(NMatrix.new(4, [1, 0, 0, 0, 5, 6, 0, 0, 9, 10, 11, 0, 13, 14, 15, 16])) + expect(n.lower_triangle(2)).to eq(NMatrix.new(4, [1, 2, 3, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])) end end context "#upper_triangle!" do it "should create a copy with the lower corner set to zero" do - n = NMatrix.seq(4)+1 - expect(n.upper_triangle!).to eq(NMatrix.new(4, [1,2,3,4,0,6,7,8,0,0,11,12,0,0,0,16])) - n = NMatrix.seq(4)+1 - expect(n.upper_triangle!(2)).to eq(NMatrix.new(4, [1,2,3,4,5,6,7,8,9,10,11,12,0,14,15,16])) + n = NMatrix.seq(4) + 1 + expect(n.upper_triangle!).to eq(NMatrix.new(4, [1, 2, 3, 4, 0, 6, 7, 8, 0, 0, 11, 12, 0, 0, 0, 16])) + n = NMatrix.seq(4) + 1 + expect(n.upper_triangle!(2)).to eq(NMatrix.new(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 14, 15, 16])) end end context "#lower_triangle!" do it "should create a copy with the lower corner set to zero" do - n = NMatrix.seq(4)+1 - expect(n.lower_triangle!).to eq(NMatrix.new(4, [1,0,0,0,5,6,0,0,9,10,11,0,13,14,15,16])) - n = NMatrix.seq(4)+1 - expect(n.lower_triangle!(2)).to eq(NMatrix.new(4, [1,2,3,0,5,6,7,8,9,10,11,12,13,14,15,16])) + n = NMatrix.seq(4) + 1 + expect(n.lower_triangle!).to eq(NMatrix.new(4, [1, 0, 0, 0, 5, 6, 0, 0, 9, 10, 11, 0, 13, 14, 15, 16])) + n = NMatrix.seq(4) + 1 + expect(n.lower_triangle!(2)).to eq(NMatrix.new(4, [1, 2, 3, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])) end end context "#rank" do it "should get the rank of a 2-dimensional matrix" do - n = NMatrix.seq([2,3]) - expect(n.rank(0, 0)).to eq(N[[0,1,2]]) + n = NMatrix.seq([2, 3]) + expect(n.rank(0, 0)).to eq(N[[0, 1, 2]]) end it "should raise an error when the rank is out of bounds" do - n = NMatrix.seq([2,3]) + n = NMatrix.seq([2, 3]) expect { n.rank(2, 0) }.to raise_error(RangeError) end end @@ -483,47 +482,47 @@ it "should change the shape of a matrix without the contents changing" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.seq(4)+1 - expect(n.reshape([8,2]).to_flat_array).to eq(n.to_flat_array) + n = NMatrix.seq(4) + 1 + expect(n.reshape([8, 2]).to_flat_array).to eq(n.to_flat_array) end it "should permit a change of dimensionality" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.seq(4)+1 - expect(n.reshape([8,1,2]).to_flat_array).to eq(n.to_flat_array) + n = NMatrix.seq(4) + 1 + expect(n.reshape([8, 1, 2]).to_flat_array).to eq(n.to_flat_array) end it "should prevent a resize" do - n = NMatrix.seq(4)+1 - expect { n.reshape([5,2]) }.to raise_error(ArgumentError) + n = NMatrix.seq(4) + 1 + expect { n.reshape([5, 2]) }.to raise_error(ArgumentError) end it "should do the reshape operation in place" do - n = NMatrix.seq(4)+1 - expect(n.reshape!([8,2]).eql?(n)).to eq(true) # because n itself changes + n = NMatrix.seq(4) + 1 + expect(n.reshape!([8, 2]).eql?(n)).to eq(true) # because n itself changes end it "should do the reshape operation in place, changing dimension" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? n = NMatrix.seq(4) - a = n.reshape!([4,2,2]) - expect(n).to eq(NMatrix.seq([4,2,2])) - expect(a).to eq(NMatrix.seq([4,2,2])) + a = n.reshape!([4, 2, 2]) + expect(n).to eq(NMatrix.seq([4, 2, 2])) + expect(a).to eq(NMatrix.seq([4, 2, 2])) end it "reshape and reshape! must produce same result" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.seq(4)+1 - a = NMatrix.seq(4)+1 - expect(n.reshape!([8,2])==a.reshape(8,2)).to eq(true) # because n itself changes + n = NMatrix.seq(4) + 1 + a = NMatrix.seq(4) + 1 + expect(n.reshape!([8, 2]) == a.reshape(8, 2)).to eq(true) # because n itself changes end it "should prevent a resize in place" do - n = NMatrix.seq(4)+1 - expect { n.reshape!([5,2]) }.to raise_error(ArgumentError) + n = NMatrix.seq(4) + 1 + expect { n.reshape!([5, 2]) }.to raise_error(ArgumentError) end end @@ -532,7 +531,7 @@ context(stype) do it "should transpose a #{stype} matrix (2-dimensional)" do n = NMatrix.seq(4, stype: stype) - expect(n.transpose.to_a.flatten).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15]) + expect(n.transpose.to_a.flatten).to eq([0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]) end end end @@ -540,23 +539,23 @@ [:dense, :list].each do |stype| context(stype) do it "should transpose a #{stype} matrix (3-dimensional)" do - n = NMatrix.new([4,4,1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], stype: stype) - expect(n.transpose([2,1,0]).to_flat_array).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15]) - expect(n.transpose([1,0,2]).to_flat_array).to eq([0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15]) - expect(n.transpose([0,2,1]).to_flat_array).to eq(n.to_flat_array) # for dense, make this reshape! + n = NMatrix.new([4, 4, 1], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], stype: stype) + expect(n.transpose([2, 1, 0]).to_flat_array).to eq([0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]) + expect(n.transpose([1, 0, 2]).to_flat_array).to eq([0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]) + expect(n.transpose([0, 2, 1]).to_flat_array).to eq(n.to_flat_array) # for dense, make this reshape! end end it "should just copy a 1-dimensional #{stype} matrix" do - n = NMatrix.new([3], [1,2,3], stype: stype) + n = NMatrix.new([3], [1, 2, 3], stype: stype) expect(n.transpose).to eq n expect(n.transpose).not_to be n end it "should check permute argument if supplied for #{stype} matrix" do - n = NMatrix.new([2,2], [1,2,3,4], stype: stype) - expect{n.transpose *4 }.to raise_error(ArgumentError) - expect{n.transpose [1,1,2] }.to raise_error(ArgumentError) + n = NMatrix.new([2, 2], [1, 2, 3, 4], stype: stype) + expect {n.transpose [4] }.to raise_error(ArgumentError) + expect {n.transpose [1, 1, 2] }.to raise_error(ArgumentError) end end end @@ -567,8 +566,8 @@ it "should work like vector product on a #{stype} (1-dimensional)" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix.new([3], [1,2,3], stype: stype) - expect(m.dot(m)).to eq (NMatrix.new([1],[14])) + m = NMatrix.new([3], [1, 2, 3], stype: stype) + expect(m.dot(m)).to eq NMatrix.new([1], [14]) end end end @@ -579,34 +578,36 @@ [:dense, :list, :yale].each do |right| context ("#{left}?#{right}") do it "tests equality of two equal matrices" do - n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: left) - m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right) + n = NMatrix.new([3, 4], [0, 0, 1, 2, 0, 0, 3, 4, 0, 0, 0, 0], stype: left) + m = NMatrix.new([3, 4], [0, 0, 1, 2, 0, 0, 3, 4, 0, 0, 0, 0], stype: right) - expect(n==m).to eq(true) + expect(n == m).to eq(true) end it "tests equality of two unequal matrices" do - n = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,1], stype: left) - m = NMatrix.new([3,4], [0,0,1,2,0,0,3,4,0,0,0,0], stype: right) + n = NMatrix.new([3, 4], [0, 0, 1, 2, 0, 0, 3, 4, 0, 0, 0, 1], stype: left) + m = NMatrix.new([3, 4], [0, 0, 1, 2, 0, 0, 3, 4, 0, 0, 0, 0], stype: right) - expect(n==m).to eq(false) + expect(n == m).to eq(false) end it "tests equality of matrices with different shapes" do - n = NMatrix.new([2,2], [1,2, 3,4], stype: left) - m = NMatrix.new([2,3], [1,2, 3,4, 5,6], stype: right) - x = NMatrix.new([1,4], [1,2, 3,4], stype: right) + n = NMatrix.new([2, 2], [1, 2, 3, 4], stype: left) + m = NMatrix.new([2, 3], [1, 2, 3, 4, 5, 6], stype: right) + x = NMatrix.new([1, 4], [1, 2, 3, 4], stype: right) - expect{n==m}.to raise_error(ShapeError) - expect{n==x}.to raise_error(ShapeError) + expect {n == m}.to raise_error(ShapeError) + expect {n == x}.to raise_error(ShapeError) end - it "tests equality of matrices with different dimension" do - n = NMatrix.new([2,1], [1,2], stype: left) - m = NMatrix.new([2], [1,2], stype: right) + if left != :yale && right != :yale + it "tests equality of matrices with different dimension" do + n = NMatrix.new([2, 1], [1, 2], stype: left) + m = NMatrix.new([2], [1, 2], stype: right) - expect{n==m}.to raise_error(ShapeError) - end if left != :yale && right != :yale # yale must have dimension 2 + expect {n == m}.to raise_error(ShapeError) + end + end # yale must have dimension 2 end end end @@ -614,27 +615,27 @@ context "#concat" do it "should default to horizontal concatenation" do - n = NMatrix.new([1,3], [1,2,3]) - expect(n.concat(n)).to eq(NMatrix.new([1,6], [1,2,3,1,2,3])) + n = NMatrix.new([1, 3], [1, 2, 3]) + expect(n.concat(n)).to eq(NMatrix.new([1, 6], [1, 2, 3, 1, 2, 3])) end it "should permit vertical concatenation" do - n = NMatrix.new([1,3], [1,2,3]) - expect(n.vconcat(n)).to eq(NMatrix.new([2,3], [1,2,3])) + n = NMatrix.new([1, 3], [1, 2, 3]) + expect(n.vconcat(n)).to eq(NMatrix.new([2, 3], [1, 2, 3])) end it "should permit depth concatenation on tensors" do # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new([1,3,1], [1,2,3]) - expect(n.dconcat(n)).to eq(NMatrix.new([1,3,2], [1,1,2,2,3,3])) + n = NMatrix.new([1, 3, 1], [1, 2, 3]) + expect(n.dconcat(n)).to eq(NMatrix.new([1, 3, 2], [1, 1, 2, 2, 3, 3])) end it "should work on matrices with different size along concat dim" do n = N[[1, 2, 3], - [4, 5, 6]] + [4, 5, 6]] m = N[[7], - [8]] + [8]] # FIXME pending("not yet implemented for NMatrix-JRuby") if jruby? @@ -644,7 +645,7 @@ it "should work on matrices with different size along concat dim" do n = N[[1, 2, 3], - [4, 5, 6]] + [4, 5, 6]] m = N[[7, 8, 9]] @@ -657,15 +658,15 @@ context "#[]" do it "should return values based on indices" do - n = NMatrix.new([2,5], [1,2,3,4,5,6,7,8,9,0]) - expect(n[1,0]).to eq 6 - expect(n[1,0..3]).to eq NMatrix.new([1,4],[6,7,8,9]) + n = NMatrix.new([2, 5], [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) + expect(n[1, 0]).to eq 6 + expect(n[1, 0..3]).to eq NMatrix.new([1, 4], [6, 7, 8, 9]) end it "should work for negative indices" do - n = NMatrix.new([1,5], [1,2,3,4,5]) + n = NMatrix.new([1, 5], [1, 2, 3, 4, 5]) expect(n[-1]).to eq(5) - expect(n[0,0..-2]).to eq(NMatrix.new([1,4],[1,2,3,4])) + expect(n[0, 0..-2]).to eq(NMatrix.new([1, 4], [1, 2, 3, 4])) end end @@ -675,18 +676,18 @@ it "should work in-place for complex dtypes" do pending("not yet implemented for list stype") if stype == :list pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128) + n = NMatrix.new([2, 3], [Complex(2, 3)], stype: stype, dtype: :complex128) n.complex_conjugate! - expect(n).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128)) + expect(n).to eq(NMatrix.new([2, 3], [Complex(2, -3)], stype: stype, dtype: :complex128)) end [:object, :int64].each do |dtype| it "should work in-place for non-complex dtypes" do pending("not yet implemented for list stype") if stype == :list pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype) + n = NMatrix.new([2, 3], 1, stype: stype, dtype: dtype) n.complex_conjugate! - expect(n).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype)) + expect(n).to eq(NMatrix.new([2, 3], [1], stype: stype, dtype: dtype)) end end end @@ -699,16 +700,16 @@ it "should work out-of-place for complex dtypes" do pending("not yet implemented for list stype") if stype == :list pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128) - expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128)) + n = NMatrix.new([2, 3], [Complex(2, 3)], stype: stype, dtype: :complex128) + expect(n.complex_conjugate).to eq(NMatrix.new([2, 3], [Complex(2, -3)], stype: stype, dtype: :complex128)) end [:object, :int64].each do |dtype| it "should work out-of-place for non-complex dtypes" do pending("not yet implemented for list stype") if stype == :list pending("not yet implemented for Complex dtype for NMatrix-JRuby") if jruby? - n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype) - expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype)) + n = NMatrix.new([2, 3], 1, stype: stype, dtype: dtype) + expect(n.complex_conjugate).to eq(NMatrix.new([2, 3], [1], stype: stype, dtype: dtype)) end end end @@ -718,10 +719,10 @@ context "#inject" do it "should sum columns of yale matrix correctly" do n = NMatrix.new([4, 3], stype: :yale, default: 0) - n[0,0] = 1 - n[1,1] = 2 - n[2,2] = 4 - n[3,2] = 8 + n[0, 0] = 1 + n[1, 1] = 2 + n[2, 2] = 4 + n[3, 2] = 8 column_sums = [] n.cols.times do |i| column_sums << n.col(i).inject(:+) @@ -732,41 +733,41 @@ context "#index" do it "returns index of first occurence of an element for a vector" do - n = NMatrix.new([5], [0,22,22,11,11]) + n = NMatrix.new([5], [0, 22, 22, 11, 11]) expect(n.index(22)).to eq([1]) end it "returns index of first occurence of an element for 2-D matrix" do - n = NMatrix.new([3,3], [23,11,23, - 44, 2, 0, - 33, 0, 32]) + n = NMatrix.new([3, 3], [23, 11, 23, + 44, 2, 0, + 33, 0, 32,]) - expect(n.index(0)).to eq([1,2]) + expect(n.index(0)).to eq([1, 2]) end it "returns index of first occerence of an element for N-D matrix" do - n = NMatrix.new([3,3,3], [23,11,23, 44, 2, 0, 33, 0, 32, - 23,11,23, 44, 2, 0, 33, 0, 32, - 23,11,23, 44, 2, 0, 33, 0, 32]) + n = NMatrix.new([3, 3, 3], [23, 11, 23, 44, 2, 0, 33, 0, 32, + 23, 11, 23, 44, 2, 0, 33, 0, 32, + 23, 11, 23, 44, 2, 0, 33, 0, 32,]) - expect(n.index(44)).to eq([0,1,0]) + expect(n.index(44)).to eq([0, 1, 0]) end end context "#last" do it "returns the last element of a 1-dimensional NMatrix" do - n = NMatrix.new([1,4], [1,2,3,4]) + n = NMatrix.new([1, 4], [1, 2, 3, 4]) expect(n.last).to eq(4) end it "returns the last element of a 2-dimensional NMatrix" do - n = NMatrix.new([2,2], [4,8,12,16]) + n = NMatrix.new([2, 2], [4, 8, 12, 16]) expect(n.last).to eq(16) end it "returns the last element of a 3-dimensional NMatrix" do - n = NMatrix.new([2,2,2], [1,2,3,4,5,6,7,8]) + n = NMatrix.new([2, 2, 2], [1, 2, 3, 4, 5, 6, 7, 8]) expect(n.last).to eq(8) end end @@ -774,36 +775,34 @@ context "#diagonal" do ALL_DTYPES.each do |dtype| before do - @square_matrix = NMatrix.new([3,3], [ - 23,11,23, + @square_matrix = NMatrix.new([3, 3], [ + 23, 11, 23, 44, 2, 0, - 33, 0, 32 - ], dtype: dtype - ) + 33, 0, 32, + ], dtype: dtype) - @rect_matrix = NMatrix.new([4,3], [ - 23,11,23, + @rect_matrix = NMatrix.new([4, 3], [ + 23, 11, 23, 44, 2, 0, - 33, 0,32, - 11,22,33 - ], dtype: dtype - ) + 33, 0, 32, + 11, 22, 33, + ], dtype: dtype) end it "returns main diagonal for square matrix" do - expect(@square_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32]) + expect(@square_matrix.diagonal).to eq(NMatrix.new([3], [23, 2, 32])) end it "returns main diagonal for rectangular matrix" do - expect(@rect_matrix.diagonal).to eq(NMatrix.new [3], [23,2,32]) + expect(@rect_matrix.diagonal).to eq(NMatrix.new([3], [23, 2, 32])) end it "returns anti-diagonal for square matrix" do - expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33]) + expect(@square_matrix.diagonal(false)).to eq(NMatrix.new([3], [23, 2, 33])) end it "returns anti-diagonal for rectangular matrix" do - expect(@square_matrix.diagonal(false)).to eq(NMatrix.new [3], [23,2,33]) + expect(@square_matrix.diagonal(false)).to eq(NMatrix.new([3], [23, 2, 33])) end end end @@ -814,8 +813,8 @@ end it "checks count argument" do - expect{@sample_matrix.repeat(1, 0)}.to raise_error(ArgumentError) - expect{@sample_matrix.repeat(-2, 0)}.to raise_error(ArgumentError) + expect {@sample_matrix.repeat(1, 0)}.to raise_error(ArgumentError) + expect {@sample_matrix.repeat(-2, 0)}.to raise_error(ArgumentError) end it "returns repeated matrix" do @@ -842,18 +841,20 @@ @expected_for_sparse = [NMatrix.new([1, 3], [1, 2, 3]), NMatrix.new([2, 1], [4, 5])] @expected_for_sparse_ij = [NMatrix.new([3, 1], [1, 2, 3]), NMatrix.new([1, 2], [4, 5])] # FIXME - @expected_3dim = [NMatrix.new([1, 3, 1], [1, 2, 3]).repeat(2, 0).repeat(2, 2), - NMatrix.new([2, 1, 1], [4, 5]).repeat(3, 1).repeat(2, 2), - NMatrix.new([1, 1, 2], [6, 7]).repeat(2, 0).repeat(3, 1)] unless jruby? + unless jruby? + @expected_3dim = [NMatrix.new([1, 3, 1], [1, 2, 3]).repeat(2, 0).repeat(2, 2), + NMatrix.new([2, 1, 1], [4, 5]).repeat(3, 1).repeat(2, 2), + NMatrix.new([1, 1, 2], [6, 7]).repeat(2, 0).repeat(3, 1),] + end @expected_3dim_sparse_ij = [NMatrix.new([3, 1, 1], [1, 2, 3]), NMatrix.new([1, 2, 1], [4, 5]), - NMatrix.new([1, 1, 2], [6, 7])] + NMatrix.new([1, 1, 2], [6, 7]),] end it "checks arrays count" do pending("Not yet implemented for NMatrix JRuby") if jruby? - expect{NMatrix.meshgrid([@x])}.to raise_error(ArgumentError) - expect{NMatrix.meshgrid([])}.to raise_error(ArgumentError) + expect {NMatrix.meshgrid([@x])}.to raise_error(ArgumentError) + expect {NMatrix.meshgrid([])}.to raise_error(ArgumentError) end it "flattens input arrays before use" do @@ -875,7 +876,7 @@ pending("Not yet implemented for NMatrix JRuby") if jruby? expect(NMatrix.meshgrid([@x, @y], indexing: :ij)).to eq(@expected_for_ij) expect(NMatrix.meshgrid([@x, @y], indexing: :xy)).to eq(@expected_result) - expect{NMatrix.meshgrid([@x, @y], indexing: :not_ij_not_xy)}.to raise_error(ArgumentError) + expect {NMatrix.meshgrid([@x, @y], indexing: :not_ij_not_xy)}.to raise_error(ArgumentError) end it "works well with both options set" do diff --git a/spec/01_enum_spec.rb b/spec/01_enum_spec.rb index 9a27822b..a897495c 100644 --- a/spec/01_enum_spec.rb +++ b/spec/01_enum_spec.rb @@ -25,13 +25,13 @@ # Enumerator tests for NMatrix. These should load early, as they # test functionality essential to matrix printing. # -require 'spec_helper' +require "spec_helper" describe "NMatrix enumeration for" do [:dense, :yale, :list].each do |stype| context stype do let(:n) { create_rectangular_matrix(stype) } - let(:m) { n[1..4,1..3] } + let(:m) { n[1..4, 1..3] } if stype == :yale it "should iterate properly along each row of a slice" do @@ -41,16 +41,16 @@ jj = [] m.extend NMatrix::YaleFunctions m.each_row do |row| - row.each_with_indices do |v,i,j| + row.each_with_indices do |v, i, j| vv << v ii << i jj << j end end - expect(vv).to eq([7,8,9, 12,13,0, 0,0,0, 0,17,18]) - expect(ii).to eq([0]*12) - expect(jj).to eq([0,1,2]*4) + expect(vv).to eq([7, 8, 9, 12, 13, 0, 0, 0, 0, 0, 17, 18]) + expect(ii).to eq([0] * 12) + expect(jj).to eq([0, 1, 2] * 4) end it "should iterate along diagonal portion of A array" do @@ -58,13 +58,13 @@ vv = [] ii = [] jj = [] - n.send :__yale_stored_diagonal_each_with_indices__ do |v,i,j| + n.send :__yale_stored_diagonal_each_with_indices__ do |v, i, j| vv << v ii << i jj << j end - expect(vv).to eq([1,7,13,0,19]) - expect(ii).to eq([0,1,2,3,4]) + expect(vv).to eq([1, 7, 13, 0, 19]) + expect(ii).to eq([0, 1, 2, 3, 4]) expect(jj).to eq(ii) end @@ -73,31 +73,31 @@ vv = [] ii = [] jj = [] - n.send :__yale_stored_nondiagonal_each_with_indices__ do |v,i,j| + n.send :__yale_stored_nondiagonal_each_with_indices__ do |v, i, j| vv << v ii << i jj << j end - expect(vv).to eq([2,3,4,5, 6,8,9,10, 11,12,14,15, 16,17,18,20]) - expect(ii).to eq([[0]*4, [1]*4, [2]*4, [4]*4].flatten) - expect(jj).to eq([1,2,3,4, 0,2,3,5, 0,1,4,5, 0,2,3,5]) + expect(vv).to eq([2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 20]) + expect(ii).to eq([[0] * 4, [1] * 4, [2] * 4, [4] * 4].flatten) + expect(jj).to eq([1, 2, 3, 4, 0, 2, 3, 5, 0, 1, 4, 5, 0, 2, 3, 5]) end it "should iterate along a sliced diagonal portion of an A array" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - m = n[0..3,1..3] + m = n[0..3, 1..3] vv = [] ii = [] jj = [] - m.send :__yale_stored_diagonal_each_with_indices__ do |v,i,j| + m.send :__yale_stored_diagonal_each_with_indices__ do |v, i, j| vv << v ii << i jj << j end - expect(vv).to eq([7,13,0]) - expect(ii).to eq([1,2,3]) - expect(jj).to eq([0,1,2]) + expect(vv).to eq([7, 13, 0]) + expect(ii).to eq([1, 2, 3]) + expect(jj).to eq([0, 1, 2]) end it "should iterate along a sliced non-diagonal portion of a sliced A array" do @@ -107,15 +107,15 @@ jj = [] n.extend NMatrix::YaleFunctions m.extend NMatrix::YaleFunctions - m.send :__yale_stored_nondiagonal_each_with_indices__ do |v,i,j| + m.send :__yale_stored_nondiagonal_each_with_indices__ do |v, i, j| vv << v ii << i jj << j end - expect(ii).to eq([0,0, 1, 3,3 ]) - expect(jj).to eq([1,2, 0, 1,2 ]) - expect(vv).to eq([8,9, 12, 17,18]) + expect(ii).to eq([0, 0, 1, 3, 3]) + expect(jj).to eq([1, 2, 0, 1, 2]) + expect(vv).to eq([8, 9, 12, 17, 18]) end it "should visit each stored element of the matrix in order by indices" do @@ -123,15 +123,15 @@ vv = [] ii = [] jj = [] - n.each_ordered_stored_with_indices do |v,i,j| + n.each_ordered_stored_with_indices do |v, i, j| vv << v ii << i jj << j end expect(vv).to eq([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 16, 17, 18, 19, 20]) - expect(ii).to eq([[0]*5, [1]*5, [2]*5, [3]*1, [4]*5].flatten) - expect(jj).to eq([0,1,2,3,4, 0,1,2,3,5, 0,1,2,4,5, 3, 0,2,3,4,5]) + expect(ii).to eq([[0] * 5, [1] * 5, [2] * 5, [3] * 1, [4] * 5].flatten) + expect(jj).to eq([0, 1, 2, 3, 4, 0, 1, 2, 3, 5, 0, 1, 2, 4, 5, 3, 0, 2, 3, 4, 5]) end it "should visit each stored element of the slice in order by indices" do @@ -139,14 +139,14 @@ vv = [] ii = [] jj = [] - m.each_ordered_stored_with_indices do |v,i,j| + m.each_ordered_stored_with_indices do |v, i, j| vv << v ii << i jj << j end - expect(ii).to eq([0,0,0, 1,1, 2, 3,3 ]) - expect(jj).to eq([0,1,2, 0,1, 2, 1,2 ]) - expect(vv).to eq([7,8,9, 12,13, 0, 17,18 ]) + expect(ii).to eq([0, 0, 0, 1, 1, 2, 3, 3]) + expect(jj).to eq([0, 1, 2, 0, 1, 2, 1, 2]) + expect(vv).to eq([7, 8, 9, 12, 13, 0, 17, 18]) end end @@ -154,33 +154,32 @@ vv = [] ii = [] jj = [] - n.each_with_indices do |v,i,j| + n.each_with_indices do |v, i, j| vv << v ii << i jj << j end - expect(vv).to eq([1,2,3,4,5,0,6,7,8,9,0,10,11,12,13,0,14,15,0,0,0,0,0,0,16,0,17,18,19,20]) - expect(ii).to eq([[0]*6, [1]*6, [2]*6, [3]*6, [4]*6].flatten) - expect(jj).to eq([0,1,2,3,4,5]*5) + expect(vv).to eq([1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 0, 10, 11, 12, 13, 0, 14, 15, 0, 0, 0, 0, 0, 0, 16, 0, 17, 18, 19, 20]) + expect(ii).to eq([[0] * 6, [1] * 6, [2] * 6, [3] * 6, [4] * 6].flatten) + expect(jj).to eq([0, 1, 2, 3, 4, 5] * 5) end it "should visit each cell in the slice as if dense, making indices available" do vv = [] ii = [] jj = [] - m.each_with_indices do |v,i,j| + m.each_with_indices do |v, i, j| vv << v ii << i jj << j end - expect(jj).to eq([0,1,2]*4) - expect(ii).to eq([[0]*3, [1]*3, [2]*3, [3]*3].flatten) - expect(vv).to eq([7,8,9,12,13,0,0,0,0,0,17,18]) - + expect(jj).to eq([0, 1, 2] * 4) + expect(ii).to eq([[0] * 3, [1] * 3, [2] * 3, [3] * 3].flatten) + expect(vv).to eq([7, 8, 9, 12, 13, 0, 0, 0, 0, 0, 17, 18]) end - if stype == :list or stype == :dense then + if (stype == :list) || (stype == :dense) it "should correctly map to a matrix with a single element" do nm = N.new([1], [2.0], stype: stype) expect(nm.map { |e| e**2 }).to eq N.new([1], [4.0], stype: stype) diff --git a/spec/02_slice_spec.rb b/spec/02_slice_spec.rb index 80d1b0a8..e00db3d4 100644 --- a/spec/02_slice_spec.rb +++ b/spec/02_slice_spec.rb @@ -25,48 +25,48 @@ # Test of slice operations. High priority tests since reference # slicing is needed for pretty_print. # -require 'spec_helper' +require "spec_helper" describe "Slice operation" do include RSpec::Longrun::DSL [:dense, :list, :yale].each do |stype| context "for #{stype}" do - #GC.start # don't have to do this, but it helps to make sure we've cleaned up our pointers properly. + # GC.start # don't have to do this, but it helps to make sure we've cleaned up our pointers properly. let(:stype_matrix) { create_matrix(stype) } it "should correctly return a row of a reference-slice" do n = create_rectangular_matrix(stype) - stype_matrix = n[1..4,1..3] + stype_matrix = n[1..4, 1..3] expect(stype_matrix.row(1, :copy)).to eq(stype_matrix.row(1, :reference)) - expect(stype_matrix.row(1, :copy).to_flat_array).to eq([12,13,0]) + expect(stype_matrix.row(1, :copy).to_flat_array).to eq([12, 13, 0]) end if stype == :yale it "should binary search for the left boundary of a partial row of stored indices correctly" do - #FIXME + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? n = NMatrix.new(10, stype: :yale, dtype: :int32) - n[3,0] = 1 - #n[3,2] = 2 - n[3,3] = 3 - n[3,4] = 4 - n[3,6] = 5 - n[3,8] = 6 - n[3,9] = 7 + n[3, 0] = 1 + # n[3,2] = 2 + n[3, 3] = 3 + n[3, 4] = 4 + n[3, 6] = 5 + n[3, 8] = 6 + n[3, 9] = 7 vs = [] is = [] js = [] - n[3,1..9].each_stored_with_indices do |v,i,j| + n[3, 1..9].each_stored_with_indices do |v, i, j| vs << v is << i js << j end - expect(vs).to eq([3,4,5,6,7]) - expect(js).to eq([2,3,5,7,8]) - expect(is).to eq([0,0,0,0,0]) + expect(vs).to eq([3, 4, 5, 6, 7]) + expect(js).to eq([2, 3, 5, 7, 8]) + expect(is).to eq([0, 0, 0, 0, 0]) end elsif stype == :list it "should iterate across a partial row of stored indices" do @@ -75,59 +75,59 @@ js = [] STDERR.puts("now") if stype == :yale - stype_matrix[2,1..2].each_stored_with_indices do |v,i,j| + stype_matrix[2, 1..2].each_stored_with_indices do |v, i, j| vs << v is << i js << j end - expect(vs).to eq([7,8]) - expect(is).to eq([0,0]) - expect(js).to eq([0,1]) + expect(vs).to eq([7, 8]) + expect(is).to eq([0, 0]) + expect(js).to eq([0, 1]) end end unless stype == :dense it "should iterate across a row of stored indices" do - #FIXME + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? vs = [] is = [] js = [] - stype_matrix[2,0..2].each_stored_with_indices do |v,i,j| + stype_matrix[2, 0..2].each_stored_with_indices do |v, i, j| vs << v is << i js << j end - expect(vs).to eq(stype == :yale ? [8,6,7] : [6,7,8]) - expect(is).to eq([0,0,0]) - expect(js).to eq(stype == :yale ? [2,0,1] : [0,1,2]) + expect(vs).to eq(stype == :yale ? [8, 6, 7] : [6, 7, 8]) + expect(is).to eq([0, 0, 0]) + expect(js).to eq(stype == :yale ? [2, 0, 1] : [0, 1, 2]) end it "should iterate across a submatrix of stored indices" do - #FIXME + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? vs = [] is = [] js = [] - stype_matrix[0..1,1..2].each_stored_with_indices do |v,i,j| + stype_matrix[0..1, 1..2].each_stored_with_indices do |v, i, j| vs << v is << i js << j end - expect(vs).to eq(stype == :yale ? [4,1,2,5] : [1,2,4,5]) - expect(is).to eq(stype == :yale ? [1,0,0,1] : [0,0,1,1]) - expect(js).to eq(stype == :yale ? [0,0,1,1] : [0,1,0,1]) + expect(vs).to eq(stype == :yale ? [4, 1, 2, 5] : [1, 2, 4, 5]) + expect(is).to eq(stype == :yale ? [1, 0, 0, 1] : [0, 0, 1, 1]) + expect(js).to eq(stype == :yale ? [0, 0, 1, 1] : [0, 1, 0, 1]) end end it "should return correct supershape" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - x = NMatrix.random([10,12]) - y = x[0...8,5...12] - expect(y.shape).to eq([8,7]) - expect(y.supershape).to eq([10,12]) + x = NMatrix.random([10, 12]) + y = x[0...8, 5...12] + expect(y.shape).to eq([8, 7]) + expect(y.supershape).to eq([10, 12]) end it "should have #is_ref? method" do @@ -140,70 +140,70 @@ end it "reference should compare with non-reference" do - expect(stype_matrix.slice(1..2,0..1)).to eq(stype_matrix[1..2, 0..1]) - expect(stype_matrix[1..2,0..1]).to eq(stype_matrix.slice(1..2, 0..1)) - expect(stype_matrix[1..2,0..1]).to eq(stype_matrix[1..2, 0..1]) + expect(stype_matrix.slice(1..2, 0..1)).to eq(stype_matrix[1..2, 0..1]) + expect(stype_matrix[1..2, 0..1]).to eq(stype_matrix.slice(1..2, 0..1)) + expect(stype_matrix[1..2, 0..1]).to eq(stype_matrix[1..2, 0..1]) end context "with copying" do - it 'should return an NMatrix' do - n = stype_matrix.slice(0..1,0..1) - expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to be true + it "should return an NMatrix" do + n = stype_matrix.slice(0..1, 0..1) + expect(nm_eql(n, NMatrix.new([2, 2], [0, 1, 3, 4], dtype: :int32))).to be true end - it 'should return a copy of 2x2 matrix to self elements' do + it "should return a copy of 2x2 matrix to self elements" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - n = stype_matrix.slice(1..2,0..1) - expect(n.shape).to eql([2,2]) + n = stype_matrix.slice(1..2, 0..1) + expect(n.shape).to eql([2, 2]) - expect(n[1,1]).to eq(stype_matrix[2,1]) - n[1,1] = -9 - expect(stype_matrix[2,1]).to eql(7) + expect(n[1, 1]).to eq(stype_matrix[2, 1]) + n[1, 1] = -9 + expect(stype_matrix[2, 1]).to eql(7) end - it 'should return a 1x2 matrix without refs to self elements' do - #FIXME + it "should return a 1x2 matrix without refs to self elements" do + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - n = stype_matrix.slice(0,1..2) - expect(n.shape).to eql([1,2]) + n = stype_matrix.slice(0, 1..2) + expect(n.shape).to eql([1, 2]) - expect(n[0]).to eq(stype_matrix[0,1]) - expect(n[1]).to eq(stype_matrix[0,2]) + expect(n[0]).to eq(stype_matrix[0, 1]) + expect(n[1]).to eq(stype_matrix[0, 2]) n[0] = -9 - expect(stype_matrix[0,1]).to eql(1) - expect(stype_matrix[0,2]).to eql(2) + expect(stype_matrix[0, 1]).to eql(1) + expect(stype_matrix[0, 2]).to eql(2) end - it 'should return a 2x1 matrix without refs to self elements' do + it "should return a 2x1 matrix without refs to self elements" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? stype_matrix.extend NMatrix::YaleFunctions - n = stype_matrix.slice(0..1,1) - expect(n.shape).to eql([2,1]) + n = stype_matrix.slice(0..1, 1) + expect(n.shape).to eql([2, 1]) - expect(n[0]).to eq(stype_matrix[0,1]) - expect(n[1]).to eq(stype_matrix[1,1]) + expect(n[0]).to eq(stype_matrix[0, 1]) + expect(n[1]).to eq(stype_matrix[1, 1]) n[0] = -9 - expect(stype_matrix[0,1]).to eql(1) - expect(stype_matrix[1,1]).to eql(4) + expect(stype_matrix[0, 1]).to eql(1) + expect(stype_matrix[1, 1]).to eql(4) end - it 'should be correct slice for range 0..2 and 0...3' do - expect(stype_matrix.slice(0..2,0..2)).to eq(stype_matrix.slice(0...3,0...3)) + it "should be correct slice for range 0..2 and 0...3" do + expect(stype_matrix.slice(0..2, 0..2)).to eq(stype_matrix.slice(0...3, 0...3)) end [:dense, :list, :yale].each do |cast_type| it "should cast copied slice from #{stype.upcase} to #{cast_type.upcase}" do - expect(nm_eql(stype_matrix.slice(1..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(1..2,1..2))).to be true - expect(nm_eql(stype_matrix.slice(0..1, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..1,1..2))).to be true - expect(nm_eql(stype_matrix.slice(1..2, 0..1).cast(cast_type, :int32), stype_matrix.slice(1..2,0..1))).to be true - expect(nm_eql(stype_matrix.slice(0..1, 0..1).cast(cast_type, :int32), stype_matrix.slice(0..1,0..1))).to be true + expect(nm_eql(stype_matrix.slice(1..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(1..2, 1..2))).to be true + expect(nm_eql(stype_matrix.slice(0..1, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..1, 1..2))).to be true + expect(nm_eql(stype_matrix.slice(1..2, 0..1).cast(cast_type, :int32), stype_matrix.slice(1..2, 0..1))).to be true + expect(nm_eql(stype_matrix.slice(0..1, 0..1).cast(cast_type, :int32), stype_matrix.slice(0..1, 0..1))).to be true # Non square - expect(nm_eql(stype_matrix.slice(0..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..2,1..2))).to be true - #require 'pry' - #binding.pry if cast_type == :yale - expect(nm_eql(stype_matrix.slice(1..2, 0..2).cast(cast_type, :int32), stype_matrix.slice(1..2,0..2))).to be true + expect(nm_eql(stype_matrix.slice(0..2, 1..2).cast(cast_type, :int32), stype_matrix.slice(0..2, 1..2))).to be true + # require 'pry' + # binding.pry if cast_type == :yale + expect(nm_eql(stype_matrix.slice(1..2, 0..2).cast(cast_type, :int32), stype_matrix.slice(1..2, 0..2))).to be true # Full expect(nm_eql(stype_matrix.slice(0..2, 0..2).cast(cast_type, :int32), stype_matrix)).to be true @@ -212,131 +212,128 @@ end # Yale: - #context "by copy" do - #it "should correctly preserve zeros" do - # stype_matrix = NMatrix.new(:yale, 3, :int64) - # column_slice = stype_matrix.column(2, :copy) - # column_slice[0].should == 0 - # column_slice[1].should == 0 - # column_slice[2].should == 0 - #end - #end + # context "by copy" do + # it "should correctly preserve zeros" do + # stype_matrix = NMatrix.new(:yale, 3, :int64) + # column_slice = stype_matrix.column(2, :copy) + # column_slice[0].should == 0 + # column_slice[1].should == 0 + # column_slice[2].should == 0 + # end + # end context "by reference" do - it 'should return an NMatrix' do - n = stype_matrix[0..1,0..1] - expect(nm_eql(n, NMatrix.new([2,2], [0,1,3,4], dtype: :int32))).to be true + it "should return an NMatrix" do + n = stype_matrix[0..1, 0..1] + expect(nm_eql(n, NMatrix.new([2, 2], [0, 1, 3, 4], dtype: :int32))).to be true end - it 'should return a 2x2 matrix with refs to self elements' do - #FIXME + it "should return a 2x2 matrix with refs to self elements" do + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? # and :cast_type != :dense - n = stype_matrix[1..2,0..1] - expect(n.shape).to eql([2,2]) + n = stype_matrix[1..2, 0..1] + expect(n.shape).to eql([2, 2]) - expect(n[0,0]).to eq(stype_matrix[1,0]) - n[0,0] = -9 - expect(stype_matrix[1,0]).to eql(-9) + expect(n[0, 0]).to eq(stype_matrix[1, 0]) + n[0, 0] = -9 + expect(stype_matrix[1, 0]).to eql(-9) end - it 'should return a 1x2 vector with refs to self elements' do - #FIXME + it "should return a 1x2 vector with refs to self elements" do + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? # and :cast_type != :dense - n = stype_matrix[0,1..2] - expect(n.shape).to eql([1,2]) + n = stype_matrix[0, 1..2] + expect(n.shape).to eql([1, 2]) - expect(n[0]).to eq(stype_matrix[0,1]) + expect(n[0]).to eq(stype_matrix[0, 1]) n[0] = -9 - expect(stype_matrix[0,1]).to eql(-9) + expect(stype_matrix[0, 1]).to eql(-9) end - it 'should return a 2x1 vector with refs to self elements' do + it "should return a 2x1 vector with refs to self elements" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? - n = stype_matrix[0..1,1] - expect(n.shape).to eql([2,1]) + n = stype_matrix[0..1, 1] + expect(n.shape).to eql([2, 1]) - expect(n[0]).to eq(stype_matrix[0,1]) + expect(n[0]).to eq(stype_matrix[0, 1]) n[0] = -9 - expect(stype_matrix[0,1]).to eql(-9) + expect(stype_matrix[0, 1]).to eql(-9) end - it 'should slice again' do + it "should slice again" do n = stype_matrix[1..2, 1..2] - expect(nm_eql(n[1,0..1], NVector.new(2, [7,8], dtype: :int32).transpose)).to be true + expect(nm_eql(n[1, 0..1], NVector.new(2, [7, 8], dtype: :int32).transpose)).to be true end - it 'should be correct slice for range 0..2 and 0...3' do - expect(stype_matrix[0..2,0..2]).to eq(stype_matrix[0...3,0...3]) + it "should be correct slice for range 0..2 and 0...3" do + expect(stype_matrix[0..2, 0..2]).to eq(stype_matrix[0...3, 0...3]) end - it 'should correctly handle :* slice notation' do - expect(stype_matrix[:*,0]).to eq stype_matrix[0...stype_matrix.shape[0], 0] + it "should correctly handle :* slice notation" do + expect(stype_matrix[:*, 0]).to eq stype_matrix[0...stype_matrix.shape[0], 0] end if stype == :dense - [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |left_dtype| - [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |right_dtype| - + [: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. - next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype) + next if [:byte, :int8].include?(left_dtype) && [:byte, :int8].include?(right_dtype) # For now, don't bother testing int-int mult. - #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype) - it "handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do - #STDERR.puts "dtype=#{dtype.to_s}" - #STDERR.puts "2" - - nary = if left_dtype.to_s =~ /complex/ - COMPLEX_MATRIX43A_ARRAY - else - MATRIX43A_ARRAY - end - - mary = if right_dtype.to_s =~ /complex/ - COMPLEX_MATRIX32A_ARRAY - else - MATRIX32A_ARRAY - end - - n = NMatrix.new([4,3], nary, dtype: left_dtype)[1..3,1..2] - m = NMatrix.new([3,2], mary, dtype: right_dtype)[1..2,0..1] + # next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype) + it "handles #{left_dtype} dot #{right_dtype} matrix multiplication" do + # STDERR.puts "dtype=#{dtype.to_s}" + # STDERR.puts "2" + + nary = if /complex/.match?(left_dtype.to_s) + COMPLEX_MATRIX43A_ARRAY + else + MATRIX43A_ARRAY + end + + mary = if /complex/.match?(right_dtype.to_s) + COMPLEX_MATRIX32A_ARRAY + else + MATRIX32A_ARRAY + end + + n = NMatrix.new([4, 3], nary, dtype: left_dtype)[1..3, 1..2] + m = NMatrix.new([3, 2], mary, dtype: right_dtype)[1..2, 0..1] r = n.dot m - expect(r.shape).to eql([3,2]) - - expect(r[0,0]).to eq(219.0) - expect(r[0,1]).to eq(185.0) - expect(r[1,0]).to eq(244.0) - expect(r[1,1]).to eq(205.0) - expect(r[2,0]).to eq(42.0) - expect(r[2,1]).to eq(35.0) - + expect(r.shape).to eql([3, 2]) + + expect(r[0, 0]).to eq(219.0) + expect(r[0, 1]).to eq(185.0) + expect(r[1, 0]).to eq(244.0) + expect(r[1, 1]).to eq(205.0) + expect(r[2, 0]).to eq(42.0) + expect(r[2, 1]).to eq(35.0) end end end context "operations" do - it "correctly transposes slices" do - expect(stype_matrix[0...3,0].transpose).to eq NMatrix[[0, 3, 6]] - expect(stype_matrix[0...3,1].transpose).to eq NMatrix[[1, 4, 7]] - expect(stype_matrix[0...3,2].transpose).to eq NMatrix[[2, 5, 8]] - expect(stype_matrix[0,0...3].transpose).to eq NMatrix[[0], [1], [2]] - expect(stype_matrix[1,0...3].transpose).to eq NMatrix[[3], [4], [5]] - expect(stype_matrix[2,0...3].transpose).to eq NMatrix[[6], [7], [8]] - expect(stype_matrix[1..2,1..2].transpose).to eq NMatrix[[4, 7], [5, 8]] + expect(stype_matrix[0...3, 0].transpose).to eq NMatrix[[0, 3, 6]] + expect(stype_matrix[0...3, 1].transpose).to eq NMatrix[[1, 4, 7]] + expect(stype_matrix[0...3, 2].transpose).to eq NMatrix[[2, 5, 8]] + expect(stype_matrix[0, 0...3].transpose).to eq NMatrix[[0], [1], [2]] + expect(stype_matrix[1, 0...3].transpose).to eq NMatrix[[3], [4], [5]] + expect(stype_matrix[2, 0...3].transpose).to eq NMatrix[[6], [7], [8]] + expect(stype_matrix[1..2, 1..2].transpose).to eq NMatrix[[4, 7], [5, 8]] end it "adds slices" do - expect(NMatrix[[0,0,0]] + stype_matrix[1,0..2]).to eq NMatrix[[3, 4, 5]] + expect(NMatrix[[0, 0, 0]] + stype_matrix[1, 0..2]).to eq NMatrix[[3, 4, 5]] end it "scalar adds to slices" do - expect(stype_matrix[1,0..2]+1).to eq NMatrix[[4, 5, 6]] + expect(stype_matrix[1, 0..2] + 1).to eq NMatrix[[4, 5, 6]] end it "compares slices to scalars" do - #FIXME + # FIXME pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? (stype_matrix[1, 0..2] > 2).each { |e| expect(e != 0).to be true } end @@ -358,43 +355,42 @@ expect(els[1]).to eq [4, 0, 1] expect(els[2]).to eq [5, 0, 2] end - end end - example 'should be cleaned up by garbage collector without errors' do + example "should be cleaned up by garbage collector without errors" do step "reference slice" do 1.times do - n = stype_matrix[1..2,0..1] + n = stype_matrix[1..2, 0..1] end GC.start end step "reference slice of casted-copy" do - expect(stype_matrix).to eq(NMatrix.new([3,3], (0..9).to_a, dtype: :int32).cast(stype, :int32)) + expect(stype_matrix).to eq(NMatrix.new([3, 3], (0..9).to_a, dtype: :int32).cast(stype, :int32)) n = nil 1.times do - m = NMatrix.new([2,2], [1,2,3,4]).cast(stype, :int32) - n = m[0..1,0..1] + m = NMatrix.new([2, 2], [1, 2, 3, 4]).cast(stype, :int32) + n = m[0..1, 0..1] end GC.start - expect(n).to eq(NMatrix.new([2,2], [1,2,3,4]).cast(stype, :int32)) + expect(n).to eq(NMatrix.new([2, 2], [1, 2, 3, 4]).cast(stype, :int32)) end end [:dense, :list, :yale].each do |cast_type| it "should cast a square reference-slice from #{stype.upcase} to #{cast_type.upcase}" do - expect(nm_eql(stype_matrix[1..2, 1..2].cast(cast_type), stype_matrix[1..2,1..2])).to be true - expect(nm_eql(stype_matrix[0..1, 1..2].cast(cast_type), stype_matrix[0..1,1..2])).to be true - expect(nm_eql(stype_matrix[1..2, 0..1].cast(cast_type), stype_matrix[1..2,0..1])).to be true - expect(nm_eql(stype_matrix[0..1, 0..1].cast(cast_type), stype_matrix[0..1,0..1])).to be true + expect(nm_eql(stype_matrix[1..2, 1..2].cast(cast_type), stype_matrix[1..2, 1..2])).to be true + expect(nm_eql(stype_matrix[0..1, 1..2].cast(cast_type), stype_matrix[0..1, 1..2])).to be true + expect(nm_eql(stype_matrix[1..2, 0..1].cast(cast_type), stype_matrix[1..2, 0..1])).to be true + expect(nm_eql(stype_matrix[0..1, 0..1].cast(cast_type), stype_matrix[0..1, 0..1])).to be true end it "should cast a rectangular reference-slice from #{stype.upcase} to #{cast_type.upcase}" do # Non square - expect(nm_eql(stype_matrix[0..2, 1..2].cast(cast_type), stype_matrix[0..2,1..2])).to be true # FIXME: memory problem. - expect(nm_eql(stype_matrix[1..2, 0..2].cast(cast_type), stype_matrix[1..2,0..2])).to be true # this one is fine + expect(nm_eql(stype_matrix[0..2, 1..2].cast(cast_type), stype_matrix[0..2, 1..2])).to be true # FIXME: memory problem. + expect(nm_eql(stype_matrix[1..2, 0..2].cast(cast_type), stype_matrix[1..2, 0..2])).to be true # this one is fine end it "should cast a square full-matrix reference-slice from #{stype.upcase} to #{cast_type.upcase}" do diff --git a/spec/03_nmatrix_monkeys_spec.rb b/spec/03_nmatrix_monkeys_spec.rb index f5305b17..23ed4677 100644 --- a/spec/03_nmatrix_monkeys_spec.rb +++ b/spec/03_nmatrix_monkeys_spec.rb @@ -1,24 +1,24 @@ -require 'spec_helper' +require "spec_helper" describe NMatrix do describe "#to_a" do it "creates an Array with the same dimensions" do - n = NMatrix.seq([3,2]) + n = NMatrix.seq([3, 2]) expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]]) end it "creates an Array with the proper element type" do - n = NMatrix.seq([3,2], dtype: :float64) + n = NMatrix.seq([3, 2], dtype: :float64) expect(n.to_a).to eq([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0]]) end it "properly interprets list matrices" do - n = NMatrix.seq([3,2], stype: :list) + n = NMatrix.seq([3, 2], stype: :list) expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]]) end it "properly interprets yale matrices" do - n = NMatrix.seq([3,2], stype: :yale) + n = NMatrix.seq([3, 2], stype: :yale) expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]]) end end @@ -30,26 +30,26 @@ let(:a) {(0..5).to_a} it "uses a given shape and type" do - expect(a.to_nm([3,2]).dtype).to eq :int64 - expect(a.to_nm([3,2])).to eq(NMatrix.seq([3,2])) + expect(a.to_nm([3, 2]).dtype).to eq :int64 + expect(a.to_nm([3, 2])).to eq(NMatrix.seq([3, 2])) end it "guesses dtype based on first element" do a[0] = 0.0 - expect(a.to_nm([3,2]).dtype).to eq :float64 + expect(a.to_nm([3, 2]).dtype).to eq :float64 end it "defaults to dtype :object if necessary" do - #FIXME + # FIXME pending("not yet implemented for object dtype for NMatrix-JRuby") if jruby? - a = %w(this is an array of strings) - expect(a.to_nm([3,2]).dtype).to eq :object - expect(a.to_nm([3,2])).to eq(NMatrix.new([3,2], a, dtype: :object)) + a = %w[this is an array of strings] + expect(a.to_nm([3, 2]).dtype).to eq :object + expect(a.to_nm([3, 2])).to eq(NMatrix.new([3, 2], a, dtype: :object)) end it "attempts to intuit the shape of the Array" do a = [[0, 1], [2, 3], [4, 5]] - expect(a.to_nm).to eq(NMatrix.new([3,2], a.flatten)) + expect(a.to_nm).to eq(NMatrix.new([3, 2], a.flatten)) expect(a.to_nm.dtype).to eq :int64 end @@ -61,7 +61,7 @@ it "intuits shape of Array into multiple dimensions" do a = [[[0], [1]], [[2], [3]], [[4], [5]]] - expect(a.to_nm).to eq(NMatrix.new([3,2,1], a.flatten)) + expect(a.to_nm).to eq(NMatrix.new([3, 2, 1], a.flatten)) expect(a).to eq(a.to_nm.to_a) end @@ -72,9 +72,8 @@ it "does not permanently alter the Array" do a = [[0, 1], [2, 3], [4, 5]] - expect(a.to_nm).to eq(NMatrix.new([3,2], a.flatten)) + expect(a.to_nm).to eq(NMatrix.new([3, 2], a.flatten)) expect(a).to eq([[0, 1], [2, 3], [4, 5]]) end end end - diff --git a/spec/blas_spec.rb b/spec/blas_spec.rb index c2ab05b3..6f0c1fc5 100644 --- a/spec/blas_spec.rb +++ b/spec/blas_spec.rb @@ -25,13 +25,12 @@ # Tests for properly exposed BLAS functions. # -require 'spec_helper' +require "spec_helper" describe NMatrix::BLAS do [:byte, :int8, :int16, :int32, :int64, :float32, :float64, :complex64, :complex128, - :object - ].each do |dtype| + :object],.each do |dtype| context dtype do it "exposes cblas_scal" do x = NMatrix.new([3, 1], [1, 2, 3], dtype: dtype) @@ -40,7 +39,7 @@ end it "exposes cblas_imax" do - u = NMatrix.new([3,1], [1, 4, 3], dtype: dtype) + u = NMatrix.new([3, 1], [1, 4, 3], dtype: dtype) index = NMatrix::BLAS.cblas_imax(3, u, 1) expect(index).to eq(1) end @@ -53,41 +52,41 @@ # would greatly simplify the calling of cblas_trsm in terms of arguments, and which would be accessible # as NMatrix::BLAS::trsm) it "exposes unfriendly cblas_trsm" do - a = NMatrix.new(3, [4,-1.0/2, -3.0/4, -2, 2, -1.0/4, -4, -2, -1.0/2], dtype: dtype) - b = NMatrix.new([3,1], [-1, 17, -9], dtype: dtype) - NMatrix::BLAS::cblas_trsm(:row, :right, :lower, :transpose, :nonunit, 1, 3, 1.0, a, 3, b, 3) + a = NMatrix.new(3, [4, -1.0 / 2, -3.0 / 4, -2, 2, -1.0 / 4, -4, -2, -1.0 / 2], dtype: dtype) + b = NMatrix.new([3, 1], [-1, 17, -9], dtype: dtype) + NMatrix::BLAS.cblas_trsm(:row, :right, :lower, :transpose, :nonunit, 1, 3, 1.0, a, 3, b, 3) # These test results all come from actually running a matrix through BLAS. We use them to ensure that NMatrix's # version of these functions give similar results. - expect(b[0]).to eq(-1.0/4) - expect(b[1]).to eq(33.0/4) + expect(b[0]).to eq(-1.0 / 4) + expect(b[1]).to eq(33.0 / 4) expect(b[2]).to eq(-13) - NMatrix::BLAS::cblas_trsm(:row, :right, :upper, :transpose, :unit, 1, 3, 1.0, a, 3, b, 3) + NMatrix::BLAS.cblas_trsm(:row, :right, :upper, :transpose, :unit, 1, 3, 1.0, a, 3, b, 3) - expect(b[0]).to eq(-15.0/2) + expect(b[0]).to eq(-15.0 / 2) expect(b[1]).to eq(5) expect(b[2]).to eq(-13) - - NMatrix::BLAS::cblas_trsm(:row, :left, :lower, :transpose, :nounit, 3, 1, 1.0, a, 3, b, 1) - expect(b[0]).to eq(307.0/8) - expect(b[1]).to eq(57.0/2) + NMatrix::BLAS.cblas_trsm(:row, :left, :lower, :transpose, :nounit, 3, 1, 1.0, a, 3, b, 1) + + expect(b[0]).to eq(307.0 / 8) + expect(b[1]).to eq(57.0 / 2) expect(b[2]).to eq(26.0) - - NMatrix::BLAS::cblas_trsm(:row, :left, :upper, :transpose, :unit, 3, 1, 1.0, a, 3, b, 1) - expect(b[0]).to eq(307.0/8) - expect(b[1]).to eq(763.0/16) - expect(b[2]).to eq(4269.0/64) + NMatrix::BLAS.cblas_trsm(:row, :left, :upper, :transpose, :unit, 3, 1, 1.0, a, 3, b, 1) + + expect(b[0]).to eq(307.0 / 8) + expect(b[1]).to eq(763.0 / 16) + expect(b[2]).to eq(4269.0 / 64) end # trmm multiplies two matrices, where one of the two is required to be # triangular it "exposes cblas_trmm" do - a = NMatrix.new([3,3], [1,1,1, 0,1,2, 0,0,-1], dtype: dtype) - b = NMatrix.new([3,3], [1,2,3, 4,5,6, 7,8,9], dtype: dtype) + a = NMatrix.new([3, 3], [1, 1, 1, 0, 1, 2, 0, 0, -1], dtype: dtype) + b = NMatrix.new([3, 3], [1, 2, 3, 4, 5, 6, 7, 8, 9], dtype: dtype) begin NMatrix::BLAS.cblas_trmm(:row, :left, :upper, false, :not_unit, 3, 3, 1, a, 3, b, 3) @@ -95,88 +94,85 @@ pending e.to_s end - product = NMatrix.new([3,3], [12,15,18, 18,21,24, -7,-8,-9], dtype: dtype) + product = NMatrix.new([3, 3], [12, 15, 18, 18, 21, 24, -7, -8, -9], dtype: dtype) expect(b).to eq(product) end end end - #should have a separate test for complex + # should have a separate test for complex [:float32, :float64, :complex64, :complex128, :object].each do |dtype| context dtype do - it "exposes cblas rot" do - x = NMatrix.new([5,1], [1,2,3,4,5], dtype: dtype) - y = NMatrix.new([5,1], [-5,-4,-3,-2,-1], dtype: dtype) - x, y = NMatrix::BLAS::rot(x, y, 1.0/2, Math.sqrt(3)/2, -1) + x = NMatrix.new([5, 1], [1, 2, 3, 4, 5], dtype: dtype) + y = NMatrix.new([5, 1], [-5, -4, -3, -2, -1], dtype: dtype) + x, y = NMatrix::BLAS.rot(x, y, 1.0 / 2, Math.sqrt(3) / 2, -1) expect(x).to be_within(1e-4).of( - NMatrix.new([5,1], [-0.3660254037844386, -0.7320508075688772, -1.098076211353316, -1.4641016151377544, -1.8301270189221928], dtype: dtype) + NMatrix.new([5, 1], [-0.3660254037844386, -0.7320508075688772, -1.098076211353316, -1.4641016151377544, -1.8301270189221928], dtype: dtype) ) expect(y).to be_within(1e-4).of( - NMatrix.new([5,1], [-6.830127018922193, -5.464101615137754, -4.098076211353316, -2.732050807568877, -1.3660254037844386], dtype: dtype) + NMatrix.new([5, 1], [-6.830127018922193, -5.464101615137754, -4.098076211353316, -2.732050807568877, -1.3660254037844386], dtype: dtype) ) end - end end [:float32, :float64, :complex64, :complex128, :object].each do |dtype| context dtype do - it "exposes cblas rotg" do pending("broken for :object") if dtype == :object - ab = NMatrix.new([2,1], [6,-8], dtype: dtype) + ab = NMatrix.new([2, 1], [6, -8], dtype: dtype) begin - c,s = NMatrix::BLAS::rotg(ab) + c, s = NMatrix::BLAS.rotg(ab) rescue NotImplementedError => e pending e.to_s end if [:float32, :float64].include?(dtype) expect(ab[0]).to be_within(1e-6).of(-10) - expect(ab[1]).to be_within(1e-6).of(-5.0/3) - expect(c).to be_within(1e-6).of(-3.0/5) + expect(ab[1]).to be_within(1e-6).of(-5.0 / 3) + expect(c).to be_within(1e-6).of(-3.0 / 5) else pending "need correct test cases" expect(ab[0]).to be_within(1e-6).of(10) - expect(ab[1]).to be_within(1e-6).of(5.0/3) - expect(c).to be_within(1e-6).of(3.0/5) + expect(ab[1]).to be_within(1e-6).of(5.0 / 3) + expect(c).to be_within(1e-6).of(3.0 / 5) end - expect(s).to be_within(1e-6).of(4.0/5) + expect(s).to be_within(1e-6).of(4.0 / 5) end # Note: this exposes gemm, not cblas_gemm (which is the unfriendly CBLAS no-error-checking version) it "exposes gemm" do - n = NMatrix.new([4,3], [14.0,9.0,3.0, 2.0,11.0,15.0, 0.0,12.0,17.0, 5.0,2.0,3.0], dtype: dtype) - m = NMatrix.new([3,2], [12.0,25.0, 9.0,10.0, 8.0,5.0], dtype: dtype) + n = NMatrix.new([4, 3], [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0], dtype: dtype) + m = NMatrix.new([3, 2], [12.0, 25.0, 9.0, 10.0, 8.0, 5.0], dtype: dtype) - #c = NMatrix.new([4,2], dtype) - r = NMatrix::BLAS.gemm(n, m) #, c) - #c.should equal(r) # check that both are same memory address + # c = NMatrix.new([4,2], dtype) + r = NMatrix::BLAS.gemm(n, m) # , c) + # c.should equal(r) # check that both are same memory address - expect(r).to eq(NMatrix.new([4,2], [273,455,243,235,244,205,102,160], dtype: dtype)) + expect(r).to eq(NMatrix.new([4, 2], [273, 455, 243, 235, 244, 205, 102, 160], dtype: dtype)) end it "exposes gemv" do - 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], dtype: dtype) - x = NMatrix.new([3,1], [2.0, 1.0, 0.0], dtype: dtype) + 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], dtype: dtype) + x = NMatrix.new([3, 1], [2.0, 1.0, 0.0], dtype: dtype) y = NMatrix::BLAS.gemv(a, x) - expect(y).to eq(NMatrix.new([4,1],[4.0,13.0,22.0,31.0],dtype: dtype)) + expect(y).to eq(NMatrix.new([4, 1], [4.0, 13.0, 22.0, 31.0], dtype: dtype)) end it "exposes asum" do pending("broken for :object") if dtype == :object - x = NMatrix.new([4,1], [-1,2,3,4], dtype: dtype) + x = NMatrix.new([4, 1], [-1, 2, 3, 4], dtype: dtype) expect(NMatrix::BLAS.asum(x)).to eq(10) end it "exposes asum for single element" do - if [:complex64,:complex128].include?(dtype) - x = NMatrix.new([1], [Complex(-3,2)], dtype: dtype) + if [:complex64, :complex128].include?(dtype) + x = NMatrix.new([1], [Complex(-3, 2)], dtype: dtype) expect(x.asum).to eq(5.0) else x = NMatrix.new([1], [-1], dtype: dtype) @@ -187,16 +183,16 @@ it "exposes nrm2" do pending("broken for :object") if dtype == :object - if dtype =~ /complex/ - x = NMatrix.new([3,1], [Complex(1,2),Complex(3,4),Complex(0,6)], dtype: dtype) - y = NMatrix.new([3,1], [Complex(0,0),Complex(0,0),Complex(0,0)], dtype: dtype) + if /complex/.match?(dtype) + x = NMatrix.new([3, 1], [Complex(1, 2), Complex(3, 4), Complex(0, 6)], dtype: dtype) + y = NMatrix.new([3, 1], [Complex(0, 0), Complex(0, 0), Complex(0, 0)], dtype: dtype) nrm2 = 8.12403840463596 else - x = NMatrix.new([4,1], [2,-4,3,5], dtype: dtype) - y = NMatrix.new([3,1], [0,0,0], dtype: dtype) + x = NMatrix.new([4, 1], [2, -4, 3, 5], dtype: dtype) + y = NMatrix.new([3, 1], [0, 0, 0], dtype: dtype) nrm2 = 5.385164807134504 end - + err = case dtype when :float32, :complex64 1e-6 @@ -204,12 +200,11 @@ 1e-14 else 1e-14 - end + end expect(NMatrix::BLAS.nrm2(x, 1, 3)).to be_within(err).of(nrm2) expect(NMatrix::BLAS.nrm2(y, 1, 3)).to be_within(err).of(0) end - end end end diff --git a/spec/elementwise_spec.rb b/spec/elementwise_spec.rb index 3c2b1584..63d0971a 100644 --- a/spec/elementwise_spec.rb +++ b/spec/elementwise_spec.rb @@ -25,7 +25,7 @@ # Element-wise operation tests. # -require 'spec_helper' +require "spec_helper" describe NMatrix do context "yale" do @@ -33,28 +33,28 @@ @n = NMatrix.new(3, stype: :yale, dtype: :int64) @n.extend NMatrix::YaleFunctions unless jruby? @m = NMatrix.new(3, stype: :yale, dtype: :int64) - @n[0,0] = 52 - @n[0,2] = 5 - @n[1,1] = 40 - @n[0,1] = 30 - @n[2,0] = 6 - @m[1,1] = -48 - @m[0,2] = -5 + @n[0, 0] = 52 + @n[0, 2] = 5 + @n[1, 1] = 40 + @n[0, 1] = 30 + @n[2, 0] = 6 + @m[1, 1] = -48 + @m[0, 2] = -5 @n.extend NMatrix::YaleFunctions unless jruby? end it "should perform scalar math" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? x = @n * 3 - expect(x[0,0]).to eq(52 * 3) - expect(x[0,1]).to eq(30 * 3) - expect(x[0,2]).to eq(5 * 3) - expect(x[1,1]).to eq(40 * 3) - expect(x[2,0]).to eq(6 * 3) + expect(x[0, 0]).to eq(52 * 3) + expect(x[0, 1]).to eq(30 * 3) + expect(x[0, 2]).to eq(5 * 3) + expect(x[1, 1]).to eq(40 * 3) + expect(x[2, 0]).to eq(6 * 3) r = NMatrix.new(3, stype: :yale, dtype: :int64) y = r + 3 - expect(y[0,0]).to eq(3) + expect(y[0, 0]).to eq(3) end it "should refuse to perform a dot operation on a yale with non-zero default" do @@ -66,126 +66,125 @@ end it "should perform element-wise addition" do - expect(@n+@m).to eq(NMatrix.new(:dense, 3, [52,30,0,0,-8,0,6,0,0], :int64).cast(:yale, :int64)) + expect(@n + @m).to eq(NMatrix.new(:dense, 3, [52, 30, 0, 0, -8, 0, 6, 0, 0], :int64).cast(:yale, :int64)) end it "should perform element-wise subtraction" do - expect(@n-@m).to eq(NMatrix.new(:dense, 3, [52,30,10,0,88,0,6,0,0], :int64).cast(:yale, :int64)) + expect(@n - @m).to eq(NMatrix.new(:dense, 3, [52, 30, 10, 0, 88, 0, 6, 0, 0], :int64).cast(:yale, :int64)) end it "should perform element-wise multiplication" do - r = NMatrix.new(:dense, 3, [0,0,-25,0,-1920,0,0,0,0], :int64).cast(:yale, :int64) + r = NMatrix.new(:dense, 3, [0, 0, -25, 0, -1920, 0, 0, 0, 0], :int64).cast(:yale, :int64) m = NMatrix.new(2, stype: :yale, dtype: :int64) - expect(@n*@m).to eq(r) + expect(@n * @m).to eq(r) end it "should perform element-wise division" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? r = NMatrix.new(:dense, 3, [52, 30, -2, 0, -1, 0, 6, 0, 0], :int64).cast(:yale, :int64) - expect(@n/(@m+1)).to eq(r) + expect(@n / (@m + 1)).to eq(r) end it "should perform element-wise modulo" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? m = NMatrix.new(3, stype: :yale, dtype: :int64, default: 0) + 5 - expect(@n % m).to eq(NMatrix.new(:dense, 3, [2,0,0,0,0,0,1,0,0], :int64).cast(:yale, :int64)) + expect(@n % m).to eq(NMatrix.new(:dense, 3, [2, 0, 0, 0, 0, 0, 1, 0, 0], :int64).cast(:yale, :int64)) end it "should handle element-wise equality (=~)" do - expect(@n =~ @m).to eq(NMatrix.new(:dense, 3, [false,false,false,true,false,true,false,true,true], :object).cast(:yale, :object, false)) + expect(@n =~ @m).to eq(NMatrix.new(:dense, 3, [false, false, false, true, false, true, false, true, true], :object).cast(:yale, :object, false)) end it "should handle element-wise inequality (!~)" do - expect(@n !~ @m).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, true)) + expect(@n !~ @m).to eq(NMatrix.new(:dense, 3, [true, true, true, false, true, false, true, false, false], :object).cast(:yale, :object, true)) end it "should handle element-wise less-than (<)" do - expect(@m < @n).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, true)) + expect(@m < @n).to eq(NMatrix.new(:dense, 3, [true, true, true, false, true, false, true, false, false], :object).cast(:yale, :object, true)) end it "should handle element-wise greater-than (>)" do - expect(@n > @m).to eq(NMatrix.new(:dense, 3, [true,true,true,false,true,false,true,false,false], :object).cast(:yale, :object, false)) + expect(@n > @m).to eq(NMatrix.new(:dense, 3, [true, true, true, false, true, false, true, false, false], :object).cast(:yale, :object, false)) end it "should handle element-wise greater-than-or-equals (>=)" do - expect(@n >= @m).to eq(NMatrix.new(:dense, 3, true, :object).cast(:yale,:object, true)) + expect(@n >= @m).to eq(NMatrix.new(:dense, 3, true, :object).cast(:yale, :object, true)) end it "should handle element-wise less-than-or-equals (<=)" do - r = NMatrix.new(:dense, 3, [false,false,false,true,false,true,false,true,true], :object).cast(:yale, :object, false) + r = NMatrix.new(:dense, 3, [false, false, false, true, false, true, false, true, true], :object).cast(:yale, :object, false) expect(@n <= @m).to eq(r) end end - context "list" do before :each do @n = NMatrix.new(:list, 2, 0, :int64) @m = NMatrix.new(:list, 2, 0, :int64) - @n[0,0] = 52 - @m[1,1] = -48 - @n[1,1] = 40 + @n[0, 0] = 52 + @m[1, 1] = -48 + @n[1, 1] = 40 end it "should perform scalar math" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? x = @n * 3 - expect(x[0,0]).to eq(52 * 3) - expect(x[1,1]).to eq(40 * 3) - expect(x[0,1]).to eq(0) + expect(x[0, 0]).to eq(52 * 3) + expect(x[1, 1]).to eq(40 * 3) + expect(x[0, 1]).to eq(0) r = NMatrix.new(3, stype: :list, default: 1) y = r + 3 - expect(y[0,0]).to eq(4) + expect(y[0, 0]).to eq(4) end it "should perform element-wise addition" do r = NMatrix.new(2, stype: :list, dtype: :int64, default: 0) - r[0,0] = 52 - r[1,1] = -8 + r[0, 0] = 52 + r[1, 1] = -8 q = @n + @m expect(q).to eq(r) end it "should perform element-wise subtraction" do r = NMatrix.new(:dense, 2, [52, 0, 0, 88], :int64).cast(:list, :int64) - expect(@n-@m).to eq(r) + expect(@n - @m).to eq(r) end it "should perform element-wise multiplication" do r = NMatrix.new(:dense, 2, [52, 0, 0, -1920], :int64).cast(:list, :int64) m = NMatrix.new(:list, 2, 1, :int64) - m[1,1] = -48 - expect(@n*m).to eq(r) + m[1, 1] = -48 + expect(@n * m).to eq(r) end it "should perform element-wise division" do m = NMatrix.new(:list, 2, 1, :int64) - m[1,1] = 2 + m[1, 1] = 2 r = NMatrix.new(:dense, 2, [52, 0, 0, 20], :int64).cast(:list, :int64) - expect(@n/m).to eq(r) + expect(@n / m).to eq(r) end it "should perform element-wise modulo" do pending("not yet implemented for sparse matrices for NMatrix-JRuby") if jruby? m = NMatrix.new(:list, 2, 1, :int64) - m[0,0] = 50 - m[1,1] = 40 + m[0, 0] = 50 + m[1, 1] = 40 (@n % m) end it "should handle element-wise equality (=~)" do r = NMatrix.new(:list, 2, false, :object) - r[0,1] = true - r[1,0] = true + r[0, 1] = true + r[1, 0] = true expect(@n =~ @m).to eq(r) end it "should handle element-wise inequality (!~)" do r = NMatrix.new(:list, 2, false, :object) - r[0,0] = true - r[1,1] = true + r[0, 0] = true + r[1, 1] = true expect(@n !~ @m).to eq(r) end @@ -196,8 +195,8 @@ it "should handle element-wise greater-than (>)" do r = NMatrix.new(:list, 2, false, :object) - r[0,0] = true - r[1,1] = true + r[0, 0] = true + r[1, 1] = true expect(@n > @m).to eq(r) end @@ -207,8 +206,8 @@ it "should handle element-wise less-than-or-equals (<=)" do r = NMatrix.new(:list, 2, false, :object) - r[0,1] = true - r[1,0] = true + r[0, 1] = true + r[1, 0] = true expect(@n <= @m).to eq(r) end end @@ -216,95 +215,95 @@ context "dense" do context "scalar arithmetic" do before :each do - @n = NMatrix.new(:dense, 2, [1,2,3,4], :int64) + @n = NMatrix.new(:dense, 2, [1, 2, 3, 4], :int64) end it "works for integers" do - expect(@n+1).to eq(NMatrix.new(:dense, 2, [2,3,4,5], :int64)) + expect(@n + 1).to eq(NMatrix.new(:dense, 2, [2, 3, 4, 5], :int64)) end - #it "works for complex64" do + # it "works for complex64" do # n = @n.cast(:dtype => :complex64) # (n + 10.0).to_a.should == [Complex(11.0), Complex(12.0), Complex(13.0), Complex(14.0)] - #end + # end end context "elementwise arithmetic" do before :each do - @n = NMatrix.new(:dense, 2, [1,2,3,4], :int64) - @m = NMatrix.new(:dense, 2, [-4,-1,0,66], :int64) + @n = NMatrix.new(:dense, 2, [1, 2, 3, 4], :int64) + @m = NMatrix.new(:dense, 2, [-4, -1, 0, 66], :int64) end it "adds" do - r = @n+@m - expect(r).to eq(NMatrix.new(:dense, [2,2], [-3, 1, 3, 70], :int64)) + r = @n + @m + expect(r).to eq(NMatrix.new(:dense, [2, 2], [-3, 1, 3, 70], :int64)) end it "subtracts" do - r = @n-@m - expect(r).to eq(NMatrix.new(:dense, [2,2], [5, 3, 3, -62], :int64)) + r = @n - @m + expect(r).to eq(NMatrix.new(:dense, [2, 2], [5, 3, 3, -62], :int64)) end it "multiplies" do - r = @n*@m - expect(r).to eq(NMatrix.new(:dense, [2,2], [-4, -2, 0, 264], :int64)) + r = @n * @m + expect(r).to eq(NMatrix.new(:dense, [2, 2], [-4, -2, 0, 264], :int64)) end it "divides in the Ruby way" do pending("not yet implemented int dtype for NMatrix-JRuby") if jruby? m = @m.clone - m[1,0] = 3 - r = @n/m - expect(r).to eq(NMatrix.new(:dense, [2,2], [-1, -2, 1, 0], :int64)) + m[1, 0] = 3 + r = @n / m + expect(r).to eq(NMatrix.new(:dense, [2, 2], [-1, -2, 1, 0], :int64)) end it "exponentiates" do - r = @n ** 2 + r = @n**2 # TODO: We might have problems with the dtype. - expect(r).to eq(NMatrix.new(:dense, [2,2], [1, 4, 9, 16], :int64)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [1, 4, 9, 16], :int64)) end it "modulo" do pending("not yet implemented int dtype for NMatrix-JRuby") if jruby? - expect(@n % (@m + 2)).to eq(NMatrix.new(:dense, [2,2], [-1, 0, 1, 4], :int64)) + expect(@n % (@m + 2)).to eq(NMatrix.new(:dense, [2, 2], [-1, 0, 1, 4], :int64)) end end context "elementwise comparisons" do before :each do - @n = NMatrix.new(:dense, 2, [1,2,3,4], :int64) - @m = NMatrix.new(:dense, 2, [-4,-1,3,2], :int64) + @n = NMatrix.new(:dense, 2, [1, 2, 3, 4], :int64) + @m = NMatrix.new(:dense, 2, [-4, -1, 3, 2], :int64) end it "equals" do r = @n =~ @m - expect(r).to eq(NMatrix.new(:dense, [2,2], [false, false, true, false], :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [false, false, true, false], :object)) end it "is not equal" do r = @n !~ @m - expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [true, true, false, true], :object)) end it "is less than" do r = @n < @m - expect(r).to eq(NMatrix.new(:dense, [2,2], false, :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], false, :object)) end it "is greater than" do r = @n > @m - expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [true, true, false, true], :object)) end it "is less than or equal to" do r = @n <= @m - expect(r).to eq(NMatrix.new(:dense, [2,2], [false, false, true, false], :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [false, false, true, false], :object)) end it "is greater than or equal to" do - n = NMatrix.new(:dense, [2,2], [1, 2, 2, 4], :int64) + n = NMatrix.new(:dense, [2, 2], [1, 2, 2, 4], :int64) r = n >= @m - expect(r).to eq(NMatrix.new(:dense, [2,2], [true, true, false, true], :object)) + expect(r).to eq(NMatrix.new(:dense, [2, 2], [true, true, false, true], :object)) end end end diff --git a/spec/homogeneous_spec.rb b/spec/homogeneous_spec.rb index 4c186780..8cac2305 100644 --- a/spec/homogeneous_spec.rb +++ b/spec/homogeneous_spec.rb @@ -25,74 +25,73 @@ # Specs for the homogeneous transformation matrix methods. # -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix/homogeneous.rb" -require 'pry' +require "pry" -describe 'NMatrix' do +describe "NMatrix" do context ".x_rotation" do it "should generate a matrix representing a rotation about the x axis" do - x = NMatrix.x_rotation(Math::PI/6) - expect(x).to be_within(1e-8).of(NMatrix.new([4,4], [1.0, 0.0, 0.0, 0.0, - 0.0, Math.cos(Math::PI/6), -0.5, 0.0, - 0.0, 0.5, Math.cos(Math::PI/6), 0.0, - 0.0, 0.0, 0.0, 1.0] )) + x = NMatrix.x_rotation(Math::PI / 6) + expect(x).to be_within(1e-8).of(NMatrix.new([4, 4], [1.0, 0.0, 0.0, 0.0, + 0.0, Math.cos(Math::PI / 6), -0.5, 0.0, + 0.0, 0.5, Math.cos(Math::PI / 6), 0.0, + 0.0, 0.0, 0.0, 1.0,])) end end - context ".y_rotation" do it "should generate a matrix representing a rotation about the y axis" do - y = NMatrix.y_rotation(Math::PI/6) - expect(y).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), 0.0, 0.5, 0.0, - 0.0, 1.0, 0.0, 0.0, - -0.5, 0.0, Math.cos(Math::PI/6), 0.0, - 0.0, 0.0, 0.0, 1.0] )) + y = NMatrix.y_rotation(Math::PI / 6) + expect(y).to be_within(1e-8).of(NMatrix.new([4, 4], [Math.cos(Math::PI / 6), 0.0, 0.5, 0.0, + 0.0, 1.0, 0.0, 0.0, + -0.5, 0.0, Math.cos(Math::PI / 6), 0.0, + 0.0, 0.0, 0.0, 1.0,])) end end context ".z_rotation" do it "should generate a matrix representing a rotation about the z axis" do - z = NMatrix.z_rotation(Math::PI/6) - expect(z).to be_within(1e-8).of(NMatrix.new([4,4], [Math.cos(Math::PI/6), -0.5, 0.0, 0.0, - 0.5, Math.cos(Math::PI/6), 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0] )) + z = NMatrix.z_rotation(Math::PI / 6) + expect(z).to be_within(1e-8).of(NMatrix.new([4, 4], [Math.cos(Math::PI / 6), -0.5, 0.0, 0.0, + 0.5, Math.cos(Math::PI / 6), 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0,])) end end context ".translation" do it "should generate a translation matrix from an Array" do - t = NMatrix.translation([4,5,6]) - expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4, - 0, 1, 0, 5, - 0, 0, 1, 6, - 0, 0, 0, 1] )) + t = NMatrix.translation([4, 5, 6]) + expect(t).to be_within(1e-8).of(NMatrix.new([4, 4], [1, 0, 0, 4, + 0, 1, 0, 5, + 0, 0, 1, 6, + 0, 0, 0, 1,])) end it "should generate a translation matrix from x, y, and z values" do - t = NMatrix.translation(4,5,6) - expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4, - 0, 1, 0, 5, - 0, 0, 1, 6, - 0, 0, 0, 1] )) + t = NMatrix.translation(4, 5, 6) + expect(t).to be_within(1e-8).of(NMatrix.new([4, 4], [1, 0, 0, 4, + 0, 1, 0, 5, + 0, 0, 1, 6, + 0, 0, 0, 1,])) end it "should generate a translation matrix from an NMatrix with correctly inferred dtype" do pending("not yet implemented for NMatrix-JRuby") if jruby? - t = NMatrix.translation(NMatrix.new([3,1], [4,5,6], dtype: :float64) ) - expect(t).to be_within(1e-8).of(NMatrix.new([4,4], [1, 0, 0, 4, - 0, 1, 0, 5, - 0, 0, 1, 6, - 0, 0, 0, 1] )) + t = NMatrix.translation(NMatrix.new([3, 1], [4, 5, 6], dtype: :float64)) + expect(t).to be_within(1e-8).of(NMatrix.new([4, 4], [1, 0, 0, 4, + 0, 1, 0, 5, + 0, 0, 1, 6, + 0, 0, 0, 1,])) expect(t.dtype).to be(:float64) end end context "#quaternion" do it "should generate a singularity-free quaternion" do - transform = NMatrix.new([4,4], [-0.9995825,-0.02527934,-0.0139845,50.61761,-0.02732551,0.9844284,0.1736463,-22.95566,0.009376526,0.1739562,-0.9847089,7.1521,0,0,0,1]) + transform = NMatrix.new([4, 4], [-0.9995825, -0.02527934, -0.0139845, 50.61761, -0.02732551, 0.9844284, 0.1736463, -22.95566, 0.009376526, 0.1739562, -0.9847089, 7.1521, 0, 0, 0, 1]) q = transform.quaternion expect(Math.sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)).to be_within(1e-6).of(1.0) end diff --git a/spec/io/fortran_format_spec.rb b/spec/io/fortran_format_spec.rb index db9a1f44..60d65121 100644 --- a/spec/io/fortran_format_spec.rb +++ b/spec/io/fortran_format_spec.rb @@ -25,31 +25,31 @@ # Basic tests for NMatrix::IO::FortranFormat. # -require './lib/nmatrix' +require "./lib/nmatrix" describe NMatrix::IO::FortranFormat do it "parses integer FORTRAN formats" do - int_fmt = NMatrix::IO::FortranFormat::Reader.new('(16I5)').parse + int_fmt = NMatrix::IO::FortranFormat::Reader.new("(16I5)").parse expect(int_fmt[:format_code]).to eq "INT_ID" expect(int_fmt[:repeat]) .to eq 16 - expect(int_fmt[:field_width]).to eq 5 + expect(int_fmt[:field_width]).to eq 5 - int_fmt = NMatrix::IO::FortranFormat::Reader.new('(I4)').parse + int_fmt = NMatrix::IO::FortranFormat::Reader.new("(I4)").parse expect(int_fmt[:format_code]).to eq "INT_ID" expect(int_fmt[:field_width]).to eq 4 end it "parses floating point FORTRAN formats" do - fp_fmt = NMatrix::IO::FortranFormat::Reader.new('(10F7.1)').parse + fp_fmt = NMatrix::IO::FortranFormat::Reader.new("(10F7.1)").parse expect(fp_fmt[:format_code]) .to eq "FP_ID" expect(fp_fmt[:repeat]) .to eq 10 expect(fp_fmt[:field_width]) .to eq 7 expect(fp_fmt[:post_decimal_width]).to eq 1 - fp_fmt = NMatrix::IO::FortranFormat::Reader.new('(F4.2)').parse + fp_fmt = NMatrix::IO::FortranFormat::Reader.new("(F4.2)").parse expect(fp_fmt[:format_code]) .to eq "FP_ID" expect(fp_fmt[:field_width]) .to eq 4 @@ -57,7 +57,7 @@ end it "parses exponential FORTRAN formats" do - exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(2E8.3E3)').parse + exp_fmt = NMatrix::IO::FortranFormat::Reader.new("(2E8.3E3)").parse expect(exp_fmt[:format_code]) .to eq "EXP_ID" expect(exp_fmt[:repeat]) .to eq 2 @@ -65,24 +65,24 @@ expect(exp_fmt[:post_decimal_width]).to eq 3 expect(exp_fmt[:exponent_width]) .to eq 3 - exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(3E3.6)').parse + exp_fmt = NMatrix::IO::FortranFormat::Reader.new("(3E3.6)").parse expect(exp_fmt[:format_code]) .to eq "EXP_ID" expect(exp_fmt[:repeat]) .to eq 3 expect(exp_fmt[:field_width]) .to eq 3 expect(exp_fmt[:post_decimal_width]).to eq 6 - exp_fmt = NMatrix::IO::FortranFormat::Reader.new('(E4.5)').parse + exp_fmt = NMatrix::IO::FortranFormat::Reader.new("(E4.5)").parse expect(exp_fmt[:format_code]) .to eq "EXP_ID" expect(exp_fmt[:field_width]) .to eq 4 expect(exp_fmt[:post_decimal_width]).to eq 5 end - ['I3', '(F4)', '(E3.', '(E4.E5)'].each do |bad_format| + ["I3", "(F4)", "(E3.", "(E4.E5)"].each do |bad_format| it "doesn't let bad input through : #{bad_format}" do expect { NMatrix::IO::FortranFormat::Reader.new(bad_format).parse }.to raise_error(IOError) + end end end -end diff --git a/spec/io/harwell_boeing_spec.rb b/spec/io/harwell_boeing_spec.rb index 36e1e16c..a2d00c13 100644 --- a/spec/io/harwell_boeing_spec.rb +++ b/spec/io/harwell_boeing_spec.rb @@ -25,7 +25,7 @@ # Basic tests for NMatrix::IO::HarwelBoeing. # TODO : After the fortran format thing is done -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix" describe NMatrix::IO::HarwellBoeing do @@ -38,8 +38,8 @@ def check_file_header header expect(header[:indcrd]) .to eq(1) expect(header[:valcrd]) .to eq(3) expect(header[:rhscrd]) .to eq(0) - - expect(header[:mxtype]) .to eq('RUA') + + expect(header[:mxtype]) .to eq("RUA") expect(header[:nrow]) .to eq(5) expect(header[:ncol]) .to eq(5) expect(header[:nnzero]) .to eq(13) @@ -47,52 +47,52 @@ def check_file_header header expect(header[:ptrfmt]) .to eq({ format_code: "INT_ID", - repeat: 6, - field_width: 3 - }) - expect(header[:indfmt]) .to eq({ + repeat: 6, + field_width: 3, + }) + expect(header[:indfmt]) .to eq({ format_code: "INT_ID", - repeat: 13, - field_width: 3 - }) - expect(header[:valfmt]) .to eq({ - format_code: "EXP_ID", - repeat: 5, - field_width: 15, - post_decimal_width: 8 - }) - expect(header[:rhsfmt]) .to eq({ - format_code: "EXP_ID", - repeat: 5, - field_width: 15, - post_decimal_width: 8 - }) + repeat: 13, + field_width: 3, + }) + expect(header[:valfmt]) .to eq({ + format_code: "EXP_ID", + repeat: 5, + field_width: 15, + post_decimal_width: 8, + }) + expect(header[:rhsfmt]) .to eq({ + format_code: "EXP_ID", + repeat: 5, + field_width: 15, + post_decimal_width: 8, + }) end it "loads a Harwell Boeing file values and header (currently real only)" do n, h = NMatrix::IO::HarwellBoeing.load("spec/io/test.rua") - expect(n.is_a? NMatrix).to eq(true) + expect(n.is_a?(NMatrix)).to eq(true) expect(n.cols) .to eq(5) expect(n.rows) .to eq(5) - expect(n[0,0]) .to eq(11) - expect(n[4,4]) .to eq(55) + expect(n[0, 0]) .to eq(11) + expect(n[4, 4]) .to eq(55) - expect(h.is_a? Hash).to eq(true) + expect(h.is_a?(Hash)).to eq(true) check_file_header(h) end it "loads only the header of the file when specified" do h = NMatrix::IO::HarwellBoeing.load("spec/io/test.rua", header: true) - expect(h.is_a? Hash).to eq(true) + expect(h.is_a?(Hash)).to eq(true) check_file_header(h) end it "raises error for wrong Harwell Boeing file name" do - expect{ + expect { NMatrix::IO::HarwellBoeing.load("spec/io/wrong.afx") }.to raise_error(IOError) end -end \ No newline at end of file +end diff --git a/spec/io_spec.rb b/spec/io_spec.rb index 9d7b7d59..cbaef265 100644 --- a/spec/io_spec.rb +++ b/spec/io_spec.rb @@ -25,12 +25,12 @@ # Basic tests for NMatrix::IO. # require "tmpdir" # Used to avoid cluttering the repository. -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix" describe NMatrix::IO do let(:tmp_dir) { Dir.mktmpdir } - let(:test_out) { File.join(tmp_dir, 'test-out') } + let(:test_out) { File.join(tmp_dir, "test-out") } it "repacks a string" do pending("not yet implemented for NMatrix-JRuby") if jruby? @@ -41,29 +41,29 @@ pending("not yet implemented for NMatrix-JRuby") if jruby? ia = NMatrix::IO::Matlab.repack("\0\1\3\3\4", :miUINT8, :itype) ja = NMatrix::IO::Matlab.repack("\0\1\3\0\0\0\0\0\0\0\0", :miUINT8, :itype) - n = NMatrix.new(:yale, [4,4], :byte, ia, ja, "\2\3\5\4", :byte) - expect(n[0,0]).to eq(2) - expect(n[1,1]).to eq(3) - expect(n[1,3]).to eq(5) - expect(n[3,0]).to eq(4) - expect(n[2,2]).to eq(0) - expect(n[3,3]).to eq(0) + n = NMatrix.new(:yale, [4, 4], :byte, ia, ja, "\2\3\5\4", :byte) + expect(n[0, 0]).to eq(2) + expect(n[1, 1]).to eq(3) + expect(n[1, 3]).to eq(5) + expect(n[3, 0]).to eq(4) + expect(n[2, 2]).to eq(0) + expect(n[3, 3]).to eq(0) end it "reads MATLAB .mat file containing a single square sparse matrix" do pending("not yet implemented for NMatrix-JRuby") if jruby? n = NMatrix::IO::Matlab.load_mat("spec/4x4_sparse.mat") - expect(n[0,0]).to eq(2) - expect(n[1,1]).to eq(3) - expect(n[1,3]).to eq(5) - expect(n[3,0]).to eq(4) - expect(n[2,2]).to eq(0) - expect(n[3,3]).to eq(0) + expect(n[0, 0]).to eq(2) + expect(n[1, 1]).to eq(3) + expect(n[1, 3]).to eq(5) + expect(n[3, 0]).to eq(4) + expect(n[2, 2]).to eq(0) + expect(n[3, 3]).to eq(0) end it "reads MATLAB .mat file containing a single dense integer matrix" do n = NMatrix::IO::Matlab.load_mat("spec/4x5_dense.mat") - m = NMatrix.new([4,5], [16,17,18,19,20,15,14,13,12,11,6,7,8,9,10,5,4,3,2,1]) + m = NMatrix.new([4, 5], [16, 17, 18, 19, 20, 15, 14, 13, 12, 11, 6, 7, 8, 9, 10, 5, 4, 3, 2, 1]) expect(n).to eq(m) end @@ -85,21 +85,19 @@ n = NMatrix::IO::PointCloud.load("spec/test.pcd") expect(n.column(0).sort.uniq.size).to eq(1) expect(n.column(0).sort.uniq.first).to eq(207.008) - expect(n[0,3]).to eq(0) + expect(n[0, 3]).to eq(0) end it "raises an error when reading a non-existent file" do pending("not yet implemented for NMatrix-JRuby") if jruby? fn = rand(10000000).to_i.to_s - while File.exist?(fn) - fn = rand(10000000).to_i.to_s - end - expect{ NMatrix.read(fn) }.to raise_error(Errno::ENOENT) + fn = rand(10000000).to_i.to_s while File.exist?(fn) + expect { NMatrix.read(fn) }.to raise_error(Errno::ENOENT) end it "reads and writes NMatrix dense" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, [4,3], [0,1,2,3,4,5,6,7,8,9,10,11], :int32) + n = NMatrix.new(:dense, [4, 3], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], :int32) n.write(test_out) m = NMatrix.read(test_out) @@ -108,7 +106,7 @@ it "reads and writes NMatrix dense as symmetric" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, 3, [0,1,2,1,3,4,2,4,5], :int16) + n = NMatrix.new(:dense, 3, [0, 1, 2, 1, 3, 4, 2, 4, 5], :int16) n.write(test_out, :symmetric) m = NMatrix.read(test_out) @@ -117,7 +115,7 @@ it "reads and writes NMatrix dense as skew" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, 3, [0,1,2,-1,3,4,-2,-4,5], :float64) + n = NMatrix.new(:dense, 3, [0, 1, 2, -1, 3, 4, -2, -4, 5], :float64) n.write(test_out, :skew) m = NMatrix.read(test_out) @@ -126,7 +124,7 @@ it "reads and writes NMatrix dense as hermitian" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, 3, [0,1,2,1,3,4,2,4,5], :complex64) + n = NMatrix.new(:dense, 3, [0, 1, 2, 1, 3, 4, 2, 4, 5], :complex64) n.write(test_out, :hermitian) m = NMatrix.read(test_out) @@ -135,10 +133,10 @@ it "reads and writes NMatrix dense as upper" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, 3, [-1,1,2,3,4,5,6,7,8], :int32) + n = NMatrix.new(:dense, 3, [-1, 1, 2, 3, 4, 5, 6, 7, 8], :int32) n.write(test_out, :upper) - m = NMatrix.new(:dense, 3, [-1,1,2,0,4,5,0,0,8], :int32) # lower version of the same + m = NMatrix.new(:dense, 3, [-1, 1, 2, 0, 4, 5, 0, 0, 8], :int32) # lower version of the same o = NMatrix.read(test_out) expect(o).to eq(m) @@ -147,10 +145,10 @@ it "reads and writes NMatrix dense as lower" do pending("not yet implemented for NMatrix-JRuby") if jruby? - n = NMatrix.new(:dense, 3, [-1,1,2,3,4,5,6,7,8], :int32) + n = NMatrix.new(:dense, 3, [-1, 1, 2, 3, 4, 5, 6, 7, 8], :int32) n.write(test_out, :lower) - m = NMatrix.new(:dense, 3, [-1,0,0,3,4,0,6,7,8], :int32) # lower version of the same + m = NMatrix.new(:dense, 3, [-1, 0, 0, 3, 4, 0, 6, 7, 8], :int32) # lower version of the same o = NMatrix.read(test_out) expect(o).to eq(m) diff --git a/spec/lapack_core_spec.rb b/spec/lapack_core_spec.rb index 2b93be7b..5cfdb7d1 100644 --- a/spec/lapack_core_spec.rb +++ b/spec/lapack_core_spec.rb @@ -29,7 +29,7 @@ # internal implmentations. # -require 'spec_helper' +require "spec_helper" describe "NMatrix::LAPACK functions with internal implementations" do # where integer math is allowed @@ -39,18 +39,18 @@ # element of piv, though maybe I misunderstand smth. It would make # more sense if piv were [2,1,3,3] it "exposes clapack laswp" do - a = NMatrix.new(:dense, [3,4], [1,2,3,4,5,6,7,8,9,10,11,12], dtype) - NMatrix::LAPACK::clapack_laswp(3, a, 4, 0, 3, [2,1,3,0], 1) - b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype) + a = NMatrix.new(:dense, [3, 4], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype) + NMatrix::LAPACK.clapack_laswp(3, a, 4, 0, 3, [2, 1, 3, 0], 1) + b = NMatrix.new(:dense, [3, 4], [3, 2, 4, 1, 7, 6, 8, 5, 11, 10, 12, 9], dtype) expect(a).to eq(b) end # This spec is OK, because the default behavior for permute_columns # is :intuitive, which is different from :lapack (default laswp behavior) it "exposes NMatrix#permute_columns and #permute_columns! (user-friendly laswp)" do - a = NMatrix.new(:dense, [3,4], [1,2,3,4,5,6,7,8,9,10,11,12], dtype) - b = NMatrix.new(:dense, [3,4], [3,2,4,1,7,6,8,5,11,10,12,9], dtype) - piv = [2,1,3,0] + a = NMatrix.new(:dense, [3, 4], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype) + b = NMatrix.new(:dense, [3, 4], [3, 2, 4, 1, 7, 6, 8, 5, 11, 10, 12, 9], dtype) + piv = [2, 1, 3, 0] r = a.permute_columns(piv) expect(r).not_to eq(a) expect(r).to eq(b) @@ -63,7 +63,6 @@ # where integer math is not allowed [:float32, :float64, :complex64, :complex128].each do |dtype| context dtype do - # clapack_getrf performs a LU decomposition, but unlike the # standard LAPACK getrf, it's the upper matrix that has unit diagonals # and the permutation is done in columns not rows. See the code for @@ -71,12 +70,12 @@ # Also the rows in the pivot vector are indexed starting from 0, # rather than 1 as in LAPACK it "calculates LU decomposition using clapack_getrf (row-major, square)" do - a = NMatrix.new(3, [4,9,2,3,5,7,8,1,6], dtype: dtype) - ipiv = NMatrix::LAPACK::clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1]) - b = NMatrix.new(3,[9, 2.0/9, 4.0/9, - 5, 53.0/9, 7.0/53, - 1, 52.0/9, 360.0/53], dtype: dtype) - ipiv_true = [1,2,2] + a = NMatrix.new(3, [4, 9, 2, 3, 5, 7, 8, 1, 6], dtype: dtype) + ipiv = NMatrix::LAPACK.clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1]) + b = NMatrix.new(3, [9, 2.0 / 9, 4.0 / 9, + 5, 53.0 / 9, 7.0 / 53, + 1, 52.0 / 9, 360.0 / 53,], dtype: dtype) + ipiv_true = [1, 2, 2] # delta varies for different dtypes err = case dtype @@ -84,21 +83,21 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(a).to be_within(err).of(b) expect(ipiv).to eq(ipiv_true) end it "calculates LU decomposition using clapack_getrf (row-major, rectangular)" do - a = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype) - ipiv = NMatrix::LAPACK::clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1]) - #we can't use GETRF_SOLUTION_ARRAY here, because of the different - #conventions of clapack_getrf - b = NMatrix.new([3,4],[10.0, -0.1, 0.0, 0.4, - 3.0, 9.3, 20.0/93, 38.0/93, - 1.0, 7.1, 602.0/93, 251.0/602], dtype: dtype) - ipiv_true = [2,2,2] + a = NMatrix.new([3, 4], GETRF_EXAMPLE_ARRAY, dtype: dtype) + ipiv = NMatrix::LAPACK.clapack_getrf(:row, a.shape[0], a.shape[1], a, a.shape[1]) + # we can't use GETRF_SOLUTION_ARRAY here, because of the different + # conventions of clapack_getrf + b = NMatrix.new([3, 4], [10.0, -0.1, 0.0, 0.4, + 3.0, 9.3, 20.0 / 93, 38.0 / 93, + 1.0, 7.1, 602.0 / 93, 251.0 / 602,], dtype: dtype) + ipiv_true = [2, 2, 2] # delta varies for different dtypes err = case dtype @@ -106,24 +105,24 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(a).to be_within(err).of(b) expect(ipiv).to eq(ipiv_true) end - #Normally we wouldn't check column-major routines, since all our matrices - #are row-major, but we use the column-major version in #getrf!, so we - #want to test it here. + # Normally we wouldn't check column-major routines, since all our matrices + # are row-major, but we use the column-major version in #getrf!, so we + # want to test it here. it "calculates LU decomposition using clapack_getrf (col-major, rectangular)" do - #this is supposed to represent the 3x2 matrix + # this is supposed to represent the 3x2 matrix # -1 2 # 0 3 # 1 -2 - a = NMatrix.new([1,6], [-1,0,1,2,3,-2], dtype: dtype) - ipiv = NMatrix::LAPACK::clapack_getrf(:col, 3, 2, a, 3) - b = NMatrix.new([1,6], [-1,0,-1,2,3,0], dtype: dtype) - ipiv_true = [0,1] + a = NMatrix.new([1, 6], [-1, 0, 1, 2, 3, -2], dtype: dtype) + ipiv = NMatrix::LAPACK.clapack_getrf(:col, 3, 2, a, 3) + b = NMatrix.new([1, 6], [-1, 0, -1, 2, 3, 0], dtype: dtype) + ipiv_true = [0, 1] # delta varies for different dtypes err = case dtype @@ -131,17 +130,17 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(a).to be_within(err).of(b) expect(ipiv).to eq(ipiv_true) end it "calculates LU decomposition using #getrf! (rectangular)" do - a = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype) + a = NMatrix.new([3, 4], GETRF_EXAMPLE_ARRAY, dtype: dtype) ipiv = a.getrf! - b = NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype) - ipiv_true = [2,3,3] + b = NMatrix.new([3, 4], GETRF_SOLUTION_ARRAY, dtype: dtype) + ipiv_true = [2, 3, 3] # delta varies for different dtypes err = case dtype @@ -149,18 +148,18 @@ 1e-6 when :float64, :complex128 1e-14 - end + end expect(a).to be_within(err).of(b) expect(ipiv).to eq(ipiv_true) end it "calculates LU decomposition using #getrf! (square)" do - a = NMatrix.new([4,4], [0,1,2,3, 1,1,1,1, 0,-1,-2,0, 0,2,0,2], dtype: dtype) + a = NMatrix.new([4, 4], [0, 1, 2, 3, 1, 1, 1, 1, 0, -1, -2, 0, 0, 2, 0, 2], dtype: dtype) ipiv = a.getrf! - b = NMatrix.new([4,4], [1,1,1,1, 0,2,0,2, 0,-0.5,-2,1, 0,0.5,-1,3], dtype: dtype) - ipiv_true = [2,4,3,4] + b = NMatrix.new([4, 4], [1, 1, 1, 1, 0, 2, 0, 2, 0, -0.5, -2, 1, 0, 0.5, -1, 3], dtype: dtype) + ipiv_true = [2, 4, 3, 4] expect(a).to eq(b) expect(ipiv).to eq(ipiv_true) @@ -168,92 +167,92 @@ # Together, these calls are basically xGESV from LAPACK: http://www.netlib.org/lapack/double/dgesv.f it "exposes clapack_getrs" do - a = NMatrix.new(3, [-2,4,-3, 3,-2,1, 0,-4,3], dtype: dtype) - ipiv = NMatrix::LAPACK::clapack_getrf(:row, 3, 3, a, 3) - b = NMatrix.new([3,1], [-1, 17, -9], dtype: dtype) + a = NMatrix.new(3, [-2, 4, -3, 3, -2, 1, 0, -4, 3], dtype: dtype) + ipiv = NMatrix::LAPACK.clapack_getrf(:row, 3, 3, a, 3) + b = NMatrix.new([3, 1], [-1, 17, -9], dtype: dtype) - NMatrix::LAPACK::clapack_getrs(:row, false, 3, 1, a, 3, ipiv, b, 3) + NMatrix::LAPACK.clapack_getrs(:row, false, 3, 1, a, 3, ipiv, b, 3) expect(b[0]).to eq(5) - expect(b[1]).to eq(-15.0/2) + expect(b[1]).to eq(-15.0 / 2) expect(b[2]).to eq(-13) end it "solves matrix equation (non-vector rhs) using clapack_getrs" do - a = NMatrix.new(3, [-2,4,-3, 3,-2,1, 0,-4,3], dtype: dtype) - b = NMatrix.new([3,2], [-1,2, 17,1, -9,-4], dtype: dtype) + a = NMatrix.new(3, [-2, 4, -3, 3, -2, 1, 0, -4, 3], dtype: dtype) + b = NMatrix.new([3, 2], [-1, 2, 17, 1, -9, -4], dtype: dtype) n = a.shape[0] nrhs = b.shape[1] - ipiv = NMatrix::LAPACK::clapack_getrf(:row, n, n, a, n) + ipiv = NMatrix::LAPACK.clapack_getrf(:row, n, n, a, n) # Even though we pass :row to clapack_getrs, it still interprets b as # column-major, so need to transpose b before and after: b = b.transpose - NMatrix::LAPACK::clapack_getrs(:row, false, n, nrhs, a, n, ipiv, b, n) + NMatrix::LAPACK.clapack_getrs(:row, false, n, nrhs, a, n, ipiv, b, n) b = b.transpose - b_true = NMatrix.new([3,2], [5,1, -7.5,1, -13,0], dtype: dtype) + b_true = NMatrix.new([3, 2], [5, 1, -7.5, 1, -13, 0], dtype: dtype) expect(b).to eq(b_true) end - #posv is like potrf+potrs - #posv is implemented in both nmatrix-atlas and nmatrix-lapacke, so the spec - #needs to be shared here + # posv is like potrf+potrs + # posv is implemented in both nmatrix-atlas and nmatrix-lapacke, so the spec + # needs to be shared here it "solves a (symmetric positive-definite) matrix equation using posv (vector rhs)" do - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - b = NMatrix.new([3,1], [4,2,0], dtype: dtype) + 0, 0, 1,], dtype: dtype) + b = NMatrix.new([3, 1], [4, 2, 0], dtype: dtype) begin - x = NMatrix::LAPACK::posv(:upper, a, b) + x = NMatrix::LAPACK.posv(:upper, a, b) rescue NotImplementedError => e pending e.to_s end - x_true = NMatrix.new([3,1], [1, 1, 0], dtype: dtype) + x_true = NMatrix.new([3, 1], [1, 1, 0], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(x).to be_within(err).of(x_true) end it "solves a (symmetric positive-definite) matrix equation using posv (non-vector rhs)" do - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - b = NMatrix.new([3,2], [4,-1, 2,-1, 0,0], dtype: dtype) + 0, 0, 1,], dtype: dtype) + b = NMatrix.new([3, 2], [4, -1, 2, -1, 0, 0], dtype: dtype) begin - x = NMatrix::LAPACK::posv(:upper, a, b) + x = NMatrix::LAPACK.posv(:upper, a, b) rescue NotImplementedError => e pending e.to_s end - x_true = NMatrix.new([3,2], [1,0, 1,-1, 0,1], dtype: dtype) + x_true = NMatrix.new([3, 2], [1, 0, 1, -1, 0, 1], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(x).to be_within(err).of(x_true) end it "calculates the singular value decomposition with NMatrix#gesvd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) begin u, s, vt = a.gesvd @@ -261,16 +260,16 @@ pending e.to_s end - s_true = NMatrix.new([mn_min,1], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min, 1], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) @@ -282,11 +281,11 @@ end it "calculates the singular value decomposition with NMatrix#gesdd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) begin u, s, vt = a.gesdd @@ -294,26 +293,25 @@ pending e.to_s end - s_true = NMatrix.new([mn_min,1], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min, 1], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) expect(vt).to be_within(err).of(vt_true) end - it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (real matrix, complex eigenvalues)" do n = 3 - a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype) + a = NMatrix.new([n, n], [-1, 0, 0, 0, 1, -2, 0, 1, -1], dtype: dtype) begin eigenvalues, vl, vr = NMatrix::LAPACK.geev(a) @@ -321,20 +319,20 @@ pending e.to_s end - eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64)) - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),2/Math.sqrt(6),0, - Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64)) - vl_true = NMatrix.new([n,n],[0,0,1, - Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0, - 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64)) + eigenvalues_true = NMatrix.new([n, 1], [Complex(0, 1), -Complex(0, 1), -1], dtype: NMatrix.upcast(dtype, :complex64)) + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0, + Complex(1, -1) / Math.sqrt(6), Complex(1, 1) / Math.sqrt(6), 0,], dtype: NMatrix.upcast(dtype, :complex64)) + vl_true = NMatrix.new([n, n], [0, 0, 1, + Complex(-1, 1) / Math.sqrt(6), Complex(-1, -1) / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0,], dtype: NMatrix.upcast(dtype, :complex64)) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-15 - end + end expect(eigenvalues).to be_within(err).of(eigenvalues_true) expect(vr).to be_within(err).of(vr_true) @@ -347,7 +345,7 @@ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (real matrix, real eigenvalues)" do n = 3 - a = NMatrix.new([n,n], [2,0,0, 0,3,2, 0,1,2], dtype: dtype) + a = NMatrix.new([n, n], [2, 0, 0, 0, 3, 2, 0, 1, 2], dtype: dtype) begin eigenvalues, vl, vr = NMatrix::LAPACK.geev(a) @@ -355,25 +353,25 @@ pending e.to_s end - eigenvalues_true = NMatrix.new([n,1], [1, 4, 2], dtype: dtype) + eigenvalues_true = NMatrix.new([n, 1], [1, 4, 2], dtype: dtype) # For some reason, some of the eigenvectors have different signs # when we use the complex versions of geev. This is totally fine, since # they are still normalized eigenvectors even with the sign flipped. if a.complex_dtype? - vr_true = NMatrix.new([n,n],[0,0,1, - 1/Math.sqrt(2),2/Math.sqrt(5),0, - -1/Math.sqrt(2),1/Math.sqrt(5),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - -1/Math.sqrt(5),1/Math.sqrt(2),0, - 2/Math.sqrt(5),1/Math.sqrt(2),0], dtype: dtype) + vr_true = NMatrix.new([n, n], [0, 0, 1, + 1 / Math.sqrt(2), 2 / Math.sqrt(5), 0, + -1 / Math.sqrt(2), 1 / Math.sqrt(5), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + -1 / Math.sqrt(5), 1 / Math.sqrt(2), 0, + 2 / Math.sqrt(5), 1 / Math.sqrt(2), 0,], dtype: dtype) else - vr_true = NMatrix.new([n,n],[0,0,1, - 1/Math.sqrt(2),-2/Math.sqrt(5),0, - -1/Math.sqrt(2),-1/Math.sqrt(5),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - 1/Math.sqrt(5),-1/Math.sqrt(2),0, - -2/Math.sqrt(5),-1/Math.sqrt(2),0], dtype: dtype) + vr_true = NMatrix.new([n, n], [0, 0, 1, + 1 / Math.sqrt(2), -2 / Math.sqrt(5), 0, + -1 / Math.sqrt(2), -1 / Math.sqrt(5), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + 1 / Math.sqrt(5), -1 / Math.sqrt(2), 0, + -2 / Math.sqrt(5), -1 / Math.sqrt(2), 0,], dtype: dtype) end err = case dtype @@ -381,7 +379,7 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(eigenvalues).to be_within(err).of(eigenvalues_true) expect(vr).to be_within(err).of(vr_true) @@ -394,7 +392,7 @@ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (left eigenvectors only)" do n = 3 - a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype) + a = NMatrix.new([n, n], [-1, 0, 0, 0, 1, -2, 0, 1, -1], dtype: dtype) begin eigenvalues, vl = NMatrix::LAPACK.geev(a, :left) @@ -402,17 +400,17 @@ pending e.to_s end - eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64)) - vl_true = NMatrix.new([n,n],[0,0,1, - Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0, - 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64)) + eigenvalues_true = NMatrix.new([n, 1], [Complex(0, 1), -Complex(0, 1), -1], dtype: NMatrix.upcast(dtype, :complex64)) + vl_true = NMatrix.new([n, n], [0, 0, 1, + Complex(-1, 1) / Math.sqrt(6), Complex(-1, -1) / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0,], dtype: NMatrix.upcast(dtype, :complex64)) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-15 - end + end expect(eigenvalues).to be_within(err).of(eigenvalues_true) expect(vl).to be_within(err).of(vl_true) @@ -420,7 +418,7 @@ it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (right eigenvectors only)" do n = 3 - a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype) + a = NMatrix.new([n, n], [-1, 0, 0, 0, 1, -2, 0, 1, -1], dtype: dtype) begin eigenvalues, vr = NMatrix::LAPACK.geev(a, :right) @@ -428,17 +426,17 @@ pending e.to_s end - eigenvalues_true = NMatrix.new([n,1], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64)) - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),2/Math.sqrt(6),0, - Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: NMatrix.upcast(dtype, :complex64)) + eigenvalues_true = NMatrix.new([n, 1], [Complex(0, 1), -Complex(0, 1), -1], dtype: NMatrix.upcast(dtype, :complex64)) + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0, + Complex(1, -1) / Math.sqrt(6), Complex(1, 1) / Math.sqrt(6), 0,], dtype: NMatrix.upcast(dtype, :complex64)) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-15 - end + end expect(eigenvalues).to be_within(err).of(eigenvalues_true) expect(vr).to be_within(err).of(vr_true) @@ -450,7 +448,7 @@ context dtype do it "calculates eigenvalues and eigenvectors NMatrix::LAPACK.geev (complex matrix)" do n = 3 - a = NMatrix.new([n,n], [Complex(0,1),0,0, 0,3,2, 0,1,2], dtype: dtype) + a = NMatrix.new([n, n], [Complex(0, 1), 0, 0, 0, 3, 2, 0, 1, 2], dtype: dtype) begin eigenvalues, vl, vr = NMatrix::LAPACK.geev(a) @@ -458,20 +456,20 @@ pending e.to_s end - eigenvalues_true = NMatrix.new([n,1], [1, 4, Complex(0,1)], dtype: dtype) - vr_true = NMatrix.new([n,n],[0,0,1, - 1/Math.sqrt(2),2/Math.sqrt(5),0, - -1/Math.sqrt(2),1/Math.sqrt(5),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - -1/Math.sqrt(5),1/Math.sqrt(2),0, - 2/Math.sqrt(5),1/Math.sqrt(2),0], dtype: dtype) + eigenvalues_true = NMatrix.new([n, 1], [1, 4, Complex(0, 1)], dtype: dtype) + vr_true = NMatrix.new([n, n], [0, 0, 1, + 1 / Math.sqrt(2), 2 / Math.sqrt(5), 0, + -1 / Math.sqrt(2), 1 / Math.sqrt(5), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + -1 / Math.sqrt(5), 1 / Math.sqrt(2), 0, + 2 / Math.sqrt(5), 1 / Math.sqrt(2), 0,], dtype: dtype) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-15 - end + end expect(eigenvalues).to be_within(err).of(eigenvalues_true) expect(vr).to be_within(err).of(vr_true) diff --git a/spec/leakcheck.rb b/spec/leakcheck.rb index 23b16d13..81303c5e 100644 --- a/spec/leakcheck.rb +++ b/spec/leakcheck.rb @@ -1,16 +1,16 @@ require "./lib/nmatrix" # Fixed: -#n = NMatrix.new(:yale, [8,2], :int64) -#m = NMatrix.new(:yale, [2,8], :int64) -#100.times do +# n = NMatrix.new(:yale, [8,2], :int64) +# m = NMatrix.new(:yale, [2,8], :int64) +# 100.times do # n.dot(m) -#end -#GC.start +# end +# GC.start # Remaining: 100.times do |t| n = NMatrix.new(:dense, 1000, :float64) - n[0,t] = 1.0 - puts n[t,0] + n[0, t] = 1.0 + puts n[t, 0] end diff --git a/spec/math_spec.rb b/spec/math_spec.rb index e1ee8d45..196f0cc9 100644 --- a/spec/math_spec.rb +++ b/spec/math_spec.rb @@ -26,27 +26,26 @@ # versions of unfriendly BLAS and LAPACK functions. # -require 'spec_helper' +require "spec_helper" describe "math" do context "elementwise math functions" do - - [:dense,:list,:yale].each do |stype| + [:dense, :list, :yale].each do |stype| context stype do - - [:int64,:float64].each do |dtype| + [:int64, :float64].each do |dtype| context dtype do before :each do - @size = [2,2] - @m = NMatrix.seq(@size, dtype: dtype, stype: stype)+1 + @size = [2, 2] + @m = NMatrix.seq(@size, dtype: dtype, stype: stype) + 1 @a = @m.to_a.flatten end NMatrix::NMMath::METHODS_ARITY_1.each do |meth| - #skip inverse regular trig functions - next if meth.to_s.start_with?('a') and (not meth.to_s.end_with?('h')) \ - and NMatrix::NMMath::METHODS_ARITY_1.include?( - meth.to_s[1...meth.to_s.length].to_sym) + # skip inverse regular trig functions + next if meth.to_s.start_with?("a") && !meth.to_s.end_with?("h") \ + && NMatrix::NMMath::METHODS_ARITY_1.include?( + meth.to_s[1...meth.to_s.length].to_sym + ) next if meth == :atanh if meth == :-@ @@ -57,19 +56,19 @@ end it "should correctly apply elementwise #{meth}" do - - expect(@m.send(meth)).to eq N.new(@size, @a.map{ |e| Math.send(meth, e) }, - dtype: :float64, stype: stype) + expect(@m.send(meth)).to eq N.new(@size, @a.map { |e| Math.send(meth, e) }, + dtype: :float64, stype: stype) end end NMatrix::NMMath::METHODS_ARITY_2.each do |meth| next if meth == :atan2 it "should correctly apply elementwise #{meth}" do - expect(@m.send(meth, @m)).to eq N.new(@size, @a.map{ |e| - Math.send(meth, e, e) }, - dtype: :float64, - stype: stype) + expect(@m.send(meth, @m)).to eq N.new(@size, @a.map { |e| + Math.send(meth, e, e) + }, + dtype: :float64, + stype: stype) end it "should correctly apply elementwise #{meth} with a scalar first arg" do @@ -83,30 +82,29 @@ it "should correctly apply elementwise natural log" do expect(@m.log).to eq N.new(@size, [0, Math.log(2), Math.log(3), Math.log(4)], - dtype: :float64, stype: stype) + dtype: :float64, stype: stype) end it "should correctly apply elementwise log with arbitrary base" do - expect(@m.log(3)).to eq N.new(@size, [0, Math.log(2,3), 1, Math.log(4,3)], - dtype: :float64, stype: stype) + expect(@m.log(3)).to eq N.new(@size, [0, Math.log(2, 3), 1, Math.log(4, 3)], + dtype: :float64, stype: stype) end context "inverse trig functions" do before :each do - @m = NMatrix.seq(@size, dtype: dtype, stype: stype)/4 + @m = NMatrix.seq(@size, dtype: dtype, stype: stype) / 4 @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, - @a.map{ |e| Math.send(atf, e) }, - dtype: :float64, stype: stype) + @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 @@ -115,26 +113,25 @@ end it "should correctly apply elementwise atan2 with a scalar second arg" do - expect(@m.atan2(1)).to eq N.new(@size, @a.map { |e| Math.send(:atan2, e, 1) }, dtype: :float64, stype: stype) + 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 - [: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 unless jruby? and dtype == :object + @size = [2, 2] + @m = NMatrix.seq(@size, dtype: dtype, stype: stype) + 1 unless jruby? && (dtype == :object) @a = @m.to_a.flatten end - if dtype.to_s.match(/int/) or [:byte, :object].include?(dtype) + if dtype.to_s.match(/int/) || [:byte, :object].include?(dtype) it "should return #{dtype} for #{dtype}" do - pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) expect(@m.send(meth)).to eq N.new(@size, @a.map { |e| e.send(meth) }, dtype: dtype, stype: stype) @@ -144,14 +141,13 @@ expect(@m.send(meth).integer_dtype?).to eq true end end - elsif dtype.to_s.match(/float/) + elsif /float/.match?(dtype.to_s) 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 /complex/.match?(dtype.to_s) it "should properly calculate #{meth} for #{dtype}" do pending("not yet implemented for NMatrix-JRuby") if jruby? @@ -170,40 +166,49 @@ ALL_DTYPES.each do |dtype| context dtype do before :each do - @size = [2,2] + @size = [2, 2] @mat = NMatrix.new @size, [1.33334, 0.9998, 1.9999, -8.9999], dtype: dtype, stype: stype - @ans = @mat.to_a.flatten unless jruby? and dtype == :object + @ans = @mat.to_a.flatten unless jruby? && (dtype == :object) + end + + unless /complex/.match?(dtype) + it "rounds" do + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) + expect(@mat.round).to eq(N.new(@size, @ans.map { |a| a.round}, + dtype: dtype, stype: stype)) + end + end + + unless /complex/.match?(dtype) + it "rounds with args" do + 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 end - it "rounds" do - 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 - 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| - Complex(a.real.round(2), a.imag.round(2))},dtype: dtype, stype: stype) - end if(/complex/ =~ dtype) - - it "rounds complex" do - 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) + if /complex/.match?(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| + Complex(a.real.round(2), a.imag.round(2)) + }, dtype: dtype, stype: stype)) + end + end + + if /complex/.match?(dtype) + it "rounds complex" do + 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 + end end end end - end end end @@ -211,21 +216,21 @@ NON_INTEGER_DTYPES.each do |dtype| context dtype do before do - @m = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype) + @m = NMatrix.new([3, 4], GETRF_EXAMPLE_ARRAY, dtype: dtype) @err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-14 - end + end end - #haven't check this spec yet. Also it doesn't check all the elements of the matrix. + # 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)) + expect(a).to be_within(@err).of(NMatrix.new([3, 4], GETRF_SOLUTION_ARRAY, dtype: dtype)) end it "also returns the permutation matrix" do @@ -234,9 +239,9 @@ a, p = @m.factorize_lu perm_matrix: true - expect(a).to be_within(@err).of(NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype)) + 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) + p_true = NMatrix.new([3, 3], [0, 0, 1, 1, 0, 0, 0, 1, 0], dtype: dtype) expect(p).to eq(p_true) end end @@ -244,9 +249,8 @@ NON_INTEGER_DTYPES.each do |dtype| 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) + # 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 @@ -255,11 +259,11 @@ # 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) + 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) + b = NMatrix.new([3, 3], [1, 0, 0, 1, 1, 0, 1, 1, 2], dtype: dtype) expect(a).to eq(b) expect(r).to eq(b) rescue NotImplementedError @@ -271,11 +275,11 @@ 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) + 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) + b = NMatrix.new([3, 3], [1, 1, 1, 0, 1, 1, 0, 0, 2], dtype: dtype) expect(a).to eq(b) expect(r).to eq(b) rescue NotImplementedError @@ -285,11 +289,11 @@ 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) + a = NMatrix.new([3, 3], [1, 2, 1, 2, 13, 5, 1, 5, 6], dtype: dtype) begin - u,l = a.factorize_cholesky + u, l = a.factorize_cholesky - l_true = NMatrix.new([3,3],[1,0,0, 2,3,0, 1,1,2], dtype: dtype) + l_true = NMatrix.new([3, 3], [1, 0, 0, 2, 3, 0, 1, 1, 2], dtype: dtype) u_true = l_true.transpose expect(u).to eq(u_true) expect(l).to eq(l_true) @@ -302,32 +306,30 @@ NON_INTEGER_DTYPES.each do |dtype| context dtype do - 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) + 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) + 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, - 0.0, 0.0, -35] , dtype: dtype) + 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 + end begin - q,r = a.factorize_qr + 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 @@ -337,31 +339,30 @@ 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, - 23.0, 121.0] , dtype: dtype) + 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) + 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, - 0.0, 0.0] , dtype: dtype) + 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 + end begin - q,r = a.factorize_qr + 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 @@ -371,25 +372,24 @@ 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) + 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) + q_solution = NMatrix.new([3, 3], Q_SOLUTION_ARRAY_3, dtype: dtype) - r_solution = NMatrix.new([3,4], R_SOLUTION_ARRAY, 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 + end begin - q,r = a.factorize_qr + 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 @@ -397,51 +397,48 @@ 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) + 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 + end begin - q,r = a.factorize_qr + q, r = a.factorize_qr 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) + 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 + end begin - q,r = a.factorize_qr + q, r = a.factorize_qr - #Q is orthogonal if Q x Q.transpose = I + # 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) - expect(product[0,1]).to be_within(err).of(0) - expect(product[1,1]).to be_within(err).of(1) - + expect(product[0, 0]).to be_within(err).of(1) + expect(product[1, 0]).to be_within(err).of(0) + expect(product[0, 1]).to be_within(err).of(0) + expect(product[1, 1]).to be_within(err).of(1) rescue NotImplementedError pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end @@ -450,47 +447,46 @@ end ALL_DTYPES.each do |dtype| - next if dtype == :byte #doesn't work for unsigned types + next if dtype == :byte # doesn't work for unsigned types context dtype do err = case dtype when :float32, :complex64 1e-4 - else #integer matrices will return :float64 + else # integer matrices will return :float64 1e-13 - end + end it "should correctly invert a matrix in place (bang)" do pending("not yet implemented for :object dtype") if dtype == :object - a = NMatrix.new(:dense, 5, [1, 8,-9, 7, 5, + 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, + 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, 0, 0, 0, 1, 5, 0, 0, 0, 0, 1,], dtype) if a.integer_dtype? - expect{a.invert!}.to raise_error(DataTypeError) + expect {a.invert!}.to raise_error(DataTypeError) else - #should return inverse as well as modifying a + # should return inverse as well as modifying a r = a.invert! expect(a).to be_within(err).of(b) expect(r).to be_within(err).of(b) end end - 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) + 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) + b = if a.integer_dtype? + 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) + NMatrix.new(:dense, 3, [-24, 18, 5, 20, -15, -4, -5, 4, 1], dtype) end expect(a.invert).to be_within(err).of(b) @@ -498,16 +494,16 @@ 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) + 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) + 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 @@ -522,7 +518,7 @@ 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) + Complex(13, 54), Complex(71, 24),], dtype: dtype) b = NMatrix.identity(2, dtype: dtype) begin @@ -548,7 +544,7 @@ 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) + Complex(45, 16), Complex(25, 32), Complex(91, 43),], dtype: dtype) begin b = a.pinv # pseudo inverse @@ -573,17 +569,16 @@ end end - ALL_DTYPES.each do |dtype| - next if dtype == :byte #doesn't work for unsigned types + next if dtype == :byte # doesn't work for unsigned types context dtype do err = case dtype when :float32, :complex64 1e-4 - else #integer matrices will return :float64 + else # integer matrices will return :float64 1e-13 - end + end it "should correctly find adjugate a matrix in place (bang)" do pending("not yet implemented for :object dtype") if dtype == :object @@ -591,61 +586,57 @@ b = NMatrix.new(:dense, 2, [5, -3, -3, 2], dtype) if a.integer_dtype? - expect{a.adjugate!}.to raise_error(DataTypeError) + expect {a.adjugate!}.to raise_error(DataTypeError) else - #should return adjugate as well as modifying a + # should return adjugate as well as modifying a r = a.adjugate! expect(a).to be_within(err).of(b) expect(r).to be_within(err).of(b) 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) + b = if a.integer_dtype? + NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], :float64) else - b = NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], dtype) + NMatrix.new(:dense, 3, [-8, 18, -4, -5, 12, -1, 4, -6, 2], dtype) end expect(a.adjoint).to be_within(err).of(b) expect(a.adjugate).to be_within(err).of(b) 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| - + [: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. - next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype) + next if [:byte, :int8].include?(left_dtype) && [:byte, :int8].include?(right_dtype) # For now, don't bother testing int-int mult. - #next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype) - it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} matrix multiplication" do - #STDERR.puts "dtype=#{dtype.to_s}" - #STDERR.puts "2" - - nary = if left_dtype.to_s =~ /complex/ - COMPLEX_MATRIX43A_ARRAY - else - MATRIX43A_ARRAY - end - - mary = if right_dtype.to_s =~ /complex/ - COMPLEX_MATRIX32A_ARRAY - else - MATRIX32A_ARRAY - end - - n = NMatrix.new([4,3], nary, dtype: left_dtype, stype: :dense) - m = NMatrix.new([3,2], mary, dtype: right_dtype, stype: :dense) + # next if [:int8,:int16,:int32,:int64].include?(left_dtype) && [:int8,:int16,:int32,:int64].include?(right_dtype) + it "dense handles #{left_dtype} dot #{right_dtype} matrix multiplication" do + # STDERR.puts "dtype=#{dtype.to_s}" + # STDERR.puts "2" + + nary = if /complex/.match?(left_dtype.to_s) + COMPLEX_MATRIX43A_ARRAY + else + MATRIX43A_ARRAY + end + + mary = if /complex/.match?(right_dtype.to_s) + COMPLEX_MATRIX32A_ARRAY + else + MATRIX32A_ARRAY + end + + n = NMatrix.new([4, 3], nary, dtype: left_dtype, stype: :dense) + m = NMatrix.new([3, 2], mary, dtype: right_dtype, stype: :dense) expect(m.shape[0]).to eq(3) expect(m.shape[1]).to eq(2) @@ -659,32 +650,31 @@ r = n.dot m - expect(r[0,0]).to eq(273.0) - expect(r[0,1]).to eq(455.0) - expect(r[1,0]).to eq(243.0) - expect(r[1,1]).to eq(235.0) - expect(r[2,0]).to eq(244.0) - expect(r[2,1]).to eq(205.0) - expect(r[3,0]).to eq(102.0) - expect(r[3,1]).to eq(160.0) + expect(r[0, 0]).to eq(273.0) + expect(r[0, 1]).to eq(455.0) + expect(r[1, 0]).to eq(243.0) + expect(r[1, 1]).to eq(235.0) + expect(r[2, 0]).to eq(244.0) + expect(r[2, 1]).to eq(205.0) + expect(r[3, 0]).to eq(102.0) + expect(r[3, 1]).to eq(160.0) - #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32 + # r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32 end end end - [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |left_dtype| - [:byte,:int8,:int16,:int32,:int64,:float32,:float64].each do |right_dtype| - + [: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. - next if [:byte,:int8].include?(left_dtype) && [:byte,:int8].include?(right_dtype) + next if [:byte, :int8].include?(left_dtype) && [:byte, :int8].include?(right_dtype) - it "dense handles #{left_dtype.to_s} dot #{right_dtype.to_s} vector multiplication" do - #STDERR.puts "dtype=#{dtype.to_s}" - #STDERR.puts "2" - 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], dtype: left_dtype) + it "dense handles #{left_dtype} dot #{right_dtype} vector multiplication" do + # STDERR.puts "dtype=#{dtype.to_s}" + # STDERR.puts "2" + 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], dtype: left_dtype) - m = NMatrix.new([3,1], [2.0, 1.0, 0.0], dtype: right_dtype) + m = NMatrix.new([3, 1], [2.0, 1.0, 0.0], dtype: right_dtype) expect(m.shape[0]).to eq(3) expect(m.shape[1]).to eq(1) @@ -698,12 +688,12 @@ r = n.dot m # r.class.should == NVector - expect(r[0,0]).to eq(4) - expect(r[1,0]).to eq(13) - expect(r[2,0]).to eq(22) - expect(r[3,0]).to eq(31) + expect(r[0, 0]).to eq(4) + expect(r[1, 0]).to eq(13) + expect(r[2, 0]).to eq(22) + expect(r[3, 0]).to eq(31) - #r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32 + # r.dtype.should == :float64 unless left_dtype == :float32 && right_dtype == :float32 end end end @@ -712,64 +702,68 @@ next if integer_dtype?(dtype) context "#cov dtype #{dtype}" 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) + @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 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) - ) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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 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) - ) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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], - [1.00000, 0.56695, 0.53374, - 0.56695, 1.00000, 0.77813, - 0.53374, 0.77813, 1.00000], dtype: dtype)) - end unless dtype =~ /complex/ + unless /complex/.match?(dtype) + it "calculates the correlation matrix" do + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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], + [1.00000, 0.56695, 0.53374, + 0.56695, 1.00000, 0.77813, + 0.53374, 0.77813, 1.00000,], dtype: dtype)) + end + end end context "#symmetric? for #{dtype}" 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) + 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 - 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), - Complex(1.4,-1.5), Complex(1.8,-1.7), 1.3], dtype: dtype) if dtype =~ /complex/ + unless /complex/.match?(dtype) + 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) + end + if /complex/.match?(dtype) + 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), + Complex(1.4, -1.5), Complex(1.8, -1.7), 1.3,], dtype: dtype) + end expect(n.hermitian?).to be_truthy end end @@ -777,118 +771,117 @@ 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, - 0,0,3], dtype: dtype)) - expect(n.permute_columns([0,2,1], {convention: :intuitive})).to eq(NMatrix.new([3,3], [1,0,0, - 0,0,2, - 0,3,0], dtype: dtype)) - expect(n.permute_columns([1,0,2], {convention: :intuitive})).to eq(NMatrix.new([3,3], [0,1,0, - 2,0,0, - 0,0,3], dtype: dtype)) - expect(n.permute_columns([1,2,0], {convention: :intuitive})).to eq(NMatrix.new([3,3], [0,0,1, - 2,0,0, - 0,3,0], dtype: dtype)) - expect(n.permute_columns([2,0,1], {convention: :intuitive})).to eq(NMatrix.new([3,3], [0,1,0, - 0,0,2, - 3,0,0], dtype: dtype)) - expect(n.permute_columns([2,1,0], {convention: :intuitive})).to eq(NMatrix.new([3,3], [0,0,1, - 0,2,0, - 3,0,0], dtype: dtype)) - expect(n.permute_columns([0,1,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [1,0,0, - 0,2,0, - 0,0,3], dtype: dtype)) - expect(n.permute_columns([0,2,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [1,0,0, - 0,0,2, - 0,3,0], dtype: dtype)) - expect(n.permute_columns([1,1,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [0,1,0, - 2,0,0, - 0,0,3], dtype: dtype)) - expect(n.permute_columns([1,2,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [0,0,1, - 2,0,0, - 0,3,0], dtype: dtype)) - expect(n.permute_columns([2,2,2], {convention: :lapack})).to eq(NMatrix.new([3,3], [0,1,0, - 0,0,2, - 3,0,0], dtype: dtype)) - 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)) + 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, + 0, 0, 3,], dtype: dtype)) + expect(n.permute_columns([0, 2, 1], {convention: :intuitive})).to eq(NMatrix.new([3, 3], [1, 0, 0, + 0, 0, 2, + 0, 3, 0,], dtype: dtype)) + expect(n.permute_columns([1, 0, 2], {convention: :intuitive})).to eq(NMatrix.new([3, 3], [0, 1, 0, + 2, 0, 0, + 0, 0, 3,], dtype: dtype)) + expect(n.permute_columns([1, 2, 0], {convention: :intuitive})).to eq(NMatrix.new([3, 3], [0, 0, 1, + 2, 0, 0, + 0, 3, 0,], dtype: dtype)) + expect(n.permute_columns([2, 0, 1], {convention: :intuitive})).to eq(NMatrix.new([3, 3], [0, 1, 0, + 0, 0, 2, + 3, 0, 0,], dtype: dtype)) + expect(n.permute_columns([2, 1, 0], {convention: :intuitive})).to eq(NMatrix.new([3, 3], [0, 0, 1, + 0, 2, 0, + 3, 0, 0,], dtype: dtype)) + expect(n.permute_columns([0, 1, 2], {convention: :lapack})).to eq(NMatrix.new([3, 3], [1, 0, 0, + 0, 2, 0, + 0, 0, 3,], dtype: dtype)) + expect(n.permute_columns([0, 2, 2], {convention: :lapack})).to eq(NMatrix.new([3, 3], [1, 0, 0, + 0, 0, 2, + 0, 3, 0,], dtype: dtype)) + expect(n.permute_columns([1, 1, 2], {convention: :lapack})).to eq(NMatrix.new([3, 3], [0, 1, 0, + 2, 0, 0, + 0, 0, 3,], dtype: dtype)) + expect(n.permute_columns([1, 2, 2], {convention: :lapack})).to eq(NMatrix.new([3, 3], [0, 0, 1, + 2, 0, 0, + 0, 3, 0,], dtype: dtype)) + expect(n.permute_columns([2, 2, 2], {convention: :lapack})).to eq(NMatrix.new([3, 3], [0, 1, 0, + 0, 0, 2, + 3, 0, 0,], dtype: dtype)) + 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, 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) - perm = [1,0,4,3,2] - expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1,5], perm, dtype: dtype)) + m = NMatrix.new([1, 5], [0, 1, 2, 3, 4], dtype: dtype) + perm = [1, 0, 4, 3, 2] + expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1, 5], perm, dtype: dtype)) - m = NMatrix.new([1,6], [0,1,2,3,4,5], dtype: dtype) - perm = [2,4,1,0,5,3] - expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1,6], perm, dtype: dtype)) + m = NMatrix.new([1, 6], [0, 1, 2, 3, 4, 5], dtype: dtype) + perm = [2, 4, 1, 0, 5, 3] + expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1, 6], perm, dtype: dtype)) - m = NMatrix.new([1,7], [0,1,2,3,4,5,6], dtype: dtype) - perm = [1,3,5,6,0,2,4] - expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1,7], perm, dtype: dtype)) + m = NMatrix.new([1, 7], [0, 1, 2, 3, 4, 5, 6], dtype: dtype) + perm = [1, 3, 5, 6, 0, 2, 4] + expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1, 7], perm, dtype: dtype)) - m = NMatrix.new([1,8], [0,1,2,3,4,5,6,7], dtype: dtype) - perm = [6,7,5,4,1,3,0,2] - expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1,8], perm, dtype: dtype)) + m = NMatrix.new([1, 8], [0, 1, 2, 3, 4, 5, 6, 7], dtype: dtype) + perm = [6, 7, 5, 4, 1, 3, 0, 2] + expect(m.permute_columns(perm, {convention: :intuitive})).to eq(NMatrix.new([1, 8], perm, dtype: dtype)) end end end context "#solve" do NON_INTEGER_DTYPES.each do |dtype| - 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 + 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) + 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 + 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 1e-5 else 1e-14 - end + end - expect(a.solve(b)).to be_within(err).of(NMatrix.new([3,1], [1,2,3], dtype: dtype)) + 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 + 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) + expect(a.solve(b)).to eq(NMatrix.new([3, 2], [1, 0, 0, 0, 2, 2], dtype: dtype)) end end 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) } + 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) + 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) @@ -896,7 +889,7 @@ 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) + 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) @@ -904,7 +897,7 @@ 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) + 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) @@ -912,11 +905,11 @@ end context "when form: :upper_tri" do - let(:a) { NMatrix.new([3,3], [3, 2, 1, 0, 2, 0.5, 0, 0, 9], dtype: dtype) } + 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) + 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) @@ -924,7 +917,7 @@ 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) + 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) @@ -932,7 +925,7 @@ 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) + 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) @@ -940,25 +933,25 @@ end context "when form: :pos_def" do - let(:a) { NMatrix.new([3,3], [4, 1, 2, 1, 5, 3, 2, 3, 6], dtype: dtype) } + 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) + 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)) + 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) + 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)) + 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" end @@ -970,9 +963,9 @@ 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) + 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) @@ -984,9 +977,9 @@ 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) + 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) @@ -1001,22 +994,22 @@ 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 + 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 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)) + 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)) end end end @@ -1029,48 +1022,50 @@ context "#pow #{dtype} #{stype}" 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 + @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 - 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], - dtype: answer_dtype, - stype: stype)) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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,], + 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, - 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)) - end unless stype =~ /yale/ or dtype == :object or ALL_DTYPES.grep(/int/).include? dtype + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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 + + unless stype =~ /yale/ || (dtype == :object) || ALL_DTYPES.grep(/int/).include?(dtype) + 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, + 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) + end + end it "raises a square matrix to zero" do - 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)) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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 + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) expect(@n.pow(1)).to eq(@n) end end @@ -1081,17 +1076,17 @@ [:dense, :yale].each do |stype| context "#kron_prod #{dtype} #{stype}" 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) + @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) end it "computes the Kronecker product of two NMatrix objects" do - pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) expect(@a.kron_prod(@b)).to eq(@c) end end @@ -1103,15 +1098,15 @@ 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, - 4,1,3], dtype: dtype) - @c = NMatrix.new([4,4], [1, 0, 1, 1, - 1, 2, 3, 1, - 3, 3, 3, 1, - 1, 2, 3, 4], dtype: dtype) + @a = NMatrix.new([2, 2], [1, 2, + 3, 4,], dtype: dtype) + @b = NMatrix.new([3, 3], [1, 2, 3, + 5, 0, 1, + 4, 1, 3,], dtype: dtype) + @c = NMatrix.new([4, 4], [1, 0, 1, 1, + 1, 2, 3, 1, + 3, 3, 3, 1, + 1, 2, 3, 4,], dtype: dtype) @err = case dtype when :float32, :complex64 1e-6 @@ -1119,7 +1114,7 @@ 1e-14 else 1e-64 # FIXME: should be 0, but be_within(0) does not work. - end + end end it "computes the determinant of 2x2 matrix" do pending("not yet implemented for :object dtype") if dtype == :object @@ -1136,18 +1131,18 @@ 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) + expect {@a.det_exact}.to raise_error(DataTypeError) else - pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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) + expect {@a.det_exact}.to raise_error(DataTypeError) else - pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) expect(@b.det_exact).to be_within(@err).of(-8) end end @@ -1156,37 +1151,37 @@ end context "#scale and #scale!" do - [:dense,:list,:yale].each do |stype| + [:dense, :list, :yale].each do |stype| ALL_DTYPES.each do |dtype| context "for #{dtype}" do before do @m = NMatrix.new([3, 3], [0, 1, 2, 3, 4, 5, - 6, 7, 8], stype: stype, dtype: dtype) + 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) + 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)) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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 pending("not yet implemented for :object dtype") if dtype == :object if dtype == :int8 - expect{@m.scale! 2}.to raise_error(DataTypeError) + expect {@m.scale! 2}.to raise_error(DataTypeError) else - pending("not yet implemented for NMatrix-JRuby") if jruby? and (dtype == :complex64 || dtype == :complex128) + pending("not yet implemented for NMatrix-JRuby") if jruby? && (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)) + 12, 14, 16,], stype: stype, dtype: dtype)) end end end @@ -1198,23 +1193,22 @@ 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) + @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) + 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" + rescue NotImplementedError + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end end end @@ -1222,24 +1216,23 @@ 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) + 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) + 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) + # 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" + rescue NotImplementedError + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end expect(@n.matrix_norm(-1)).to eq(6) end @@ -1247,9 +1240,9 @@ 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) + 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) @@ -1258,8 +1251,8 @@ 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) + 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 @@ -1269,95 +1262,86 @@ 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 + 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 - - context "#svd_rank" do + + context "#svd_rank" do FLOAT_DTYPES.each do |dtype| context dtype do - #examples from https://www.cliffsnotes.com/study-guides/algebra/linear-algebra/real-euclidean-vector-spaces/the-rank-of-a-matrix + # examples from https://www.cliffsnotes.com/study-guides/algebra/linear-algebra/real-euclidean-vector-spaces/the-rank-of-a-matrix it "calculates the rank of matrix using singular value decomposition with NMatrix on rectangular matrix without tolerence" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new([4,3],[2,-1,3, 1,0,1, 0,2,-1, 1,1,4], dtype: dtype) + a = NMatrix.new([4, 3], [2, -1, 3, 1, 0, 1, 0, 2, -1, 1, 1, 4], dtype: dtype) begin - rank = a.svd_rank() - - rank_true = 3 - expect(rank).to eq (rank_true) + rank = a.svd_rank + rank_true = 3 + expect(rank).to eq rank_true rescue NotImplementedError - pending "Suppressing a NotImplementedError when the lapacke plugin is not available" - end + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" + end end it "calculates the rank of matrix using singular value decomposition with NMatrix on rectangular matrix with tolerence" do - - a = NMatrix.new([4,3],[2,-1,3, 1,0,1, 0,2,-1, 1,1,4], dtype: dtype) + a = NMatrix.new([4, 3], [2, -1, 3, 1, 0, 1, 0, 2, -1, 1, 1, 4], dtype: dtype) pending("not yet implemented for NMatrix-JRuby") if jruby? begin rank = a.svd_rank(4) - - rank_true = 1 - expect(rank).to eq (rank_true) + rank_true = 1 + expect(rank).to eq rank_true rescue NotImplementedError - pending "Suppressing a NotImplementedError when the lapacke plugin is not available" + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end end it "calculates the rank of matrix using singular value decomposition with NMatrix on square matrix without tolerence" do - - a = NMatrix.new([4,4],[1,-1,1,-1, -1,1,-1,1, 1,-1,1,-1, -1,1,-1,1], dtype: dtype) + a = NMatrix.new([4, 4], [1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1], dtype: dtype) pending("not yet implemented for NMatrix-JRuby") if jruby? begin - rank = a.svd_rank() - - rank_true = 1 - expect(rank).to eq (rank_true) + rank = a.svd_rank + rank_true = 1 + expect(rank).to eq rank_true rescue NotImplementedError - pending "Suppressing a NotImplementedError when the lapacke plugin is not available" + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end end it "calculates the rank of matrix using singular value decomposition with NMatrix on square matrix with very small tolerence(for float32)" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new([4,4],[1,-1,1,-1, -1,1,-1,1, 1,-1,1,-1, -1,1,-1,1], dtype: :float32) + a = NMatrix.new([4, 4], [1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1], dtype: :float32) begin rank = a.svd_rank(1.7881389169360773e-08) - - rank_true = 2 - expect(rank).to eq (rank_true) + rank_true = 2 + expect(rank).to eq rank_true rescue NotImplementedError - pending "Suppressing a NotImplementedError when the lapacke plugin is not available" + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end end it "calculates the rank of matrix using singular value decomposition with NMatrix on square matrix with very small tolerence(for float64)" do pending("not yet implemented for NMatrix-JRuby") if jruby? - a = NMatrix.new([4,4],[1,-1,1,-1, -1,1,-1,1, 1,-1,1,-1, -1,1,-1,1], dtype: :float64) + a = NMatrix.new([4, 4], [1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1], dtype: :float64) begin rank = a.svd_rank(1.7881389169360773e-08) - - rank_true = 1 - expect(rank).to eq (rank_true) + rank_true = 1 + expect(rank).to eq rank_true rescue NotImplementedError - pending "Suppressing a NotImplementedError when the lapacke plugin is not available" + pending "Suppressing a NotImplementedError when the lapacke plugin is not available" end end - end - end - end - + end + end end diff --git a/spec/nmatrix_yale_spec.rb b/spec/nmatrix_yale_spec.rb index 90b0f138..04cbf8cd 100644 --- a/spec/nmatrix_yale_spec.rb +++ b/spec/nmatrix_yale_spec.rb @@ -24,12 +24,11 @@ # # Basic tests for NMatrix's Yale storage type. # -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix" describe NMatrix do context :yale do - it "compares two empty matrices" do n = NMatrix.new(4, stype: :yale, dtype: :float64) m = NMatrix.new(4, stype: :yale, dtype: :float64) @@ -40,177 +39,176 @@ n = NMatrix.new(2, stype: :yale, dtype: :float64) m = NMatrix.new(2, stype: :yale, dtype: :float64) - m[0,0] = 1 - m[0,1] = 1 + m[0, 0] = 1 + m[0, 1] = 1 expect(n).not_to eq(m) - n[0,0] = 1 + n[0, 0] = 1 expect(n).not_to eq(m) - n[0,1] = 1 + n[0, 1] = 1 expect(n).to eq(m) end it "compares two matrices following elementwise operations" do n = NMatrix.new(2, stype: :yale, dtype: :float64) m = NMatrix.new(2, stype: :yale, dtype: :float64) - n[0,1] = 1 - m[0,1] = -1 - x = n+m - expect(n+m).to eq(NMatrix.new(2, 0.0, stype: :yale)) + n[0, 1] = 1 + m[0, 1] = -1 + x = n + m + expect(n + m).to eq(NMatrix.new(2, 0.0, stype: :yale)) end it "sets diagonal values" do - n = NMatrix.new([2,3], stype: :yale, dtype: :float64) + n = NMatrix.new([2, 3], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[1,1] = 0.1 - n[0,0] = 0.2 + n[1, 1] = 0.1 + n[0, 0] = 0.2 expect(n.yale_d).to eq([0.2, 0.1]) end it "gets non-diagonal rows as hashes" do - n = NMatrix.new([4,6], stype: :yale, dtype: :float64) + n = NMatrix.new([4, 6], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[0,0] = 0.1 - n[0,2] = 0.2 - n[0,3] = 0.3 - n[1,5] = 0.4 + n[0, 0] = 0.1 + n[0, 2] = 0.2 + n[0, 3] = 0.3 + n[1, 5] = 0.4 h = n.yale_nd_row(0, :hash) expect(h).to eq({2 => 0.2, 3 => 0.3}) end it "gets non-diagonal occupied column indices for a given row" do - n = NMatrix.new([4,6], stype: :yale, dtype: :float64) + n = NMatrix.new([4, 6], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[0,0] = 0.1 - n[0,2] = 0.2 - n[0,3] = 0.3 - n[1,5] = 0.4 + n[0, 0] = 0.1 + n[0, 2] = 0.2 + n[0, 3] = 0.3 + n[1, 5] = 0.4 a = n.yale_nd_row(0, :array) - expect(a).to eq([2,3]) + expect(a).to eq([2, 3]) end it "does not resize until necessary" do - n = NMatrix.new([2,3], stype: :yale, dtype: :float64) + n = NMatrix.new([2, 3], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) expect(n.yale_size).to eq(3) expect(n.capacity).to eq(5) - n[0,0] = 0.1 - n[0,1] = 0.2 - n[1,0] = 0.3 + n[0, 0] = 0.1 + n[0, 1] = 0.2 + n[1, 0] = 0.3 expect(n.yale_size).to eq(5) expect(n.capacity).to eq(5) end - it "sets when not resizing" do - n = NMatrix.new([2,3], stype: :yale, dtype: :float64) + n = NMatrix.new([2, 3], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[0,0] = 0.1 - n[0,1] = 0.2 - n[1,0] = 0.3 + n[0, 0] = 0.1 + n[0, 1] = 0.2 + n[1, 0] = 0.3 expect(n.yale_a).to eq([0.1, 0.0, 0.0, 0.2, 0.3]) - expect(n.yale_ija).to eq([3,4,5,1,0]) + expect(n.yale_ija).to eq([3, 4, 5, 1, 0]) end it "sets when resizing" do - n = NMatrix.new([2,3], stype: :yale, dtype: :float64) + n = NMatrix.new([2, 3], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[0,0] = 0.01 - n[1,1] = 0.1 - n[0,1] = 0.2 - n[1,0] = 0.3 - n[1,2] = 0.4 + n[0, 0] = 0.01 + n[1, 1] = 0.1 + n[0, 1] = 0.2 + n[1, 0] = 0.3 + n[1, 2] = 0.4 expect(n.yale_d).to eq([0.01, 0.1]) - expect(n.yale_ia).to eq([3,4,6]) - expect(n.yale_ja).to eq([1,0,2,nil]) + expect(n.yale_ia).to eq([3, 4, 6]) + expect(n.yale_ja).to eq([1, 0, 2, nil]) expect(n.yale_lu).to eq([0.2, 0.3, 0.4, nil]) end it "resizes without erasing values" do - require 'yaml' + require "yaml" - associations = File.open('spec/nmatrix_yale_resize_test_associations.yaml') { |y| YAML::load(y) } + associations = File.open("spec/nmatrix_yale_resize_test_associations.yaml") { |y| YAML.load(y) } - n = NMatrix.new([618,2801], stype: :yale, dtype: :byte, capacity: associations.size) - #n = NMatrix.new(:yale, [618, 2801], associations.size, :byte) + n = NMatrix.new([618, 2801], stype: :yale, dtype: :byte, capacity: associations.size) + # n = NMatrix.new(:yale, [618, 2801], associations.size, :byte) - associations.each_pair do |j,i| - n[i,j] = 1 - expect(n[i,j]).to be(1), "Value at #{i},#{j} not inserted correctly!" + associations.each_pair do |j, i| + n[i, j] = 1 + expect(n[i, j]).to be(1), "Value at #{i},#{j} not inserted correctly!" end - associations.each_pair do |j,i| - expect(n[i,j]).to be(1), "Value at #{i},#{j} erased during resize!" + associations.each_pair do |j, i| + expect(n[i, j]).to be(1), "Value at #{i},#{j} erased during resize!" end end it "sets values within rows" do - n = NMatrix.new([3,20], stype: :yale, dtype: :float64) + n = NMatrix.new([3, 20], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[2,1] = 1.0 - n[2,0] = 1.5 - n[2,15] = 2.0 + n[2, 1] = 1.0 + n[2, 0] = 1.5 + n[2, 15] = 2.0 expect(n.yale_lu).to eq([1.5, 1.0, 2.0]) expect(n.yale_ja).to eq([0, 1, 15]) end it "gets values within rows" do - n = NMatrix.new([3,20], stype: :yale, dtype: :float64) - n[2,1] = 1.0 - n[2,0] = 1.5 - n[2,15] = 2.0 - expect(n[2,1]).to eq(1.0) - expect(n[2,0]).to eq(1.5) - expect(n[2,15]).to eq(2.0) + n = NMatrix.new([3, 20], stype: :yale, dtype: :float64) + n[2, 1] = 1.0 + n[2, 0] = 1.5 + n[2, 15] = 2.0 + expect(n[2, 1]).to eq(1.0) + expect(n[2, 0]).to eq(1.5) + expect(n[2, 15]).to eq(2.0) end it "sets values within large rows" do - n = NMatrix.new([10,300], stype: :yale, dtype: :float64) + n = NMatrix.new([10, 300], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[5,1] = 1.0 - n[5,0] = 1.5 - n[5,15] = 2.0 - n[5,291] = 3.0 - n[5,292] = 4.0 - n[5,289] = 5.0 - n[5,290] = 6.0 - n[5,293] = 2.0 - n[5,299] = 7.0 - n[5,100] = 8.0 + n[5, 1] = 1.0 + n[5, 0] = 1.5 + n[5, 15] = 2.0 + n[5, 291] = 3.0 + n[5, 292] = 4.0 + n[5, 289] = 5.0 + n[5, 290] = 6.0 + n[5, 293] = 2.0 + n[5, 299] = 7.0 + n[5, 100] = 8.0 expect(n.yale_lu).to eq([1.5, 1.0, 2.0, 8.0, 5.0, 6.0, 3.0, 4.0, 2.0, 7.0]) expect(n.yale_ja).to eq([0, 1, 15, 100, 289, 290, 291, 292, 293, 299]) end it "gets values within large rows" do - n = NMatrix.new([10,300], stype: :yale, dtype: :float64) + n = NMatrix.new([10, 300], stype: :yale, dtype: :float64) n.extend(NMatrix::YaleFunctions) - n[5,1] = 1.0 - n[5,0] = 1.5 - n[5,15] = 2.0 - n[5,291] = 3.0 - n[5,292] = 4.0 - n[5,289] = 5.0 - n[5,290] = 6.0 - n[5,293] = 2.0 - n[5,299] = 7.0 - n[5,100] = 8.0 + n[5, 1] = 1.0 + n[5, 0] = 1.5 + n[5, 15] = 2.0 + n[5, 291] = 3.0 + n[5, 292] = 4.0 + n[5, 289] = 5.0 + n[5, 290] = 6.0 + n[5, 293] = 2.0 + n[5, 299] = 7.0 + n[5, 100] = 8.0 n.yale_ja.each_index do |idx| j = n.yale_ja[idx] - expect(n[5,j]).to eq(n.yale_lu[idx]) + expect(n[5, j]).to eq(n.yale_lu[idx]) end end it "dots two identical matrices" do a = NMatrix.new(4, stype: :yale, dtype: :float64) - a[0,1] = 4.0 - a[1,2] = 1.0 - a[1,3] = 1.0 - a[3,1] = 2.0 + a[0, 1] = 4.0 + a[1, 2] = 1.0 + a[1, 3] = 1.0 + a[3, 1] = 2.0 b = a.dup c = a.dot b - d = NMatrix.new(4, [0,0,4,4, 0,2,0,0, 0,0,0,0, 0,0,2,2], dtype: :float64, stype: :yale) + d = NMatrix.new(4, [0, 0, 4, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2], dtype: :float64, stype: :yale) expect(c).to eq(d) end @@ -218,26 +216,25 @@ it "dots two identical matrices where a positive and negative partial sum cancel on the diagonal" do a = NMatrix.new(4, 0.0, stype: :yale) - a[0,0] = 1.0 - a[0,1] = 4.0 - a[1,2] = 2.0 - a[1,3] = -4.0 - a[3,1] = 4.0 - a[3,3] = 4.0 + a[0, 0] = 1.0 + a[0, 1] = 4.0 + a[1, 2] = 2.0 + a[1, 3] = -4.0 + a[3, 1] = 4.0 + a[3, 3] = 4.0 b = a.dup c = a.dot b c.extend(NMatrix::YaleFunctions) - expect(c.yale_ija.reject { |i| i.nil? }).to eq([5,8,9,9,11,1,2,3,3,1,2]) + expect(c.yale_ija.reject { |i| i.nil? }).to eq([5, 8, 9, 9, 11, 1, 2, 3, 3, 1, 2]) expect(c.yale_a.reject { |i| i.nil? }).to eq([1.0, -16.0, 0.0, 0.0, 0.0, 4.0, 8.0, -16.0, -16.0, 16.0, 8.0]) - end it "dots two vectors" do - n = NMatrix.new([16,1], 0, stype: :yale) - m = NMatrix.new([1,16], 0, stype: :yale) + n = NMatrix.new([16, 1], 0, stype: :yale) + m = NMatrix.new([1, 16], 0, stype: :yale) n[0] = m[0] = 1 n[1] = m[1] = 2 @@ -265,12 +262,12 @@ expect(nm.yale_a[0...107]).to eq(nmr.yale_a[0...107]) mn = m.dot(n) - expect(mn[0,0]).to eq(541) + expect(mn[0, 0]).to eq(541) end it "calculates the row key intersections of two matrices" do - a = NMatrix.new([3,9], [0,1], stype: :yale, dtype: :byte, default: 0) - b = NMatrix.new([3,9], [0,0,1,0,1], stype: :yale, dtype: :byte, default: 0) + a = NMatrix.new([3, 9], [0, 1], stype: :yale, dtype: :byte, default: 0) + b = NMatrix.new([3, 9], [0, 0, 1, 0, 1], stype: :yale, dtype: :byte, default: 0) a.extend NMatrix::YaleFunctions b.extend NMatrix::YaleFunctions @@ -280,7 +277,6 @@ expect(a.yale_ja_d_keys_at(ai) & b.yale_ja_d_keys_at(bi)).to eq(a.yale_row_keys_intersection(ai, b, bi)) end end - end end end diff --git a/spec/plugins/atlas/atlas_spec.rb b/spec/plugins/atlas/atlas_spec.rb index 3448603a..176ba263 100644 --- a/spec/plugins/atlas/atlas_spec.rb +++ b/spec/plugins/atlas/atlas_spec.rb @@ -25,20 +25,20 @@ # Tests for interfaces that are only exposed by nmatrix-atlas # -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix/atlas" describe "NMatrix::LAPACK implementation from nmatrix-atlas plugin" do [:float32, :float64, :complex64, :complex128].each do |dtype| context dtype do it "exposes clapack_getri" do - a = NMatrix.new(:dense, 3, [1,0,4,1,1,6,-3,0,-10], dtype) - ipiv = NMatrix::LAPACK::clapack_getrf(:row, 3, 3, a, 3) # get pivot from getrf, use for getri + a = NMatrix.new(:dense, 3, [1, 0, 4, 1, 1, 6, -3, 0, -10], dtype) + ipiv = NMatrix::LAPACK.clapack_getrf(:row, 3, 3, a, 3) # get pivot from getrf, use for getri begin - NMatrix::LAPACK::clapack_getri(:row, 3, a, 3, ipiv) + NMatrix::LAPACK.clapack_getri(:row, 3, a, 3, ipiv) - b = NMatrix.new(:dense, 3, [-5,0,-2,-4,1,-1,1.5,0,0.5], dtype) + b = NMatrix.new(:dense, 3, [-5, 0, -2, -4, 1, -1, 1.5, 0, 0.5], dtype) expect(a).to eq(b) rescue NotImplementedError => e pending e.to_s @@ -53,58 +53,58 @@ it "exposes clapack_potrf upper" do pending "potrf requires clapack" unless NMatrix.has_clapack? - a = NMatrix.new(:dense, 3, [25,15,-5, 0,18,0, 0,0,11], dtype) - NMatrix::LAPACK::clapack_potrf(:row, :upper, 3, a, 3) - b = NMatrix.new(:dense, 3, [5,3,-1, 0,3,1, 0,0,3], dtype) + a = NMatrix.new(:dense, 3, [25, 15, -5, 0, 18, 0, 0, 0, 11], dtype) + NMatrix::LAPACK.clapack_potrf(:row, :upper, 3, a, 3) + b = NMatrix.new(:dense, 3, [5, 3, -1, 0, 3, 1, 0, 0, 3], dtype) expect(a).to eq(b) end it "exposes clapack_potrf lower" do pending "potrf requires clapack" unless NMatrix.has_clapack? - a = NMatrix.new(:dense, 3, [25,0,0, 15,18,0,-5,0,11], dtype) - NMatrix::LAPACK::clapack_potrf(:row, :lower, 3, a, 3) - b = NMatrix.new(:dense, 3, [5,0,0, 3,3,0, -1,1,3], dtype) + a = NMatrix.new(:dense, 3, [25, 0, 0, 15, 18, 0, -5, 0, 11], dtype) + NMatrix::LAPACK.clapack_potrf(:row, :lower, 3, a, 3) + b = NMatrix.new(:dense, 3, [5, 0, 0, 3, 3, 0, -1, 1, 3], dtype) expect(a).to eq(b) end it "exposes clapack_potri" do pending "potri requires clapack" unless NMatrix.has_clapack? - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - NMatrix::LAPACK::clapack_potrf(:row, :upper, 3, a, 3) - NMatrix::LAPACK::clapack_potri(:row, :upper, 3, a, 3) - b = NMatrix.new(3, [0.5, -0.5, 1, 0, 1.5, -2, 0, 0, 4], dtype: dtype) + 0, 0, 1,], dtype: dtype) + NMatrix::LAPACK.clapack_potrf(:row, :upper, 3, a, 3) + NMatrix::LAPACK.clapack_potri(:row, :upper, 3, a, 3) + b = NMatrix.new(3, [0.5, -0.5, 1, 0, 1.5, -2, 0, 0, 4], dtype: dtype) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-14 - end + end expect(a).to be_within(err).of(b) end it "exposes clapack_potrs" do pending "potrs requires clapack" unless NMatrix.has_clapack? - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - b = NMatrix.new([3,1], [3,0,2], dtype: dtype) + 0, 0, 1,], dtype: dtype) + b = NMatrix.new([3, 1], [3, 0, 2], dtype: dtype) - NMatrix::LAPACK::clapack_potrf(:row, :upper, 3, a, 3) - NMatrix::LAPACK::clapack_potrs(:row, :upper, 3, 1, a, 3, b, 3) + NMatrix::LAPACK.clapack_potrf(:row, :upper, 3, a, 3) + NMatrix::LAPACK.clapack_potrs(:row, :upper, 3, 1, a, 3, b, 3) - x = NMatrix.new([3,1], [3.5, -5.5, 11], dtype: dtype) + x = NMatrix.new([3, 1], [3.5, -5.5, 11], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(b).to be_within(err).of(x) end @@ -114,14 +114,14 @@ [:float32, :float64, :complex64, :complex128].each do |dtype| context dtype do it "calculates the singular value decomposition with lapack_gesvd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) - s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) #s is always real and always returned as float/double, never as complex - u = NMatrix.new([m,m], 0, dtype: dtype) - vt = NMatrix.new([n,n], 0, dtype: dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) + s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) # s is always real and always returned as float/double, never as complex + u = NMatrix.new([m, m], 0, dtype: dtype) + vt = NMatrix.new([n, n], 0, dtype: dtype) # This is a pure LAPACK function so it expects column-major functions # So we need to transpose the input as well as the output @@ -130,16 +130,16 @@ u = u.transpose vt = vt.transpose - s_true = NMatrix.new([mn_min], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) @@ -147,14 +147,14 @@ end it "calculates the singular value decomposition with lapack_gesdd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) - s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) #s is always real and always returned as float/double, never as complex - u = NMatrix.new([m,m], 0, dtype: dtype) - vt = NMatrix.new([n,n], 0, dtype: dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) + s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) # s is always real and always returned as float/double, never as complex + u = NMatrix.new([m, m], 0, dtype: dtype) + vt = NMatrix.new([n, n], 0, dtype: dtype) # This is a pure LAPACK function so it expects column-major functions # So we need to transpose the input as well as the output @@ -163,16 +163,16 @@ u = u.transpose vt = vt.transpose - s_true = NMatrix.new([mn_min], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) @@ -181,49 +181,49 @@ it "exposes lapack_geev" do n = 3 - a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype) + a = NMatrix.new([n, n], [-1, 0, 0, 0, 1, -2, 0, 1, -1], dtype: dtype) w = NMatrix.new([n], dtype: dtype) - if a.complex_dtype? #for real dtypes, imaginary parts of eigenvalues are stored in separate vector - wi = nil + wi = if a.complex_dtype? # for real dtypes, imaginary parts of eigenvalues are stored in separate vector + nil else - wi = NMatrix.new([n], dtype: dtype) + NMatrix.new([n], dtype: dtype) end - vl = NMatrix.new([n,n], dtype: dtype) - vr = NMatrix.new([n,n], dtype: dtype) + vl = NMatrix.new([n, n], dtype: dtype) + vr = NMatrix.new([n, n], dtype: dtype) # This is a pure LAPACK routine so it expects column-major matrices, # so we need to transpose everything. a = a.transpose - NMatrix::LAPACK::lapack_geev(:left, :right, n, a, n, w, wi, vl, n, vr, n, 2*n) + NMatrix::LAPACK.lapack_geev(:left, :right, n, a, n, w, wi, vl, n, vr, n, 2 * n) vr = vr.transpose vl = vl.transpose - if !a.complex_dtype? - w = w + wi*Complex(0,1) + unless a.complex_dtype? + w += wi * Complex(0, 1) end - w_true = NMatrix.new([n], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64)) + w_true = NMatrix.new([n], [Complex(0, 1), -Complex(0, 1), -1], dtype: NMatrix.upcast(dtype, :complex64)) if a.complex_dtype? - #For complex types the right/left eigenvectors are stored as columns - #of vr/vl. - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),2/Math.sqrt(6),0, - Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0, - 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: dtype) + # For complex types the right/left eigenvectors are stored as columns + # of vr/vl. + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0, + Complex(1, -1) / Math.sqrt(6), Complex(1, 1) / Math.sqrt(6), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + Complex(-1, 1) / Math.sqrt(6), Complex(-1, -1) / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0,], dtype: dtype) else - #For real types, the real part of the first and second eigenvectors is - #stored in the first column, the imaginary part of the first (= the - #negative of the imaginary part of the second) eigenvector is stored - #in the second column, and the third eigenvector (purely real) is the - #third column. - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),0,0, - 1/Math.sqrt(6),-1/Math.sqrt(6),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - -1/Math.sqrt(6),1/Math.sqrt(6),0, - 2/Math.sqrt(6),0,0], dtype: dtype) + # For real types, the real part of the first and second eigenvectors is + # stored in the first column, the imaginary part of the first (= the + # negative of the imaginary part of the second) eigenvector is stored + # in the second column, and the third eigenvector (purely real) is the + # third column. + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 0, 0, + 1 / Math.sqrt(6), -1 / Math.sqrt(6), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + -1 / Math.sqrt(6), 1 / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 0, 0,], dtype: dtype) end err = case dtype @@ -231,7 +231,7 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(w).to be_within(err).of(w_true) expect(vr).to be_within(err).of(vr_true) diff --git a/spec/plugins/fftw/fftw_spec.rb b/spec/plugins/fftw/fftw_spec.rb index 14bc5f86..62e94b72 100644 --- a/spec/plugins/fftw/fftw_spec.rb +++ b/spec/plugins/fftw/fftw_spec.rb @@ -25,47 +25,46 @@ # Tests for interfaces that are only exposed by nmatrix-fftw # -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix/fftw" describe NMatrix do context "#fft" do before do @answer = NMatrix.new([10], - [ - Complex(330.3200,0.0000) , Complex(-8.4039 ,-150.3269), - Complex(-99.4807,-68.6579) , Complex(-143.6861, -20.4273), - Complex(67.6207 , 8.5236), Complex(130.7800 , 0.0000), - Complex(67.6207 , -8.5236), Complex(-143.6861, 20.4273), - Complex(-99.4807 , 68.6579), Complex(-8.4039 ,150.3269) - ], dtype: :complex128) + [ + Complex(330.3200, 0.0000), Complex(-8.4039, -150.3269), + Complex(-99.4807, -68.6579), Complex(-143.6861, -20.4273), + Complex(67.6207, 8.5236), Complex(130.7800, 0.0000), + Complex(67.6207, -8.5236), Complex(-143.6861, 20.4273), + Complex(-99.4807, 68.6579), Complex(-8.4039, 150.3269), + ], dtype: :complex128) end it "computes an FFT of a complex NMatrix" do nm = NMatrix.new([10], [ - Complex(9.32,0), Complex(44,0), Complex(125,0), Complex(34,0), - Complex(31,0), Complex(44,0), Complex(12,0), Complex(1,0), - Complex(53.23,0),Complex(-23.23,0)], dtype: :complex128) + Complex(9.32, 0), Complex(44, 0), Complex(125, 0), Complex(34, 0), + Complex(31, 0), Complex(44, 0), Complex(12, 0), Complex(1, 0), + Complex(53.23, 0), Complex(-23.23, 0), + ], dtype: :complex128) expect(nm.fft.round(4)).to eq(@answer) end end context "#fft2" do it "computes 2D FFT if NMatrix has such shape" do - input = NMatrix.new([2,2], + input = NMatrix.new([2, 2], [ - Complex(9.3200,0), Complex(43.0000,0), - Complex(3.2000,0), Complex(4.0000,0) - ], dtype: :complex128 - ) - output = NMatrix.new([2,2], + Complex(9.3200, 0), Complex(43.0000, 0), + Complex(3.2000, 0), Complex(4.0000, 0), + ], dtype: :complex128) + output = NMatrix.new([2, 2], [ - Complex(59.520,0), Complex(-34.480,0), - Complex(45.120,0), Complex(-32.880,0), - ], dtype: :complex128 - ) - expect(input.fft2.round(4)).to eq(output) + Complex(59.520, 0), Complex(-34.480, 0), + Complex(45.120, 0), Complex(-32.880, 0), + ], dtype: :complex128) + expect(input.fft2.round(4)).to eq(output) end end end @@ -80,28 +79,28 @@ expect(plan.shape) .to eq([4]) expect(plan.size) .to eq(4) expect(plan.dim) .to eq(1) - expect(plan.flags) .to eq([:estimate]) + expect(plan.flags) .to eq([:estimate]) expect(plan.direction).to eq(:forward) end it "creates a new plan for multi dimensional DFT with options" do - plan = NMatrix::FFTW::Plan.new([10,5,8], + plan = NMatrix::FFTW::Plan.new([10, 5, 8], direction: :backward, flags: [:exhaustive, :estimate], dim: 3) - expect(plan.shape) .to eq([10,5,8]) - expect(plan.size) .to eq(10*5*8) + expect(plan.shape) .to eq([10, 5, 8]) + expect(plan.size) .to eq(10 * 5 * 8) expect(plan.dim) .to eq(3) expect(plan.flags) .to eq([:exhaustive, :estimate]) expect(plan.direction).to eq(:backward) end it "creates a new plan for real input/complex output" do - plan = NMatrix::FFTW::Plan.new([5,20,10,4,2], - direction: :forward, flags: [:patient, :exhaustive], dim: 5, + plan = NMatrix::FFTW::Plan.new([5, 20, 10, 4, 2], + direction: :forward, flags: [:patient, :exhaustive], dim: 5, type: :real_complex) - expect(plan.shape) .to eq([5,20,10,4,2]) - expect(plan.size) .to eq(5*20*10*4*2) + expect(plan.shape) .to eq([5, 20, 10, 4, 2]) + expect(plan.size) .to eq(5 * 20 * 10 * 4 * 2) expect(plan.dim) .to eq(5) expect(plan.flags) .to eq([:patient, :exhaustive]) expect(plan.type) .to eq(:real_complex) @@ -114,22 +113,22 @@ end it "creates a new plan for real input/real output" do - plan = NMatrix::FFTW::Plan.new([30,30], type: :real_real, - real_real_kind: [:rodft00, :redft10], dim: 2) + plan = NMatrix::FFTW::Plan.new([30, 30], type: :real_real, + real_real_kind: [:rodft00, :redft10], dim: 2) - expect(plan.shape).to eq([30,30]) - expect(plan.size) .to eq(30*30) + expect(plan.shape).to eq([30, 30]) + expect(plan.size) .to eq(30 * 30) expect(plan.dim) .to eq(2) expect(plan.flags).to eq([:estimate]) expect(plan.type) .to eq(:real_real) end it "creates a new plan for complex input/real output" do - plan = NMatrix::FFTW::Plan.new([30,400], type: :complex_real, - dim: 2, flags: [:patient, :exhaustive]) + plan = NMatrix::FFTW::Plan.new([30, 400], type: :complex_real, + dim: 2, flags: [:patient, :exhaustive]) - expect(plan.shape).to eq([30,400]) - expect(plan.size) .to eq(30*400) + expect(plan.shape).to eq([30, 400]) + expect(plan.size) .to eq(30 * 400) expect(plan.dim) .to eq(2) expect(plan.flags).to eq([:patient, :exhaustive]) expect(plan.type) .to eq(:complex_real) @@ -139,7 +138,7 @@ context "#set_input" do it "accepts nothing but complex128 input for the default or complex_real plan" do plan = NMatrix::FFTW::Plan.new(4) - input = NMatrix.new([4], [23.54,52.34,52.345,64], dtype: :float64) + input = NMatrix.new([4], [23.54, 52.34, 52.345, 64], dtype: :float64) expect { plan.set_input(input) }.to raise_error(ArgumentError) @@ -152,7 +151,7 @@ it "accepts nothing but float64 input for real_complex or real_real plan" do plan = NMatrix::FFTW::Plan.new(4, type: :real_complex) - input = NMatrix.new([4], [1,2,3,4], dtype: :int32) + input = NMatrix.new([4], [1, 2, 3, 4], dtype: :int32) expect { plan.set_input(input) @@ -164,30 +163,30 @@ it "calculates a basic 1D DFT" do input = NMatrix.new([10], [ - Complex(9.32,0), - Complex(44,0), - Complex(125,0), - Complex(34,0), - Complex(31,0), - Complex(44,0), - Complex(12,0), - Complex(1,0), - Complex(53.23,0), - Complex(-23.23,0), + Complex(9.32, 0), + Complex(44, 0), + Complex(125, 0), + Complex(34, 0), + Complex(31, 0), + Complex(44, 0), + Complex(12, 0), + Complex(1, 0), + Complex(53.23, 0), + Complex(-23.23, 0), ], dtype: :complex128) output = NMatrix.new([10], [ - Complex(330.3200,0.0000), - Complex(-8.4039 ,-150.3269), - Complex(-99.4807 , -68.6579), + Complex(330.3200, 0.0000), + Complex(-8.4039, -150.3269), + Complex(-99.4807, -68.6579), Complex(-143.6861, -20.4273), - Complex(67.6207 , 8.5236), - Complex(130.7800 , 0.0000), - Complex(67.6207 , -8.5236), + Complex(67.6207, 8.5236), + Complex(130.7800, 0.0000), + Complex(67.6207, -8.5236), Complex(-143.6861, 20.4273), - Complex(-99.4807 , 68.6579), - Complex(-8.4039 ,150.3269) + Complex(-99.4807, 68.6579), + Complex(-8.4039, 150.3269), ], dtype: :complex128) plan = NMatrix::FFTW::Plan.new(10) @@ -197,21 +196,19 @@ end it "calculates 2D DFT with options" do - input = NMatrix.new([2,2], + input = NMatrix.new([2, 2], [ - Complex(9.3200,0), Complex(43.0000,0), - Complex(3.2000,0), Complex(4.0000,0) - ], dtype: :complex128 - ) + Complex(9.3200, 0), Complex(43.0000, 0), + Complex(3.2000, 0), Complex(4.0000, 0), + ], dtype: :complex128) - output = NMatrix.new([2,2], + output = NMatrix.new([2, 2], [ - Complex(59.520,0), Complex(-34.480,0), - Complex(45.120,0), Complex(-32.880,0), - ], dtype: :complex128 - ) + Complex(59.520, 0), Complex(-34.480, 0), + Complex(45.120, 0), Complex(-32.880, 0), + ], dtype: :complex128) - plan = NMatrix::FFTW::Plan.new([2,2], + plan = NMatrix::FFTW::Plan.new([2, 2], direction: :forward, flags: :estimate, dim: 2) plan.set_input input expect(plan.execute).to eq(true) @@ -219,12 +216,11 @@ end it "calculates ND DFT with options" do - end it "calculates 1D real input/complex output DFT" do input = NMatrix.new([4], [3.10, 1.73, 1.04, 2.83], dtype: :float64) - output = NMatrix.new([3], + output = NMatrix.new([3], [Complex(8.70, 0), Complex(2.06, 1.1), Complex(-0.42, 0)], dtype: :complex128) plan = NMatrix::FFTW::Plan.new([4], type: :real_complex) plan.set_input input @@ -234,11 +230,11 @@ it "calculates 2D real input/complex output DFT" do input = NMatrix.new([16], [ - 1 , 5,54 ,656, - 4.3,1.32,-43.34,14 , - 1 , 5, 54,656, - 4.3,1.32,-43.34,14 - ], dtype: :float64) + 1, 5, 54, 656, + 4.3, 1.32, -43.34, 14, + 1, 5, 54, 656, + 4.3, 1.32, -43.34, 14, + ], dtype: :float64) output = NMatrix.new([9], [ Complex(1384.56, 0.0), @@ -249,11 +245,10 @@ Complex(0.0, 0.0), Complex(1479.44, 0.0), Complex(-201.28, 1276.64), - Complex(-1103.28, 0.0) - ], dtype: :complex128 - ) + Complex(-1103.28, 0.0), + ], dtype: :complex128) - plan = NMatrix::FFTW::Plan.new([4,4], type: :real_complex, dim: 2) + plan = NMatrix::FFTW::Plan.new([4, 4], type: :real_complex, dim: 2) plan.set_input input expect(plan.execute).to eq(true) expect(plan.output).to eq(output) @@ -262,19 +257,19 @@ it "calculates 1D complex input/real output DFT" do input = NMatrix.new([8], [ - Complex(9.32,0), - Complex(43.0,0), - Complex(3.20,0), - Complex(4.00,0), - Complex(5.32,0), - Complex(3.20,0), - Complex(4.00,0), - Complex(5.32,0) + Complex(9.32, 0), + Complex(43.0, 0), + Complex(3.20, 0), + Complex(4.00, 0), + Complex(5.32, 0), + Complex(3.20, 0), + Complex(4.00, 0), + Complex(5.32, 0), ], dtype: :complex128) output = NMatrix.new([8], [ - 115.04,59.1543,8.24,-51.1543,-72.96,-51.1543,8.24,59.1543 - ], dtype: :float64) + 115.04, 59.1543, 8.24, -51.1543, -72.96, -51.1543, 8.24, 59.1543, + ], dtype: :float64) plan = NMatrix::FFTW::Plan.new([8], type: :complex_real) plan.set_input input @@ -285,21 +280,21 @@ it "calculates 2D complex input/real output DFT" do input = NMatrix.new([9], [ - Complex(9.32,0), - Complex(43.0,0), - Complex(3.20,0), - Complex(4.00,0), - Complex(5.32,0), - Complex(3.20,0), - Complex(4.00,0), - Complex(5.32,0), - Complex(45.32,0) + Complex(9.32, 0), + Complex(43.0, 0), + Complex(3.20, 0), + Complex(4.00, 0), + Complex(5.32, 0), + Complex(3.20, 0), + Complex(4.00, 0), + Complex(5.32, 0), + Complex(45.32, 0), ], dtype: :complex128) output = NMatrix.new([9], [ - 118.24,-32.36,-32.36,83.86,-35.54,-33.14,83.86,-33.14,-35.54 - ], dtype: :float64) + 118.24, -32.36, -32.36, 83.86, -35.54, -33.14, 83.86, -33.14, -35.54, + ], dtype: :float64) - plan = NMatrix::FFTW::Plan.new([3,3], type: :complex_real, dim: 2) + plan = NMatrix::FFTW::Plan.new([3, 3], type: :complex_real, dim: 2) plan.set_input input expect(plan.execute).to eq(true) expect(plan.output.round(2)) .to eq(output) @@ -307,9 +302,9 @@ it "calculates basic 1D real input/real output DFT of kind RODFT00" do input = NMatrix.new([9], - [9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64) + [9.32, 43.00, 3.20, 4.00, 5.32, 3.20, 4.00, 5.32, 45.32], dtype: :float64) output = NMatrix.new([9], - [126.56,28.77,165.67,-24.76,105.52,-110.31,-1.23,-116.45,-14.44], + [126.56, 28.77, 165.67, -24.76, 105.52, -110.31, -1.23, -116.45, -14.44], dtype: :float64) plan = NMatrix::FFTW::Plan.new([9], type: :real_real, real_real_kind: [:rodft00]) plan.set_input input @@ -319,9 +314,9 @@ it "calculates basic 1D real input/real output DFT of kind REDFT10" do input = NMatrix.new([9], - [9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64) + [9.32, 43.00, 3.20, 4.00, 5.32, 3.20, 4.00, 5.32, 45.32], dtype: :float64) output = NMatrix.new([9], - [245.36,-6.12,126.84,-62.35,35.00,-109.42,-38.24,-92.49,-21.20], + [245.36, -6.12, 126.84, -62.35, 35.00, -109.42, -38.24, -92.49, -21.20], dtype: :float64) plan = NMatrix::FFTW::Plan.new([9], type: :real_real, real_real_kind: [:redft10]) @@ -332,13 +327,13 @@ it "calculates 2D DFT for real input/real output of kind REDFT10, REDFT11" do input = NMatrix.new([9], - [9.32,43.00,3.20,4.00,5.32,3.20,4.00,5.32,45.32], dtype: :float64) + [9.32, 43.00, 3.20, 4.00, 5.32, 3.20, 4.00, 5.32, 45.32], dtype: :float64) output = NMatrix.new([9], - [272.181,-249.015,66.045,72.334,23.907,-228.463,85.368,-105.331,30.836], + [272.181, -249.015, 66.045, 72.334, 23.907, -228.463, 85.368, -105.331, 30.836], dtype: :float64) - plan = NMatrix::FFTW::Plan.new([3,3], type: :real_real, - real_real_kind: [:redft10, :redft11], dim: 2) + plan = NMatrix::FFTW::Plan.new([3, 3], type: :real_real, + real_real_kind: [:redft10, :redft11], dim: 2) plan.set_input input expect(plan.execute).to eq(true) expect(plan.output.round(3)) .to eq(output) diff --git a/spec/plugins/lapacke/lapacke_spec.rb b/spec/plugins/lapacke/lapacke_spec.rb index 8e661334..32ebbde6 100644 --- a/spec/plugins/lapacke/lapacke_spec.rb +++ b/spec/plugins/lapacke/lapacke_spec.rb @@ -25,17 +25,17 @@ # Tests for interfaces that are only exposed by nmatrix-lapacke # -require 'spec_helper' +require "spec_helper" require "./lib/nmatrix/lapacke" describe "NMatrix::LAPACK functions implemented with LAPACKE interface" do [:float32, :float64, :complex64, :complex128].each do |dtype| context dtype do it "exposes lapacke_getrf" do - a = NMatrix.new([3,4], GETRF_EXAMPLE_ARRAY, dtype: dtype) + a = NMatrix.new([3, 4], GETRF_EXAMPLE_ARRAY, dtype: dtype) ipiv = NMatrix::LAPACK.lapacke_getrf(:row, 3, 4, a, 4) - b = NMatrix.new([3,4], GETRF_SOLUTION_ARRAY, dtype: dtype) - ipiv_true = [2,3,3] + b = NMatrix.new([3, 4], GETRF_SOLUTION_ARRAY, dtype: dtype) + ipiv_true = [2, 3, 3] # delta varies for different dtypes err = case dtype @@ -43,15 +43,15 @@ 1e-6 when :float64, :complex128 1e-14 - end + end expect(a).to be_within(err).of(b) expect(ipiv).to eq(ipiv_true) end it "exposes lapacke_getri" do - a = NMatrix.new(:dense, 3, [1,0,4,1,1,6,-3,0,-10], dtype) - ipiv = NMatrix::LAPACK::lapacke_getrf(:row, 3, 3, a, 3) # get pivot from getrf, use for getri + a = NMatrix.new(:dense, 3, [1, 0, 4, 1, 1, 6, -3, 0, -10], dtype) + ipiv = NMatrix::LAPACK.lapacke_getrf(:row, 3, 3, a, 3) # get pivot from getrf, use for getri # delta varies for different dtypes err = case dtype @@ -59,21 +59,21 @@ 1e-5 when :float64, :complex128 1e-14 - end + end - NMatrix::LAPACK::lapacke_getri(:row, 3, a, 3, ipiv) + NMatrix::LAPACK.lapacke_getri(:row, 3, a, 3, ipiv) - b = NMatrix.new(:dense, 3, [-5,0,-2,-4,1,-1,1.5,0,0.5], dtype) + b = NMatrix.new(:dense, 3, [-5, 0, -2, -4, 1, -1, 1.5, 0, 0.5], dtype) expect(a).to be_within(err).of(b) end it "exposes lapacke_getrs with vector solutions" do - a = NMatrix.new(3, [-2,4,-3,3,-2,1,0,-4,3], dtype: dtype) - ipiv = NMatrix::LAPACK::lapacke_getrf(:row, 3, 3, a, 3) - b = NMatrix.new([3,1], [-1, 17, -9], dtype: dtype) + a = NMatrix.new(3, [-2, 4, -3, 3, -2, 1, 0, -4, 3], dtype: dtype) + ipiv = NMatrix::LAPACK.lapacke_getrf(:row, 3, 3, a, 3) + b = NMatrix.new([3, 1], [-1, 17, -9], dtype: dtype) - #be careful! the leading dimenension (lda,ldb) is the number of rows for row-major in LAPACKE. Different from CLAPACK convention! - NMatrix::LAPACK::lapacke_getrs(:row, false, 3, 1, a, 3, ipiv, b, 1) + # be careful! the leading dimenension (lda,ldb) is the number of rows for row-major in LAPACKE. Different from CLAPACK convention! + NMatrix::LAPACK.lapacke_getrs(:row, false, 3, 1, a, 3, ipiv, b, 1) # delta varies for different dtypes err = case dtype @@ -81,20 +81,20 @@ 1e-5 when :float64, :complex128 1e-13 - end + end expect(b[0]).to be_within(err).of(5) - expect(b[1]).to be_within(err).of(-15.0/2) + expect(b[1]).to be_within(err).of(-15.0 / 2) expect(b[2]).to be_within(err).of(-13) end it "exposes lapacke_getrs with matrix solutions" do - a = NMatrix.new(3, [-2,4,-3,3,-2,1,0,-4,3], dtype: dtype) - ipiv = NMatrix::LAPACK::lapacke_getrf(:row, 3, 3, a, 3) - b = NMatrix.new([3,2], [-1, 2, 17, 10, -9, 1], dtype: dtype) + a = NMatrix.new(3, [-2, 4, -3, 3, -2, 1, 0, -4, 3], dtype: dtype) + ipiv = NMatrix::LAPACK.lapacke_getrf(:row, 3, 3, a, 3) + b = NMatrix.new([3, 2], [-1, 2, 17, 10, -9, 1], dtype: dtype) - #be careful! the leading dimenension (lda,ldb) is the number of rows for row-major in LAPACKE. Different from CLAPACK convention! - NMatrix::LAPACK::lapacke_getrs(:row, false, 3, 2, a, 3, ipiv, b, 2) + # be careful! the leading dimenension (lda,ldb) is the number of rows for row-major in LAPACKE. Different from CLAPACK convention! + NMatrix::LAPACK.lapacke_getrs(:row, false, 3, 2, a, 3, ipiv, b, 2) # delta varies for different dtypes err = case dtype @@ -102,115 +102,115 @@ 1e-4 when :float64, :complex128 1e-13 - end + end - x = NMatrix.new([3,2], [5, -1.5, -7.5, -21.25, -13, -28], dtype: dtype) + x = NMatrix.new([3, 2], [5, -1.5, -7.5, -21.25, -13, -28], dtype: dtype) expect(b).to be_within(err).of(x) end it "exposes lapacke_potrf" do # first do upper begin - a = NMatrix.new(:dense, 3, [25,15,-5, 0,18,0, 0,0,11], dtype) - NMatrix::LAPACK::lapacke_potrf(:row, :upper, 3, a, 3) - b = NMatrix.new(:dense, 3, [5,3,-1, 0,3,1, 0,0,3], dtype) + a = NMatrix.new(:dense, 3, [25, 15, -5, 0, 18, 0, 0, 0, 11], dtype) + NMatrix::LAPACK.lapacke_potrf(:row, :upper, 3, a, 3) + b = NMatrix.new(:dense, 3, [5, 3, -1, 0, 3, 1, 0, 0, 3], dtype) expect(a).to eq(b) end # then do lower - a = NMatrix.new(:dense, 3, [25,0,0, 15,18,0,-5,0,11], dtype) - NMatrix::LAPACK::lapacke_potrf(:row, :lower, 3, a, 3) - b = NMatrix.new(:dense, 3, [5,0,0, 3,3,0, -1,1,3], dtype) + a = NMatrix.new(:dense, 3, [25, 0, 0, 15, 18, 0, -5, 0, 11], dtype) + NMatrix::LAPACK.lapacke_potrf(:row, :lower, 3, a, 3) + b = NMatrix.new(:dense, 3, [5, 0, 0, 3, 3, 0, -1, 1, 3], dtype) expect(a).to eq(b) end it "exposes lapacke_potri" do - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - NMatrix::LAPACK::lapacke_potrf(:row, :upper, 3, a, 3) - NMatrix::LAPACK::lapacke_potri(:row, :upper, 3, a, 3) - b = NMatrix.new(3, [0.5, -0.5, 1, 0, 1.5, -2, 0, 0, 4], dtype: dtype) + 0, 0, 1,], dtype: dtype) + NMatrix::LAPACK.lapacke_potrf(:row, :upper, 3, a, 3) + NMatrix::LAPACK.lapacke_potri(:row, :upper, 3, a, 3) + b = NMatrix.new(3, [0.5, -0.5, 1, 0, 1.5, -2, 0, 0, 4], dtype: dtype) err = case dtype when :float32, :complex64 1e-6 when :float64, :complex128 1e-14 - end + end expect(a).to be_within(err).of(b) end it "exposes lapacke_potrs with vector solution" do - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - b = NMatrix.new([3,1], [3,0,2], dtype: dtype) + 0, 0, 1,], dtype: dtype) + b = NMatrix.new([3, 1], [3, 0, 2], dtype: dtype) - NMatrix::LAPACK::lapacke_potrf(:row, :upper, 3, a, 3) - #ldb is different from CLAPACK versions - NMatrix::LAPACK::lapacke_potrs(:row, :upper, 3, 1, a, 3, b, 1) + NMatrix::LAPACK.lapacke_potrf(:row, :upper, 3, a, 3) + # ldb is different from CLAPACK versions + NMatrix::LAPACK.lapacke_potrs(:row, :upper, 3, 1, a, 3, b, 1) - x = NMatrix.new([3,1], [3.5, -5.5, 11], dtype: dtype) + x = NMatrix.new([3, 1], [3.5, -5.5, 11], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(b).to be_within(err).of(x) end it "exposes lapacke_potrs with matrix solution" do - a = NMatrix.new(3, [4, 0,-1, + a = NMatrix.new(3, [4, 0, -1, 0, 2, 1, - 0, 0, 1], dtype: dtype) - b = NMatrix.new([3,2], [3,4, - 0,4, - 2,0], dtype: dtype) + 0, 0, 1,], dtype: dtype) + b = NMatrix.new([3, 2], [3, 4, + 0, 4, + 2, 0,], dtype: dtype) - NMatrix::LAPACK::lapacke_potrf(:row, :upper, 3, a, 3) - #ldb is different from CLAPACK versions - NMatrix::LAPACK::lapacke_potrs(:row, :upper, 3, 2, a, 3, b, 2) + NMatrix::LAPACK.lapacke_potrf(:row, :upper, 3, a, 3) + # ldb is different from CLAPACK versions + NMatrix::LAPACK.lapacke_potrs(:row, :upper, 3, 2, a, 3, b, 2) - x = NMatrix.new([3,2], [3.5, 0, - -5.5, 4, - 11, -4], dtype: dtype) + x = NMatrix.new([3, 2], [3.5, 0, + -5.5, 4, + 11, -4,], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(b).to be_within(err).of(x) end it "calculates the singular value decomposition with lapacke_gesvd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) - s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) #s is always real and always returned as float/double, never as complex - u = NMatrix.new([m,m], 0, dtype: dtype) - vt = NMatrix.new([n,n], 0, dtype: dtype) - superb = NMatrix.new([mn_min-1], dtype: a.abs_dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) + s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) # s is always real and always returned as float/double, never as complex + u = NMatrix.new([m, m], 0, dtype: dtype) + vt = NMatrix.new([n, n], 0, dtype: dtype) + superb = NMatrix.new([mn_min - 1], dtype: a.abs_dtype) NMatrix::LAPACK.lapacke_gesvd(:row, :a, :a, m, n, a, n, s, u, m, vt, n, superb) - s_true = NMatrix.new([mn_min], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) @@ -218,27 +218,27 @@ end it "calculates the singular value decomposition with lapacke_gesdd" do - #example from Wikipedia + # example from Wikipedia m = 4 n = 5 - mn_min = [m,n].min - a = NMatrix.new([m,n],[1,0,0,0,2, 0,0,3,0,0, 0,0,0,0,0, 0,4,0,0,0], dtype: dtype) - s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) #s is always real and always returned as float/double, never as complex - u = NMatrix.new([m,m], 0, dtype: dtype) - vt = NMatrix.new([n,n], 0, dtype: dtype) + mn_min = [m, n].min + a = NMatrix.new([m, n], [1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0], dtype: dtype) + s = NMatrix.new([mn_min], 0, dtype: a.abs_dtype) # s is always real and always returned as float/double, never as complex + u = NMatrix.new([m, m], 0, dtype: dtype) + vt = NMatrix.new([n, n], 0, dtype: dtype) NMatrix::LAPACK.lapacke_gesdd(:row, :a, m, n, a, n, s, u, m, vt, n) - s_true = NMatrix.new([mn_min], [4,3,Math.sqrt(5),0], dtype: a.abs_dtype) - u_true = NMatrix.new([m,m], [0,0,1,0, 0,1,0,0, 0,0,0,-1, 1,0,0,0], dtype: dtype) - vt_true = NMatrix.new([n,n], [0,1,0,0,0, 0,0,1,0,0, Math.sqrt(0.2),0,0,0,Math.sqrt(0.8), 0,0,0,1,0, -Math.sqrt(0.8),0,0,0,Math.sqrt(0.2)], dtype: dtype) + s_true = NMatrix.new([mn_min], [4, 3, Math.sqrt(5), 0], dtype: a.abs_dtype) + u_true = NMatrix.new([m, m], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0], dtype: dtype) + vt_true = NMatrix.new([n, n], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, Math.sqrt(0.2), 0, 0, 0, Math.sqrt(0.8), 0, 0, 0, 1, 0, -Math.sqrt(0.8), 0, 0, 0, Math.sqrt(0.2)], dtype: dtype) err = case dtype when :float32, :complex64 1e-5 when :float64, :complex128 1e-14 - end + end expect(s).to be_within(err).of(s_true) expect(u).to be_within(err).of(u_true) @@ -247,44 +247,44 @@ it "calculates eigenvalues and eigenvectors using lapacke_geev" do n = 3 - a = NMatrix.new([n,n], [-1,0,0, 0,1,-2, 0,1,-1], dtype: dtype) + a = NMatrix.new([n, n], [-1, 0, 0, 0, 1, -2, 0, 1, -1], dtype: dtype) w = NMatrix.new([n], dtype: dtype) - if a.complex_dtype? #for real dtypes, imaginary parts of eigenvalues are stored in separate vector - wi = nil + wi = if a.complex_dtype? # for real dtypes, imaginary parts of eigenvalues are stored in separate vector + nil else - wi = NMatrix.new([n], dtype: dtype) + NMatrix.new([n], dtype: dtype) end - vl = NMatrix.new([n,n], dtype: dtype) - vr = NMatrix.new([n,n], dtype: dtype) + vl = NMatrix.new([n, n], dtype: dtype) + vr = NMatrix.new([n, n], dtype: dtype) NMatrix::LAPACK.lapacke_geev(:row, :t, :t, n, a, n, w, wi, vl, n, vr, n) - if !a.complex_dtype? - w = w + wi*Complex(0,1) + unless a.complex_dtype? + w += wi * Complex(0, 1) end - w_true = NMatrix.new([n], [Complex(0,1), -Complex(0,1), -1], dtype: NMatrix.upcast(dtype, :complex64)) + w_true = NMatrix.new([n], [Complex(0, 1), -Complex(0, 1), -1], dtype: NMatrix.upcast(dtype, :complex64)) if a.complex_dtype? - #For complex types the right/left eigenvectors are stored as columns - #of vr/vl. - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),2/Math.sqrt(6),0, - Complex(1,-1)/Math.sqrt(6),Complex(1,1)/Math.sqrt(6),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - Complex(-1,1)/Math.sqrt(6),Complex(-1,-1)/Math.sqrt(6),0, - 2/Math.sqrt(6),2/Math.sqrt(6),0], dtype: dtype) + # For complex types the right/left eigenvectors are stored as columns + # of vr/vl. + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0, + Complex(1, -1) / Math.sqrt(6), Complex(1, 1) / Math.sqrt(6), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + Complex(-1, 1) / Math.sqrt(6), Complex(-1, -1) / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 2 / Math.sqrt(6), 0,], dtype: dtype) else - #For real types, the real part of the first and second eigenvectors is - #stored in the first column, the imaginary part of the first (= the - #negative of the imaginary part of the second) eigenvector is stored - #in the second column, and the third eigenvector (purely real) is the - #third column. - vr_true = NMatrix.new([n,n],[0,0,1, - 2/Math.sqrt(6),0,0, - 1/Math.sqrt(6),-1/Math.sqrt(6),0], dtype: dtype) - vl_true = NMatrix.new([n,n],[0,0,1, - -1/Math.sqrt(6),1/Math.sqrt(6),0, - 2/Math.sqrt(6),0,0], dtype: dtype) + # For real types, the real part of the first and second eigenvectors is + # stored in the first column, the imaginary part of the first (= the + # negative of the imaginary part of the second) eigenvector is stored + # in the second column, and the third eigenvector (purely real) is the + # third column. + vr_true = NMatrix.new([n, n], [0, 0, 1, + 2 / Math.sqrt(6), 0, 0, + 1 / Math.sqrt(6), -1 / Math.sqrt(6), 0,], dtype: dtype) + vl_true = NMatrix.new([n, n], [0, 0, 1, + -1 / Math.sqrt(6), 1 / Math.sqrt(6), 0, + 2 / Math.sqrt(6), 0, 0,], dtype: dtype) end err = case dtype @@ -292,199 +292,197 @@ 1e-6 when :float64, :complex128 1e-15 - end + end expect(w).to be_within(err).of(w_true) expect(vr).to be_within(err).of(vr_true) expect(vl).to be_within(err).of(vl_true) end - + it "exposes lapacke_geqrf" do - a = NMatrix.new(3, [12.0, -51.0, 4.0, - 6.0, 167.0, -68.0, - -4.0, 24.0, -41.0] , dtype: dtype) + a = NMatrix.new(3, [12.0, -51.0, 4.0, + 6.0, 167.0, -68.0, + -4.0, 24.0, -41.0,], dtype: dtype) - b = NMatrix.new([3,1], 0, dtype: dtype) + b = NMatrix.new([3, 1], 0, dtype: dtype) - NMatrix::LAPACK::lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], b) + NMatrix::LAPACK.lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], b) - x = NMatrix.new([3,1], TAU_SOLUTION_ARRAY, dtype: dtype) - - y = NMatrix.new([3,3], GEQRF_SOLUTION_ARRAY, dtype: dtype) + x = NMatrix.new([3, 1], TAU_SOLUTION_ARRAY, dtype: dtype) + + y = NMatrix.new([3, 3], GEQRF_SOLUTION_ARRAY, dtype: dtype) err = case dtype when :float32, :complex64 1e-4 when :float64, :complex128 1e-14 - end - + end + expect(b).to be_within(err).of(x) - expect(a).to be_within(err).of(y) + expect(a).to be_within(err).of(y) end it "calculates QR decomposition in a compressed format using geqrf!" do - a = NMatrix.new(3, [12.0, -51.0, 4.0, - 6.0, 167.0, -68.0, - -4.0, 24.0, -41.0] , dtype: dtype) + a = NMatrix.new(3, [12.0, -51.0, 4.0, + 6.0, 167.0, -68.0, + -4.0, 24.0, -41.0,], dtype: dtype) tau = a.geqrf! - - x = NMatrix.new([3,1], TAU_SOLUTION_ARRAY, dtype: dtype) - - y = NMatrix.new([3,3], GEQRF_SOLUTION_ARRAY, dtype: dtype) + + x = NMatrix.new([3, 1], TAU_SOLUTION_ARRAY, dtype: dtype) + + y = NMatrix.new([3, 3], GEQRF_SOLUTION_ARRAY, dtype: dtype) err = case dtype when :float32, :complex64 1e-4 when :float64, :complex128 1e-14 - end - + end + expect(tau).to be_within(err).of(x) - expect(a).to be_within(err).of(y) + expect(a).to be_within(err).of(y) end it "exposes lapacke_ormqr and lapacke_unmqr" do - a = NMatrix.new([4,2], [34.0, 21.0, - 23.0, 53.0, - 26.0, 346.0, - 23.0, 121.0] , dtype: dtype) + a = NMatrix.new([4, 2], [34.0, 21.0, + 23.0, 53.0, + 26.0, 346.0, + 23.0, 121.0,], dtype: dtype) - tau = NMatrix.new([2,1], dtype: dtype) + tau = NMatrix.new([2, 1], dtype: dtype) result = NMatrix.identity(4, dtype: dtype) - - # get tau from geqrf, use for ormqr - NMatrix::LAPACK::lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], tau) - #Q is stored in result + # get tau from geqrf, use for ormqr + NMatrix::LAPACK.lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], tau) + + # Q is stored in result a.complex_dtype? ? - NMatrix::LAPACK::lapacke_unmqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], - a, a.shape[1], tau, result, result.shape[1]) + NMatrix::LAPACK.lapacke_unmqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], + a, a.shape[1], tau, result, result.shape[1]) : - NMatrix::LAPACK::lapacke_ormqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], - a, a.shape[1], tau, result, result.shape[1]) + NMatrix::LAPACK.lapacke_ormqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], + a, a.shape[1], tau, result, result.shape[1]) - x = NMatrix.new([4,4], Q_SOLUTION_ARRAY_1, dtype: dtype) + x = NMatrix.new([4, 4], Q_SOLUTION_ARRAY_1, dtype: dtype) err = case dtype when :float32, :complex64 1e-4 when :float64, :complex128 1e-14 - end + end - expect(result).to be_within(err).of(x) + expect(result).to be_within(err).of(x) end it "calculates the product of the orthogonal matrix with an arbitrary matrix" do - a = N.new([2,2], [34.0, 21, 23, 53] , dtype: dtype) + a = N.new([2, 2], [34.0, 21, 23, 53], dtype: dtype) + + tau = NMatrix.new([2, 1], dtype: dtype) + + # Result is the multiplicand that gets overriden : result = Q * result + result = NMatrix.new([2, 2], [2, 0, 0, 2], dtype: dtype) - tau = NMatrix.new([2,1], dtype: dtype) - - #Result is the multiplicand that gets overriden : result = Q * result - result = NMatrix.new([2,2], [2,0,0,2], dtype: dtype) - - # get tau from geqrf, use for ormqr - NMatrix::LAPACK::lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], tau) + # get tau from geqrf, use for ormqr + NMatrix::LAPACK.lapacke_geqrf(:row, a.shape[0], a.shape[1], a, a.shape[1], tau) - #Q is stored in result + # Q is stored in result a.complex_dtype? ? - NMatrix::LAPACK::lapacke_unmqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], - a, a.shape[1], tau, result, result.shape[1]) + NMatrix::LAPACK.lapacke_unmqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], + a, a.shape[1], tau, result, result.shape[1]) : - NMatrix::LAPACK::lapacke_ormqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], - a, a.shape[1], tau, result, result.shape[1]) + NMatrix::LAPACK.lapacke_ormqr(:row, :left, false, result.shape[0], result.shape[1], tau.shape[0], + a, a.shape[1], tau, result, result.shape[1]) - x = NMatrix.new([2,2], [-1.6565668262559257 , -1.1206187354084205, - -1.1206187354084205 , 1.6565668262559263], dtype: dtype) + x = NMatrix.new([2, 2], [-1.6565668262559257, -1.1206187354084205, + -1.1206187354084205, 1.6565668262559263,], dtype: dtype) err = case dtype when :float32, :complex64 1e-4 when :float64, :complex128 1e-14 - end + end - expect(result).to be_within(err).of(x) + expect(result).to be_within(err).of(x) end - + it "calculates the orthogonal matrix Q using ormqr/unmqr after geqrf!" do - a = NMatrix.new([4,2], [34.0, 21.0, - 23.0, 53.0, - 26.0, 346.0, - 23.0, 121.0] , dtype: dtype) - - # get tau from geqrf, use for ormqr + a = NMatrix.new([4, 2], [34.0, 21.0, + 23.0, 53.0, + 26.0, 346.0, + 23.0, 121.0,], dtype: dtype) + + # get tau from geqrf, use for ormqr tau = a.geqrf! - #Q is stored in result + # Q is stored in result result = a.complex_dtype? ? a.unmqr(tau) : a.ormqr(tau) - - x = NMatrix.new([4,4], Q_SOLUTION_ARRAY_1, dtype: dtype) + x = NMatrix.new([4, 4], Q_SOLUTION_ARRAY_1, dtype: dtype) err = case dtype when :float32, :complex64 1e-4 when :float64, :complex128 1e-14 - end + end - expect(result).to be_within(err).of(x) + expect(result).to be_within(err).of(x) end end - + it "calculates the transpose of Q using ormqr/unmqr after geqrf!" do - a = NMatrix.new([4,2], [34.0, 21.0, - 23.0, 53.0, - 26.0, 346.0, - 23.0, 121.0] , dtype: dtype) - - # get tau from geqrf, use for ormqr - tau = a.geqrf! + a = NMatrix.new([4, 2], [34.0, 21.0, + 23.0, 53.0, + 26.0, 346.0, + 23.0, 121.0,], dtype: dtype) - #Q is stored in result - result = a.complex_dtype? ? a.unmqr(tau, :left, :complex_conjugate) : a.ormqr(tau, :left, :transpose) - + # get tau from geqrf, use for ormqr + tau = a.geqrf! - x = NMatrix.new([4,4], Q_SOLUTION_ARRAY_1, dtype: dtype) - x = x.transpose + # Q is stored in result + result = a.complex_dtype? ? a.unmqr(tau, :left, :complex_conjugate) : a.ormqr(tau, :left, :transpose) - err = case dtype - when :float32, :complex64 - 1e-4 - when :float64, :complex128 - 1e-14 - end + x = NMatrix.new([4, 4], Q_SOLUTION_ARRAY_1, dtype: dtype) + x = x.transpose - expect(result).to be_within(err).of(x) + err = case dtype + when :float32, :complex64 + 1e-4 + when :float64, :complex128 + 1e-14 + end + + expect(result).to be_within(err).of(x) end it "calculates the multiplication c * Q using ormqr/unmqr after geqrf!" do - a = NMatrix.new(3, [12.0, -51.0, 4.0, - 6.0, 167.0, -68.0, - -4.0, 24.0, -41.0] , dtype: dtype) - - # get tau from geqrf, use for ormqr - tau = a.geqrf! - c = NMatrix.new([2,3], [1,0,1,0,0,1], dtype: dtype) - - #Q is stored in result - result = a.complex_dtype? ? a.unmqr(tau, :right, false, c) : a.ormqr(tau, :right, false, c) - - solution = NMatrix.new([2,3], [-0.5714285714285714, 0.2228571428571429, 1.2742857142857142, - 0.28571428571428575, -0.1714285714285714, 0.9428571428571428] , dtype: dtype) - err = case dtype - when :float32, :complex64 - 1e-4 - when :float64, :complex128 - 1e-14 - end + a = NMatrix.new(3, [12.0, -51.0, 4.0, + 6.0, 167.0, -68.0, + -4.0, 24.0, -41.0,], dtype: dtype) + + # get tau from geqrf, use for ormqr + tau = a.geqrf! + c = NMatrix.new([2, 3], [1, 0, 1, 0, 0, 1], dtype: dtype) + + # Q is stored in result + result = a.complex_dtype? ? a.unmqr(tau, :right, false, c) : a.ormqr(tau, :right, false, c) + + solution = NMatrix.new([2, 3], [-0.5714285714285714, 0.2228571428571429, 1.2742857142857142, + 0.28571428571428575, -0.1714285714285714, 0.9428571428571428,], dtype: dtype) + err = case dtype + when :float32, :complex64 + 1e-4 + when :float64, :complex128 + 1e-14 + end - expect(result).to be_within(err).of(solution) + expect(result).to be_within(err).of(solution) end end end diff --git a/spec/rspec_monkeys.rb b/spec/rspec_monkeys.rb index e2f7a1fc..478b0e3b 100644 --- a/spec/rspec_monkeys.rb +++ b/spec/rspec_monkeys.rb @@ -27,20 +27,19 @@ module RSpec::Matchers::BuiltIn class BeWithin - def of(expected) @expected = expected - @unit = '' - if expected.is_a?(NMatrix) - @tolerance = if @delta.is_a?(NMatrix) - @delta.clone - elsif @delta.is_a?(Array) - NMatrix.new(:dense, expected.shape, @delta, expected.dtype) - else - NMatrix.ones_like(expected) * @delta - end + @unit = "" + @tolerance = if expected.is_a?(NMatrix) + if @delta.is_a?(NMatrix) + @delta.clone + elsif @delta.is_a?(Array) + NMatrix.new(:dense, expected.shape, @delta, expected.dtype) + else + NMatrix.ones_like(expected) * @delta + end else - @tolerance = @delta + @delta end self @@ -48,9 +47,9 @@ def of(expected) def percent_of(expected) @expected = expected - @unit = '%' + @unit = "%" @tolerance = @expected.abs * @delta / 100.0 # <- only change is to reverse abs and @delta self end end -end \ No newline at end of file +end diff --git a/spec/rspec_spec.rb b/spec/rspec_spec.rb index 1ac905c1..f1e70bd5 100644 --- a/spec/rspec_spec.rb +++ b/spec/rspec_spec.rb @@ -24,12 +24,12 @@ # # A spec for testing monkey patches to RSpec for NMatrix. # -require 'spec_helper' +require "spec_helper" describe "RSpec" do it "should permit #be_within to be used on a dense NMatrix" do pending("not yet implemented for NMatrix-JRuby") if jruby? - expect(NMatrix.new([4,1], 1.0, dtype: :complex128, stype: :dense) / 10000.0).to be_within(0.00000001).of(NMatrix.new([4,1], 0.0001, dtype: :float64, stype: :dense)) - expect(NMatrix.new([4,1], 1.0, dtype: :complex128, stype: :dense) / 10000.0).not_to be_within(0.00000001).of(NMatrix.new([4,1], 1.0, dtype: :float64, stype: :dense)) + expect(NMatrix.new([4, 1], 1.0, dtype: :complex128, stype: :dense) / 10000.0).to be_within(0.00000001).of(NMatrix.new([4, 1], 0.0001, dtype: :float64, stype: :dense)) + expect(NMatrix.new([4, 1], 1.0, dtype: :complex128, stype: :dense) / 10000.0).not_to be_within(0.00000001).of(NMatrix.new([4, 1], 1.0, dtype: :float64, stype: :dense)) end end diff --git a/spec/shortcuts_spec.rb b/spec/shortcuts_spec.rb index df75713e..7066eae1 100644 --- a/spec/shortcuts_spec.rb +++ b/spec/shortcuts_spec.rb @@ -25,8 +25,8 @@ # Specs for the shortcuts used in NMatrix and in NVector. # -require 'spec_helper' -require 'pry' +require "spec_helper" +require "pry" describe NMatrix do it "zeros() creates a matrix of zeros" do @@ -59,71 +59,71 @@ m = NMatrix.hilbert(3) hilbert3 = NMatrix.new([3, 3], [1.0, 0.5, 0.3333333333333333,\ - 0.5, 0.3333333333333333, 0.25, 0.3333333333333333, 0.25, 0.2]) + 0.5, 0.3333333333333333, 0.25, 0.3333333333333333, 0.25, 0.2,]) expect(m).to eq hilbert3 0.upto(2) do |i| 0.upto(2) do |j| - expect(m[i, j]).to be_within(0.000001).of(hilbert3[i,j]) + expect(m[i, j]).to be_within(0.000001).of(hilbert3[i, j]) end end end it "inv_hilbert() creates an inverse hilbert matrix" do m = NMatrix.inv_hilbert(6) - inv_hilbert6 = [3360.0, -88200.0, 564480.0, -1411200.0] - expect(m[2,0]).to be_within(0.000001).of(inv_hilbert6[0]) - expect(m[2,1]).to be_within(0.000001).of(inv_hilbert6[1]) - expect(m[2,2]).to be_within(0.000001).of(inv_hilbert6[2]) - expect(m[2,3]).to be_within(0.000001).of(inv_hilbert6[3]) + inv_hilbert6 = [3360.0, -88200.0, 564480.0, -1411200.0] + expect(m[2, 0]).to be_within(0.000001).of(inv_hilbert6[0]) + expect(m[2, 1]).to be_within(0.000001).of(inv_hilbert6[1]) + expect(m[2, 2]).to be_within(0.000001).of(inv_hilbert6[2]) + expect(m[2, 3]).to be_within(0.000001).of(inv_hilbert6[3]) m = NMatrix.inv_hilbert(3) - inv_hilbert3 = NMatrix.new([3, 3], [ 9.0, -36.0, 30.0, -36.0, 192.0, -180.0, 30.0, -180.0, 180.0] ) + inv_hilbert3 = NMatrix.new([3, 3], [9.0, -36.0, 30.0, -36.0, 192.0, -180.0, 30.0, -180.0, 180.0]) 0.upto(2) do |i| 0.upto(2) do |j| - expect(m[i, j]).to be_within(0.000001).of(inv_hilbert3[i,j]) + expect(m[i, j]).to be_within(0.000001).of(inv_hilbert3[i, j]) end end end it "diag() creates a matrix with pre-supplied diagonal" do - arr = [1,2,3,4] + arr = [1, 2, 3, 4] m = NMatrix.diag(arr) expect(m.is_a?(NMatrix)).to be true end it "diagonals() contains the seeded values on the diagonal" do - arr = [1,2,3,4] + arr = [1, 2, 3, 4] m = NMatrix.diagonals(arr) - expect(m[0,0]).to eq(arr[0]) - expect(m[1,1]).to eq(arr[1]) - expect(m[2,2]).to eq(arr[2]) - expect(m[3,3]).to eq(arr[3]) + expect(m[0, 0]).to eq(arr[0]) + expect(m[1, 1]).to eq(arr[1]) + expect(m[2, 2]).to eq(arr[2]) + expect(m[3, 3]).to eq(arr[3]) end ALL_DTYPES.each do |dtype| [:dense, :yale, :list].each do |stype| context "#block_diagonal #{dtype} #{stype}" do it "block_diagonal() creates a block-diagonal NMatrix" do - pending("not yet implemented for NMatrix-JRuby") if jruby? and dtype == :object - a = NMatrix.new([2,2], [1,2, - 3,4]) - b = NMatrix.new([1,1], [123.0]) - c = NMatrix.new([3,3], [1,2,3, - 1,2,3, - 1,2,3]) - d = Array[ [1,1,1], [2,2,2], [3,3,3] ] + pending("not yet implemented for NMatrix-JRuby") if jruby? && (dtype == :object) + a = NMatrix.new([2, 2], [1, 2, + 3, 4,]) + b = NMatrix.new([1, 1], [123.0]) + c = NMatrix.new([3, 3], [1, 2, 3, + 1, 2, 3, + 1, 2, 3,]) + d = Array[[1, 1, 1], [2, 2, 2], [3, 3, 3]] e = 12 m = NMatrix.block_diagonal(a, b, c, d, e, dtype: dtype, stype: stype) - expect(m).to eq(NMatrix.new([10,10], [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 12], dtype: dtype, stype: stype)) + expect(m).to eq(NMatrix.new([10, 10], [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,], dtype: dtype, stype: stype)) end end end @@ -138,22 +138,20 @@ end it "creates a matrix of random numbers with defined seed value" do - m1 = NMatrix.random(2,:seed => 62) - m2 = NMatrix.random(2,:seed => 62) - m3 = NMatrix.random(2,:seed => 65) - + m1 = NMatrix.random(2, seed: 62) + m2 = NMatrix.random(2, seed: 62) + m3 = NMatrix.random(2, seed: 65) expect(m1).to eq(m2) expect(m1).not_to eq(m3) - end it "creates a complex matrix of random numbers" do - m = NMatrix.random(2, :dtype => :complex128) + m = NMatrix.random(2, dtype: :complex128) end it "correctly accepts :scale parameter" do - m = NMatrix.random([2,2], dtype: :byte, scale: 255) + m = NMatrix.random([2, 2], dtype: :byte, scale: 255) m.each do |v| expect(v).to be >= 0 expect(v).to be < 255 @@ -172,21 +170,20 @@ end context "::magic" do - ALL_DTYPES.each do |dtype| context dtype do it "creates a matrix with numbers from 1 to n^n(n squared)" do pending("not yet implemented for NMatrix-JRuby") if jruby? a = NMatrix.magic(3, dtype: dtype) - magic3 = NMatrix.new([3,3], [4, 9, 2, 3, 5, 7, 8, 1, 6], dtype: dtype) + magic3 = NMatrix.new([3, 3], [4, 9, 2, 3, 5, 7, 8, 1, 6], dtype: dtype) expect(a).to eq magic3 b = NMatrix.magic(4, dtype: dtype) - magic4 = NMatrix.new([4,4], [1, 15, 14, 4, 12, 6, 7, 9, 8, 10, 11, 5, 13, 3, 2, 16], dtype: dtype) + magic4 = NMatrix.new([4, 4], [1, 15, 14, 4, 12, 6, 7, 9, 8, 10, 11, 5, 13, 3, 2, 16], dtype: dtype) expect(b).to eq magic4 c = NMatrix.magic(6, dtype: dtype) - magic6 = NMatrix.new([6,6], [31, 9, 2, 22, 27, 20, 3, 32, 7, 21, 23, 25, 35, 1, 6, 26, 19, 24, 4, 36, 29, 13, 18, 11, 30, 5, 34, 12, 14, 16, 8, 28, 33, 17, 10, 15], dtype: dtype) + magic6 = NMatrix.new([6, 6], [31, 9, 2, 22, 27, 20, 3, 32, 7, 21, 23, 25, 35, 1, 6, 26, 19, 24, 4, 36, 29, 13, 18, 11, 30, 5, 34, 12, 14, 16, 8, 28, 33, 17, 10, 15], dtype: dtype) expect(c).to eq magic6 end end @@ -205,10 +202,10 @@ it "creates a row vector when given only one shape parameter" do pending("not yet implemented for NMatrix-JRuby") if jruby? v = NMatrix.linspace(1, 10, 4) - #Expect a row vector only + # Expect a row vector only expect(v.shape.length).to eq(1) - ans = [1.0,4.0,7.0,10.0] + ans = [1.0, 4.0, 7.0, 10.0] expect(v[0]).to be_within(0.000001).of(ans[0]) expect(v[1]).to be_within(0.000001).of(ans[1]) @@ -218,15 +215,15 @@ it "creates a matrix of input shape with each entry linearly spaced in row major order" do pending("not yet implemented for NMatrix-JRuby") if jruby? - v = NMatrix.linspace(1, Math::PI, [2,2]) + v = NMatrix.linspace(1, Math::PI, [2, 2]) expect(v.dtype).to eq(:float64) ans = [1.0, 1.7138642072677612, 2.4277284145355225, 3.1415927410125732] - expect(v[0,0]).to be_within(0.000001).of(ans[0]) - expect(v[0,1]).to be_within(0.000001).of(ans[1]) - expect(v[1,0]).to be_within(0.000001).of(ans[2]) - expect(v[1,1]).to be_within(0.000001).of(ans[3]) + expect(v[0, 0]).to be_within(0.000001).of(ans[0]) + expect(v[0, 1]).to be_within(0.000001).of(ans[1]) + expect(v[1, 0]).to be_within(0.000001).of(ans[2]) + expect(v[1, 1]).to be_within(0.000001).of(ans[3]) end end @@ -237,7 +234,7 @@ expect(v.shape.length).to eq(1) - #Unit test taken from Matlab R2015b output of logspace(1,2,10) + # Unit test taken from Matlab R2015b output of logspace(1,2,10) ans = [10.0000, 12.9155, 16.6810, 21.5443, 27.8256, 35.9381, 46.4159, 59.9484, 77.4264, 100.0000] expect(v[0].round(4)).to be_within(0.000001).of(ans[0]) @@ -256,7 +253,7 @@ pending("not yet implemented for NMatrix-JRuby") if jruby? v = NMatrix.logspace(1, :pi, 7) - #Unit test taken from Matlab R2015b output of logspace(1,pi,10) + # Unit test taken from Matlab R2015b output of logspace(1,pi,10) ans = [10.0000, 8.2450, 6.7980, 5.6050, 4.6213, 3.8103, 3.1416] expect(v[0].round(4)).to be_within(0.000001).of(ans[0]) @@ -270,16 +267,16 @@ it "creates a matrix of input shape with each entry logarithmically spaced in row major order" do pending("not yet implemented for NMatrix-JRuby") if jruby? - v = NMatrix.logspace(1, 2, [3,2]) + v = NMatrix.logspace(1, 2, [3, 2]) ans = [10.0, 15.8489, 25.1189, 39.8107, 63.0957, 100.0] - expect(v[0,0].round(4)).to be_within(0.000001).of(ans[0]) - expect(v[0,1].round(4)).to be_within(0.000001).of(ans[1]) - expect(v[1,0].round(4)).to be_within(0.000001).of(ans[2]) - expect(v[1,1].round(4)).to be_within(0.000001).of(ans[3]) - expect(v[2,0].round(4)).to be_within(0.000001).of(ans[4]) - expect(v[2,1].round(4)).to be_within(0.000001).of(ans[5]) + expect(v[0, 0].round(4)).to be_within(0.000001).of(ans[0]) + expect(v[0, 1].round(4)).to be_within(0.000001).of(ans[1]) + expect(v[1, 0].round(4)).to be_within(0.000001).of(ans[2]) + expect(v[1, 1].round(4)).to be_within(0.000001).of(ans[3]) + expect(v[2, 0].round(4)).to be_within(0.000001).of(ans[4]) + expect(v[2, 1].round(4)).to be_within(0.000001).of(ans[5]) end end @@ -289,7 +286,7 @@ 2.times do |i| 2.times do |j| - expect(m[i,j]).to eq(value) + expect(m[i, j]).to eq(value) value += 1 end end @@ -313,7 +310,7 @@ 2.times do |i| 2.times do |j| - expect(m[i, j]/10).to be_within(Float::EPSILON).of(value.to_f/10) + expect(m[i, j] / 10).to be_within(Float::EPSILON).of(value.to_f / 10) value += 1 end end @@ -357,24 +354,24 @@ end it "diagonals() creates an NMatrix" do - arr = [1,2,3,4] + arr = [1, 2, 3, 4] m = NMatrix.diagonals(arr) expect(m.is_a?(NMatrix)).to be true end it "diagonals() contains the seeded values on the diagonal" do - arr = [1,2,3,4] + arr = [1, 2, 3, 4] m = NMatrix.diagonals(arr) - expect(m[0,0]).to eq(arr[0]) - expect(m[1,1]).to eq(arr[1]) - expect(m[2,2]).to eq(arr[2]) - expect(m[3,3]).to eq(arr[3]) + expect(m[0, 0]).to eq(arr[0]) + expect(m[1, 1]).to eq(arr[1]) + expect(m[2, 2]).to eq(arr[2]) + expect(m[3, 3]).to eq(arr[3]) end context "_like constructors" do before :each do - @nm_1d = NMatrix[5.0,0.0,1.0,2.0,3.0] - @nm_2d = NMatrix[[0.0,1.0],[2.0,3.0]] + @nm_1d = NMatrix[5.0, 0.0, 1.0, 2.0, 3.0] + @nm_2d = NMatrix[[0.0, 1.0], [2.0, 3.0]] end it "should create an nmatrix of ones with dimensions and type the same as its argument" do @@ -388,11 +385,9 @@ expect(NMatrix.zeros_like(@nm_2d)).to eq NMatrix[[0.0, 0.0], [0.0, 0.0]] end end - end describe "NVector" do - it "zeros() creates a vector of zeros" do v = NVector.zeros(4) @@ -419,7 +414,7 @@ it "seq() creates a vector of integers, sequentially" do v = NVector.seq(7) - expect(v).to eq(NMatrix.new([7,1], [0, 1, 2, 3, 4, 5, 6])) + expect(v).to eq(NMatrix.new([7, 1], [0, 1, 2, 3, 4, 5, 6])) end it "seq() only accepts integers as dimension" do @@ -431,40 +426,39 @@ it "indgen() creates a vector of integers as well as seq()" do v = NVector.indgen(7) - expect(v).to eq(NMatrix.new([7,1], [0, 1, 2, 3, 4, 5, 6])) + expect(v).to eq(NMatrix.new([7, 1], [0, 1, 2, 3, 4, 5, 6])) end it "findgen creates a vector of floats, sequentially" do v = NVector.findgen(2) - expect(v).to eq(NMatrix.new([2,1], [0.0, 1.0])) + expect(v).to eq(NMatrix.new([2, 1], [0.0, 1.0])) end it "bindgen() creates a vector of bytes, sequentially" do v = NVector.bindgen(4) - expect(v).to eq(NMatrix.new([4,1], [0, 1, 2, 3], dtype: :byte)) + expect(v).to eq(NMatrix.new([4, 1], [0, 1, 2, 3], dtype: :byte)) end it "cindgen() creates a vector of complexes, sequentially" do pending("not yet implemented for NMatrix-JRuby") if jruby? v = NVector.cindgen(2) - expect(v).to eq(NMatrix.new([2,1], [Complex(0.0, 0.0), Complex(1.0, 0.0)], dtype: :complex64)) + expect(v).to eq(NMatrix.new([2, 1], [Complex(0.0, 0.0), Complex(1.0, 0.0)], dtype: :complex64)) end it "linspace() creates a vector with n values equally spaced between a and b" do pending("not yet implemented for NMatrix-JRuby") if jruby? v = NVector.linspace(0, 2, 5) - expect(v).to eq(NMatrix.new([5,1], [0.0, 0.5, 1.0, 1.5, 2.0])) + expect(v).to eq(NMatrix.new([5, 1], [0.0, 0.5, 1.0, 1.5, 2.0])) end it "logspace() creates a vector with n values logarithmically spaced between decades 10^a and 10^b" do pending("not yet implemented for NMatrix-JRuby") if jruby? v = NVector.logspace(0, 3, 4) - expect(v).to eq(NMatrix.new([4,1], [1.0, 10.0, 100.0, 1000.0])) + expect(v).to eq(NMatrix.new([4, 1], [1.0, 10.0, 100.0, 1000.0])) end end describe "Inline constructor" do - it "creates a NMatrix with the given values" do m = NMatrix.new([2, 2], [1, 4, 6, 7]) n = NMatrix[[1, 4], [6, 7]] diff --git a/spec/slice_set_spec.rb b/spec/slice_set_spec.rb index 234b1b86..b71cc8b5 100644 --- a/spec/slice_set_spec.rb +++ b/spec/slice_set_spec.rb @@ -24,8 +24,8 @@ # # Test of slice set operations. -require 'spec_helper' -require 'pry' +require "spec_helper" +require "pry" describe "Set slice operation" do include RSpec::Longrun::DSL @@ -37,46 +37,45 @@ end example "set and unset a range of entries with single values" do - if stype == :yale step "verify correct arrangement of Yale IJA and A arrays" do @m.extend NMatrix::YaleFunctions unless jruby? if jruby? pending("not yet implemented for NMatrix-JRuby") else - expect(@m.yale_ija).to eq([4,6,8,10,1,2,0,2,0,1]) + expect(@m.yale_ija).to eq([4, 6, 8, 10, 1, 2, 0, 2, 0, 1]) end - expect(@m.yale_a).to eq([0,4,8,0, 1,2,3,5,6,7]) + expect(@m.yale_a).to eq([0, 4, 8, 0, 1, 2, 3, 5, 6, 7]) end end step "set and reset a single entry" do n = @m.clone - old_val = @m[0,0] - @m[0,0] = 100 - expect(@m[0,0]).to eq(100) - @m[0,0] = old_val + old_val = @m[0, 0] + @m[0, 0] = 100 + expect(@m[0, 0]).to eq(100) + @m[0, 0] = old_val expect(@m).to eq(n) end if stype == :yale n = @m.clone step "set a row of entries" do - n[0,0..2] = 0 - expect(n[0,0..2].to_flat_array).to eq([0,0,0]) - expect(n[1,0..2].to_flat_array).to eq([3,4,5]) - expect(n[2,0..2].to_flat_array).to eq([6,7,8]) + n[0, 0..2] = 0 + expect(n[0, 0..2].to_flat_array).to eq([0, 0, 0]) + expect(n[1, 0..2].to_flat_array).to eq([3, 4, 5]) + expect(n[2, 0..2].to_flat_array).to eq([6, 7, 8]) end step "set a second row of entries" do - n[2,0..2] = 0 - expect(n[2,0..2].to_flat_array).to eq([0,0,0]) - expect(n[1,0..2].to_flat_array).to eq([3,4,5]) + n[2, 0..2] = 0 + expect(n[2, 0..2].to_flat_array).to eq([0, 0, 0]) + expect(n[1, 0..2].to_flat_array).to eq([3, 4, 5]) end step "reset both rows of entries" do - n[0,0..2] = [0,1,2] - n[2,0..2] = [6,7,8] + n[0, 0..2] = [0, 1, 2] + n[2, 0..2] = [6, 7, 8] expect(n).to eq(@m) end end @@ -86,65 +85,65 @@ m = @m.clone step "set upper left-hand 2x2 corner to 100" do - m[0..1,0..1] = 100 + m[0..1, 0..1] = 100 if stype == :yale - expect(m.yale_ija).to eq([4, 6, 8, 10, 1, 2, 0, 2, 0, 1]) - expect(m.yale_a).to eq([100, 100, 8, 0, 100, 2, 100, 5, 6, 7]) + expect(m.yale_ija).to eq([4, 6, 8, 10, 1, 2, 0, 2, 0, 1]) + expect(m.yale_a).to eq([100, 100, 8, 0, 100, 2, 100, 5, 6, 7]) end - expect(m[0..1,0..1]).to eq(slice_result_a) - expect(m[2,0..1]).to eq(@m[2,0..1]) - expect(m[0..1,2]).to eq(@m[0..1,2]) + expect(m[0..1, 0..1]).to eq(slice_result_a) + expect(m[2, 0..1]).to eq(@m[2, 0..1]) + expect(m[0..1, 2]).to eq(@m[0..1, 2]) end step "set upper left-hand 2x2 corner to 0" do - m[0..1,0..1] = 0 + m[0..1, 0..1] = 0 if stype == :yale - expect([4,5,6,8,2,2,0,1]).to eq(m.yale_ija) - expect([0,0,8,0,2,5,6,7]).to eq(m.yale_a) + expect([4, 5, 6, 8, 2, 2, 0, 1]).to eq(m.yale_ija) + expect([0, 0, 8, 0, 2, 5, 6, 7]).to eq(m.yale_a) end - expect(m[0..1,0..1]).to eq(slice_result_b) + expect(m[0..1, 0..1]).to eq(slice_result_b) end m = @m.clone step "set lower left-hand 2x2 corner to 100" do - m[1..2,0..1] = 100 - expect(m[1..2,0..1]).to eq(slice_result_a) - expect(m[0,0..1]).to eq(@m[0,0..1]) - expect(m[1..2,2]).to eq(@m[1..2,2]) + m[1..2, 0..1] = 100 + expect(m[1..2, 0..1]).to eq(slice_result_a) + expect(m[0, 0..1]).to eq(@m[0, 0..1]) + expect(m[1..2, 2]).to eq(@m[1..2, 2]) end step "set lower left-hand 2x2 corner to 0" do - m[1..2,0..1] = 0 - expect(m[1..2,0..1]).to eq(slice_result_b) + m[1..2, 0..1] = 0 + expect(m[1..2, 0..1]).to eq(slice_result_b) end m = @m.clone step "set lower right-hand 2x2 corner to 100" do - m[1..2,1..2] = 100 - expect(m[1..2,1..2]).to eq(slice_result_a) - expect(m[0,1..2]).to eq(@m[0,1..2]) - expect(m[1..2,0]).to eq(@m[1..2,0]) + m[1..2, 1..2] = 100 + expect(m[1..2, 1..2]).to eq(slice_result_a) + expect(m[0, 1..2]).to eq(@m[0, 1..2]) + expect(m[1..2, 0]).to eq(@m[1..2, 0]) end step "set lower right-hand 2x2 corner to 0" do - m[1..2,1..2] = 0 - expect(m[1..2,1..2]).to eq(slice_result_b) + m[1..2, 1..2] = 0 + expect(m[1..2, 1..2]).to eq(slice_result_b) end m = @m.clone step "set upper right-hand 2x2 corner to 100" do - m[0..1,1..2] = 100 - expect(m[0..1,1..2]).to eq(slice_result_a) - expect(m[2,1..2]).to eq(@m[2,1..2]) - expect(m[0..1,0]).to eq(@m[0..1,0]) + m[0..1, 1..2] = 100 + expect(m[0..1, 1..2]).to eq(slice_result_a) + expect(m[2, 1..2]).to eq(@m[2, 1..2]) + expect(m[0..1, 0]).to eq(@m[0..1, 0]) end step "set upper right-hand 2x2 corner to 0" do - m[0..1,1..2] = 0 - expect(m[0..1,1..2]).to eq(slice_result_b) + m[0..1, 1..2] = 0 + expect(m[0..1, 1..2]).to eq(slice_result_b) end end @@ -152,11 +151,9 @@ pending("not yet implemented for int dtype for NMatrix-JRuby") if jruby? x = NMatrix.new(4, stype: :yale, dtype: :int16) x.extend NMatrix::YaleFunctions if stype == :yale - x[1..3,1..3] = @m - expect(x.to_flat_array).to eq([0,0,0,0, 0,0,1,2, 0,3,4,5, 0,6,7,8]) + x[1..3, 1..3] = @m + expect(x.to_flat_array).to eq([0, 0, 0, 0, 0, 0, 1, 2, 0, 3, 4, 5, 0, 6, 7, 8]) end - end end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c422aff4..0ebb9227 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -25,101 +25,101 @@ # Common data and helper functions for testing. require "rspec/longrun" -#require "narray/narray" +# require "narray/narray" require "./lib/nmatrix" require "./lib/nmatrix/rspec" -ALL_DTYPES = [:byte,:int8,:int16,:int32,:int64, :float32,:float64, :object, - :complex64, :complex128] - +ALL_DTYPES = [:byte, :int8, :int16, :int32, :int64, :float32, :float64, :object, + :complex64, :complex128,] + NON_INTEGER_DTYPES = [:float32, :float64, :complex64, :complex128, - :object] + :object,] FLOAT_DTYPES = [:float32, :float64] - + MATRIX43A_ARRAY = [14.0, 9.0, 3.0, 2.0, 11.0, 15.0, 0.0, 12.0, 17.0, 5.0, 2.0, 3.0] MATRIX32A_ARRAY = [12.0, 25.0, 9.0, 10.0, 8.0, 5.0] COMPLEX_MATRIX43A_ARRAY = MATRIX43A_ARRAY.zip(MATRIX43A_ARRAY.reverse).collect { |ary| Complex(ary[0], ary[1]) } COMPLEX_MATRIX32A_ARRAY = MATRIX32A_ARRAY.zip(MATRIX32A_ARRAY.reverse).collect { |ary| Complex(ary[0], -ary[1]) } -#3x4 matrix used for testing various getrf and LU decomposition functions -GETRF_EXAMPLE_ARRAY = [-1,0,10,4,9,2,3,5,7,8,1,6] -GETRF_SOLUTION_ARRAY = [9.0, 2.0, 3.0, 5.0, 7.0/9, 58.0/9, -4.0/3, 19.0/9, -1.0/9, 1.0/29, 301.0/29, 130.0/29] +# 3x4 matrix used for testing various getrf and LU decomposition functions +GETRF_EXAMPLE_ARRAY = [-1, 0, 10, 4, 9, 2, 3, 5, 7, 8, 1, 6] +GETRF_SOLUTION_ARRAY = [9.0, 2.0, 3.0, 5.0, 7.0 / 9, 58.0 / 9, -4.0 / 3, 19.0 / 9, -1.0 / 9, 1.0 / 29, 301.0 / 29, 130.0 / 29] -TAU_SOLUTION_ARRAY = [1.8571428571428572,1.9938461538461538, 0.0] +TAU_SOLUTION_ARRAY = [1.8571428571428572, 1.9938461538461538, 0.0] -GEQRF_SOLUTION_ARRAY =[ -14.0, -21.0, 14.000000000000002, - 0.23076923076923078, -175.00000000000003, 70.00000000000001, - -0.15384615384615385, 0.055555555555555546, -35.0] +GEQRF_SOLUTION_ARRAY = [-14.0, -21.0, 14.000000000000002, + 0.23076923076923078, -175.00000000000003, 70.00000000000001, + -0.15384615384615385, 0.055555555555555546, -35.0,] -R_SOLUTION_ARRAY = [-159.2388143638353, -41.00131005172065, -56.75123892439876, -90.75048729628048, - 0.0, 25.137473501580676, 2.073591725046292, 9.790607357775713, - 0.0, 0.0, -20.83259700334131, -17.592414929551445] +R_SOLUTION_ARRAY = [-159.2388143638353, -41.00131005172065, -56.75123892439876, -90.75048729628048, + 0.0, 25.137473501580676, 2.073591725046292, 9.790607357775713, + 0.0, 0.0, -20.83259700334131, -17.592414929551445,] -Q_SOLUTION_ARRAY_1 = [-0.632455532033676, -0.5209522876558295, -0.3984263084135902, -0.41214704991068, - -0.42783756578748666, -0.20837937347171134, 0.876505919951498, 0.07259770177184455, - -0.48364246567281094, 0.8265854747306287,-0.015758658987033422, -0.2873988222474053, - -0.42783756578748666, 0.044081783789183565, -0.26971376257215296, 0.8615487797670971] +Q_SOLUTION_ARRAY_1 = [-0.632455532033676, -0.5209522876558295, -0.3984263084135902, -0.41214704991068, + -0.42783756578748666, -0.20837937347171134, 0.876505919951498, 0.07259770177184455, + -0.48364246567281094, 0.8265854747306287, -0.015758658987033422, -0.2873988222474053, + -0.42783756578748666, 0.044081783789183565, -0.26971376257215296, 0.8615487797670971,] -Q_SOLUTION_ARRAY_2 = [-0.8571428571428572, 0.3942857142857143, 0.33142857142857146, - -0.4285714285714286, -0.9028571428571428, -0.03428571428571425, - 0.28571428571428575, -0.1714285714285714, 0.9428571428571428] +Q_SOLUTION_ARRAY_2 = [-0.8571428571428572, 0.3942857142857143, 0.33142857142857146, + -0.4285714285714286, -0.9028571428571428, -0.03428571428571425, + 0.28571428571428575, -0.1714285714285714, 0.9428571428571428,] -Q_SOLUTION_ARRAY_3 = [-0.7724247413634004, -0.026670393594597247, -0.6345460653374136, +Q_SOLUTION_ARRAY_3 = [-0.7724247413634004, -0.026670393594597247, -0.6345460653374136, -0.5777485870360393, -0.38541856437557026, 0.7194853024298236, - -0.26375478973384403, 0.9223563413020934, 0.28229805268947933] + -0.26375478973384403, 0.9223563413020934, 0.28229805268947933,] def create_matrix(stype) #:nodoc: - m = NMatrix.new([3,3], 0, dtype: :int32, stype: stype, default: 0) - - m[0,0] = 0 - m[0,1] = 1 - m[0,2] = 2 - m[1,0] = 3 - m[1,1] = 4 - m[1,2] = 5 - m[2,0] = 6 - m[2,1] = 7 - m[2,2] = 8 + m = NMatrix.new([3, 3], 0, dtype: :int32, stype: stype, default: 0) + + m[0, 0] = 0 + m[0, 1] = 1 + m[0, 2] = 2 + m[1, 0] = 3 + m[1, 1] = 4 + m[1, 2] = 5 + m[2, 0] = 6 + m[2, 1] = 7 + m[2, 2] = 8 m end def create_rectangular_matrix(stype) #:nodoc: - m = NMatrix.new([5,6], 0, dtype: :int32, stype: stype, default: 0) - - m[0,0] = 1 - m[0,1] = 2 - m[0,2] = 3 - m[0,3] = 4 - m[0,4] = 5 - m[0,5] = 0 - - m[1,0] = 6 - m[1,1] = 7 - m[1,2] = 8 - m[1,3] = 9 - m[1,4] = 0 - m[1,5] = 10 - - m[2,0] = 11 - m[2,1] = 12 - m[2,2] = 13 - m[2,3] = 0 - m[2,4] = 14 - m[2,5] = 15 + m = NMatrix.new([5, 6], 0, dtype: :int32, stype: stype, default: 0) + + m[0, 0] = 1 + m[0, 1] = 2 + m[0, 2] = 3 + m[0, 3] = 4 + m[0, 4] = 5 + m[0, 5] = 0 + + m[1, 0] = 6 + m[1, 1] = 7 + m[1, 2] = 8 + m[1, 3] = 9 + m[1, 4] = 0 + m[1, 5] = 10 + + m[2, 0] = 11 + m[2, 1] = 12 + m[2, 2] = 13 + m[2, 3] = 0 + m[2, 4] = 14 + m[2, 5] = 15 # skip row 3 -- all 0 - m[3,0] = m[3,1] = m[3,2] = m[3,3] = m[3,4] = m[3,5] = 0 + m[3, 0] = m[3, 1] = m[3, 2] = m[3, 3] = m[3, 4] = m[3, 5] = 0 - m[4,0] = 16 - m[4,1] = 0 - m[4,2] = 17 - m[4,3] = 18 - m[4,4] = 19 - m[4,5] = 20 + m[4, 0] = 16 + m[4, 1] = 0 + m[4, 2] = 17 + m[4, 3] = 18 + m[4, 4] = 19 + m[4, 5] = 20 m end @@ -148,8 +148,8 @@ def nm_eql(n, m) #:nodoc: else # NMatrix n.shape[0].times do |i| n.shape[1].times do |j| - if n[i,j] != m[i,j] - puts "n[#{i},#{j}] != m[#{i},#{j}] (#{n[i,j]} != #{m[i,j]})" + if n[i, j] != m[i, j] + puts "n[#{i},#{j}] != m[#{i},#{j}] (#{n[i, j]} != #{m[i, j]})" return false end end @@ -159,14 +159,13 @@ def nm_eql(n, m) #:nodoc: end def integer_dtype? dtype - [:byte,:int8,:int16,:int32,:int64].include?(dtype) + [:byte, :int8, :int16, :int32, :int64].include?(dtype) end # If a focus: true option is supplied to any test, running `rake spec focus=true` # will run only the focused tests and nothing else. if ENV["focus"] == "true" RSpec.configure do |c| - c.filter_run :focus => true + c.filter_run focus: true end end - diff --git a/spec/stat_spec.rb b/spec/stat_spec.rb index 72b5c53a..5fb6f919 100644 --- a/spec/stat_spec.rb +++ b/spec/stat_spec.rb @@ -25,28 +25,28 @@ # Tests for statistical functions in NMatrix. # -require 'spec_helper' -require 'pry' +require "spec_helper" +require "pry" describe "Statistical functions" do context "mapping and reduction related functions" do [:dense, :yale, :list].each do |stype| context "on #{stype} matrices" do - let(:nm_1d) { NMatrix.new([5], [5.0,0.0,1.0,2.0,3.0], stype: stype) unless stype == :yale } - let(:nm_2d) { NMatrix.new([2,2], [0.0, 1.0, 2.0, 3.0], stype: stype) } + let(:nm_1d) { NMatrix.new([5], [5.0, 0.0, 1.0, 2.0, 3.0], stype: stype) unless stype == :yale } + let(:nm_2d) { NMatrix.new([2, 2], [0.0, 1.0, 2.0, 3.0], stype: stype) } it "behaves like Enumerable#reduce with no argument to reduce" do expect(nm_1d.reduce_along_dim(0) { |acc, el| acc + el }.to_f).to eq 11 unless stype == :yale - expect(nm_2d.reduce_along_dim(1) { |acc, el| acc + el }).to eq NMatrix.new([2,1], [1.0, 5.0], stype: stype) + expect(nm_2d.reduce_along_dim(1) { |acc, el| acc + el }).to eq NMatrix.new([2, 1], [1.0, 5.0], stype: stype) end it "should calculate the mean along the specified dimension" do pending("not yet implemented for NMatrix-JRuby") if jruby? - unless stype == :yale then + unless stype == :yale puts nm_1d.mean expect(nm_1d.mean).to eq NMatrix.new([1], [2.2], stype: stype, dtype: :float64) end - expect(nm_2d.mean).to eq NMatrix[[1.0,2.0], stype: stype] + expect(nm_2d.mean).to eq NMatrix[[1.0, 2.0], stype: stype] expect(nm_2d.mean(1)).to eq NMatrix[[0.5], [2.5], stype: stype] end @@ -87,8 +87,8 @@ end it "should convert to float if it contains only a single element" do - expect(NMatrix[4.0, stype: stype].to_f).to eq 4.0 unless stype == :yale - expect(NMatrix[[[[4.0]]], stype: stype].to_f).to eq 4.0 unless stype == :yale + expect(NMatrix[4.0, stype: stype].to_f).to eq 4.0 unless stype == :yale + expect(NMatrix[[[[4.0]]], stype: stype].to_f).to eq 4.0 unless stype == :yale expect(NMatrix[[4.0], stype: stype].to_f).to eq 4.0 end @@ -98,13 +98,13 @@ end it "should map a block to all elements" do - expect(nm_1d.map { |e| e ** 2 }).to eq NMatrix[25.0,0.0,1.0,4.0,9.0, stype: stype] unless stype == :yale - expect(nm_2d.map { |e| e ** 2 }).to eq NMatrix[[0.0,1.0],[4.0,9.0], stype: stype] + expect(nm_1d.map { |e| e**2 }).to eq NMatrix[25.0, 0.0, 1.0, 4.0, 9.0, stype: stype] unless stype == :yale + expect(nm_2d.map { |e| e**2 }).to eq NMatrix[[0.0, 1.0], [4.0, 9.0], stype: stype] end it "should map! a block to all elements in place" do - fct = Proc.new { |e| e ** 2 } - unless stype == :yale then + fct = proc { |e| e**2 } + unless stype == :yale expected1 = nm_1d.map(&fct) nm_1d.map!(&fct) expect(nm_1d).to eq expected1 @@ -135,36 +135,36 @@ it "should iterate correctly for reduce without a block" do pending("not yet implemented for NMatrix-JRuby") if jruby? - unless stype == :yale then + unless stype == :yale en = nm_1d.reduce_along_dim(0, 1.0) - expect(en.each { |a, e| a+e }.to_f).to eq 12 + expect(en.each { |a, e| a + e }.to_f).to eq 12 end en = nm_2d.reduce_along_dim(1, 1.0) - expect(en.each { |a, e| a+e }).to eq NMatrix[[2.0],[6.0], stype: stype] + expect(en.each { |a, e| a + e }).to eq NMatrix[[2.0], [6.0], stype: stype] end it "should iterate correctly for each_along_dim without a block" do - unless stype == :yale then + unless stype == :yale res = NMatrix.zeros_like(nm_1d[0...1]) en = nm_1d.each_along_dim(0) en.each { |e| res += e } expect(res.to_f).to eq 11 end - res = NMatrix.zeros_like (nm_2d[0...2, 0]) + res = NMatrix.zeros_like nm_2d[0...2, 0] en = nm_2d.each_along_dim(1) en.each { |e| res += e } expect(res).to eq NMatrix[[1.0], [5.0], stype: stype] end it "should yield matrices of matching dtype for each_along_dim" do - m = NMatrix.new([2,3], [1,2,3,3,4,5], dtype: :complex128, stype: stype) + m = NMatrix.new([2, 3], [1, 2, 3, 3, 4, 5], dtype: :complex128, stype: stype) m.each_along_dim(1) do |sub_m| expect(sub_m.dtype).to eq :complex128 end end it "should reduce to a matrix of matching dtype for reduce_along_dim" do - m = NMatrix.new([2,3], [1,2,3,3,4,5], dtype: :complex128, stype: stype) + m = NMatrix.new([2, 3], [1, 2, 3, 3, 4, 5], dtype: :complex128, stype: stype) m.reduce_along_dim(1) do |acc, sub_m| expect(sub_m.dtype).to eq :complex128 acc @@ -178,13 +178,13 @@ it "should allow overriding the dtype for reduce_along_dim" do pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix[[1,2,3], [3,4,5], dtype: :complex128] + m = NMatrix[[1, 2, 3], [3, 4, 5], dtype: :complex128] m.reduce_along_dim(1, 0.0, :float64) do |acc, sub_m| expect(acc.dtype).to eq :float64 acc end - m = NMatrix[[1,2,3], [3,4,5], dtype: :complex128, stype: stype] + m = NMatrix[[1, 2, 3], [3, 4, 5], dtype: :complex128, stype: stype] m.reduce_along_dim(1, nil, :float64) do |acc, sub_m| expect(acc.dtype).to eq :float64 acc @@ -193,19 +193,19 @@ it "should convert integer dtypes to float when calculating mean" do pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix[[1,2,3], [3,4,5], dtype: :int32, stype: stype] + m = NMatrix[[1, 2, 3], [3, 4, 5], dtype: :int32, stype: stype] expect(m.mean(0).dtype).to eq :float64 end it "should convert integer dtypes to float when calculating variance" do pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix[[1,2,3], [3,4,5], dtype: :int32, stype: stype] + m = NMatrix[[1, 2, 3], [3, 4, 5], dtype: :int32, stype: stype] expect(m.variance(0).dtype).to eq :float64 end it "should convert integer dtypes to float when calculating standard deviation" do pending("not yet implemented for NMatrix-JRuby") if jruby? - m = NMatrix[[1,2,3], [3,4,5], dtype: :int32, stype: stype] + m = NMatrix[[1, 2, 3], [3, 4, 5], dtype: :int32, stype: stype] expect(m.std(0).dtype).to eq :float64 end end