sy 2.1.2 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae8923105001742a2064fd481c4d717be266bb0b
4
- data.tar.gz: 17eb6ed00ef92bb3198b924ac1bb26c78e65e43a
3
+ metadata.gz: 05a4502f974a88c613b402394d0e303bac458836
4
+ data.tar.gz: 799053c77aef863d27d6d5e816289a26fe48952d
5
5
  SHA512:
6
- metadata.gz: 260fb7cf5817e8a6f2e6580ed4ad4659907e0ef4c7afb359cb2c2bd3be491f42d0b5db086562d2306139906a7c09e7f004ee5a26ea6213a18d2b5afa77ef69a9
7
- data.tar.gz: 90c477a51032265b20e2b4b83d20278ccaa2e1dabca76fab66892226aac7afa646dbd351fa3003ccdb2e28c03f4837d8c6d3d2fa2594e6441aab7b3e8de5a15d
6
+ metadata.gz: 9d83e13e2eac8a780dce7ea70f9f578586bbf749e9d1aec39345b9a6d5f0b4dc24754ce0cfd81671cddef6016cc6a242a1885e3b0be09f827cd410139c6a6d8d
7
+ data.tar.gz: 90f1266a32befff128873f820ebc679ff97de0a5f3325724864f3b24b7e4c9d32b8b50d362a256419a886f5ab61f9ac8bf0af087d2915422b6f5aa9b956e6bb5
data/lib/sy.rb CHANGED
@@ -5,7 +5,6 @@ require 'y_support/name_magic'
5
5
  require 'y_support/core_ext/hash'
6
6
  require 'y_support/typing'
7
7
  require 'y_support/unicode'
8
- require 'y_support/abstract_algebra'
9
8
 
10
9
  require 'active_support/core_ext/module/delegation'
11
10
  require 'active_support/core_ext/array/extract_options'
@@ -71,10 +70,7 @@ module SY
71
70
  # of the constant "UNIT" implies, via YSupport's NameMagic mixin, that the
72
71
  # name of the object becomes :unit and that it is possible to use syntax
73
72
  # such as 42.unit to create magnitudes of SY::Amount.
74
- puts "About to construct UNIT." if SY::DEBUG
75
73
  UNIT = Unit.standard of: Amount
76
- puts "UNIT constructed. SY::Unit instances are " +
77
- "#{SY::Unit.instance_names}" if SY::DEBUG
78
74
 
79
75
  # AVOGADRO_CONSTANT (Nᴀ) is a certain well-known amount of things:
80
76
  Nᴀ = AVOGADRO_CONSTANT = 6.02214e23
@@ -83,11 +79,7 @@ module SY
83
79
  MoleAmount = Quantity.dimensionless coerces: Amount
84
80
 
85
81
  # And let SY::MOLE be its standard unit, related to SY::Amount via Nᴀ:
86
- puts "About to construct MOLE." if SY::DEBUG
87
82
  MOLE = Unit.standard of: MoleAmount, short: "mol", amount: Nᴀ * UNIT
88
- puts SY::Unit.__instances__ if SY::DEBUG
89
- puts "MOLE constructed. SY::Unit instances are" +
90
- "#{SY::Unit.instance_names}" if SY::DEBUG
91
83
 
92
84
  # === Basic dimension L (length)
93
85
 
@@ -185,7 +177,7 @@ module SY
185
177
  super
186
178
  end
187
179
 
188
- # FIXME: #% method etc
180
+ # TODO: #% method etc
189
181
  end
190
182
 
191
183
  # Making sure that for Celsius temperature, #°C returns absolute magnitude.
@@ -196,10 +188,6 @@ module SY
196
188
  end
197
189
  end
198
190
 
199
- # FIXME: Make this more systematic.
200
- # FIXME: Make sure that SI prefixes may not be used with Celsius
201
- # FIXME: Make sure that highly unusual SI prefixes may not be used
202
-
203
191
  class << CelsiusTemperature.send( :Magnitude )
204
192
  include SY::CelsiusMagnitude
205
193
  end
@@ -208,32 +196,9 @@ module SY
208
196
  include SY::CelsiusMagnitude
209
197
  end
210
198
 
211
- # alias :°C :celsius # with U+00B0 DEGREE SIGN
212
- # alias :˚C :celsius # with U+02DA RING ABOVE
213
- # alias :℃ :celsius # U+2103 DEGREE CELSIUS
214
-
215
- # FahrenheitTemperature = Quantity.of :Θ
216
- # FAHRENHEIT = Unit.standard of: FahrenheitTemperature, short: '°F'
217
- # # alias :°F :fahrenheit # with U+00B0 DEGREE SIGN
218
- # # alias :˚F :fahrenheit # with U+02DA RING ABOVE
219
- # # alias :℉ :fahrenheit # U+2109 DEGREE FAHRENHEIT
220
- # # FIXME: Patch FahrenheitTemperature to make it work with SY::Temperature
221
-
222
-
223
- # HUMAN_BODY_TEMPERATURE = 37.°C.( KELVIN )
224
- # STANDARD_TEMPERATURE = 25.°C.( KELVIN )
225
199
  HUMAN_BODY_TEMPERATURE = TP_H₂O + 37 * KELVIN
226
200
  STANDARD_LABORATORY_TEMPERATURE = TP_H₂O + 25 * KELVIN
227
201
 
228
- # === Dimensionless quantities
229
-
230
- # For now, these are just unimplemented proposals of what users might expect
231
- # from SY:
232
- #
233
- # degree, alias deg, ° # angle measure
234
- # arcminute, alias ʹ, ′ # angle measure
235
- # arcsecond, alias ʹʹ, ′′, ″
236
-
237
202
  # === Quantities of composite dimensions
238
203
 
239
204
  # Quantity SY::Area is obtained by raising quantity SY::Length to 2:
@@ -281,7 +246,7 @@ module SY
281
246
  # of its dimension.
282
247
  Speed = ( Length / Time ).standard!
283
248
 
284
- # Common constant
249
+ # Commonly used constant.
285
250
  SPEED_OF_LIGHT = 299_792_458 * METRE / SECOND
286
251
 
287
252
  # Supplementary unit of length.
@@ -299,7 +264,7 @@ module SY
299
264
  # For SY::Energy...
300
265
  Energy = ( Force * Length ).standard!
301
266
 
302
- # make SY::JOULE its standard unit:
267
+ # Make SY::JOULE its standard unit:
303
268
  JOULE = Unit.standard of: Energy, short: "J"
304
269
  # SY::CALORIE means thermochemical calorie:
305
270
  CALORIE = Unit.of Energy, short: "cal", amount: 4.184 * JOULE
@@ -331,11 +296,6 @@ module SY
331
296
  # make SY::VOLT its standard unit:
332
297
  VOLT = Unit.standard of: ElectricPotential, short: "V"
333
298
 
334
- # TODO: This should raise a friendly error:
335
- # MOLAR = Unit.standard of: Molarity, short: "M", amount: 1.mol.l⁻¹
336
- # (normal way of definition is MOLAR = Unit.standard of: Molarity, short: "M"
337
- # and it has already been defined to boot)
338
-
339
299
  # SY::Molality...
340
300
  Molality = MoleAmount / Mass
341
301
 
