ruby-units 1.1.5 → 1.2.0.a

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/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