ruby-units 1.1.5 → 1.2.0.a

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -1,5 +1,7 @@
1
1
  Change Log for Ruby-units
2
2
  =========================
3
+ 2010-11-07 1.2.0.a * a bunch of fixes to make ruby-units ruby 1.9 compatible
4
+ (ruby 1.9.3dev (2010-11-07 trunk 29711) [i386-darwin9.8.0])
3
5
  2010-03-16 1.1.5 * another bugfix, and update url to point to github
4
6
  2010-03-15 1.1.4 * fixed a couple of outstanding bugs
5
7
  2007-12-13 1.1.3 * fixed a minor bug with string %
data/lib/ruby-units.rb CHANGED
@@ -2,10 +2,10 @@ require 'ruby_units/array'
2
2
  require 'ruby_units/date'
3
3
  require 'ruby_units/time'
4
4
  require 'ruby_units/math'
5
+ require 'ruby_units/complex'
5
6
  require 'ruby_units/numeric'
6
7
  require 'ruby_units/object'
7
8
  require 'ruby_units/string'
8
- require 'ruby_units/complex'
9
9
  require 'ruby_units/units'
10
10
  require 'ruby_units/ruby-units'
11
11
 
data/lib/ruby_units.rb CHANGED
@@ -2,10 +2,10 @@ require 'ruby_units/array'
2
2
  require 'ruby_units/date'
3
3
  require 'ruby_units/time'
4
4
  require 'ruby_units/math'
5
+ require 'ruby_units/complex'
5
6
  require 'ruby_units/numeric'
6
7
  require 'ruby_units/object'
7
8
  require 'ruby_units/string'
8
- require 'ruby_units/complex'
9
9
  require 'ruby_units/units'
10
10
  require 'ruby_units/ruby-units'
11
11
 
@@ -1,7 +1,7 @@
1
1
  class Complex < Numeric
2
2
  def to_unit(other = nil)
3
3
  real_unit = self.real.to_unit
4
- image_unit = self.image.to_unit
4
+ image_unit = self.imaginary.to_unit
5
5
  raise ArgumentError, 'Units on real and imaginary parts are incompatible' unless real_unit =~ image_unit
6
6
  final_unit = (real_unit.units.empty? ? image_unit.units : real_unit.units).to_unit
7
7
  final_unit * Complex(real_unit.to(final_unit).scalar, image_unit.to(final_unit).scalar)
@@ -7,10 +7,11 @@ class Date
7
7
  alias :unit_date_add :+
8
8
  def +(unit)
9
9
  case unit
10
- when Unit:
10
+ when Unit
11
11
  unit = unit.to('d').round if ['y', 'decade', 'century'].include? unit.units
12
12
  unit_date_add(unit.to('day').scalar)
13
- when Time: unit_date_add(unit.to_datetime)
13
+ when Time
14
+ unit_date_add(unit.to_datetime)
14
15
  else
15
16
  unit_date_add(unit)
16
17
  end
@@ -20,10 +21,11 @@ class Date
20
21
  alias :unit_date_sub :-
21
22
  def -(unit)
22
23
  case unit
23
- when Unit:
24
+ when Unit
24
25
  unit = unit.to('d').round if ['y', 'decade', 'century'].include? unit.units
25
26
  unit_date_sub(unit.to('day').scalar)
26
- when Time: unit_date_sub(unit.to_datetime)
27
+ when Time
28
+ unit_date_sub(unit.to_datetime)
27
29
  else
28
30
  unit_date_sub(unit)
29
31
  end
@@ -34,8 +36,10 @@ class Date
34
36
  end
35
37
  alias :unit :to_unit
36
38
 
37
- def to_time
38
- Time.local(*ParseDate.parsedate(self.to_s))
39
+ unless Date.instance_methods.include?(:to_time)
40
+ def to_time
41
+ Time.local(*ParseDate.parsedate(self.to_s))
42
+ end
39
43
  end
40
44
 
41
45
  alias :units_datetime_inspect :inspect
@@ -44,8 +48,10 @@ class Date
44
48
  self.to_s
45
49
  end
46
50
 
47
- def to_date
48
- Date.civil(self.year, self.month, self.day)
51
+ unless Date.instance_methods.include?(:to_date)
52
+ def to_date
53
+ Date.civil(self.year, self.month, self.day)
54
+ end
49
55
  end
50
56
 
51
57
  end
@@ -1,47 +1,76 @@
1
1
  # Math will convert unit objects to radians and then attempt to use the value for
2
2
  # trigonometric functions.
3
+ require 'mathn'
3
4
 
4
5
  module Math
5
- alias unit_sqrt sqrt
6
+
7
+ alias :unit_sqrt :sqrt
6
8
  def sqrt(n)
7
9
  if Unit === n
8
- (n**(1/2)).to_unit
10
+ (n**(Rational(1,2))).to_unit
9
11
  else
10
12
  unit_sqrt(n)
11
13
  end
12
14
  end
15
+ module_function :unit_sqrt
16
+ module_function :sqrt
17
+
18
+ if self.respond_to?(:cbrt)
19
+ alias :unit_cbrt :cbrt
20
+ def cbrt(n)
21
+ if Unit === n
22
+ (n**(Rational(1,3))).to_unit
23
+ else
24
+ unit_cbrt(n)
25
+ end
26
+ end
27
+ module_function :unit_cbrt
28
+ module_function :cbrt
29
+ end
13
30
 
14
- alias unit_sin sin
31
+ alias :unit_sin :sin
15
32
  def sin(n)
16
33
  Unit === n ? unit_sin(n.to('radian').scalar) : unit_sin(n)
17
34
  end
35
+ module_function :unit_sin
36
+ module_function :sin
18
37
 
19
- alias unit_cos cos
38
+ alias :unit_cos :cos
20
39
  def cos(n)
21
40
  Unit === n ? unit_cos(n.to('radian').scalar) : unit_cos(n)
22
41
  end
42
+ module_function :unit_cos
43
+ module_function :cos
23
44
 
24
- alias unit_sinh sinh
45
+ alias :unit_sinh :sinh
25
46
  def sinh(n)
26
47
  Unit === n ? unit_sinh(n.to('radian').scalar) : unit_sinh(n)
27
48
  end
49
+ module_function :unit_sinh
50
+ module_function :sinh
28
51
 
29
- alias unit_cosh cosh
52
+ alias :unit_cosh :cosh
30
53
  def cosh(n)
31
54
  Unit === n ? unit_cosh(n.to('radian').scalar) : unit_cosh(n)
32
55
  end
56
+ module_function :unit_cosh
57
+ module_function :cosh
33
58
 
34
- alias unit_tan tan
59
+ alias :unit_tan :tan
35
60
  def tan(n)
36
61
  Unit === n ? unit_tan(n.to('radian').scalar) : unit_tan(n)
37
62
  end
63
+ module_function :tan
64
+ module_function :unit_tan
38
65
 
39
- alias unit_tanh tanh
66
+ alias :unit_tanh :tanh
40
67
  def tanh(n)
41
68
  Unit === n ? unit_tanh(n.to('radian').scalar) : unit_tanh(n)
42
69
  end
70
+ module_function :unit_tanh
71
+ module_function :tanh
43
72
 
44
- alias unit_hypot hypot
73
+ alias :unit_hypot :hypot
45
74
  # Convert parameters to consistent units and perform the function
46
75
  def hypot(x,y)
47
76
  if Unit === x && Unit === y
