auom 0.0.6 → 0.1.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.
- data/.circle.yml +4 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +2 -9
- data/Changelog.md +4 -0
- data/Gemfile +2 -2
- data/Gemfile.devtools +39 -32
- data/auom.gemspec +3 -4
- data/circle.yml +4 -0
- data/config/flay.yml +1 -1
- data/config/{site.reek → reek.yml} +12 -11
- data/config/rubocop.yml +89 -0
- data/lib/auom.rb +7 -325
- data/lib/auom/algebra.rb +13 -10
- data/lib/auom/equalization.rb +6 -2
- data/lib/auom/inspection.rb +22 -57
- data/lib/auom/relational.rb +4 -2
- data/lib/auom/unit.rb +324 -0
- data/spec/shared/incompatible_operation_behavior.rb +3 -1
- data/spec/shared/operation_behavior.rb +3 -2
- data/spec/shared/sunits_shared.rb +3 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/auom/algebra/add_spec.rb +8 -6
- data/spec/unit/auom/algebra/divide_spec.rb +26 -15
- data/spec/unit/auom/algebra/multiply_spec.rb +25 -15
- data/spec/unit/auom/algebra/substract_spec.rb +8 -6
- data/spec/unit/auom/equalization/equality_operator_spec.rb +5 -3
- data/spec/unit/auom/inspection/class_methods/prettify_unit_part_spec.rb +6 -4
- data/spec/unit/auom/inspection/inspect_spec.rb +15 -13
- data/spec/unit/auom/relational/greater_than_or_equal_to_predicate_spec.rb +3 -1
- data/spec/unit/auom/relational/greater_than_predicate_spec.rb +3 -1
- data/spec/unit/auom/relational/less_than_or_equal_to_predicate_spec.rb +3 -1
- data/spec/unit/auom/relational/less_than_predicate_spec.rb +3 -1
- data/spec/unit/auom/unit/assert_same_unit_spec.rb +5 -3
- data/spec/unit/auom/unit/class_methods/convert_spec.rb +8 -6
- data/spec/unit/auom/unit/class_methods/lookup_spec.rb +6 -4
- data/spec/unit/auom/unit/class_methods/new_spec.rb +22 -21
- data/spec/unit/auom/unit/class_methods/try_convert_spec.rb +6 -4
- data/spec/unit/auom/unit/class_methods/units_spec.rb +3 -1
- data/spec/unit/auom/unit/denominators_spec.rb +5 -3
- data/spec/unit/auom/unit/numerators_spec.rb +5 -3
- data/spec/unit/auom/unit/same_unit_predicate_spec.rb +5 -3
- data/spec/unit/auom/unit/scalar_spec.rb +4 -2
- data/spec/unit/auom/unit/unit +0 -0
- data/spec/unit/auom/unit/unit_spec.rb +5 -3
- data/spec/unit/auom/unit/unitless_predicate_spec.rb +9 -1
- metadata +13 -28
data/.circle.yml
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.devtools
CHANGED
@@ -1,55 +1,62 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
group :development do
|
4
|
-
gem 'rake',
|
5
|
-
gem 'rspec',
|
6
|
-
gem '
|
4
|
+
gem 'rake', '~> 10.1.0'
|
5
|
+
gem 'rspec', '~> 2.14.1'
|
6
|
+
gem 'rspec-core', '~> 2.14.8'
|
7
|
+
gem 'yard', '~> 0.8.7'
|
8
|
+
|
9
|
+
platform :rbx do
|
10
|
+
gem 'rubysl-singleton', '~> 2.0.0'
|
11
|
+
end
|
7
12
|
end
|
8
13
|
|
9
14
|
group :yard do
|
10
|
-
gem 'kramdown', '~>
|
15
|
+
gem 'kramdown', '~> 1.3.2'
|
11
16
|
end
|
12
17
|
|
13
18
|
group :guard do
|
14
|
-
gem 'guard', '~>
|
15
|
-
gem 'guard-bundler', '~>
|
16
|
-
gem 'guard-rspec', '~> 2.
|
19
|
+
gem 'guard', '~> 2.4.0'
|
20
|
+
gem 'guard-bundler', '~> 2.0.0'
|
21
|
+
gem 'guard-rspec', '~> 4.2.6'
|
22
|
+
gem 'guard-rubocop', '~> 1.0.2'
|
17
23
|
|
18
24
|
# file system change event handling
|
19
|
-
gem '
|
20
|
-
gem 'rb-
|
21
|
-
gem 'rb-
|
22
|
-
|
23
|
-
gem 'listen', '~> 0.7.3'
|
25
|
+
gem 'listen', '~> 2.5.0'
|
26
|
+
gem 'rb-fchange', '~> 0.0.6', require: false
|
27
|
+
gem 'rb-fsevent', '~> 0.9.3', require: false
|
28
|
+
gem 'rb-inotify', '~> 0.9.0', require: false
|
24
29
|
|
25
30
|
# notification handling
|
26
|
-
gem 'libnotify', '~> 0.8.0', :
|
27
|
-
gem 'rb-notifu', '~> 0.0.4', :
|
28
|
-
gem 'terminal-notifier-guard', '~> 1.5.3', :
|
31
|
+
gem 'libnotify', '~> 0.8.0', require: false
|
32
|
+
gem 'rb-notifu', '~> 0.0.4', require: false
|
33
|
+
gem 'terminal-notifier-guard', '~> 1.5.3', require: false
|
29
34
|
end
|
30
35
|
|
31
36
|
group :metrics do
|
32
|
-
gem '
|
33
|
-
gem '
|
34
|
-
gem '
|
35
|
-
gem '
|
36
|
-
gem '
|
37
|
+
gem 'coveralls', '~> 0.7.0'
|
38
|
+
gem 'flay', '~> 2.4.0'
|
39
|
+
gem 'flog', '~> 4.2.0'
|
40
|
+
gem 'reek', '~> 1.3.2'
|
41
|
+
gem 'rubocop', '~> 0.18.1'
|
42
|
+
gem 'simplecov', '~> 0.8.2'
|
43
|
+
gem 'yardstick', '~> 0.9.9'
|
37
44
|
|
38
|
-
platforms :
|
39
|
-
|
40
|
-
gem '
|
45
|
+
platforms :mri do
|
46
|
+
gem 'mutant', '~> 0.5.7'
|
47
|
+
gem 'mutant-rspec', '~> 0.5.3'
|
41
48
|
end
|
42
49
|
|
43
|
-
platforms :
|
44
|
-
gem '
|
45
|
-
end
|
46
|
-
|
47
|
-
platforms :mri_19 do
|
48
|
-
gem 'simplecov', '~> 0.7.1'
|
50
|
+
platforms :ruby_19, :ruby_20 do
|
51
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
49
52
|
end
|
50
53
|
|
51
|
-
|
52
|
-
gem '
|
54
|
+
platform :rbx do
|
55
|
+
gem 'json', '~> 1.8.1'
|
56
|
+
gem 'racc', '~> 1.4'
|
57
|
+
gem 'rubysl-logger', '~> 2.0.0'
|
58
|
+
gem 'rubysl-open-uri', '~> 2.0.0'
|
59
|
+
gem 'rubysl-prettyprint', '~> 2.0.2'
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
@@ -59,6 +66,6 @@ end
|
|
59
66
|
|
60
67
|
platform :jruby do
|
61
68
|
group :jruby do
|
62
|
-
gem 'jruby-openssl', '~> 0.8.
|
69
|
+
gem 'jruby-openssl', '~> 0.8.5'
|
63
70
|
end
|
64
71
|
end
|
data/auom.gemspec
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'auom'
|
5
|
-
s.version = '0.0
|
5
|
+
s.version = '0.1.0'
|
6
6
|
|
7
7
|
s.authors = ['Markus Schirp']
|
8
|
-
s.email = 'mbj@
|
8
|
+
s.email = 'mbj@schirp-dso.com'
|
9
9
|
s.summary = 'Algebra (with) Units Of Measurement'
|
10
10
|
s.homepage = 'http://github.com/mbj/auom'
|
11
11
|
|
@@ -16,6 +16,5 @@ Gem::Specification.new do |s|
|
|
16
16
|
|
17
17
|
s.rubygems_version = '1.8.10'
|
18
18
|
|
19
|
-
s.add_dependency('
|
20
|
-
s.add_dependency('equalizer', '~> 0.0.5')
|
19
|
+
s.add_dependency('equalizer', '~> 0.0.9')
|
21
20
|
end
|
data/circle.yml
ADDED
data/config/flay.yml
CHANGED
@@ -6,7 +6,7 @@ UncommunicativeParameterName:
|
|
6
6
|
- !ruby/regexp /^.$/
|
7
7
|
- !ruby/regexp /[0-9]$/
|
8
8
|
- !ruby/regexp /[A-Z]/
|
9
|
-
|
9
|
+
TooManyMethods:
|
10
10
|
max_methods: 14
|
11
11
|
enabled: true
|
12
12
|
exclude: []
|
@@ -21,7 +21,7 @@ UncommunicativeMethodName:
|
|
21
21
|
- !ruby/regexp /[A-Z]/
|
22
22
|
LongParameterList:
|
23
23
|
max_params: 2
|
24
|
-
exclude:
|
24
|
+
exclude:
|
25
25
|
- "AUOM::Unit#initialize" # 3 params
|
26
26
|
- "AUOM::Unit#self.new" # 3 params
|
27
27
|
- "AUOM::Unit#self.resolve" # 3 params
|
@@ -48,16 +48,16 @@ UncommunicativeModuleName:
|
|
48
48
|
- !ruby/regexp /[0-9]$/
|
49
49
|
NestedIterators:
|
50
50
|
ignore_iterators: []
|
51
|
-
exclude:
|
51
|
+
exclude:
|
52
52
|
- AUOM::Unit#initialize # 2 levels
|
53
53
|
enabled: true
|
54
54
|
max_allowed_nesting: 1
|
55
|
-
|
56
|
-
max_statements:
|
57
|
-
exclude:
|
55
|
+
TooManyStatements:
|
56
|
+
max_statements: 6
|
57
|
+
exclude:
|
58
58
|
- "AUOM::Inspection#pretty_unit" # 7 statements
|
59
59
|
enabled: true
|
60
|
-
|
60
|
+
DuplicateMethodCall:
|
61
61
|
allow_calls: []
|
62
62
|
exclude:
|
63
63
|
- "AUOM::ClassMethods#new" # invalid detection
|
@@ -78,16 +78,17 @@ UncommunicativeVariableName:
|
|
78
78
|
- !ruby/regexp /^.$/
|
79
79
|
- !ruby/regexp /[0-9]$/
|
80
80
|
- !ruby/regexp /[A-Z]/
|
81
|
-
|
81
|
+
RepeatedConditional:
|
82
82
|
enabled: true
|
83
83
|
max_ifs: 1
|
84
84
|
DataClump:
|
85
85
|
exclude: []
|
86
86
|
enabled: true
|
87
|
-
max_copies:
|
87
|
+
max_copies: 1
|
88
88
|
min_clump_size: 2
|
89
|
-
|
90
|
-
exclude:
|
89
|
+
ControlParameter:
|
90
|
+
exclude:
|
91
|
+
- AUOM::Unit#assert_same_unit
|
91
92
|
enabled: true
|
92
93
|
LongYieldList:
|
93
94
|
max_params: 0
|
data/config/rubocop.yml
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
inherit_from: ../.rubocop.yml
|
2
|
+
|
3
|
+
# General note about rubocop.
|
4
|
+
# It does NOT allow to silence a specific rule violation.
|
5
|
+
# For that reason I sometimes have to disable a whole cop where
|
6
|
+
# I just tried to whitelist a specific occurence.
|
7
|
+
|
8
|
+
|
9
|
+
AllCops:
|
10
|
+
Includes:
|
11
|
+
- '../**/*.rake'
|
12
|
+
- 'Gemfile'
|
13
|
+
- 'Gemfile.triage'
|
14
|
+
- 'mutant.gemspec'
|
15
|
+
|
16
|
+
# Avoid parameter lists longer than five parameters.
|
17
|
+
ParameterLists:
|
18
|
+
Max: 3
|
19
|
+
CountKeywordArgs: true
|
20
|
+
|
21
|
+
# Avoid more than `Max` levels of nesting.
|
22
|
+
BlockNesting:
|
23
|
+
Max: 3
|
24
|
+
|
25
|
+
# Align with the style guide.
|
26
|
+
CollectionMethods:
|
27
|
+
PreferredMethods:
|
28
|
+
collect: 'map'
|
29
|
+
inject: 'reduce'
|
30
|
+
find: 'detect'
|
31
|
+
find_all: 'select'
|
32
|
+
|
33
|
+
MethodLength:
|
34
|
+
CountComments: false
|
35
|
+
Max: 17 # TODO: Bring down to 10
|
36
|
+
|
37
|
+
RegexpLiteral: # I do not agree %r(\A) is more readable than /\A/
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
# Limit line length
|
41
|
+
LineLength:
|
42
|
+
Max: 124 # TODO: lower to 79
|
43
|
+
|
44
|
+
# Disable documentation checking until a class needs to be documented once
|
45
|
+
Documentation:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
# Do not favor modifier if/unless usage when you have a single-line body
|
49
|
+
IfUnlessModifier:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
# Allow case equality operator (in limited use within the specs)
|
53
|
+
CaseEquality:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
# Constants do not always have to use SCREAMING_SNAKE_CASE
|
57
|
+
ConstantName:
|
58
|
+
Enabled: false
|
59
|
+
|
60
|
+
# Not all trivial readers/writers can be defined with attr_* methods
|
61
|
+
TrivialAccessors:
|
62
|
+
Enabled: false
|
63
|
+
|
64
|
+
# And also have a differend opinion here
|
65
|
+
AndOr:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
# I like my raise
|
69
|
+
SignalException:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
# I need to chain optparse builder, else it is more ugly
|
73
|
+
MultilineBlockChain:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
ClassLength:
|
77
|
+
Max: 119
|
78
|
+
|
79
|
+
# I align private keywords with class body
|
80
|
+
IndentationWidth:
|
81
|
+
Enabled: false
|
82
|
+
|
83
|
+
# I like to have an empty line before closing the currently opened body
|
84
|
+
EmptyLinesAroundBody:
|
85
|
+
Enabled: false
|
86
|
+
|
87
|
+
# I like my style more
|
88
|
+
AccessModifierIndentation:
|
89
|
+
Enabled: false
|
data/lib/auom.rb
CHANGED
@@ -1,332 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
require 'rational'
|
2
|
-
require 'backports'
|
3
4
|
require 'equalizer'
|
4
5
|
|
6
|
+
# Library namespace
|
7
|
+
module AUOM
|
8
|
+
end
|
9
|
+
|
5
10
|
require 'auom/algebra'
|
6
11
|
require 'auom/equalization'
|
7
12
|
require 'auom/inspection'
|
8
13
|
require 'auom/relational'
|
9
|
-
|
10
|
-
# Library namespace
|
11
|
-
module AUOM
|
12
|
-
# A scalar with units
|
13
|
-
class Unit
|
14
|
-
include Equalizer.new(:scalar, :numerators, :denominators)
|
15
|
-
include Algebra
|
16
|
-
include Equalization
|
17
|
-
include Inspection
|
18
|
-
include Relational
|
19
|
-
|
20
|
-
# Return scalar
|
21
|
-
#
|
22
|
-
# @example
|
23
|
-
#
|
24
|
-
# include AUOM
|
25
|
-
# m = Unit.new(1, :meter)
|
26
|
-
# m.scalar # => Rational(1, 1)
|
27
|
-
#
|
28
|
-
# @return [Rational]
|
29
|
-
#
|
30
|
-
# @api public
|
31
|
-
#
|
32
|
-
attr_reader :scalar
|
33
|
-
|
34
|
-
# Return numerators
|
35
|
-
#
|
36
|
-
# @example
|
37
|
-
#
|
38
|
-
# include AUOM
|
39
|
-
# m = Unit.new(1, :meter)
|
40
|
-
# m.numerators # => [:meter]
|
41
|
-
#
|
42
|
-
# @return [Rational]
|
43
|
-
#
|
44
|
-
# @api public
|
45
|
-
#
|
46
|
-
attr_reader :numerators
|
47
|
-
|
48
|
-
# Return denominators
|
49
|
-
#
|
50
|
-
# @example
|
51
|
-
#
|
52
|
-
# include AUOM
|
53
|
-
# m = Unit.new(1, :meter)
|
54
|
-
# m.denoninators # => []
|
55
|
-
#
|
56
|
-
# @return [Rational]
|
57
|
-
#
|
58
|
-
# @api public
|
59
|
-
#
|
60
|
-
attr_reader :denominators
|
61
|
-
|
62
|
-
# Return unit descriptor
|
63
|
-
#
|
64
|
-
# @return [Array]
|
65
|
-
#
|
66
|
-
# @api public
|
67
|
-
#
|
68
|
-
# @example
|
69
|
-
#
|
70
|
-
# u = Unit.new(1, [:meter, :meter], :euro)
|
71
|
-
# u.unit # => [[:meter, :meter], [:euro]]
|
72
|
-
#
|
73
|
-
attr_reader :unit
|
74
|
-
|
75
|
-
# These constants can easily be changed
|
76
|
-
# by an application specific subclass that overrides
|
77
|
-
# AUOM::Unit.units with an own hash!
|
78
|
-
UNITS = {
|
79
|
-
:item => [1, :item],
|
80
|
-
:liter => [1, :liter],
|
81
|
-
:pack => [1, :pack],
|
82
|
-
:can => [1, :can],
|
83
|
-
:kilogramm => [1, :kilogramm],
|
84
|
-
:euro => [1, :euro],
|
85
|
-
:meter => [1, :meter],
|
86
|
-
:kilometer => [1000, :meter]
|
87
|
-
}.freeze
|
88
|
-
|
89
|
-
# Return buildin units symbols
|
90
|
-
#
|
91
|
-
# @return [Hash]
|
92
|
-
#
|
93
|
-
# @api private
|
94
|
-
#
|
95
|
-
def self.units
|
96
|
-
UNITS
|
97
|
-
end
|
98
|
-
|
99
|
-
# Check for unitless unit
|
100
|
-
#
|
101
|
-
# @return [true]
|
102
|
-
# return true if unit is unitless
|
103
|
-
#
|
104
|
-
# @return [false]
|
105
|
-
# return false if unit is NOT unitless
|
106
|
-
#
|
107
|
-
# @example
|
108
|
-
#
|
109
|
-
# Unit.new(1).unitless? # => true
|
110
|
-
# Unit.new(1, :meter).unitless ? # => false
|
111
|
-
#
|
112
|
-
# @api public
|
113
|
-
#
|
114
|
-
def unitless?
|
115
|
-
numerators.empty? and denominators.empty?
|
116
|
-
end
|
117
|
-
|
118
|
-
# Test if units are the same
|
119
|
-
#
|
120
|
-
# @param [Unit] other
|
121
|
-
#
|
122
|
-
# @return [true]
|
123
|
-
# if units are the same
|
124
|
-
#
|
125
|
-
# @return [false]
|
126
|
-
# otehrwise
|
127
|
-
#
|
128
|
-
# @example
|
129
|
-
#
|
130
|
-
# a = Unit.new(1)
|
131
|
-
# b = Unit.new(1, :euro)
|
132
|
-
# c = Unit.new(2, :euro)
|
133
|
-
#
|
134
|
-
# a.same_unit?(b) # => false
|
135
|
-
# b.same_unit?(c) # => true
|
136
|
-
#
|
137
|
-
# @api public
|
138
|
-
#
|
139
|
-
def same_unit?(other)
|
140
|
-
other.unit.eql?(unit)
|
141
|
-
end
|
142
|
-
|
143
|
-
# Instancitate a new unit
|
144
|
-
#
|
145
|
-
# @param [Rational] scalar
|
146
|
-
# @param [Enumerable] numerators
|
147
|
-
# @param [Enumerable] denominators
|
148
|
-
#
|
149
|
-
# @return [Unit]
|
150
|
-
#
|
151
|
-
# @example
|
152
|
-
#
|
153
|
-
# # A unitless unit
|
154
|
-
# u = Unit.new(1)
|
155
|
-
# u.unitless? # => true
|
156
|
-
# u.scalar # => Rational(1, 1)
|
157
|
-
#
|
158
|
-
# # A unitless unit from string
|
159
|
-
# u = Unit.new('1.5')
|
160
|
-
# u.unitless? # => true
|
161
|
-
# u.scalar # => Rational(3, 2)
|
162
|
-
#
|
163
|
-
# # A simple unit
|
164
|
-
# u = Unit.new(1, :meter)
|
165
|
-
# u.unitless? # => false
|
166
|
-
# u.numerators # => [:meter]
|
167
|
-
# u.scalar # => Rational(1, 1)
|
168
|
-
#
|
169
|
-
# # A complex unit
|
170
|
-
# u = Unit.new(Rational(1, 3), :euro, :meter)
|
171
|
-
# u.fractions? # => true
|
172
|
-
# u.sclar # => Rational(1, 3)
|
173
|
-
# u.inspect # => <AUOM::Unit @scalar=~0.3333 euro/meter>
|
174
|
-
# u.unit # => [[:euro], [:meter]]
|
175
|
-
#
|
176
|
-
# @api public
|
177
|
-
#
|
178
|
-
def self.new(scalar, numerators=[], denominators=[])
|
179
|
-
scalar = rational(scalar)
|
180
|
-
|
181
|
-
scalar, numerators = resolve([*numerators], scalar, :*)
|
182
|
-
scalar, denominators = resolve([*denominators], scalar, :/)
|
183
|
-
|
184
|
-
# sorting on #to_s as Symbol#<=> is not present on 1.8.7
|
185
|
-
super(scalar, *[numerators, denominators].map { |base| base.sort_by(&:to_s) }).freeze
|
186
|
-
end
|
187
|
-
|
188
|
-
# Assert units are the same
|
189
|
-
#
|
190
|
-
# @param [Unit] other
|
191
|
-
#
|
192
|
-
# @return [self]
|
193
|
-
#
|
194
|
-
# @api private
|
195
|
-
#
|
196
|
-
def assert_same_unit(other)
|
197
|
-
unless same_unit?(other)
|
198
|
-
raise ArgumentError, 'Incompatible units'
|
199
|
-
end
|
200
|
-
|
201
|
-
self
|
202
|
-
end
|
203
|
-
|
204
|
-
# Return converted operand or raise error
|
205
|
-
#
|
206
|
-
# @param [Object] operand
|
207
|
-
#
|
208
|
-
# @return [Unit]
|
209
|
-
#
|
210
|
-
# @raise [ArgumentError]
|
211
|
-
# raises argument error in case operand cannot be converted
|
212
|
-
#
|
213
|
-
# @api private
|
214
|
-
#
|
215
|
-
def self.convert(operand)
|
216
|
-
converted = try_convert(operand)
|
217
|
-
unless converted
|
218
|
-
raise ArgumentError, "Cannot convert #{operand.inspect} to #{self}"
|
219
|
-
end
|
220
|
-
converted
|
221
|
-
end
|
222
|
-
|
223
|
-
# Return converted operand or nil
|
224
|
-
#
|
225
|
-
# @param [Object] operand
|
226
|
-
#
|
227
|
-
# @return [Unit]
|
228
|
-
# return unit in case operand can be converted
|
229
|
-
#
|
230
|
-
# @return [nil]
|
231
|
-
# return nil in case operand can NOT be converted
|
232
|
-
#
|
233
|
-
# @api private
|
234
|
-
#
|
235
|
-
def self.try_convert(operand)
|
236
|
-
case operand
|
237
|
-
when self
|
238
|
-
operand
|
239
|
-
when Fixnum, Rational
|
240
|
-
new(operand)
|
241
|
-
else
|
242
|
-
nil
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
|
247
|
-
private
|
248
|
-
|
249
|
-
# Initialize unit
|
250
|
-
#
|
251
|
-
# @param [Rational] scalar
|
252
|
-
# @param [Enumerable] numerators
|
253
|
-
# @param [Enumerable] denominators
|
254
|
-
#
|
255
|
-
# @api private
|
256
|
-
#
|
257
|
-
def initialize(scalar, numerators, denominators)
|
258
|
-
@scalar = scalar
|
259
|
-
|
260
|
-
[numerators, denominators].permutation do |left, right|
|
261
|
-
left.delete_if { |item| right.delete_at(right.index(item) || right.length) }
|
262
|
-
end
|
263
|
-
|
264
|
-
@numerators = numerators.freeze
|
265
|
-
@denominators = denominators.freeze
|
266
|
-
|
267
|
-
@unit = [@numerators, @denominators].freeze
|
268
|
-
@scalar.freeze
|
269
|
-
end
|
270
|
-
|
271
|
-
# Return rational converted from value
|
272
|
-
#
|
273
|
-
# @param [Object] value
|
274
|
-
#
|
275
|
-
# @return [Rationa]
|
276
|
-
#
|
277
|
-
# @raise [ArgumentError]
|
278
|
-
# raises argument error when cannot be converted to a rational
|
279
|
-
#
|
280
|
-
# @api private
|
281
|
-
#
|
282
|
-
def self.rational(value)
|
283
|
-
case value
|
284
|
-
when Rational
|
285
|
-
value
|
286
|
-
when Fixnum
|
287
|
-
Rational(value)
|
288
|
-
else
|
289
|
-
raise ArgumentError, "#{value.inspect} cannot be converted to rational"
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
private_class_method :rational
|
294
|
-
|
295
|
-
# Resolve unit component
|
296
|
-
#
|
297
|
-
# @param [Enumerable] components
|
298
|
-
# @param [Symbol] operation
|
299
|
-
#
|
300
|
-
# @return [Array]
|
301
|
-
#
|
302
|
-
# @api private
|
303
|
-
#
|
304
|
-
def self.resolve(components, scalar, operation)
|
305
|
-
resolved = components.map do |component|
|
306
|
-
scale, component = lookup(component)
|
307
|
-
scalar = scalar.send(operation, scale)
|
308
|
-
component
|
309
|
-
end
|
310
|
-
[scalar, resolved]
|
311
|
-
end
|
312
|
-
|
313
|
-
private_class_method :resolve
|
314
|
-
|
315
|
-
# Return unit information
|
316
|
-
#
|
317
|
-
# @param [Symbol] value
|
318
|
-
# the unit to search for
|
319
|
-
#
|
320
|
-
# @return [Array]
|
321
|
-
#
|
322
|
-
# @api private
|
323
|
-
#
|
324
|
-
def self.lookup(value)
|
325
|
-
units.fetch(value) do
|
326
|
-
raise ArgumentError, "Unknown unit #{value.inspect}"
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
private_class_method :lookup
|
331
|
-
end
|
332
|
-
end
|
14
|
+
require 'auom/unit'
|