class Pulo::Quantity

Attributes

base_unit[RW]
dimensions[RW]
unit[RW]

Instance variables and methods - Child Quantities

value[RW]

Instance variables and methods - Child Quantities

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