units-system 0.0.5 → 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/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'modalsupport'
4
+
5
+ group :development do
6
+ gem "shoulda", ">= 0"
7
+ gem "rdoc", "~> 3.12"
8
+ gem "bundler", "~> 1"
9
+ gem "jeweler", "~> 1.8.3"
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.8.3)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rdoc
10
+ json (1.6.6)
11
+ modalsupport (0.8.3)
12
+ rake (0.9.2.2)
13
+ rdoc (3.12)
14
+ json (~> 1.4)
15
+ shoulda (3.0.1)
16
+ shoulda-context (~> 1.0.0)
17
+ shoulda-matchers (~> 1.0.0)
18
+ shoulda-context (1.0.0)
19
+ shoulda-matchers (1.0.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1)
26
+ jeweler (~> 1.8.3)
27
+ modalsupport
28
+ rdoc (~> 3.12)
29
+ shoulda
data/README.rdoc CHANGED
@@ -59,10 +59,10 @@ local variables.
59
59
  # Now let's convert som imperial units to SI:
60
60
  puts (100*mi/h).to_si # => 44.704*m/s
61
61
 
62
- # Note that in is a Ruby keyword, so to use inches you must use self.in:
62
+ # Note that +in+ is a Ruby keyword, so to use inches you must use +self.in+:
63
63
  puts (10*cm).to(self.in) # => 3.93700787401575*in
64
64
  # ...or use tha alternative nonstandard name +inch+
65
- puts (10*cm).to(self.inch) # => 3.93700787401575*inch
65
+ puts (10*cm).to(inch) # => 3.93700787401575*inch
66
66
 
67
67
  # Now let's use derived units, e.g. power units:
68
68
  x = 10*kW
data/Rakefile CHANGED
@@ -1,21 +1,27 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
2
12
  require 'rake'
3
13
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "units-system"
8
- gem.summary = %Q{Arithmetic with units of measure}
9
- gem.description = %Q{Experimental unit conversion & arithmetic for Ruby 1.9}
10
- gem.email = "jgoizueta@gmail.com"
11
- gem.homepage = "http://github.com/jgoizueta/units-system"
12
- gem.authors = ["Javier Goizueta"]
13
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
- end
15
- Jeweler::GemcutterTasks.new
16
- rescue LoadError
17
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "units-system"
17
+ gem.summary = %Q{Arithmetic with units of measure}
18
+ gem.description = %Q{Experimental unit conversion & arithmetic for Ruby 1.9}
19
+ gem.email = "jgoizueta@gmail.com"
20
+ gem.homepage = "http://github.com/jgoizueta/units-system"
21
+ gem.authors = ["Javier Goizueta"]
22
+ # dependencies defined in Gemfile
18
23
  end
24
+ Jeweler::RubygemsDotOrgTasks.new
19
25
 
20
26
  require 'rake/testtask'
21
27
  Rake::TestTask.new(:test) do |test|
@@ -24,24 +30,9 @@ Rake::TestTask.new(:test) do |test|
24
30
  test.verbose = true
25
31
  end
26
32
 
27
- begin
28
- require 'rcov/rcovtask'
29
- Rcov::RcovTask.new do |test|
30
- test.libs << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
- rescue LoadError
35
- task :rcov do
36
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
- end
38
- end
39
-
40
- task :test => :check_dependencies
41
-
42
33
  task :default => :test
43
34
 
44
- require 'rake/rdoctask'
35
+ require 'rdoc/task'
45
36
  Rake::RDocTask.new do |rdoc|
46
37
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
38
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.1.0
data/lib/units-system.rb CHANGED
@@ -1,561 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
- # Ruby Units-System experiments.
3
+ require 'modalsupport'
4
+ require 'units/measure'
5
+ require 'units/prefixes'
6
+ require 'units/system'
7
+ require 'units/math'
4
8
 
5
9
  module Units
6
-
7
- class Measure
8
10
 
