unitwise 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +5 -10
- data/CHANGELOG.md +38 -0
- data/Gemfile +1 -5
- data/README.md +33 -4
- data/data/base_unit.yaml +2 -2
- data/data/derived_unit.yaml +359 -321
- data/data/prefix.yaml +25 -25
- data/lib/unitwise/atom.rb +33 -4
- data/lib/unitwise/errors.rb +5 -2
- data/lib/unitwise/expression/decomposer.rb +21 -9
- data/lib/unitwise/expression/matcher.rb +3 -8
- data/lib/unitwise/expression/parser.rb +11 -4
- data/lib/unitwise/functional.rb +8 -0
- data/lib/unitwise/measurement.rb +1 -5
- data/lib/unitwise/number.rb +62 -0
- data/lib/unitwise/prefix.rb +0 -6
- data/lib/unitwise/scale.rb +2 -16
- data/lib/unitwise/standard/function.rb +2 -2
- data/lib/unitwise/standard/prefix.rb +4 -3
- data/lib/unitwise/standard/scale.rb +2 -2
- data/lib/unitwise/term.rb +2 -2
- data/lib/unitwise/unit.rb +3 -3
- data/lib/unitwise/version.rb +1 -1
- data/lib/unitwise.rb +14 -1
- data/test/support/scale_tests.rb +16 -22
- data/test/test_helper.rb +1 -2
- data/test/unitwise/atom_test.rb +38 -2
- data/test/unitwise/expression/matcher_test.rb +3 -3
- data/test/unitwise/functional_test.rb +1 -1
- data/test/unitwise/measurement_test.rb +8 -1
- data/test/unitwise/number_test.rb +52 -0
- data/test/unitwise_test.rb +21 -1
- metadata +6 -3
data/data/prefix.yaml
CHANGED
@@ -3,119 +3,119 @@
|
|
3
3
|
:symbol: Y
|
4
4
|
:primary_code: Y
|
5
5
|
:secondary_code: YA
|
6
|
-
:scalar:
|
6
|
+
:scalar: 1000000000000000000000000
|
7
7
|
- :names: zetta
|
8
8
|
:symbol: Z
|
9
9
|
:primary_code: Z
|
10
10
|
:secondary_code: ZA
|
11
|
-
:scalar:
|
11
|
+
:scalar: 1000000000000000000000
|
12
12
|
- :names: exa
|
13
13
|
:symbol: E
|
14
14
|
:primary_code: E
|
15
15
|
:secondary_code: EX
|
16
|
-
:scalar:
|
16
|
+
:scalar: 1000000000000000000
|
17
17
|
- :names: peta
|
18
18
|
:symbol: P
|
19
19
|
:primary_code: P
|
20
20
|
:secondary_code: PT
|
21
|
-
:scalar:
|
21
|
+
:scalar: 1000000000000000
|
22
22
|
- :names: tera
|
23
23
|
:symbol: T
|
24
24
|
:primary_code: T
|
25
25
|
:secondary_code: TR
|
26
|
-
:scalar:
|
26
|
+
:scalar: 1000000000000
|
27
27
|
- :names: giga
|
28
28
|
:symbol: G
|
29
29
|
:primary_code: G
|
30
30
|
:secondary_code: GA
|
31
|
-
:scalar:
|
31
|
+
:scalar: 1000000000
|
32
32
|
- :names: mega
|
33
33
|
:symbol: M
|
34
34
|
:primary_code: M
|
35
35
|
:secondary_code: MA
|
36
|
-
:scalar:
|
36
|
+
:scalar: 1000000
|
37
37
|
- :names: kilo
|
38
38
|
:symbol: k
|
39
39
|
:primary_code: k
|
40
40
|
:secondary_code: K
|
41
|
-
:scalar:
|
41
|
+
:scalar: 1000
|
42
42
|
- :names: hecto
|
43
43
|
:symbol: h
|
44
44
|
:primary_code: h
|
45
45
|
:secondary_code: H
|
46
|
-
:scalar:
|
46
|
+
:scalar: 100
|
47
47
|
- :names: deka
|
48
48
|
:symbol: da
|
49
49
|
:primary_code: da
|
50
50
|
:secondary_code: DA
|
51
|
-
:scalar:
|
51
|
+
:scalar: 10
|
52
52
|
- :names: deci
|
53
53
|
:symbol: d
|
54
54
|
:primary_code: d
|
55
55
|
:secondary_code: D
|
56
|
-
:scalar:
|
56
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e0
|
57
57
|
- :names: centi
|
58
58
|
:symbol: c
|
59
59
|
:primary_code: c
|
60
60
|
:secondary_code: C
|
61
|
-
:scalar: 1e-
|
61
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-1
|
62
62
|
- :names: milli
|
63
63
|
:symbol: m
|
64
64
|
:primary_code: m
|
65
65
|
:secondary_code: M
|
66
|
-
:scalar: 1e-
|
66
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-2
|
67
67
|
- :names: micro
|
68
|
-
:symbol:
|
68
|
+
:symbol: μ
|
69
69
|
:primary_code: u
|
70
70
|
:secondary_code: U
|
71
|
-
:scalar: 1e-
|
71
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-5
|
72
72
|
- :names: nano
|
73
73
|
:symbol: n
|
74
74
|
:primary_code: n
|
75
75
|
:secondary_code: N
|
76
|
-
:scalar: 1e-
|
76
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-8
|
77
77
|
- :names: pico
|
78
78
|
:symbol: p
|
79
79
|
:primary_code: p
|
80
80
|
:secondary_code: P
|
81
|
-
:scalar: 1e-
|
81
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-11
|
82
82
|
- :names: femto
|
83
83
|
:symbol: f
|
84
84
|
:primary_code: f
|
85
85
|
:secondary_code: F
|
86
|
-
:scalar: 1e-
|
86
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-14
|
87
87
|
- :names: atto
|
88
88
|
:symbol: a
|
89
89
|
:primary_code: a
|
90
90
|
:secondary_code: A
|
91
|
-
:scalar: 1e-
|
91
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-17
|
92
92
|
- :names: zepto
|
93
93
|
:symbol: z
|
94
94
|
:primary_code: z
|
95
95
|
:secondary_code: ZO
|
96
|
-
:scalar: 1e-
|
96
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-20
|
97
97
|
- :names: yocto
|
98
98
|
:symbol: y
|
99
99
|
:primary_code: y
|
100
100
|
:secondary_code: YO
|
101
|
-
:scalar: 1e-
|
101
|
+
:scalar: !ruby/object:BigDecimal 18:0.1e-23
|
102
102
|
- :names: kibi
|
103
103
|
:symbol: Ki
|
104
104
|
:primary_code: Ki
|
105
105
|
:secondary_code: KIB
|
106
|
-
:scalar:
|
106
|
+
:scalar: 1024
|
107
107
|
- :names: mebi
|
108
108
|
:symbol: Mi
|
109
109
|
:primary_code: Mi
|
110
110
|
:secondary_code: MIB
|
111
|
-
:scalar:
|
111
|
+
:scalar: 1048576
|
112
112
|
- :names: gibi
|
113
113
|
:symbol: Gi
|
114
114
|
:primary_code: Gi
|
115
115
|
:secondary_code: GIB
|
116
|
-
:scalar:
|
116
|
+
:scalar: 1073741824
|
117
117
|
- :names: tebi
|
118
118
|
:symbol: Ti
|
119
119
|
:primary_code: Ti
|
120
120
|
:secondary_code: TIB
|
121
|
-
:scalar:
|
121
|
+
:scalar: 1099511627776
|
data/lib/unitwise/atom.rb
CHANGED
@@ -7,13 +7,13 @@ module Unitwise
|
|
7
7
|
include Compatible
|
8
8
|
|
9
9
|
class << self
|
10
|
-
# Array of hashes representing atom properties.
|
10
|
+
# Array of hashes representing default atom properties.
|
11
11
|
# @api private
|
12
12
|
def data
|
13
13
|
@data ||= data_files.map { |file| YAML.load(File.open file) }.flatten
|
14
14
|
end
|
15
15
|
|
16
|
-
# Data files containing atom data
|
16
|
+
# Data files containing default atom data
|
17
17
|
# @api private
|
18
18
|
def data_files
|
19
19
|
%w(base_unit derived_unit).map { |type| Unitwise.data_file type }
|
@@ -103,11 +103,11 @@ module Unitwise
|
|
103
103
|
# @return [Numeric]
|
104
104
|
# @api public
|
105
105
|
def scalar(magnitude = 1)
|
106
|
-
base? ?
|
106
|
+
base? ? magnitude : scale.scalar(magnitude)
|
107
107
|
end
|
108
108
|
|
109
109
|
def magnitude(scalar = scalar())
|
110
|
-
special? ? scale.magnitude(scalar) :
|
110
|
+
special? ? scale.magnitude(scalar) : 1
|
111
111
|
end
|
112
112
|
|
113
113
|
# An atom may have a complex scale with several base atoms at various
|
@@ -117,5 +117,34 @@ module Unitwise
|
|
117
117
|
base? ? [Term.new(:atom_code => primary_code)] : scale.root_terms
|
118
118
|
end
|
119
119
|
memoize :root_terms
|
120
|
+
|
121
|
+
|
122
|
+
# A basic validator for atoms. It checks for the bare minimum properties
|
123
|
+
# and that it's scalar and magnitude can be resolved. Note that this method
|
124
|
+
# requires the units it depends on to already exist, so it is not used
|
125
|
+
# when loading the initial data from UCUM.
|
126
|
+
# @return [true] returns true if the atom is valid
|
127
|
+
# @raise [Unitwise::DefinitionError]
|
128
|
+
def validate!
|
129
|
+
missing_properties = %i{primary_code names scale}.select do |prop|
|
130
|
+
val = liner_get(prop)
|
131
|
+
val.nil? || (val.respond_to?(:empty) && val.empty?)
|
132
|
+
end
|
133
|
+
|
134
|
+
if !missing_properties.empty?
|
135
|
+
missing_list = missing_properties.join(',')
|
136
|
+
raise Unitwise::DefinitionError,
|
137
|
+
"Atom has missing properties: #{missing_list}."
|
138
|
+
end
|
139
|
+
|
140
|
+
msg = "Atom definition could not be resolved. Ensure that it is a base " \
|
141
|
+
"unit or is defined relative to existing units."
|
142
|
+
|
143
|
+
begin
|
144
|
+
!scalar.nil? && !magnitude.nil? || raise(Unitwise::DefinitionError, msg)
|
145
|
+
rescue Unitwise::ExpressionError
|
146
|
+
raise Unitwise::DefinitionError, msg
|
147
|
+
end
|
148
|
+
end
|
120
149
|
end
|
121
150
|
end
|
data/lib/unitwise/errors.rb
CHANGED
@@ -5,13 +5,7 @@ module Unitwise
|
|
5
5
|
# of a string, as well as caching the results.
|
6
6
|
class Decomposer
|
7
7
|
|
8
|
-
MODES = [:primary_code, :secondary_code, :names, :slugs, :symbol]
|
9
|
-
|
10
|
-
PARSERS = MODES.reduce({}) do |hash, mode|
|
11
|
-
hash[mode] = Parser.new(mode); hash
|
12
|
-
end
|
13
|
-
|
14
|
-
TRANSFORMER = Transformer.new
|
8
|
+
MODES = [:primary_code, :secondary_code, :names, :slugs, :symbol].freeze
|
15
9
|
|
16
10
|
class << self
|
17
11
|
|
@@ -25,6 +19,16 @@ module Unitwise
|
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
22
|
+
def parsers
|
23
|
+
@parsers ||= MODES.reduce({}) do |hash, mode|
|
24
|
+
hash[mode] = Parser.new(mode); hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def transformer
|
29
|
+
@transformer = Transformer.new
|
30
|
+
end
|
31
|
+
|
28
32
|
private
|
29
33
|
|
30
34
|
# A simple cache to prevent re-decomposing the same units
|
@@ -32,6 +36,14 @@ module Unitwise
|
|
32
36
|
def cache
|
33
37
|
@cache ||= {}
|
34
38
|
end
|
39
|
+
|
40
|
+
# Reset memoized data. Allows rebuilding of parsers, transformers, and
|
41
|
+
# the cache after list of atoms has been modified.
|
42
|
+
def reset
|
43
|
+
@parsers = nil
|
44
|
+
@transformer = nil
|
45
|
+
@cache = nil
|
46
|
+
end
|
35
47
|
end
|
36
48
|
|
37
49
|
attr_reader :expression, :mode
|
@@ -44,7 +56,7 @@ module Unitwise
|
|
44
56
|
end
|
45
57
|
|
46
58
|
def parse
|
47
|
-
|
59
|
+
self.class.parsers.reduce(nil) do |_, (mode, parser)|
|
48
60
|
parsed = parser.parse(expression) rescue next
|
49
61
|
@mode = mode
|
50
62
|
break parsed
|
@@ -52,7 +64,7 @@ module Unitwise
|
|
52
64
|
end
|
53
65
|
|
54
66
|
def transform
|
55
|
-
@transform ||=
|
67
|
+
@transform ||= self.class.transformer.apply(parse, :mode => mode)
|
56
68
|
end
|
57
69
|
|
58
70
|
def terms
|
@@ -5,19 +5,15 @@ module Unitwise
|
|
5
5
|
class Matcher
|
6
6
|
class << self
|
7
7
|
def atom(mode)
|
8
|
-
|
9
|
-
@atom[mode] ||= new(Atom.all, mode).alternative
|
8
|
+
new(Atom.all, mode).alternative
|
10
9
|
end
|
11
10
|
|
12
11
|
def metric_atom(mode)
|
13
|
-
|
14
|
-
@metric_atom[mode] ||=
|
15
|
-
new(Atom.all.select(&:metric?), mode).alternative
|
12
|
+
new(Atom.all.select(&:metric?), mode).alternative
|
16
13
|
end
|
17
14
|
|
18
15
|
def prefix(mode)
|
19
|
-
|
20
|
-
@prefix[mode] ||= new(Prefix.all, mode).alternative
|
16
|
+
new(Prefix.all, mode).alternative
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
@@ -41,7 +37,6 @@ module Unitwise
|
|
41
37
|
def alternative
|
42
38
|
Parslet::Atoms::Alternative.new(*matchers)
|
43
39
|
end
|
44
|
-
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
@@ -5,14 +5,21 @@ module Unitwise
|
|
5
5
|
class Parser < Parslet::Parser
|
6
6
|
attr_reader :key
|
7
7
|
def initialize(key = :primary_code)
|
8
|
-
@key
|
8
|
+
@key = key
|
9
|
+
@atom_matcher = Matcher.atom(key)
|
10
|
+
@metric_atom_matcher = Matcher.metric_atom(key)
|
11
|
+
@prefix_matcher = Matcher.prefix(key)
|
9
12
|
end
|
10
13
|
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :atom_matcher, :metric_atom_matcher, :prefix_matcher
|
17
|
+
|
11
18
|
root :expression
|
12
19
|
|
13
|
-
rule (:atom) {
|
14
|
-
rule (:metric_atom) {
|
15
|
-
rule (:prefix) {
|
20
|
+
rule (:atom) { atom_matcher.as(:atom_code) }
|
21
|
+
rule (:metric_atom) { metric_atom_matcher.as(:atom_code) }
|
22
|
+
rule (:prefix) { prefix_matcher.as(:prefix_code) }
|
16
23
|
|
17
24
|
rule (:simpleton) do
|
18
25
|
(prefix.as(:prefix) >> metric_atom.as(:atom) | atom.as(:atom))
|
data/lib/unitwise/functional.rb
CHANGED
data/lib/unitwise/measurement.rb
CHANGED
@@ -129,7 +129,7 @@ module Unitwise
|
|
129
129
|
# measurement.to_r # => (17/4)
|
130
130
|
# @api public
|
131
131
|
def to_r
|
132
|
-
|
132
|
+
Number.rationalize(value)
|
133
133
|
end
|
134
134
|
|
135
135
|
# Will attempt to convert to a unit by method name.
|
@@ -156,10 +156,6 @@ module Unitwise
|
|
156
156
|
self.class.new(*args)
|
157
157
|
end
|
158
158
|
|
159
|
-
# Set the value for the measurement.
|
160
|
-
# @api private
|
161
|
-
attr_writer :value
|
162
|
-
|
163
159
|
# Determine value of the unit after conversion to another unit
|
164
160
|
# @api private
|
165
161
|
def converted_value(other_unit)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Unitwise
|
2
|
+
class Number
|
3
|
+
# Attempts to coerce a value to the simplest Numeric that fully expresses
|
4
|
+
# it's value. For instance a value of 1.0 would return 1, a value of
|
5
|
+
# #<BigDecimal:7f9558d559b8,'0.45E1',18(18)> would return 4.5.
|
6
|
+
# @api public
|
7
|
+
# @param value [Integer, Float, Rational, String, BigDecimal]
|
8
|
+
# @return [Integer, Float, Rational, BigDecimal]
|
9
|
+
def self.simplify(value)
|
10
|
+
case value
|
11
|
+
when Integer
|
12
|
+
value
|
13
|
+
when Float
|
14
|
+
(i = value.to_i) == value ? i : value
|
15
|
+
when Rational
|
16
|
+
if (i = value.to_i) == value
|
17
|
+
i
|
18
|
+
elsif (f = value.to_f) && f.to_r == value
|
19
|
+
f
|
20
|
+
else
|
21
|
+
value
|
22
|
+
end
|
23
|
+
else # String, BigDecimal, Other
|
24
|
+
s = value.is_a?(String) ? value : value.to_s
|
25
|
+
d = value.is_a?(BigDecimal) ? value : BigDecimal(s)
|
26
|
+
if (i = d.to_i) == d
|
27
|
+
i
|
28
|
+
elsif (f = d.to_f) == d
|
29
|
+
f
|
30
|
+
else
|
31
|
+
d
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Coerces a string-like number to a BigDecimal or Integer as appropriate
|
37
|
+
# @api public
|
38
|
+
# @param value Something that can be represented as a string number
|
39
|
+
# @return [Integer, BigDecimal]
|
40
|
+
def self.coefficify(value)
|
41
|
+
d = BigDecimal.new(value.to_s)
|
42
|
+
if (i = d.to_i) == d
|
43
|
+
i
|
44
|
+
else
|
45
|
+
d
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Coerce a numeric to a Rational, but avoid inaccurate conversions by
|
50
|
+
# jruby. More details here: https://github.com/jruby/jruby/issues/4711.
|
51
|
+
# @api public
|
52
|
+
# @param number [Numeric]
|
53
|
+
# @return Rational
|
54
|
+
def self.rationalize(number)
|
55
|
+
if number.is_a?(BigDecimal) && RUBY_PLATFORM == 'java'
|
56
|
+
number.to_s.to_r
|
57
|
+
else
|
58
|
+
number.to_r
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/unitwise/prefix.rb
CHANGED
data/lib/unitwise/scale.rb
CHANGED
@@ -30,10 +30,6 @@ module Unitwise
|
|
30
30
|
unit.atoms
|
31
31
|
end
|
32
32
|
|
33
|
-
def value=(value)
|
34
|
-
@value = BigDecimal(value.to_s)
|
35
|
-
end
|
36
|
-
|
37
33
|
# List the terms associated with this scale's unit.
|
38
34
|
# @return [Array]
|
39
35
|
# @api public
|
@@ -56,7 +52,7 @@ module Unitwise
|
|
56
52
|
if special?
|
57
53
|
unit.scalar(magnitude)
|
58
54
|
else
|
59
|
-
value * unit.scalar
|
55
|
+
Number.rationalize(value) * Number.rationalize(unit.scalar)
|
60
56
|
end
|
61
57
|
end
|
62
58
|
|
@@ -95,17 +91,7 @@ module Unitwise
|
|
95
91
|
# @return [Numeric]
|
96
92
|
# @api public
|
97
93
|
def simplified_value
|
98
|
-
|
99
|
-
value
|
100
|
-
elsif (i = Integer(value)) == value
|
101
|
-
i
|
102
|
-
elsif value.is_a?(Float) || value.is_a?(Rational)
|
103
|
-
value
|
104
|
-
elsif (f = Float(value)) == value
|
105
|
-
f
|
106
|
-
else
|
107
|
-
value
|
108
|
-
end
|
94
|
+
Unitwise::Number.simplify(value)
|
109
95
|
end
|
110
96
|
memoize :simplified_value
|
111
97
|
|
@@ -12,7 +12,7 @@ module Unitwise::Standard
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def value
|
15
|
-
attributes["function"]["@value"]
|
15
|
+
Unitwise::Number.simplify(attributes["function"]["@value"])
|
16
16
|
end
|
17
17
|
|
18
18
|
def unit
|
@@ -32,4 +32,4 @@ module Unitwise::Standard
|
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end
|
@@ -6,12 +6,13 @@ module Unitwise::Standard
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def scale
|
9
|
-
|
9
|
+
Unitwise::Number.coefficify(
|
10
|
+
attributes.fetch('value').attributes.fetch('value')
|
11
|
+
)
|
10
12
|
end
|
11
13
|
|
12
14
|
def to_hash
|
13
15
|
super().merge(:scalar => scale)
|
14
16
|
end
|
15
|
-
|
16
17
|
end
|
17
|
-
end
|
18
|
+
end
|
@@ -7,7 +7,7 @@ module Unitwise::Standard
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def value
|
10
|
-
nori.attributes
|
10
|
+
Unitwise::Number.coefficify(nori.attributes.fetch('value'))
|
11
11
|
end
|
12
12
|
|
13
13
|
def primary_unit_code
|
@@ -22,4 +22,4 @@ module Unitwise::Standard
|
|
22
22
|
{:value => value, :unit_code => primary_unit_code}
|
23
23
|
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
data/lib/unitwise/term.rb
CHANGED
@@ -59,7 +59,7 @@ module Unitwise
|
|
59
59
|
# @param magnitude [Numeric] The magnitude to calculate the scalar for.
|
60
60
|
# @return [Numeric] The unitless linear scalar value.
|
61
61
|
# @api public
|
62
|
-
def scalar(magnitude = 1
|
62
|
+
def scalar(magnitude = 1)
|
63
63
|
calculate(atom ? atom.scalar(magnitude) : magnitude)
|
64
64
|
end
|
65
65
|
|
@@ -68,7 +68,7 @@ module Unitwise
|
|
68
68
|
# @return [Numeric] The magnitude on this scale.
|
69
69
|
# @api public
|
70
70
|
def magnitude(scalar = scalar())
|
71
|
-
calculate(atom ? atom.magnitude(scalar) : 1
|
71
|
+
calculate(atom ? atom.magnitude(scalar) : 1)
|
72
72
|
end
|
73
73
|
|
74
74
|
# The base units this term is derived from
|
data/lib/unitwise/unit.rb
CHANGED
@@ -86,8 +86,8 @@ module Unitwise
|
|
86
86
|
# @param magnitude [Numeric] An optional magnitude on this unit's scale.
|
87
87
|
# @return [Numeric] A scalar value on a linear scale
|
88
88
|
# @api public
|
89
|
-
def scalar(magnitude = 1
|
90
|
-
terms.reduce(1
|
89
|
+
def scalar(magnitude = 1)
|
90
|
+
terms.reduce(1) do |prod, term|
|
91
91
|
prod * term.scalar(magnitude)
|
92
92
|
end
|
93
93
|
end
|
@@ -98,7 +98,7 @@ module Unitwise
|
|
98
98
|
# @return [Numeric] The equivalent magnitude on this scale
|
99
99
|
# @api public
|
100
100
|
def magnitude(scalar = scalar())
|
101
|
-
terms.reduce(1
|
101
|
+
terms.reduce(1) do |prod, term|
|
102
102
|
prod * term.magnitude(scalar)
|
103
103
|
end
|
104
104
|
end
|
data/lib/unitwise/version.rb
CHANGED
data/lib/unitwise.rb
CHANGED
@@ -8,6 +8,7 @@ require 'bigdecimal'
|
|
8
8
|
require 'unitwise/version'
|
9
9
|
require 'unitwise/base'
|
10
10
|
require 'unitwise/compatible'
|
11
|
+
require 'unitwise/number'
|
11
12
|
require 'unitwise/expression'
|
12
13
|
require 'unitwise/scale'
|
13
14
|
require 'unitwise/functional'
|
@@ -43,7 +44,19 @@ module Unitwise
|
|
43
44
|
false
|
44
45
|
end
|
45
46
|
end
|
46
|
-
|
47
|
+
|
48
|
+
# Add additional atoms. Useful for registering uncommon or custom units.
|
49
|
+
# @param properties [Hash] Properties of the atom
|
50
|
+
# @return [Unitwise::Atom] The newly created atom
|
51
|
+
# @raise [Unitwise::DefinitionError]
|
52
|
+
def self.register(atom_hash)
|
53
|
+
atom = Unitwise::Atom.new(atom_hash)
|
54
|
+
atom.validate!
|
55
|
+
Unitwise::Atom.all.push(atom)
|
56
|
+
Unitwise::Expression::Decomposer.send(:reset)
|
57
|
+
atom
|
58
|
+
end
|
59
|
+
|
47
60
|
# The system path for the installed gem
|
48
61
|
# @api private
|
49
62
|
def self.path
|
data/test/support/scale_tests.rb
CHANGED
@@ -86,32 +86,26 @@ module ScaleTests
|
|
86
86
|
end
|
87
87
|
|
88
88
|
describe "#simplified_value" do
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
result.must_be_kind_of(Integer)
|
94
|
-
end
|
95
|
-
it "should convert from a Float" do
|
96
|
-
result = described_class.new(4.0, 'foot').simplified_value
|
97
|
-
result.must_equal 4
|
98
|
-
result.must_be_kind_of(Integer)
|
99
|
-
end
|
100
|
-
it "should convert from a BigDecimal" do
|
101
|
-
result = described_class.new(BigDecimal("4.5"), "volt").simplified_value
|
102
|
-
result.must_equal 4.5
|
103
|
-
result.must_be_kind_of(Float)
|
104
|
-
end
|
89
|
+
it "must simplify to an Integer" do
|
90
|
+
result = described_class.new(4.0, 'foot').simplified_value
|
91
|
+
result.must_equal 4
|
92
|
+
result.must_be_kind_of(Integer)
|
105
93
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
94
|
+
|
95
|
+
it "must simplify to a Float" do
|
96
|
+
result = described_class.new(BigDecimal("1.5"), 'foot').simplified_value
|
97
|
+
result.must_equal 1.5
|
98
|
+
result.must_be_kind_of(Float)
|
112
99
|
end
|
113
100
|
end
|
114
101
|
|
102
|
+
describe "#inspect" do
|
103
|
+
it "must show the unit and value" do
|
104
|
+
result = described_class.new(12, 'meter').inspect
|
105
|
+
result.must_include("value=12")
|
106
|
+
result.must_include("unit=meter")
|
107
|
+
end
|
108
|
+
end
|
115
109
|
end
|
116
110
|
end
|
117
111
|
end
|
data/test/test_helper.rb
CHANGED
@@ -9,9 +9,8 @@ require 'minitest/pride'
|
|
9
9
|
require 'unitwise'
|
10
10
|
|
11
11
|
module Minitest::Assertions
|
12
|
-
def assert_almost_equal(expected, actual)
|
12
|
+
def assert_almost_equal(expected, actual, range=0.0001)
|
13
13
|
message = "Expected #{actual} to be almost equal to #{expected}"
|
14
|
-
range = 0.00001
|
15
14
|
assert expected + range > actual && expected - range < actual, message
|
16
15
|
end
|
17
16
|
end
|