Class: Phys::Quantity

Inherits:
Object
  • Object
show all
Defined in:
lib/phys/units/quantity.rb

Overview

Phys::Quantity is the primary class of Phys-Units library, intended to be manipulated by users. This class represents Physical Quantities with a Unit of measurement. It contains Value and Unit.

  • Value of the quantity is given as the first parameter of Quantity constructor (alias is Quantity[]). It must be a class instance having arithmetic methods, but it is not necessary to be a Numeric. This is a duck typing way.

    Phys::Quantity[2.5,"miles"].value    #=> 2.5
    Phys::Quantity[NArray.float(5).indgen,"miles"].want("m").value
    #=> NArray.float(5):
        [ 0.0, 1609.34, 3218.69, 4828.03, 6437.38 ]
  • Unit is an instance of Phys::Unit class. It is created from the second argument of Quantity constructor. See document of Phys::Unit.

    Phys::Quantity[2.5,"miles"].unit #=> #<Phys::Unit 1609.344,{"m"=>1},@expr="5280 ft">

Examples:

require 'phys/units'
Q = Phys::Quantity

Q[1.23,'km'] + Q[4.56,'m']    #=> Phys::Quantity[1.23456,'km']
Q[123,'mile'] / Q[2,'hr']     #=> Phys::Quantity[61,'mile/hr']
Q[61,'miles/hr'].want('m/s')  #=> Phys::Quantity[27.26944,'m/s']
Q[1.0,'are'] == Q[10,'m']**2  #=> true
Q[70,'tempF'] + Q[10,'degC']  #=> Phys::Quantity[88,'tempF']
Q[20,'tempC'].want('tempF')   #=> Phys::Quantity[68,'tempF']
Math.cos(Q[60,'degree'].to_f) #=> 0.5

See Also:

Direct Known Subclasses

Quanty

Constant Summary

@@verbose_inspect =
false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, expr, unit = nil) ⇒ Quantity #initialize(value, unit) ⇒ Quantity #initialize(value) ⇒ Quantity

Initialize a new quantity.

Raises:

  • (TypeError)

    if invalid arg types.

  • (Phys::UnitError)

    if unit conversion is failed.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/phys/units/quantity.rb', line 81

def initialize(value,expr=nil,unit=nil)
  @value = value
  case expr
  when String, Symbol
    @expr = expr.to_s.strip
    @expr = nil if @expr==''
    @unit = unit
  when NilClass
    @expr = nil
    @unit = unit
  when Unit
    raise "Wrong # of argument" if unit
    @expr = nil
    @unit = expr
  else
    raise ArgumentError,"Second argument is invalid: #{expr.inspect}"
  end
  case @unit
  when NilClass
    @unit = Unit.parse(@expr||1)
  when Unit
  else
    raise ArgumentError, "Third argument is invalid: #{@unit.inspect}"
  end
end

Instance Attribute Details

#exprString (readonly)

Unit expression. Given as the second parameter of the Quantity constructor.



115
116
117
# File 'lib/phys/units/quantity.rb', line 115

def expr
  @expr
end

#unitPhys::Unit (readonly)

Unit of the quantity. Instance of Phys::Unit class.



119
120
121
# File 'lib/phys/units/quantity.rb', line 119

def unit
  @unit
end

#valueObject (readonly) Also known as: val

Value of the quantity. Instance of classes with same arithmetic methods as Numeric.



110
111
112
# File 'lib/phys/units/quantity.rb', line 110

def value
  @value
end

Class Method Details

.[](value, unit = nil) ⇒ Phys::Quantity

Alias to Phys::Quantity.new.

Raises:

  • (TypeError)

    if invalid arg types.

  • (Phys::UnitError)

    if unit conversion is failed.



63
64
65
# File 'lib/phys/units/quantity.rb', line 63

def [](value,unit=nil)
  self.new(value,unit)
end

Instance Method Details

#%(other) ⇒ Object Also known as: modulo

Modulo.

  • If the other param is Phys::Quantity, other is converted to the unit of self, and returns modulo of values.

  • If the other param is not Phys::Quantity, other is regarded as dimensionless, and returns modulo of Phys::Quantity.

Raises:



453
454
455
456
457
458
459
# File 'lib/phys/units/quantity.rb', line 453

