auom 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +2 -6
- data/.travis.yml +5 -2
- data/Changelog.md +5 -1
- data/Gemfile +0 -5
- data/README.md +17 -22
- data/TODO +1 -1
- data/auom.gemspec +14 -14
- data/circle.yml +3 -0
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +2 -1
- data/config/rubocop.yml +130 -34
- data/lib/auom.rb +0 -2
- data/lib/auom/algebra.rb +5 -7
- data/lib/auom/equalization.rb +0 -2
- data/lib/auom/inspection.rb +26 -23
- data/lib/auom/relational.rb +2 -4
- data/lib/auom/unit.rb +15 -17
- data/spec/shared/incompatible_operation_behavior.rb +0 -2
- data/spec/shared/operation_behavior.rb +5 -4
- data/spec/shared/sunits_shared.rb +0 -2
- data/spec/spec_helper.rb +1 -4
- data/spec/unit/auom/algebra/add_spec.rb +12 -16
- data/spec/unit/auom/algebra/divide_spec.rb +50 -52
- data/spec/unit/auom/algebra/multiply_spec.rb +17 -21
- data/spec/unit/auom/algebra/substract_spec.rb +4 -8
- data/spec/unit/auom/equalization/equality_operator_spec.rb +3 -7
- data/spec/unit/auom/inspection/class_methods/prettify_unit_part_spec.rb +7 -7
- data/spec/unit/auom/inspection/inspect_spec.rb +1 -5
- data/spec/unit/auom/relational/greater_than_or_equal_to_predicate_spec.rb +0 -4
- data/spec/unit/auom/relational/greater_than_predicate_spec.rb +0 -4
- data/spec/unit/auom/relational/less_than_or_equal_to_predicate_spec.rb +0 -4
- data/spec/unit/auom/relational/less_than_predicate_spec.rb +0 -4
- data/spec/unit/auom/unit/assert_same_unit_spec.rb +2 -6
- data/spec/unit/auom/unit/class_methods/convert_spec.rb +0 -4
- data/spec/unit/auom/unit/class_methods/lookup_spec.rb +2 -6
- data/spec/unit/auom/unit/class_methods/new_spec.rb +16 -21
- data/spec/unit/auom/unit/class_methods/try_convert_spec.rb +0 -4
- data/spec/unit/auom/unit/class_methods/units_spec.rb +0 -4
- data/spec/unit/auom/unit/denominators_spec.rb +0 -4
- data/spec/unit/auom/unit/numerators_spec.rb +0 -4
- data/spec/unit/auom/unit/same_unit_predicate_spec.rb +1 -5
- data/spec/unit/auom/unit/scalar_spec.rb +0 -4
- data/spec/unit/auom/unit/unit_spec.rb +0 -4
- data/spec/unit/auom/unit/unitless_predicate_spec.rb +0 -4
- metadata +29 -22
- data/Gemfile.devtools +0 -71
- data/Guardfile +0 -8
data/lib/auom/equalization.rb
CHANGED
data/lib/auom/inspection.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module AUOM
|
4
2
|
# Inspection module for auom units
|
5
3
|
module Inspection
|
4
|
+
|
5
|
+
INSPECT_FORMAT = '<%s @scalar=%s%s>'.freeze
|
6
|
+
SCALAR_FORMAT = '~%0.4f'.freeze
|
7
|
+
UNIT_FORMAT = ' %s/%s'.freeze
|
8
|
+
|
6
9
|
# Return inspectable representation
|
7
10
|
#
|
8
11
|
# @return [String]
|
@@ -10,12 +13,24 @@ module AUOM
|
|
10
13
|
# @api private
|
11
14
|
#
|
12
15
|
def inspect
|
13
|
-
|
16
|
+
format(INSPECT_FORMAT, self.class, pretty_scalar, pretty_unit)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return prettified units
|
20
|
+
#
|
21
|
+
# @param [Array] base
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def self.prettify_unit_part(base)
|
28
|
+
counts(base).map { |unit, length| length > 1 ? "#{unit}^#{length}" : unit }.join('*')
|
14
29
|
end
|
15
30
|
|
16
31
|
private
|
17
32
|
|
18
|
-
# Return
|
33
|
+
# Return prettified scalar
|
19
34
|
#
|
20
35
|
# @return [String]
|
21
36
|
#
|
@@ -23,13 +38,13 @@ module AUOM
|
|
23
38
|
#
|
24
39
|
def pretty_scalar
|
25
40
|
if reminder?
|
26
|
-
|
41
|
+
format(SCALAR_FORMAT, scalar)
|
27
42
|
else
|
28
|
-
scalar.
|
43
|
+
scalar.to_int
|
29
44
|
end
|
30
45
|
end
|
31
46
|
|
32
|
-
# Return
|
47
|
+
# Return prettified unit part
|
33
48
|
#
|
34
49
|
# @return [String]
|
35
50
|
# if there is a prettifiable unit part
|
@@ -42,15 +57,15 @@ module AUOM
|
|
42
57
|
def pretty_unit
|
43
58
|
return if unitless?
|
44
59
|
|
45
|
-
numerator = Inspection.prettify_unit_part(
|
46
|
-
denominator = Inspection.prettify_unit_part(
|
60
|
+
numerator = Inspection.prettify_unit_part(numerators)
|
61
|
+
denominator = Inspection.prettify_unit_part(denominators)
|
47
62
|
|
48
63
|
numerator = '1' if numerator.empty?
|
49
64
|
if denominator.empty?
|
50
65
|
return " #{numerator}"
|
51
66
|
end
|
52
67
|
|
53
|
-
|
68
|
+
format(UNIT_FORMAT, numerator, denominator)
|
54
69
|
end
|
55
70
|
|
56
71
|
# Test if scalar has and reminder in decimal representation
|
@@ -67,18 +82,6 @@ module AUOM
|
|
67
82
|
!(scalar % scalar.denominator).zero?
|
68
83
|
end
|
69
84
|
|
70
|
-
# Return prettified units
|
71
|
-
#
|
72
|
-
# @param [Array] base
|
73
|
-
#
|
74
|
-
# @return [String]
|
75
|
-
#
|
76
|
-
# @api private
|
77
|
-
#
|
78
|
-
def self.prettify_unit_part(base)
|
79
|
-
counts(base).map { |unit, length| length > 1 ? "#{unit}^#{length}" : unit }.join('*')
|
80
|
-
end
|
81
|
-
|
82
85
|
# Return unit counts
|
83
86
|
#
|
84
87
|
# @param [Array] base
|
@@ -91,7 +94,7 @@ module AUOM
|
|
91
94
|
counts = base.each_with_object(Hash.new(0)) { |unit, hash| hash[unit] += 1 }
|
92
95
|
counts.sort do |left, right|
|
93
96
|
result = right.last <=> left.last
|
94
|
-
if result
|
97
|
+
if result.equal?(0)
|
95
98
|
left.first <=> right.first
|
96
99
|
else
|
97
100
|
result
|
data/lib/auom/relational.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module AUOM
|
4
2
|
# Mixin to add relational operators
|
5
3
|
module Relational
|
@@ -21,7 +19,7 @@ module AUOM
|
|
21
19
|
end
|
22
20
|
alias_method :<=, :less_than_or_equal_to?
|
23
21
|
|
24
|
-
# Test if unit is greater than or equal
|
22
|
+
# Test if unit is greater than or equal to other
|
25
23
|
#
|
26
24
|
# @param [Unit] other
|
27
25
|
#
|
@@ -74,7 +72,7 @@ module AUOM
|
|
74
72
|
|
75
73
|
private
|
76
74
|
|
77
|
-
#
|
75
|
+
# Perform relational operation
|
78
76
|
#
|
79
77
|
# @param [Unit] other
|
80
78
|
# @param [Symbol] operation
|
data/lib/auom/unit.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module AUOM
|
4
2
|
# A scalar with units
|
5
3
|
class Unit
|
@@ -43,7 +41,7 @@ module AUOM
|
|
43
41
|
#
|
44
42
|
# include AUOM
|
45
43
|
# m = Unit.new(1, :meter)
|
46
|
-
# m.
|
44
|
+
# m.denominators # => []
|
47
45
|
#
|
48
46
|
# @return [Rational]
|
49
47
|
#
|
@@ -78,7 +76,7 @@ module AUOM
|
|
78
76
|
kilometer: [1000, :meter]
|
79
77
|
}.freeze
|
80
78
|
|
81
|
-
# Return
|
79
|
+
# Return built-in units symbols
|
82
80
|
#
|
83
81
|
# @return [Hash]
|
84
82
|
#
|
@@ -115,7 +113,7 @@ module AUOM
|
|
115
113
|
# if units are the same
|
116
114
|
#
|
117
115
|
# @return [false]
|
118
|
-
#
|
116
|
+
# otherwise
|
119
117
|
#
|
120
118
|
# @example
|
121
119
|
#
|
@@ -132,7 +130,7 @@ module AUOM
|
|
132
130
|
other.unit.eql?(unit)
|
133
131
|
end
|
134
132
|
|
135
|
-
#
|
133
|
+
# Instantiate a new unit
|
136
134
|
#
|
137
135
|
# @param [Rational] scalar
|
138
136
|
# @param [Enumerable] numerators
|
@@ -161,7 +159,7 @@ module AUOM
|
|
161
159
|
# # A complex unit
|
162
160
|
# u = Unit.new(Rational(1, 3), :euro, :meter)
|
163
161
|
# u.fractions? # => true
|
164
|
-
# u.
|
162
|
+
# u.scalar # => Rational(1, 3)
|
165
163
|
# u.inspect # => <AUOM::Unit @scalar=~0.3333 euro/meter>
|
166
164
|
# u.unit # => [[:euro], [:meter]]
|
167
165
|
#
|
@@ -189,7 +187,7 @@ module AUOM
|
|
189
187
|
#
|
190
188
|
def assert_same_unit(other)
|
191
189
|
unless same_unit?(other)
|
192
|
-
|
190
|
+
fail ArgumentError, 'Incompatible units'
|
193
191
|
end
|
194
192
|
|
195
193
|
self
|
@@ -209,7 +207,7 @@ module AUOM
|
|
209
207
|
def self.convert(operand)
|
210
208
|
converted = try_convert(operand)
|
211
209
|
unless converted
|
212
|
-
|
210
|
+
fail ArgumentError, "Cannot convert #{operand.inspect} to #{self}"
|
213
211
|
end
|
214
212
|
converted
|
215
213
|
end
|
@@ -230,7 +228,7 @@ module AUOM
|
|
230
228
|
case operand
|
231
229
|
when self
|
232
230
|
operand
|
233
|
-
when
|
231
|
+
when Integer, Rational
|
234
232
|
new(operand)
|
235
233
|
end
|
236
234
|
end
|
@@ -252,18 +250,18 @@ module AUOM
|
|
252
250
|
left.delete_if { |item| right.delete_at(right.index(item) || right.length) }
|
253
251
|
end
|
254
252
|
|
255
|
-
@numerators
|
253
|
+
@numerators = numerators.freeze
|
256
254
|
@denominators = denominators.freeze
|
257
255
|
|
258
|
-
@unit = [
|
259
|
-
|
256
|
+
@unit = [numerators, denominators].freeze
|
257
|
+
scalar.freeze
|
260
258
|
end
|
261
259
|
|
262
260
|
# Return rational converted from value
|
263
261
|
#
|
264
262
|
# @param [Object] value
|
265
263
|
#
|
266
|
-
# @return [
|
264
|
+
# @return [Rational]
|
267
265
|
#
|
268
266
|
# @raise [ArgumentError]
|
269
267
|
# raises argument error when cannot be converted to a rational
|
@@ -274,10 +272,10 @@ module AUOM
|
|
274
272
|
case value
|
275
273
|
when Rational
|
276
274
|
value
|
277
|
-
when
|
275
|
+
when Integer
|
278
276
|
Rational(value)
|
279
277
|
else
|
280
|
-
|
278
|
+
fail ArgumentError, "#{value.inspect} cannot be converted to rational"
|
281
279
|
end
|
282
280
|
end
|
283
281
|
|
@@ -314,7 +312,7 @@ module AUOM
|
|
314
312
|
#
|
315
313
|
def self.lookup(value)
|
316
314
|
units.fetch(value) do
|
317
|
-
|
315
|
+
fail ArgumentError, "Unknown unit #{value.inspect}"
|
318
316
|
end
|
319
317
|
end
|
320
318
|
|
@@ -1,13 +1,14 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
shared_examples_for 'an operation' do
|
4
2
|
it 'returns a new object' do
|
5
|
-
object.
|
3
|
+
expect(object).to_not equal(subject)
|
6
4
|
end
|
7
5
|
|
8
6
|
it 'is idempotent on equivalency' do
|
9
7
|
first = subject
|
10
|
-
|
8
|
+
fail unless RSpec.configuration.threadsafe?
|
9
|
+
mutex = __memoized.instance_variable_get(:@mutex)
|
10
|
+
memoized = __memoized.instance_variable_get(:@memoized)
|
11
|
+
mutex.synchronize { memoized.delete(:subject) }
|
11
12
|
should eql(first)
|
12
13
|
end
|
13
14
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
1
|
describe AUOM::Algebra, '#add' do
|
6
2
|
subject { object.add(operand) }
|
7
3
|
|
@@ -10,22 +6,22 @@ describe AUOM::Algebra, '#add' do
|
|
10
6
|
context 'when unit is unitless' do
|
11
7
|
let(:arguments) { [1] }
|
12
8
|
|
13
|
-
context 'and operand is
|
14
|
-
let(:operand) {
|
9
|
+
context 'and operand is an Integer' do
|
10
|
+
let(:operand) { 2 }
|
15
11
|
|
16
12
|
it_should_behave_like 'an operation'
|
17
13
|
|
18
|
-
it { should eql(AUOM::Unit.new(
|
14
|
+
it { should eql(AUOM::Unit.new(3)) }
|
19
15
|
end
|
20
16
|
|
21
17
|
context 'and operand is a unitless unit' do
|
22
|
-
let(:operand) { AUOM::Unit.new(
|
18
|
+
let(:operand) { AUOM::Unit.new(2) }
|
23
19
|
|
24
|
-
it { should eql(AUOM::Unit.new(
|
20
|
+
it { should eql(AUOM::Unit.new(3)) }
|
25
21
|
end
|
26
22
|
|
27
23
|
context 'and operand is a unitful unit' do
|
28
|
-
let(:operand) { AUOM::Unit.new(
|
24
|
+
let(:operand) { AUOM::Unit.new(2, :meter) }
|
29
25
|
|
30
26
|
it_should_behave_like 'an incompatible operation'
|
31
27
|
end
|
@@ -34,28 +30,28 @@ describe AUOM::Algebra, '#add' do
|
|
34
30
|
context 'when unit is unitful' do
|
35
31
|
let(:arguments) { [1, :meter, :euro] }
|
36
32
|
|
37
|
-
context 'and operand is
|
38
|
-
let(:operand) {
|
33
|
+
context 'and operand is an Integer' do
|
34
|
+
let(:operand) { 2 }
|
39
35
|
|
40
36
|
it_should_behave_like 'an incompatible operation'
|
41
37
|
end
|
42
38
|
|
43
39
|
context 'and operand is a unitless unit' do
|
44
|
-
let(:operand) { AUOM::Unit.new(
|
40
|
+
let(:operand) { AUOM::Unit.new(2) }
|
45
41
|
|
46
42
|
it_should_behave_like 'an incompatible operation'
|
47
43
|
end
|
48
44
|
|
49
45
|
context 'and operand is a incompatible unit' do
|
50
|
-
let(:operand) { AUOM::Unit.new(
|
46
|
+
let(:operand) { AUOM::Unit.new(2, :euro) }
|
51
47
|
|
52
48
|
it_should_behave_like 'an incompatible operation'
|
53
49
|
end
|
54
50
|
|
55
51
|
context 'and operand is a compatible unit' do
|
56
|
-
let(:operand) { AUOM::Unit.new(
|
52
|
+
let(:operand) { AUOM::Unit.new(2, :meter, :euro) }
|
57
53
|
|
58
|
-
it { should eql(AUOM::Unit.new(
|
54
|
+
it { should eql(AUOM::Unit.new(3, :meter, :euro)) }
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
@@ -1,85 +1,83 @@
|
|
1
|
-
|
1
|
+
describe AUOM::Algebra do
|
2
|
+
describe '#divide' do
|
3
|
+
subject { object.divide(operand) }
|
2
4
|
|
3
|
-
|
5
|
+
let(:object) { AUOM::Unit.new(*arguments) }
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
context 'with unitless unit' do
|
8
|
+
let(:arguments) { [4] }
|
7
9
|
|
8
|
-
|
10
|
+
context 'when operand is a fixnum' do
|
11
|
+
let(:operand) { 2 }
|
9
12
|
|
10
|
-
|
11
|
-
let(:arguments) { [4] }
|
12
|
-
|
13
|
-
context 'when operand is a fixnum' do
|
14
|
-
let(:operand) { 2 }
|
15
|
-
|
16
|
-
it_should_behave_like 'an operation'
|
13
|
+
it_should_behave_like 'an operation'
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
it { should eql(AUOM::Unit.new(2)) }
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
context 'when operand is a unitless unit' do
|
19
|
+
let(:operand) { AUOM::Unit.new(2) }
|
23
20
|
|
24
|
-
|
21
|
+
it_should_behave_like 'an operation'
|
25
22
|
|
26
|
-
|
27
|
-
|
23
|
+
it { should eql(AUOM::Unit.new(2)) }
|
24
|
+
end
|
28
25
|
|
29
|
-
|
30
|
-
|
26
|
+
context 'when operand is a unitful unit' do
|
27
|
+
let(:operand) { AUOM::Unit.new(2, :meter) }
|
31
28
|
|
32
|
-
|
29
|
+
it_should_behave_like 'an operation'
|
33
30
|
|
34
|
-
|
31
|
+
it { should eql(AUOM::Unit.new(2, [], :meter)) }
|
32
|
+
end
|
35
33
|
end
|
36
|
-
end
|
37
34
|
|
38
|
-
|
39
|
-
|
35
|
+
context 'with unitful unit' do
|
36
|
+
let(:arguments) { [2, :meter] }
|
40
37
|
|
41
|
-
|
42
|
-
|
38
|
+
context 'when operand is a fixnum' do
|
39
|
+
let(:operand) { 1 }
|
43
40
|
|
44
|
-
|
41
|
+
it_should_behave_like 'an operation'
|
45
42
|
|
46
|
-
|
47
|
-
|
43
|
+
it { should eql(AUOM::Unit.new(2, :meter)) }
|
44
|
+
end
|
48
45
|
|
49
|
-
|
50
|
-
|
46
|
+
context 'when operand is a unitless unit' do
|
47
|
+
let(:operand) { AUOM::Unit.new(1) }
|
51
48
|
|
52
|
-
|
49
|
+
it_should_behave_like 'an operation'
|
53
50
|
|
54
|
-
|
55
|
-
|
51
|
+
it { should eql(AUOM::Unit.new(2, :meter)) }
|
52
|
+
end
|
56
53
|
|
57
|
-
|
54
|
+
context 'when operand is a unitful unit' do
|
58
55
|
|
59
|
-
|
60
|
-
|
56
|
+
context 'and units get added to denominator' do
|
57
|
+
let(:operand) { AUOM::Unit.new(1, :euro) }
|
61
58
|
|
62
|
-
|
59
|
+
it_should_behave_like 'an operation'
|
63
60
|
|
64
|
-
|
65
|
-
|
61
|
+
it { should eql(AUOM::Unit.new(2, :meter, :euro)) }
|
62
|
+
end
|
66
63
|
|
67
|
-
|
68
|
-
|
64
|
+
context 'and units get added to numerator' do
|
65
|
+
let(:operand) { AUOM::Unit.new(1, nil, :euro) }
|
69
66
|
|
70
|
-
|
67
|
+
it_should_behave_like 'an operation'
|
71
68
|
|
72
|
-
|
73
|
-
|
69
|
+
it { should eql(AUOM::Unit.new(2, %i[euro meter])) }
|
70
|
+
end
|
74
71
|
|
75
|
-
|
76
|
-
|
72
|
+
context 'and units cancel each other' do
|
73
|
+
let(:operand) { AUOM::Unit.new(1, :meter) }
|
77
74
|
|
78
|
-
|
75
|
+
it_should_behave_like 'an operation'
|
79
76
|
|
80
|
-
|
81
|
-
|
77
|
+
it { should eql(AUOM::Unit.new(2)) }
|
78
|
+
end
|
82
79
|
|
80
|
+
end
|
83
81
|
end
|
84
82
|
end
|
85
83
|
end
|