sy 1.0.0
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.
- 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
|