Class: Eymiha::NumericWithUnits

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/eymiha/units/numeric_with_units.rb

Overview

A NumericWithUnits is the intersection of a Numeric and a UnitsHash.

Unit-sensitive coding is made much easier using an object that transparently adds units to a common everyday Numerics. Everything that can be done to a Numeric is still there, but explicit and implicit unit conversions are present in all of the operations.

With this, numbers with units can be created easily. For example,

2.feet        # a length of 2 feet
5.inches^2    # an area of 5 square inches
44.5.ft/sec   # a velocity of 44.5 feet per second

This should provide a good starting point for using the Units framework. Also pay attention to the examples given in the method documentation; some of the dynamic features of the framework are exposed in them.

Constant Summary collapse

@@debug =
false
@@derived_align_type =
:whole_powers

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(numeric, unit, power = 1) ⇒ NumericWithUnits

Returns a new NumericWithUnits instance whose numeric part is set to numeric and whose units part is set to a units hash for the unit raised to the provided power.



41
42
43
# File 'lib/eymiha/units/numeric_with_units.rb', line 41

def initialize(numeric,unit,power=1)
  @numeric, @unit = numeric, units_hash(unit)**power
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

:nodoc:



510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
# File 'lib/eymiha/units/numeric_with_units.rb', line 510

def method_missing(method,*args) # :nodoc:
  begin
    s = method.to_s
    ms = s.split '_'
    if ms[0] == 'to'
      convert! s.gsub(/^to_/,"")
    elsif ms[0] == 'in'
      convert s.gsub(/^in_/,"")
    elsif ms.select{|e| e == 'per'}.size > 0
      convert_per method
    else
      convert s
    end
  rescue Exception
    value = numeric.send(method,*args)
    if (value.kind_of? String)
      "#{value} #{unit.to_s(numeric)}"
    else
      NumericWithUnits.new(value,unit)
    end
  end
end

Instance Attribute Details

#numericObject

A Numeric containing the numeric part of the instance



33
34
35
# File 'lib/eymiha/units/numeric_with_units.rb', line 33

def numeric
  @numeric
end

#originalObject

:nodoc:



36
37
38
# File 'lib/eymiha/units/numeric_with_units.rb', line 36

def original
  @original
end

#unitObject

A UnitsHash containing the units part of the instance



35
36
37
# File 'lib/eymiha/units/numeric_with_units.rb', line 35

def unit
  @unit
end

Class Method Details

.commutative_operator(op, old, calc) ⇒ Object

:nodoc:



482
483
484
485
486
487
488
489
# File 'lib/eymiha/units/numeric_with_units.rb', line 482

def NumericWithUnits.commutative_operator(op,old,calc) # :nodoc:
  ([] <<
   "alias :old_#{old} :#{op}" <<
   "def #{op}(value)" <<
   "  (value.kind_of? NumericWithUnits) ? #{calc} : old_#{old}(value)" <<
   "end").
    join("\r\n")
end

.create_commutative_operators(klasses) ⇒ Object

:nodoc:



491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/eymiha/units/numeric_with_units.rb', line 491

def NumericWithUnits.create_commutative_operators(klasses) # :nodoc:
  commutative_operators ||=
    ([] <<
     commutative_operator( "*",   "multiply", "value * self"        ) <<
     commutative_operator( "/",   "divide",   "(value**-1) * self"  ) <<
     commutative_operator( "+",   "add",      "value + self"        ) <<
     commutative_operator( "-",   "subtract", "(-value) + self"     ) <<
     commutative_operator( "%",   "modulo",   "value.inv_mod(self)" ) <<
     commutative_operator( "<=>", "compare",  "-(value <=> self)"   ) <<
     commutative_operator( ">",   "gt",       "(value < self)"      ) <<
     commutative_operator( "<",   "lt",       "(value > self)"      ) <<
     commutative_operator( ">=",  "gteq",     "(value <= self)"     ) <<
     commutative_operator( "<=",  "lteq",     "(value >= self)"     ) <<
     commutative_operator( "==",  "eq",       "(value == self)"     ) <<
     commutative_operator( "=~",  "approxeq", "(value =~ self)"     )).
    join("\r\n")
  klasses.each { |klass| klass.class_eval commutative_operators }
end

.debug=(value) ⇒ Object



28
29
30
# File 'lib/eymiha/units/numeric_with_units.rb', line 28

def self.debug=(value)
  @@debug = value
end