@@ -351,4 +311,4 @@ module SY
351
311
  ELEMENTARY_CHARGE = 1.60217656535e-19 * COULOMB
352
312
 
353
313
  ELECTRONVOLT = Unit.of Energy, short: "eV", amount: ELEMENTARY_CHARGE * VOLT
354
- end
314
+ end
@@ -18,24 +18,15 @@ module SY::AbsoluteMagnitude
18
18
  # and :amount named argument, where amount must be nonnegative.
19
19
  #
20
20
  def initialize( of: nil, amount: nil )
21
- puts "Constructing AbsoluteMagnitude of #{of}, amount: #{amount}" if SY::DEBUG
22
21
  fail ArgumentError, "Quantity (:of) argument missing!" if of.nil?
23
22
  @quantity = of
24
23
  @amount = case amount
25
- when Numeric then
26
- puts "This amount is a Numeric, using it directly" if SY::DEBUG
27
- amount
28
- when nil then
29
- puts "This amount is 'nil', using 1 instead" if SY::DEBUG
30
- 1
24
+ when Numeric then amount
25
+ when nil then 1
31
26
  else
32
27
  begin
33
- puts "Amount #{amount} will be reframed to #{@quantity}" if SY::DEBUG
34
28
  amount.( @quantity ).amount
35
- rescue NameError, NoMethodError
36
- puts "fail, amount #{amount} will be used directly" if SY::DEBUG
37
- amount
38
- end
29
+ rescue NameError, NoMethodError; amount end
39
30
  end
40
31
  fail SY::MagnitudeError, "Attempt to construct an unsigned magnitude " +
41
32
  "(SY::AbsoluteMagnitude) with a negative amount." if @amount < 0
@@ -44,16 +35,12 @@ module SY::AbsoluteMagnitude
44
35
  # For absolute magnitudes, #+ method always returns a result framed in
45
36
  # corresponding relative quantity.
46
37
  #
47
- # TODO: Figure out which module comes on the top in Quantity@Magnitude, whether Magnitude
48
- # or SignedMagnitude, and therefore, whether it is necessary to adjust this method.
49
38
  def + m2
50
39
  return magnitude amount + m2.amount if m2.quantity == quantity.relative
51
40
  return quantity.relative.magnitude( amount + m2.amount ) if
52
41
  quantity == m2.quantity
53
42
  return self if m2.equal? SY::ZERO
54
- # o1, o2 = m2.coerce( self )
55
- # return o1 + o2
56
- raise SY::QuantityError, "Unable to perform #{quantity} + #{m2.quantity}!"
43
+ fail SY::QuantityError, "Unable to perform #{quantity} + #{m2.quantity}!"
57
44
  end
58
45
 
59
46
  # Addition of absolute magnitudes that returns a result framed as
@@ -62,24 +49,18 @@ module SY::AbsoluteMagnitude
62
49
  def add m2
63
50
  return magnitude( amount + m2.amount ) if quantity == m2.quantity
64
51
  return self if m2.equal? SY::ZERO
65
- # o1, o2 = m2.coerce( self )
66
- # return o1.add o2
67
- raise SY::QuantityError, "Unable to perform #add with #{m2.quantity}!"
52
+ fail SY::QuantityError, "Unable to perform #add with #{m2.quantity}!"
68
53
  end
69
54
 
70
55
  # For absolute magnitudes, #- method always returns a result framed in
71
56
  # corresponding relative quantity.
72
57
  #
73
- # TODO: Figure out which module comes on the top in Quantity@Magnitude, whether Magnitude
74
- # or SignedMagnitude, and therefore, whether it is necessary to adjust this method.
75
58
  def - m2
76
59
  return magnitude amount - m2.amount if m2.quantity == quantity.relative
77
60
  return quantity.relative.magnitude( amount - m2.amount ) if
78
61
  quantity == m2.quantity
79
62
  return self if m2.equal? SY::ZERO
80
- # o1, o2 = m2.coerce( self )
81
- # return o1 - o2
82
- raise( SY::QuantityError, "Unable to perform #{quantity} - #{m2.quantity}!" )
63
+ fail SY::QuantityError, "Unable to perform #{quantity} - #{m2.quantity}!"
83
64
  end
84
65
 
85
66
  # Subtraction of absolute magnitudes that returns a result framed as
@@ -89,9 +70,7 @@ module SY::AbsoluteMagnitude
89
70
  def subtract m2
90
71
  return magnitude( amount + m2.amount ) if quantity == m2.quantity
91
72
  return self if m2.equal? SY::ZERO
92
- # o1, o2 = m2.coerce( self )
93
- # return o1.subtract o2
94
- raise( SY::QuantityError, "Unable to perform #add with #{m2.quantity}!" )
73
+ fail SY::QuantityError, "Unable to perform #add with #{m2.quantity}!"
95
74
  end
96
75
 
97
76
  # "Subtraction" of absolute magnitudes, that never takes more thant the
@@ -112,7 +91,5 @@ module SY::AbsoluteMagnitude
112
91
 
113
92
  # String describing this class.
114
93
  #
115
- def çς
116
- "Magnitude"
117
- end
94
+ def çς; "Magnitude" end
118
95
  end # class SY::AbsoluteMagnitude
@@ -28,8 +28,8 @@ class SY::Composition < Hash
28
28
  ꜧ.reject! { |_, exp| exp == 0 }
29
29
  }
30
30
 
31
- # FIXME: This quick fix simplification rule simplifies MoleAmount and
32
- # LitreVolume into Molarity. This solution is insufficiently systematic.
31
+ # This simplification rule simplifies MoleAmount and LitreVolume into
32
+ # Molarity.
33
33
  #
34
34
  SR << -> ꜧ {
35
35
  begin
@@ -61,8 +61,8 @@ class SY::Composition < Hash
61
61
  return ꜧ
62
62
  }
63
63
 
64
- # FIXME: This quick fix simplification rule simplifies LitreVolume times
65
- # Molarity into MoleAmount. This solution is insufficiently systematic.
64
+ # This simplification rule simplifies LitreVolume times Molarity into
65
+ # MoleAmount.
66
66
  #