9
- def initialize(mag=1.0, units={})
10
- @magnitude = mag # rename to value?
11
- case units
12
- when Symbol
13
- uinfo = Units.unit(units)
14
- if uinfo
15
- if uinfo.dim
16
- @units = {uinfo.dim=>[units,1]}
17
- else
18
- @magnitude *= uinfo.factor
19
- @units = {}
20
- end
21
- else
22
- raise ArgumentError,"Invalid symbol for Measure definition: #{units.inspect} "
23
- end
24
- when Measure
25
- @magnitude *= units.magnitude
26
- @units = units.units
27
- else
28
- @units = units
29
- end
30
- end
31
-
32
- attr_reader :magnitude, :units
33
-
34
- # represent in text using Ruby notation
35
- def to_s
36
- return @magnitude.to_s if magnitude?
37
- u_descr = Units.units_descr(@units)
38
- "#{@magnitude}*#{u_descr}"
39
- end
40
-
41
- # more verbose description (not grammatically perfect)
42
- def describe
43
- return @magnitude.to_s if magnitude?
44
- u_descr = Units.units_descr(@units, true)
45
- "#{@magnitude} #{u_descr}"
46
- end
47
-
48
- # more natural concise text representation
49
- def abr
50
- self.to_s.gsub('**','^').tr('*',' ')
51
- end
52
-
53
- # decompose compound units
54
- def detailed_units(all_levels = false)
55
- mag = @magnitude
56
- prev_units = self.units
57
- units = {}
58
- loop do
59
- compound = false
60
- prev_units.each_pair do |dim, (unit,mul)|
61
- ud = Units.unit(unit)
62
- if ud.decomposition
63
- compound = true
64
- mag *= ud.decomposition.magnitude
65
- ud.decomposition.units.each_pair do |d, (u,m)|
66
- mag *= self.class.combine(units, d, u, m)
67
- end
68
- else
69
- mag *= self.class.combine(units, dim, unit, mul)
70
- end
71
- end
72
- if all_levels && compound
73
- prev_units = units
74
- units = {}
75
- else
76
- break
77
- end
78
- end
79
- Measure.new mag, units
80
- end
81
-
82
- # decompose to base units
83
- def base
84
- detailed_units true
85
- end
86
-
87
- def self.combine(units, dim, unit, mult)
88
- factor = 1
89
- if units[dim]
90
- u,m = units[dim]
91
- if u!=unit
92
- factor *= Units.conversion_factor(unit, u)**mult
93
- end
94
- units[dim] = [u, m+mult]
95
- else
96
- units[dim] = [unit, mult]
97
- end
98
- factor
99
- end
100
-
101
- def /(other)
102
- self * (other.kind_of?(Numeric) ? 1.0/other : other.inverse)
103
- end
104
-
105
- def inspect
106
- "Measure(#{@magnitude.inspect}, #{@units.inspect})"
107
- end
108
-
109
- def *(other)
110
- case other
111
- when Numeric
112
- mag = self.magnitude*other
113
- units = self.units
114
- else
115
- mag = self.magnitude*other.magnitude
116
- units = {}
117
- (self.units.keys | other.units.keys).each do |dim|
118
- other_u = other.units[dim] || [nil,0]
119
- this_u = self.units[dim] || [other_u.first,0]
120
- # mag *= Units.conversion_factor(this_u.first, other_u.first) if other_u.first
121
- mult = this_u.last+other_u.last
122
- mag *= Units.conversion_factor(other_u.first, this_u.first)**(other_u.last) if other_u.first
123
- units[dim] = [this_u.first, mult]
124
- end
125
- end
126
- units.reject!{|dim,(u,m)| m==0}
127
- Measure.new(mag, units)
128
- end
129
-
130
- def +(other)
131
- Measure.new self.magnitude+other.to(self.units).magnitude, self.units
132
- end
133
-
134
- def -(other)
135
- self + (-other)
136
- end
137
-
138
- def **(n)
139
- raise ArgumentError,"Only integer powers are allowed for magnitudes" unless n.kind_of?(Integer)
140
- units = @units.dup
141
- units.each_pair do |dim, (u, m)|
142
- units[dim] = [u, m*n]
143
- end
144
- Measure.new @magnitude, units
145
- end
146
-
147
- def inverse
148
- #Measure.new(1.0/@magnitude, @units.map_hash{|unit,mult| [unit, -mult]})
149
- units = {}
150
- @units.each_pair do |dim, (unit, mult)|
151
- units[dim] = [unit, -mult]
152
- end
153
- Measure.new(1.0/@magnitude, units)
154
- end
155
-
156
- def -@
157
- Measure.new(-@magnitude, units)
158
- end
159
-
160
- def in(other, mode=:absolute)
161
- other = Measure.new(1.0, other) unless other.kind_of?(Measure)
162
- other = other.base
163
- this = self.base
164
- dims = this.units.keys | other.units.keys
165
- mag = this.magnitude/other.magnitude
166
- dims.each do |dim|
167
- if !this.units[dim] || !other.units[dim] ||
168
- (this.units[dim].last != other.units[dim].last)
169
- raise "Inconsistent units #{Units.units_descr(this.units)} #{Units.units_descr(other.units)}"
170
- end
171
- this_u, mult = this.units[dim]
172
- other_u = other.units[dim].first
173
- mag *= Units.conversion_factor(this_u, other_u)**mult
174
- end
175
- if mode!=:relative && dims.size==1 && this.units[dims.first].last==1
176
- # consider "level" conversion for biased units (otherwise consider interval or difference values)
177
- mag += Units.conversion_bias(this.units[dims.first].first, other.units[dims.first].first)
178
- end
179
- mag
180
- end
181
-
182
- def to(units, mode=:absolute)
183
- units = units.u if units.kind_of?(Measure)
184
- Measure.new self.in(units, mode), units
185
- end
186
-
187
- def si_units
188
- units = {}
189
- @units.each_pair do |dim, (unit, mult)|
190
- si_unit = SI_UNITS[dim]
191
- if si_unit.kind_of?(Measure)
192
- si_unit.units.each_pair do |d, (u,m)|
193
- self.class.combine(units, d, u, m*mult)
194
- end
195
- else
196
- self.class.combine(units, dim, si_unit, mult)
197
- end
198
- end
199
- units
200
- end
201
-
202
- def to_si
203
- to(si_units)
204
- end
205
-
206
- def coerce(other)
207
- [Measure.new(other, {}), self]
208
- end
209
-
210
- def u # dimension? unit? only_units? strip_units? units_measure?
211
- Measure.new(1.0, self.units)
212
- end
213
-
214
- # dimension (quantity)
215
- def dimension
216
- q = nil
217
- u = self.base.si_units
218
- SI_UNITS.each_pair do |dim, unit|
219
- unit = Measure.new(1.0, unit) unless unit.kind_of?(Measure)
220
- if unit.base.si_units == u
221
- q = dim
222
- break
223
- end
224
- end
225
- q
226
- end
227
-
228
- def dimensionless?
229
- base.units.reject{|d,(u,m)| m==0}.empty?
230
- end
231
-
232
- # less strict dimensionless condition (e.g. an angle is not a pure magnitude in this sense)
233
- def magnitude?
234
- self.units.reject{|d,(u,m)| m==0}.empty?
235
- end
236
-
237
- end # Measure
238
-
239
- def Measure(*args)
240
- if args.size==1
241
- case args.first
242
- when Numeric
243
- m = args.first
244
- u = {}
245
- else
246
- m = 1.0
247
- u = args.first
248
- end
249
- args = [m,u]
250
- end
251
- Units::Measure.new(*args)
252
- end
253
- module_function :Measure
254
-
255
- PREFIXES = {
256
- :y=>[1E-24, 'yocto'],
257
- :z=>[1E-21, 'zepto'],
258
- :a=>[1E-18, 'atto'],
259
- :f=>[1E-15, 'femto'],
260
- :p=>[1E-12, 'pico'],
261
- :n=>[1E-09, 'nano'],
262
- :"\302\265"=>[1E-06, 'micro'], # ASCII alternative: u; define it?
263
- :m=>[1E-03, 'milli'],
264
- :c=>[1E-02, 'centi'],
265
- :d=>[1E-01, 'deci'],
266
- :da=>[1E1, 'deca'],
267
- :h=>[1E02, 'hecto'],
268
- :k=>[1E03, 'kilo'],
269
- :M=>[1E06, 'mega'],
270
- :G=>[1E09, 'giga'],
271
- :T=>[1E12, 'tera'],
272
- :P=>[1E15, 'peta'],
273
- :E=>[1E18, 'exa'],
274
- :Z=>[1E21, 'zetta'],
275
- :Y=>[1E24, 'yotta']
276
- }
277
-
278
- def self.prefix_factor(prefix)
279
- pd = PREFIXES[prefix.to_sym]
280
- pd && pd.first
281
- end
282
-
283
- def self.prefix_name(prefix)
284
- pd = PREFIXES[prefix.to_sym]
285
- pd && pd.last
286
- end
287
-
288
- def self.prefix_factor_and_name(prefix)
289
- PREFIXES[prefix]
290
- end
291
-
292
- # mathematical functions available to unit blocks are defined here
293
- module Math
294
- end
295
-
296
- # unit methods and constants are defined here to be injected in units blocks
297
- module System
298
-
299
- extend Math
300
-
301
- def self.define(unit)
302
- define_var unit
303
- PREFIXES.each do |prefix, (factor, name)|
304
- define_var "#{prefix}#{unit}".to_sym
305
- end
306
- end
307
-
308
- class <<self
309
- private
310
- def define_var(name)
311
- name_initial = name.to_s[0,1]
312
- if name_initial==name_initial.upcase && name_initial!=name_initial.downcase
313
- # we could define a method with the requested name, but it would
314
- # no be usable without qualification (System.X) or brackets (X())
315
- # so we define a constant. But this requires Ruby 1.9 to be useful;
316
- # otherwise the constant is not accesible without qualification in units blocks.
317
- System.const_set name, Units.Measure(name)
318
- end
319
- self.class_eval do
320
- define_method name do
321
- Units.Measure(name)
322
- end
323
- module_function name
324
- end
325
- end
326
- end
327
-
328
- end # Units::System
329
-
330
- def units(&blk)
331
- Units::System.class_eval(&blk)
332
- end
333
- alias :u :units
334
- module_function :units, :u
335
-
336
- UnitDefinition = Struct.new(:dim, :factor, :name, :decomposition, :bias)
337
-
338
- UNITS = {} # Hash.new{|h,k| h[k]=UnitDefinition.new()}
339
-
340
- # get unit definition
341
- def self.unit(unit_symbol)
342
- ud = UNITS[unit_symbol]
343
- if ud.nil?
344
- factor = 1.0
345
- if factor_name = PREFIXES[unit_symbol]
346
- ud = UnitDefinition.new(nil, *factor_name)
347
- else
348
- u = unit_symbol.to_s
349
- PREFIXES.each_pair do |prefix, (f,name)|
350
- prefix = prefix.to_s
351
- if u[0...prefix.length] == prefix
352
- factor = f
353
- ud = UNITS[u[prefix.length..-1].to_sym]
354
- if ud
355
- ud = ud.dup
356
- ud.name = "#{name}#{ud.name}"
357
- break
358
- end
359
- end
360
- end
361
- end
362
- ud.factor *= factor if ud
363
- ud.decomposition *= factor if ud && ud.decomposition
364
- end
365
- raise ArgumentError,"Invalid Units #{unit_symbol}" unless ud
366
- ud
367
- end
368
-
369
- # Define new units.
370
- # Define a base unit (with a factor for conversion to SI units)
371
- # Units.define :unit_symbol, 'unit-name', :quantity, si_units_per_this_unit
372
- # Define a unit in terms or another (valid for base or derived units)
373
- # Units.define :unit_symbol, 'unit-name', value, :in_units
374
- # Define a base unit as a measure-expression
375
- # Units.define :unit_symbol, 'unit_name', u{...}
376
- # Define a derived unit as a measure-expression
377
- # Units.define :unit_symbol, 'unit_name', :quantity, u{...}
378
- # For base dimensions the SI unit for a quantity must also be stablished with Unit.si_units;
379
- # for derived units, SI units are automatically taken to be the first define unit of the quantity
380
- # with unitary value in SI base units.
381
- def self.define(unit_symbol, name, *args)
382
- eqhivalence = nil
383
- si_unit = false
384
- bias = nil
385
- if args.first.kind_of?(Symbol)
386
- dim = args.shift
387
- if args.first.kind_of?(Numeric)
388
- # simple units
389
- factor = args.shift
390
- factor_units = args.shift
391
- if factor_units
392
- ud = unit(factor_units)
393
- if ud.dim != dim
394
- raise ArgumentError, "Inconsistent units #{factor_units} in definition of #{unit_symbol}"
395
- end
396
- # maybe it was not simple after all...
397
- equivalence = factor*ud.decomposition if ud.decomposition
398
- factor *= ud.factor
399
- end
400
- # si_unit = (factor==1.0) # to save si_units definitions # TODO: tolerance?
401
- else
402
- # compound unit
403
- equivalence = args.shift
404
- factor = equivalence.to_si.magnitude
405
- si_unit = (factor==1.0) # TODO: tolerance?
406
- if equivalence.units.empty?
407
- # dimensionless compound dimension... (special case for angular units)
408
- equivalence = nil
409
- end
410
- end
411
- elsif args.first.kind_of?(Numeric)
412
- # unit define in terms of other unit
413
- factor = args.shift
414
- factor_units = args.shift
415
- u = unit(factor_units)
416
- dim = u.dim
417
- equivalence = factor*u.decomposition if u.decomposition
418
- factor *= u.factor
419
- bias = args.shift
420
- else
421
- # unit defined from a measure expression; the dimension must be already known or defined
422
- # here (as as symbol preceding the expression).
423
- definition = args.shift
424
- dim = definition.dimension
425
- raise ArgumentError,"To define a new compound unit a dimension must be specified" unless dim
426
- equivalence = definition
427
- factor = definition.to_si.magnitude
428
- # si_unit = (factor==1.0) # to save si_units definitions # TODO: tolerance?
429
- end
430
- unit_def = UnitDefinition.new(dim, factor, name, equivalence, bias)
431
- if UNITS.has_key?(unit_symbol)
432
- raise "Redefinition of #{unit_symbol} as #{unit_def} (previously defined as #{UNITS[unit_symbol]})"
433
- end
434
- UNITS[unit_symbol] = unit_def
435
- System.define unit_symbol
436
- Units.si_units unit_def.dim, unit_symbol if si_unit && !SI_UNITS.has_key?(unit_def.dim)
437
- end
438
-
439
- SI_UNITS = {}
440
-
441
- def self.si_units(dim, unit)
442
- SI_UNITS[dim] = unit
443
- end
444
-
445
- def self.dimension(u)
446
- unit(u).dim
447
- end
448
-
449
- def self.conversion_factor(from, to)
450
- from_u = unit(from)
451
- to_u = unit(to)
452
- raise ArgumentError,"Inconsistent Units (#{from}, #{to})" if from_u.dim!=to_u.dim
453
- from_u.factor/to_u.factor
454
- end
455
-
456
- def self.conversion_bias(from, to)
457
- from_u = unit(from)
458
- to_u = unit(to)
459
- raise ArgumentError,"Inconsistent Units (#{from}, #{to})" if from_u.dim!=to_u.dim
460
- factor = from_u.factor/to_u.factor
461
- (from_u.bias||0)*factor - (to_u.bias||0)
462
- end
463
-
464
- # simple unit name
465
- def self.unit_name(u)
466
- uinfo = Units.unit(u)
467
- uinfo && uinfo.name
468
- end
469
-
470
- def self.unit_descr(u, long=false, mult=1)
471
- if long
472
- u = unit_name(u)
473
- if mult!=1
474
- case mult
475
- when 2
476
- "squared #{u}"
477
- when 3
478
- "cubed #{u}"
479
- else
480
- "#{u} to the #{mult} power"
481
- end
482
- else
483
- u
484
- end
485
- else
486
- if mult!=1
487
- "#{u}**#{mult}"
488
- else
489
- u.to_s
490
- end
491
- end
492
- end
493
-
494
- def self.units_descr(units, long=false)
495
- units = units.values.sort_by{|u,m| -m}
496
- pos_units = units.select{|u| u.last>0}
497
- neg_units = units.select{|u| u.last<0}
498
- times = long ? " " : "*"
499
- num = pos_units.map{|u,m| unit_descr(u,long,m)}.join(times)
500
- num = "(#{num})" if pos_units.size>1 && !neg_units.empty? && !long
501
- den = neg_units.map{|u,m| unit_descr(u,long,-m)}.join("*")
502
- den = "(#{den})" if neg_units.size>1 && !long
503
- if pos_units.empty?
504
- u_descr = "1/#{den}"
505
- elsif neg_units.empty?
506
- u_descr = num
507
- else
508
- connector = long ? " per " : "/"
509
- u_descr = "#{num}#{connector}#{den}"
510
- end
511
- u_descr
512
- end
513
-
514
- module Math
515
-
516
- [:sin, :cos, :tan].each do |fun|
517
- define_method fun do |x|
518
- x = Units.u{x.in(rad)} if x.kind_of?(Measure)
519
- ::Math.send(fun, x)
520
- end
521
- module_function fun
522
- end
523
-
524
- [:asin, :acos, :atan].each do |fun|
525
- define_method fun do |x|
526
- if x.kind_of?(Measure)
527
- raise ArgumentError,"Invalid dimensions for #{fun} argument" unless x.dimensionless?
528
- x = x.magnitude
529
- end
530
- Units.u{::Math.send(fun, x)*rad}
531
- end
532
- module_function fun
533
- end
534
-
535
- module_function
536
- def atan2(x,y)
537
- if x.kind_of?(Measure)
538
- if y.kind_of?(Measure)
539
- if x.base.to_si.units != y.base.to_si.units
540
- raise ArgumentError,"Inconsistent units for atan2 arguments #{x.u}, #{y.u}"
541
- end
542
- # or x = x.to_si.magnitude, y=y.to_si.magnitude
543
- y = y.in(x.units)
544
- x = x.magnitude
545
- else
546
- raise ArgumentError,"Invalid dimensions for atan2 argument #{x.u}" unless x.dimensionless?
547
- x = x.magnitude
548
- end
549
- elsif y.kind_of?(Measure)
550
- raise ArgumentError,"Invalid dimensions for atan2 argument #{y.u}" unless y.dimensionless?
551
- y = y.magnitude
552
- end
553
- Units.u{::Math.atan2(x,y)*rad}
554
- end
555
-
556
- end
557
-
558
-
559
11
  # This must be included in any module or class from which units expressions