.derived_align_typeObject

Returns the type of exponentiation merging during alignment.

  • :whole_powers require exponents to have integer values

  • :fractional_powers allow exponents to have rational values



326
327
328
# File 'lib/eymiha/units/numeric_with_units.rb', line 326

def self.derived_align_type
  @@derived_align_type
end

.derived_align_type=(type) ⇒ Object

Sets and returns the type of exponentiation merging during alignment.



319
320
321
# File 'lib/eymiha/units/numeric_with_units.rb', line 319

def self.derived_align_type=(type)
  @@derived_align_type = type
end

Instance Method Details

#%(value) ⇒ Object

Returns a new NumericWithUnits containing the numeric part of the instance modulo the numeric part of the value, with the units part equal to the instance’s units part. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

30.in % 2.ft        #  0.5 feet
5.in % 2.3          #  0.4 inches
5.in % 2.sec        #  UnitsException


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/eymiha/units/numeric_with_units.rb', line 252

def %(value)
  if derived?
    reduce%value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self%value.reduce
    else
      aligned_value = align(value)
      aligned_value.numeric = aligned_value.numeric % value.numeric
      aligned_value
    end
  elsif value.kind_of? Numeric
    NumericWithUnits.new(numeric % value,unit)
  else
    raise UnitsException.new("units mismatch")
  end
end

#*(value) ⇒ Object

Returns a new NumericWithUnits containing the product of the instance and the value. The units of the two factors are merged. If the value is not a Numeric nor NumericWithUnits, a UnitsException is thrown.

6.in * 2.ft         #  1 foot^2
6.in * 2            #  12 inches
6.in * 2.sec        #  12 ft sec
6.in * "hello"      #  UnitsException


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/eymiha/units/numeric_with_units.rb', line 174

def *(value)
  if derived?
    reduce*value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self*value.reduce
    else
      extend(value,1)
    end
  elsif value.kind_of? Numeric
    NumericWithUnits.new(numeric*value,unit)
  else
    raise UnitsException.new("units mismatch")
  end
end

#**(value) ⇒ Object

Returns a new NumericWithUnits containing the numeric and units parts of the instance both raised to the valueth power. If the value is not a Numeric, a UnitsException is thrown.

6.in ** 3           #  216 in^3
6.in ** 3.in        #  UnitsException


222
223
224
225
226
227
228
# File 'lib/eymiha/units/numeric_with_units.rb', line 222

def **(value)
  if (value.kind_of? Numeric) && !(value.kind_of? NumericWithUnits)
    extend(nil,value)
  else
    raise UnitsException.new("units mismatch")
  end
end

#+(value) ⇒ Object

Returns a new NumericWithUnits containing the sum of the instance and the value. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

6.inches + 1.foot   #  18 inches
6.inches + 1        #   7 inches
6.inches + 1.sec    #  UnitsException


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/eymiha/units/numeric_with_units.rb', line 137

def +(value)
  if derived?
    reduce+value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self+value.reduce
    else
      aligned_value = align(value)
      aligned_value.numeric += value.numeric
      aligned_value
    end
  elsif value.kind_of? Numeric
    NumericWithUnits.new(numeric+value,unit)
  else
    raise UnitsException.new("units mismatch")
  end
end

#+@Object

Unary plus returns a copy of the instance.



119
120
121
# File 'lib/eymiha/units/numeric_with_units.rb', line 119

def +@
  clone
end

#-(value) ⇒ Object

Returns a new NumericWithUnits containing the difference between the instance and the value. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

6.inches - 1.foot   #  -6 inches
6.inches - 1        #   5 inches
6.inches - 1.sec    #  UnitsException


162
163
164
# File 'lib/eymiha/units/numeric_with_units.rb', line 162

def -(value)
  self + (-value)
end

#-@Object

Unary minus returns a copy of the instance with its numeric part negated.



124
125
126
127
128
# File 'lib/eymiha/units/numeric_with_units.rb', line 124

def -@
  value = clone
  value.numeric = -(value.numeric)
  value
end

#/(value) ⇒ Object

Returns a new NumericWithUnits containing the value of the instance divided by the value. The units of the result are the units of the instance merged with the recipricol of the units of the value. If the value is neither a Numeric nor NumericWithUnits, a UnitsException is thrown.

6.in / 2.ft         #  0.25
6.in / 2            #  3 inches
6.in / 2.sec        #  3 ft / sec
6.in / "hello"      #  UnitsException


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/eymiha/units/numeric_with_units.rb', line 200

def /(value)
  if derived?
    reduce/value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self/value.reduce
    else
      extend(value,-1)
    end
  elsif value.kind_of? Numeric
    NumericWithUnits.new(numeric/value,unit)
  else
    raise UnitsException.new("units mismatch")
  end
end

#<=>(value) ⇒ Object

Compares the numeric and units parts of the instance with the value. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

2.ft <=> 1.yd        #  -1
3.ft <=> 1.yd        #   0
4.ft <=> 1.yd        #   1
4.ft <=> 3.5         #   1
4.ft <=> 2.minutes   #  UnitsException


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/eymiha/units/numeric_with_units.rb', line 78

def <=>(value)
  if derived?
    reduce <=> value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self <=> value.reduce
    else
      align(value).numeric <=> value.numeric
    end
  elsif value.kind_of? Numeric
    numeric <=> value
  else
    raise UnitsException.new("units mismatch")
  end
end

#^(value) ⇒ Object

Returns a new NumericWithUnits containing the numeric and units parts of the instance with just the units raised to the valueth power. If the value is not a Numeric, a UnitsException is thrown.

6.in ^ 3            #  6 in^3
6.in ^ 3.in         #  UnitsException


236
237
238
239
240
241
242
# File 'lib/eymiha/units/numeric_with_units.rb', line 236

def ^(value)
  if (value.kind_of? Numeric) && !(value.kind_of? NumericWithUnits)
    NumericWithUnits.new(numeric,unit,value)
  else
    raise UnitsException.new("units mismatch")
  end
end

#align(target, all = true, type = @@derived_align_type) ⇒ Object

Returns a new NumericWithUnits whose value is equivalent to that of the instance, but whose units are aligned to the target, according to the value of derived_align_type. If all is true, then the UnitsMeasure of the instance and the target must match exactly, or else a UnitsException is raised.

(80.miles_per_hour).align(1.min,false)   #  1.3333333 mi / min


339
340
341
342
343
344
345
346
347
# File 'lib/eymiha/units/numeric_with_units.rb', line 339

def align(target,all=true,type=@@derived_align_type)
  if target.kind_of? Array
    piece_align(target)
  elsif !derived? && !target.derived?
    simple_align(target,all)
  else
    power_align(target,all,type)
  end
end

#approximately_equals?(value, epsilon = Numeric.epsilon) ⇒ Boolean Also known as: =~

Returns true if the value and the instance are within a distance epsilon of each other. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

1.ft.approximately_equals? 0.33.yd       # false
1.ft.approximately_equals? 0.333333.yd   # true

Returns:

  • (Boolean)


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/eymiha/units/numeric_with_units.rb', line 100

def approximately_equals?(value,epsilon=Numeric.epsilon)
  if derived?
    reduce.approximately_equals?(value,epsilon)
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      approximately_equals?(value.reduce,epsilon)
    else
      align(value).numeric.approximately_equals?(value.numeric,epsilon)
    end
  elsif value.kind_of? Numeric
    numeric.approximately_equals?(value,epsilon)
  else
    raise UnitsException.new("units mismatch")
  end
end

#can_align(target, exact = true) ⇒ Object

:nodoc:



296
297
298
299
# File 'lib/eymiha/units/numeric_with_units.rb', line 296

def can_align(target,exact=true) # :nodoc:
  ru, tru = reduce.unit, target.reduce.unit
  !exact || (ru == tru)
end

#common_power(ps) ⇒ Object

:nodoc:



310
311
312
# File 'lib/eymiha/units/numeric_with_units.rb', line 310

def common_power(ps) # :nodoc:
  ps.values.collect {|a| a[2]}.inject {|p,e| p.abs < e.abs ? p : e}
end

#convert(target_units = nil) ⇒ Object

Returns a copy of the instance converted to the target_units. Note that the conversion is only with respect to the UnitsMeasures of the target_units - the remainder of the units will remain unconverted.



591
592
593
# File 'lib/eymiha/units/numeric_with_units.rb', line 591

def convert(target_units=nil)
  target_units ? align(1.unite(target_units),false) : clone
end

#convert!(target_units = nil) ⇒ Object

Converts the instance itself.



596
597
598
599
600
# File 'lib/eymiha/units/numeric_with_units.rb', line 596

def convert!(target_units=nil)
  result = convert(target_units)
  self.numeric, self.unit = result.numeric, result.unit
  self
end

#convert_per(method) ⇒ Object

:nodoc:

Raises:



533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'lib/eymiha/units/numeric_with_units.rb', line 533

def convert_per method # :nodoc:
  ps = method.to_s.split '_per_'
  raise UnitsException.new('invalid per method') if ps.size !=  2
  numerator = 1.unite(ps[0])
  numerator_units = Set.new numerator.unit.keys
  denominator = 1.unite(ps[1])
  denominator_units = Set.new denominator.unit.keys
  positives = unit.keys.collect{|k| unit[k] > 0 ? k : nil}.compact!
  negatives = unit.keys.collect{|k| unit[k] < 0 ? k : nil}.compact!
  numerator_positives =
    Set.new 1.unite(positives).align(numerator,false).unit.keys
  numerator_negatives =
    Set.new 1.unite(negatives).align(numerator,false).unit.keys
  denominator_positives =
    Set.new 1.unite(positives).align(denominator,false).unit.keys
  denominator_negatives =
    Set.new 1.unite(negatives).align(denominator,false).unit.keys
  if (numerator_units == numerator_positives) &&
      (denominator_units == denominator_negatives)
    convert(ps[0]+'_and_'+ps[1])
  elsif (numerator_units == numerator_negatives) &&
      (denominator_units == denominator_positives)
    convert(ps[0]+'_and_'+ps[1])**-1
  else
    raise UnitsException.new('invalid per units')
  end
end

#derived?Boolean

Returns true if a component of unit part of the instance has a derived UnitsMeasure.

Returns:

  • (Boolean)


624
625
626
# File 'lib/eymiha/units/numeric_with_units.rb', line 624

def derived?
  unit.derived?
end

#extend(units, power) ⇒ Object

Returns a new NumericWithUnits whose value is extended by raising it to the power, or by multiplying it by units raised to the power.

7.miles.extend(nil,2)    #  49 mi^2
5.feet.extend(10.ft,2)   #  500 ft^3


470
471
472
473
474
475
476
477
478
479
480
# File 'lib/eymiha/units/numeric_with_units.rb', line 470

def extend(units,power)
  if !units
    NumericWithUnits.new(numeric**power,unit**power)
  else
    value = align(units,false)
    extended_numeric = value.numeric*(units.numeric**power)
    extended_unit = value.unit.merge(units,power)
    (extended_unit.size == 0)? extended_numeric :
      NumericWithUnits.new(extended_numeric,extended_unit)
  end
end

#format(name = nil) ⇒ Object

Returns a String formatted using the named format defined in the instance’s measure. Raises a UnitsException if either the unit part of the instance has no defined UnitsMeasure or a format with the given name does not exist in that UnitsMeasure.



611
612
613
614
615
616
617
618
619
620
# File 'lib/eymiha/units/numeric_with_units.rb', line 611

def format(name=nil)
  if name == nil
    to_s
  else
    raise UnitsException.new("system not explicit") if (measure == nil)
    format = measure.formats[name]
    raise UnitsException.new("missing format") if format == nil
    format.call(self)
  end
end

#inv_mod(value) ⇒ Object

Returns a new NumericWithUnits containing the numeric part of the value modulo the numeric part of the instance, with the units part equal to the instance’s units part. If the value is a Numeric, the units are assumed to match. If the UnitsMeasures don’t match, a UnitsException is raised.

30.in % 2.ft        #  24 inches
5.in % 2.3          #  2.3 inches
5.in % 2.sec        #  UnitsException


278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/eymiha/units/numeric_with_units.rb', line 278

def inv_mod(value)
  if derived?
    reduce.inv_mod value
  elsif value.kind_of? NumericWithUnits
    if value.derived?
      self.inv_mod value.reduce
    else
      aligned_value = align(value)
      aligned_value.numeric = value.numeric % aligned_value.numeric
      aligned_value
    end
  elsif value.kind_of? Numeric
    NumericWithUnits.new(value % numeric,unit)
  else
    raise UnitsException.new("units mismatch")
  end
end

#kind_of?(klass) ⇒ Boolean

Returns true if the instance or it’s numeric part is a kind of klass.

28.feet.kind_of? String             # false
28.feet.kind_of? NumericWithUnits   # true
28.feet.kind_of? Numeric            # true
28.feet.kind_of? Integer            # true
28.feet.kind_of? Float              # false
28.0.feet.kind_of? Float            # true

Note while NumericWithUnits actually descends from Object, it acts as if it is inherited from the class of the numeric part of the instance, since it forwards any unknown method calls to it. In this way the duck really is a duck.

Returns:

  • (Boolean)


576
577
578
# File 'lib/eymiha/units/numeric_with_units.rb', line 576

def kind_of?(klass)
  (numeric.kind_of? klass)? true : old_kind_of?(klass)
end

#measureObject

Returns the UnitsMeasures in the units part of the instance.



603
604
605
# File 'lib/eymiha/units/numeric_with_units.rb', line 603

def measure
  unit.measure
end

#old_kind_of?Object



561
# File 'lib/eymiha/units/numeric_with_units.rb', line 561

alias :old_kind_of? :kind_of?

#piece_align(pieces, type = @@derived_align_type) ⇒ Object

:nodoc:

Raises:



431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/eymiha/units/numeric_with_units.rb', line 431

def piece_align(pieces,type=@@derived_align_type) # :nodoc:
  puts "piece_align #{self} #{pieces}" if @@debug
  factor = 1
  target_unit = UnitsHash.new
  unit_reduce = reduce
  pieces.each do |p|
    p.unit.each do |tu,tv|
      t_u = {}
      tt_u = {}
      tu_reduce = tu.equals.reduce
      found = tu_reduce.unit.each do |ttu,ttv|
        su = unit_reduce.unit.keys.select {|u|
          u.units_measure.equal? ttu.units_measure }
        break false if su.size == 0
        tt_u[ttu] = reduce_power(unit_reduce.unit[ttu],ttv,type)
      end
      if found
        tt_u.each {|k,v| tt_u[k] = revise_power(v,tv)}
        t_u[tu] = tv
        t_factor = tu_reduce.numeric**tv
        target_unit[tu] = tv
        factor *= t_factor/(tu.equals.numeric**tv)
        tt_u.each {|k,v|
          unit_reduce.numeric /= t_factor
          unit_reduce.unit[k] = v[3]}
      end
    end
  end
  raise UnitsException.new("units mismatch") if unit_reduce.unit.has_units?
  nwu = NumericWithUnits.new(factor*unit_reduce.numeric,target_unit)
  puts "  piece_align returning #{nwu}" if @@debug
  nwu
end

#power_align(target, all = true, type = @@derived_align_type) ⇒ Object

:nodoc:

Raises:



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/eymiha/units/numeric_with_units.rb', line 387

def power_align(target,all=true,type=@@derived_align_type) # :nodoc:
  puts "power_align #{self} #{target}" if @@debug
  raise UnitsException.new("units mismatch") unless can_align(target,all)
  factor = 1
  target_unit = UnitsHash.new
  unit_reduce = reduce
  puts "  unit_reduce #{unit_reduce}" if @@debug
  target.unit.each do |tu,tv|
    t_u = {}
    tt_u = {}
    tu_reduce = tu.equals.reduce
    found = tu_reduce.unit.each do |ttu,ttv|
      su = unit_reduce.unit.keys.select {|u|
        u.units_measure.equal? ttu.units_measure }
      break false if su.size == 0
      tt_u[ttu] = reduce_power(unit_reduce.unit[ttu],ttv,type)
    end
    if found
      cp = common_power(tt_u)
      puts "  cp #{cp}" if @@debug
      tt_u.each {|k,v| tt_u[k] = revise_power(v,cp)}
      t_u[tu] = tv**cp
      t_factor = tu_reduce.numeric**cp
      puts "  t_factor #{t_factor}" if @@debug
      target_unit[tu] = cp
      puts "  tu.equals.numeric**cp #{tu.equals.numeric**cp}" if @@debug
      factor *= t_factor/(tu.equals.numeric**cp)
      puts "  factor #{factor}" if @@debug
      tt_u.each {|k,v|
        unit_reduce.numeric /= t_factor
        unit_reduce.unit[k] = v[3]}
    end
  end
  puts "  unit_reduce #{unit_reduce}" if @@debug
  unit_redux = unit_reduce.simple_align(self,false)
  puts "  unit_redux #{unit_redux}" if @@debug
  result_unit = target_unit.merge(unit_redux)
  raise UnitsException.new("units mismatch") if
    all && (target.unit != result_unit)
  nwu = NumericWithUnits.new(factor*unit_redux.numeric,result_unit)
  puts "  power_align returning #{nwu}" if @@debug
  nwu
end

#promote_originalObject

:nodoc:



65
66
67
# File 'lib/eymiha/units/numeric_with_units.rb', line 65

def promote_original # :nodoc:
  @numeric, @unit = original.numeric, original.unit
end

#reduceObject

Return a new NumericWithUnits that is equivalent to the instance but whose unit contains no derived UnitMeasures.



630
631
632
633
# File 'lib/eymiha/units/numeric_with_units.rb', line 630

def reduce
  puts "reduce unit.reduce #{unit.reduce}" if @@debug
  numeric * unit.reduce
end

#reduce_power(p, f, type) ⇒ Object

:nodoc:



301
302
303
304
305
306
307
308
# File 'lib/eymiha/units/numeric_with_units.rb', line 301

def reduce_power(p,f,type) # :nodoc:
  if type == :whole_powers
    pa = p.abs
    (p == 0) ? [p,f,0] : (pa < f) ? [p, f, pa/p] : [p, f, p/f]
  else
    (p == 0) ? [p,f,0] : [p, f, (1.0*p)/f]
  end
end

#revise_power(rp, p) ⇒ Object

:nodoc:



314
315
316
# File 'lib/eymiha/units/numeric_with_units.rb', line 314

def revise_power(rp,p) # :nodoc:
  [rp[0], rp[1], p, rp[0]-p*rp[1]]
end

#simple_align(target, all = true) ⇒ Object

:nodoc:

Raises:



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/eymiha/units/numeric_with_units.rb', line 349

def simple_align(target,all=true) # :nodoc:
  puts "simple align #{self} #{target}" if @@debug
  factor = 1
  target_unit = UnitsHash.new
  unit.each do |tu,tv|
    su = target.unit.keys.select {|u|
      u.units_measure.equal? tu.units_measure }
    if tu.equals.kind_of? Array
      m = tu.equals.select{|u| u.unit[su[0]]}
      m = tu.equals.collect{|u|
 u.align(1.unite(su[0]))}.compact if m.size == 0
      factor *= (m[0].numeric)**tv
      target_unit[su[0]] = tv
    else
      if su.size == 1
        e = su[0].equals
        if e.kind_of? Array
          m = e.select{|u|
            u.unit[tu]}
          m = e.equals.collect{|u|
     u.align(1.unite(su[0]))}.compact if m.size == 0
          factor *= (1.0/m[0].numeric)**tv
        else
          factor *= (1.0*tu.equals.numeric/e.numeric)**tv
        end
        target_unit[su[0]] = tv
      else
        target_unit[tu] = tv
      end
    end
  end
  raise UnitsException.new("units mismatch") if
    all && (target.unit != target_unit)
  nwu = NumericWithUnits.new(numeric*factor,target_unit)
  puts "  simple_align returning #{nwu}" if @@debug
  nwu
end

#to_s(format = nil) ⇒ Object

Returns a String representation of the instance, using the named format if provided.

15.5.minutes.to_s                        #  15.5 minutes
15.5.minutes.to_seconds.to_s             #  930.0 seconds
15.5.minutes.in_seconds.to_s             #  930.0 seconds
15.5.minutes.seconds.to_s                #  930.0 seconds
(15.5.minutes+1).seconds.to_s            #  990.0 seconds
(15.5.minutes.seconds+1).to_s            #  931.0 seconds
10.feet_per_minute.to_s                  #  10 ft / min
seconds_per_hour.to_s                    #  3600.0
14.5.inches.to_s(:feet_inches_and_32s)   #  "1 foot 2-16/32 inches"


61
62
63
# File 'lib/eymiha/units/numeric_with_units.rb', line 61

def to_s(format = nil)
  format == nil ? "#{numeric} #{unit.to_s(numeric)}" : self.format(format)
end

#unite(target_unit = nil, power = 1, measure = nil) ⇒ Object

Returns a new NumericWithUnits whose numeric part is the target of the Numeric’s unite method.

28.ft^2.unite("seconds")   #  28 seconds


584
585
586
# File 'lib/eymiha/units/numeric_with_units.rb', line 584

def unite(target_unit=nil,power=1,measure=nil)
  numeric.unite(target_unit,power,measure)
end

#units_hash(unit) ⇒ Object

:nodoc:



45
46
47
# File 'lib/eymiha/units/numeric_with_units.rb', line 45

def units_hash(unit) # :nodoc:
  (unit.kind_of? UnitsHash) ? unit : UnitsHash.new(unit)
end