phys-units 0.9.2 → 0.9.3
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.
- checksums.yaml +4 -4
- data/README.md +16 -14
- data/lib/phys/units/errors.rb +1 -6
- data/lib/phys/units/jp.rb +169 -0
- data/lib/phys/units/load_units.rb +2 -3
- data/lib/phys/units/mixin.rb +6 -0
- data/lib/phys/units/parse.rb +4 -4
- data/lib/phys/units/parse.y +6 -6
- data/lib/phys/units/quantity.rb +119 -95
- data/lib/phys/units/quanty.rb +10 -0
- data/lib/phys/units/unit.rb +280 -83
- data/lib/phys/units/unit_class.rb +29 -11
- data/lib/phys/units/utils.rb +3 -2
- data/lib/phys/units/version.rb +1 -1
- data/misc/mkjpspec.rb +149 -0
- data/misc/mkunitspec.rb +60 -0
- data/misc/readme.jp.md +6 -0
- data/spec/{units_dat_spec.rb → all_units_spec.rb} +0 -0
- data/spec/jp_units_spec.rb +256 -0
- data/spec/quantity_spec.rb +51 -9
- data/spec/unit_spec.rb +2 -2
- metadata +11 -4
data/lib/phys/units/unit.rb
CHANGED
@@ -9,61 +9,110 @@
|
|
9
9
|
|
10
10
|
module Phys
|
11
11
|
|
12
|
+
# Phys::Unit is a class to represent Physical Unit of Measure.
|
13
|
+
# It must have:
|
14
|
+
# * *Factor* of the unit. Conversion factor to +dimension+,
|
15
|
+
# i.e., its base units.
|
16
|
+
# * *Dimension* of the unit.
|
17
|
+
# Dimension is a hash table with base units and dimension values.
|
18
|
+
# Example:
|
19
|
+
# Phys::Unit["N"].dimension #=> {"kg"=>1, "m"=>1, "s"=>-2}
|
20
|
+
#== Usage
|
21
|
+
# require "phys/units"
|
22
|
+
# Q = Phys::Quantity
|
23
|
+
# U = Phys::Unit
|
24
|
+
#
|
25
|
+
# U["miles"] / U["hr"] #=> #<Phys::Unit 0.44704,{"m"=>1, "s"=>-1}>
|
26
|
+
# U["hr"] + U["30 min"] #=> #<Phys::Unit 5400,{"s"=>1}>
|
27
|
+
# U["(m/s)"]**2 #=> #<Phys::Unit 1,{"m"=>2, "s"=>-2}>
|
28
|
+
#
|
29
|
+
# case Q[1,"miles/hr"]
|
30
|
+
# when U["m"]
|
31
|
+
# "length"
|
32
|
+
# when U["s"]
|
33
|
+
# "time"
|
34
|
+
# when U["m/s"]
|
35
|
+
# "velocity"
|
36
|
+
# else
|
37
|
+
# "other"
|
38
|
+
# end #=> "velocity"
|
12
39
|
class Unit
|
13
40
|
|
41
|
+
# @visibility private
|
14
42
|
LIST = {}
|
43
|
+
# @visibility private
|
15
44
|
PREFIX = {}
|
16
45
|
|
46
|
+
# @visibility private
|
17
47
|
def self.prefix_regex
|
18
48
|
@@prefix_regex
|
19
49
|
end
|
20
50
|
|
21
|
-
|
51
|
+
# Initialize a new unit.
|
52
|
+
# @overload initialize(factor,dimension=nil)
|
53
|
+
# @param [Numeric] factor Unit conversion factor.
|
54
|
+
# @param [Hash] dimension Dimension hash.
|
55
|
+
# @overload initialize(expr,name=nil)
|
56
|
+
# @param [String] expr Unit string to be parsed later.
|
57
|
+
# @param [String] name Name of this unit.
|
58
|
+
# @overload initialize(unit,name=nil)
|
59
|
+
# @param [Phys::Unit] unit Copy contents from the argument.
|
60
|
+
# @param [String] name Name of this unit.
|
61
|
+
# @raise [TypeError] if invalit arg types.
|
62
|
+
#
|
63
|
+
def initialize(arg,extr=nil)
|
22
64
|
case arg
|
23
65
|
when Numeric
|
24
66
|
arg = Rational(arg) if Integer===arg
|
25
67
|
@factor = arg
|
26
|
-
alloc_dim(
|
68
|
+
alloc_dim(extr)
|
27
69
|
when Phys::Unit
|
28
|
-
|
70
|
+
@factor = arg.factor
|
71
|
+
alloc_dim arg.dim
|
72
|
+
@name = extr
|
29
73
|
when String
|
30
|
-
@
|
31
|
-
|
32
|
-
@factor = expr.factor
|
33
|
-
@offset = expr.offset
|
34
|
-
alloc_dim expr.dim
|
35
|
-
else
|
36
|
-
@expr = expr
|
37
|
-
end
|
74
|
+
@expr = arg
|
75
|
+
@name = extr
|
38
76
|
else
|
39
77
|
raise TypeError,"invalid argument : #{arg.inspect}"
|
40
78
|
end
|
41
79
|
end
|
42
80
|
|
43
|
-
|
81
|
+
# Unit expression to be parsed.
|
82
|
+
# @return [String, NilClass]
|
83
|
+
attr_reader :expr
|
84
|
+
|
85
|
+
# @visibility private
|
86
|
+
attr_reader :offset
|
87
|
+
# @visibility private
|
88
|
+
attr_reader :name
|
44
89
|
|
45
|
-
|
90
|
+
# Dimension hash.
|
91
|
+
# @example
|
92
|
+
# Phys::Unit["N"].dimension #=> {"kg"=>1, "m"=>1, "s"=>-2}
|
93
|
+
# @return [Hash]
|
94
|
+
def dimension
|
46
95
|
use_dimension
|
47
96
|
@dim
|
48
97
|
end
|
49
|
-
alias dimension
|
98
|
+
alias dim dimension
|
50
99
|
|
100
|
+
# Conversion factor except the dimension-value.
|
101
|
+
# @return [Numeric]
|
51
102
|
def factor
|
52
103
|
use_dimension
|
53
104
|
@factor
|
54
105
|
end
|
55
106
|
|
107
|
+
# Dimension value. Returns PI number for pi dimension,
|
108
|
+
# otherwise returns one. see BaseUnit.
|
109
|
+
# @return [Numeric]
|
56
110
|
def dimension_value
|
57
111
|
1
|
58
112
|
end
|
59
113
|
|
60
|
-
|
61
|
-
|
62
|
-
@factor = x.factor
|
63
|
-
@offset = x.offset
|
64
|
-
alloc_dim x.dim
|
65
|
-
end
|
66
|
-
|
114
|
+
# (internal use)
|
115
|
+
# @visibility private
|
67
116
|
def alloc_dim(hash=nil)
|
68
117
|
case hash
|
69
118
|
when Hash
|
@@ -74,32 +123,40 @@ module Phys
|
|
74
123
|
@dim.default = 0
|
75
124
|
end
|
76
125
|
|
126
|
+
# (internal use)
|
127
|
+
# Parse @expr string if it has not been parsed yet.
|
128
|
+
# This function must be called before access to @dim or @factor.
|
129
|
+
# @return [nil]
|
130
|
+
# @raise [UnitError] if unit parse error.
|
131
|
+
# @visibility private
|
77
132
|
def use_dimension
|
78
133
|
return if @dim && @factor
|
79
134
|
if @expr && @dim.nil?
|
80
|
-
puts "unit='#{@name}', parsing '#{@expr}'..." if Unit.debug
|
135
|
+
#puts "unit='#{@name}', parsing '#{@expr}'..." if Unit.debug
|
81
136
|
unit = Unit.parse(@expr)
|
82
137
|
case unit
|
83
138
|
when Unit
|
84
139
|
@dim = unit.dim
|
85
140
|
@factor = unit.factor
|
86
141
|
if @dim.nil? || @factor.nil?
|
87
|
-
raise
|
142
|
+
raise UnitError,"parse error : #{unit.inspect}"
|
88
143
|
end
|
89
144
|
when Numeric
|
90
145
|
@factor = unit
|
91
146
|
alloc_dim
|
92
147
|
else
|
93
|
-
raise
|
148
|
+
raise UnitError,"parse error : #{self.inspect}"
|
94
149
|
end
|
95
150
|
else
|
96
|
-
raise
|
151
|
+
raise UnitError,"undefined unit?: #{self.inspect}"
|
97
152
|
end
|
98
153
|
end
|
99
154
|
|
155
|
+
# Inspect string.
|
156
|
+
# @return [String]
|
100
157
|
def inspect
|
101
158
|
a = [Utils.num_inspect(@factor), @dim.inspect]
|
102
|
-
a << "@name="+@name.inspect if @name
|
159
|
+
#a << "@name="+@name.inspect if @name
|
103
160
|
a << "@expr="+@expr.inspect if @expr
|
104
161
|
a << "@offset="+@offset.inspect if @offset
|
105
162
|
a << "@dimensionless=true" if @dimensionless
|
@@ -110,6 +167,8 @@ module Phys
|
|
110
167
|
"#<#{self.class} #{s}>"
|
111
168
|
end
|
112
169
|
|
170
|
+
# Make unit string from dimension.
|
171
|
+
# @return [String]
|
113
172
|
def unit_string
|
114
173
|
use_dimension
|
115
174
|
a = []
|
@@ -125,8 +184,8 @@ module Phys
|
|
125
184
|
end
|
126
185
|
alias string_form unit_string
|
127
186
|
|
128
|
-
#
|
129
|
-
|
187
|
+
# Conversion Factor to base unit.
|
188
|
+
# @return [Numeric]
|
130
189
|
def conversion_factor
|
131
190
|
use_dimension
|
132
191
|
f = @factor
|
@@ -141,39 +200,77 @@ module Phys
|
|
141
200
|
f
|
142
201
|
end
|
143
202
|
|
203
|
+
# Returns true if scalar unit.
|
204
|
+
# *Scalar* means the unit does not have any dimension
|
205
|
+
# including dimensionless-dimension, and its factor is one.
|
206
|
+
# @return [Boolean]
|
144
207
|
def scalar?
|
145
208
|
use_dimension
|
146
209
|
(@dim.nil? || @dim.empty?) && @factor==1
|
147
210
|
end
|
148
211
|
|
212
|
+
# (internal use)
|
213
|
+
# @visibility private
|
149
214
|
def dimensionless_deleted
|
150
215
|
use_dimension
|
151
216
|
hash = @dim.dup
|
152
217
|
hash.delete_if{|k,v| LIST[k].dimensionless?}
|
153
218
|
end
|
154
219
|
|
220
|
+
# (internal use)
|
155
221
|
def dimensionless?
|
156
222
|
use_dimension
|
157
223
|
@dim.each_key.all?{|k| LIST[k].dimensionless?}
|
158
224
|
end
|
159
225
|
|
160
|
-
|
161
|
-
|
226
|
+
# (internal use)
|
227
|
+
# @visibility private
|
228
|
+
def same_dimension?(unit)
|
229
|
+
dimensionless_deleted == unit.dimensionless_deleted
|
162
230
|
end
|
163
231
|
alias same_dim? same_dimension?
|
164
232
|
|
233
|
+
# (internal use)
|
234
|
+
# @visibility private
|
235
|
+
# @raise [UnitError] if not dimensionless.
|
165
236
|
def assert_dimensionless
|
166
237
|
if !dimensionless?
|
167
|
-
raise
|
238
|
+
raise UnitError,"Not dimensionless: #{self.inspect}"
|
168
239
|
end
|
169
240
|
end
|
170
241
|
|
171
|
-
|
172
|
-
|
173
|
-
|
242
|
+
# (internal use)
|
243
|
+
# @visibility private
|
244
|
+
# @raise [UnitError] if different dimensions.
|
245
|
+
def assert_same_dimension(unit)
|
246
|
+
if !same_dimension?(unit)
|
247
|
+
raise UnitError,"Different dimension: #{self.inspect} and #{unit.inspect}"
|
174
248
|
end
|
175
249
|
end
|
176
250
|
|
251
|
+
# Comformability of units. Returns true if unit conversion is allowed.
|
252
|
+
# @param [Object] x other object (unit or quantity or numeric or other)
|
253
|
+
# @return [Boolean]
|
254
|
+
def conformable?(x)
|
255
|
+
case x
|
256
|
+
when Unit
|
257
|
+
dimensionless_deleted == x.dimensionless_deleted
|
258
|
+
when Quantity
|
259
|
+
dimensionless_deleted == x.unit.dimensionless_deleted
|
260
|
+
when Numeric
|
261
|
+
dimensionless?
|
262
|
+
else
|
263
|
+
false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
alias === conformable?
|
267
|
+
alias compatible? conformable?
|
268
|
+
alias conversion_allowed? conformable?
|
269
|
+
|
270
|
+
# Convert a quantity to this unit.
|
271
|
+
# @param [Phys::Quantity] quantity to be converted.
|
272
|
+
# @return [Phys::Quantity]
|
273
|
+
# @raise [UnitError] if unit conversion is failed.
|
177
274
|
def convert(quantity)
|
178
275
|
if Quantity===quantity
|
179
276
|
assert_same_dimension(quantity.unit)
|
@@ -184,55 +281,75 @@ module Phys
|
|
184
281
|
end
|
185
282
|
end
|
186
283
|
|
284
|
+
# Convert a quantity to this unit only in scale.
|
285
|
+
# @param [Phys::Quantity] quantity to be converted.
|
286
|
+
# @return [Phys::Quantity]
|
287
|
+
# @raise [UnitError] if unit conversion is failed.
|
187
288
|
def convert_scale(quantity)
|
188
289
|
convert(quantity)
|
189
290
|
end
|
190
291
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
x / conversion_factor
|
292
|
+
# Convert from a value in this unit to a value in base unit.
|
293
|
+
# @param [Numeric] value
|
294
|
+
# @return [Numeric]
|
295
|
+
def convert_value_to_base_unit(value)
|
296
|
+
value * conversion_factor
|
197
297
|
end
|
198
298
|
|
199
|
-
|
200
|
-
|
201
|
-
|
299
|
+
# Convert from a value in base unit to a value in this unit.
|
300
|
+
# @param [Numeric] value
|
301
|
+
# @return [Numeric]
|
302
|
+
def convert_value_from_base_unit(value)
|
303
|
+
value / conversion_factor
|
202
304
|
end
|
203
305
|
|
306
|
+
# Returns numeric value of this unit, i.e. conversion factor.
|
307
|
+
# Raises UnitError if not dimensionless.
|
308
|
+
# @return [Numeric]
|
309
|
+
# @raise [UnitError] if not dimensionless.
|
204
310
|
def to_numeric
|
205
311
|
assert_dimensionless
|
206
312
|
conversion_factor
|
207
313
|
end
|
208
314
|
alias to_num to_numeric
|
209
315
|
|
210
|
-
def convert_to_float(x)
|
211
|
-
convert_to_numeric(x).to_f
|
212
|
-
end
|
213
316
|
|
317
|
+
# Returns Base Unit excluding dimensionless-dimension.
|
318
|
+
# @return [Phys::Unit]
|
214
319
|
def base_unit
|
215
320
|
Unit.new(1,dimensionless_deleted)
|
216
321
|
end
|
217
322
|
|
218
|
-
|
323
|
+
#--
|
219
324
|
|
325
|
+
# Return true if this unit is operable.
|
326
|
+
# @return [Boolean]
|
220
327
|
def operable?
|
221
328
|
true
|
222
329
|
end
|
223
330
|
|
331
|
+
# Raise error if this unit is not operable.
|
332
|
+
# @return [nil]
|
333
|
+
# @visibility private
|
224
334
|
def check_operable
|
225
335
|
if !operable?
|
226
|
-
raise
|
336
|
+
raise UnitError,"non-operable for #{inspect}"
|
227
337
|
end
|
338
|
+
nil
|
228
339
|
end
|
229
340
|
|
230
|
-
|
231
|
-
|
232
|
-
|
341
|
+
# Raise error if this unit or argument is not operable.
|
342
|
+
# @return [nil]
|
343
|
+
# @visibility private
|
344
|
+
def check_operable2(unit)
|
345
|
+
if !(operable? && unit.operable?)
|
346
|
+
raise UnitError,"non-operable: #{inspect} and #{unit.inspect}"
|
233
347
|
end
|
348
|
+
nil
|
234
349
|
end
|
235
350
|
|
351
|
+
# (internal use)
|
352
|
+
# @visibility private
|
236
353
|
def dimension_binop(other)
|
237
354
|
x = self.dim
|
238
355
|
y = other.dim
|
@@ -241,7 +358,7 @@ module Phys
|
|
241
358
|
keys = x.keys | y.keys
|
242
359
|
dims = {}
|
243
360
|
dims.default = 0
|
244
|
-
keys.each do |k|
|
361
|
+
keys.each do |k|
|
245
362
|
v = yield( x[k]||0, y[k]||0 )
|
246
363
|
dims[k] = v if v!=0
|
247
364
|
end
|
@@ -254,6 +371,8 @@ module Phys
|
|
254
371
|
end
|
255
372
|
end
|
256
373
|
|
374
|
+
# (internal use)
|
375
|
+
# @visibility private
|
257
376
|
def dimension_uop
|
258
377
|
x = self.dim
|
259
378
|
if Hash===x
|
@@ -269,6 +388,11 @@ module Phys
|
|
269
388
|
end
|
270
389
|
end
|
271
390
|
|
391
|
+
# Addition of units.
|
392
|
+
# Both units must be operable and conversion-allowed.
|
393
|
+
# @param [Phys::Unit, Numeric] x other unit
|
394
|
+
# @return [Phys::Unit]
|
395
|
+
# @raise [Phys::UnitError] if unit conversion is failed.
|
272
396
|
def +(x)
|
273
397
|
x = Unit.cast(x)
|
274
398
|
check_operable2(x)
|
@@ -276,6 +400,11 @@ module Phys
|
|
276
400
|
Unit.new(@factor+x.factor,@dim.dup)
|
277
401
|
end
|
278
402
|
|
403
|
+
# Subtraction of units.
|
404
|
+
# Both units must be operable and conversion-allowed.
|
405
|
+
# @param [Phys::Unit, Numeric] x other unit
|
406
|
+
# @return [Phys::Unit]
|
407
|
+
# @raise [Phys::UnitError] if not conformable unit conversion is failed.
|
279
408
|
def -(x)
|
280
409
|
x = Unit.cast(x)
|
281
410
|
check_operable2(x)
|
@@ -283,16 +412,28 @@ module Phys
|
|
283
412
|
Unit.new(@factor-x.factor,@dim.dup)
|
284
413
|
end
|
285
414
|
|
415
|
+
# Unary minus.
|
416
|
+
# This unit must be operable.
|
417
|
+
# @return [Phys::Unit]
|
418
|
+
# @raise [Phys::UnitError] if not operable.
|
286
419
|
def -@
|
287
420
|
check_operable
|
288
421
|
use_dimension
|
289
422
|
Unit.new(-@factor,@dim.dup)
|
290
423
|
end
|
291
424
|
|
425
|
+
# Unary plus.
|
426
|
+
# Returns self.
|
427
|
+
# @return [Phys::Unit]
|
292
428
|
def +@
|
293
429
|
self
|
294
430
|
end
|
295
431
|
|
432
|
+
# Multiplication of units.
|
433
|
+
# Both units must be operable.
|
434
|
+
# @param [Phys::Unit, Numeric] x other unit
|
435
|
+
# @return [Phys::Unit]
|
436
|
+
# @raise [Phys::UnitError] if not operable.
|
296
437
|
def *(x)
|
297
438
|
x = Unit.cast(x)
|
298
439
|
if scalar?
|
@@ -306,10 +447,15 @@ module Phys
|
|
306
447
|
Unit.new(factor,dims)
|
307
448
|
end
|
308
449
|
|
450
|
+
# Division of units.
|
451
|
+
# Both units must be operable.
|
452
|
+
# @param [Phys::Unit, Numeric] x other unit
|
453
|
+
# @return [Phys::Unit]
|
454
|
+
# @raise [Phys::UnitError] if not operable.
|
309
455
|
def /(x)
|
310
456
|
x = Unit.cast(x)
|
311
457
|
if scalar?
|
312
|
-
return x.
|
458
|
+
return x.inverse
|
313
459
|
elsif x.scalar?
|
314
460
|
return self
|
315
461
|
end
|
@@ -319,10 +465,15 @@ module Phys
|
|
319
465
|
Unit.new(factor,dims)
|
320
466
|
end
|
321
467
|
|
468
|
+
# Rational division of units.
|
469
|
+
# Both units must be operable.
|
470
|
+
# @param [Phys::Unit, Numeric] x other unit
|
471
|
+
# @return [Phys::Unit]
|
472
|
+
# @raise [Phys::UnitError] if not operable.
|
322
473
|
def rdiv(x)
|
323
474
|
x = Unit.cast(x)
|
324
475
|
if scalar?
|
325
|
-
return x.
|
476
|
+
return x.inverse
|
326
477
|
elsif x.scalar?
|
327
478
|
return self
|
328
479
|
end
|
@@ -332,20 +483,32 @@ module Phys
|
|
332
483
|
Unit.new(factor,dims)
|
333
484
|
end
|
334
485
|
|
486
|
+
# @visibility private
|
335
487
|
def self.rdiv(x,y)
|
336
488
|
Unit.cast(x).rdiv(y)
|
337
489
|
end
|
338
490
|
|
339
|
-
|
491
|
+
# Inverse of units.
|
492
|
+
# This unit must be operable.
|
493
|
+
# @param [Phys::Unit, Numeric] unit
|
494
|
+
# @return [Phys::Unit]
|
495
|
+
# @raise [Phys::UnitError] if not operable.
|
496
|
+
def inverse
|
340
497
|
check_operable
|
341
498
|
dims = dimension_uop{|a| -a}
|
342
499
|
Unit.new(Rational(1,self.factor), dims)
|
343
500
|
end
|
344
501
|
|
345
|
-
|
346
|
-
|
502
|
+
# @visibility private
|
503
|
+
def self.inverse(x)
|
504
|
+
Unit.cast(x).inverse
|
347
505
|
end
|
348
506
|
|
507
|
+
# Exponentiation of units.
|
508
|
+
# This units must be operable.
|
509
|
+
# @param [Numeric] x numeric
|
510
|
+
# @return [Phys::Unit]
|
511
|
+
# @raise [Phys::UnitError] if not operable.
|
349
512
|
def **(x)
|
350
513
|
check_operable
|
351
514
|
m = Utils.as_numeric(x)
|
@@ -353,18 +516,31 @@ module Phys
|
|
353
516
|
Unit.new(@factor**m,dims)
|
354
517
|
end
|
355
518
|
|
519
|
+
# @visibility private
|
356
520
|
def self.func(fn, x)
|
357
521
|
fn = 'log' if fn == 'ln'
|
358
522
|
m = Unit.new(x).to_numeric
|
359
523
|
Unit.new( Math.send(fn,m) )
|
360
524
|
end
|
361
525
|
|
526
|
+
# Equality of units
|
527
|
+
# @param [Object] x other unit or object
|
528
|
+
# @return [Boolean]
|
362
529
|
def ==(x)
|
530
|
+
case x
|
531
|
+
when Numeric
|
532
|
+
x = Unit.cast(x)
|
533
|
+
when Unit
|
534
|
+
else
|
535
|
+
return false
|
536
|
+
end
|
363
537
|
use_dimension
|
364
|
-
@factor == x.factor && @dim == x.dim &&
|
538
|
+
@factor == x.factor && @dim == x.dim &&
|
365
539
|
offset == x.offset && dimension_value == x.dimension_value
|
366
540
|
end
|
367
541
|
|
542
|
+
# Coerce.
|
543
|
+
# @return [Array]
|
368
544
|
def coerce(x)
|
369
545
|
[Unit.find_unit(x), self]
|
370
546
|
end
|
@@ -372,27 +548,30 @@ module Phys
|
|
372
548
|
end # Unit
|
373
549
|
|
374
550
|
|
551
|
+
# BaseUnit is a class to represent units defined by "!" in unit.dat
|
552
|
+
# including SI units.
|
375
553
|
class BaseUnit < Unit
|
376
|
-
|
377
|
-
|
554
|
+
|
555
|
+
def self.define(name,expr,dimval=nil)
|
556
|
+
dimles = (expr == "!dimensionless")
|
557
|
+
LIST[name] = self.new(name,dimles,dimval)
|
558
|
+
end
|
559
|
+
|
560
|
+
def initialize(name,dimless=false,dimval=nil)
|
561
|
+
case name
|
378
562
|
when String
|
379
|
-
@name =
|
563
|
+
@name = name
|
380
564
|
@factor = 1
|
381
|
-
@dim = {
|
565
|
+
@dim = {name=>1}
|
382
566
|
@dim.default = 0
|
383
567
|
@dimensionless = dimless
|
384
|
-
@dimension_value =
|
568
|
+
@dimension_value = dimval || 1
|
385
569
|
else
|
386
570
|
raise ArgumentError "BaseUnit#initialize: arg must be string: #{s}"
|
387
571
|
end
|
388
572
|
end
|
389
573
|
|
390
|
-
|
391
|
-
super(x)
|
392
|
-
@dimensionless = x.dimensionless
|
393
|
-
@dimension_value = x.dimension_value
|
394
|
-
end
|
395
|
-
|
574
|
+
# @visibility private
|
396
575
|
def use_dimension
|
397
576
|
end
|
398
577
|
|
@@ -400,6 +579,7 @@ module Phys
|
|
400
579
|
@dimensionless
|
401
580
|
end
|
402
581
|
|
582
|
+
# @visibility private
|
403
583
|
def dimensionless_deleted
|
404
584
|
if @dimensionless
|
405
585
|
{}
|
@@ -408,42 +588,59 @@ module Phys
|
|
408
588
|
end
|
409
589
|
end
|
410
590
|
|
591
|
+
# Dimension value.
|
592
|
+
# Returns PI number for pi dimension, otherwise returns one.
|
593
|
+
# @return [Numeric]
|
594
|
+
# @example
|
595
|
+
# Phys::Unit["pi"].dimension_value #=> 3.141592653589793
|
411
596
|
attr_reader :dimension_value
|
412
597
|
end
|
413
598
|
|
414
599
|
|
600
|
+
# OffsetUnit is a class to represent units with offset value.
|
601
|
+
# Focused on Farenheight/Celsius temperature.
|
415
602
|
class OffsetUnit < Unit
|
416
603
|
|
417
604
|
def self.define(name,unit,offset=nil)
|
418
|
-
LIST[name] = self.new(name,
|
605
|
+
LIST[name] = self.new(unit,name,offset)
|
419
606
|
end
|
420
607
|
|
421
|
-
def initialize(name,
|
422
|
-
super(name,arg)
|
423
|
-
@offset = offset
|
608
|
+
def initialize(arg,name=nil,offset=nil)
|
424
609
|
if offset.nil?
|
425
610
|
raise ArgumentError,"offset is not supplied"
|
426
611
|
end
|
612
|
+
super(arg,name)
|
613
|
+
@offset = offset
|
427
614
|
end
|
428
615
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
def convert_value_from_base_unit(x)
|
434
|
-
(x - @offset) / conversion_factor
|
435
|
-
end
|
436
|
-
|
616
|
+
# Convert a quantity to this unit only in scale.
|
617
|
+
# @param [Phys::Quantity] quantity to be converted.
|
618
|
+
# @return [Phys::Quantity]
|
619
|
+
# @raise [UnitError] if unit conversion is failed.
|
437
620
|
def convert_scale(quantity)
|
438
621
|
if Quantity===quantity
|
439
|
-
assert_same_dimension(quantity.unit)
|
622
|
+
assert_same_dimension(quantity.unit)
|
440
623
|
v = quantity.value * quantity.unit.conversion_factor
|
441
624
|
v = v / self.conversion_factor
|
442
625
|
else
|
443
|
-
raise
|
626
|
+
raise UnitError,"not Quantitiy: #{quantity.inspect}"
|
444
627
|
end
|
445
628
|
end
|
446
629
|
|
630
|
+
# Convert from a value in this unit to a value in base unit.
|
631
|
+
# @param [Numeric] value
|
632
|
+
# @return [Numeric]
|
633
|
+
def convert_value_to_base_unit(value)
|
634
|
+
value * conversion_factor + @offset
|
635
|
+
end
|
636
|
+
|
637
|
+
# Convert from a value in base unit to a value in this unit.
|
638
|
+
# @param [Numeric] value
|
639
|
+
# @return [Numeric]
|
640
|
+
def convert_value_from_base_unit(value)
|
641
|
+
(value - @offset) / conversion_factor
|
642
|
+
end
|
643
|
+
|
447
644
|
def operable?
|
448
645
|
false
|
449
646
|
end
|