@@ -50,38 +79,23 @@ module Math
50
79
  unit_hypot(x,y)
51
80
  end
52
81
  end
82
+ module_function :unit_hypot
83
+ module_function :hypot
53
84
 
54
- alias unit_atan2 atan2
85
+ alias :unit_atan2 :atan2
55
86
  def atan2(x,y)
56
87
  case
57
88
  when (Unit === x && Unit === y) && (x !~ y)
58
89
  raise ArgumentError, "Incompatible Units"
59
90
  when (Unit === x && Unit === y) && (x =~ y)
60
- unit_atan2(x.base_scalar, y.base_scalar)
91
+ Math::unit_atan2(x.base_scalar, y.base_scalar)
61
92
  when (Unit === x || Unit === y)
62
93
  raise ArgumentError, "Incompatible Units"
63
94
  else
64
- unit_atan2(x,y)
95
+ Math::unit_atan2(x,y)
65
96
  end
66
97
  end
67
-
68
- module_function :unit_hypot
69
- module_function :hypot
70
- module_function :unit_sqrt
71
- module_function :sqrt
72
- module_function :unit_sin
73
- module_function :sin
74
- module_function :unit_cos
75
- module_function :cos
76
- module_function :unit_sinh
77
- module_function :sinh
78
- module_function :unit_cosh
79
- module_function :cosh
80
- module_function :unit_tan
81
- module_function :tan
82
- module_function :unit_tanh
83
- module_function :tanh
84
- module_function :unit_atan2
85
- module_function :atan2
98
+ module_function :unit_atan2
99
+ module_function :atan2
86
100
 
87
- end
101
+ end
@@ -1,11 +1,11 @@
1
- require 'mathn'
2
- require 'rational'
3
1
  require 'date'
4
- require 'parsedate'
5
-
2
+ if RUBY_VERSION < "1.9"
3
+ require 'parsedate'
4
+ require 'rational'
5
+ end
6
6
  # = Ruby Units
7
7
  #
8
- # Copyright 2006 by Kevin C. Olbrich, Ph.D.
8
+ # Copyright 2006-2010 by Kevin C. Olbrich, Ph.D.
9
9
  #
10
10
  # See http://rubyforge.org/ruby-units/
11
11
  #
@@ -40,7 +40,7 @@ require 'parsedate'
40
40
  # Unit.setup
41
41
  class Unit < Numeric
42
42
  # pre-generate hashes from unit definitions for performance.
43
- VERSION = '1.1.5'
43
+ VERSION = '1.2.0.a'
44
44
  @@USER_DEFINITIONS = {}
45
45
  @@PREFIX_VALUES = {}
46
46
  @@PREFIX_MAP = {}
@@ -133,12 +133,11 @@ class Unit < Numeric
133
133
  @@OUTPUT_MAP[key]=value[0][0]
134
134
  end
135
135
  @@PREFIX_REGEX = @@PREFIX_MAP.keys.sort_by {|prefix| [prefix.length, prefix]}.reverse.join('|')