def %(other)
  if Quantity===other
    @value % @unit.convert(other)
  else
    self.class.new( @value % other, @expr, @unit )
  end
end

#*(other) ⇒ Phys::Quantity

Multiplication. If the other param is not Phys::Quantity, other is regarded as a dimensionless value. The values and units are multiplied respectively.

Raises:



354
355
356
357
358
359
360
361
362
# File 'lib/phys/units/quantity.rb', line 354

def *(other)
  if Quantity===other
    a = [self.enclose_expr, other.enclose_expr]
    a.delete(nil)
    self.class.new( @value*other.value, a.join(' '), @unit*other.unit )
  else
    self.class.new( @value*other, @expr, @unit )
  end
end

#**(n) ⇒ Phys::Quantity

Exponentiation.

Raises:



311
312
313
314
315
316
317
318
319
320
# File 'lib/phys/units/quantity.rb', line 311

def **(n)
  if @expr.nil?
    expr = nil
  elsif /^[A-Za-z_]+$/o =~ @expr
    expr = @expr+'^'+n.to_s
  else
    expr = '('+@expr+')^'+n.to_s+''
  end
  self.class.new( @value**n, expr, @unit**n )
end

#+(other) ⇒ Phys::Quantity

Addition. Before the operation, it converts other to the unit of self.

  • If the other param is Phys::Quantity, other is converted to the unit of self.

  • If the other param is not Phys::Quantity, both params must be dimensionless.

Raises:



159
160
161
162
# File 'lib/phys/units/quantity.rb', line 159

def +(other)
  val = @value + @unit.convert_scale(other)
  self.class.new( val, @expr, @unit )
end

#+@Phys::Quantity

Unary Plus. Returns self.



223
224
225
# File 'lib/phys/units/quantity.rb', line 223

def +@
  self.class.new(  @value, @expr, @unit )
end

#-(other) ⇒ Phys::Quantity

Subtraction. Before the operation, it converts other to the unit of self.

  • If the other param is Phys::Quantity, other is converted to the unit of self.

  • If the other param is not Phys::Quantity, both params must be dimensionless.

Raises:



174
175
176
177
# File 'lib/phys/units/quantity.rb', line 174

def -(other)
  val = @value - @unit.convert_scale(other)
  self.class.new( val, @expr, @unit )
end

#-@Phys::Quantity

Unary Minus. Returns a quantity with negative value in the same unit of self.



230
231
232
# File 'lib/phys/units/quantity.rb', line 230

def -@
  self.class.new( -@value, @expr, @unit )
end

#/(other) ⇒ Phys::Quantity

Division. If the other param is not Phys::Quantity, other is regarded as a dimensionless value. The values and units are divided respectively. Note that the method of the value's class is used.

Examples:

Phys::Quantity[3,:m]/2 #=> Phys::Quantity[1,"m"]

Raises:



375
376
377
378
379
380
381
382
383
# File 'lib/phys/units/quantity.rb', line 375

def /(other)
  if Quantity===other
    a = [self.enclose_expr, other.enclose_expr_div]
    a.delete(nil)
    self.class.new( @value/other.value, a.join, @unit/other.unit )
  else
    self.class.new( @value/other, @expr, @unit )
  end
end

#<(other) ⇒ Boolean

Comparison. Returns true if self is less than other. Before the comparison, it converts other to the unit of self.

Raises:



281
282
283
# File 'lib/phys/units/quantity.rb', line 281

def < (other)
  @value < @unit.convert(other)
end

#<=(other) ⇒ Boolean

Comparison. Returns true if self is less-than or equal-to other. Before the comparison, it converts other to the unit of self.

Raises:



272
273
274
# File 'lib/phys/units/quantity.rb', line 272

def <= (other)
  @value <= @unit.convert(other)
end

#<=>(other) ⇒ Integer

Comparison of quantities. Before the comparison, it converts other to the unit of self.

Raises:



239
240
241
# File 'lib/phys/units/quantity.rb', line 239

def <=> (other)
  @value <=> @unit.convert(other)
end

#==(other) ⇒ Boolean

Equality. Returns true if self has the same value as other. Before the comparison, it converts other to the unit of self.



247
248
249
250
251
252
253
254
255
256
# File 'lib/phys/units/quantity.rb', line 247