560
12
  # are to be used in units or u blocks.
561
13
  # It is not needed in Ruby 1.9.1 due to they way constant loop-up is done in that version,
@@ -571,101 +23,9 @@ module Units
571
23
  end
572
24
  end
573
25
  end
574
-
575
- include UseBlocks
576
-
577
- # Units definitions
578
-
579
- # declare SI base units
580
- si_units :mass, :kg # m
581
- si_units :length, :m # l
582
- si_units :time, :s # t
583
- si_units :electric_current, :A # I
584
- si_units :temperature, :K # T
585
- si_units :luminous_intensity, :cd # Iv
586
- si_units :amount_of_substance, :mol # n
587
-
588
- # define base units
589
- define :g, 'gram', :mass, 1E-3
590
- define :m, 'meter', :length, 1.0
591
- define :s, 'second', :time, 1.0
592
- define :A, 'ampere', :electric_current, 1.0
593
- define :K, 'kelvin', :temperature, 1.0
594
- define :cd,'candela',:luminous_intensity, 1.0
595
- define :mol,'mole', :amount_of_substance, 1.0
596
-
597
- # declare derived quantities with no named units
598
- si_units :speed, u{m/s}
599
- si_units :acceleration, u{m/s**2}
600
- si_units :area, u{m**2}
601
- si_units :volume, u{m**3}
602
-
603
- # derived quantities with named units
604
- define :W, 'Watt', :power, u{kg*m**2/s**3} # J/s
605
- define :Hz, 'herz', :frequency, u{1/s}
606
- define :N, 'newton', :force, u{m*kg/s**2}
607
- define :Pa, 'pascal', :pressure, u{N/m**2}
608
- define :J, 'joule', :energy, u{N*m}
609
- define :C, 'coulomb', :electric_charge, u{s*A}
610
- define :V, 'volt', :voltage, u{W/A}
611
- define :F, 'farad', :electric_capacitance, u{C/V}
612
- define :Ω, 'ohm', :electric_resistance, u{V/A} # ohm: Ω omega: Ω
613
- define :S, 'siemens', :electric_condctance, u{1/Ω}
614
- define :Wb, 'weber', :magnetic_flux, u{J/A}
615
- define :T, 'tesla', :magnetic_field, u{N/(A*m)}
616
- define :H, 'henry', :inductance, u{Wb/A}
617
- define :rad, 'radian', :angle, u{m/m}
618
- define :sr, 'steradian', :solid_angle, u{m**2/m**2}
619
- define :lm, 'lumen', :luminous_flux, u{cd*sr}
620
- define :lx, 'lux', :illuminance, u{lm/m**2}
621
- define :Bq, 'bequerel', :radioactivity, u{1/s}
622
- define :Gy, 'gray', :absorbed_dose, u{J/kg}
623
- define :Sv, 'sievert', :equivalent_dose, u{J/kg}
624
- define :kat, 'katal', :catalytic_activity, u{mol/s}
625
-
626
- # Other units
627
-
628
- define :min, 'minute', 60, :s
629
- define :h, 'hour', 60, :min
630
- define :d, 'day', 24, :h
631
- define :mi, 'mile', 1.609344, :km
632
- define :in, 'inch', 2.54, :cm
633
- define :ft, 'foot', 0.3048, :m
634
- define :inch, 'inch', 1, :in # alternative to avoid having to use self.in (in is a Ruby keyword)
635
- define :lb, 'pound', 0.45359237, :kg
636
26
 
