Class: UOM::CompositeUnitKeyCanonicalizer

Inherits:
Object
  • Object
show all
Defined in:
lib/uom/composite_unit_key_canonicalizer.rb

Overview

A CompositeUnitKeyCanonicalizer creates a standard key for the CompositeUnit extent.

Instance Method Summary collapse

Instance Method Details

#canonicalize(u1, u2, operator, &locator) ⇒ Object

Returns the canonical form of the given units u1 and u2 and operator :* or :/ as an array consisting of a CompositeUnit, non-composite Unit and operator, e.g.:

canonicalize(METER, SECOND * SECOND, :*) #=> [METER * SECOND, SECOND, :*]
canonicalize(METER, SECOND / SECOND, :*) #=> [METER * SECOND, SECOND, :/]
canonicalize(METER, SECOND * SECOND, :/) #=> [METER / SECOND, SECOND, :/]
canonicalize(METER, SECOND / SECOND, :/) #=> [METER / SECOND, SECOND, :*]

The locator block given to this method matches a CompositeUnit with arguments u11, u12 and op1.

See also canonicalize_operators.



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/uom/composite_unit_key_canonicalizer.rb', line 21

def canonicalize(u1, u2, operator, &locator) # :yields: u11, u12, op1
  # nothing to do if u2 is already a non-composite unit
  return u1, u2, operator unless CompositeUnit === u2
  # canonicalize u2
  cu21, cu22, cop2 = canonicalize(u2.axes.first, u2.axes.last, u2.operator, &locator)
  # redistribute u1 with the canonicalized u2 axes cu21 and cu22 using the redistributed operators rop1 and rop2
  rop1, rop2 = redistribute_operators(operator, cop2)
  # yield canonicalize(u1, cu21, rop1, &locator)
  # the maximally reduced canonical form
  return u1.send(rop1, cu21), cu22, rop2
end

#match(hash, u1, u2, operator) ⇒ Object



6
7
8
9
# File 'lib/uom/composite_unit_key_canonicalizer.rb', line 6

def match(hash, u1, u2, operator)
  spec = canonicalize(u1, u2, operator)
  hash[spec] ||= new(*spec)
end

#redistribute_operators(operator, other) ⇒ Object

Returns the operators to apply to a canonical form according to the rules:

x * (y * z) = (x * y) * z
x * (y / z) = (x * y) / z
x / (y * z) = (x / y) / z
x / (y / z) = (x / y) * z

i.e.:

redistribute_operators(:*, :*) #=> [:*, :*]
redistribute_operators(:*, :/) #=> [:*, :/]
redistribute_operators(:/, :*) #=> [:/, :/]
redistribute_operators(:/, :/) #=> [:/, :*]


43
44
45
46
47
48
49
50
51
# File 'lib/uom/composite_unit_key_canonicalizer.rb', line 43

def redistribute_operators(operator, other)
  # not as obscure as it looks: if operator is * then there is no change to the operators since * is associative, i.e.:
  #   x * (y * z) = (x * y) * z
  #   x * (y / z) = (x * y) / z
  # otherwise, operator is /. in that case, apply the rules:
  #   x / (y * z) = (x / y) / z
  #   x / (y / z) = (x / y) * z
  operator == :* ? [operator, other] : (other == :* ? [:/, :/] : [:/, :*])
end