def == (other)
  if Quantity===other
    @unit.conformable?(other.unit) &&
      @value == @unit.convert(other)
  elsif @unit.dimensionless?
    @unit.convert_value_to_base_unit(@value) == other
  else
    false
  end
end

#===(x) ⇒ Boolean Also known as: conformable?, compatible?, conversion_allowed?

Conformability of quantity. Returns true if unit conversion between self and x is possible.



564
565
566
567
568
569
570
571
572
573
574
575
# File 'lib/phys/units/quantity.rb', line 564

def ===(x)
  case x
  when Unit
    unit === x
  when Quantity
    unit === x.unit
  when Numeric
    unit.dimensionless?
  else
    false
  end
end

#>(other) ⇒ Boolean

Comparison. Returns true if self is greater than other. Before the comparison, it converts other to the unit of self.

Raises:



290
291
292
# File 'lib/phys/units/quantity.rb', line 290

def > (other)
  @value > @unit.convert(other)
end

#>=(other) ⇒ Boolean

Comparison. Returns true if self is greater-than or equal-to other. Before the comparison, it converts other to the unit of self.

Raises:



263
264
265
# File 'lib/phys/units/quantity.rb', line 263

def >= (other)
  @value >= @unit.convert(other)
end

#absPhys::Quantity

Absolute. Returns a quantity in the same unit of self.



181
182
183
# File 'lib/phys/units/quantity.rb', line 181

def abs
  self.class.new( @value.abs, @expr, @unit )
end

#abs2Phys::Quantity

Square. Returns a quantity in squared unit of self.



187
188
189
# File 'lib/phys/units/quantity.rb', line 187

def abs2
  self**2
end

#ceilPhys::Quantity

Ceil. Returns a quantity with the smallest Integer value greater than or equal to self value, in the same unit of self.



194
195
196
# File 'lib/phys/units/quantity.rb', line 194

def ceil
  self.class.new( @value.ceil, @expr, @unit )
end

#close_to(other, epsilon = Float::EPSILON) ⇒ Boolean

Closeness. Returns true if

(self-other).abs <= (self.abs+other.abs) * epsilon

Before the comparison, it converts other to the unit of self.

Raises:



301
302
303
304
305
# File 'lib/phys/units/quantity.rb', line 301

def close_to(other,epsilon=Float::EPSILON)
  other_value = @unit.convert(other)
  abs_sum = @value.abs+other_value.abs
  (@value-other_value).abs <= abs_sum*epsilon
end

#coerce(other) ⇒ Array



484
485
486
# File 'lib/phys/units/quantity.rb', line 484

def coerce(other)
  [ self.class.new(other), self ]
end

#div(other) ⇒ Object

Division without Modulo.

  • If the other param is Phys::Quantity, other is converted to the unit of self, and returns div of values.

  • If the other param is not Phys::Quantity, other is regarded as dimensionless, and returns div of Phys::Quantity.

Raises:



415
416
417
418
419
420
421
# File 'lib/phys/units/quantity.rb', line 415

def div(other)
  if Quantity===other
    @value.div( @unit.convert(other) )
  else
    self.class.new( @value.div(other), @expr, @unit )
  end
end

#divmod(other) ⇒ Array

Division with Modulo.

  • If the other param is Phys::Quantity, other is converted to the unit of self, and returns divmod of values.

  • If the other param is not Phys::Quantity, other is regarded as dimensionless, and returns divmod of Phys::Quantity.

Raises:



473
474
475
476
477
478
479
480
481
# File 'lib/phys/units/quantity.rb', line 473

def divmod(other)
  if Quantity===other
    @value.divmod( @unit.convert(other) )
  else
    d,m = @value.divmod(other)
    [ self.class.new( d, @expr, @unit ),
      self.class.new( m, @expr, @unit ) ]
  end
end

#floorPhys::Quantity

Floor. Returns a quantity with the largest integer value less than or equal to self value, in the same unit of self.



210
211
212
# File 'lib/phys/units/quantity.rb', line 210

def floor
  self.class.new( @value.floor, @expr, @unit )
end

#inspectString

Inspect String.



547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'lib/phys/units/quantity.rb', line 547

