class NumericWithUnit::Unit

Attributes

derivation[R]
dimension[R]
symbol[R]

Instance Methods

Public Class Methods

<<(arg) click to toggle source

add unit to base unit list.

# File lib/numeric_with_unit/unit.rb, line 192
def self.<<(arg)
  if arg.is_a?(self)
    @@list << arg
  else
    @@list << Unit[arg]
  end
end
[](arg) click to toggle source

apply to_s to arg and return parsed unit.

# File lib/numeric_with_unit/unit.rb, line 170
def self.[](arg)
  self.parse(arg.to_s)
end
[]=(key, arg) click to toggle source

cast unit and add unit to base unit list at the same time.

# File lib/numeric_with_unit/unit.rb, line 175
def self.[]=(key, arg)
  if arg.is_a?(Array) and arg.size == 2
    a = [key, arg.first]
    u = arg.last
  else
    a = [key]
    u = arg
  end
  @@list << (u.is_a?(self) ? u : self[u]).cast(*a)
end
assign() { |config| ... } click to toggle source

create new unit and add unit to base unit list at the same time.

# File lib/numeric_with_unit/unit.rb, line 206
def self.assign
  @@list << self.new{|config| yield(config)}
end
delete(unit_symbol) click to toggle source

remove unit from base unit list.

# File lib/numeric_with_unit/unit.rb, line 201
def self.delete(unit_symbol)
  @@list.delete_if{|unit| unit.symbol == unit_symbol}
end
derive() { |derivation| ... } click to toggle source

create new unit from derivation _(for internal use)_ .

# File lib/numeric_with_unit/unit.rb, line 109
def self.derive #(block)
  derivation = Hash.new(0)
  yield(derivation)
  derivation.delete_if{|k,v| k.symbol.nil?}
  
  return Unit.new if derivation.empty?
  
  
  # constructing symbol
  h = derivation.reject{|k,v| k.symbol.empty?}.sort_by{|u,v| u.symbol}.sort_by{|u,v| v}
  syms_pos = h.select{|u,v| v > 0}.map{|u,v| u.symbol + (v.abs>1 ? v.abs.to_s : '')}
  syms_neg = h.select{|u,v| v < 0}.map{|u,v| u.symbol + (v.abs>1 ? v.abs.to_s : '')}
  symbol = syms_pos.join('.')
  symbol += '/' + (syms_neg.size>1 ? "(#{syms_neg.join('.')})" : "#{syms_neg.first}") unless syms_neg.empty?
  
  # constructing dimension
  dimension = Hash.new(0)
  derivation.each do |u,v|
    u.dimension.each do |d,i|
      dimension[d] += i*v
    end
  end
  
  # constructing from_si proc
  from_si = derivation.map{|u,v|
    prc = if v > 0
      ->(x){u.from_si(x)}
    else
      ->(x){x.quo(u.from_si(1)-u.from_si(0))} #FIXME: ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
    end
    [prc, v.abs]
  }.map{|prc,v|
    ->(x){ v.times{x = prc[x]}; x }
  }.reduce{|memo, prc|
    ->(x){memo[prc[x]]}
  }
  
  # constructing to_si proc
  to_si = derivation.map{|u,v|
    prc = if v > 0
      ->(x){u.to_si(x)}
    else
      ->(x){x.quo(u.to_si(1)-u.to_si(0))} #FIXME: ℃とKの変換のような場合に、変換式の切片を消すため。変換式が線形じゃないケースは想定していない
    end
    [prc, v.abs]
  }.map{|prc,v|
    ->(x){ v.times{x = prc[x]}; x }
  }.reduce{|memo, prc|
    ->(x){memo[prc[x]]}
  }
  
  # deriving new unit
  self.new(derivation){|config|
    config.symbol = symbol
    config.dimension = dimension
    config.from_si = from_si
    config.to_si = to_si
  }
end
list() click to toggle source

return base unit list.

# File lib/numeric_with_unit/unit.rb, line 187
def self.list
  @@list
end
new(derivation=nil) { |config| ... } click to toggle source
# File lib/numeric_with_unit/unit.rb, line 330
def initialize(derivation=nil)
  # TODO: Unit::Configとinitializeの役割が分離できていないので見なおせ
  config = Config.new
  yield(config) if block_given?
  config.compile
  
  @symbol = config.symbol
  @dimension = config.dimension
  @from_si = config.from_si
  @to_si = config.to_si
  
  unless derivation
    derivation = Hash.new(0)
    derivation[self] += 1
  end
  @derivation = derivation
