Class: Quantify::Unit::Compound
- Defined in:
- lib/quantify/unit/compound_unit.rb
Instance Attribute Summary collapse
-
#acts_as_equivalent_unit ⇒ Object
readonly
Returns the value of attribute acts_as_equivalent_unit.
-
#base_units ⇒ Object
readonly
Returns the value of attribute base_units.
Attributes inherited from Base
#acts_as_alternative_unit, #dimensions, #factor, #label, #name, #symbol
Class Method Summary collapse
-
.consolidate_base_units(base_units) ⇒ Object
Consilidates base quantities by finding multiple instances of the same unit type and reducing them into a single unit represenation, by altering the repsective index.
-
.rationalize_base_units(base_units = [], *required_units) ⇒ Object
Make compound unit use consistent units for representing each physical quantity.
Instance Method Summary collapse
-
#cancel_base_units!(*units) ⇒ Object
Cancel base units across numerator and denominator.
-
#consolidate_base_units! ⇒ Object
Consolidate base units.
-
#denominator_units ⇒ Object
Returns an array containing only the base units which have negative indices.
-
#equivalent_known_unit ⇒ Object
Return a known unit which is equivalent to self in terms of its physical quantity (dimensions), factor and scaling attributes (i.e. representing the precise same physical unit but perhaps with different identifiers), e.g.
-
#initialize(*units) ⇒ Compound
constructor
Initialize a compound unit by providing an array containing a represenation of each base unit.
- #is_base_quantity_si_unit? ⇒ Boolean
- #is_non_si_unit? ⇒ Boolean
-
#is_si_unit? ⇒ Boolean
Determine is a unit object represents an SI named unit.
-
#numerator_units ⇒ Object
Returns an array containing only the base units which have positive indices.
-
#or_equivalent ⇒ Object
Returns an equivalent known unit (via #equivalent_known_unit) if it exists.
-
#pluralized_name ⇒ Object
Convenient accessor method for pluralized names.
-
#rationalize_base_units!(scope = :partial, *units) ⇒ Object
Make the base units of self use consistent units for each physical quantity represented.
Methods inherited from Base
#alternatives, #canonical_label=, #coerce, configure, #configure, #configure_as_canonical, construct, construct_and_load, #divide, #has_same_identity_as?, #has_scaling?, #initialize_copy, #is_alternative_for?, #is_base_unit?, #is_benchmark_unit?, #is_compound_unit?, #is_derived_unit?, #is_dimensionless?, #is_equivalent_to?, #is_prefixed_unit?, #load, load, #loaded?, #make_canonical, #measures, #method_missing, #multiply, #pow, prefix_and_load, #reciprocalize, #refresh_identifiers!, #scaling, #si_unit, #to_hash, #unload, #valid?, #valid_descriptors?, #valid_dimensions?, #valid_prefixes, #with_prefix, #with_prefixes
Methods included from ExtendedMethods
Constructor Details
#initialize(*units) ⇒ Compound
Initialize a compound unit by providing an array containing a represenation of each base unit.
Array may contain elements specified as follows:
1. a instance of CompoundBaseUnit
2. an instance of Unit::Base (in which case its index is assumed as 1
3. a sub-array of size 2 containing an instance of Unit::Base and an
explicit index
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/quantify/unit/compound_unit.rb', line 89 def initialize(*units) @base_units = [] units.each do |unit| if unit.is_a? CompoundBaseUnit @base_units << unit elsif unit.is_a? Unit::Base @base_units << CompoundBaseUnit.new(unit) elsif unit.is_a?(Array) && unit.first.is_a?(Unit::Base) && !unit.first.is_a?(Compound) && unit.size == 2 @base_units << CompoundBaseUnit.new(unit.first,unit.last) else raise Exceptions::InvalidArgumentError, "#{unit} does not represent a valid base unit" end end @acts_as_alternative_unit = true @acts_as_equivalent_unit = false consolidate_numerator_and_denominator_units! end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Quantify::Unit::Base
Instance Attribute Details
#acts_as_equivalent_unit ⇒ Object (readonly)
Returns the value of attribute acts_as_equivalent_unit.
75 76 77 |
# File 'lib/quantify/unit/compound_unit.rb', line 75 def acts_as_equivalent_unit @acts_as_equivalent_unit end |
#base_units ⇒ Object (readonly)
Returns the value of attribute base_units.
75 76 77 |
# File 'lib/quantify/unit/compound_unit.rb', line 75 def base_units @base_units end |
Class Method Details
.consolidate_base_units(base_units) ⇒ Object
Consilidates base quantities by finding multiple instances of the same unit type and reducing them into a single unit represenation, by altering the repsective index. It has the effect of raising units to powers and cancelling those which appear in the numerator AND denominator
This is a class method which takes an arbitrary array of base units as an argument. This means that consolidation can be performed on either all base units or just a subset - the numerator or denominator units.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/quantify/unit/compound_unit.rb', line 34 def self.consolidate_base_units(base_units) raise Exceptions::InvalidArgumentError, "Must provide an array of base units" unless base_units.is_a? Array new_base_units = [] while base_units.size > 0 do new_base = base_units.shift next if new_base.unit.is_dimensionless? new_base.index = base_units.select do |other_base| new_base.unit.is_equivalent_to? other_base.unit end.inject(new_base.index) do |index,other_base| base_units.delete other_base index += other_base.index end new_base_units << new_base unless new_base.is_dimensionless? end return new_base_units end |
.rationalize_base_units(base_units = [], *required_units) ⇒ Object
Make compound unit use consistent units for representing each physical quantity. For example, lb/kg => kg/kg.
This is a class method which takes an arbitrary array of base units as an argument. This means that consolidation can be performed on either all base units or just a subset - e.g. the numerator or denominator units.
The units to use for particular physical dimension can be specified following the inital argument. If no unit is specified for a physical quantity which is represented in the array of base units, then the first unit found for that physical quantity is used as the canonical one.
67 68 69 70 71 72 73 |
# File 'lib/quantify/unit/compound_unit.rb', line 67 def self.rationalize_base_units(base_units=[],*required_units) base_units.each do |base| new_unit = required_units.map { |unit| Unit.for(unit) }.find { |unit| unit.measures == base.measures } || base_units.find { |unit| unit.measures == base.measures }.unit base.unit = new_unit end end |
Instance Method Details
#cancel_base_units!(*units) ⇒ Object
Cancel base units across numerator and denominator. If similar units occur in both the numerator and denominator, they can be cancelled, i.e. their powers reduced correspondingly until one is removed.
This method is useful when wanting to remove specific units that can be cancelled from the compound unit configuration while retaining the remaining units in the current format.
If no other potentially cancelable units need to be retained, the method #consolidate_base_units! can be called with the :full argument instead
This method takes an arbitrary number of arguments which represent the units which are required to be cancelled (string, symbol or object)
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/quantify/unit/compound_unit.rb', line 163 def cancel_base_units!(*units) units.each do |unit| raise Exceptions::InvalidArgumentError, "Cannot cancel by a compound unit" if unit.is_a? Unit::Compound unit = Unit.for unit unless unit.is_a? Unit::Base numerator_unit = numerator_units.find { |base| unit.is_equivalent_to? base.unit } denominator_unit = denominator_units.find { |base| unit.is_equivalent_to? base.unit } if numerator_unit && denominator_unit cancel_value = [numerator_unit.index,denominator_unit.index].min.abs numerator_unit.index -= cancel_value denominator_unit.index += cancel_value end end consolidate_numerator_and_denominator_units! end |
#consolidate_base_units! ⇒ Object
Consolidate base units. A ‘full’ consolidation is performed, i.e. consolidation across numerator and denominator. This is equivalent to the automatic partial consolidation AND a cancelling of units (i.e. #cancel_base_units!)
143 144 145 146 147 |
# File 'lib/quantify/unit/compound_unit.rb', line 143 def consolidate_base_units! @base_units = Compound.consolidate_base_units(@base_units) initialize_attributes return self end |
#denominator_units ⇒ Object
Returns an array containing only the base units which have negative indices
115 116 117 |
# File 'lib/quantify/unit/compound_unit.rb', line 115 def denominator_units @base_units.select { |base| base.is_denominator? } end |
#equivalent_known_unit ⇒ Object
Return a known unit which is equivalent to self in terms of its physical quantity (dimensions), factor and scaling attributes (i.e. representing the precise same physical unit but perhaps with different identifiers), e.g.
((Unit.kg*(Unit.m**"))/(Unit.s**2)).equivalent_known_unit.name
#=> "joule"
212 213 214 215 216 |
# File 'lib/quantify/unit/compound_unit.rb', line 212 def equivalent_known_unit Unit.units.find do |unit| self.is_equivalent_to?(unit) && !unit.is_compound_unit? end end |
#is_base_quantity_si_unit? ⇒ Boolean
134 135 136 |
# File 'lib/quantify/unit/compound_unit.rb', line 134 def is_base_quantity_si_unit? @base_units.all? { |base| base.is_base_quantity_si_unit? } end |
#is_non_si_unit? ⇒ Boolean
130 131 132 |
# File 'lib/quantify/unit/compound_unit.rb', line 130 def is_non_si_unit? @base_units.any? { |base| base.is_non_si_unit? } end |
#is_si_unit? ⇒ Boolean
Determine is a unit object represents an SI named unit.
126 127 128 |
# File 'lib/quantify/unit/compound_unit.rb', line 126 def is_si_unit? @base_units.all? { |base| base.is_si_unit? } end |
#numerator_units ⇒ Object
Returns an array containing only the base units which have positive indices
110 111 112 |
# File 'lib/quantify/unit/compound_unit.rb', line 110 def numerator_units @base_units.select { |base| base.is_numerator? } end |
#or_equivalent ⇒ Object
Returns an equivalent known unit (via #equivalent_known_unit) if it exists. Otherwise, returns false.
221 222 223 224 225 226 227 228 |
# File 'lib/quantify/unit/compound_unit.rb', line 221 def or_equivalent equivalent_unit = equivalent_known_unit if equivalent_unit && equivalent_unit.acts_as_equivalent_unit return equivalent_unit else return self end end |
#pluralized_name ⇒ Object
Convenient accessor method for pluralized names
120 121 122 |
# File 'lib/quantify/unit/compound_unit.rb', line 120 def pluralized_name derive_name :plural end |
#rationalize_base_units!(scope = :partial, *units) ⇒ Object
Make the base units of self use consistent units for each physical quantity represented. For example, lb/kg => kg/kg.
By default, units are rationalized within the the numerator and denominator respectively. That is, different units representing the same physical quantity may appear across the numerator and denominator, but not within each. To fully rationalize the base units of self, pass in the symbol :full as a first argument. Otherwise :partial is passed as the default.
The units to use for particular physical dimension can be specified following the inital argument. If no unit is specified for a physical quantity which is represented in the array of base units, then the first unit found for that physical quantity is used as the canonical one.
194 195 196 197 198 199 200 201 202 |
# File 'lib/quantify/unit/compound_unit.rb', line 194 def rationalize_base_units!(scope=:partial,*units) if scope == :full Compound.rationalize_base_units(@base_units,*units) else Compound.rationalize_base_units(numerator_units,*units) Compound.rationalize_base_units(denominator_units,*units) end consolidate_numerator_and_denominator_units! end |