module SY::Magnitude

This module defines common assets of a magnitude – be it absolute (number of unit objects), or relative (magnitude difference).

Attributes

amount[R]
in_standard_unit[R]
quantity[R]

Public Class Methods

absolute( of: nil, amount: nil ) click to toggle source

Constructs an absolute magnitude of a given quantity.

# File lib/sy/magnitude.rb, line 10
def absolute( of: nil, amount: nil )
  of.absolute.magnitude( amount )
end
difference( of: nil, amount: nil ) click to toggle source

Constructs a relative magnitude of a given quantity.

# File lib/sy/magnitude.rb, line 16
def difference( of: nil, amount: nil )
  of.relative.magnitude( amount )
end
of( quantity, amount: nil ) click to toggle source

Constructs a magnitude of a given quantity.

# File lib/sy/magnitude.rb, line 22
def of( quantity, amount: nil )
  quantity.magnitude( amount )
end
one( of: nil ) click to toggle source

Magnitude 1 of a given quantity.

# File lib/sy/magnitude.rb, line 34
def one( of: nil )
  absolute of: of, amount: 1
end
zero( of: nil ) click to toggle source

Zero magnitude of a given quantity.

# File lib/sy/magnitude.rb, line 28
def zero( of: nil )
  absolute of: of, amount: 0
end

Public Instance Methods

%(m2) click to toggle source

Percent operator (remainder after division)

# File lib/sy/magnitude.rb, line 177
def % m2
  return magnitude amount % m2.amount if quantity == m2.quantity
  return self % m2.( quantity ) if quantity.coerces? m2.quantity
  apply_through_coerce :%, m2
end
*(m2) click to toggle source

Multiplication.

# File lib/sy/magnitude.rb, line 128
def * m2
  case m2
  when Numeric then
    magnitude amount * m2
  # when SY::ZERO then
  #   return magnitude 0
  when Matrix then
    m2.map { |e| self * e }
  else
    ( quantity * m2.quantity ).magnitude( amount * m2.amount )
  end
end
**(exp) click to toggle source

Exponentiation.

# File lib/sy/magnitude.rb, line 158
def ** exp
  case exp
  when SY::Magnitude then
    raise SY::DimensionError, "Exponent must have zero dimension! " +
      "(exp given)" unless exp.dimension.zero?
    ( quantity ** exp.amount ).magnitude( amount ** exp.amount )
  else
    ( quantity ** exp ).magnitude( amount ** exp )
  end
end
+(m2) click to toggle source

Addition.

# File lib/sy/magnitude.rb, line 112
def + m2
  return magnitude amount + m2.amount if quantity == m2.quantity
  return self + m2.( quantity ) if quantity.coerces? m2.quantity
  apply_through_coerce :+, m2
end
+@() click to toggle source

Reframes the magnitude into its relative quantity.

# File lib/sy/magnitude.rb, line 88
def +@
  quantity.relative.magnitude( amount )
end
-(m2) click to toggle source

Subtraction.

# File lib/sy/magnitude.rb, line 120
def - m2
  return magnitude amount - m2.amount if quantity == m2.quantity
  return self - m2.( quantity ) if quantity.coerces? m2.quantity
  apply_through_coerce :-, m2
end
-@() click to toggle source

Reframes the magnitude into its relative quantity, with negative amount.

# File lib/sy/magnitude.rb, line 94
def -@
  quantity.relative.magnitude( -amount )
end
/(m2) click to toggle source

Division.

# File lib/sy/magnitude.rb, line 143
def / m2
  case m2
  when Numeric then
    magnitude amount / m2
  # when SY::ZERO then
  #   raise ZeroDivisionError, "Attempt to divide #{self} by #{SY::ZERO}."
  when Matrix then
    amount / m2 * quantity.magnitude( 1 )
  else
    ( quantity / m2.quantity ).magnitude( amount / m2.amount )
  end
end
<=>(m2) click to toggle source

Three-way comparison operator of magnitudes.

# File lib/sy/magnitude.rb, line 49
def <=> m2
  return amount <=> m2.amount if quantity == m2.quantity
  return self <=> m2.( quantity ) if quantity.coerces? m2.quantity
  apply_through_coerce :<=>, m2
end
abs() click to toggle source

Absolute value of a magnitude (no reframe).

# File lib/sy/magnitude.rb, line 100
def abs
  magnitude amount.abs
end
absolute() click to toggle source

Computes absolute value and reframes into the absolute quantity.