67
67
  SR << -> ꜧ {
68
68
  begin
@@ -130,8 +130,6 @@ class SY::Composition < Hash
130
130
  # is a base dimension.
131
131
  #
132
132
  def atomic?
133
- puts "composition is #{self}" if SY::DEBUG
134
- puts "first[0].dimension is #{first[0].dimension}" if SY::DEBUG
135
133
  singular? && first[0].dimension.base?
136
134
  end
137
135
 
@@ -206,9 +204,8 @@ class SY::Composition < Hash
206
204
  #
207
205
  def simplify
208
206
  ꜧ = self.to_hash
209
- puts "simplifying #{ꜧ}" if SY::DEBUG
210
207
  SIMPLIFICATION_RULES.each { |rule| rule.( ꜧ ) }
211
- self.class[ ꜧ ].tap { |_| puts "result is #{_}" if SY::DEBUG }
208
+ self.class[ ꜧ ]
212
209
  end
213
210
 
214
211
  # Returns the quantity appropriate to this composition.
@@ -236,15 +233,8 @@ class SY::Composition < Hash
236
233
  # of the pertinent standard quantity.)
237
234
  #
238
235
  def infer_measure
239
- puts "#infer_measure; hash is #{self}" if SY::DEBUG
240
236
  map do |qnt, exp|
241
- puts "#infer_measure: doing quantity #{qnt} with exponent #{exp}!" if SY::DEBUG
242
- if qnt.standardish? then
243
- puts "#{qnt} standardish" if SY::DEBUG
244
- SY::Measure.identity
245
- else
246
- puts "#{qnt} not standardish" if SY::DEBUG
247
- puts "its measure is #{qnt.measure}, class #{qnt.measure.class}" if SY::DEBUG
237
+ if qnt.standardish? then SY::Measure.identity else
248
238
  qnt.measure( of: qnt.standard ) ** exp
249
239
  end
250
240
  end.reduce( SY::Measure.identity, :* )
@@ -265,18 +255,13 @@ class SY::Composition < Hash
265
255
  #
266
256
  def expand
267
257
  return self if irreducible?
268
- puts "#expand: #{self} not irreducible" if SY::DEBUG
269
258
  self.class[ reduce( self.class.empty ) { |cᴍ, pair|
270
259
  qnt, exp = pair
271
- puts "#expand: qnt: #{qnt}, exp: #{exp}" if SY::DEBUG
272
- puts "cᴍ is #{cᴍ}" if SY::DEBUG
273
260
  ( cᴍ + if qnt.irreducible? then
274
261
  self.class.singular( qnt ) * exp
275
262
  else
276
263
  qnt.composition * exp
277
- end.tap { |x| puts "Adding #{x}." if SY::DEBUG }
278
- ).tap { |x| puts "Result is #{x}." if SY::DEBUG }
264
+ end )
279
265
  } ]
280
- .tap{ |rslt| puts "#expand: result is #{rslt}" if SY::DEBUG }
281
266
  end
282
267
  end # class SY::Composition
@@ -39,9 +39,7 @@ class SY::Dimension
39
39
 
40
40
  # Presents class-owned instances (array).
41
41
  #
42
- def instances
43
- return @instances ||= []
44
- end
42
+ def instances; return @instances ||= [] end
45
43
 
46
44
  # Base dimension constructor. Base dimension symbol is expeced as argument.
47
45
  #
@@ -23,7 +23,7 @@ module SY::ExpressibleInUnits
23
23
  im = instance_method ß
24
24
  warn w unless ::SY::ExpressibleInUnits.method_family.include? im if
25
25
  ꜧ[ß].warns? unless instance_variable_get( :@no_collision ) == ß
26
- instance_variable_set( :@no_collision, nil ) # FIXME: This is too clumsy
26
+ instance_variable_set( :@no_collision, nil )
27
27
  else
28
28
  warn w if ꜧ[ß].warns?
29
29
  end
@@ -33,7 +33,7 @@ module SY::ExpressibleInUnits
33
33
  im = instance_method ß
34
34
  warn w unless ::SY::ExpressibleInUnits.method_family.include? im if
35
35
  ꜧ[ß].warns? unless instance_variable_get( :@no_collision ) == ß
36
- instance_variable_set( :@no_collision, nil ) # FIXME: This is too clumsy
36
+ instance_variable_set( :@no_collision, nil )
37
37
  else
38
38
  warn w if ꜧ[ß].warns?
39
39
  end
@@ -83,10 +83,7 @@ module SY::ExpressibleInUnits
83
83
  def known_units
84
84
  begin
85
85
  unit_namespace.instances
86
- rescue NoMethodError
87
- [] # no #instances method defined yet
88
- end
89
- .tap { |r| puts "Known units are #{r}" if SY::DEBUG }
86
+ rescue NoMethodError; [] end
90
87
  end
91
88
 
92
89
  # All methods defined by this mixin.
@@ -98,7 +95,6 @@ module SY::ExpressibleInUnits
98
95
  # Find unit based on name / abbreviation.
99
96
  #
100
97
  def find_unit ς
101
- puts "searching for unit #{ς}" if SY::DEBUG
102
98
  known_units.find do |u|
103
99
  u.name.to_s.downcase == ς.downcase &&
104
100
  ( ς == ς.downcase || ς == ς.upcase ) ||
@@ -109,7 +105,6 @@ module SY::ExpressibleInUnits
109
105
  # Return prefix method or empty string, if prefix method not necessary.
110
106
  #
111
107
  def prefix_method_string prefix
112
- puts "About to call PREFIX TABLE.to_full with #{prefix}" if SY::DEBUG
113
108
  full_prefix = SY::PREFIX_TABLE.to_full( prefix )
114
109
  full_prefix == '' ? '' : ".#{full_prefix}"
115
110
  end
@@ -126,19 +121,12 @@ module SY::ExpressibleInUnits
126
121
  super if ß.to_s =~ /to_.+/ # dissmiss :to_..., esp. :to_ary
127
122
  begin # prevent recurrent call of method_missing for the same symbol
128
123
  anti_recursion_exec token: ß, var: :@SY_Units_mmiss do
129
- puts "Method missing: '#{ß}'" if SY::DEBUG
130
124
  prefixes, units, exps = parse_unit_symbol ß
131
- # Define the unit method on self.class:
132
- # I'D HAVE TO PERFORM THE COLLISION CHECK HERE
133
- # IF NO COLLISION, INFORM THE SUBSEQUENT METHOD DEFINED CALL ON
134
- # SELF.CLASS
135
- puts "parsed" if SY::DEBUG
136
- self.class.instance_variable_set "@no_collision", ß # FIXME: This is too clumsy
125
+ self.class.instance_variable_set "@no_collision", ß
137
126
  self.class.module_eval write_unit_method( ß, prefixes, units, exps )
138
127
  SY::ExpressibleInUnits.method_family << self.class.instance_method( ß )
139
128
  end
140
129
  rescue NameError => err
141
- puts "NameError raised: #{err}" if SY::DEBUG
142
130
  super # give up
143
131
  rescue SY::ExpressibleInUnits::RecursionError
144
132
  super # give up
@@ -167,7 +155,6 @@ module SY::ExpressibleInUnits
167
155
  # figures out which SY units it represents, along with prefixes and exponents.
168
156
  #
169
157
  def parse_unit_symbol ß
170
- puts "About to parse #{ß} using all prefixes" if SY::DEBUG
171
158
  SY::Unit.parse_sps_using_all_prefixes( ß ) # rely on SY::Unit
172
159
  end
173
160
 
@@ -176,12 +163,10 @@ module SY::ExpressibleInUnits
176
163
  # Arrays must be of equal length. (Note: 'ß' is 'symbol', 'ς' is 'string')
177
164
  #
178
165
  def write_unit_method ß, prefixes, units, exponents
179
- puts "writing unit method #{ß}" if SY::DEBUG
180
166
  # Prepare prefix / unit / exponent triples for making factor strings:
181
167
  triples = [ prefixes, units, exponents ].transpose
182
168
  # A procedure for triple processing before use:
183
169
  process_triple = lambda do |pfx, unit_ς, exp|
184
- puts "Processing triple #{pfx}, #{unit_ς}, #{exp}." if SY::DEBUG
185
170
  [ ::SY::ExpressibleInUnits.find_unit( unit_ς ).name.to_s.upcase,
186
171
  ::SY::ExpressibleInUnits.prefix_method_string( pfx ),
187
172
  ::SY::ExpressibleInUnits.exponentiation_string( exp ) ]
