sy 2.0.2 → 2.0.4

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.
@@ -3,12 +3,12 @@
3
3
  # Qualities specific to relative magnitudes.
4
4
  #
5
5
  module SY::SignedMagnitude
6
- # Relative magnitude constructor takes :quantity (alias :of) named argument,
7
- # and :amount named argument, where :amount is allowed to be negative.
6
+ # Relative magnitude constructor takes :quantity (alias :of) argument and
7
+ # :amount argument. Amount is allowed to be negative.
8
8
  #
9
- def initialize args={}
10
- @quantity = args[:quantity] || args[:of]
11
- amnt = args[:amount]
9
+ def initialize **named_args
10
+ @quantity = named_args[:quantity] || named_args[:of]
11
+ amnt = named_args[:amount]
12
12
  @amount = case amnt
13
13
  when Numeric then amnt
14
14
  when nil then 1
data/lib/sy/unit.rb CHANGED
@@ -6,16 +6,15 @@
6
6
  module SY::Unit
7
7
  def self.pre_included target
8
8
  class << target
9
- # Overriding this method from NameMagic mixin makes sure that all Unit
10
- # subclasses have the same namespace in Unit class, rather then each
11
- # parametrized subclass its own.
9
+ # Overriding this method from NameMagic mixin ensures, that all Unit
10
+ # subclasses use common namespace (Unit), rather than each their own.
12
11
  #
13
12
  def namespace
14
13
  SY::Unit
15
14
  end
16
15
 
17
- # Tweaking instance accessor from NameMagic, to make it accept unit
18
- # abbreviations, and unit names regardless of capitalization
16
+ # Tweaking instance accessor from NameMagic to make it accept unit
17
+ # abbreviations and unit names regardless of capitalization
19
18
  #
20
19
  def instance arg
21
20
  begin
@@ -101,14 +100,11 @@ module SY::Unit
101
100
  # specified quantity. Note that :amount for standard units, if supplied, has
102
101
  # special meaning of setting the relationship of that quantity.
103
102
  #
104
- def standard args={}
105
- args.must_have :quantity, syn!: :of
106
- qnt = SY::Quantity.instance( args.delete :quantity )
107
- if args.empty? then
108
- qnt.standard_unit
109
- else
110
- qnt.new_standard_unit( args )
111
- end
103
+ def standard( of: nil, **nn )
104
+ puts "Constructing a standard unit of #{of}." if SY::DEBUG
105
+ fail ArgumentError, ":of argument missing!" if of.nil?
106
+ qnt = SY::Quantity.instance( of )
107
+ nn.empty? ? qnt.standard_unit : qnt.new_standard_unit( **nn )
112
108
  end
113
109
 
114
110
  # Unit abbreviations as a hash of abbreviation => unit pairs.
@@ -165,10 +161,8 @@ module SY::Unit
165
161
  # ambiguity with regard to standard prefixes and abbreviations thereof should
166
162
  # also be avoided.
167
163
  #
168
- def initialize args={}
169
- if args.has? :abbreviation, syn!: :short then
170
- @abbreviation = args.delete( :abbreviation ).to_sym
171
- end
164
+ def initialize( short: nil, **nn )
165
+ @abbreviation = short.to_sym if short
172
166
 
173
167
  # FIXME: Here, we would have to watch out for :amount being set
174
168
  # if it is a number, amount is in standard units
@@ -176,7 +170,7 @@ module SY::Unit
176
170
  # it estableshes a relationship between this and that quantity. It means that
177
171
  # the unit amount automatically becomes ... one ... and such relationship can
178
172
  # only be established for standard quantity
179
- super args
173
+ super( **nn )
180
174
  end
181
175
 
182
176
  # Addition: Unit is converted to a magnitude before the operation.
data/lib/sy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module SY
2
- VERSION = "2.0.2"
2
+ VERSION = "2.0.4"
3
3
  DEBUG = false # debug mode switch - sometimes there are lines like
4
4
  # puts "something" if SY::DEBUG
5
5
  end
data/test/sy_test.rb CHANGED
@@ -65,17 +65,17 @@ describe SY::Dimension do
65
65
  end
66
66
  end
67
67
 
68
- describe SY::Mapping do
68
+ describe SY::Measure do
69
69
  it "should" do
70
- i = SY::Mapping.identity
71
- a, b = SY::Mapping.new( 2 ), SY::Mapping.new( 3 )
70
+ i = SY::Measure.identity
71
+ a, b = SY::Measure.new( ratio: 2 ), SY::Measure.new( ratio: 3 )
72
72
  assert_equal 1, i.ratio
73
- assert_equal 4, a.im.( 8 )
74
- assert_equal 3, b.ex.( 1 )
75
- assert_equal 6, (a * b).ex.( 1 )
76
- assert_equal 2, (a * b / b).ex.( 1 )
77
- assert_equal 4, (a ** 2).ex.( 1 )
78
- assert_equal 2, a.inverse.im.( 1 )
73
+ assert_equal 4, a.r.( 8 )
74
+ assert_equal 3, b.w.( 1 )
75
+ assert_equal 6, (a * b).w.( 1 )
76
+ assert_equal 2, (a * b / b).w.( 1 )
77
+ assert_equal 4, (a ** 2).w.( 1 )
78
+ assert_equal 2, a.inverse.r.( 1 )
79
79
  end
80
80
  end
81
81
 
@@ -98,7 +98,7 @@ describe SY::Composition do
98
98
  SY::Composition[ SY::Amount => 1, SY::Length => 1 ]
99
99
  .to_quantity.dimension )
100
100
  assert_equal SY.Dimension( 'L' ), l.dimension
101
- assert_kind_of SY::Mapping, a.infer_mapping
101
+ assert_kind_of SY::Measure, a.infer_measure
102
102
  end
103
103
  end
104
104
 
@@ -109,7 +109,7 @@ describe SY::Quantity, SY::Magnitude do
109
109
  @amount_in_dozens = begin
110
110
  SY.Quantity( "AmountInDozens" )
111
111
  rescue
112
- SY::Quantity.dimensionless mapping: 12, ɴ: "AmountInDozens"
112
+ SY::Quantity.dimensionless amount: 12, ɴ: "AmountInDozens"
113
113
  end
114
114
  @inch_length = begin
115
115
  SY.Quantity( "InchLength" )
@@ -129,15 +129,15 @@ describe SY::Quantity, SY::Magnitude do
129
129
  @amount_in_dozens.must_be_kind_of SY::Quantity
130
130
  d1 = @amount_in_dozens.magnitude 1
131
131
  a12 = SY::Amount.magnitude 12
132
- mda = @amount_in_dozens.mapping_to SY::Amount
133
- i, e = mda.im, mda.ex
134
- ia = i.( a12.amount )
135
- @amount_in_dozens.magnitude ia
136
- im = @amount_in_dozens.import( a12 )
132
+ mda = @amount_in_dozens.measure of: SY::Amount
133
+ r, w = mda.r, mda.w
134
+ ra = r.( a12.amount )
135
+ @amount_in_dozens.magnitude ra
136
+ ra = @amount_in_dozens.read( a12 )
137
137
  assert_equal @amount_in_dozens.magnitude( 1 ),
138
- @amount_in_dozens.import( SY::Amount.magnitude( 12 ) )
138
+ @amount_in_dozens.read( SY::Amount.magnitude( 12 ) )
139
139
  assert_equal SY::Amount.magnitude( 12 ),
140
- @amount_in_dozens.export( 1, SY::Amount )
140
+ @amount_in_dozens.write( 1, SY::Amount )
141
141
  SY::Length.composition.must_equal SY::Composition.singular( :Length )
142
142
  end
143
143
 
@@ -147,7 +147,7 @@ describe SY::Quantity, SY::Magnitude do
147
147
  @inch = SY::Unit.standard( of: @inch_length, amount: 2.54.cm,
148
148
  ɴ: 'inch', short: '”' )
149
149
  @i1 = @inch_length.magnitude 1
150
- @il_mapping = @inch_length.mapping_to SY::Length
150
+ @il_measure = @inch_length.measure( of: SY::Length )
151
151
  end
152
152
 
153
153
  it "should" do
@@ -155,12 +155,12 @@ describe SY::Quantity, SY::Magnitude do
155
155
  @inch_length.colleague.name.must_equal :InchLength±
156
156
  @m1.to_s.must_equal "1.m"
157
157
  @i1.amount.must_equal 1
158
- assert_kind_of SY::Mapping, @il_mapping
159
- assert_kind_of Numeric, @il_mapping.ratio
160
- assert_in_epsilon 0.0254, @il_mapping.ratio
161
- @il_mapping.ex.( 1 ).must_be_within_epsilon 0.0254
158
+ assert_kind_of SY::Measure, @il_measure
159
+ assert_kind_of Numeric, @il_measure.ratio
160
+ assert_in_epsilon 0.0254, @il_measure.ratio
161
+ @il_measure.w.( 1 ).must_be_within_epsilon 0.0254
162
162
  begin
163
- impossible_mapping = @inch_length.mapping_to SY::Amount
163
+ impossible_mapping = @inch_length.measure( of: SY::Amount )
164
164
  rescue SY::DimensionError
165
165
  :dimension_error
166
166
  end.must_equal :dimension_error
@@ -172,214 +172,214 @@ describe SY::Quantity, SY::Magnitude do
172
172
  1.inch.in( :mm ).must_equal 25.4
173
173
  end
174
174
  end
175
- end
176
-
177
- describe "expected behavior" do
178
- it "should" do
179
- # Length quantity and typical units
180
- SY::METRE.must_be_kind_of SY::Unit
181
- SY::METRE.absolute?.must_equal true
182
- 1.metre.absolute.must_equal SY::METRE
183
- assert 1.metre.absolute != 1.metre.relative
184
- 1.metre.relative.relative?.must_equal true
185
-
186
-
187
- SY::METRE.relative.must_equal 1.metre
188
- 1.m.must_equal 1.metre
189
- 1.m.must_equal 1000.mm
190
- SY::METRE.quantity.name.must_equal :Length
191
- assert_in_delta 0.9.µm, 900.nm, 1e-6.nm
192
- [ 1.m, 1.m ].min.must_equal 1.m
193
- 1.m + 1.m == 1.m
194
- assert_in_epsilon 1.m, 1.m, 0.1
195
- 600.m.must_equal 0.6.km
196
- SY::METRE.quantity.must_equal SY::Length
197
- SY::Length.dimension.must_equal SY.Dimension( :L )
198
- SY.Dimension( :L ).standard_quantity.must_equal SY::Length
199
- SY::Length.standard_unit.must_equal SY::METRE
200
- SY::METRE.amount.must_equal 1
201
- SY::METRE.mili.amount.must_equal 0.001
202
- 3.km.in( :dm ).must_equal 30_000
203
- ( 1.m + 20.cm ).must_equal 1_200.mm
204
- assert 1.mm.object_id != 1.mm.object_id
205
- assert 1.mm == 1.mm
206
- assert 1.01.m != 1.m
207
- assert_equal 1, 1.01.m <=> 1.m
208
- assert_equal 0, 1.00.m <=> 1.m
209
- assert_equal -1, 0.99.m <=> 1.m
210
- assert 0.9.mm < 1.mm
211
- assert 1.1.mm > 1.09.mm
212
- assert ( 0.1.m - ( 1.m - 0.9.m ) ).abs < 1.nm.abs
213
- # Mass quantity and typical units
214
- SY::KILOGRAM.must_be_kind_of SY::Unit
215
- SY::GRAM.must_be_kind_of SY::Unit
216
- assert SY::Mass.standard_unit.equal?( SY::KILOGRAM )
217
- 1.kilogram.must_be_kind_of SY::Magnitude
218
- 1.gram.must_be_kind_of SY::Magnitude
219
- 1.kilogram.absolute.quantity.must_equal SY::Mass
220
- 1.gram.absolute.quantity.must_equal SY::Mass
221
- ( SY::KILOGRAM * 1 ).must_equal SY::GRAM * 1000
222
- 1.kilogram.must_equal 1000.g
223
- 1.kg.to_f.must_equal 1
224
- 1.g.to_f.must_equal 0.001
225
- 1.miligram.must_equal 0.001.g
226
- 1.mg.must_equal 1.miligram
227
- 1.µg.must_equal 0.001.miligram
228
- 1.ng.must_equal 0.001.microgram
229
- 1.pg.quantity.must_equal 0.001.nanogram.quantity
230
- 1.pg.amount.must_be_within_epsilon 0.001.nanogram.amount, 1e-6
231
- assert_equal 1.g, [1.g, 2.g].min
232
- assert_equal 1.mg, 1.g * 0.001
233
- 1.pg.abs.must_be_within_epsilon 0.001.nanogram.abs, 1e-6
234
- SY::TON.must_be_kind_of SY::Unit
235
- 1.ton.must_equal 1000.kg
236
- 1.t.must_equal 1.ton
237
- 1.kt.must_equal 1000.ton
238
- 1.Mt.must_equal 1000.kiloton
239
- 1.mm.quantity.name.must_equal :Length±
240
- SY::Length.standard_unit.must_equal SY::METRE
241
- SY::Length.standard_unit.name.must_equal :metre
242
- SY::Length.standard_unit.must_equal SY::METRE
243
- SY.Quantity( :Length ).object_id.must_equal SY::Length.object_id
244
- SY::Length.relative.object_id.must_equal SY.Quantity( :Length± ).object_id
245
- SY.Quantity( :Length± ).colleague.name.must_equal :Length
246
- SY.Quantity( :Length± ).colleague.class.must_equal SY::Quantity
247
- SY.Quantity( :Length± ).colleague.object_id.must_equal SY::Length.object_id
248
- SY.Quantity( :Length± ).send( :Unit ).object_id
249
- .must_equal SY::Length.send( :Unit ).object_id
250
- 1.mm.quantity.standard_unit.name.must_equal :metre
251
- 1.mm.to_s.must_equal "0.001.m"
252
- 1.mm.inspect.must_equal "#<±Magnitude: 0.001.m >"
253
- 1.µs.inspect.must_equal "#<±Magnitude: 1e-06.s >"
254
-
255
- SY::Area.dimension.must_equal SY.Dimension( :L² )
256
- SY::Area.composition.must_equal SY::Composition[ SY::Length => 2 ]
257
-
258
- SY::AMPERE.name.must_equal :ampere
259
- SY::AMPERE.abbreviation.must_equal :A
260
- SY::AMPERE.dimension.must_equal 1.A.dimension
261
- SY.Magnitude( of: SY::ElectricCurrent, amount: 1 ).must_equal 1.A.absolute
262
- 1.A.quantity.must_equal SY::ElectricCurrent.relative
263
- 1.A.quantity.standard_unit.name.must_equal :ampere
264
- 1.A.to_s( SY::AMPERE ).must_equal "1.A"
265
- 1.A.to_s.must_equal "1.A"
266
- 1.A.amount.must_equal 1
267
- 1.A.quantity.standard_unit.abbreviation.must_equal :A
268
- 1.A.inspect.must_equal "#<±Magnitude: 1.A >"
269
-
270
- 1.l⁻¹.reframe( SY::Molarity ).quantity.must_equal SY::Molarity
271
- x = ( SY::Nᴀ / SY::LITRE )
272
- x = x.reframe( SY::Molarity )
273
- y = 1.molar.absolute
274
- y.quantity.must_equal x.quantity
275
- y.amount.must_equal y.amount
276
- SY::MoleAmount.protected?.must_equal true
277
- SY::LitreVolume.protected?.must_equal true
278
- SY::MOLAR.quantity.name.must_equal :Molarity
279
- m = 1.µM
280
- 1.µM.quantity.relative?.must_equal true
281
- 1.µM.quantity.name.must_equal :Molarity±
282
- 1.µM.quantity.absolute.name.must_equal :Molarity
283
- 7.µM.must_be_within_epsilon 5.µM + 2.µM, 1e-6
284
- +1.s.must_equal 1.s
285
- # -1.s.must_equal -1 * 1.s # must raise
286
- assert_equal -(-(1.s)), +(1.s)
287
- 1.s⁻¹.quantity.must_equal ( 1.s ** -1 ).quantity
288
- 1.s⁻¹.quantity.must_equal ( 1 / 1.s ).quantity
289
- 1.s⁻¹.amount.must_equal ( 1.s ** -1 ).amount
290
- 1.s⁻¹.must_equal 1.s ** -1
291
- q1 = ( 1.s⁻¹ ).quantity
292
- q1.composition.to_hash.must_equal( { SY::Time => -1 } )
293
-
294
- q2 = ( 1 / 1.s ).quantity
295
- q2.composition.to_hash.must_equal( { SY::Time => -1 } )
296
-
297
- q1.relative?.must_equal true
298
- q2.relative?.must_equal true
299
-
300
- q1.object_id.must_equal q2.object_id
301
- ( 1.s⁻¹ ).quantity.object_id.must_equal ( 1 / 1.s ).quantity.object_id
302
- ( 1 / 1.s ).must_equal 1.s⁻¹
303
- 1.s⁻¹.( SY::Frequency ).must_equal 1.Hz
304
- # 7.°C.must_equal( 8.°C - 1.K )
305
- # (-15).°C.must_equal 258.15.K
306
- # 7000.µM.must_be_within_epsilon( 7.mM, 1e-9 )
307
- ::SY::Unit.instances.map do |i|
308
- begin
309
- i.abbreviation
310
- rescue
311
- end
312
- end.must_include :M
313
- SY::Unit.instance_names.must_include :mole
314
- # Avogadro's number is defined directly in SY
315
- 1.mol.quantity.object_id.must_equal SY::Nᴀ.( SY::MoleAmount ).quantity.object_id
316
- SY::Nᴀ.( SY::MoleAmount ).must_equal 1.mol
317
- 0.7.mol.l⁻¹.amount.must_equal 0.7
318
- 1.M.must_equal 1.mol.l⁻¹.( SY::Molarity )
319
- # (if #reframe conversion method is not used, different quantities
320
- # do not compare. Arithmetics is possible because Magnitude operators
321
- # mostly give their results only in standard quantities.
322
-
323
- # Avogadro's number is defined directly in SY
324
- 1.mol.must_equal SY::Nᴀ.unit.( SY::MoleAmount )
325
-
326
175
 