# File lib/sy/magnitude.rb, line 76
def absolute
  quantity.absolute.magnitude( amount.abs )
end
call(q2) click to toggle source

Reframes a magnitude into a relative version of a given quantity. (If absolute quantity is supplied as an argument, its relative colleague is used to reframe.)

# File lib/sy/magnitude.rb, line 229
def call q2
  case q2
  when SY::Quantity then q2.relative.read self
  when SY::Unit then q2.quantity.relative.read self
  else raise TypeError, "Unable to reframe into a #{q2.class}!" end
end
coerce(m2) click to toggle source

Type coercion for magnitudes.

# File lib/sy/magnitude.rb, line 185
def coerce m2
  if m2.is_a? Numeric then
    return SY::Amount.relative.magnitude( m2 ), self
  elsif m2.is_a? Matrix then
    return m2 * SY::UNIT, self
  elsif quantity.coerces? m2.quantity then
    return m2.( quantity ), self
  else
    raise TypeError, "#{self} cannot be coerced into a #{m2.class}!"
  end
end
eql?(other) click to toggle source

Same magnitudes and same (eql) quantities.

# File lib/sy/magnitude.rb, line 171
def eql? other
  quantity == other.quantity && amount == other.amount
end
in(m2) click to toggle source

Gives the magnitude as a plain number in multiples of another magnitude, supplied as argument. The quantities must match.

# File lib/sy/magnitude.rb, line 200
def in m2
  case m2
  when Symbol, String then
    begin
      self.in eval( "1.#{m2}" ).aT_kind_of SY::Magnitude # digest it
    rescue TypeError
      raise TypeError, "Evaluating 1.#{m2} does not result in a magnitude; " +
        "method collision with another library?"
    end
  when SY::Magnitude then
    quantity.measure( of: m2.quantity ).w.( amount ) / m2.amount
  else
    raise TypeError, "Unexpected type for Magnitude#in method! (#{m2.class})"
  end
end
inspect() click to toggle source

Inspect string of the magnitude

# File lib/sy/magnitude.rb, line 310
def inspect
  "#<#{çς}: #{self} >"
end
negative?() click to toggle source

True if amount is negative. Implicitly false for absolute quantities.

# File lib/sy/magnitude.rb, line 238
def negative?
  amount < 0
end
nonnegative?() click to toggle source

Opposite of negative?. Implicitly true for absolute quantities.

# File lib/sy/magnitude.rb, line 244
def nonnegative?
  amount >= 0
end
reframe(q2) click to toggle source

Reframes a magnitude into a different quantity. Dimension must match.

# File lib/sy/magnitude.rb, line 218
def reframe q2
  case q2
  when SY::Quantity then q2.read self
  when SY::Unit then q2.quantity.read self
  else raise TypeError, "Unable to reframe into a #{q2.class}!" end
end
relative() click to toggle source

Reframes into the relative quantity.

# File lib/sy/magnitude.rb, line 82
def relative
  quantity.relative.magnitude( amount )
end
round(*args) click to toggle source

Rounded value of a Magnitude: A new magnitude with rounded amount.

# File lib/sy/magnitude.rb, line 106
def round *args
  magnitude amount.round( *args )
end
to_magnitude() click to toggle source

Without arguments, it returns a new magnitude equal to self. If argument is given, it is treated as factor, by which the amount is to be muliplied.

# File lib/sy/magnitude.rb, line 317
def to_magnitude
  magnitude( amount )
end
to_s( unit=quantity.units.first || quantity.standard_unit, number_format=default_amount_format ) click to toggle source
# File lib/sy/magnitude.rb, line 267
def to_s( unit=quantity.units.first || quantity.standard_unit,
          number_format=default_amount_format )
  begin
    un = unit.short || unit.name
    if un then
      number = self.in unit
      number_ς = number_format % number
      prefix = ''
      exp = 1
      # unit_presentation = prefix, unit, exp
      unit_ς = SY::SPS.( [ "#{prefix}#{unit.short}" ], [ exp ] )
      [ number_ς, unit_ς ].join '.'
    else
      number = amount
      # otherwise, use units of component quantities
       = quantity.composition.to_hash
      symbols, exponents = .each_with_object Hash.new do |pair, memo|
        qnt, exp = pair
        if qnt.standard_unit.name
          std_unit = qnt.standard_unit
          memo[ std_unit.short || std_unit.name ] = exp
        else
          m = qnt.magnitude( 1 ).to_s
          memo[ m[2..-1] ] = exp
          number = m[0].to_i * number
        end
      end.to_a.transpose
      # assemble SPS
      unit_ς = SY::SPS.( symbols, exponents )
      # interpolate
      number_ς = number_format % number
      return number_ς if unit_ς == '' || unit_ς == 'unit'
      [ number_ς, unit_ς ].join '.'
    end
  rescue
    fail
    number_ς = number_format % amount
    [ number_ς, "unit[#{quantity}]" ].join '.'
  end
end

Private Instance Methods

amount_formatting_precision() click to toggle source
# File lib/sy/magnitude.rb, line 397
def amount_formatting_precision
  @amount_formatting_precision ||= default_amount_formatting_precision
end
apply_through_coerce(operator, operand2) click to toggle source

Applies an operator on self with otherwise incompatible second operand.

# File lib/sy/magnitude.rb, line 407
def apply_through_coerce operator, operand2
  begin
    compat_obj_1, compat_obj_2 = operand2.coerce( self )
  rescue SY::DimensionError
    msg = "Mismatch: #{dimension} #{operator} #{operand2.dimension}!"
    fail SY::DimensionError, msg
  rescue SY::QuantityError
    msg = "Mismatch: #{quantity} #{operator} #{operand2.quantity}!"
    fail SY::QuantityError, msg
  rescue NoMethodError
    fail TypeError, "#{operand2.class} can't be coerced into #{quantity}!"
  else
    compat_obj_1.send( operator, compat_obj_2 )
  end
end
construct_to_s( named_unit=default_named_unit, number_format=default_amount_format ) click to toggle source

The engine for constructing to_s strings.

# File lib/sy/magnitude.rb, line 357
def construct_to_s( named_unit=default_named_unit,
                    number_format=default_amount_format )
  name = named_unit.name.tE "must exist", "the unit name"
  abbrev_or_name = named_unit.short || name
  "#{number_format}.#{ str == '' ? unit : str }" %
    numeric_value_in( unit )
end
default_amount_format() click to toggle source

Default format string for expressing the amount of this magnitude.

# File lib/sy/magnitude.rb, line 393
def default_amount_format
  "%.#{amount_formatting_precision}g"
end
default_amount_formatting_precision() click to toggle source
# File lib/sy/magnitude.rb, line 401
def default_amount_formatting_precision
  3
end
default_named_unit() click to toggle source

Default named unit to be used in expressing this magnitude.

# File lib/sy/magnitude.rb, line 387
def default_named_unit
  standard_unit
end
dim_complaint(obj1=self, obj2) click to toggle source

Error complaint about incompatible dimensions.

# File lib/sy/magnitude.rb, line 375
def dim_complaint obj1=self, obj2
  "#{obj1} not of the same dimension as #{obj2}!"
end
same_dimension?(other) click to toggle source
# File lib/sy/magnitude.rb, line 331
def same_dimension? other
  case other
  when SY::Magnitude then dimension == other.dimension
  when Numeric then dimension.zero?
  when SY::Quantity then dimension == other.dimension
  when SY::Dimension then dimension == other
  else
    raise TErr, "The object (#{other.class} class) does not " +
      "have dimension comparable to SY::Dimension defined"
  end
end
same_quantity?(other) click to toggle source
# File lib/sy/magnitude.rb, line 343
def same_quantity? other
  case other
  when SY::Quantity then quantity == other
  else
    begin
      quantity == other.quantity
    rescue NoMethodError
      raise TypeError, "#{other} does not have quantity!"
    end
  end
end
to_amount_of_standard_quantity() click to toggle source

Gives the amount of standard quantity corresponding to this magnitude, if such conversion is possible.

# File lib/sy/magnitude.rb, line 326
def to_amount_of_standard_quantity
  return amount if quantity.standard?
  amount * quantity.relationship.to_amount_of_standard_quantity
end
to_s_with_unit_using_abbreviation(named_unit=default_named_unit) click to toggle source
# File lib/sy/magnitude.rb, line 365
def to_s_with_unit_using_abbreviation named_unit=default_named_unit
  "%s.#{named_unit.abbreviation}"
end
to_s_with_unit_using_name() click to toggle source
# File lib/sy/magnitude.rb, line 369
def to_s_with_unit_using_name
  # FIXME
end
çς() click to toggle source

String describing this class.

# File lib/sy/magnitude.rb, line 381
def çς
  "Magnitude"
end