@@ -211,7 +196,7 @@ module SY::ExpressibleInUnits
211
196
  method_body = factors.join( " * \n " )
212
197
  end
213
198
  # Return the finished method string:
214
- return ( method_skeleton % method_body ).tap { |ς| puts ς if SY::DEBUG }
199
+ return ( method_skeleton % method_body )
215
200
  end
216
201
 
217
202
  # Takes a token as the first argument, a symbol of the instance variable to
@@ -230,9 +215,4 @@ module SY::ExpressibleInUnits
230
215
  registry.delete token
231
216
  end
232
217
  end
233
-
234
- # FIXME: There should be an option to define by default, already at the
235
- # beginning, certain methods for certain classes, to get in front of possible
236
- # collisions. Collision was detected for example for #second with
237
- # active_support/duration.rb
238
218
  end
@@ -18,22 +18,16 @@ module SY
18
18
  class << BASE_DIMENSIONS
19
19
  # Letters of the base dimensions.
20
20
  #
21
- def letters
22
- keys
23
- end
21
+ def letters; keys end
24
22
 
25
23
  # Base dimensions letters with prefixes. (Remark: I forgot what did I mean
26
24
  # those prefixes for. Something important, I just forgot what.)
27
25
  #
28
- def prefixed_letters
29
- [] # none for now
30
- end
26
+ def prefixed_letters; [] end
31
27
 
32
28
  # Base dimension symbols – letters and prefixed letters.
33
29
  #
34
- def base_symbols
35
- @baseß ||= letters + prefixed_letters
36
- end
30
+ def base_symbols; @baseß ||= letters + prefixed_letters end
37
31
  alias basic_symbols base_symbols
38
32
 
39
33
  # Takes an sps representing a dimension, and converts it to a hash of
@@ -45,7 +39,7 @@ module SY
45
39
  end
46
40
  end
47
41
 
48
- # Table of standard prefixes and their corresponding unit multiples.
42
+ # Table of standard prefixes and their corresponding unit multiples.
49
43
  #
50
44
  PREFIX_TABLE = [ { full: "exa", short: "E", factor: 1e18 },
51
45
  { full: "peta", short: "P", factor: 1e15 },
@@ -144,9 +138,7 @@ module SY
144
138
  SUPERSCRIPT = Hash.new { |ꜧ, key|
145
139
  if key.is_a? String then
146
140
  key.size <= 1 ? nil : key.each_char.map{|c| ꜧ[c] }.join
147
- else
148
- ꜧ[key.to_s]
149
- end
141
+ else ꜧ[key.to_s] end
150
142
  }.merge! Hash[ '-/0123456789'.each_char.zip( '⁻⎖⁰¹²³⁴⁵⁶⁷⁸⁹'.each_char ) ]
151
143
 
152
144
  # Reverse conversion of Unicode superscript exponents (from exponent
@@ -155,9 +147,7 @@ module SY
155
147
  SUPERSCRIPT_DOWN = Hash.new { |ꜧ, key|
156
148
  if key.is_a? String then
157
149
  key.size == 1 ? nil : key.each_char.map{|c| ꜧ[c] }.join
158
- else
159
- ꜧ[key.to_s]
160
- end
150
+ else ꜧ[key.to_s] end
161
151
  }.merge!( SUPERSCRIPT.invert ).merge!( '¯' => '-', # other superscript chars
162
152
  '´' => '/' )
163
153
 
@@ -265,124 +265,16 @@ module SY::Magnitude
265
265
 
266
266
  #
267
267
  def to_s( unit=quantity.units.first || quantity.standard_unit,
268
- number_format=default_amount_format ) # FIXME: TUTO JE TO KUREVSTVO TU SA TA JEDNOTKA KONSTRUUJE
269
- puts "#to_s called on a magnitude of quantity #{quantity}" if SY::DEBUG
270
- # step 1: produce pairs [number, unit_presentation],
271
- # where unit_presentation is an array of triples
272
- # [prefix, unit, exponent], which together give the
273
- # correct dimension for this magnitude, and correct
274
- # factor so that number * factor == self.amount
275
- # step 2: define a goodness function for them
276
- # step 3: define a satisfaction criterion
277
- # step 4: maximize this goodness function until the satisfaction
278
- # criterion is met
279
- # step 5: interpolate the string from the chosen choice
280
-
281
- # so, let's start doing it
282
- # how do we produce the first choice?
283
- # if the standard unit for this quantity is named, we'll start with it
284
-
285
- # let's say that the abbreviation of this std. unit is Uu, so the first
286
- # choices will be:
287
- #
288
- # amount.Uu
289
- # (amount * 1000).µUu
290
- # (amount / 1000).kUu
291
- # (amount * 1_000_000).nUu
292
- # (amount / 1_000_000).MUu
293
- # ...
294
- #
295
- # (let's say we'll use only short prefixes)
296
- #
297
- # which one do we use?
298
- # That depends. For example, CelsiusTemperature is never rendered with
299
- # SI prefixes, so their cost should be +Infinity
300
- #
301
- # Cost of the number could be eg.:
302
- #
303
- # style: cost:
304
- # 3.141 0
305
- # 31.41, 314.1 1
306
- # 0.3141 2
307
- # 3141.0 3
308
- # 0.03141 4
309
- # 31410.0 5n
310
- # 0.003141 6
311
- # ...
312
- #
313
- # Default cost of prefixes could be eg.
314
- #
315
- # unit representation: cost:
316
- # U 0
317
- # dU +Infinity
318
- # cU +Infinity
319
- # mU 1
320
- # dkU +Infinity
321
- # hU +Infinity
322
- # kU 1
323
- # µU 2
324
- # MU 2
325
- # nU 3
326
- # GU 3
327
- # pU 4
328
- # TU 4
329
- # fU 5
330
- # PU 5
331
- # aU 6
332
- # EU 6
333
- #
334
- # Cost of exponents could be eg. their absolute value, and +1 for minus sign
335
- #
336
- # Same unit with two different prefixes may never be used (cost +Infinity)
337
- #
338
- # Afterwards, there should be cost of inconsistency. This could be implemented
339
- # eg. as computing the first 10 possibilities for amount: 1 and giving them
340
- # bonuses -20, -15, -11, -8, -6, -5, -4, -3, -2, -1. That would further reduce the variability of the
341
- # unit representations.
342
- #
343
- # Commenting again upon default cost of prefixes, prefixes before second:
344
- #
345
- # prefix: cost:
346
- # s 0
347
- # ms 4
348
- # ns 5
349
- # ps 6
350
- # fs 7
351
- # as 9
352
- # ks +Infinity
353
- # Ms +Infinity
354
- # ...
355
- #
356
- # Prefixes before metre
357
- #
358
- # prefix: cost:
359
- # m 0
360
- # mm 2
361
- # µm 2
362
- # nm 3
363
- # km 3
364
- # Mm +Infinity
365
- # ...
366
- #
367
-
368
- # number, unit_presentation = choice
369
-
370
- # return "#{amount} of #{quantity}"
371
-
268
+ number_format=default_amount_format )
372
269
  begin
373
-
374
270
  un = unit.short || unit.name
375
-
376
271
  if un then
377
272
  number = self.in unit