136
- @@UNIT_REGEX = @@UNIT_MAP.keys.sort_by {|unit| [unit.length, unit]}.reverse.join('|')
136
+ @@UNIT_REGEX = @@UNIT_MAP.keys.sort_by {|unit_name| [unit_name.length, unit]}.reverse.join('|')
137
137
  @@UNIT_MATCH_REGEX = /(#{@@PREFIX_REGEX})*?(#{@@UNIT_REGEX})\b/
138
138
  Unit.new(1)
139
139
  end
140
140
 
141
-
142
141
  include Comparable
143
142
  attr_accessor :scalar, :numerator, :denominator, :signature, :base_scalar, :base_numerator, :base_denominator, :output, :unit_name
144
143
 
@@ -164,11 +163,13 @@ class Unit < Numeric
164
163
 
165
164
  # basically a copy of the basic to_yaml. Needed because otherwise it ends up coercing the object to a string
166
165
  # before YAML'izing it.
167
- def to_yaml( opts = {} )
168
- YAML::quick_emit( object_id, opts ) do |out|
169
- out.map( taguri, to_yaml_style ) do |map|
170
- for m in to_yaml_properties do
171
- map.add( m[1..-1], instance_variable_get( m ) )
166
+ if RUBY_VERSION < "1.9"
167
+ def to_yaml( opts = {} )
168
+ YAML::quick_emit( object_id, opts ) do |out|
169
+ out.map( taguri, to_yaml_style ) do |map|
170
+ for m in to_yaml_properties do
171
+ map.add( m[1..-1], instance_variable_get( m ) )
172
+ end
172
173
  end
173
174
  end
174
175
  end
@@ -202,6 +203,8 @@ class Unit < Numeric
202
203
  return
203
204
  end
204
205
  if options.size == 3
206
+ options[1] = options[1].join if options[1].kind_of?(Array)
207
+ options[2] = options[2].join if options[2].kind_of?(Array)
205
208
  begin
206
209
  cached = @@cached_units["#{options[1]}/#{options[2]}"] * options[0]
207
210
  copy(cached)
@@ -212,28 +215,28 @@ class Unit < Numeric
212
215
  end
213
216
 
214
217
  case options[0]
215
- when Hash:
218
+ when Hash
216
219
  @scalar = options[0][:scalar] || 1
217
220
  @numerator = options[0][:numerator] || UNITY_ARRAY
218
221
  @denominator = options[0][:denominator] || UNITY_ARRAY
219
222
  @signature = options[0][:signature]
220
- when Array:
223
+ when Array
221
224
  initialize(*options[0])
222
225
  return
223
- when Numeric:
226
+ when Numeric
224
227
  @scalar = options[0]
225
228
  @numerator = @denominator = UNITY_ARRAY
226
- when Time:
229
+ when Time
227
230
  @scalar = options[0].to_f
228
231
  @numerator = ['<second>']
229
232
  @denominator = UNITY_ARRAY
230
- when DateTime:
233
+ when DateTime
231
234
  @scalar = options[0].ajd
232
235
  @numerator = ['<day>']
233
236
  @denominator = UNITY_ARRAY
234
- when "":
237
+ when ""
235
238
  raise ArgumentError, "No Unit Specified"
236
- when String:
239
+ when String
237
240
  parse(options[0])
238
241
  else
239
242
  raise ArgumentError, "Invalid Unit Format"
@@ -284,7 +287,7 @@ class Unit < Numeric
284
287
  # Returns 'true' if the Unit is represented in base units
285
288
  def is_base?
286
289
  return @is_base if defined? @is_base
287
- return @is_base=true if @signature == 400 && self.numerator.size == 1 && self.denominator == UNITY_ARRAY && self.units =~ /(deg|temp)K/
290
+ return @is_base=true if self.degree? && self.numerator.size == 1 && self.denominator == UNITY_ARRAY && self.units =~ /(deg|temp)K/
288
291
  n = @numerator + @denominator
289
292
  for x in n.compact do
290
293
  return @is_base=false unless x == UNITY || (@@BASE_UNITS.include?((x)))
@@ -296,40 +299,42 @@ class Unit < Numeric
296
299
  # results of the conversion are cached so subsequent calls to this will be fast
297
300
  def to_base
298
301
  return self if self.is_base?
299
- if self.units =~ /\A(deg|temp)(C|F|K|C)\Z/
302
+ if self.units =~ /\A(deg|temp)(C|F|K|C)\Z/
300
303
  @signature = 400
301
304
  base = case self.units
302
- when /temp/ : self.to('tempK')
303
- when /deg/ : self.to('degK')
305
+ when /temp/
306
+ self.to('tempK')
307
+ when /deg/
308
+ self.to('degK')
304
309
  end
305
310
  return base
306
311
  end
307
312
 
308
313
  cached = ((@@base_unit_cache[self.units] * self.scalar) rescue nil)
309
314
  return cached if cached
310
-
315
+
311
316
  num = []
312
317
  den = []
313
318
  q = 1
314
319
  for unit in @numerator.compact do
315
- if @@PREFIX_VALUES[unit]
316
- q *= @@PREFIX_VALUES[unit]
317
- else
318
- q *= @@UNIT_VALUES[unit][:scalar] if @@UNIT_VALUES[unit]
319
- num << @@UNIT_VALUES[unit][:numerator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:numerator]
320
- den << @@UNIT_VALUES[unit][:denominator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:denominator]
321
- end
320
+ if @@PREFIX_VALUES[unit]
321
+ q *= @@PREFIX_VALUES[unit]
322
+ else
323
+ q *= @@UNIT_VALUES[unit][:scalar] if @@UNIT_VALUES[unit]
324
+ num << @@UNIT_VALUES[unit][:numerator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:numerator]
325
+ den << @@UNIT_VALUES[unit][:denominator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:denominator]
326
+ end
322
327
  end
323
328
  for unit in @denominator.compact do
324
- if @@PREFIX_VALUES[unit]
325
- q /= @@PREFIX_VALUES[unit]
326
- else
327
- q /= @@UNIT_VALUES[unit][:scalar] if @@UNIT_VALUES[unit]
328
- den << @@UNIT_VALUES[unit][:numerator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:numerator]
329
- num << @@UNIT_VALUES[unit][:denominator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:denominator]
330
- end
329
+ if @@PREFIX_VALUES[unit]
330
+ q /= @@PREFIX_VALUES[unit]
331
+ else
332
+ q /= @@UNIT_VALUES[unit][:scalar] if @@UNIT_VALUES[unit]
333
+ den << @@UNIT_VALUES[unit][:numerator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:numerator]
334
+ num << @@UNIT_VALUES[unit][:denominator] if @@UNIT_VALUES[unit] && @@UNIT_VALUES[unit][:denominator]
335
+ end
331
336
  end
332
-
337
+
333
338
  num = num.flatten.compact
334
339
  den = den.flatten.compact
335
340
  num = UNITY_ARRAY if num.empty?
@@ -356,15 +361,15 @@ class Unit < Numeric
356
361
  return out
357
362
  else
358
363
  case target_units
359
- when :ft :
364
+ when :ft
360
365
  inches = self.to("in").scalar.to_int
361
366
  out = "#{(inches / 12).truncate}\'#{(inches % 12).round}\""
362
- when :lbs :
367
+ when :lbs
363
368
  ounces = self.to("oz").scalar.to_int
364
369
  out = "#{(ounces / 16).truncate} lbs, #{(ounces % 16).round} oz"
365
370
  when String
366
371
  out = case target_units
367
- when /(%[-+\.\w\d#]+)\s*(.+)*/ #format string like '%0.2f in'
372
+ when /(%[\-+\.\w#]+)\s*(.+)*/ #format string like '%0.2f in'
368
373
  begin
369
374
  if $2 #unit specified, need to convert
370
375
  self.to($2).to_s($1)
@@ -381,7 +386,7 @@ class Unit < Numeric
381
386
  end
382
387
  else
383
388
  out = case @scalar
384
- when Rational :
389
+ when Rational
385
390
  "#{@scalar} #{self.units}"
386
391
  else
387
392
  "#{'%g' % @scalar} #{self.units}"
@@ -400,8 +405,15 @@ class Unit < Numeric
400
405
 
401
406
  # true if unit is a 'temperature', false if a 'degree' or anything else
402
407
  def is_temperature?
403
- return true if self.signature == 400 && self.units =~ /temp/
408
+ self.is_degree? && self.units =~ /temp/
409
+ end
410
+ alias :temperature? :is_temperature?
411
+
412
+ # true if a degree unit or equivalent.
413
+ def is_degree?
414
+ self.kind == :temperature
404
415
  end
416
+ alias :degree? :is_degree?
405
417
 
406
418
  # returns the 'degree' unit associated with a temperature unit
407
419
  # '100 tempC'.unit.temperature_scale #=> 'degC'
@@ -420,14 +432,15 @@ class Unit < Numeric
420
432
  # Compare two Unit objects. Throws an exception if they are not of compatible types.
421
433
  # Comparisons are done based on the value of the unit in base SI units.
422
434
  def <=>(other)
423
- case other
424
- when 0: self.base_scalar <=> 0
425
- when Unit:
435
+ case
436
+ when other.zero? && !self.is_temperature?
437
+ return self.base_scalar <=> 0
438
+ when Unit === other
426
439
  raise ArgumentError, "Incompatible Units" unless self =~ other
427
- self.base_scalar <=> other.base_scalar
440
+ return self.base_scalar <=> other.base_scalar
428
441
  else
429
442
  x,y = coerce(other)
430
- x <=> y
443
+ return x <=> y
431
444
  end
432
445
  end
433
446
 
@@ -441,7 +454,8 @@ class Unit < Numeric
441
454
  def =~(other)
442
455
  return true if self == 0 || other == 0
443
456
  case other
444
- when Unit : self.signature == other.signature
457
+ when Unit
458
+ self.signature == other.signature
445
459
  else
446
460
  x,y = coerce(other)
447
461
  x =~ y
@@ -457,7 +471,8 @@ class Unit < Numeric
457
471
  # Unit("100 cm") === Unit("1 m") # => false
458
472
  def ===(other)
459
473
  case other
460
- when Unit: (self.scalar == other.scalar) && (self.units == other.units)
474
+ when Unit
475
+ (self.scalar == other.scalar) && (self.units == other.units)
461
476
  else
462
477
  x,y = coerce(other)
463
478
  x === y
@@ -473,12 +488,12 @@ class Unit < Numeric
473
488
  def +(other)
474
489
  if Unit === other
475
490
  case
476
- when self.zero? : other.dup
477
- when self =~ other :
491
+ when self.zero?
492
+ other.dup
493
+ when self =~ other
478
494
  raise ArgumentError, "Cannot add two temperatures" if ([self, other].all? {|x| x.is_temperature?})
479
495
  if [self, other].any? {|x| x.is_temperature?}
480
- case self.is_temperature?
481
- when true:
496
+ if self.is_temperature?
482
497
  Unit.new(:scalar => (self.scalar + other.to(self.temperature_scale).scalar), :numerator => @numerator, :denominator=>@denominator, :signature => @signature)
483
498
  else
484
499
  Unit.new(:scalar => (other.scalar + self.to(other.temperature_scale).scalar), :numerator => other.numerator, :denominator=>other.denominator, :signature => other.signature)
@@ -488,13 +503,13 @@ class Unit < Numeric
488
503
  Unit.new(:scalar=>(self.base_scalar + other.base_scalar)*@q, :numerator=>@numerator, :denominator=>@denominator, :signature => @signature)
489
504
  end
490
505
  else
491
- raise ArgumentError, "Incompatible Units ('#{self}' not compatible with '#{other}')"
506
+ raise ArgumentError, "Incompatible Units ('#{self}' not compatible with '#{other}')"
492
507
  end
493
508
  elsif Time === other
494
509
  other + self
495
510
  else
496
- x,y = coerce(other)
497
- y + x
511
+ x,y = coerce(other)
512
+ y + x
498
513
  end
499
514
  end
500
515
 
@@ -502,15 +517,16 @@ class Unit < Numeric
502
517
  # throws an exception if the units are not compatible.
503
518
  def -(other)
504
519
  if Unit === other
505
- case
506
- when self.zero? : -other.dup
507
- when self =~ other :
520
+ case
521
+ when self.zero?
522
+ -other.dup
523
+ when self =~ other
508
524
  case
509
- when [self, other].all? {|x| x.is_temperature?} :
525
+ when [self, other].all? {|x| x.is_temperature?}
510
526
  Unit.new(:scalar => (self.base_scalar - other.base_scalar), :numerator => KELVIN, :denominator => UNITY_ARRAY, :signature => @signature).to(self.temperature_scale)
511
- when self.is_temperature? :
527
+ when self.is_temperature?
512
528
  Unit.new(:scalar => (self.base_scalar - other.base_scalar), :numerator => ['<temp-K>'], :denominator => UNITY_ARRAY, :signature => @signature).to(self)
513
- when other.is_temperature? :
529
+ when other.is_temperature?
514
530
  raise ArgumentError, "Cannot subtract a temperature from a differential degree unit"
515
531
  else
516
532
  @q ||= ((@@cached_units[self.units].scalar / @@cached_units[self.units].base_scalar) rescue (self.units.unit.scalar/self.units.unit.to_base.scalar))
@@ -561,6 +577,18 @@ class Unit < Numeric
561
577
  y / x
562
578
  end
563
579
  end
580
+
581
+ # divide two units and return quotient and remainder
582
+ # when both units are in the same units we just use divmod on the raw scalars
583
+ # otherwise we use the scalar of the base unit which will be a float
584
+ def divmod(other)
585
+ raise ArgumentError, "Incompatible Units" unless self =~ other
586
+ if self.units == other.units
587
+ return self.scalar.divmod(other.scalar)
588
+ else
589
+ return self.to_base.scalar.divmod(other.to_base.scalar)
590
+ end
591
+ end
564
592
 
565
593
  # Exponentiate. Only takes integer powers.
566
594
  # Note that anything raised to the power of 0 results in a Unit object with a scalar of 1, and no units.
@@ -578,11 +606,11 @@ class Unit < Numeric
578
606
  return self.inverse if other == -1
579
607
  end
580
608
  case other
581
- when Rational:
609
+ when Rational
582
610
  self.power(other.numerator).root(other.denominator)
583
- when Integer:
611
+ when Integer
584
612
  self.power(other)
585
- when Float:
613
+ when Float
586
614
  return self**(other.to_i) if other == other.to_i
587
615
  valid = (1..9).map {|x| 1/x}
588
616
  raise ArgumentError, "Not a n-th root (1..9), use 1/n" unless valid.include? other.abs
@@ -624,13 +652,13 @@ class Unit < Numeric
624
652
  for item in @numerator.uniq do
625
653
  x = num.find_all {|i| i==item}.size
626
654
  r = ((x/n)*(n-1)).to_int
627
- r.times {|x| num.delete_at(num.index(item))}
655
+ r.times {|y| num.delete_at(num.index(item))}
628
656
  end
629
657
 
630
658
  for item in @denominator.uniq do
631
659
  x = den.find_all {|i| i==item}.size
632
660
  r = ((x/n)*(n-1)).to_int
633
- r.times {|x| den.delete_at(den.index(item))}
661
+ r.times {|y| den.delete_at(den.index(item))}
634
662
  end
635
663
  q = @scalar < 0 ? (-1)**Rational(1,n) * (@scalar.abs)**Rational(1,n) : @scalar**Rational(1,n)
636
664
  Unit.new(:scalar=>q,:numerator=>num,:denominator=>den)
@@ -652,7 +680,7 @@ class Unit < Numeric
652
680
  #
653
681
  # Special handling for temperature conversions is supported. If the Unit object is converted
654
682
  # from one temperature unit to another, the proper temperature offsets will be used.
655
- # Supports Kelvin, Celcius, fahrenheit, and Rankine scales.
683
+ # Supports Kelvin, Celsius, fahrenheit, and Rankine scales.
656
684
  #
657
685
  # Note that if temperature is part of a compound unit, the temperature will be treated as a differential
658
686
  # and the units will be scaled appropriately.
@@ -661,34 +689,43 @@ class Unit < Numeric
661
689
  return self if TrueClass === other
662
690
  return self if FalseClass === other
663
691
  if (Unit === other && other.is_temperature?) || (String === other && other =~ /temp(K|C|R|F)/)
664
- raise ArgumentError, "Receiver is not a temperature unit" unless self.signature == 400
692
+ raise ArgumentError, "Receiver is not a temperature unit" unless self.degree?
665
693
  start_unit = self.units
666
694
  target_unit = other.units rescue other
667
695
  unless @base_scalar
668
696
  @base_scalar = case start_unit
669
- when 'tempC' : @scalar + 273.15
670
- when 'tempK' : @scalar
671
- when 'tempF' : (@scalar+459.67)*(5.0/9.0)
672
- when 'tempR' : @scalar*(5.0/9.0)
697
+ when 'tempC'
698
+ @scalar + 273.15
699
+ when 'tempK'
700
+ @scalar
701
+ when 'tempF'
702
+ (@scalar+459.67)*(5.0/9.0)
703
+ when 'tempR'
704
+ @scalar*(5.0/9.0)
673
705
  end
674
706
  end
675
707
  q= case target_unit
676
- when 'tempC' : @base_scalar - 273.15
677
- when 'tempK' : @base_scalar
678
- when 'tempF' : @base_scalar * (9.0/5.0) - 459.67
679
- when 'tempR' : @base_scalar * (9.0/5.0)
680
- end
681
-
708
+ when 'tempC'
709
+ @base_scalar - 273.15
710
+ when 'tempK'
711
+ @base_scalar
712
+ when 'tempF'
713
+ @base_scalar * (9.0/5.0) - 459.67
714
+ when 'tempR'
715
+ @base_scalar * (9.0/5.0)
716
+ end
717
+
682
718
  Unit.new("#{q} #{target_unit}")
683
719
  else
684
- case other
685
- when Unit:
686
- return self if other.units == self.units
687
- target = other
688
- when String: target = Unit.new(other)
689
- else
690
- raise ArgumentError, "Unknown target units"
691
- end
720
+ case other
721
+ when Unit
722
+ return self if other.units == self.units
723
+ target = other
724
+ when String
725
+ target = Unit.new(other)
726
+ else
727
+ raise ArgumentError, "Unknown target units"
728
+ end
692
729
  raise ArgumentError, "Incompatible Units" unless self =~ target
693
730
  one = @numerator.map {|x| @@PREFIX_VALUES[x] ? @@PREFIX_VALUES[x] : x}.map {|i| i.kind_of?(Numeric) ? i : @@UNIT_VALUES[i][:scalar] }.compact
694
731
  two = @denominator.map {|x| @@PREFIX_VALUES[x] ? @@PREFIX_VALUES[x] : x}.map {|i| i.kind_of?(Numeric) ? i : @@UNIT_VALUES[i][:scalar] }.compact
@@ -706,7 +743,7 @@ class Unit < Numeric
706
743
  # converts the unit back to a float if it is unitless. Otherwise raises an exception
707
744
  def to_f
708
745
  return @scalar.to_f if self.unitless?
709
- raise RuntimeError, "Can't convert to Float unless unitless. Use Unit#scalar"
746
+ raise RuntimeError, "Can't convert to Float unless unitless (#{self.to_s}). Use Unit#scalar"
710
747
  end
711
748
 
712
749
  # converts the unit back to a complex if it is unitless. Otherwise raises an exception
@@ -740,13 +777,13 @@ class Unit < Numeric
740
777
  output_d = ['1']
741
778
  else
742
779
  den.each_with_index do |token,index|
743
- if token && @@PREFIX_VALUES[token] then
744
- output_d << "#{@@OUTPUT_MAP[token]}#{@@OUTPUT_MAP[den[index+1]]}"
745
- den[index+1]=nil
746
- else
747
- output_d << "#{@@OUTPUT_MAP[token]}" if token
748
- end
780
+ if token && @@PREFIX_VALUES[token] then
781
+ output_d << "#{@@OUTPUT_MAP[token]}#{@@OUTPUT_MAP[den[index+1]]}"
782
+ den[index+1]=nil
783
+ else
784
+ output_d << "#{@@OUTPUT_MAP[token]}" if token
749
785
  end
786
+ end
750
787
  end
751
788
  on = output_n.reject {|x| x.empty?}.map {|x| [x, output_n.find_all {|z| z==x}.size]}.uniq.map {|x| ("#{x[0]}".strip+ (x[1] > 1 ? "^#{x[1]}" : ''))}
752
789
  od = output_d.reject {|x| x.empty?}.map {|x| [x, output_d.find_all {|z| z==x}.size]}.uniq.map {|x| ("#{x[0]}".strip+ (x[1] > 1 ? "^#{x[1]}" : ''))}
@@ -811,7 +848,7 @@ class Unit < Numeric
811
848
 
812
849
  # true if scalar is zero
813
850
  def zero?
814
- return @scalar.zero?
851
+ return self.to_base.scalar.zero?
815
852
  end
816
853
 
817
854
  # '5 min'.unit.ago
@@ -833,10 +870,12 @@ class Unit < Numeric
833
870
  # 'min'.since(time)
834
871
  def since(time_point = ::Time.now)
835
872
  case time_point
836
- when Time: (Time.now - time_point).unit('s').to(self)
837
- when DateTime, Date: (DateTime.now - time_point).unit('d').to(self)
838
- when String:
839
- (DateTime.now - time_point.time(:context=>:past)).unit('d').to(self)
873
+ when Time
874
+ (Time.now - time_point).unit('s').to(self)
875
+ when DateTime, Date
876
+ (DateTime.now - time_point).unit('d').to(self)
877
+ when String
878
+ (DateTime.now - time_point.to_datetime(:context=>:past)).unit('d').to(self)
840
879
  else
841
880
  raise ArgumentError, "Must specify a Time, DateTime, or String"
842
881
  end
@@ -845,11 +884,12 @@ class Unit < Numeric
845
884
  # 'min'.until(time)
846
885
  def until(time_point = ::Time.now)
847
886
  case time_point
848
- when Time: (time_point - Time.now).unit('s').to(self)
849
- when DateTime, Date: (time_point - DateTime.now).unit('d').to(self)
850
- when String:
851
- r = (time_point.time(:context=>:future) - DateTime.now)
852
- Time === time_point.time ? r.unit('s').to(self) : r.unit('d').to(self)
887
+ when Time
888
+ (time_point - Time.now).unit('s').to(self)
889
+ when DateTime, Date
890
+ (time_point - DateTime.now).unit('d').to(self)
891
+ when String
892
+ (time_point.to_datetime(:context=>:future) - DateTime.now).unit('d').to(self)
853
893
  else
854
894
  raise ArgumentError, "Must specify a Time, DateTime, or String"
855
895
  end
@@ -882,7 +922,8 @@ class Unit < Numeric
882
922
  return [other.to_unit, self]
883
923
  end
884
924
  case other
885
- when Unit : [other, self]
925
+ when Unit
926
+ [other, self]
886
927
  else
887
928
  [Unit.new(other), self]
888
929
  end
@@ -906,22 +947,21 @@ class Unit < Numeric
906
947
 
907
948
  # calculates the unit signature vector used by unit_signature
908
949
  def unit_signature_vector
909
- return self.to_base.unit_signature_vector unless self.is_base?
910
- result = self
911
- vector = Array.new(SIGNATURE_VECTOR.size,0)
912
- for element in @numerator
913
- if r=@@ALL_UNIT_DEFINITIONS[element]
914
- n = SIGNATURE_VECTOR.index(r[2])
915
- vector[n] = vector[n] + 1 if n
916
- end
950
+ return self.to_base.unit_signature_vector unless self.is_base?
951
+ vector = Array.new(SIGNATURE_VECTOR.size,0)
952
+ for element in @numerator
953
+ if r=@@ALL_UNIT_DEFINITIONS[element]
954
+ n = SIGNATURE_VECTOR.index(r[2])
955
+ vector[n] = vector[n] + 1 if n
917
956
  end
918
- for element in @denominator
919
- if r=@@ALL_UNIT_DEFINITIONS[element]
920
- n = SIGNATURE_VECTOR.index(r[2])
921
- vector[n] = vector[n] - 1 if n
922
- end
957
+ end
958
+ for element in @denominator
959
+ if r=@@ALL_UNIT_DEFINITIONS[element]
960
+ n = SIGNATURE_VECTOR.index(r[2])
961
+ vector[n] = vector[n] - 1 if n
923
962
  end
924
- vector
963
+ end
964
+ vector
925
965
  end
926
966
 
927
967
  private
@@ -984,8 +1024,10 @@ class Unit < Numeric
984
1024
  den = []
985
1025
  for key, value in combined do
986
1026
  case
987
- when value > 0 : value.times {num << key}
988
- when value < 0 : value.abs.times {den << key}
1027
+ when value > 0
1028
+ value.times {num << key}
1029
+ when value < 0
1030
+ value.abs.times {den << key}
989
1031
  end
990
1032
  end
991
1033
  num = UNITY_ARRAY if num.empty?
@@ -1083,8 +1125,10 @@ class Unit < Numeric
1083
1125
  n = item[1].to_i
1084
1126
  x = "#{item[0]} "
1085
1127
  case
1086
- when n>=0 : top.gsub!(/#{item[0]}(\^|\*\*)#{n}/) {|s| x * n}
1087
- when n<0 : bottom = "#{bottom} #{x * -n}"; top.gsub!(/#{item[0]}(\^|\*\*)#{n}/,"")
1128
+ when n>=0
1129
+ top.gsub!(/#{item[0]}(\^|\*\*)#{n}/) {|s| x * n}
1130
+ when n<0
1131
+ bottom = "#{bottom} #{x * -n}"; top.gsub!(/#{item[0]}(\^|\*\*)#{n}/,"")
1088
1132
  end
1089
1133
  end
1090
1134
  bottom.gsub!(BOTTOM_REGEX) {|s| "#{$1} " * $2.to_i} if bottom
@@ -1,3 +1,4 @@
1
+ require 'time'
1
2
  # make a string into a unit
2
3
  class String
3
4
  def to_unit(other = nil)
@@ -9,10 +10,14 @@ class String
9
10
 
10
11
  # format unit output using formating codes '%0.2f' % '1 mm'.unit => '1.00 mm'
11
12
  def %(*args)
13
+ return if self.empty?
12
14
  case
13
- when Unit === args[0]: args[0].to_s(self)
14
- when (!defined?(Uncertain).nil? && (Uncertain === args[0])): args[0].to_s(self)
15
- when Complex === args[0]: args[0].to_s
15
+ when Unit === args[0]
16
+ args[0].to_s(self)
17
+ when (!defined?(Uncertain).nil? && (Uncertain === args[0]))
18
+ args[0].to_s(self)
19
+ when Complex === args[0]
20
+ args[0].to_s
16
21
  else
17
22
  unit_format(*args)
18
23
  end
@@ -63,18 +68,30 @@ class String
63
68
  raise(ArgumentError, 'Invalid Time String') unless r
64
69
  return r
65
70
  rescue
66
- Time.local(*ParseDate.parsedate(self))
71
+ case
72
+ when self == "now"
73
+ Time.now
74
+ when Time.respond_to?(:parse)
75
+ Time.parse(self)
76
+ else
77
+ Time.local(*ParseDate.parsedate(self))
78
+ end
67
79
  end
68
80
  end
69
81
 
70
82
  def to_datetime(options = {})
71
83
  begin
72
84
  # raises an exception if Chronic.parse = nil or if Chronic not defined
73
- r = Chronic.parse(self,options).to_datetime
74
- rescue
75
- r=DateTime.civil(*ParseDate.parsedate(self)[0..5].compact)
85
+ r = Chronic.parse(self,options).send(:to_datetime)
86
+ rescue Exception => e
87
+ r = case
88
+ when self.to_s == "now"
89
+ DateTime.now
90
+ else
91
+ DateTime.parse(self)
92
+ end
76
93
  end
77
- raise RuntimeError, "Invalid Time String" if r == DateTime.new
94
+ raise RuntimeError, "Invalid Time String (#{self.to_s})" if r == DateTime.new
78
95
  return r
79
96
  end
80
97
 
@@ -82,7 +99,14 @@ class String
82
99
  begin
83
100
  r = Chronic.parse(self,options).to_date
84
101
  rescue
85
- r = Date.civil(*ParseDate.parsedate(self)[0..5].compact)
102
+ r = case
103
+ when self == "today"
104
+ Date.today
105
+ when RUBY_VERSION < "1.9"
106
+ Date.civil(*ParseDate.parsedate(self)[0..5].compact)
107
+ else
108
+ Date.parse(self)
109
+ end
86
110
  end
87
111
  raise RuntimeError, 'Invalid Date String' if r == Date.new
88
112
  return r
@@ -24,28 +24,24 @@ class Time
24
24
  alias :u :to_unit
25
25
  alias :unit_add :+
26
26
 
27
- def to_datetime
28
- DateTime.civil(1970,1,1)+(self.to_f+self.gmt_offset)/86400
29
- end
30
-
31
- # ruby 1.8.6 has a reasonable implementation of this that works well, so let's use it.
32
- if VERSION == "1.8.4"
27
+ unless Time.instance_methods.include?(:to_date)
33
28
  def to_date
34
29
  x=(Date.civil(1970,1,1)+((self.to_f+self.gmt_offset)/86400.0)-0.5)
35
- Date.civil(x.year, x.month, x.day )
30
+ Date.civil(x.year, x.month, x.day)
36
31
  end
37
32
  end
38
33
 
39
34
  def +(other)
40
35
  case other
41
- when Unit:
36
+ when Unit
42
37
  other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units
43
38
  begin
44
39
  unit_add(other.to('s').scalar)
45
40
  rescue RangeError
46
41
  self.to_datetime + other
47
42
  end
48
- when DateTime: unit_add(other.to_time)
43
+ when DateTime
44
+ unit_add(other.to_time)
49
45
  else
50
46
  unit_add(other)
51
47
  end
@@ -60,15 +56,16 @@ class Time
60
56
 
61
57
  def -(other)
62
58
  case other
63
- when Unit:
59
+ when Unit
64
60
  other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units
65
61
  begin
66
62
  unit_sub(other.to('s').scalar)
67
63
  rescue RangeError
68
- self.to_datetime - other
64
+ self.send(:to_datetime) - other
69
65
  end
70
66
 
71
- when DateTime: unit_sub(other.to_time)
67
+ when DateTime
68
+ unit_sub(other.to_time)
72
69
  else
73
70
  unit_sub(other)
74
71
  end
@@ -1,13 +1,22 @@
1
+ require 'rubygems'
1
2
  require 'test/unit'
2
3
  require 'ruby-units'
3
- require 'rubygems'
4
- require 'uncertain' if Gem::GemPathSearcher.new.find('uncertain')
5
4
  require 'yaml'
6
- require 'chronic' if Gem::GemPathSearcher.new.find('chronic')
5
+ begin
6
+ require 'chronic'
7
+ rescue LoadError
8
+ warn "Can't test Chronic integration unless gem 'chronic' is installed"
9
+ end
10
+ begin
11
+ require 'uncertain'
12
+ rescue LoadError
13
+ warn "Can't test Uncertain Units unless 'Uncertain' gem is installed"
14
+ end
15
+
7
16
 
8
17
  class Unit < Numeric
9
18
  @@USER_DEFINITIONS = {'<inchworm>' => [%w{inworm inchworm}, 0.0254, :length, %w{<meter>} ],
10
- '<habenero>' => [%{degH}, 100, :temperature, %w{<celsius>}]}
19
+ '<habenero>' => [%w{degH}, 100, :temperature, %w{<celsius>}]}
11
20
  Unit.setup
12
21
  end
13
22
 
@@ -17,7 +26,7 @@ class Time
17
26
  class << self
18
27
  alias :unforced_now :now
19
28
  def forced_now
20
- return @@forced_now ? @@forced_now : unforced_now
29
+ @@forced_now.nil? ? unforced_now : @@forced_now
21
30
  end
22
31
  alias :now :forced_now
23
32
 
@@ -28,7 +37,7 @@ class Time
28
37
 
29
38
  alias :unforced_gmt :gmt_offset
30
39
  def forced_gmt
31
- return @@forced_gmt ? @@forced_gmt : unforced_gmt
40
+ @@forced_gmt.nil? ? unforced_gmt : @@forced_gmt
32
41
  end
33
42
  alias :gmt_offset :forced_gmt
34
43
 
@@ -64,7 +73,7 @@ class TestRubyUnits < Test::Unit::TestCase
64
73
 
65
74
  def setup
66
75
  @april_fools = Time.at 1143910800
67
- @april_fools_datetime = DateTime.parse('2006-4-1 12:00')
76
+ @april_fools_datetime = DateTime.parse('2006-04-01T12:00:00-05:00')
68
77
  Time.forced_now = @april_fools
69
78
  DateTime.forced_now = @april_fools_datetime
70
79
  #Unit.clear_cache
@@ -85,7 +94,6 @@ class TestRubyUnits < Test::Unit::TestCase
85
94
  assert_equal "s", a.to_unit.units
86
95
  assert_equal a + 3600, a + "1 h".unit
87
96
  assert_equal a - 3600, a - "1 h".unit
88
- b = Unit(a) + "1 h".unit
89
97
  assert_in_delta Time.now - "1 h".unit, "1 h".ago, 1
90
98
  assert_in_delta Time.now + 3600, "1 h".from_now, 1
91
99
  assert_in_delta "1 h".unit + Time.now, "1 h".from_now, 1
@@ -96,42 +104,60 @@ class TestRubyUnits < Test::Unit::TestCase
96
104
  assert_in_delta Time.now, "now".time, 1
97
105
  end
98
106
 
99
- def test_time_helpers
100
- assert_equal @april_fools, Time.now
101
- assert_equal "1 day".from_now, @april_fools + 86400
102
- assert_equal "1 day".from("now"), @april_fools + 86400
103
- assert_equal "1 day".ago, @april_fools - 86400
104
- assert_equal "1 day".before_now, @april_fools - 86400
105
- assert_equal '1 days'.before('now'), @april_fools - 86400
107
+ def test_from_now
108
+ assert_equal "1 day".from_now, @april_fools + 86400
109
+ end
110
+
111
+ def test_from
112
+ assert_equal "1 day".from("now"), @april_fools + 86400
113
+ end
114
+
115
+ def test_ago
116
+ assert_equal "1 day".ago, @april_fools - 86400
117
+ end
118
+
119
+ def test_before_now
120
+ assert_equal "1 day".before_now, @april_fools - 86400
121
+ end
122
+
123
+ def test_before
124
+ assert_equal '1 days'.before('now'), @april_fools - 86400
125
+ end
126
+
127
+ def test_since
106
128
  assert_equal 'days'.since(@april_fools - 86400), "1 day".unit
107
- assert_equal 'days'.since('3/31/06 12:00'), "1 day".unit
108
- assert_equal 'days'.since(DateTime.parse('2006-3-31 12:00')), "1 day".unit
109
- assert_equal 'days'.until('4/2/2006'), '1 day'.unit
110
- assert_equal 'now'.time, Time.now
111
- assert_equal 'now'.datetime, DateTime.now
112
- assert_raises(ArgumentError) { 'days'.until(1) }
129
+ assert_equal 'days'.since('2006-3-31 12:00:00 -5:00'), "1 day".unit
130
+ assert_equal 'days'.since(DateTime.parse('2006-3-31 12:00 -5:00')), "1 day".unit
113
131
  assert_raises(ArgumentError) { 'days'.since(1) }
114
- assert_equal Unit.new(Time.now).scalar, 1143910800
132
+ end
133
+
134
+ def test_until
135
+ assert_equal 'days'.until('2006-04-2 12:00:00 -5:00'), '1 day'.unit
136
+ assert_raises(ArgumentError) { 'days'.until(1) }
137
+ end
138
+
139
+ def test_time_helpers
140
+ assert_equal @april_fools, Time.now
141
+ assert_equal @april_fools_datetime, DateTime.now
142
+ assert_equal Time.now, 'now'.time
143
+ assert_equal DateTime.now, 'now'.datetime
144
+ assert_equal 1143910800, Unit.new(Time.now).scalar
115
145
  assert_equal @april_fools.unit.to_time, @april_fools
116
146
  assert_equal Time.in('1 day'), @april_fools + 86400
117
- assert_equal "2006-04-01T12:00:00+00:00", @april_fools_datetime.inspect
147
+ assert_equal "2006-04-01T12:00:00-05:00", @april_fools_datetime.inspect
118
148
  assert_equal "2006-04-01T00:00:00+00:00", '2453826.5 days'.unit.to_datetime.to_s
119
149
  end
120
150
 
121
151
  def test_string_helpers
122
152
  assert_equal '1 mm'.to('in'), Unit('1 mm').to('in')
123
153
  end
124
-
125
- def test_math
126
- pi = Math::PI
127
- assert_equal Math.sin(pi), Math.sin("180 deg".unit)
128
- assert_equal Math.cos(pi), Math.cos("180 deg".unit)
129
- assert_equal Math.tan(pi), Math.tan("180 deg".unit)
130
- assert_equal Math.sinh(pi), Math.sinh("180 deg".unit)
131
- assert_equal Math.cosh(pi), Math.cosh("180 deg".unit)
132
- assert_equal Math.tanh(pi), Math.tanh("180 deg".unit)
133
- end
134
154
 
155
+ [:sin, :cos, :tan, :sinh, :cosh, :tanh].each do |trig|
156
+ define_method("test_#{trig}") do
157
+ assert_equal Math.send(trig, Math::PI), Math.send(trig, "180 deg".unit)
158
+ end
159
+ end
160
+
135
161
  def test_clone
136
162
  unit1= "1 mm".unit
137
163
  unit2 = unit1.clone
@@ -312,7 +338,7 @@ class TestRubyUnits < Test::Unit::TestCase
312
338
  assert_equal ['<foot>'], unit3.numerator
313
339
  assert_equal ['<1>'],unit3.denominator
314
340
  }
315
- assert_raises(ArgumentError) { unit3= unit1 >> 5.0}
341
+ assert_raises(ArgumentError) { unit1 >> 5.0}
316
342
  assert_equal unit1, unit1.to(true)
317
343
  assert_equal unit1, unit1.to(false)
318
344
  assert_equal unit1, unit1.to(nil)
@@ -405,7 +431,7 @@ class TestRubyUnits < Test::Unit::TestCase
405
431
  assert_equal "2".unit, unit2
406
432
  }
407
433
  assert_raises(ArgumentError) {
408
- unit2 = "1".unit + nil
434
+ "1".unit + nil
409
435
  }
410
436
  end
411
437
 
@@ -505,7 +531,7 @@ class TestRubyUnits < Test::Unit::TestCase
505
531
  assert_equal unit2, unit1**-2
506
532
  }
507
533
  assert_raises(ZeroDivisionError) {
508
- unit="0 mm".unit**-1
534
+ "0 mm".unit**-1
509
535
  }
510
536
  end
511
537
 
@@ -581,8 +607,9 @@ class TestRubyUnits < Test::Unit::TestCase
581
607
  assert_raises(ArgumentError) { '-1000 tempC'.unit}
582
608
  assert_raises(ArgumentError) { '-1000 tempF'.unit}
583
609
 
584
- assert_equal '0 tempC'.unit, '32 tempF'.unit
585
- assert_equal '0 tempC'.unit, '273.15 tempK'.unit
610
+ assert_in_delta '32 tempF'.unit.base_scalar, '0 tempC'.unit.base_scalar, 0.01
611
+ assert_in_delta '0 tempC'.unit.base_scalar, '32 tempF'.unit.base_scalar, 0.01
612
+ assert_in_delta '0 tempC'.unit.base_scalar, '273.15 tempK'.unit.base_scalar, 0.01
586
613
  assert_in_delta '0 tempC'.unit.base_scalar, '491.67 tempR'.unit.base_scalar, 0.01
587
614
 
588
615
  a = '10 degC'.unit
@@ -592,14 +619,13 @@ class TestRubyUnits < Test::Unit::TestCase
592
619
  assert_equal a >> 'tempF', '-441.67 tempF'.unit
593
620
 
594
621
  unit1 = '37 tempC'.unit
595
- unit2 = unit1 >> "tempF" >> 'tempK' >> 'tempR' >> 'tempC'
596
622
  assert_equal unit1 >> 'tempF' >> 'tempK' >> 'tempR' >> 'tempC', unit1
597
623
 
598
624
  a = '100 tempF'.unit
599
625
  b = '10 degC'.unit
600
626
  c = '50 tempF'.unit
601
627
  d = '18 degF'.unit
602
- assert_equal a+b, '118 tempF'.unit
628
+ assert_equal('118 tempF'.unit,a+b)
603
629
  assert_equal b+a, '118 tempF'.unit
604
630
  assert_equal a-b, '82 tempF'.unit
605
631
  assert_in_delta((a-c).scalar, '50 degF'.unit.scalar, 0.01)
@@ -752,14 +778,12 @@ class TestRubyUnits < Test::Unit::TestCase
752
778
  assert_equal "cells", a.units
753
779
  end
754
780
 
755
- def test_uncertain
756
- if defined?(Uncertain)
757
- a = '1 +/- 1 mm'.unit
758
- assert_equal a.to_s, '1 +/- 1 mm'
759
- else
760
- warn "Can't test Uncertain Units unless 'Uncertain' gem is installed"
761
- end
762
- end
781
+ if defined?(Uncertain)
782
+ def test_uncertain
783
+ a = '1 +/- 1 mm'.unit
784
+ assert_equal a.to_s, '1 +/- 1 mm'
785
+ end
786
+ end
763
787
 
764
788
  def test_format
765
789
  assert_equal "%0.2f" % "1 mm".unit, "1.00 mm"
@@ -771,7 +795,7 @@ class TestRubyUnits < Test::Unit::TestCase
771
795
  end
772
796
 
773
797
  def test_currency
774
- assert_nothing_raised {a = "$1".unit}
798
+ assert_nothing_raised {"$1".unit}
775
799
  end
776
800
 
777
801
  def test_kind
@@ -781,9 +805,9 @@ class TestRubyUnits < Test::Unit::TestCase
781
805
 
782
806
  def test_percent
783
807
  assert_nothing_raised {
784
- z = "1 percent".unit
785
- a = "1%".unit
786
- b = "0.01%".unit
808
+ "1 percent".unit
809
+ "1%".unit
810
+ "0.01%".unit
787
811
  }
788
812
  a = '100 ml'.unit
789
813
  b = '50%'.unit
@@ -852,9 +876,29 @@ class TestRubyUnits < Test::Unit::TestCase
852
876
  a = '-9 mm^2'.unit
853
877
  b = a**(0.5)
854
878
  assert_in_delta Math.sqrt(a).to_unit.scalar.real, b.scalar.real, 0.00001
855
- assert_in_delta Math.sqrt(a).to_unit.scalar.image, b.scalar.image, 0.00001
856
-
879
+ # ruby 1.8.x uses .image while 1.9.x uses .imaginary
880
+ if Complex.instance_methods.include?(:imaginary)
881
+ assert_in_delta Math.sqrt(a).to_unit.scalar.imaginary, b.scalar.imaginary, 0.00001
882
+ else
883
+ assert_in_delta Math.sqrt(a).to_unit.scalar.image, b.scalar.image, 0.00001
884
+ end
857
885
  end
886
+
887
+ def test_div
888
+ assert_equal 11,"23 m".unit.div('2 m'.unit)
889
+ end
890
+
891
+ def test_divmod
892
+ assert_equal [277,1], 555.unit('mm').divmod(2.unit('mm'))
893
+ assert_equal [277, 0.0010000000000000373], '0.555 m'.unit.divmod('2 mm'.unit)
894
+ assert_raises(ArgumentError) { '1 m'.unit.divmod('1 kg'.unit) }
895
+ end
896
+
897
+ if Math.respond_to?(:cbrt)
898
+ def test_cbrt
899
+ assert_in_delta '2 mm'.to_unit, Math.cbrt('8 mm^3'.to_unit), 0.0001
900
+ end
901
+ end
858
902
 
859
903
  def test_hypot
860
904
  assert_equal Math.hypot('3 mm'.unit,'4 mm'.unit), '5 mm'.unit
@@ -914,7 +958,7 @@ class TestRubyUnits < Test::Unit::TestCase
914
958
  end
915
959
 
916
960
  def test_version
917
- assert_equal('1.1.5', Unit::VERSION)
961
+ assert_equal('1.2.0.a', Unit::VERSION)
918
962
  end
919
963
 
920
964
  def test_negation
@@ -922,5 +966,17 @@ class TestRubyUnits < Test::Unit::TestCase
922
966
  assert_equal(a.class, (1-a).class)
923
967
  end
924
968
 
969
+ def test_degree
970
+ assert "100 tempF".unit.degree?
971
+ assert "100 degC".unit.degree?
972
+ assert !"1 mm".unit.degree?
973
+ end
974
+
975
+ def test_temperature
976
+ assert "100 tempF".unit.temperature?
977
+ assert !"100 degC".unit.temperature?
978
+ assert !"1 mm".unit.temperature?
979
+ end
980
+
925
981
  end
926
982
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-units
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ prerelease: true
5
5
  segments:
6
6
  - 1
7
- - 1
8
- - 5
9
- version: 1.1.5
7
+ - 2
8
+ - 0
9
+ - a
10
+ version: 1.2.0.a
10
11
  platform: ruby
11
12
  authors:
12
13
  - Kevin Olbrich, Ph.D
@@ -14,13 +15,14 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-03-17 00:00:00 -04:00
18
+ date: 2010-11-07 01:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rubyforge
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
@@ -31,24 +33,11 @@ dependencies:
31
33
  version: 2.0.4
32
34
  type: :development
33
35
  version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: gemcutter
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- - 5
44
- - 0
45
- version: 0.5.0
46
- type: :development
47
- version_requirements: *id002
48
36
  - !ruby/object:Gem::Dependency
49
37
  name: hoe-yard
50
38
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
52
41
  requirements:
53
42
  - - ">="
54
43
  - !ruby/object:Gem::Version
@@ -58,21 +47,22 @@ dependencies:
58
47
  - 2
59
48
  version: 0.1.2
60
49
  type: :development
61
- version_requirements: *id003
50
+ version_requirements: *id002
62
51
  - !ruby/object:Gem::Dependency
63
52
  name: hoe
64
53
  prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
66
56
  requirements:
67
57
  - - ">="
68
58
  - !ruby/object:Gem::Version
69
59
  segments:
70
60
  - 2
71
- - 5
72
- - 0
73
- version: 2.5.0
61
+ - 6
62
+ - 1
63
+ version: 2.6.1
74
64
  type: :development
75
- version_requirements: *id004
65
+ version_requirements: *id003
76
66
  description: This library handles unit conversions and unit math
77
67
  email: kevin.olbrich+ruby_units@gmail.com
78
68
  executables: []
@@ -116,6 +106,7 @@ rdoc_options:
116
106
  require_paths:
117
107
  - lib
118
108
  required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
119
110
  requirements:
120
111
  - - ">="
121
112
  - !ruby/object:Gem::Version
@@ -123,16 +114,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
114
  - 0
124
115
  version: "0"
125
116
  required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
126
118
  requirements:
127
- - - ">="
119
+ - - ">"
128
120
  - !ruby/object:Gem::Version
129
121
  segments:
130
- - 0
131
- version: "0"
122
+ - 1
123
+ - 3
124
+ - 1
125
+ version: 1.3.1
132
126
  requirements: []
133
127
 
134
128
  rubyforge_project: ruby-units
135
- rubygems_version: 1.3.6
129
+ rubygems_version: 1.3.7
136
130
  signing_key:
137
131
  specification_version: 3
138
132
  summary: A class that performs unit conversions and unit math