Skip to content

Commit

Permalink
Issue with v2v bin operation and indexes (SciRuby#501)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Naude committed Aug 17, 2022
1 parent 77b1a7d commit 82ca1c1
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 36 deletions.
13 changes: 13 additions & 0 deletions lib/daru/helpers/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,18 @@ def array_of?(array, match)
!array.empty? &&
array.all? { |el| match === el } # rubocop:disable Style/CaseEquality,Performance/RedundantEqualityComparisonBlock
end

def sort_composite_data(array)
array.sort
rescue ArgumentError, TypeError => e
case e.to_s
when /comparison of Symbol with String failed/,
/comparison of Symbol with \d+ failed/,
/comparison of String with :.* failed/,
/comparison of Integer with :.* failed/,
/no implicit conversion from nil to integer/
array.sort_by(&:to_s)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/daru/maths/arithmetic/vector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def v2o_binary(operation, other)

def v2v_binary(operation, other, opts = {})
# FIXME: why the sorting?.. - zverok, 2016-05-18
index = (@index.to_a | other.index.to_a).sort
index = ArrayHelper.sort_composite_data(@index.to_a | other.index.to_a)

elements = index.map do |idx|
this = self.index.include?(idx) ? self[idx] : nil
Expand Down
88 changes: 53 additions & 35 deletions spec/maths/arithmetic/vector_spec.rb
Original file line number Diff line number Diff line change
@@ -1,48 +1,68 @@
describe Daru::Vector do
before :each do
@dv1 = Daru::Vector.new [1,2,3,4], name: :boozy, index: [:bud, :kf, :henie, :corona]
@dv2 = Daru::Vector.new [1,2,3,4], name: :mayer, index: [:obi, :wan, :kf, :corona]
@with_md1 = Daru::Vector.new [1,2,3,nil,5,nil], name: :missing, index: [:a, :b, :c, :obi, :wan, :corona]
@with_md2 = Daru::Vector.new [1,2,3,nil,5,nil], name: :missing, index: [:obi, :wan, :corona, :a, :b, :c]
let(:dv1) { described_class.new([1, 2, 3, 4], name: :boozy, index: [:bud, :kf, :henie, :corona]) }
let(:dv2) { described_class.new([1, 2, 3, 4], name: :mayer, index: [:obi, :wan, :kf, :corona]) }
let(:with_md1) do
described_class.new([1, 2, 3, nil, 5, nil], name: :missing, index: [:a, :b, :c, :obi, :wan, :corona])
end
let(:with_md2) do
described_class.new([1, 2, 3, nil, 5, nil], name: :missing, index: [:obi, :wan, :corona, :a, :b, :c])
end

context "#+" do
describe "#+" do
it "adds matching indexes of the other vector" do
expect(@dv1 + @dv2).to eq(Daru::Vector.new([nil,8,nil,5,nil,nil], name: :boozy, index: [:bud,:corona,:henie,:kf,:obi,:wan]))
expect(dv1 + dv2).to eq(
Daru::Vector.new([nil, 8, nil, 5, nil, nil], name: :boozy, index: [:bud, :corona, :henie, :kf, :obi, :wan])
)
end

it "adds number to each element of the entire vector" do
expect(@dv1 + 5).to eq(Daru::Vector.new [6,7,8,9], name: :boozy, index: [:bud, :kf, :henie, :corona])
expect(dv1 + 5).to eq(Daru::Vector.new([6, 7, 8, 9], name: :boozy, index: [:bud, :kf, :henie, :corona]))
end

it "does not add when a number is being added" do
expect(@with_md1 + 1).to eq(Daru::Vector.new([2,3,4,nil,6,nil], name: :missing, index: [:a, :b, :c, :obi, :wan, :corona]))
expect(with_md1 + 1).to eq(
Daru::Vector.new([2, 3, 4, nil, 6, nil], name: :missing, index: [:a, :b, :c, :obi, :wan, :corona])
)
end

it "puts a nil when one of the operands is nil" do
expect(@with_md1 + @with_md2).to eq(Daru::Vector.new([nil,7,nil,nil,nil,7], name: :missing, index: [:a, :b, :c, :corona, :obi, :wan]))
expect(with_md1 + with_md2).to eq(
Daru::Vector.new([nil, 7, nil, nil, nil, 7], name: :missing, index: [:a, :b, :c, :corona, :obi, :wan])
)
end

context 'when vectors have numeric and non-numeric indexes' do
let(:dv1) { described_class.new([1, 2, 3]) }
let(:dv2) { described_class.new([1, 2, 3], index: [:a, :b, :c]) }

it "appropriately adds vectors with numeric and non-numeric indexes" do
expect(dv1 + dv2).to eq(Daru::Vector.new(Array.new(6), index: [0, 1, 2, :a, :b, :c]))
end
end

it "appropriately adds vectors with numeric and non-numeric indexes" do
pending "Need an alternate index implementation?"
v1 = Daru::Vector.new([1,2,3])
v2 = Daru::Vector.new([1,2,3], index: [:a,:b,:c])
context 'when index contains symbols and strings' do
let(:dv1) { described_class.new([1, 2, 3, 4], name: :boozy, index: [:bud, 'kf', :henie, :corona]) }
let(:dv2) { described_class.new([1, 2, 3, 4], name: :mayer, index: [:obi, :wan, 'kf', :corona]) }

expect(v1 + v2).to eq(Daru::Vector.new([nil]*6, index: [0,1,2,:a,:b,:c]))
it "adds matching indexes of the other vector" do
expect(dv1 + dv2).to eq(
Daru::Vector.new([nil,8,nil,5,nil,nil], name: :boozy, index: [:bud, :corona, :henie, 'kf', :obi, :wan])
)
end
end
end

context "#-" do
describe "#-" do
it "subtracts matching indexes of the other vector" do
expect(@dv1 - @dv2).to eq(Daru::Vector.new([nil,0,nil,-1,nil,nil], name: :boozy, index: [:bud,:corona,:henie,:kf,:obi,:wan]))
expect(dv1 - dv2).to eq(Daru::Vector.new([nil,0,nil,-1,nil,nil], name: :boozy, index: [:bud,:corona,:henie,:kf,:obi,:wan]))
end

it "subtracts number from each element of the entire vector" do
expect(@dv1 - 5).to eq(Daru::Vector.new [-4,-3,-2,-1], name: :boozy, index: [:bud, :kf, :henie, :corona])
expect(dv1 - 5).to eq(Daru::Vector.new [-4,-3,-2,-1], name: :boozy, index: [:bud, :kf, :henie, :corona])
end
end

context "#*" do
describe "#*" do
it "multiplies matching indexes of the other vector" do

end
Expand All @@ -52,7 +72,7 @@
end
end

context "#\/" do
describe "#\/" do
it "divides matching indexes of the other vector" do

end
Expand All @@ -62,55 +82,53 @@
end
end

context "#%" do
describe "#%" do

end

context "#**" do
describe "#**" do

end

context "#exp" do
describe "#exp" do
it "calculates exp of all numbers" do
expect(@with_md1.exp.round(3)).to eq(Daru::Vector.new([2.718281828459045,
expect(with_md1.exp.round(3)).to eq(Daru::Vector.new([2.718281828459045,
7.38905609893065, 20.085536923187668, nil, 148.4131591025766, nil], index:
[:a, :b, :c, :obi, :wan, :corona], name: :missing).round(3))
end
end

context "#add" do

describe "#add" do
it "adds two vectors with nils as 0 if skipnil is true" do
expect(@with_md1.add(@with_md2, skipnil: true)).to eq(Daru::Vector.new(
expect(with_md1.add(with_md2, skipnil: true)).to eq(Daru::Vector.new(
[1, 7, 3, 3, 1, 7],
name: :missing,
index: [:a, :b, :c, :corona, :obi, :wan]))
end

it "adds two vectors same as :+ if skipnil is false" do
expect(@with_md1.add(@with_md2, skipnil: false)).to eq(Daru::Vector.new(
expect(with_md1.add(with_md2, skipnil: false)).to eq(Daru::Vector.new(
[nil, 7, nil, nil, nil, 7],
name: :missing,
index: [:a, :b, :c, :corona, :obi, :wan]))
end

end

context "#abs" do
describe "#abs" do
it "calculates abs value" do
@with_md1.abs
with_md1.abs
end
end

context "#sqrt" do
describe "#sqrt" do
it "calculates sqrt" do
@with_md1.sqrt
with_md1.sqrt
end
end

context "#round" do
describe "#round" do
it "rounds to given precision" do
@with_md1.round(2)
with_md1.round(2)
end
end
end

0 comments on commit 82ca1c1

Please sign in to comment.