unit 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +9 -5
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.markdown +28 -8
- data/Rakefile +5 -6
- data/lib/unit.rb +0 -1
- data/lib/unit/class.rb +16 -4
- data/lib/unit/dsl.rb +2 -0
- data/lib/unit/system.rb +4 -8
- data/lib/unit/version.rb +1 -1
- data/spec/error_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/system_spec.rb +11 -11
- data/spec/unit_spec.rb +129 -93
- data/unit.gemspec +9 -10
- metadata +29 -23
- data/lib/unit/compatibility.rb +0 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a84061a71aee6a42474eabd1fbf16301f8395d74
|
4
|
+
data.tar.gz: 979a52da34a279ed995492f15e03dc946024b13c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1aa9ee8eb10eafdf62ae69ca9010abaf9a14226c64d74845ca5df15975f98d6eb3b33a1fbf6f22c70f970c3c25ebd06c56308559e55e8af45d444cedcaafcdab
|
7
|
+
data.tar.gz: 6408e2577ceca493523554aba26a753651388d4ef9afddcae7ea8d7242f1253a3b000cc6b75f637cc8b1092d68f20153e833b8982cc598fffd3263fbd5f5924d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org/'
|
2
2
|
gemspec
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
README
|
2
|
-
|
2
|
+
===
|
3
|
+
**Unit** introduces computational units to Ruby. It offers built-in support for binary, mathematical, SI, imperial, scientific and temporal units, and a simple interface for adding your own, custom units.
|
3
4
|
|
4
|
-
|
5
|
+
[](http://badge.fury.io/rb/unit) [](https://gemnasium.com/minad/unit) [](http://travis-ci.org/minad/unit) [](https://codeclimate.com/github/minad/unit)
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
- Define units for operands to avoid the inevitable mistakes that plague unit-less operations.
|
8
|
+
- Perform complex mathematical operations while respecting the units of each operand.
|
9
|
+
- Get meaningful errors when units aren't compatible.
|
10
|
+
- Convert values between different systems of units with ease.
|
11
|
+
|
12
|
+
Examples
|
13
|
+
===
|
14
|
+
### General Usage
|
8
15
|
|
9
16
|
require 'unit'
|
10
17
|
puts 1.meter.in_kilometer
|
@@ -13,9 +20,22 @@ Usage
|
|
13
20
|
puts 10.KiB_per_second
|
14
21
|
puts Unit('1 m/s^2')
|
15
22
|
|
16
|
-
|
23
|
+
### Mathematics
|
24
|
+
|
25
|
+
Unit(1, 'km') + Unit(500, 'm') == Unit(1.5, 'km')
|
26
|
+
Unit(1, 'kg') - Unit(500, 'g') == Unit(0.5, 'kg')
|
27
|
+
Unit(100, 'miles/hour') * Unit(0.5, 'hours') == Unit('50 mi')
|
28
|
+
Unit(5.5, 'feet') / 2 == Unit(2.75, 'feet')
|
29
|
+
Unit(2, 'm') ** 2 == Unit(4, 'm^2')
|
30
|
+
|
31
|
+
### Conversions
|
32
|
+
|
33
|
+
Unit(1, 'mile').in('km') == Unit(1.609344, 'km')
|
34
|
+
(Unit(10, 'A') * Unit(0.1, 'volt')).in('watts') == Unit(1, 'watt')
|
35
|
+
|
36
|
+
See the test cases for many more examples.
|
17
37
|
|
18
|
-
|
19
|
-
|
38
|
+
Maintainers
|
39
|
+
---
|
40
|
+
Daniel Mendler and [Chris Cashwell](https://github.com/ccashwell)
|
20
41
|
|
21
|
-
Daniel Mendler
|
data/Rakefile
CHANGED
@@ -2,17 +2,16 @@
|
|
2
2
|
require 'rspec/core/rake_task'
|
3
3
|
task :default => :spec
|
4
4
|
|
5
|
-
desc
|
6
|
-
task :spec => [
|
5
|
+
desc 'Run specs'
|
6
|
+
task :spec => ['spec:no_dsl', 'spec:dsl']
|
7
7
|
|
8
8
|
namespace :spec do
|
9
|
-
desc
|
9
|
+
desc 'Run specs without DSL'
|
10
10
|
RSpec::Core::RakeTask.new(:no_dsl) do |t|
|
11
|
-
t.rspec_opts =
|
11
|
+
t.rspec_opts = '-t ~dsl'
|
12
12
|
end
|
13
13
|
|
14
|
-
desc
|
14
|
+
desc 'Run specs with DSL'
|
15
15
|
RSpec::Core::RakeTask.new(:dsl) do |t|
|
16
|
-
# Run all tests
|
17
16
|
end
|
18
17
|
end
|
data/lib/unit.rb
CHANGED
data/lib/unit/class.rb
CHANGED
@@ -159,11 +159,11 @@ class Unit < Numeric
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def inspect
|
162
|
-
unit.empty? ? %{Unit("#{value}")} : %{Unit("#{
|
162
|
+
unit.empty? ? %{Unit("#{value}")} : %{Unit("#{value_string} #{unit_string('.')}")}
|
163
163
|
end
|
164
164
|
|
165
165
|
def to_s
|
166
|
-
unit.empty? ? value.to_s : "#{
|
166
|
+
unit.empty? ? value.to_s : "#{value_string} #{unit_string}"
|
167
167
|
end
|
168
168
|
|
169
169
|
def to_tex
|
@@ -182,14 +182,26 @@ class Unit < Numeric
|
|
182
182
|
Unit.new(self.to_f, unit, system)
|
183
183
|
end
|
184
184
|
|
185
|
-
def round
|
186
|
-
Unit.new(value.round, unit, system)
|
185
|
+
def round(precision = 0)
|
186
|
+
Unit.new(value.round(precision), unit, system)
|
187
187
|
end
|
188
188
|
|
189
189
|
def coerce(other)
|
190
190
|
[coerce_numeric(other), self]
|
191
191
|
end
|
192
192
|
|
193
|
+
def value_string
|
194
|
+
if Rational === value
|
195
|
+
if value.denominator == 1
|
196
|
+
value.numerator.to_s
|
197
|
+
else
|
198
|
+
value.inspect
|
199
|
+
end
|
200
|
+
else
|
201
|
+
value.to_s
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
193
205
|
def unit_string(sep = '·')
|
194
206
|
(unit_list(@unit.select {|factor, name, exp| exp >= 0 }) +
|
195
207
|
unit_list(@unit.select {|factor, name, exp| exp < 0 })).join(sep)
|
data/lib/unit/dsl.rb
CHANGED
data/lib/unit/system.rb
CHANGED
@@ -11,7 +11,7 @@ class Unit < Numeric
|
|
11
11
|
@unit_symbol = {}
|
12
12
|
|
13
13
|
# one is internal trivial factor
|
14
|
-
@factor = {:
|
14
|
+
@factor = {one: {symbol: 'one', value: 1} }
|
15
15
|
@factor_symbol = {'one' => :one}
|
16
16
|
@factor_value = {1 => :one}
|
17
17
|
|
@@ -45,11 +45,7 @@ class Unit < Numeric
|
|
45
45
|
load_factors(data['factors']) if data['factors']
|
46
46
|
load_units(data['units']) if data['units']
|
47
47
|
|
48
|
-
@unit.each
|
49
|
-
defs = unit.delete(:defs)
|
50
|
-
unit[:def] = parse_unit(defs) if defs
|
51
|
-
validate_unit(unit[:def])
|
52
|
-
end
|
48
|
+
@unit.each {|name, unit| validate_unit(unit[:def]) }
|
53
49
|
|
54
50
|
true
|
55
51
|
end
|
@@ -141,7 +137,7 @@ class Unit < Numeric
|
|
141
137
|
raise "Invalid definition for factor #{name}" unless base
|
142
138
|
value = base ** exp
|
143
139
|
$stderr.puts "Factor #{name} already defined" if @factor[name]
|
144
|
-
@factor[name] = { :
|
140
|
+
@factor[name] = { symbol: symbols.first, value: value }
|
145
141
|
symbols.each do |sym|
|
146
142
|
$stderr.puts "Factor symbol #{sym} for #{name} already defined" if @factor_symbol[name]
|
147
143
|
@factor_symbol[sym] = name
|
@@ -155,7 +151,7 @@ class Unit < Numeric
|
|
155
151
|
name = name.to_sym
|
156
152
|
symbols = [unit['sym'] || []].flatten
|
157
153
|
$stderr.puts "Unit #{name} already defined" if @unit[name]
|
158
|
-
@unit[name] = { :
|
154
|
+
@unit[name] = { symbol: symbols.first, def: parse_unit(unit['def']) }
|
159
155
|
symbols.each do |sym|
|
160
156
|
$stderr.puts "Unit symbol #{sym} for #{name} already defined" if @unit_symbol[name]
|
161
157
|
@unit_symbol[sym] = name
|
data/lib/unit/version.rb
CHANGED
data/spec/error_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe "Errors" do
|
|
6
6
|
it "should have a nice error message" do
|
7
7
|
a = Unit(1, "meter")
|
8
8
|
b = Unit(1, "second")
|
9
|
-
|
9
|
+
expect { a + b }.to raise_error(TypeError, "#{a.inspect} and #{b.inspect} are incompatible")
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -18,7 +18,7 @@ describe "Errors" do
|
|
18
18
|
)
|
19
19
|
end
|
20
20
|
|
21
|
-
it "should have a nice error message using the DSL", :
|
21
|
+
it "should have a nice error message using the DSL", dsl: true do
|
22
22
|
unit = Unit(1000, "m / s")
|
23
23
|
expect { unit.in_seconds! }.to(
|
24
24
|
raise_error(TypeError, %{Unexpected #{unit.inspect}, expected to be in s})
|
data/spec/spec_helper.rb
CHANGED
data/spec/system_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Unit::System do
|
|
9
9
|
system.load(:si)
|
10
10
|
test_file = File.join(File.dirname(__FILE__), "yml", "io.yml")
|
11
11
|
File.open(test_file) { |file| system.load(file) }
|
12
|
-
Unit(1, "pim", system).
|
12
|
+
expect(Unit(1, "pim", system)).to eq(Unit(3.14159, "m", system))
|
13
13
|
end
|
14
14
|
|
15
15
|
context "when passed a String" do
|
@@ -18,14 +18,14 @@ describe Unit::System do
|
|
18
18
|
filename = File.join(File.dirname(__FILE__), "yml", "filename.yml")
|
19
19
|
system.load(:si)
|
20
20
|
system.load(filename)
|
21
|
-
Unit(2, "dzm", system).
|
21
|
+
expect(Unit(2, "dzm", system)).to eq(Unit(24, "m", system))
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
context "that is not a filename" do
|
26
26
|
it "should load the built-in system of that name" do
|
27
27
|
system.load("si")
|
28
|
-
|
28
|
+
expect { Unit(2, 'm', system) }.not_to raise_exception
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -42,7 +42,7 @@ describe Unit::System do
|
|
42
42
|
}
|
43
43
|
}
|
44
44
|
)
|
45
|
-
Unit(2, "dzm", system).
|
45
|
+
expect(Unit(2, "dzm", system)).to eq(Unit(24, "m", system))
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -57,14 +57,14 @@ describe Unit::System do
|
|
57
57
|
}
|
58
58
|
}
|
59
59
|
)
|
60
|
-
Unit(2, "dzm", system).
|
60
|
+
expect(Unit(2, "dzm", system)).to eq(Unit(24, "m", system))
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
context "when passed an invalid factor" do
|
65
65
|
it "should raise an exception" do
|
66
66
|
system.load(:si)
|
67
|
-
|
67
|
+
expect {
|
68
68
|
system.load(
|
69
69
|
'factors' => {
|
70
70
|
'dozen' => {
|
@@ -72,26 +72,26 @@ describe Unit::System do
|
|
72
72
|
}
|
73
73
|
}
|
74
74
|
)
|
75
|
-
}.
|
75
|
+
}.to raise_exception("Invalid definition for factor dozen")
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
context "when called on the same filename a second time" do
|
81
81
|
it "should be a no-op" do
|
82
|
-
$stderr.
|
82
|
+
expect($stderr).not_to receive(:puts)
|
83
83
|
test_file = File.join(File.dirname(__FILE__), "yml", "filename.yml")
|
84
84
|
system.load(:si)
|
85
85
|
system.load(test_file)
|
86
|
-
|
86
|
+
expect { system.load(test_file) }.not_to raise_exception
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
90
|
context "when called on the same symbol a second time" do
|
91
91
|
it "should be a no-op" do
|
92
|
-
$stderr.
|
92
|
+
expect($stderr).not_to receive(:puts)
|
93
93
|
system.load(:si)
|
94
|
-
|
94
|
+
expect { system.load(:si) }.not_to raise_exception
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
data/spec/unit_spec.rb
CHANGED
@@ -7,67 +7,67 @@ Unit.default_system.load(:misc)
|
|
7
7
|
|
8
8
|
describe 'Unit' do
|
9
9
|
it 'should support multiplication' do
|
10
|
-
(Unit(2, 'm') * Unit(3, 'm')).
|
11
|
-
(Unit(2, 'm') * 3).
|
12
|
-
(Unit(2, 'm') * Rational(3, 4)).
|
13
|
-
(Unit(2, 'm') * 0.5).
|
10
|
+
expect(Unit(2, 'm') * Unit(3, 'm')).to eq(Unit(6, 'm^2'))
|
11
|
+
expect(Unit(2, 'm') * 3).to eq(Unit(6, 'm'))
|
12
|
+
expect(Unit(2, 'm') * Rational(3, 4)).to eq(Unit(3, 2, 'm'))
|
13
|
+
expect(Unit(2, 'm') * 0.5).to eq(Unit(1.0, 'm'))
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should support division' do
|
17
|
-
(Unit(2, 'm') / Unit(3, 'm^2')).
|
18
|
-
(Unit(2, 'm') / 3).
|
19
|
-
(Unit(2, 'm') / Rational(3, 4)).
|
20
|
-
(Unit(2, 'm') / 0.5).
|
17
|
+
expect(Unit(2, 'm') / Unit(3, 'm^2')).to eq(Unit(2, 3, '1/m'))
|
18
|
+
expect(Unit(2, 'm') / 3).to eq(Unit(2, 3, 'm'))
|
19
|
+
expect(Unit(2, 'm') / Rational(3, 4)).to eq(Unit(8, 3, 'm'))
|
20
|
+
expect(Unit(2, 'm') / 0.5).to eq(Unit(4.0, 'm'))
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should support addition' do
|
24
|
-
(Unit(42, 'm') + Unit(1, 'km')).
|
24
|
+
expect(Unit(42, 'm') + Unit(1, 'km')).to eq(Unit(1042, 'm'))
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'should support subtraction' do
|
28
|
-
(Unit(1, 'm') - Unit(1, 'cm')).
|
29
|
-
(Unit(2, 'm') - Unit(1, 'm')).
|
28
|
+
expect(Unit(1, 'm') - Unit(1, 'cm')).to eq(Unit(99, 100, 'm'))
|
29
|
+
expect(Unit(2, 'm') - Unit(1, 'm')).to eq(Unit(1, 'm'))
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should support arithmetic with Integers when appropriate" do
|
33
|
-
(1 + Unit(1)).
|
34
|
-
(2 - Unit(1)).
|
35
|
-
(Unit(2) - 1).
|
36
|
-
(2 - Unit(-1)).
|
37
|
-
(Unit(2) - -1).
|
33
|
+
expect(1 + Unit(1)).to eq(Unit(2))
|
34
|
+
expect(2 - Unit(1)).to eq(Unit(1))
|
35
|
+
expect(Unit(2) - 1).to eq(Unit(1))
|
36
|
+
expect(2 - Unit(-1)).to eq(Unit(3))
|
37
|
+
expect(Unit(2) - -1).to eq(Unit(3))
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should support arithmetic with other classes using #coerce" do
|
41
|
-
(Unit(2) + UnitOne.new).
|
42
|
-
(2 + UnitOne.new).
|
43
|
-
(Unit(2) - UnitOne.new).
|
44
|
-
(2 - UnitOne.new).
|
45
|
-
(Unit(2) * UnitOne.new).
|
46
|
-
(2 * UnitOne.new).
|
47
|
-
(Unit(2) / UnitOne.new).
|
48
|
-
(2 / UnitOne.new).
|
49
|
-
|
50
|
-
(UnitOne.new + Unit(4)).
|
51
|
-
(UnitOne.new + 4).
|
52
|
-
(UnitOne.new - Unit(4)).
|
53
|
-
(UnitOne.new - 4).
|
54
|
-
(UnitOne.new * Unit(4)).
|
55
|
-
(UnitOne.new * 4).
|
56
|
-
(UnitOne.new / Unit(4)).
|
57
|
-
(UnitOne.new / 4).
|
41
|
+
expect(Unit(2) + UnitOne.new).to eq(Unit(3))
|
42
|
+
expect(2 + UnitOne.new).to eq(3)
|
43
|
+
expect(Unit(2) - UnitOne.new).to eq(Unit(1))
|
44
|
+
expect(2 - UnitOne.new).to eq(1)
|
45
|
+
expect(Unit(2) * UnitOne.new).to eq(Unit(2))
|
46
|
+
expect(2 * UnitOne.new).to eq(2)
|
47
|
+
expect(Unit(2) / UnitOne.new).to eq(Unit(2))
|
48
|
+
expect(2 / UnitOne.new).to eq(2)
|
49
|
+
|
50
|
+
expect(UnitOne.new + Unit(4)).to eq(Unit(5))
|
51
|
+
expect(UnitOne.new + 4).to eq(5)
|
52
|
+
expect(UnitOne.new - Unit(4)).to eq(Unit(-3))
|
53
|
+
expect(UnitOne.new - 4).to eq(-3)
|
54
|
+
expect(UnitOne.new * Unit(4)).to eq(Unit(4))
|
55
|
+
expect(UnitOne.new * 4).to eq(4)
|
56
|
+
expect(UnitOne.new / Unit(4)).to eq(Unit(1, 4))
|
57
|
+
expect(UnitOne.new / 4).to eq(0)
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should support logic with other classes using #coerce" do
|
61
|
-
Unit(1).
|
62
|
-
Unit(2).
|
61
|
+
expect(Unit(1)).to eq(UnitOne.new)
|
62
|
+
expect(Unit(2)).to be > UnitOne.new
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should support eql comparison" do
|
66
|
-
Unit(1).
|
67
|
-
Unit(1.0).
|
66
|
+
expect(Unit(1)).to eql(Unit(1))
|
67
|
+
expect(Unit(1.0)).not_to eql(Unit(1))
|
68
68
|
|
69
|
-
Unit(1).
|
70
|
-
Unit(1.0).
|
69
|
+
expect(Unit(1)).not_to eql(UnitOne.new)
|
70
|
+
expect(Unit(1.0)).not_to eql(UnitOne.new)
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should not support adding anything but numeric unless object is coerceable" do
|
@@ -78,8 +78,8 @@ describe 'Unit' do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should support adding through zero" do
|
81
|
-
(Unit(0, "m") + Unit(1, "m")).
|
82
|
-
(Unit(1, "m") + Unit(-1, "m") + Unit(1, "m")).
|
81
|
+
expect(Unit(0, "m") + Unit(1, "m")).to eq(Unit(1, "m"))
|
82
|
+
expect(Unit(1, "m") + Unit(-1, "m") + Unit(1, "m")).to eq(Unit(1, "m"))
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'should check unit compatiblity' do
|
@@ -89,10 +89,10 @@ describe 'Unit' do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'should support exponentiation' do
|
92
|
-
(Unit(2, 'm') ** 3).
|
93
|
-
(Unit(9, 'm^2') ** 0.5).
|
94
|
-
(Unit(9, 'm^2') ** Rational(1, 2)).
|
95
|
-
(Unit(2, 'm') ** 1.3).
|
92
|
+
expect(Unit(2, 'm') ** 3).to eq(Unit(8, 'm^3'))
|
93
|
+
expect(Unit(9, 'm^2') ** 0.5).to eq(Unit(3.0, 'm'))
|
94
|
+
expect(Unit(9, 'm^2') ** Rational(1, 2)).to eq(Unit(3, 'm'))
|
95
|
+
expect(Unit(2, 'm') ** 1.3).to eq(Unit(2 ** 1.3, 'm^1.3'))
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'should not allow units as exponent' do
|
@@ -104,7 +104,7 @@ describe 'Unit' do
|
|
104
104
|
unit = Unit(1, 'joule')
|
105
105
|
normalized_unit = Unit(1000, 'gram meter^2 / second^2')
|
106
106
|
|
107
|
-
unit.normalize.
|
107
|
+
expect(unit.normalize).to eql normalized_unit
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should not modify the receiver" do
|
@@ -112,7 +112,7 @@ describe 'Unit' do
|
|
112
112
|
normalized_unit = Unit(1000, 'gram meter^2 / second^2')
|
113
113
|
|
114
114
|
unit.normalize
|
115
|
-
unit.
|
115
|
+
expect(unit).not_to eql normalized_unit
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -121,7 +121,7 @@ describe 'Unit' do
|
|
121
121
|
unit = Unit(1, 'joule')
|
122
122
|
normalized_unit = Unit(1000, 'gram meter^2 / second^2')
|
123
123
|
|
124
|
-
unit.normalize
|
124
|
+
expect(unit.normalize!).to eql normalized_unit
|
125
125
|
end
|
126
126
|
|
127
127
|
it "should modify the receiver" do
|
@@ -129,66 +129,94 @@ describe 'Unit' do
|
|
129
129
|
normalized_unit = Unit(1000, 'gram meter^2 / second^2')
|
130
130
|
|
131
131
|
unit.normalize!
|
132
|
-
unit.
|
132
|
+
expect(unit).to eql normalized_unit
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
136
|
it 'should convert units' do
|
137
|
-
Unit(1, "MeV").in("joule").
|
138
|
-
Unit(1, "kilometer").in("meter").
|
139
|
-
Unit(1, "liter").in('meter^3').
|
140
|
-
Unit(1, "kilometer/hour").in("meter/second").
|
137
|
+
expect(Unit(1, "MeV").in("joule")).to eq(Unit(1.602176487e-13, 'joule'))
|
138
|
+
expect(Unit(1, "kilometer").in("meter")).to eq(Unit(1000, 'meter'))
|
139
|
+
expect(Unit(1, "liter").in('meter^3')).to eq(Unit(1, 1000, 'meter^3'))
|
140
|
+
expect(Unit(1, "kilometer/hour").in("meter/second")).to eq(Unit(5, 18, 'meter/second'))
|
141
141
|
end
|
142
142
|
|
143
143
|
it 'should have a working compatible? method' do
|
144
|
-
Unit(7, "meter").compatible?('kilogram').
|
145
|
-
Unit(3, "parsec").compatible_with?('meter').
|
144
|
+
expect(Unit(7, "meter").compatible?('kilogram')).to eq(false)
|
145
|
+
expect(Unit(3, "parsec").compatible_with?('meter')).to eq(true)
|
146
146
|
end
|
147
147
|
|
148
148
|
it 'should have a pretty string representation' do
|
149
|
-
Unit(7, "joule").normalize.to_s.
|
149
|
+
expect(Unit(7, "joule").normalize.to_s).to eq('7000 g·m^2·s^-2')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should have a pretty string representation after subtraction' do
|
153
|
+
expect((Unit('5 cm') - Unit('1 cm')).to_s).to eq('4 cm')
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "#value_string" do
|
157
|
+
it 'should behave like to_s normally' do
|
158
|
+
expect(Unit(1, "liter").send(:value_string)).to eq("1")
|
159
|
+
expect(Unit(0.5, "parsec").send(:value_string)).to eq("0.5")
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should wrap fractions in parentheses' do
|
163
|
+
expect(Unit(Rational(1, 2), "m").send(:value_string)).to eq("(1/2)")
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should show reduced fractions' do
|
167
|
+
expect(Unit(Rational(16, 6), "m").send(:value_string)).to eq("(8/3)")
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should not show 1 in the denominator' do
|
171
|
+
expect(Unit(Rational(1), "foot").send(:value_string)).to eq("1")
|
172
|
+
expect(Unit(Rational(4, 1), "inch").send(:value_string)).to eq("4")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should support round trip through to_s' do
|
177
|
+
expect(Unit(Unit('(1/2) cm').to_s)).to eq(Unit('(1/2) cm'))
|
150
178
|
end
|
151
179
|
|
152
180
|
it 'should parse units' do
|
153
|
-
Unit(1, 'KiB s^-1').unit.
|
154
|
-
Unit(1, 'KiB/s').unit.
|
155
|
-
Unit(1, 'kilometer^2 / megaelectronvolt^7 * gram centiliter').unit.
|
156
|
-
[:one, :gram, 1], [:centi, :liter, 1]].sort
|
181
|
+
expect(Unit(1, 'KiB s^-1').unit).to eq([[:kibi, :byte, 1], [:one, :second, -1]].sort)
|
182
|
+
expect(Unit(1, 'KiB/s').unit).to eq([[:kibi, :byte, 1], [:one, :second, -1]].sort)
|
183
|
+
expect(Unit(1, 'kilometer^2 / megaelectronvolt^7 * gram centiliter').unit).to eq([[:kilo, :meter, 2], [:mega, :electronvolt, -7],
|
184
|
+
[:one, :gram, 1], [:centi, :liter, 1]].sort)
|
157
185
|
end
|
158
186
|
|
159
187
|
it 'should reduce units' do
|
160
|
-
Unit(1, "joule/kilogram").normalize.unit.
|
161
|
-
Unit(1, "megaton/kilometer").unit.
|
188
|
+
expect(Unit(1, "joule/kilogram").normalize.unit).to eq([[:one, :meter, 2], [:one, :second, -2]].sort)
|
189
|
+
expect(Unit(1, "megaton/kilometer").unit).to eq([[:one, :meter, -1], [:kilo, :ton, 1]])
|
162
190
|
end
|
163
191
|
|
164
192
|
it 'should work with floating point values' do
|
165
193
|
w = 5.2 * Unit('kilogram')
|
166
|
-
w.in("pounds").to_int.
|
194
|
+
expect(w.in("pounds").to_int).to eq(11)
|
167
195
|
end
|
168
196
|
|
169
197
|
it 'should have dimensionless? method' do
|
170
|
-
Unit(100, "m/km").
|
171
|
-
Unit(42, "meter/second").
|
172
|
-
Unit(100, "meter/km").
|
198
|
+
expect(Unit(100, "m/km")).to be_dimensionless
|
199
|
+
expect(Unit(42, "meter/second")).not_to be_unitless
|
200
|
+
expect(Unit(100, "meter/km")).to eq(Unit(Rational(1, 10)))
|
173
201
|
end
|
174
202
|
|
175
203
|
it 'should be equal to rational if dimensionless' do
|
176
|
-
Unit(100, "meter/km").
|
177
|
-
Unit(100, "meter/km").approx.
|
204
|
+
expect(Unit(100, "meter/km")).to eq(Rational(1, 10))
|
205
|
+
expect(Unit(100, "meter/km").approx).to eq(0.1)
|
178
206
|
end
|
179
207
|
|
180
208
|
it 'should be comparable' do
|
181
|
-
Unit(1, 'm').
|
182
|
-
Unit(1, 'm').
|
209
|
+
expect(Unit(1, 'm')).to be < Unit(2, 'm')
|
210
|
+
expect(Unit(1, 'm')).to be <= Unit(2, 'm')
|
183
211
|
|
184
|
-
Unit(1, 'm').
|
185
|
-
Unit(1, 'm').
|
212
|
+
expect(Unit(1, 'm')).to be <= Unit(1, 'm')
|
213
|
+
expect(Unit(1, 'm')).to be >= Unit(1, 'm')
|
186
214
|
|
187
|
-
Unit(1, 'm').
|
188
|
-
Unit(1, 'm').
|
215
|
+
expect(Unit(1, 'm')).to be > Unit(0, 'm')
|
216
|
+
expect(Unit(1, 'm')).to be >= Unit(0, 'm')
|
189
217
|
|
190
|
-
Unit(100, "m").
|
191
|
-
Unit(100, "m").
|
218
|
+
expect(Unit(100, "m")).to be < Unit(1, "km")
|
219
|
+
expect(Unit(100, "m")).to be > Unit(0.0001, "km")
|
192
220
|
end
|
193
221
|
|
194
222
|
it "should fail comparison on differing units" do
|
@@ -196,38 +224,46 @@ describe 'Unit' do
|
|
196
224
|
end
|
197
225
|
|
198
226
|
it "should keep units when the value is zero" do
|
199
|
-
Unit(0, "m").unit.
|
227
|
+
expect(Unit(0, "m").unit).to eq([[:one, :meter, 1]])
|
200
228
|
end
|
201
229
|
|
202
230
|
it "should support absolute value" do
|
203
|
-
Unit(1, "m").abs.
|
204
|
-
Unit(-1, "m").abs.
|
231
|
+
expect(Unit(1, "m").abs).to eq(Unit(1, "m"))
|
232
|
+
expect(Unit(-1, "m").abs).to eq(Unit(1, "m"))
|
205
233
|
end
|
206
234
|
|
207
235
|
it "should have #zero?" do
|
208
|
-
Unit(0, "m").zero
|
209
|
-
Unit(1, "m").zero
|
236
|
+
expect(Unit(0, "m").zero?).to eq(true)
|
237
|
+
expect(Unit(1, "m").zero?).to eq(false)
|
210
238
|
end
|
211
239
|
|
212
240
|
it "should produce an approximation" do
|
213
|
-
Unit(Rational(1,3), "m").approx.
|
241
|
+
expect(Unit(Rational(1,3), "m").approx).to eq(Unit(1.0/3.0, "m"))
|
214
242
|
end
|
215
243
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
244
|
+
describe "#round" do
|
245
|
+
it "should be able to round and return a unit" do
|
246
|
+
expect(Unit(Rational(1,3), "m").round).to eq(Unit(0, "m"))
|
247
|
+
expect(Unit(Rational(2,3), "m").round).to eq(Unit(1, "m"))
|
248
|
+
expect(Unit(0.1, "m").round).to eq(Unit(0, "m"))
|
249
|
+
expect(Unit(0.5, "m").round).to eq(Unit(1, "m"))
|
250
|
+
expect(Unit(1, "m").round).to eq(Unit(1, "m"))
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should respect rounding precision" do
|
254
|
+
expect(Unit(0.1234, "m").round(0)).to eq(Unit(0, "m"))
|
255
|
+
expect(Unit(1.2345, "m").round(1)).to eq(Unit(1.2, "m"))
|
256
|
+
expect(Unit(5.4321, "m").round(2)).to eq(Unit(5.43, "m"))
|
257
|
+
end
|
222
258
|
end
|
223
259
|
|
224
260
|
end
|
225
261
|
|
226
|
-
describe "Unit DSL", :
|
262
|
+
describe "Unit DSL", dsl: true do
|
227
263
|
it 'should provide method sugar' do
|
228
|
-
1.meter.
|
229
|
-
1.meter_per_second.
|
230
|
-
1.meter.in_kilometer.
|
231
|
-
1.unit('°C').
|
264
|
+
expect(1.meter).to eq(Unit('1 meter'))
|
265
|
+
expect(1.meter_per_second).to eq(Unit('1 m/s'))
|
266
|
+
expect(1.meter.in_kilometer).to eq(Unit('1 m').in('km'))
|
267
|
+
expect(1.unit('°C')).to eq(Unit(1, '°C'))
|
232
268
|
end
|
233
269
|
end
|
data/unit.gemspec
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require File.dirname(__FILE__) + '/lib/unit/version'
|
3
|
+
require 'date'
|
3
4
|
|
4
5
|
Gem::Specification.new do |s|
|
5
|
-
s.name =
|
6
|
+
s.name = 'unit'
|
6
7
|
s.version = Unit::VERSION
|
8
|
+
s.description =
|
9
|
+
s.summary = 'Scientific unit support for ruby for calculations'
|
10
|
+
s.homepage = 'http://github.com/minad/unit'
|
11
|
+
s.license = 'MIT'
|
7
12
|
|
8
|
-
s.authors = [
|
13
|
+
s.authors = ['Daniel Mendler', 'Chris Cashwell']
|
9
14
|
s.date = Date.today.to_s
|
10
|
-
s.email = [
|
15
|
+
s.email = ['mail@daniel-mendler.de']
|
11
16
|
|
12
17
|
s.files = `git ls-files`.split("\n")
|
13
|
-
s.require_paths =
|
14
|
-
|
15
|
-
s.has_rdoc = true
|
16
|
-
s.require_paths = ["lib"]
|
17
|
-
s.rubyforge_project = s.name
|
18
|
-
s.summary = 'Scientific unit support for ruby for calculations'
|
19
|
-
s.homepage = %q{http://github.com/minad/unit}
|
18
|
+
s.require_paths = ['lib']
|
20
19
|
|
21
20
|
s.add_development_dependency('rake', ['>= 0.8.7'])
|
22
21
|
s.add_development_dependency('rspec')
|
metadata
CHANGED
@@ -1,54 +1,59 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Daniel Mendler
|
8
|
+
- Chris Cashwell
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement:
|
17
|
-
none: false
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
requirements:
|
19
|
-
- -
|
18
|
+
- - ">="
|
20
19
|
- !ruby/object:Gem::Version
|
21
20
|
version: 0.8.7
|
22
21
|
type: :development
|
23
22
|
prerelease: false
|
24
|
-
version_requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.8.7
|
25
28
|
- !ruby/object:Gem::Dependency
|
26
29
|
name: rspec
|
27
|
-
requirement:
|
28
|
-
none: false
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
29
31
|
requirements:
|
30
|
-
- -
|
32
|
+
- - ">="
|
31
33
|
- !ruby/object:Gem::Version
|
32
34
|
version: '0'
|
33
35
|
type: :development
|
34
36
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
-
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description: Scientific unit support for ruby for calculations
|
37
43
|
email:
|
38
44
|
- mail@daniel-mendler.de
|
39
45
|
executables: []
|
40
46
|
extensions: []
|
41
47
|
extra_rdoc_files: []
|
42
48
|
files:
|
43
|
-
- .gitignore
|
44
|
-
- .travis.yml
|
49
|
+
- ".gitignore"
|
50
|
+
- ".travis.yml"
|
45
51
|
- Gemfile
|
46
52
|
- LICENSE
|
47
53
|
- README.markdown
|
48
54
|
- Rakefile
|
49
55
|
- lib/unit.rb
|
50
56
|
- lib/unit/class.rb
|
51
|
-
- lib/unit/compatibility.rb
|
52
57
|
- lib/unit/constructor.rb
|
53
58
|
- lib/unit/dsl.rb
|
54
59
|
- lib/unit/system.rb
|
@@ -69,27 +74,28 @@ files:
|
|
69
74
|
- spec/yml/io.yml
|
70
75
|
- unit.gemspec
|
71
76
|
homepage: http://github.com/minad/unit
|
72
|
-
licenses:
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
73
80
|
post_install_message:
|
74
81
|
rdoc_options: []
|
75
82
|
require_paths:
|
76
83
|
- lib
|
77
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
-
none: false
|
79
85
|
requirements:
|
80
|
-
- -
|
86
|
+
- - ">="
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: '0'
|
83
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
-
none: false
|
85
90
|
requirements:
|
86
|
-
- -
|
91
|
+
- - ">="
|
87
92
|
- !ruby/object:Gem::Version
|
88
93
|
version: '0'
|
89
94
|
requirements: []
|
90
|
-
rubyforge_project:
|
91
|
-
rubygems_version:
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.2.2
|
92
97
|
signing_key:
|
93
|
-
specification_version:
|
98
|
+
specification_version: 4
|
94
99
|
summary: Scientific unit support for ruby for calculations
|
95
100
|
test_files: []
|
101
|
+
has_rdoc:
|