Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #53 from kitcheck/multiplicandity
Browse files Browse the repository at this point in the history
Support multiplication and division by scalars
  • Loading branch information
Alex Johnson committed Feb 24, 2016
2 parents f4d4329 + 969d5e1 commit 4ed6227
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 3 deletions.
10 changes: 10 additions & 0 deletions lib/unit/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ def -(other)
end
end

def *(other)
if other.is_a?(Numeric)
self.scale(other)
else
raise IncompatibleUnitsError.new("These units are incompatible (#{self.to_s} and #{other.to_s})")
end
end

def /(other)
if other.is_a? self.class
if @uom == other.uom
Expand All @@ -51,6 +59,8 @@ def /(other)
u1, u2 = self.class.equivalise(self, other)
u1.scalar / u2.scalar
end
elsif other.is_a?(Numeric)
self.scale(1.0/other)
else
raise "Implement in subclasses"
end
Expand Down
20 changes: 18 additions & 2 deletions lib/unit/concentration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,26 @@ def -(other)
use_operator_on_other(:-, other)
end

def *(other)
if other.is_a?(Numeric)
Concentration.new(
numerator * other,
denominator
)
else
raise IncompatibleUnitsError.new("These units are incompatible (#{self.to_s} and #{other.to_s})")
end
end

def /(other)
if other.concentration?
if other.respond_to?(:concentration?) && other.concentration?
con1, con2 = Concentration.equivalise(self, other)
con1.scalar / con2.scalar
elsif other.is_a? Numeric
Concentration.new(
numerator / other,
denominator
)
else
raise IncompatibleUnitsError
end
Expand All @@ -40,7 +56,7 @@ def convert_to(uom)
tokens = Lexer.new.tokenize("1 #{uom}")
destination_conc = Parser.new.parse(tokens)
Concentration.new(
numerator.convert_to(destination_conc.numerator.uom).scale(destination_conc.scalar),
numerator.convert_to(destination_conc.numerator.uom).scale(destination_conc.scalar),
denominator.convert_to(destination_conc.denominator.uom)
)
end
Expand Down
4 changes: 3 additions & 1 deletion lib/unit/mass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ class Mass < Base
def /(other)
if other.is_a? Mass
super(other)
elsif other.is_a? Numeric
super(other)
elsif other.is_a? Volume
Concentration.new(self, other)
else
raise IncompatibleUnitsError.new("These units are incompatible (#{self.uom} and #{other.uom})")
raise IncompatibleUnitsError.new("These units are incompatible (#{self.to_s} and #{other.to_s})")
end
end

Expand Down
54 changes: 54 additions & 0 deletions test/concentration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,60 @@ class ConcentrationTest < Minitest::Test
end
end

context "multiplying" do
setup do
num1 = Unit::Mass.new(2, 'mg')
denom = Unit::Volume.new(1, 'ml')
@con = Unit::Concentration.new(num1, denom)
end

context "multiplying by a mass" do
should "raise a IncompatibleUnitsError" do
assert_raises Unit::IncompatibleUnitsError do
u1 = Unit::Mass.new(2, 'mg')
@con*u1
end
end
end

context "multiplying by an integer" do
should "create a scaled concentration" do
concentration = @con * 2

assert_equal true, concentration.is_a?(Unit::Concentration)
assert_equal 4, concentration.scalar
assert_equal "mg/ml", concentration.uom
end
end
end

context "dividing" do
setup do
num1 = Unit::Mass.new(2, 'mg')
denom = Unit::Volume.new(1, 'ml')
@con = Unit::Concentration.new(num1, denom)
end

context "dividing by a mass" do
should "raise a IncompatibleUnitsError" do
assert_raises Unit::IncompatibleUnitsError do
u1 = Unit::Mass.new(2, 'mg')
@con/u1
end
end
end

context "dividing by an integer" do
should "create a scaled concentration" do
concentration = @con / 2

assert_equal true, concentration.is_a?(Unit::Concentration)
assert_equal 1, concentration.scalar
assert_equal "mg/ml", concentration.uom
end
end
end

context "#mass_from_volume" do
setup do
num1 = Unit::Mass.new(2, 'mg')
Expand Down
55 changes: 55 additions & 0 deletions test/mass_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,61 @@ class MassTest < Minitest::Test
assert_equal "mg/ml", conc.uom
end
end

context "dividing by an integer" do
should "create a scaled mass" do
u1 = Unit::Mass.new(4, 'mg')
mass = u1/2

assert_equal true, mass.is_a?(Unit::Mass)
assert_equal 2, mass.scalar
assert_equal "mg", mass.uom
end
end

context "dividing by a float" do
should "create a scaled mass" do
u1 = Unit::Mass.new(4, 'mg')
mass = u1/1.25

assert_equal true, mass.is_a?(Unit::Mass)
assert_equal 3.2, mass.scalar
assert_equal "mg", mass.uom
end
end

context "dividing by a unit" do
should "raise a IncompatibleUnitsError" do
assert_raises Unit::IncompatibleUnitsError do
u1 = Unit::Mass.new(4, 'mg')
u2 = Unit::Mass.new(4, 'unit')
u1/2
end
end
end
end

context "multiplying" do
context "multiplying by a mass" do
should "raise a IncompatibleUnitsError" do
assert_raises Unit::IncompatibleUnitsError do
u1 = Unit::Mass.new(4, 'mg')
u2 = Unit::Mass.new(4, 'mg')
u1*u2
end
end
end

context "multiplying by an integer" do
should "create a scaled mass" do
u1 = Unit::Mass.new(4, 'mg')
mass = u1 * 2

assert_equal true, mass.is_a?(Unit::Mass)
assert_equal 8, mass.scalar
assert_equal "mg", mass.uom
end
end
end

context "comparison" do
Expand Down
35 changes: 35 additions & 0 deletions test/unit_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,41 @@ class UnitTest < Minitest::Test
end
end
end

should "raise if trying to multiply two units" do
assert_raises Unit::IncompatibleUnitsError do
@u1 * @u2
end
end

should "raise if trying to divide two units" do
assert_raises Unit::IncompatibleUnitsError do
@u1 / @u2
end
end
end

context "multiplying" do
context "multiplying by a unit" do
should "raise a IncompatibleUnitsError" do
assert_raises Unit::IncompatibleUnitsError do
u1 = Unit::Unit.new(4, 'unit')
u2 = Unit::Unit.new(4, 'unit')
u1*u2
end
end
end

context "multiplying by an integer" do
should "create a scaled unit" do
u1 = Unit::Unit.new(4, 'unit')
unit = u1 * 2

assert_equal true, unit.is_a?(Unit::Unit)
assert_equal 8, unit.scalar
assert_equal "unit", unit.uom
end
end
end

context "division" do
Expand Down

0 comments on commit 4ed6227

Please sign in to comment.