Class: Reality::Measure::Unit
- Inherits:
-
Object
- Object
- Reality::Measure::Unit
- Defined in:
- lib/reality/measure/unit.rb
Constant Summary collapse
- UNIT_REGEX =
/[^\s\+\*\/\/\^²³·]+/
- POWER_REGEX =
/[²³]|\^(\d+)/
- OP_REGEX =
/[\/*·]/
Class Attribute Summary collapse
-
.unicode ⇒ Object
Returns the value of attribute unicode.
Instance Attribute Summary collapse
-
#components ⇒ Object
readonly
Returns the value of attribute components.
Class Method Summary collapse
Instance Method Summary collapse
- #*(other) ⇒ Object
- #-@ ⇒ Object
- #/(other) ⇒ Object
- #==(other) ⇒ Object
-
#initialize(*components) ⇒ Unit
constructor
A new instance of Unit.
- #inspect ⇒ Object
- #scalar? ⇒ Boolean
- #to_s ⇒ Object
Constructor Details
#initialize(*components) ⇒ Unit
Returns a new instance of Unit.
53 54 55 56 57 58 |
# File 'lib/reality/measure/unit.rb', line 53 def initialize(*components) @components = components. group_by{|sig, pow| sig}. map{|sig, cmps| [sig, cmps.map(&:last).inject(:+)]}. reject{|sig, pow| pow.zero?} end |
Class Attribute Details
.unicode ⇒ Object
Returns the value of attribute unicode.
9 10 11 |
# File 'lib/reality/measure/unit.rb', line 9 def unicode @unicode end |
Instance Attribute Details
#components ⇒ Object (readonly)
Returns the value of attribute components.
51 52 53 |
# File 'lib/reality/measure/unit.rb', line 51 def components @components end |
Class Method Details
.parse(str) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/reality/measure/unit.rb', line 15 def parse(str) return str if str.kind_of?(Unit) scanner = StringScanner.new(str) denom = false units = [] loop do # (variable [power] operator) .... unit = scanner.scan(UNIT_REGEX) or fail("Variable expected at #{scanner.rest}") pow = scanner.scan(POWER_REGEX) units << [unit, parse_pow(pow, denom)] break if scanner.eos? op = scanner.scan(OP_REGEX) or fail("Operator expected at #{scanner.rest}") if op == '/' denom and fail("Second division at #{scanner.rest}") denom = true end end new(*units) end |
.parse_pow(p, denom) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/reality/measure/unit.rb', line 38 def parse_pow(p, denom) res = case p when nil then 1 when '²' then 2 when '³' then 3 when /^\^(\d+)$/ then $1.to_i else fail(ArgumentError, "Can't parse power #{p}") end denom ? -res : res end |
Instance Method Details
#*(other) ⇒ Object
72 73 74 75 76 77 |
# File 'lib/reality/measure/unit.rb', line 72 def *(other) other.class == self.class or fail(TypeError, "Can't multiply #{self.class} by #{other.class}") self.class.new(*components, *other.components) end |
#-@ ⇒ Object
68 69 70 |
# File 'lib/reality/measure/unit.rb', line 68 def -@ self.class.new(*components.map{|sig, pow| [sig, -pow]}) end |
#/(other) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/reality/measure/unit.rb', line 79 def /(other) other.class == self.class or fail(TypeError, "Can't divide #{self.class} by #{other.class}") self * -other end |
#==(other) ⇒ Object
60 61 62 |
# File 'lib/reality/measure/unit.rb', line 60 def ==(other) other.class == self.class && other.components == self.components end |
#inspect ⇒ Object
100 101 102 |
# File 'lib/reality/measure/unit.rb', line 100 def inspect "#<#{self.class}(#{to_s})>" end |
#scalar? ⇒ Boolean
64 65 66 |
# File 'lib/reality/measure/unit.rb', line 64 def scalar? components.empty? end |
#to_s ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/reality/measure/unit.rb', line 86 def to_s num, denom = components.partition{|sig, pow| pow > 0} numerator = num.map{|sig, pow| "#{sig}#{power(pow)}"}.join(mul) denominator = denom.map{|sig, pow| "#{sig}#{power(pow)}"}.join(mul) case when numerator.empty? [1, denominator].join('/') when denominator.empty? numerator else [numerator, denominator].join('/') end end |