378
273
  number_ς = number_format % number
379
-
380
274
  prefix = ''
381
275
  exp = 1
382
276
  # unit_presentation = prefix, unit, exp
383
-
384
277
  unit_ς = SY::SPS.( [ "#{prefix}#{unit.short}" ], [ exp ] )
385
-
386
278
  [ number_ς, unit_ς ].join '.'
387
279
  else
388
280
  number = amount
@@ -406,7 +298,6 @@ module SY::Magnitude
406
298
  return number_ς if unit_ς == '' || unit_ς == 'unit'
407
299
  [ number_ς, unit_ς ].join '.'
408
300
  end
409
-
410
301
  rescue
411
302
  fail
412
303
  number_ς = number_format % amount
@@ -414,29 +305,9 @@ module SY::Magnitude
414
305
  end
415
306
  end
416
307
 
417
- # def to_s unit=quantity.units.first, number_format='%.3g'
418
- # begin
419
- # return to_string( unit ) if unit and unit.abbreviation
420
- # rescue
421
- # end
422
- # # otherwise, use units of basic dimensions – here be the magic:
423
- # hsh = dimension.to_hash
424
- # symbols, exponents = hsh.each_with_object Hash.new do |pair, memo|
425
- # dimension_letter, exponent = pair
426
- # std_unit = SY::Dimension.basic( dimension_letter ).standard_unit
427
- # memo[ std_unit.abbreviation || std_unit.name ] = exponent
428
- # end.to_a.transpose
429
- # # assemble the superscripted product string:
430
- # sps = SY::SPS.( symbols, exponents )
431
- # # and finally, interpolate the string
432
- # "#{number_format}#{sps == '' ? '' : '.' + sps}" % amount
433
- # "#{amount}#{sps == '' ? '' : '.' + sps}"
434
- # end
435
-
436
308
  # Inspect string of the magnitude
437
309
  #
438
310
  def inspect
439
- puts "inspect called on a magnitude of quantity #{quantity}" if SY::DEBUG
440
311
  "#<#{çς}: #{self} >"
441
312
  end
442
313
 
@@ -12,15 +12,11 @@ class SY::Measure
12
12
  class << self
13
13
  # Identity measure.
14
14
  #
15
- def identity
16
- simple_scale 1
17
- end
15
+ def identity; simple_scale 1 end
18
16
 
19
17
  # Simple scaling measure. (Eg. pounds vs kilograms)
20
18
  #
21
- def simple_scale scale
22
- new( ratio: scale )
23
- end
19
+ def simple_scale scale; new( ratio: scale ) end
24
20
 
25
21
  # Simple offset measure. (Such as °C)
26
22
  #
@@ -89,11 +85,8 @@ class SY::Measure
89
85
  # Inverse measure.
90
86
  #
91
87
  def inverse
92
- if ratio.nil? then
93
- self.class.new( r: w, w: r ) # swap closures
94
- else
95
- self.class.new( ratio: 1 / ratio )
96
- end
88
+ if ratio.nil? then self.class.new( r: w, w: r ) # swap closures
89
+ else self.class.new( ratio: 1 / ratio ) end
97
90
  end
98
91
 
99
92
  # Measure composition (like f * g function composition).
@@ -65,9 +65,7 @@ class Matrix
65
65
  def /(other)
66
66
  case other
67
67
  when Numeric
68
- rows = @rows.collect {|row|
69
- row.collect {|e| e / other }
70
- }
68
+ rows = @rows.collect do |row| row.collect {|e| e / other } end
71
69
  return new_matrix rows, column_count
72
70
  when Matrix
73
71
  return self * other.inverse
@@ -87,11 +87,8 @@ class SY::Measure
87
87
  # Inverse measure.
88
88
  #
89
89
  def inverse
90
- if ratio.nil? then
91
- self.class.new( r: w, w: r ) # swap closures
92
- else
93
- self.class.new( ratio: 1 / ratio )
94
- end
90
+ if ratio.nil? then self.class.new( r: w, w: r ) # swap closures
91
+ else self.class.new( ratio: 1 / ratio ) end
95
92
  end
96
93
 
97
94
  # Measure composition (like f * g function composition).
@@ -101,9 +98,7 @@ class SY::Measure
101
98
  r1, r2, w1, w2 = r, other.r, w, other.w
102
99
  self.class.new( r: lambda { |ref_amnt| r1.( r2.( ref_amnt ) ) },
103
100
  w: lambda { |amnt| w2.( w1.( amnt ) ) } )
104
- else
105
- self.class.new( ratio: ratio * other.ratio )
106
- end
101
+ else self.class.new( ratio: ratio * other.ratio ) end
107
102
  end
108
103
 
109
104
  # Measure composition with inverse of another measure.
@@ -5,10 +5,6 @@
5
5
  class SY::Quantity
6
6
  include NameMagic
7
7
 
8
- # name_set_hook do |name, new_instance, old_name|
9
- # new_instance.protect!; name
10
- # end
11
-
12
8
  RELATIVE_QUANTITY_NAME_SUFFIX = "±"
13
9
 
14
10
  attr_reader :MagnitudeModule, :Magnitude, :Unit
@@ -38,7 +34,6 @@ class SY::Quantity
38
34
  #
39
35
  def standard( of: nil )
40
36
  fail ArgumentError, "Dimension (:of argument) must be given!" if of.nil?
41
- puts "Constructing standard quantity of #{of} dimension" if SY::DEBUG
42
37
  return SY.Dimension( of ).standard_quantity
43
38
  end
44
39
 
@@ -64,14 +59,11 @@ class SY::Quantity
64
59
  coerces: [],
65
60
  coerces_to: [],
66
61
  **nn )
67
- puts "Quantity init relative: #{relative}, composition: #{composition}, measure: #{measure}, #{nn}" if SY::DEBUG
68
62
  @units = [] # array of units as favored by this quantity
69
63
  @relative = relative
70
64
  if composition.nil? then
71
- puts "Composition not given, dimension expected." if SY::DEBUG
72
65
  @dimension = SY.Dimension( of )
73
66
  else
74
- puts "Composition received (#{composition})." if SY::DEBUG
75
67
  @composition = SY::Composition[ composition ]
76
68
  @dimension = @composition.dimension
77
69
  end
@@ -86,9 +78,6 @@ class SY::Quantity
86
78
  end
87
79
  coerces( *Array( coerces ) )
88
80
  Array( coerces_to ).each { |qnt| qnt.coerces self }
89
- puts "Composition of the initialized instance is #{composition}." if SY::DEBUG
90
- puts "Initialized instance is #{relative? ? :relative : :absolute}" if SY::DEBUG
91
- puts "Initialized instance object_id is #{object_id}" if SY::DEBUG
92
81
  end
93
82
 
94
83
  # Simple quantity is one with simple composition. If nontrivial composition
@@ -193,21 +182,15 @@ class SY::Quantity
193
182
  #
194
183
  def measure( of: nil )
195
184
  return @measure if of.nil? # act as simple getter if :of not specified
196
- puts "#{self.inspect} asked about measure of #{of}" if SY::DEBUG
197
185
  return SY::Measure.identity if of == self or of == colleague
