units-system 0.2.5 → 0.3.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/README.rdoc +28 -0
- data/VERSION +1 -1
- data/lib/units-system.rb +22 -1
- data/lib/units/definitions.rb +28 -5
- data/lib/units/math.rb +26 -0
- data/lib/units/system.rb +49 -1
- data/test/test_constants.rb +68 -0
- data/test/test_units-system.rb +3 -2
- data/units-system.gemspec +3 -2
- metadata +4 -3
data/README.rdoc
CHANGED
@@ -148,6 +148,34 @@ New units can be defined with +Units.define+
|
|
148
148
|
Units.define :kph, 1, Units.u{km/h}
|
149
149
|
puts Units.u{270*kph.to(m/s)} # => 75.0*m/s
|
150
150
|
|
151
|
+
=== Constants
|
152
|
+
|
153
|
+
Constants could be define practically as units, but to avoid introducing too much
|
154
|
+
noise in the units namespace, they can be defined separately with:
|
155
|
+
|
156
|
+
Units.constant :g, 'standard gravity', u{9.80665*m/s**2}
|
157
|
+
|
158
|
+
A constant can be used anywhere with the Units::Const prefix:
|
159
|
+
|
160
|
+
puts Units::Const.g # => 9.80665*m/s**2
|
161
|
+
# gram-force:
|
162
|
+
puts u{g*Const.g} # => 9.80665*(g*m)/s**2
|
163
|
+
|
164
|
+
To avoid using the prefix, constants to be used unprefixed can be declared with a +with_constants+;
|
165
|
+
Note in the first example, that by introducing a constant named +g+ we're hiding the gram units and
|
166
|
+
would not be able to use it in the block.
|
167
|
+
|
168
|
+
# kilopond:
|
169
|
+
puts Units.with_constants(:g){kg*g} # => 9.80665*(kg*m)/s**2
|
170
|
+
# 1 GeV mass
|
171
|
+
puts Units.with_constants(:c){1*GeV/c**2}.to(:kg) # => 1.782661844855044e-27*kg
|
172
|
+
# Planck units
|
173
|
+
Units.with_constants :c, :G, :hbar do
|
174
|
+
puts sqrt(hbar*G/c**3) # => 1.6161992557033346e-35*m
|
175
|
+
puts sqrt(hbar*c/G) # => 2.176509252445312e-08*kg
|
176
|
+
puts sqrt(hbar*G/c**5) # => 5.391060423886096e-44*s
|
177
|
+
end
|
178
|
+
|
151
179
|
== Caveat
|
152
180
|
|
153
181
|
Note that Ruby variable definition rules imply that this:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/units-system.rb
CHANGED
@@ -13,15 +13,36 @@ module Units
|
|
13
13
|
# It is not needed in Ruby 1.9.1 due to they way constant look-up is done in that version,
|
14
14
|
# but Ruby 1.9.2 has changed that an requires this again.
|
15
15
|
module UseBlocks
|
16
|
+
@@constants = nil # an instance variable would not work here because const_missing is executed on other modules (which include this one)
|
16
17
|
def self.append_features(target)
|
17
18
|
def target.const_missing(name)
|
18
19
|
begin
|
19
|
-
|
20
|
+
name = name.to_sym
|
21
|
+
if name==:Const
|
22
|
+
Units::Const
|
23
|
+
else
|
24
|
+
result = @@constants[name] if @@constants
|
25
|
+
result || Units.Measure(name)
|
26
|
+
end
|
20
27
|
rescue ArgumentError
|
21
28
|
super
|
22
29
|
end
|
23
30
|
end
|
24
31
|
end
|
32
|
+
|
33
|
+
def self.with_constants(*consts)
|
34
|
+
prev = @@constants
|
35
|
+
# @@constants = consts.map_hash{|c| Units.constant(c)}
|
36
|
+
@@constants = {}
|
37
|
+
consts.each do |c|
|
38
|
+
c = c.to_sym
|
39
|
+
@@constants[c] = Units.constant(c)
|
40
|
+
end
|
41
|
+
result = yield
|
42
|
+
@@constants = prev
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
25
46
|
end
|
26
47
|
|
27
48
|
include UseBlocks
|
data/lib/units/definitions.rb
CHANGED
@@ -78,17 +78,17 @@ module Units
|
|
78
78
|
define :arcmin, 'arc-minute', 1, :′
|
79
79
|
define :arcsec, 'arc-second', 1, :″
|
80
80
|
|
81
|
-
|
81
|
+
constant :g0, 'standard gravity', u{9.806_65*m/s**2}
|
82
82
|
|
83
83
|
define :bar, 'bar', 1E5, :Pa
|
84
84
|
define :atm, 'atmosphere', 101325.0, :Pa
|
85
|
-
define :mWC, 'meters of water column',
|
85
|
+
define :mWC, 'meters of water column', with_constants(:g0){1E3*kg*g0/m**2}
|
86
86
|
define :Torr, 'torricelli', u{atm/760}
|
87
|
-
define :mHg, 'mHg',
|
87
|
+
define :mHg, 'mHg', with_constants(:g0){13.5951E3*kg*g0/m**2}
|
88
88
|
|
89
89
|
# define :kp, 'kilopond', :force, u{kg*g0} # or define pond?
|
90
|
-
define :gf, 'gram-force',
|
91
|
-
define :lbf, 'pound-force',
|
90
|
+
define :gf, 'gram-force', with_constants(:g0){g*g0} # kilopond kp = kgf
|
91
|
+
define :lbf, 'pound-force', with_constants(:g0){lb*g0}
|
92
92
|
|
93
93
|
define :dyn, 'dyne', 10, :µN # u{1*g*cm/s**2}
|
94
94
|
define :galUS, 'U.S. liquid gallon', u{231*self.in**3}
|
@@ -97,4 +97,27 @@ module Units
|
|
97
97
|
|
98
98
|
define :psi, 'pounds-force per square inch', u{lbf/self.in**2}
|
99
99
|
|
100
|
+
constant :pi, 'Pi', ::Math::PI
|
101
|
+
|
102
|
+
# Constants (CODATA 2010 recommended values)
|
103
|
+
constant :c, 'speed of light', u{ 299_792_458*m/s }
|
104
|
+
constant :h, 'Planck constant', u{ 6.626_069_57E-34*J*s }
|
105
|
+
constant :hbar, 'Dirac constant', u{Const.h/(2*Const.pi)}
|
106
|
+
constant :ħ, 'Dirac constant', Const.hbar
|
107
|
+
constant :μ0, 'magnetic constant', u{4*Const.pi*1E-7*N/A**2}
|
108
|
+
constant :ϵ0, 'electric constant', 1/Const.μ0/Const.c**2
|
109
|
+
constant :G, 'gravitational constant', u{ 6.673_84E-11*m**3/kg/s**2 }
|
110
|
+
constant :e, 'elementary charge', u{1.602_176_565E-19*C}
|
111
|
+
constant :me, 'electron mass', u{9.109_382_91E-31*kg}
|
112
|
+
constant :mp, 'proton mass', u{1.672_621_777E-27*kg}
|
113
|
+
constant :α, 'fine-structure constant', with_constants(:e, :pi, :ϵ0, :ħ, :c){e**2/(4*pi*ϵ0*ħ*c)}
|
114
|
+
constant :R∞, 'Rydberg constant', with_constants(:α, :me, :c, :h){α**2*me*c/2/h}
|
115
|
+
constant :NA, 'Avogadro constant', u{6.022_141_29E22*mol}
|
116
|
+
constant :F, 'Faraday constant', Const.NA*Const.e
|
117
|
+
constant :R, 'molar gas constant', u{8.314_4621*J/mol/K}
|
118
|
+
constant :k, 'Boltzmann constant', Const.R/Const.NA
|
119
|
+
|
120
|
+
define :eV, 'electron volt', u{Const.e*V}
|
121
|
+
define :u, 'atomic mass unit', u{1.660_538_921E-27*kg}
|
122
|
+
|
100
123
|
end # Units
|
data/lib/units/math.rb
CHANGED
@@ -44,6 +44,32 @@ module Units
|
|
44
44
|
Units.u{::Math.atan2(x,y)*rad}
|
45
45
|
end
|
46
46
|
|
47
|
+
def sqrt(x)
|
48
|
+
if x.kind_of?(Measure)
|
49
|
+
if x.units.empty?
|
50
|
+
Measure[::Math.sqrt(x.magnitude)]
|
51
|
+
else
|
52
|
+
y = x
|
53
|
+
all_even = x.units.values.map{|v| v.last % 2}.uniq == [0]
|
54
|
+
unless all_even
|
55
|
+
x = x.base
|
56
|
+
all_even = x.units.values.map{|v| v.last % 2}.uniq == [0]
|
57
|
+
end
|
58
|
+
if all_even
|
59
|
+
units = {}
|
60
|
+
x.units.each do |dim, (unit, exp)|
|
61
|
+
units[dim] = [unit, exp/2]
|
62
|
+
end
|
63
|
+
Measure[::Math.sqrt(x.magnitude), units]
|
64
|
+
else
|
65
|
+
raise ArgumentError, "Invalid dimensiones for sqrt argument #{y}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
else
|
69
|
+
::Math.sqrt(x)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
47
73
|
end
|
48
74
|
|
49
75
|
end # Units
|
data/lib/units/system.rb
CHANGED
@@ -232,5 +232,53 @@ module Units
|
|
232
232
|
u_descr
|
233
233
|
end
|
234
234
|
|
235
|
-
|
235
|
+
ConstantDefinition = Struct.new(:symbol, :description, :value)
|
236
|
+
CONSTANTS = {}
|
237
|
+
module Const
|
238
|
+
def self.define(name, description, value)
|
239
|
+
symbol = name.to_sym
|
240
|
+
cd = ConstantDefinition.new(symbol, description, value)
|
241
|
+
CONSTANTS[symbol] = cd
|
242
|
+
class_eval do
|
243
|
+
# Ruby 1.9.1 allows this nicer definition:
|
244
|
+
# define_singleton_method name do
|
245
|
+
# value
|
246
|
+
# end
|
247
|
+
eigenclass = class<<self; self; end
|
248
|
+
eigenclass.instance_eval{define_method(name){value}}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.constant(symbol, description=nil, value=nil)
|
254
|
+
if description.nil? && value.nil?
|
255
|
+
c = CONSTANTS[symbol]
|
256
|
+
c && c.value
|
257
|
+
else
|
258
|
+
Const.define symbol, description, value
|
259
|
+
end
|
260
|
+
end
|
236
261
|
|
262
|
+
def self.with_constants(*constants, &blk)
|
263
|
+
m = Module.new
|
264
|
+
m.extend Units::System
|
265
|
+
m.extend Units::Math
|
266
|
+
cap_constants = []
|
267
|
+
constants.each do |const|
|
268
|
+
m.instance_eval do
|
269
|
+
# Ruby 1.9.1 allows this nicer definition:
|
270
|
+
# define_singleton_method(const){Units.constant(const)}
|
271
|
+
eigenclass = class<<self; self; end
|
272
|
+
eigenclass.instance_eval{define_method(const){Units.constant(const)}}
|
273
|
+
name_initial = const.to_s[0,1]
|
274
|
+
if name_initial==name_initial.upcase && name_initial!=name_initial.downcase
|
275
|
+
cap_constants << const
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
UseBlocks.with_constants(*cap_constants) do
|
280
|
+
m.instance_eval &blk
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end # Units
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConstants < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include Units::UseBlocks
|
6
|
+
|
7
|
+
should "have qualified constants" do
|
8
|
+
assert_equal 299792458, Units::Const.c.magnitude
|
9
|
+
assert_equal 6.67384E-11, Units::Const.G.magnitude
|
10
|
+
assert_equal [:m, 1], Units::Const.c.units[:length]
|
11
|
+
assert_equal 299792458**2, (Units::Const.c**2).magnitude
|
12
|
+
assert_equal [:m, 2], (Units::Const.c**2).units[:length]
|
13
|
+
assert_nil (Units::Const.c/Units.u{m}).units[:length]
|
14
|
+
end
|
15
|
+
|
16
|
+
should "have qualified constants in units blocks" do
|
17
|
+
assert_equal 299792458, Units.units{Units::Const.c}.magnitude
|
18
|
+
assert_equal 6.67384E-11, Units.units{Units::Const.G}.magnitude
|
19
|
+
assert_equal [:m, 1], Units.units{Units::Const.c}.units[:length]
|
20
|
+
assert_equal 299792458**2, Units.units{Units::Const.c**2}.magnitude
|
21
|
+
assert_equal [:m, 2], Units.units{Units::Const.c**2}.units[:length]
|
22
|
+
assert_nil Units.units{Units::Const.c/m}.units[:length]
|
23
|
+
end
|
24
|
+
|
25
|
+
should "not need qualification for Const inside a units block" do
|
26
|
+
assert_equal 299792458, Units.units{Const.c}.magnitude
|
27
|
+
assert_equal 6.67384E-11, Units.units{Const.G}.magnitude
|
28
|
+
assert_equal [:m, 1], Units.units{Const.c}.units[:length]
|
29
|
+
assert_equal 299792458**2, Units.units{Const.c**2}.magnitude
|
30
|
+
assert_equal [:m, 2], Units.units{Const.c**2}.units[:length]
|
31
|
+
assert_nil Units.units{Const.c/m}.units[:length]
|
32
|
+
end
|
33
|
+
|
34
|
+
should "provide constant values" do
|
35
|
+
c = Units::Const.c
|
36
|
+
assert_equal 299792458, Units.units{c}.magnitude
|
37
|
+
assert_equal [:m, 1], Units.units{c}.units[:length]
|
38
|
+
assert_equal 299792458**2, Units.units{c**2}.magnitude
|
39
|
+
assert_equal [:m, 2], Units.units{c**2}.units[:length]
|
40
|
+
assert_nil Units.units{c/m}.units[:length]
|
41
|
+
end
|
42
|
+
|
43
|
+
should "allow use of local unqualified declared constants" do
|
44
|
+
assert_equal 299792458, Units.with_constants(:c){c}.magnitude
|
45
|
+
assert_equal 299792458*6.67384E-11, Units.with_constants(:c,:G){G*c}.magnitude
|
46
|
+
assert_nil Units.with_constants(:c){c/m}.units[:length]
|
47
|
+
assert_in_delta 1.782661844855044e-27, Units.with_constants(:c){1*GeV/c**2}.to(:kg).magnitude, Float::EPSILON
|
48
|
+
end
|
49
|
+
|
50
|
+
should "not need qualification for Const inside a with_constants block" do
|
51
|
+
assert_equal 299792458, Units.with_constants{Const.c}.magnitude
|
52
|
+
assert_equal 6.67384E-11, Units.with_constants{Const.G}.magnitude
|
53
|
+
assert_equal [:m, 1], Units.with_constants{Const.c}.units[:length]
|
54
|
+
assert_equal 299792458**2, Units.with_constants{Const.c**2}.magnitude
|
55
|
+
assert_equal [:m, 2], Units.with_constants{Const.c**2}.units[:length]
|
56
|
+
assert_nil Units.with_constants{Const.c/m}.units[:length]
|
57
|
+
end
|
58
|
+
|
59
|
+
should "define new constants" do
|
60
|
+
Units.constant :cc, "test constant c", Units::Const.c
|
61
|
+
assert_equal Units::Const.c, Units::Const.cc
|
62
|
+
assert_equal 299792458*6.67384E-11, Units.with_constants(:cc,:G){G*cc}.magnitude
|
63
|
+
Units.constant :GG, "test constant G", Units::Const.G
|
64
|
+
assert_equal Units::Const.G, Units::Const.GG
|
65
|
+
assert_equal 299792458*6.67384E-11, Units.with_constants(:c,:GG){GG*c}.magnitude
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/test_units-system.rb
CHANGED
@@ -132,7 +132,8 @@ class TestUnitsSystem < Test::Unit::TestCase
|
|
132
132
|
should "render valid code when inspecting measures" do
|
133
133
|
assert_equal Units.u{m}, eval(Units.u{m}.inspect)
|
134
134
|
assert_equal Units.u{3*m/s}, eval(Units.u{3*m/s}.inspect)
|
135
|
-
|
135
|
+
assert_in_delta Units.u{3*m/s+2*km/h}.magnitude, eval(Units.u{3*m/s+2*km/h}.inspect).magnitude, 1E-12
|
136
|
+
assert_equal Units.u{3*m/s+2*km/h}.units, eval(Units.u{3*m/s+2*km/h}.inspect).units
|
136
137
|
end
|
137
138
|
|
138
139
|
should "allow arithmetic between measures and text" do
|
@@ -146,7 +147,7 @@ class TestUnitsSystem < Test::Unit::TestCase
|
|
146
147
|
assert_equal "1.0 m", Units.u{m}.abr
|
147
148
|
assert_equal "3.0 m", Units.u{3*m}.abr
|
148
149
|
assert_equal "3.0 m/s", Units.u{3*m/s}.abr
|
149
|
-
|
150
|
+
assert_match /\A3\.555555555555\d+ m\/s\Z/, Units.u{3*m/s + 2*km/h}.abr
|
150
151
|
assert_equal "1,5 m/s", Units.units{3*m/(2*s)}.abr{|v| v.to_s.tr('.',',') }
|
151
152
|
end
|
152
153
|
|
data/units-system.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "units-system"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Javier Goizueta"]
|
12
|
-
s.date = "2012-09-
|
12
|
+
s.date = "2012-09-27"
|
13
13
|
s.description = "Experimental unit conversion & arithmetic for Ruby 1.9"
|
14
14
|
s.email = "jgoizueta@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/units/prefixes.rb",
|
32
32
|
"lib/units/system.rb",
|
33
33
|
"test/helper.rb",
|
34
|
+
"test/test_constants.rb",
|
34
35
|
"test/test_units-system.rb",
|
35
36
|
"units-system.gemspec"
|
36
37
|
]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: units-system
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: modalsupport
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- lib/units/prefixes.rb
|
114
114
|
- lib/units/system.rb
|
115
115
|
- test/helper.rb
|
116
|
+
- test/test_constants.rb
|
116
117
|
- test/test_units-system.rb
|
117
118
|
- units-system.gemspec
|
118
119
|
homepage: http://github.com/jgoizueta/units-system
|
@@ -129,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
130
|
version: '0'
|
130
131
|
segments:
|
131
132
|
- 0
|
132
|
-
hash:
|
133
|
+
hash: 3591103717823383579
|
133
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
135
|
none: false
|
135
136
|
requirements:
|