637
- define :°C, 'degree Celsius', 1, :K, +273.15
638
- define :°F, 'degree Fahrenheit', 5.0/9.0, :K, +459.67
639
- define :R, 'rankine', 5.0/9.0, :K
640
-
641
- define :l, 'litre', u{dm**3}
642
- define :L, 'litre', 1, :l
643
-
644
- define :°, 'degree', ::Math::PI/180.0, :rad
645
- define :′, 'arc-minute', ::Math::PI/180.0/60.0, :rad
646
- define :″, 'arc-second', ::Math::PI/180.0/3600.0, :rad
647
- # not so cool, but easier to type alternatives:
648
- define :deg, 'degree', 1, :°
649
- define :arcmin, 'arc-minute', 1, :′
650
- define :arcsec, 'arc-second', 1, :″
651
-
652
- define :g0, 'standard gravity', u{9.80665*m/s**2}
653
-
654
- define :bar, 'bar', 1E5, :Pa
655
- define :atm, 'atmosphere', 101325.0, :Pa
656
- define :mWC, 'meters of water column', u{1E3*kg*g0/m**2}
657
- define :Torr, 'torricelli', u{atm/760}
658
- define :mHg, 'mHg', u{13.5951E3*kg*g0/m**2}
659
-
660
- # define :kp, 'kilopond', :force, u{kg*g0} # or define pond?
661
- define :gf, 'gram-force', u{g*g0} # kilopond kp = kgf
662
- define :lbf, 'pound-force', u{lb*g0}
663
-
664
- define :dyn, 'dyne', 10, :µN # u{1*g*cm/s**2}
665
- define :galUS, 'U.S. liquid gallon', u{231*self.in**3}
666
- define :galUK, 'Imperial gallon', 4.546092, :l
667
- define :hp, 'horsepower', u{550*ft*lbf/s}
668
-
669
- define :psi, 'pounds-force per square inch', u{lbf/self.in**2}
27
+ include UseBlocks
670
28
 
671
29
  end # Units
30
+
31
+ require 'units/definitions'