198
- raise SY::DimensionError, "#{self} vs. #{of}!" unless same_dimension? of
186
+ fail SY::DimensionError, "#{self} vs. #{of}!" unless same_dimension? of
199
187
  return of.measure( of: of.standard ).inverse if standardish?
200
188
  m = begin
201
- puts "composition is #{composition}, class #{composition.class}" if SY::DEBUG
202
- measure ||
203
- colleague.measure ||
204
- composition.infer_measure
189
+ measure || colleague.measure || composition.infer_measure
205
190
  rescue NoMethodError
206
191
  fail SY::QuantityError, "Measure of #{of} by #{self} impossible!"
207
192
  end
208
193
  return m if of.standardish?
209
- puts "#{of} not standardish, obtained measure relates to #{standard}, and " +
210
- "it will have to be extended to #{of}." if SY::DEBUG
211
194
  return m * standard.measure( of: of )
212
195
  end
213
196
 
@@ -266,11 +249,7 @@ class SY::Quantity
266
249
  # Constructs a absolute magnitude of this quantity.
267
250
  #
268
251
  def magnitude amount
269
- puts "self.object_id is #{object_id}" if SY::DEBUG
270
- puts "composition is #{composition}" if SY::DEBUG
271
- puts "Constructing #{self}#magnitude with amount #{amount}." if SY::DEBUG
272
252
  Magnitude().new( of: self, amount: amount )
273
- .tap { puts "#{self}#magnitude constructed!" if SY::DEBUG }
274
253
  end
275
254
 
276
255
  # Constructs a new unit of this quantity.
@@ -307,7 +286,6 @@ class SY::Quantity
307
286
  # Quantity multiplication.
308
287
  #
309
288
  def * q2
310
- puts "#{self.name} * #{q2.name}" if SY::DEBUG
311
289
  rel = [ self, q2 ].any? &:relative
312
290
  ( SY::Composition[ self => 1 ] + SY::Composition[ q2 => 1 ] )
313
291
  .to_quantity relative: rel
@@ -316,7 +294,6 @@ class SY::Quantity
316
294
  # Quantity division.
317
295
  #
318
296
  def / q2
319
- puts "#{self.name} / #{q2.name}" if SY::DEBUG
320
297
  rel = [ self, q2 ].any? &:relative?
321
298
  ( SY::Composition[ self => 1 ] - SY::Composition[ q2 => 1 ] )
322
299
  .to_quantity relative: rel
@@ -325,7 +302,6 @@ class SY::Quantity
325
302
  # Quantity raising to a number.
326
303
  #
327
304
  def ** num
328
- puts "#{self.name} ** #{num}" if SY::DEBUG
329
305
  SY::Composition[ self => num ].to_quantity relative: relative?
330
306
  end
331
307
 
@@ -344,8 +320,6 @@ class SY::Quantity
344
320
  # Returns the standard quantity for this quantity's dimension.
345
321
  #
346
322
  def standard
347
- puts "Dimension of this quantity is #{dimension}" if SY::DEBUG
348
- puts "Its standard quantity is #{dimension.standard_quantity}" if SY::DEBUG
349
323
  dimension.standard_quantity
350
324
  end
351
325
 
@@ -397,21 +371,16 @@ class SY::Quantity
397
371
  # Main parametrized (ie. quantity-specific) module for magnitudes.
398
372
  #
399
373
  def MagnitudeModule
400
- puts "#{self}#MagnitudeModule called" if SY::DEBUG
401
374
  @MagnitudeModule ||= if absolute? then
402
375
  Module.new { include SY::Magnitude }
403
- else
404
- absolute.MagnitudeModule
405
- end
376
+ else absolute.MagnitudeModule end
406
377
  end
407
378
 
408
379
  # Parametrized magnitude class.
409
380
  #
410
381
  def Magnitude
411
- puts "#{self}#Magnitude called" if SY::DEBUG
412
382
  @Magnitude or
