class SY::Quantity
Constants
- RELATIVE_QUANTITY_NAME_SUFFIX
Attributes
Public Class Methods
Dimensionless quantity constructor alias.
# File lib/sy/quantity.rb, line 42 def dimensionless *args ꜧ = args.extract_options! raise TErr, "Dimension not zero!" unless ꜧ[:dimension].zero? if ꜧ.has? :dimension, syn!: :of new( *( args << ꜧ.merge!( of: SY::Dimension.zero ) ) ).protect! end
Standard constructor of a metrological quantity. A quantity may have a name and a dimension.
# File lib/sy/quantity.rb, line 54 def initialize( relative: nil, composition: nil, of: nil, measure: nil, amount: nil, coerces: [], coerces_to: [], **nn ) @units = [] # array of units as favored by this quantity @relative = relative if composition.nil? then @dimension = SY.Dimension( of ) else @composition = SY::Composition[ composition ] @dimension = @composition.dimension end @measure = measure.is_a?( SY::Measure ) ? measure : if measure.nil? then if amount.nil? then nil else SY::Measure.simple_scale( amount ) end else fail ArgumentError, ":amount and :measure shouldn't be both supplied" unless amount.nil? SY::Measure.simple_scale( measure ) end coerces( *Array( coerces ) ) Array( coerces_to ).each { |qnt| qnt.coerces self } end
Dimension-based quantity constructor. Examples: Quantity.of Dimension.new( "L.T⁻²" )
Quantity.of "L.T⁻²"
# File lib/sy/quantity.rb, line 18 def of *args ꜧ = args.extract_options! dim = case args.size when 0 then ꜧ.must_have :dimension ꜧ.delete :dimension else args.shift end args << ꜧ.merge!( of: SY::Dimension.new( dim ) ) return new( *args ).protect! end
Standard quantity. Example: Quantity.standard of: Dimension.new( "L.T⁻²" )
or <tt>Quantity.standard of: “L.T⁻²” (Both should give Acceleration as their result.)
# File lib/sy/quantity.rb, line 35 def standard( of: nil ) fail ArgumentError, "Dimension (:of argument) must be given!" if of.nil? return SY.Dimension( of ).standard_quantity end
Public Instance Methods
Quantity
multiplication.
# File lib/sy/quantity.rb, line 289 def * q2 rel = [ self, q2 ].any? &:relative ( SY::Composition[ self => 1 ] + SY::Composition[ q2 => 1 ] ) .to_quantity relative: rel end
Quantity
raising to a number.
# File lib/sy/quantity.rb, line 305 def ** num SY::Composition[ self => num ].to_quantity relative: relative? end
Quantity
division.
# File lib/sy/quantity.rb, line 297 def / q2 rel = [ self, q2 ].any? &:relative? ( SY::Composition[ self => 1 ] - SY::Composition[ q2 => 1 ] ) .to_quantity relative: rel end
Absolute quantity related to this quantity.
# File lib/sy/quantity.rb, line 239 def absolute absolute? ? self : colleague end
Is the quantity absolute? (Opposite of relative?
)
# File lib/sy/quantity.rb, line 205 def absolute? not relative? end
# File lib/sy/quantity.rb, line 351 def coerce other case other when Numeric then return SY::Amount.relative, self when SY::Quantity then # By default, coercion between quantities doesn't exist. The basic # purpose of having quantities is to avoid mutual mixing of # incompatible magnitudes, as in "one cannot sum pears with apples". # if other == self then return other, self else raise SY::QuantityError, "#{other} and #{self} do not mix!" end else raise TErr, "#{self} cannot be coerced into a #{other.class}!" end end
Quantities explicitly coerced by this quantity.
# File lib/sy/quantity.rb, line 94 def coerces *other_quantities if other_quantities.empty? then @coerces ||= [] else other_quantities.each { |qnt| coerces << qnt } end end
Is the quantity supplied as the argument coerced by this quantity?
# File lib/sy/quantity.rb, line 102 def coerces? other other == self || coerces.include?( other ) || colleague.coerces.include?( other.colleague ) || if simple? then false else composition.coerces? other.composition end end
For an absolute quantity, colleague is the corresponding relative quantity. Vice-versa, for a relative quantity, colleague is its absolute quantity.
# File lib/sy/quantity.rb, line 218 def colleague @colleague ||= construct_colleague end
Is the quantity dimensionless?
# File lib/sy/quantity.rb, line 311 def dimensionless? dimension.zero? end
Inspect string.
# File lib/sy/quantity.rb, line 347 def inspect "#<Quantity:#{to_s}>" end
Irreducible quantity is one which cannot or should not be reduced to its components in the process of quantity simplification.
# File lib/sy/quantity.rb, line 136 def irreducible? simple? or protected? end
Constructs a absolute magnitude of this quantity.
# File lib/sy/quantity.rb, line 251 def magnitude amount Magnitude().new( of: self, amount: amount ) end
Creates a measure of a specified other quantity. If no :of is specified, simply acts as a getter of @measure attribute.
# File lib/sy/quantity.rb, line 183 def measure( of: nil ) return @measure if of.nil? # act as simple getter if :of not specified return SY::Measure.identity if of == self or of == colleague fail SY::DimensionError, "#{self} vs. #{of}!" unless same_dimension? of return of.measure( of: of.standard ).inverse if standardish? m = begin measure || colleague.measure || composition.infer_measure rescue NoMethodError fail SY::QuantityError, "Measure of #{of} by #{self} impossible!" end return m if of.standardish? return m * standard.measure( of: of ) end
Constructor of a new standard unit (replacing current @standard_unit). For standard units, amount is implicitly 1. So :amount argument here has different meaning – it sets the measure of the quantity. Measure can also be specified more explicitly by :measure named argument.
# File lib/sy/quantity.rb, line 268 def new_standard_unit( amount: nil, measure: nil, **nn ) explain_amount_of_standard_units if amount.is_a? Numeric # n00b help # For standard units, amount has special meaning of setting up mapping. if measure then raise ArgumentError, "When :measure is specified, :amount must not be " + "expliticly specified." unless amount.nil? raise TypeError, ":measure argument must be a SY::Measure!" unless measure.is_a? SY::Measure set_measure( measure ) else set_measure( SY::Measure.simple_scale( amount.nil? ? 1 : amount.amount ) ) end # Replace @standard_unit with the newly constructed unit. Unit().instance_variable_set( :@standard, unit( **nn ).tap do |u| ( units.unshift u ).uniq! end ) end
Protects quantity from decomposition.
# File lib/sy/quantity.rb, line 119 def protect! @protected = true @composition ||= SY::Composition.singular self return self end
Protected quantity is not allowed to be decomposed in the process of quantity simplification.
# File lib/sy/quantity.rb, line 113 def protected? @protected end
Converts magnitude of another quantity to a magnitude of this quantity.
# File lib/sy/quantity.rb, line 167 def read magnitude_of_other_quantity other_quantity = magnitude_of_other_quantity.quantity other_amount = magnitude_of_other_quantity.amount magnitude measure( of: other_quantity ).r.( other_amount ) end
Relative quantity related to this quantity.
# File lib/sy/quantity.rb, line 211 def relative relative? ? self : colleague end
Is the quantity relative?
# File lib/sy/quantity.rb, line 199 def relative? @relative ? true : false end
Acts as colleague setter.
# File lib/sy/quantity.rb, line 224 def set_colleague q2 raise SY::DimensionError, "Mismatch: #{self}, #{q2}!" unless same_dimension? q2 raise SY::QuantityError, "#{self} an #{q2} are both " + "{relative? ? 'relative' : 'absolute'}!" if relative? == q2.relative? if measure && q2.measure then raise SY::QuantityError, "Measure mismatch: #{self}, #{q2}!" unless measure == q2.measure end @colleague = q2 q2.instance_variable_set :@colleague, self end
Acts as composition setter (dimension must match).
# File lib/sy/quantity.rb, line 149 def set_composition comp @composition = SY::Composition[ comp ] .aT "composition, when redefined after initialization,", "match the dimension" do |comp| comp.dimension == dimension end end
Acts as setter of measure (of the pertinent standard quantity).
# File lib/sy/quantity.rb, line 157 def set_measure measure @measure = if measure.is_a?( SY::Measure ) then measure else SY::Measure.simple_scale( measure ) end end
Simple quantity is one with simple composition. If nontrivial composition is known for the colleague, it is assumed that the same composition would apply for this quantity, so it is not simple.
# File lib/sy/quantity.rb, line 87 def simple? cᴍ = composition cᴍ.empty? || cᴍ.singular? && cᴍ.first[0] == self end
Returns the standard quantity for this quantity's dimension.
# File lib/sy/quantity.rb, line 323 def standard dimension.standard_quantity end
Make the quantity standard for its dimension.
# File lib/sy/quantity.rb, line 317 def standard! SY::Dimension.standard_quantities[ dimension ] = self end
Is the dimension standard?
# File lib/sy/quantity.rb, line 329 def standard? self == standard end
Reader of standard unit.
# File lib/sy/quantity.rb, line 245 def standard_unit Unit().standard end
Is the dimension or its colleague standard?
# File lib/sy/quantity.rb, line 335 def standardish? standard? || colleague.standard? end
A string briefly describing the quantity.
# File lib/sy/quantity.rb, line 341 def to_s name.nil? ? "[#{dimension}]" : name.to_s end
Constructs a new unit of this quantity.
# File lib/sy/quantity.rb, line 257 def unit **nn u = Unit().new( nn.update( of: self ) ) ( units << u ).uniq! # Add it to @units array. return u end
Unprotects quantity from decomposition.
# File lib/sy/quantity.rb, line 127 def unprotect! @protected = false @composition = nil if @composition == SY::Composition.singular( self ) return self end
Converts an amount of this quantity to a magnitude of other quantity.
# File lib/sy/quantity.rb, line 175 def write amount_of_this_quantity, other_quantity measure( of: other_quantity ) .write( magnitude( amount_of_this_quantity ), other_quantity ) end
Private Instance Methods
# File lib/sy/quantity.rb, line 437 def construct_colleague ɴ = name ʀsuffix = SY::Quantity::RELATIVE_QUANTITY_NAME_SUFFIX rel = relative? # Here, it is impossible to rely on Composition::QUANTITY_TABLE – # on the contrary, the table relies on Quantity#colleague. constr_ɴ = ->( ɴ, ʀ ) { ç.new composition: composition, ɴ: ɴ, relative: ʀ } constr_anon = ->( ʀ ) { ç.new composition: composition, relative: ʀ } # enough of preliminaries if not rel then inst = ɴ ? constr_ɴ.( "#{ɴ}#{ʀsuffix}", true ) : constr_anon.( true ) inst.aT &:relative? elsif ɴ.to_s.ends_with?( ʀsuffix ) && ɴ.size > ʀsuffix.size inst = constr_ɴ.( ɴ.to_s[0..ɴ.size-ʀsuffix.size-1], false ) inst.aT &:absolute? else inst = constr_anon.( false ).aT &:absolute? end inst.instance_variable_set :@colleague, self return inst end
# File lib/sy/quantity.rb, line 461 def explain_amount_of_standard_units raise TypeError, "For standard units, :amount is 1, by definition. When" + ":amount parameter is supplied to a standard unit constructor, its" + "meaning is different: Using a magnitude of the same dimension, but" + "different quantity, it establishes conversion relationship between" + "the two quantities." end
# File lib/sy/quantity.rb, line 457 def same_dimension? other dimension == other.dimension end