class Pulo::Quantity
Attributes
base_unit[RW]
dimensions[RW]
Public Class Methods
best_si_unit(scale)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 50 def best_si_unit(scale) @si_unit_scales.min_by do |unit| (scale-unit[0]).abs end[1] end
method_missing(method_sym, *arguments, &block)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 56 def method_missing(method_sym, *arguments, &block) puts "#{quantity_name} doesn't have a unit #{method_sym}." puts "Available units are: " + units.map{|unt| unt[1].name }.join(', ') end
new(value=nil, unit=nil)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 90 def initialize(value=nil, unit=nil) value ||= 1.0 if unit if unit.is_a?(Symbol) raise "Unit #{unit.to_s} not defined for #{self.class.quantity_name}." unless self.class.units[unit] self.unit=self.class.units[unit] else self.unit=unit end else self.unit=self.class.base_unit end self.value=Float(value) unless self.value.is_a?(Float) self end
quantity_name()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 61 def quantity_name self.name.split('::')[1] end
si_unit_scales()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 44 def si_unit_scales; @si_unit_scales ||={};end
synonyms()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 45 def synonyms; @synonyms ||=[]; end
units()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 43 def units; @units ||={}; end
units_sorted()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 65 def units_sorted self.units.values.sort do |a,b| next -1 if a.is_si? && !b.is_si? next 1 if !a.is_si? && b.is_si? if a.is_si? next -1 if a.scale<b.scale next 1 else if a.si_convert_unit==b.si_convert_unit next a.si_convert_factor<=>b.si_convert_factor else a.si_convert_unit<=>b.si_convert_unit end end end end
Public Instance Methods
*(other)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 159 def *(other) case when other.is_a?(Numeric) self.class.new self.value*other,self.unit when other.is_a?(Quantity) new_dims=self.class.dimensions+other.class.dimensions #get both quantities to their equivalent SI if needed q1=self; q1=q1.to_si unless q1.is_si? q2=other; q2=q2.to_si unless q2.is_si? target_scale=q1.unit.scale+q2.unit.scale target_value=q1.value*q2.value existing_or_new_quantity new_dims,target_scale,target_value else raise QuantitiesException.new("Cannot multiply a #{other.class.name} and a #{self.class.name}") end end
**(power)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 194 def **(power) raise QuantitiesException.new('Can only raise a quantity to an integer power') unless power.is_a?(Integer) new_dims=self.class.dimensions*power q1=self; q1=q1.to_si unless q1.is_si? target_scale=q1.unit.scale*power target_value=q1.value**power existing_or_new_quantity new_dims,target_scale,target_value end
+(other)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 131 def +(other) case when other.is_a?(Numeric) self.class.new self.value+other,self.unit when other.class.dimensions==self.class.dimensions if self.unit==other.unit self.class.new self.value+other.value,self.unit else self.class.new self.value+other.send(self.unit.name).value,self.unit end else raise QuantitiesException.new("Cannot add a #{other.class.name} to a #{self.class.name}") end end
-(other)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 145 def -(other) case when other.is_a?(Numeric) self.class.new self.value-other,self.unit when other.class.dimensions==self.class.dimensions if self.unit==other.unit self.class.new self.value-other.value,self.unit else self.class.new self.value-other.send(self.unit.name).value,self.unit end else raise QuantitiesException.new("Cannot minus a #{other.class.name} from a #{self.class.name}") end end
-@()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 128 def -@ self.class.new -self.value,self.unit end
/(other)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 177 def /(other) case when other.is_a?(Numeric) self.class.new self.value/other,self.unit when other.is_a?(Quantity) new_dims=self.class.dimensions-other.class.dimensions q1=self; q1=q1.to_si unless q1.is_si? q2=other; q2=q2.to_si unless q2.is_si? target_scale=q1.unit.scale-q2.unit.scale target_value=q1.value/q2.value existing_or_new_quantity new_dims,target_scale,target_value else raise QuantitiesException.new("Cannot divide a #{self.class.name} by a #{other.class.name}") end end
<=>(other)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 221 def <=>(other) unless (other.is_a?(Quantity) && self.class.dimensions==other.class.dimensions) || (other.is_a?(Numeric) && self.class==Dimensionless) raise QuantitiesException.new("Can only compare quantities with same dimensions (given: #{self.class} and #{other.class}).") end if other.is_a?(Numeric) other=Dimensionless.n(other) end to_base_unit.value<=>other.to_base_unit.value end
dimensions()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 107 def dimensions self.class.dimensions end
existing_or_new_quantity(new_dims, target_scale, target_value)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 231 def existing_or_new_quantity(new_dims, target_scale, target_value) if Pulo.quantities[new_dims] klass=Pulo.quantities[new_dims][0] unit=klass.best_si_unit Math.log10(target_value.abs) + target_scale klass.new(target_value*10**(target_scale-unit.scale), unit) else qname=new_dims.to_s(true).gsub(/-/, '_') QuantityBuilder.build(qname) do # noinspection RubyArgCount dimensions new_dims.spec si_unit '0.0'+qname, '', new_dims.to_s, 1.0 unless target_scale==0 si_unit target_scale.to_s+qname, '', new_dims.to_s+'*10^'+target_scale.to_s, 1.0*10**target_scale end end.klass.send(target_scale.to_s+qname, target_value) end end
in()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 116 def in; self; end
inverse()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 125 def inverse Dimensionless.new/self end
is_si?()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 253 def is_si? @unit.is_si? end
method_missing(method_sym, *arguments, &block)
click to toggle source
Pass unknown methods through to the underlying value (Float
) if it responds. eg floor and modulo methods
# File lib/pulo/quantity/quantity.rb, line 119 def method_missing(method_sym, *arguments, &block) if self.value.respond_to?(method_sym) self.value.send(method_sym,*arguments,&block) end end
rescale()
click to toggle source
Converts to SI and most 'natural' scale
# File lib/pulo/quantity/quantity.rb, line 263 def rescale unless self.is_si? return self.to_base_unit.rescale end scale=Math.log10(self.value)+self.unit.scale unit_scales=self.class.si_unit_scales.sort if scale<unit_scales[0][0] return self.send unit_scales[0][1].name end if scale>=unit_scales.last[0] return self.send unit_scales.last[1].name end unit_scales.each_cons(2) do |us| if us[0][0]<=scale && us[1][0]>scale return self.send us[0][1].name end end end
rt(power)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 205 def rt(power) raise QuantitiesException.new('Can only do integer roots') unless power.is_a?(Integer) self.class.dimensions.spec.each do |dim| if dim[1]/power.to_f % 1 != 0 raise QuantitiesException.new('Root would lead to non-integer dimensions') end end new_dims=self.class.dimensions/power q1=self; q1=q1.to_si unless q1.is_si? target_scale=q1.unit.scale/power target_value=q1.value**(1.0/power) existing_or_new_quantity new_dims,target_scale,target_value end
to()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 115 def to; self; end
to_base_unit()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 249 def to_base_unit self.send(self.class.base_unit.name) end
to_s(precision=nil, supress_quantity_names=false)
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 111 def to_s(precision=nil, supress_quantity_names=false) "#{self.class.quantity_name + ': ' unless Pulo.supress_quantity_names || supress_quantity_names || self.class==Dimensionless}#{NumberToRoundedConverter.convert(@value,precision)} #{@unit.abbreviation}" end
to_si()
click to toggle source
# File lib/pulo/quantity/quantity.rb, line 257 def to_si return self if self.is_si? self.send(self.unit.si_convert_unit) end