Class: SY::Measure

Inherits:
Object
  • Object
show all
Defined in:
lib/sy/mapping.rb,
lib/sy/measure.rb

Overview

Represents a certain way, that a quantity measures another quantity (reference quantity). Instance has two attributes:

  • @r - read closure, for converting from the measured reference quantity.

  • @w - write closure, for converting back to the reference quantity.

Convenience methods #read and #write facilitate their use.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ratio: nil, r: nil, w: nil) ⇒ Measure

The constructor expects :r and :w arguments for read and write closure.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/sy/mapping.rb', line 61

def initialize ratio: nil,
  r: ( fail ArgumentError, ":r closure not specified!" unless ratio ),
  w: ( fail ArgumentError, ":w closure not specified!" unless ratio )
  if ratio.nil?
    fail TypeError, ":r and :w arguments must both be closures!" unless
      r.is_a?( Proc ) && w.is_a?( Proc )
    @ratio, @r, @w = nil, r, w
  else
    fail ArgumentError, ":r or :w must not be given if :ratio given!" if r || w
    @ratio = ratio
    @r = lambda { |ref_amnt| ref_amnt / ratio }
    @w = lambda { |amnt| amnt * ratio }
  end
end

Instance Attribute Details

#rObject (readonly)

Returns the value of attribute r.



57
58
59
# File 'lib/sy/mapping.rb', line 57

def r
  @r
end

#ratioObject (readonly)

Returns the value of attribute ratio.



57
58
59
# File 'lib/sy/mapping.rb', line 57

def ratio
  @ratio
end

#wObject (readonly)

Returns the value of attribute w.



57
58
59
# File 'lib/sy/mapping.rb', line 57

def w
  @w
end

Class Method Details

.identityObject

Identity measure.



14
15
16
# File 'lib/sy/mapping.rb', line 14

def identity
  simple_scale 1
end

.linear(hsh) ⇒ Object

Linear (scaled offset) measure. Expects a hash with 2 points demonstrating the relationship: { ref_amount_1 => amount_1, ref_amount_2 => amount_2 }. (Example: Fahrenheit degrees vs. Kelvins.)



35
36
37
38
39
40
# File 'lib/sy/mapping.rb', line 35

def linear hsh
  ref_amnt_1, amnt_1, ref_amnt_2, amnt_2 = hsh.to_a.flatten
  scale = ( ref_amnt_2 - ref_amnt_1 ) / ( amnt_2 - amnt_1 )
  new( r: lambda { |ref_amnt| amnt_1 + ( ref_amnt - ref_amnt_1 ) / scale },
       w: lambda { |amnt| ref_amnt_1 + ( amnt - amnt_1 ) * scale } )
end

.logarithmic(base = Math::E) ⇒ Object

Logarithmic.



44
45
46
47
# File 'lib/sy/mapping.rb', line 44

def logarithmic base=Math::E
  new( r: lambda { |ref_amnt| Math.log ref_amnt, base },
       w: lambda { |amnt| base ** amnt } )
end

.negative_logarithmic(base = Math::E) ⇒ Object

Negative logarithmic.



51
52
53
54
# File 'lib/sy/mapping.rb', line 51

def negative_logarithmic base=Math::E
  new( r: lambda { |ref_amnt| -Math.log( ref_amnt, base ) },
       w: lambda { |amnt| base ** ( -amnt ) } )
end

.simple_offset(offset) ⇒ Object

Simple offset measure. (Such as °C)



26
27
28
29
# File 'lib/sy/mapping.rb', line 26

def simple_offset offset
  new( r: lambda { |ref_amnt| ref_amnt - offset },
       w: lambda { |amnt| amnt + offset } )
end

.simple_scale(scale) ⇒ Object

Simple scaling measure. (Eg. pounds vs kilograms)



20
21
22
# File 'lib/sy/mapping.rb', line 20

def simple_scale scale
  new( ratio: scale )
end

Instance Method Details

#*(other) ⇒ Object

Measure composition (like f * g function composition).



100
101
102
103
104
105
106
107
108
# File 'lib/sy/mapping.rb', line 100

def * other
  if ratio.nil? then
    r1, r2, w1, w2 = r, other.r, w, other.w
    self.class.new( r: lambda { |ref_amnt| r1.( r2.( ref_amnt ) ) },
                    w: lambda { |amnt| w2.( w1.( amnt ) ) } )
  else
    self.class.new( ratio: ratio * other.ratio )
  end
end

#**(n) ⇒ Object

Measure power.



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/sy/mapping.rb', line 118

def ** n
  if ratio.nil? then
    r_closure, w_closure = r, w
    self.class.new( r: lambda { |ref_amnt|
                      n.times.inject ref_amnt do |m, _| r_closure.( m ) end
                    },
                    w: lambda { |amnt|
                      n.times.inject amnt do |m, _| w_closure.( m ) end
                    } )
  else
    self.class.new( ratio: ratio ** n )
  end
end

#/(other) ⇒ Object

Measure composition with inverse of another measure.



112
113
114
# File 'lib/sy/mapping.rb', line 112

def / other
  self * other.inverse
end

#inverseObject

Inverse measure.



90
91
92
93
94
95
96
# File 'lib/sy/mapping.rb', line 90

def inverse
  if ratio.nil? then
    self.class.new( r: w, w: r ) # swap closures
  else
    self.class.new( ratio: 1 / ratio )
  end
end

#read(magnitude_of_reference_quantity, quantity) ⇒ Object

Convenience method to read a magnitude of a reference quantity.



78
79
80
# File 'lib/sy/mapping.rb', line 78

def read magnitude_of_reference_quantity, quantity
  quantity.magnitude r.( magnitude_of_reference_quantity.amount )
end

#write(magnitude, reference_quantity) ⇒ Object

Convenience method to convert a magnitude back to the reference quantity.



84
85
86
# File 'lib/sy/mapping.rb', line 84

def write magnitude, reference_quantity
  reference_quantity.magnitude w.( magnitude.amount )
end