413
- ( puts "Constructing #{self}@Magnitude parametrized class" if SY::DEBUG
414
- mmod = MagnitudeModule()
383
+ ( mmod = MagnitudeModule()
415
384
  mixin = relative? ? SY::SignedMagnitude : SY::AbsoluteMagnitude
416
385
  qnt_ɴ_λ = -> { name ? "#{name}@%s" : "#<Quantity:#{object_id}@%s>" }
417
386
 
@@ -439,18 +408,15 @@ class SY::Quantity
439
408
  # Parametrized unit class.
440
409
  #
441
410
  def Unit
442
- puts "#{self}#Unit called" if SY::DEBUG
443
- @Unit ||= ( puts "Constructing #{self}@Unit parametrized class" if SY::DEBUG
444
- if relative? then absolute.Unit else
411
+ @Unit ||= ( if relative? then absolute.Unit else
445
412
  qnt = self
446
413
  ɴλ = -> { name ? "#{name}@%s" : "#<Quantity:#{object_id}@%s>" }
447
414
 
448
- Class.new Magnitude() do puts "Creating @Unit class!" if SY::DEBUG
449
- include SY::Unit; puts "Included SY::Unit" if SY::DEBUG
415
+ Class.new Magnitude() do
416
+ include SY::Unit
450
417
 
451
418
  singleton_class.class_exec do
452
419
  define_method :standard do |**nn| # Customized #standard.
453
- puts "parametrized #{qnt}@Unit#standard called" if SY::DEBUG
454
420
  @standard ||= new **nn.update( of: qnt )
455
421
  end
456
422
 
@@ -462,20 +428,15 @@ class SY::Quantity
462
428
  unit_parametrized_subclass.namespace = SY::Unit
463
429
  end
464
430
  end ).tap do |u|
465
- puts "@Unit constructed, its namespace is #{u.namespace}" if SY::DEBUG
466
- puts "its instances are #{u.namespace.instances}" if SY::DEBUG
467
- puts "its instance names are #{u.namespace.instance_names}" if SY::DEBUG
468
431
  end
469
432
  end
470
433
 
471
434
  private
472
435
 
473
436
  def construct_colleague
474
- puts "#{self}#construct_colleague" if SY::DEBUG
475
437
  ɴ = name
476
438
  ʀsuffix = SY::Quantity::RELATIVE_QUANTITY_NAME_SUFFIX
477
439
  rel = relative?
478
- puts "#{self} is #{rel ? 'relative' : 'absolute'}" if SY::DEBUG
479
440
  # Here, it is impossible to rely on Composition::QUANTITY_TABLE –
480
441
  # on the contrary, the table relies on Quantity#colleague.
481
442
  constr_ɴ = ->( ɴ, ʀ ) { ç.new composition: composition, ɴ: ɴ, relative: ʀ }
@@ -7,31 +7,20 @@ module SY::SignedMagnitude
7
7
  # :amount argument. Amount is allowed to be negative.
8
8
  #
9
9
  def initialize( of: nil, amount: nil )
10
- puts "Constructing AbsoluteMagnitude of #{of}, amount: #{amount}" if SY::DEBUG
11
10
  fail ArgumentError, "Quantity (:of) argument missing!" if of.nil?
12
11
  @quantity = of
13
12
  @amount = case amount
14
- when Numeric then
15
- puts "This amount is a Numeric, using it directly" if SY::DEBUG
16
- amount
17
- when nil then
18
- puts "This amount is 'nil', using 1 instead" if SY::DEBUG
19
- 1
13
+ when Numeric then amount
14
+ when nil then 1
20
15
  else
21
16
  begin
22
- puts "Amount #{amount} will be reframed to #{@quantity}" if SY::DEBUG
23
17
  amount.( @quantity ).amount
24
- rescue NameError, NoMethodError
25
- puts "fail, amount #{amount} will be used directly" if SY::DEBUG
26
- amount
27
- end
18
+ rescue NameError, NoMethodError; amount end
28
19
  end
29
20
  end
30
21
 
31
22
  # Addition.
32
23
  #
33
- # TODO: Figure out which module comes on the top in Quantity@Magnitude, whether Magnitude
34
- # or SignedMagnitude, and therefore, whether it is necessary to adjust this method.
35
24
  def + m2
36
25
  return magnitude( amount + m2.amount ) if quantity == m2.quantity
37
26
  return quantity.absolute.magnitude( amount + m2.amount ) if
@@ -42,7 +31,6 @@ module SY::SignedMagnitude
42
31
 
43
32
  # Subtraction.
44
33
  #
45
- # TODO: ditto
46
34
  def - m2
47
35
  return magnitude( amount - m2.amount ) if m2.quantity == quantity.relative
48
36
  return quantity.relative.magnitude( amount - m2.amount ) if
@@ -46,16 +46,12 @@ module SY::Unit
46
46
  w = SY::ExpressibleInUnits::COLLISION_WARNING
47
47
  SY::ExpressibleInUnits.included_in.each do |modul|
48
48
  im = modul.instance_methods
49
- # puts ɱ, "class: #{ɱ.class}"
50
- # puts im.size
51
- # puts down
52
- # puts im.include? down
53
49
  warn w % [down, modul] if im.include? down
54
50
  abbrev = new_instance.abbreviation
55
51
  warn w % [abbrev, modul] if im.include? abbrev
56
52
  end
57
53
  end
58
- up.to_sym.tap { |sym| puts "name_set_hook #{sym}" if SY::DEBUG }
54
+ up.to_sym
59
55
  end
60
56
 
61
57
  # We'll now define all the prefix methods on the target (#mili, #mega...),
@@ -94,7 +90,6 @@ module SY::Unit
94
90
  # special meaning of setting the relationship of that quantity.
95
91
  #
96
92
  def standard( of: nil, **nn )
97
- puts "Constructing a standard unit of #{of}." if SY::DEBUG
98
93
  fail ArgumentError, ":of argument missing!" if of.nil?
99
94
  qnt = SY::Quantity.instance( of )
100
95
  nn.empty? ? qnt.standard_unit : qnt.new_standard_unit( **nn )
@@ -110,7 +105,7 @@ module SY::Unit
110
105
  # Full list of known unit names and unit abbreviations.
111
106
  #
112
107
  def known_symbols
113
- instance_names.map( &:downcase ) + abbreviations.keys
108
+ instances.names( false ).map( &:downcase ) + abbreviations.keys
114
109
  end
115
110
 
116
111
  # Parses an SPS, curring it with known unit names and abbreviations,
@@ -156,13 +151,6 @@ module SY::Unit
156
151
  def initialize( short: nil, warns: true, **nn )
157
152
  @abbreviation = short.to_sym if short
158
153
  @warns = warns # does this unit care about blatant name collisions?
159
-
160
- # FIXME: Here, we would have to watch out for :amount being set
161
- # if it is a number, amount is in standard units
162
- # however, if it is a magnitude, especially one of another equidimensional quantity,
163
- # it estableshes a relationship between this and that quantity. It means that
164
- # the unit amount automatically becomes ... one ... and such relationship can
165
- # only be established for standard quantity
166
154
  super nn
167
155
  end
168
156
 
@@ -269,7 +257,5 @@ module SY::Unit
269
257
 
270
258
  # String describing this class.
271
259
  #
272
- def çς
273
- "Unit"
274
- end
260
+ def çς; "Unit" end
275
261
  end # class SY::Unit
@@ -1,7 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module SY
4
- VERSION = "2.1.2"
5
- DEBUG = false # debug mode switch - sometimes there are lines like
6
- # puts "something" if SY::DEBUG
4
+ VERSION = "2.1.4"
7
5
  end
@@ -1,21 +1,21 @@
1
1
  #! /usr/bin/ruby
2
2
  # encoding: utf-8
3
3
 
4
- # **************************************************************************
4
+ # *****************************************************************
5
5
  # THIS IS SPEC-STYLE TEST FILE FOR SY PHYSICAL UNITS LIBRARY
6
- # **************************************************************************
6
+ # *****************************************************************
7
7
 
8
8
  # The following will load Ruby spec-style library
9
9
  require 'mathn'
10
10
  require 'minitest/autorun'
11
11
 
12
12
  # The following will load SY library
13
- require 'sy'
14
- # require './../lib/sy'
13
+ # require 'sy'
14
+ require './../lib/sy'
15
15
 
16
- # **************************************************************************
16
+ # *****************************************************************
17
17
  # THE SPECIFICATIONS START HERE
18
- # **************************************************************************
18
+ # *****************************************************************
19
19
 
20
20
  describe SY do
21
21
  it "should have basic assets" do
@@ -253,7 +253,7 @@ describe SY::Quantity, SY::Magnitude do
253
253
  1.mm.to_s.must_equal "0.001.m"
254
254
  1.mm.inspect.must_equal "#<±Magnitude: 0.001.m >"
255
255
  1.µs.inspect.must_equal "#<±Magnitude: 1e-06.s >"
256
-
256
+
257
257
  SY::Area.dimension.must_equal SY.Dimension( :L² )
258
258
  SY::Area.composition.must_equal SY::Composition[ SY::Length => 2 ]
259
259
 
@@ -298,7 +298,7 @@ describe SY::Quantity, SY::Magnitude do
298
298
 
299
299
  q1.relative?.must_equal true
300
300
  q2.relative?.must_equal true
301
-
301
+
302
302
  q1.object_id.must_equal q2.object_id
303
303
  ( 1.s⁻¹ ).quantity.object_id.must_equal ( 1 / 1.s ).quantity.object_id
304
304
  ( 1 / 1.s ).must_equal 1.s⁻¹
@@ -312,9 +312,10 @@ describe SY::Quantity, SY::Magnitude do
312
312
  rescue
313
313
  end
314
314
  end.must_include :M
315
- SY::Unit.instance_names.must_include :MOLE
315
+ SY::Unit.instances.names( false ).must_include :MOLE
316
316
  # Avogadro's number is defined directly in SY
317
- 1.mol.quantity.object_id.must_equal SY::Nᴀ.unit.( SY::MoleAmount ).quantity.object_id
317
+ 1.mol.quantity.object_id
318
+ .must_equal SY::Nᴀ.unit.( SY::MoleAmount ).quantity.object_id
318
319
  SY::Nᴀ.unit.( SY::MoleAmount ).must_equal 1.mol
319
320
  0.7.mol.l⁻¹.amount.must_equal 0.7
320
321
  1.M.must_equal 1.mol.l⁻¹.( SY::Molarity )
@@ -325,7 +326,6 @@ describe SY::Quantity, SY::Magnitude do
325
326
  # Avogadro's number is defined directly in SY
326
327
  1.mol.must_equal SY::Nᴀ.unit.( SY::MoleAmount )
327
328
 
328
-
329
329
  0.7.M.must_equal 0.7.mol.l⁻¹.( SY::Molarity )
330
330
  # (if #is_actually! conversion method is not used, current
331
331
  # implementation will refuse to compare different quantities,
@@ -353,10 +353,17 @@ describe SY::Quantity, SY::Magnitude do
353
353
  # watt
354
354
  ( 1.V * 1.A ).( SY::Power ).must_be_within_epsilon 1.W, 1e-9
355
355
 
356
- # pretty representation
357
- ( 1.m / 3.s ).to_s.must_equal( "0.333.m.s⁻¹" )
358
- ( 1.m / 7.01e7.s ).to_s.must_equal( "1.43e-08.m.s⁻¹" )
356
+ # Custom unit creation
357
+ XOXO = SY::Unit.of SY::Volume, amount: 1.l
358
+ assert_equal 1.l.( SY::Volume ), 1.xoxo.( SY::Volume )
359
359
 
360
+ # TRIPLE_POINT_OF_WATER
361
+ assert_equal SY::TRIPLE_POINT_OF_WATER, 0.°C.( SY::Temperature )
362
+ assert_equal 273.15, 0.°C.in( :K )
363
+ assert_equal SY::Unit.instance( :SECOND ), SY::Unit.instance( :second )
364
+ assert_equal SY::TRIPLE_POINT_OF_WATER, 0.°C # coercion behavior
365
+
366
+ # other tests
360
367
  assert_equal 1.m, 1.s * 1.m.s⁻¹
361
368
  assert_equal 1.µM.s⁻¹, 1.µM / 1.s
362
369
  assert_equal 1.m.s⁻¹, 1.m.s( -1 )
@@ -367,64 +374,39 @@ describe SY::Quantity, SY::Magnitude do
367
374
  assert_equal SY::Amount( 1 ), 1.µM / ( 1.µM + 0.µM )
368
375
  assert_equal 1.µM, 1.µM * 1.µM / ( 1.µM + 0.µM )
369
376
  assert_in_epsilon 1.µM, 1.µmol / 1.dm( 3 ).( SY::LitreVolume )
370
-
377
+
371
378
  assert_equal SY::Molarity.relative, 1.mol.l⁻¹.quantity
372
379
  assert_equal SY::MoleAmount.relative, 1.M.l.quantity
373
380
 
381
+
374
382
  assert_equal 1 / SY::Time, 1 / SY::Time
375
383
  assert_equal 1 / SY::Time.relative, 1 / SY::Time
376
384
  assert_equal ( 1 / SY::Time.relative ), 1.mol.s⁻¹.( 1 / SY::Time ).quantity
377
385
  assert_equal ( 1 / SY::Time ).object_id,
378
- ( 1.0.µmol.min⁻¹.mg⁻¹ * 100.kDa ).( 1 / SY::Time ).quantity.object_id
386
+ ( 1.0.µmol.min⁻¹.mg⁻¹ * 100.kDa ).( 1 / SY::Time ).quantity.object_id
379
387
  assert_equal SY::Time.magnitude( 1 ), SY::SECOND
380
- assert_equal Matrix[[60.mM], [60.mM]], Matrix[[1e-03.s⁻¹.M], [1e-3.s⁻¹.M]] * 60.s
388
+ end
389
+
390
+ describe "pretty representation" do
391
+ it "should" do
392
+ ( 1.0.m / 3.s ).to_s.must_be_kind_of String
393
+ ( 1.0.m / 3.s ).to_s.must_equal "0.333.m.s⁻¹"
394
+
395
+ ( 1.m / 7.01e7.s ).to_s.must_equal( "1.43e-08.m.s⁻¹" )
396
+ end
397
+ end
398
+
399
+ describe "matrix integration" do
400
+ it "should" do
401
+ assert_equal Matrix[[60.mM], [60.mM]], Matrix[[1e-03.s⁻¹.M], [1e-3.s⁻¹.M]] * 60.s
381
402
 
382
- assert_equal Matrix[[5.m]], Matrix[[1.m.s⁻¹, 2.m.s⁻¹]] * Matrix.column_vector( [1.s, 2.s] )
383
- assert_equal Matrix[[2.m, 3.m], [4.m, 5.m]],
384
- Matrix[[1.m, 2.m], [3.m, 4.m]] + Matrix[[1.m, 1.m], [1.m, 1.m]]
385
- assert_equal Matrix[[5.µM]], Matrix[[1.µM]] + Matrix[[2.µM.s⁻¹]] * Matrix[[2.s]]
386
- assert_equal Matrix[[1.s]], Matrix[[1]] * 1.s
387
- assert_equal Matrix[[1.s]], 1.s * Matrix[[1]]
388
- XOXO = SY::Unit.of SY::Volume, amount: 1.l
389
- assert_equal 1.l.( SY::Volume ), 1.xoxo.( SY::Volume )
390
- assert_equal SY::TRIPLE_POINT_OF_WATER, 0.°C.( SY::Temperature )
391
- assert_equal 273.15, 0.°C.in( :K )
392
- assert_equal SY::Unit.instance( :SECOND ), SY::Unit.instance( :second )
393
- assert_equal SY::TRIPLE_POINT_OF_WATER, 0.°C # coercion behavior
394
- assert 2.°C.eql?( 1.°C + 1.K )
395
- assert ( 1.°C - 1.°C ).eql?( 0.K )
396
- assert_equal :raised, begin
397
- 1.°C + 1.°C
398
- :nothing_raised
399
- rescue QuantityError
400
- :raised
401
- end
402
- assert_equal :raised, begin
403
- 1.K + 1.°C
404
- :nothing_raised
405
- rescue QuantityError
406
- :raised
407
- end
408
- assert_equal :raised, begin
409
- 1.K - 1.°C
410
- :nothing_raised
411
- rescue QuantityError
412
- :raised
413
- end
414
- assert 1.mm.K⁻¹.eql?( 1.mm.°C⁻¹ )
415
- assert 1.mm.K.eql?( 1.mm.°C )
416
- assert_equal :raised, begin
417
- 1.mm / 1.°C
418
- :nothing_raised
419
- rescue QuantityError
420
- :raised
421
- end
422
- assert_equal :raised, begin
423
- 1.mm * 1.°C
424
- :nothing_raised
425
- rescue QuantityError
426
- :raised
427
- end
403
+ assert_equal Matrix[[5.m]], Matrix[[1.m.s⁻¹, 2.m.s⁻¹]] * Matrix.column_vector( [1.s, 2.s] )
404
+ assert_equal Matrix[[2.m, 3.m], [4.m, 5.m]],
405
+ Matrix[[1.m, 2.m], [3.m, 4.m]] + Matrix[[1.m, 1.m], [1.m, 1.m]]
406
+ assert_equal Matrix[[5.µM]], Matrix[[1.µM]] + Matrix[[2.µM.s⁻¹]] * Matrix[[2.s]]
407
+ assert_equal Matrix[[1.s]], Matrix[[1]] * 1.s
408
+ assert_equal Matrix[[1.s]], 1.s * Matrix[[1]]
409
+ end
428
410
  end
429
411
  end
430
412
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boris Stitnicky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-20 00:00:00.000000000 Z
11
+ date: 2016-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler