sy 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/sy.rb +274 -0
- data/lib/sy/absolute_magnitude.rb +96 -0
- data/lib/sy/abstract_algebra.rb +102 -0
- data/lib/sy/composition.rb +219 -0
- data/lib/sy/dimension.rb +182 -0
- data/lib/sy/expressible_in_units.rb +135 -0
- data/lib/sy/fixed_assets_of_the_module.rb +287 -0
- data/lib/sy/magnitude.rb +515 -0
- data/lib/sy/mapping.rb +84 -0
- data/lib/sy/matrix.rb +69 -0
- data/lib/sy/quantity.rb +455 -0
- data/lib/sy/signed_magnitude.rb +51 -0
- data/lib/sy/unit.rb +288 -0
- data/lib/sy/version.rb +4 -0
- data/lib/sy/wildcard_zero.rb +29 -0
- data/sy.gemspec +19 -0
- data/test/sy_test.rb +385 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e78755a352e971c6b349b4caf3e35f67e95876dd
|
4
|
+
data.tar.gz: 43903464572d42927c2a6ac4359c1341c3f71f79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f817d558c1f3be298243a703ade9c6945d22f3a6febada5fb86e7c375986ea1b5b8d78f7f8d5d463086feea69a5010cb33b199a5e27c513d0a94d1582e9aed9
|
7
|
+
data.tar.gz: 2e953fc6121f7d30419d48493e80b45cb18ea6295eeb8fb5c708bc1f0851f7c9410e334adb742b1c09f32029aca246ad35657342fcf63912312d70f80b362dd3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 boris
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Sy
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'sy'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install sy
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/sy.rb
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'y_support/null_object'
|
4
|
+
require 'y_support/name_magic'
|
5
|
+
require 'y_support/core_ext/hash'
|
6
|
+
require 'y_support/typing'
|
7
|
+
require 'y_support/unicode'
|
8
|
+
require 'y_support/abstract_algebra'
|
9
|
+
|
10
|
+
require 'active_support/core_ext/module/delegation'
|
11
|
+
require 'active_support/core_ext/array/extract_options'
|
12
|
+
require 'active_support/core_ext/string/starts_ends_with'
|
13
|
+
|
14
|
+
require_relative 'sy/version'
|
15
|
+
require_relative 'sy/expressible_in_units'
|
16
|
+
require_relative 'sy/fixed_assets_of_the_module'
|
17
|
+
require_relative 'sy/mapping'
|
18
|
+
require_relative 'sy/dimension'
|
19
|
+
require_relative 'sy/quantity'
|
20
|
+
require_relative 'sy/composition'
|
21
|
+
require_relative 'sy/magnitude'
|
22
|
+
require_relative 'sy/absolute_magnitude'
|
23
|
+
require_relative 'sy/signed_magnitude'
|
24
|
+
require_relative 'sy/unit'
|
25
|
+
|
26
|
+
# The most prominent feature of SY is, that it extends the Numeric class
|
27
|
+
# with methods corresponding to units and their abbreviations.
|
28
|
+
#
|
29
|
+
# In other words, we can say 5.metre, or Rational( 5, 2 ).metre, and the
|
30
|
+
# computer will understand, that these numbers represent magnitudes of the
|
31
|
+
# physical quantity SY::Length expressed in the unit SY::METRE. Equally,
|
32
|
+
# we can use abbreviations (such as 5.m, 2.5.m), prefixes (such as 5.km,
|
33
|
+
# 5.kilometre, 5.km), exponents (such as 5.m² for 5 square metres) and
|
34
|
+
# chaining (such as 5.m.s⁻¹ to denote speed of 5 metres per second).
|
35
|
+
#
|
36
|
+
# You should definitely learn how to type Unicode exponent characters, such
|
37
|
+
# as ², ³, ⁻¹ etc. It is possible to use alterantive syntax such as 5.m.s(-1)
|
38
|
+
# instead of 5.m.s⁻¹, but you should avoid it whenever possible. Unicode
|
39
|
+
# exponents make the physical models that you will be constructing with SY
|
40
|
+
# much more readable. And we know that code is (usually) write once, read
|
41
|
+
# many times. So it pays off to type an extra keystroke when writing the to
|
42
|
+
# make the model more readable for the many subsequent revisions.
|
43
|
+
#
|
44
|
+
# One more remark here would be, that due to the fact, that many unit names
|
45
|
+
# and abbreviations are very short and common words, there can be collisions.
|
46
|
+
# For example ActiveSupport already provides handling for time units (hour,
|
47
|
+
# minute, second etc.), which would collide with SY methods of the same name.
|
48
|
+
# Since SY relies on method_missing, if these methods are already defined for
|
49
|
+
# numerics, SY method_missing will not activate and ActiveSupport methods will
|
50
|
+
# be used. In this particular case, SY methods still can be invoked using
|
51
|
+
# abbreviations (5.s, 5.h, 5.min)
|
52
|
+
#
|
53
|
+
Numeric.class_exec { include ::SY::ExpressibleInUnits }
|
54
|
+
|
55
|
+
# === Instead of introduction
|
56
|
+
#
|
57
|
+
# SY module defines certain usual constants, quantities and units. The best
|
58
|
+
# introduction to how SY works would be if we take a look at the examples
|
59
|
+
# of the most common quantities and units right here in the SY module:
|
60
|
+
#
|
61
|
+
module SY
|
62
|
+
# Let SY::Amount be a standard dimensionless quantity:
|
63
|
+
Amount = Quantity.standard of: Dimension.zero
|
64
|
+
|
65
|
+
# Convenience constructor of amounts:
|
66
|
+
def self.Amount number
|
67
|
+
SY::Amount.relative.magnitude number
|
68
|
+
end
|
69
|
+
|
70
|
+
# AVOGADRO_CONSTANT (Nᴀ) is a certain well-known amount of things:
|
71
|
+
Nᴀ = AVOGADRO_CONSTANT = SY.Amount 6.02214e23
|
72
|
+
|
73
|
+
# Let SY::UNIT be a standard unit of SY::Amount. Note that the upcase name
|
74
|
+
# of the constant "UNIT" implies, via YSupport's NameMagic mixin, that the
|
75
|
+
# name of the object becomes :unit and that it is possible to use syntax
|
76
|
+
# such as 42.unit to create magnitudes of SY::Amount.
|
77
|
+
UNIT = Unit.standard of: Amount
|
78
|
+
|
79
|
+
# Let SY::MoleAmount be another dimensionless quantity:
|
80
|
+
MoleAmount = Quantity.dimensionless
|
81
|
+
|
82
|
+
# And let SY::MOLE be its standard unit, related to SY::Amount via Nᴀ:
|
83
|
+
MOLE = Unit.standard of: MoleAmount, short: "mol", amount: Nᴀ.unit
|
84
|
+
|
85
|
+
# === Basic dimension L (length)
|
86
|
+
|
87
|
+
# Let SY::Length be a standard quantity of basic dimension L:
|
88
|
+
Length = Quantity.standard of: :L
|
89
|
+
|
90
|
+
# Let SY::METRE be its standard unit.
|
91
|
+
METRE = Unit.standard of: Length, short: "m"
|
92
|
+
|
93
|
+
# === Basic dimension M (mass)
|
94
|
+
|
95
|
+
# Let SY::Mass be a standard quantity of basic dimension M:
|
96
|
+
Mass = Quantity.standard of: :M
|
97
|
+
|
98
|
+
# Let SY::KILOGRAM be its standard unit:
|
99
|
+
KILOGRAM = Unit.standard of: Mass, short: "kg"
|
100
|
+
# Let SY::GRAM be another unit of SY::Mass, equal to 0.001.kg:
|
101
|
+
GRAM = Unit.of Mass, amount: 0.001.kg, short: "g"
|
102
|
+
# Let SY::TON be another...
|
103
|
+
TON = Unit.of Mass, amount: 1000.kg, short: "t"
|
104
|
+
# And SY::DALTON another...
|
105
|
+
DALTON = Unit.of Mass, short: "Da", amount: 1.66053892173e-27.kg
|
106
|
+
|
107
|
+
# === Basic dimension T
|
108
|
+
|
109
|
+
# Let SY::Time be a standard quantity of basic dimension T:
|
110
|
+
Time = Quantity.standard of: :T
|
111
|
+
|
112
|
+
# Let SY::SECOND be its standard unit:
|
113
|
+
SECOND = Unit.standard of: Time, short: "s"
|
114
|
+
# Let SY::MINUTE be another unit:
|
115
|
+
MINUTE = Unit.of Time, short: "min", amount: 60.s
|
116
|
+
# And SY::HOUR another:
|
117
|
+
HOUR = Unit.of Time, short: "h", amount: 60.min
|
118
|
+
|
119
|
+
# === Basic dimension Q
|
120
|
+
|
121
|
+
# Let SY::ElectricCharge be a standard quantity of basic dimension Q:
|
122
|
+
ElectricCharge = Quantity.standard of: :Q
|
123
|
+
|
124
|
+
# And SY::COULOMB be its standard unit:
|
125
|
+
COULOMB = Unit.standard of: ElectricCharge, short: "C"
|
126
|
+
|
127
|
+
# === Basic dimension Θ
|
128
|
+
|
129
|
+
# Let SY::Temperature be a standard quantity of basic dimension Θ:
|
130
|
+
Temperature = Quantity.standard of: :Θ
|
131
|
+
|
132
|
+
# And SY::KELVIN be its standard unit:
|
133
|
+
KELVIN = Unit.standard of: Temperature, short: "K"
|
134
|
+
|
135
|
+
# Now let us define a useful constant:
|
136
|
+
TP_H₂O = TRIPLE_POINT_OF_WATER = 273.15.K
|
137
|
+
|
138
|
+
# Celsius temperature is a little bit peculiar in that it has offset of
|
139
|
+
# 273.15.K with respect to Kelvin temperature, and I am not sure whether
|
140
|
+
# at this moment SY is handling this right. But nevertheless:
|
141
|
+
CelsiusTemperature = Quantity.of :Θ
|
142
|
+
|
143
|
+
# Degree celsius is SY::CELSIUS
|
144
|
+
CELSIUS = Unit.standard of: CelsiusTemperature, short: '°C'
|
145
|
+
# FIXME: Patch CelsiusTemperature to make it work with SY::Temperature
|
146
|
+
# alias :°C :celsius # with U+00B0 DEGREE SIGN
|
147
|
+
# alias :˚C :celsius # with U+02DA RING ABOVE
|
148
|
+
# alias :℃ :celsius # U+2103 DEGREE CELSIUS
|
149
|
+
|
150
|
+
# FahrenheitTemperature = Quantity.of :Θ
|
151
|
+
# FAHRENHEIT = Unit.standard of: FahrenheitTemperature, short: '°F'
|
152
|
+
# # alias :°F :fahrenheit # with U+00B0 DEGREE SIGN
|
153
|
+
# # alias :˚F :fahrenheit # with U+02DA RING ABOVE
|
154
|
+
# # alias :℉ :fahrenheit # U+2109 DEGREE FAHRENHEIT
|
155
|
+
# # FIXME: Patch FahrenheitTemperature to make it work with SY::Temperature
|
156
|
+
|
157
|
+
|
158
|
+
# HUMAN_BODY_TEMPERATURE = 37.°C.( KELVIN )
|
159
|
+
# STANDARD_TEMPERATURE = 25.°C.( KELVIN )
|
160
|
+
HUMAN_BODY_TEMPERATURE = TP_H₂O + 37.K
|
161
|
+
STANDARD_LABORATORY_TEMPERATURE = TP_H₂O + 25.K
|
162
|
+
|
163
|
+
# === Dimensionless quantities
|
164
|
+
|
165
|
+
# For now, these are just unimplemented proposals of what users might expect
|
166
|
+
# from SY:
|
167
|
+
#
|
168
|
+
# degree, alias deg, ° # angle measure
|
169
|
+
# arcminute, alias ʹ, ′ # angle measure
|
170
|
+
# arcsecond, alias ʹʹ, ′′, ″
|
171
|
+
|
172
|
+
# === Quantities of composite dimensions
|
173
|
+
|
174
|
+
# Quantity SY::Area is obtained by raising quantity SY::Length to 2:
|
175
|
+
Area = Length ** 2
|
176
|
+
|
177
|
+
# Quantity SY::Volume is obtained by raising quantity SY::Length to 3:
|
178
|
+
Volume = Length ** 3
|
179
|
+
|
180
|
+
# SY::LitreVolume is another quantity of the same dimension as SY::Volume:
|
181
|
+
LitreVolume = Quantity.of Volume.dimension
|
182
|
+
|
183
|
+
# SY::LITRE is the standard unit of SY::LitreVolume:
|
184
|
+
LITRE = Unit.standard of: LitreVolume, short: "l", amount: 1.dm³
|
185
|
+
|
186
|
+
# At this point, there are certain things to note. Since standard units of
|
187
|
+
# SY::Area and SY::Volume have not been specified, they are assumed to be
|
188
|
+
# simply 1.metre², resp. 1.metre³. But LitreVolume, whose standard unit
|
189
|
+
# has been named litre, with abbreviation "l", will from now on present
|
190
|
+
# its magnitudes expressed in litres, rather than cubic metres. While
|
191
|
+
# theoretically, LitreVolume and Volume both have dimension L³ and both
|
192
|
+
# can be used to express volume, LitreVolume in SY conveys the context of
|
193
|
+
# chemistry.
|
194
|
+
|
195
|
+
# SY::Molarity is obtained by dividing SY::MoleAmount by SY::LitreVolume:
|
196
|
+
Molarity = ( MoleAmount / LitreVolume ).protect!
|
197
|
+
|
198
|
+
# Standard unit of SY::Molarity is SY::MOLAR:
|
199
|
+
MOLAR = Unit.standard of: Molarity, abbreviation: "M"
|
200
|
+
|
201
|
+
# Let us now note the #protect! directive at the line above defining
|
202
|
+
# SY::Molarity. Method #protect! prevents Molarity from understanding itself
|
203
|
+
# as merely L⁻³ (or 1/metre³), as would follow from its dimensional analysis.
|
204
|
+
# Method #protect! causes Molarity to appreciate its identity as :molar,
|
205
|
+
# which is exactly what chemists expect.
|
206
|
+
|
207
|
+
# SY::Frequency, a quantity that many will expect:
|
208
|
+
Frequency = 1 / Time
|
209
|
+
|
210
|
+
# SY::HERTZ is its unit:
|
211
|
+
HERTZ = Unit.of Frequency, short: "Hz"
|
212
|
+
# Fixme: it would be expected that 1.s(-1) would not present itself as 1.Hz,
|
213
|
+
# provided that we did not make :hertz standard unit of Frequency
|
214
|
+
|
215
|
+
# Define SY::Speed as SY::Length / SY::Time and make it a standard quantity
|
216
|
+
# of its dimension.
|
217
|
+
Speed = ( Length / Time ).standard!
|
218
|
+
|
219
|
+
# Similar for SY::Acceleration:
|
220
|
+
Acceleration = ( Speed / Time ).standard!
|
221
|
+
|
222
|
+
# For SY::Force...
|
223
|
+
Force = ( Acceleration * Mass ).standard!
|
224
|
+
|
225
|
+
# This time, make SY::NEWTON its standard unit:
|
226
|
+
NEWTON = Unit.standard of: Force, short: "N"
|
227
|
+
|
228
|
+
# For SY::Energy...
|
229
|
+
Energy = ( Force * Length ).standard!
|
230
|
+
|
231
|
+
# make SY::JOULE its standard unit:
|
232
|
+
JOULE = Unit.standard of: Energy, short: "J"
|
233
|
+
# SY::CALORIE means thermochemical calorie:
|
234
|
+
CALORIE = Unit.of Energy, short: "cal", amount: 4.184.J
|
235
|
+
|
236
|
+
# SY::Power...
|
237
|
+
Power = ( Energy / Time ).standard!
|
238
|
+
|
239
|
+
# make SY::WATT its standard unit:
|
240
|
+
WATT = Unit.standard of: Power, short: "W"
|
241
|
+
|
242
|
+
# SY::Pressure...
|
243
|
+
Pressure = ( Force / Area ).standard!
|
244
|
+
|
245
|
+
# make SY::PASCAL its standard unit:
|
246
|
+
PASCAL = Unit.standard of: Pressure, short: "Pa"
|
247
|
+
|
248
|
+
# SY::ElectricCurrent...
|
249
|
+
ElectricCurrent = ( ElectricCharge / Time ).standard!
|
250
|
+
|
251
|
+
# make SY::AMPERE its standard unit:
|
252
|
+
AMPERE = Unit.standard of: ElectricCurrent, short: "A"
|
253
|
+
|
254
|
+
# SY::ElectricPotential...
|
255
|
+
ElectricPotential = ( Energy / ElectricCharge ).standard!
|
256
|
+
|
257
|
+
# make SY::VOLT its standard unit:
|
258
|
+
VOLT = Unit.standard of: ElectricPotential, short: "V"
|
259
|
+
|
260
|
+
# FIXME: This should raise a friendly error:
|
261
|
+
# MOLAR = Unit.standard of: Molarity, abbreviation: "M", amount: 1.mol.l⁻¹
|
262
|
+
|
263
|
+
# SY::Molality...
|
264
|
+
Molality = MoleAmount / Mass
|
265
|
+
|
266
|
+
# make SY::MOLAL its unit (but don't make it a standard unit...):
|
267
|
+
MOLAL = Unit.of Molality
|
268
|
+
|
269
|
+
# SY::Molecularity...
|
270
|
+
Molecularity = Amount / LitreVolume
|
271
|
+
|
272
|
+
# Having defined Joules and Kelvins, we can spell out the Boltzmann constant:
|
273
|
+
Kʙ = BOLTZMANN_CONSTANT = 1.380648813e-23.J.K⁻¹
|
274
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Qualities specific to absolute magnitudes.
|
4
|
+
#
|
5
|
+
module SY::AbsoluteMagnitude
|
6
|
+
# Absolute magnitude constructor takes :quantity (alias :of) named argument,
|
7
|
+
# and :amount named argument, where amount must be nonnegative.
|
8
|
+
#
|
9
|
+
def initialize args={}
|
10
|
+
@quantity = args[:quantity] || args[:of]
|
11
|
+
amnt = args[:amount]
|
12
|
+
@amount = case amnt
|
13
|
+
when Numeric then amnt
|
14
|
+
when nil then 1
|
15
|
+
else
|
16
|
+
begin
|
17
|
+
amnt.amount
|
18
|
+
rescue NameError, NoMethodError
|
19
|
+
amnt
|
20
|
+
end
|
21
|
+
end
|
22
|
+
raise SY::MagnitudeError,
|
23
|
+
"Unsigned magnitudes canot have negative amount!" if @amount < 0
|
24
|
+
end
|
25
|
+
|
26
|
+
# For absolute magnitudes, #+ method always returns a result framed in
|
27
|
+
# corresponding relative quantity.
|
28
|
+
#
|
29
|
+
def + m2
|
30
|
+
return magnitude amount + m2.amount if m2.quantity == quantity.relative
|
31
|
+
return quantity.relative.magnitude( amount + m2.amount ) if
|
32
|
+
quantity == m2.quantity
|
33
|
+
return self if m2.equal? SY::ZERO
|
34
|
+
# o1, o2 = m2.coerce( self )
|
35
|
+
# return o1 + o2
|
36
|
+
raise SY::QuantityError, "Unable to perform #{quantity} + #{m2.quantity}!"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Addition of absolute magnitudes that returns a result framed as
|
40
|
+
# absolute quantity.
|
41
|
+
#
|
42
|
+
def add m2
|
43
|
+
return magnitude( amount + m2.amount ) if quantity == m2.quantity
|
44
|
+
return self if m2.equal? SY::ZERO
|
45
|
+
# o1, o2 = m2.coerce( self )
|
46
|
+
# return o1.add o2
|
47
|
+
raise SY::QuantityError, "Unable to perform #add with #{m2.quantity}!"
|
48
|
+
end
|
49
|
+
|
50
|
+
# For absolute magnitudes, #- method always returns a result framed in
|
51
|
+
# corresponding relative quantity.
|
52
|
+
#
|
53
|
+
def - m2
|
54
|
+
return magnitude amount - m2.amount if m2.quantity == quantity.relative
|
55
|
+
return quantity.relative.magnitude( amount - m2.amount ) if
|
56
|
+
quantity == m2.quantity
|
57
|
+
return self if m2.equal? SY::ZERO
|
58
|
+
# o1, o2 = m2.coerce( self )
|
59
|
+
# return o1 - o2
|
60
|
+
raise( SY::QuantityError, "Unable to perform #{quantity} - #{m2.quantity}!" )
|
61
|
+
end
|
62
|
+
|
63
|
+
# Subtraction of absolute magnitudes that returns a result framed as
|
64
|
+
# absolute quantity. (With caller being responsible for the result being
|
65
|
+
# nonnegative.)
|
66
|
+
#
|
67
|
+
def subtract m2
|
68
|
+
return magnitude( amount + m2.amount ) if quantity == m2.quantity
|
69
|
+
return self if m2.equal? SY::ZERO
|
70
|
+
# o1, o2 = m2.coerce( self )
|
71
|
+
# return o1.subtract o2
|
72
|
+
raise( SY::QuantityError, "Unable to perform #add with #{m2.quantity}!" )
|
73
|
+
end
|
74
|
+
|
75
|
+
# "Subtraction" of absolute magnitudes, that never takes more thant the
|
76
|
+
# amount from which subtraction is being performed. But for this reason,
|
77
|
+
# unlike regular #subtract, it is not known in advance what amount will
|
78
|
+
# be subtracted. Returns an array of two values: first one is the amount
|
79
|
+
# actually subtracted (which may differ from the amount asked for), and
|
80
|
+
# the second is the actual result of the subtraction (amount left). The
|
81
|
+
# latter will be zero if attempt is made to subtract greater amount from
|
82
|
+
# a smaller one.
|
83
|
+
#
|
84
|
+
def take other
|
85
|
+
actually_taken = [ self, other ].min
|
86
|
+
return [ actually_taken, other.subtract( take ) ]
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# String describing this class.
|
92
|
+
#
|
93
|
+
def çς
|
94
|
+
"Magnitude"
|
95
|
+
end
|
96
|
+
end # class SY::Magnitude
|