end
parse(unit_str) click to toggle source

parsing unit_str (ex. “kg”, km/hr“, ”cm2“) to (derived) unit.

# File lib/numeric_with_unit/unit.rb, line 212
def self.parse(unit_str)
  rec = ->(arg){__send__(__method__, arg)}

  dervation_str = parse_3rd(parse_2nd(parse_1st(unit_str)))
  derive{|derivation|
    dervation_str.each do |unit_str, order|
      if i = @@list.rindex{|unit| unit.symbol == unit_str}
        derivation[@@list[i]] += order
      elsif m = unit_str.match(/^(?<prefix>#{@@prefix.keys.join('|')})(?<unit>#{list.join('|')})$/) and m[:unit].empty?.!
        u = rec[m[:unit]].cast(unit_str, @@prefix[m[:prefix]])
        derivation[u] += order
      else
        raise NoUnitError, "[#{unit_str}] is not defined!"
      end
    end
  }
end

Public Instance Methods

*(other_unit) click to toggle source
# File lib/numeric_with_unit/unit.rb, line 395
def *(other_unit)
  self.class.derive do |derivation|
    @derivation.each{|k, v| derivation[k] += v}
    other_unit.derivation.each{|k, v| derivation[k] += v}
  end
end
**(num) click to toggle source
# File lib/numeric_with_unit/unit.rb, line 409
def **(num)
  if num.zero?
    self.class.new
  else
    self.class.derive do |derivation|
      # NOTE:
      # ここto_iでOKか?v*numが整数じゃなければraiseすべき?→すべき→NumericWithUnitでやるべき?
      # Unitでは整数じゃない次数の単位は許容すべきか否か→していい気がする
      @derivation.each{|k, v| derivation[k] = (v*num).to_i}
    end
  end
end
/(other_unit) click to toggle source
# File lib/numeric_with_unit/unit.rb, line 402
def /(other_unit)
  self.class.derive do |derivation|
    @derivation.each{|k, v| derivation[k] += v}
    other_unit.derivation.each{|k, v| derivation[k] -= v}
  end
end
==(other) click to toggle source
Calls superclass method
# File lib/numeric_with_unit/unit.rb, line 387
def ==(other)
  if other.is_a?(self.class)
    symbol == other.symbol and dimension == other.dimension
  else
    super
  end
end
cast(new_symbol, factor = 1) click to toggle source

create new unit with new symbol and factor from self. use for converting [in] = 25.4 .

# File lib/numeric_with_unit/unit.rb, line 350
def cast(new_symbol, factor = 1)
  self.class.new do |config|
    config.symbol = new_symbol
    config.dimension = @dimension
    config.from_si = ->(x){from_si(x.quo(factor))}
    config.to_si = ->(x){to_si(x * factor)}
  end
end
dimension_equal?(other_unit) click to toggle source

return true if self and other_unit have the same dimension.

# File lib/numeric_with_unit/unit.rb, line 381
def dimension_equal?(other_unit)
  (@dimension.keys | other_unit.dimension.keys).all?{|k|
    @dimension[k] == other_unit.dimension[k]
  }
end
dimensionless?() click to toggle source
# File lib/numeric_with_unit/unit.rb, line 376
def dimensionless?
  @dimension.all?{|k,v| v.zero?}
end
from_si(value) click to toggle source
# File lib/numeric_with_unit/unit.rb, line 371
def from_si(value)
  @from_si.call(value)
end
inspect() click to toggle source
# File lib/numeric_with_unit/unit.rb, line 363
def inspect
  "#<#{self.class}:[#{@symbol}] #{@dimension}>"
end
simplify() click to toggle source
# File lib/numeric_with_unit/unit.rb, line 423
def simplify
  self.class.derive{|derivation|
    @dimension.each do|d,o|
      u = self.class.list.find{|u| u.dimension == {d => 1}} #TODO: find? ok?
      raise NoUnitError, "No unit with #{{d=>1}} dimension is assined." unless u
      derivation[u] = o
    end
  }
end
to_s() click to toggle source
# File lib/numeric_with_unit/unit.rb, line 359
def to_s
  @symbol
end
to_si(value) click to toggle source
# File lib/numeric_with_unit/unit.rb, line 367
def to_si(value)
  @to_si.call(value)
end