def inspect
  if @expr
    expr = "," +@expr.inspect
  else
    expr = ""
  end
  if @@verbose_inspect
    sufx = " "+@unit.inspect
  else
    sufx = ""
  end
  self.class.to_s+"["+Unit::Utils.num_inspect(@value)+expr+"]"+sufx
end

#quo(other) ⇒ Phys::Quantity Also known as: fdiv

Division more correctly. If the other param is not Phys::Quantity, other is regarded as a dimensionless value. The values and units are divided respectively.

Raises:



393
394
395
396
397
398
399
400
401
# File 'lib/phys/units/quantity.rb', line 393

def quo(other)
  if Quantity===other
    a = [self.enclose_expr, other.enclose_expr_div]
    a.delete(nil)
    self.class.new( @value.quo(other.value), a.join, @unit/other.unit )
  else
    self.class.new( @value.quo(other), @expr, @unit )
  end
end

#remainder(other) ⇒ Object

Remainder.

  • If the other param is Phys::Quantity, other is converted to the unit of self, and returns remainder of values.

  • If the other param is not Phys::Quantity, other is regarded as dimensionless, and returns remainder of Phys::Quantity.

Raises:



434
435
436
437
438
439
440
# File 'lib/phys/units/quantity.rb', line 434

def remainder(other)  #:nodoc: used internally
  if Quantity===other
    @value.remainder( @unit.convert(other) )
  else
    self.class.new( @value.remainder(other), @expr, @unit )
  end
end

#round(ndigits = nil) ⇒ Phys::Quantity

Round. Rounds self value to a given precision in decimal digits (default 0 digits). Returns a quantity with the rounded value in the same unit of self.



202
203
204
205
# File 'lib/phys/units/quantity.rb', line 202

def round(ndigits=nil)
  val = ndigits ? @value.round(ndigits) : @value.round
  self.class.new( val, @expr, @unit )
end

#to_base_unitPhys::Quantity Also known as: to_si, to_SI

Conversion to base unit. Returns the quantity converted to a base unit.

Raises:



492
493
494
495
496
497
# File 'lib/phys/units/quantity.rb', line 492

def to_base_unit
  unit = @unit.base_unit
  val  = unit.convert(self)
  expr = unit.unit_string
  self.class.new( val, expr, unit )
end

#to_fFloat Also known as: to_float

Conversion to Float.

Raises:



512
513
514
# File 'lib/phys/units/quantity.rb', line 512

def to_f
  to_numeric.to_f
end

#to_iInteger Also known as: to_int, to_integer

Conversion to Integer.

Raises:



520
521
522
# File 'lib/phys/units/quantity.rb', line 520

def to_i
  to_numeric.to_i
end

#to_numericNumeric Also known as: to_num

Conversion to Numeric.

Raises:



504
505
506
# File 'lib/phys/units/quantity.rb', line 504

def to_numeric
  @unit.to_numeric * @value
end

#to_rRational Also known as: to_rational

Conversion to Rational.

Raises:



529
530
531
# File 'lib/phys/units/quantity.rb', line 529

def to_r
  to_numeric.to_r
end

#to_sString

Conversion to String.



536
537
538
539
540
541
542
543
# File 'lib/phys/units/quantity.rb', line 536

def to_s
  if @expr
    expr = ",'" +@expr+"'"
  else
    expr = ""
  end
  self.class.to_s+"["+Unit::Utils.num_inspect(@value)+expr+"]"
end

#truncatePhys::Quantity

Truncate. Returns a quantity with the value truncated to an integer, in the same unit of self.



217
218
219
# File 'lib/phys/units/quantity.rb', line 217

def truncate
  self.class.new( @value.truncate, @expr, @unit )
end

#want(unit = nil) ⇒ Phys::Quantity Also known as: convert, >>

Conversion to a quantity in another unit.

Raises:



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/phys/units/quantity.rb', line 126

def want(unit=nil)
  case unit
  when Unit
    expr = unit.expr
  when Quantity
    expr = unit.expr
    unit = unit.unit
  when String,Symbol
    expr = unit
    unit = Unit.parse(expr)
  when Numeric
    unit = Unit.cast(unit)
  when NilClass
    unit = Unit.cast(1)
  else
    raise TypeError, "invalid argument: #{unit.inspect}"
  end
  val = unit.convert(self)
  self.class.new( val, expr, unit )
end