327
- 0.7.M.must_equal 0.7.mol.l⁻¹.( SY::Molarity )
328
- # (if #is_actually! conversion method is not used, current
329
- # implementation will refuse to compare different quantities,
330
- # even if their dimensions match)
331
-
332
- 30.Hz.must_equal 30.s⁻¹.( SY::Frequency )
333
-
334
- # Dalton * Avogadro must be 1 gram
335
- ( 1.Da * SY::Nᴀ ).must_be_within_epsilon( 1.g, 1e-6 )
336
-
337
- # kilogram
338
- 1.kg.must_equal 1000.g
339
- SY::Speed.dimension.must_equal SY::Dimension( "L.T⁻¹" )
340
- SY::Acceleration.dimension.must_equal SY::Dimension( "L.T⁻²" )
341
- SY::Force.dimension.must_equal SY::Dimension( "L.M.T⁻²" )
342
- ( 1.kg * 1.m.s⁻² ).( SY::Force ).must_be_within_epsilon 1.N, 1e-9
343
-
344
- # joule
345
- ( 1.N * 1.m ).( SY::Energy ).must_equal 1.J
346
- 1e-23.J.K⁻¹.must_equal 1.0e-20.mJ.K⁻¹
347
-
348
-
349
- # pascal
350
- ( 1.N / 1.m ** 2 ).( SY::Pressure ).must_be_within_epsilon 1.Pa, 1e-9
351
-
352
- # watt
353
- ( 1.V * 1.A ).( SY::Power ).must_be_within_epsilon 1.W, 1e-9
354
-
355
- # pretty representation
356
- ( 1.m / 3.s ).to_s.must_equal( "0.333.m.s⁻¹" )
357
- ( 1.m / 7.01e7.s ).to_s.must_equal( "1.43e-08.m.s⁻¹" )
358
-
359
- assert_equal 1.m, 1.s * 1.m.s⁻¹
360
- assert_equal 1.µM.s⁻¹, 1.µM / 1.s
361
- assert_equal 1.m.s⁻¹, 1.m.s( -1 )
362
- assert_equal 2_000.mm.s⁻², 2.m.s( -2 )
363
- assert_equal 3.µM, 1.µM + 2.µM
364
- assert_equal SY::Amount, SY::Molarity / SY::Molarity
365
- assert_equal SY::Amount( 1 ), 1.µM / 1.µM
366
- assert_equal SY::Amount( 1 ), 1.µM / ( 1.µM + 0.µM )
367
- assert_equal 1.µM, 1.µM * 1.µM / ( 1.µM + 0.µM )
368
- assert_in_epsilon 1.µM, 1.µmol / 1.dm( 3 ).( SY::LitreVolume )
369
-
370
- assert_equal SY::Molarity.relative, 1.mol.l⁻¹.quantity
371
-
372
- assert_equal 1 / SY::Time, 1 / SY::Time
373
- assert_equal 1 / SY::Time.relative, 1 / SY::Time
374
- assert_equal ( 1 / SY::Time.relative ), 1.mol.s⁻¹.( 1 / SY::Time ).quantity
375
- assert_equal ( 1 / SY::Time ).object_id,
376
- ( 1.0.µmol.min⁻¹.mg⁻¹ * 100.kDa ).( 1 / SY::Time ).quantity.object_id
377
- assert_equal SY::Time.magnitude( 1 ), SY::SECOND
378
- assert_equal Matrix[[60.mM], [60.mM]], Matrix[[1e-03.s⁻¹.M], [1e-3.s⁻¹.M]] * 60.s
379
-
380
- assert_equal Matrix[[5.m]], Matrix[[1.m.s⁻¹, 2.m.s⁻¹]] * Matrix.column_vector( [1.s, 2.s] )
381
- assert_equal Matrix[[2.m, 3.m], [4.m, 5.m]],
382
- Matrix[[1.m, 2.m], [3.m, 4.m]] + Matrix[[1.m, 1.m], [1.m, 1.m]]
383
- assert_equal Matrix[[5.µM]], Matrix[[1.µM]] + Matrix[[2.µM.s⁻¹]] * Matrix[[2.s]]
176
+ describe "expected behavior" do
177
+ it "should" do
178
+ # Length quantity and typical units
179
+ SY::METRE.must_be_kind_of SY::Unit
180
+ SY::METRE.absolute?.must_equal true
181
+ 1.metre.absolute.must_equal SY::METRE
182
+ assert 1.metre.absolute != 1.metre.relative
183
+ 1.metre.relative.relative?.must_equal true
184
+
185
+
186
+ SY::METRE.relative.must_equal 1.metre
187
+ 1.m.must_equal 1.metre
188
+ 1.m.must_equal 1000.mm
189
+ SY::METRE.quantity.name.must_equal :Length
190
+ assert_in_delta 0.9.µm, 900.nm, 1e-6.nm
191
+ [ 1.m, 1.m ].min.must_equal 1.m
192
+ 1.m + 1.m == 1.m
193
+ assert_in_epsilon 1.m, 1.m, 0.1
194
+ 600.m.must_equal 0.6.km
195
+ SY::METRE.quantity.must_equal SY::Length
196
+ SY::Length.dimension.must_equal SY.Dimension( :L )
197
+ SY.Dimension( :L ).standard_quantity.must_equal SY::Length
198
+ SY::Length.standard_unit.must_equal SY::METRE
199
+ SY::METRE.amount.must_equal 1
200
+ SY::METRE.mili.amount.must_equal 0.001
201
+ 3.km.in( :dm ).must_equal 30_000
202
+ ( 1.m + 20.cm ).must_equal 1_200.mm
203
+ assert 1.mm.object_id != 1.mm.object_id
204
+ assert 1.mm == 1.mm
205
+ assert 1.01.m != 1.m
206
+ assert_equal 1, 1.01.m <=> 1.m
207
+ assert_equal 0, 1.00.m <=> 1.m
208
+ assert_equal -1, 0.99.m <=> 1.m
209
+ assert 0.9.mm < 1.mm
210
+ assert 1.1.mm > 1.09.mm
211
+ assert ( 0.1.m - ( 1.m - 0.9.m ) ).abs < 1.nm.abs
212
+ # Mass quantity and typical units
213
+ SY::KILOGRAM.must_be_kind_of SY::Unit
214
+ SY::GRAM.must_be_kind_of SY::Unit
215
+ assert SY::Mass.standard_unit.equal?( SY::KILOGRAM )
216
+ 1.kilogram.must_be_kind_of SY::Magnitude
217
+ 1.gram.must_be_kind_of SY::Magnitude
218
+ 1.kilogram.absolute.quantity.must_equal SY::Mass
219
+ 1.gram.absolute.quantity.must_equal SY::Mass
220
+ ( SY::KILOGRAM * 1 ).must_equal SY::GRAM * 1000
221
+ 1.kilogram.must_equal 1000.g
222
+ 1.kg.to_f.must_equal 1
223
+ 1.g.to_f.must_equal 0.001
224
+ 1.miligram.must_equal 0.001.g
225
+ 1.mg.must_equal 1.miligram
226
+ 1.µg.must_equal 0.001.miligram
227
+ 1.ng.must_equal 0.001.microgram
228
+ 1.pg.quantity.must_equal 0.001.nanogram.quantity
229
+ 1.pg.amount.must_be_within_epsilon 0.001.nanogram.amount, 1e-6
230
+ assert_equal 1.g, [1.g, 2.g].min
231
+ assert_equal 1.mg, 1.g * 0.001
232
+ 1.pg.abs.must_be_within_epsilon 0.001.nanogram.abs, 1e-6
233
+ SY::TON.must_be_kind_of SY::Unit
234
+ 1.ton.must_equal 1000.kg
235
+ 1.t.must_equal 1.ton
236
+ 1.kt.must_equal 1000.ton
237
+ 1.Mt.must_equal 1000.kiloton
238
+ 1.mm.quantity.name.must_equal :Length±
239
+ SY::Length.standard_unit.must_equal SY::METRE
240
+ SY::Length.standard_unit.name.must_equal :metre
241
+ SY::Length.standard_unit.must_equal SY::METRE
242
+ SY.Quantity( :Length ).object_id.must_equal SY::Length.object_id
243
+ SY::Length.relative.object_id.must_equal SY.Quantity( :Length± ).object_id
244
+ SY.Quantity( :Length± ).colleague.name.must_equal :Length
245
+ SY.Quantity( :Length± ).colleague.class.must_equal SY::Quantity
246
+ SY.Quantity( :Length± ).colleague.object_id.must_equal SY::Length.object_id
247
+ SY.Quantity( :Length± ).send( :Unit ).object_id
248
+ .must_equal SY::Length.send( :Unit ).object_id
249
+ 1.mm.quantity.standard_unit.name.must_equal :metre
250
+ 1.mm.to_s.must_equal "0.001.m"
251
+ 1.mm.inspect.must_equal "#<±Magnitude: 0.001.m >"
252
+ 1.µs.inspect.must_equal "#<±Magnitude: 1e-06.s >"
253
+
254
+ SY::Area.dimension.must_equal SY.Dimension( :L² )
255
+ SY::Area.composition.must_equal SY::Composition[ SY::Length => 2 ]
256
+
257
+ SY::AMPERE.name.must_equal :ampere
258
+ SY::AMPERE.abbreviation.must_equal :A
259
+ SY::AMPERE.dimension.must_equal 1.A.dimension
260
+ SY.Magnitude( of: SY::ElectricCurrent, amount: 1 ).must_equal 1.A.absolute
261
+ 1.A.quantity.must_equal SY::ElectricCurrent.relative
262
+ 1.A.quantity.standard_unit.name.must_equal :ampere
263
+ 1.A.to_s( SY::AMPERE ).must_equal "1.A"
264
+ 1.A.to_s.must_equal "1.A"
265
+ 1.A.amount.must_equal 1
266
+ 1.A.quantity.standard_unit.abbreviation.must_equal :A
267
+ 1.A.inspect.must_equal "#<±Magnitude: 1.A >"
268
+
269
+ 1.l⁻¹.reframe( SY::Molarity ).quantity.must_equal SY::Molarity
270
+ x = ( SY::Nᴀ / SY::LITRE )
271
+ x = x.reframe( SY::Molarity )
272
+ y = 1.molar.absolute
273
+ y.quantity.must_equal x.quantity
274
+ y.amount.must_equal y.amount
275
+ SY::MoleAmount.protected?.must_equal true
276
+ SY::LitreVolume.protected?.must_equal true
277
+ SY::MOLAR.quantity.name.must_equal :Molarity
278
+ m = 1.µM
279
+ 1.µM.quantity.relative?.must_equal true
280
+ 1.µM.quantity.name.must_equal :Molarity±
281
+ 1.µM.quantity.absolute.name.must_equal :Molarity
282
+ 7.µM.must_be_within_epsilon 5.µM + 2.µM, 1e-6
283
+ +1.s.must_equal 1.s
284
+ # -1.s.must_equal -1 * 1.s # must raise
285
+ assert_equal -(-(1.s)), +(1.s)
286
+ 1.s⁻¹.quantity.must_equal ( 1.s ** -1 ).quantity
287
+ 1.s⁻¹.quantity.must_equal ( 1 / 1.s ).quantity
288
+ 1.s⁻¹.amount.must_equal ( 1.s ** -1 ).amount
289
+ 1.s⁻¹.must_equal 1.s ** -1
290
+ q1 = ( 1.s⁻¹ ).quantity
291
+ q1.composition.to_hash.must_equal( { SY::Time => -1 } )
292
+
293
+ q2 = ( 1 / 1.s ).quantity
294
+ q2.composition.to_hash.must_equal( { SY::Time => -1 } )
295
+
296
+ q1.relative?.must_equal true
297
+ q2.relative?.must_equal true
298
+
299
+ q1.object_id.must_equal q2.object_id
300
+ ( 1.s⁻¹ ).quantity.object_id.must_equal ( 1 / 1.s ).quantity.object_id
301
+ ( 1 / 1.s ).must_equal 1.s⁻¹
302
+ 1.s⁻¹.( SY::Frequency ).must_equal 1.Hz
303
+ # 7.°C.must_equal( 8.°C - 1.K )
304
+ # (-15).°C.must_equal 258.15.K
305
+ # 7000.µM.must_be_within_epsilon( 7.mM, 1e-9 )
306
+ ::SY::Unit.instances.map do |i|
307
+ begin
308
+ i.abbreviation
309
+ rescue
310
+ end
311
+ end.must_include :M
312
+ SY::Unit.instance_names.must_include :mole
313
+ # Avogadro's number is defined directly in SY
314
+ 1.mol.quantity.object_id.must_equal SY::Nᴀ.( SY::MoleAmount ).quantity.object_id
315
+ SY::Nᴀ.( SY::MoleAmount ).must_equal 1.mol
316
+ 0.7.mol.l⁻¹.amount.must_equal 0.7
317
+ 1.M.must_equal 1.mol.l⁻¹.( SY::Molarity )
318
+ # (if #reframe conversion method is not used, different quantities
319
+ # do not compare. Arithmetics is possible because Magnitude operators
320
+ # mostly give their results only in standard quantities.
321
+
322
+ # Avogadro's number is defined directly in SY
323
+ 1.mol.must_equal SY::Nᴀ.unit.( SY::MoleAmount )
324
+
325
+
326
+ 0.7.M.must_equal 0.7.mol.l⁻¹.( SY::Molarity )
327
+ # (if #is_actually! conversion method is not used, current
328
+ # implementation will refuse to compare different quantities,
329
+ # even if their dimensions match)
330
+
331
+ 30.Hz.must_equal 30.s⁻¹.( SY::Frequency )
332
+
333
+ # Dalton * Avogadro must be 1 gram
334
+ ( 1.Da * SY::Nᴀ ).must_be_within_epsilon( 1.g, 1e-6 )
335
+
336
+ # kilogram
337
+ 1.kg.must_equal 1000.g
338
+ SY::Speed.dimension.must_equal SY::Dimension( "L.T⁻¹" )
339
+ SY::Acceleration.dimension.must_equal SY::Dimension( "L.T⁻²" )
340
+ SY::Force.dimension.must_equal SY::Dimension( "L.M.T⁻²" )
341
+ ( 1.kg * 1.m.s⁻² ).( SY::Force ).must_be_within_epsilon 1.N, 1e-9
342
+
343
+ # joule
344
+ ( 1.N * 1.m ).( SY::Energy ).must_equal 1.J
345
+ 1e-23.J.K⁻¹.must_equal 1.0e-20.mJ.K⁻¹
346
+
347
+
348
+ # pascal
349
+ ( 1.N / 1.m ** 2 ).( SY::Pressure ).must_be_within_epsilon 1.Pa, 1e-9
350
+
351
+ # watt
352
+ ( 1.V * 1.A ).( SY::Power ).must_be_within_epsilon 1.W, 1e-9
353
+
354
+ # pretty representation
355
+ ( 1.m / 3.s ).to_s.must_equal( "0.333.m.s⁻¹" )
356
+ ( 1.m / 7.01e7.s ).to_s.must_equal( "1.43e-08.m.s⁻¹" )
357
+
358
+ assert_equal 1.m, 1.s * 1.m.s⁻¹
359
+ assert_equal 1.µM.s⁻¹, 1.µM / 1.s
360
+ assert_equal 1.m.s⁻¹, 1.m.s( -1 )
361
+ assert_equal 2_000.mm.s⁻², 2.m.s( -2 )
362
+ assert_equal 3.µM, 1.µM + 2.µM
363
+ assert_equal SY::Amount, SY::Molarity / SY::Molarity
364
+ assert_equal SY::Amount( 1 ), 1.µM / 1.µM
365
+ assert_equal SY::Amount( 1 ), 1.µM / ( 1.µM + 0.µM )
366
+ assert_equal 1.µM, 1.µM * 1.µM / ( 1.µM + 0.µM )
367
+ assert_in_epsilon 1.µM, 1.µmol / 1.dm( 3 ).( SY::LitreVolume )
368
+
369
+ assert_equal SY::Molarity.relative, 1.mol.l⁻¹.quantity
370
+
371
+ assert_equal 1 / SY::Time, 1 / SY::Time
372
+ assert_equal 1 / SY::Time.relative, 1 / SY::Time
373
+ assert_equal ( 1 / SY::Time.relative ), 1.mol.s⁻¹.( 1 / SY::Time ).quantity
374
+ assert_equal ( 1 / SY::Time ).object_id,
375
+ ( 1.0.µmol.min⁻¹.mg⁻¹ * 100.kDa ).( 1 / SY::Time ).quantity.object_id
376
+ assert_equal SY::Time.magnitude( 1 ), SY::SECOND
377
+ assert_equal Matrix[[60.mM], [60.mM]], Matrix[[1e-03.s⁻¹.M], [1e-3.s⁻¹.M]] * 60.s
378
+
379
+ assert_equal Matrix[[5.m]], Matrix[[1.m.s⁻¹, 2.m.s⁻¹]] * Matrix.column_vector( [1.s, 2.s] )
380
+ assert_equal Matrix[[2.m, 3.m], [4.m, 5.m]],
381
+ Matrix[[1.m, 2.m], [3.m, 4.m]] + Matrix[[1.m, 1.m], [1.m, 1.m]]
382
+ assert_equal Matrix[[5.µM]], Matrix[[1.µM]] + Matrix[[2.µM.s⁻¹]] * Matrix[[2.s]]
383
+ end
384
384
  end
385
385
  end