Class: Eymiha::NumericWithUnits
- 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
-
#numeric ⇒ Object
A Numeric containing the numeric part of the instance.
-
#original ⇒ Object
:nodoc:.
-
#unit ⇒ Object
A UnitsHash containing the units part of the instance.
Class Method Summary collapse
-
.commutative_operator(op, old, calc) ⇒ Object
:nodoc:.
-
.create_commutative_operators(klasses) ⇒ Object
:nodoc:.
- .debug=(value) ⇒ Object
-
.derived_align_type ⇒ Object
Returns the type of exponentiation merging during alignment.
-
.derived_align_type=(type) ⇒ Object
Sets and returns the type of exponentiation merging during alignment.
Instance Method Summary collapse
-
#%(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.
-
#*(value) ⇒ Object
Returns a new NumericWithUnits containing the product of the instance and the value.
-
#**(value) ⇒ Object
Returns a new NumericWithUnits containing the numeric and units parts of the instance both raised to the valueth power.
-
#+(value) ⇒ Object
Returns a new NumericWithUnits containing the sum of the instance and the value.
-
#+@ ⇒ Object
Unary plus returns a copy of the instance.
-
#-(value) ⇒ Object
Returns a new NumericWithUnits containing the difference between the instance and the value.
-
#-@ ⇒ Object
Unary minus returns a copy of the instance with its numeric part negated.
-
#/(value) ⇒ Object
Returns a new NumericWithUnits containing the value of the instance divided by the value.
-
#<=>(value) ⇒ Object
Compares the numeric and units parts of the instance with the value.
-
#^(value) ⇒ Object
Returns a new NumericWithUnits containing the numeric and units parts of the instance with just the units raised to the valueth power.
-
#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.
-
#approximately_equals?(value, epsilon = Numeric.epsilon) ⇒ Boolean
(also: #=~)
Returns true if the value and the instance are within a distance epsilon of each other.
-
#can_align(target, exact = true) ⇒ Object
:nodoc:.
-
#common_power(ps) ⇒ Object
:nodoc:.
-
#convert(target_units = nil) ⇒ Object
Returns a copy of the instance converted to the target_units.
-
#convert!(target_units = nil) ⇒ Object
Converts the instance itself.
-
#convert_per(method) ⇒ Object
:nodoc:.
-
#derived? ⇒ Boolean
Returns true if a component of unit part of the instance has a derived UnitsMeasure.
-
#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.
-
#format(name = nil) ⇒ Object
Returns a String formatted using the named format defined in the instance’s measure.
-
#initialize(numeric, unit, power = 1) ⇒ NumericWithUnits
constructor
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.
-
#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.
-
#kind_of?(klass) ⇒ Boolean
Returns true if the instance or it’s numeric part is a kind of klass.
-
#measure ⇒ Object
Returns the UnitsMeasures in the units part of the instance.
-
#method_missing(method, *args) ⇒ Object
:nodoc:.
- #old_kind_of? ⇒ Object
-
#piece_align(pieces, type = @@derived_align_type) ⇒ Object
:nodoc:.
-
#power_align(target, all = true, type = @@derived_align_type) ⇒ Object
:nodoc:.
-
#promote_original ⇒ Object
:nodoc:.
-
#reduce ⇒ Object
Return a new NumericWithUnits that is equivalent to the instance but whose unit contains no derived UnitMeasures.
-
#reduce_power(p, f, type) ⇒ Object
:nodoc:.
-
#revise_power(rp, p) ⇒ Object
:nodoc:.
-
#simple_align(target, all = true) ⇒ Object
:nodoc:.
-
#to_s(format = nil) ⇒ Object
Returns a String representation of the instance, using the named format if provided.
-
#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.
-
#units_hash(unit) ⇒ Object
:nodoc:.
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
#numeric ⇒ Object
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 |
#original ⇒ Object
:nodoc:
36 37 38 |
# File 'lib/eymiha/units/numeric_with_units.rb', line 36 def original @original end |
#unit ⇒ Object
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_type ⇒ Object
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
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:
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.
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.
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 |
#measure ⇒ Object
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:
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:
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_original ⇒ Object
: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 |
#reduce ⇒ Object
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:
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 |