Used colon-less keyword syntax in method signatures where the optional variable name...
[cslatevm.git] / src / lib / dimensioned.slate
blob398b852f80d2aca10bf5b766f62889a7760b8563
1 numerics ensureNamespace: #units &delegate: True.
2 "Based on the Squeak Units code at http://home.netsurf.de/helge.horch/squeak/units.html"
4 numerics define: #Dimension &parents: {Cloneable}.
6 d1@(Dimension traits) isConsistentWith: d2@(Dimension traits) [d1 isSameAs: d2].
8 numerics define: #Length &parents: {Dimension}.
10 numerics define: #Time &parents: {Dimension}.
12 numerics define: #Mass &parents: {Dimension}.
14 numerics define: #Temperature &parents: {Dimension}.
16 numerics define: #Count &parents: {Dimension}.
18 numerics define: #ElectricalCharge &parents: {Dimension}.
20 numerics define: #Unit.
22 u1@(Unit traits) isConsistentWith: u2@(Unit traits) [u1 dimension isConsistentWith: u2 dimension].
24 u1@(Unit traits) * u2@(Unit traits)
25 [| unitDict units expons scratch |
26   unitDict := Dictionary new.
27   u1 unitsAndExponentsDo: [| :unit :expon | (unitDict includesKey: unit)
28     ifTrue: [unitDict at: unit := (unitDict at: unit) + expon]
29     ifFalse: [unitDict at: unit := expon]].
30   u2 unitsAndExponentsDo: [| :unit :expon | (unitDict includesKey: unit)
31     ifTrue: [unitDict at: unit := (unitDict at: unit) + expon]
32     ifFalse: [unitDict at: unit := expon]].
33   units := ExtensibleArray new.
34   expons := ExtensibleArray new.
35   (unitDict keySet sortBy:
36     [| :left :right |
37       (left abbrev lexicographicallyCompare: right abbrev) < 0])
38     do: [| :unit |
39       scratch := unitDict at: unit.
40       scratch isZero ifFalse: [units add: unit. expons add: scratch]].
41   units size = 1 /\ [expons first = 1]
42     ifTrue: [^ units first].
43   ComplexUnit units: units exponents: expons
46 u1@(Unit traits) / u2@(Unit traits)
47 [u1 * u2 reciprocal].
49 u1@(Unit traits) per: u2@(Unit traits)
50 [u1 / u2].
52 u@(Unit traits) raisedTo: expon
54   ComplexUnit units: {u} exponents: {expon}
57 u@(Unit traits) reciprocal
59   ComplexUnit units: {u} exponents: {-1}
62 u@(Unit traits) squared
63 [u * u].
65 u1@(Unit traits) factor: u2@(Unit traits)
67   u2 * (u1 bases / u2 bases)
70 u@(Unit traits) unitsAndExponentsDo: block
71 "Evaluate the block once for each unit/exponent pair in u, defaulting to this."
72 [block applyWith: u with: 1].
74 u@(Unit traits) conversionFactorTo: v@(Unit traits)
75 "Assuming u and v are consistent, return the numerical answer to u*X=v."
76 [u conversionFactor / v conversionFactor].
78 u@(Unit traits) additiveFactor
79 "The value of the base level of the scale - usually 0; the only thing that
80 has a real standard non-zero value is Temperatures (by old convention)."
81 [0].
83 _@(Unit traits) consistentWith: _@(Unit traits)
84 [False].
86 numerics define: #ObjectUnit &parents: {Unit}
87 "A Unit used to describe/count Slate objects."
88   &slots: {#object -> Nil.
89 "The object/exemplar on which the Unit is based."
90 #comparisonBlock -> #isSameAs: `er.
91 "How to tell if units are compatible; the caller needs to consider this."}.
93 u@(ObjectUnit traits) isConsistentWith: v@(ObjectUnit traits)
94 [u comparisonBlock apply*, u object, v object].
96 u@(ObjectUnit traits) printOn: s@(PrettyPrinterMixin traits)
97 [s ; 'of: ' ; (RootedPath from: here to: u object) printString].
99 u@(ObjectUnit traits) printFullOn: s@(PrettyPrinterMixin traits) plural: p
101   p ifTrue: [s ; u object printName plural]
102     ifFalse: [s ; u object printName]
105 numerics define: #UnitValue &parents: {Number} &slots: {#unit. #value}.
107 uv@(UnitValue traits) unit: unit value: value
108 [uv clone `setting: #{#unit. #value} to: {unit. value}].
110 uv@(UnitValue traits) dimension [uv unit dimension].
112 uv@(UnitValue traits) printOn: s@(PrettyPrinterMixin traits) &full
114   uv value printOn: s.
115   s ; ' '.
116   (full ifNil: [True])
117     ifTrue: [uv unit printFullOn: s plural: uv value ~= 1]
118     ifFalse: [uv unit printOn: s].
119   uv
122 x@(Number traits) as: uv@(UnitValue traits)
124   UnitValue unit: CompoundUnit null value: x
127 uv@(UnitValue traits) as: x@(Number traits)
128 [uv value].
130 uv@(UnitValue traits) convertTo: u@(Unit traits)
131 "Convert the value to have the same units as u, using scaling factors."
133   (uv unit isConsistentWith: u) ifTrue:
134     [uv unit: u value: (uv value - uv unit additiveFactor) * (uv unit conversionFactorTo: u) - u additiveFactor]
137 uv@(UnitValue traits) in: u@(Unit traits)
138 "Alias of convertTo:."
139 [uv convertTo: u].
141 uv@(UnitValue traits) bases
142 "Return the reduction of uv to base units."
144   uv convertTo: uv unit baseUnits
147 uv@(UnitValue traits) as: u@(Unit traits)
149   uv convertTo: u
152 x@(Number traits) of: u@(Unit traits)
154   UnitValue unit: u value: x
157 x@(Number traits) of: obj &comparison
158 [| u |
159   u := ObjectUnit `>> [object := obj. comparisonBlock ?= comparison. ].
160   UnitValue unit: u value: x
163 x@(Number traits) as: u@(Unit traits)
165   x of: u
168 x@(UnitValue traits) isConsistentWith: y@(UnitValue traits)
170   x unit isConsistentWith: y unit
173 x@(UnitValue traits) + y@(UnitValue traits)
174 [| sum |
175   (x isConsistentWith: y) ifFalse: [^ Nil].
176   "TODO: construct sum!"
177   (x as: y) `>> [value := sum value + y value. reduced]
180 x@(UnitValue traits) + y
182   x value + y as: x unit
185 x + y@(UnitValue traits)
187   y + x
190 x@(UnitValue traits) - y@(UnitValue traits)
192   x + y negated
195 x@(UnitValue traits) - y
197   x value - y as: x unit
200 x - y@(UnitValue traits)
202   x - y value as: x unit
205 x@(UnitValue traits) * y@(UnitValue traits)
207   (x unit: x unit * y unit value: x value * y value) reduced
210 x@(UnitValue traits) * y
212   x value * y as: x unit
215 x * y@(UnitValue traits)
217   y * x
220 x@(UnitValue traits) / y@(UnitValue traits)
222   (y unit: x unit / y unit value: x value / y value) reduced
225 x@(UnitValue traits) / y
227   x value / y as: x unit
230 x / y@(UnitValue traits)
232   x / y value as: x unit
235 x@(UnitValue traits) = y@(UnitValue traits)
237   (x isConsistentWith: y) /\ [y value = (x as: y) value]
240 x@(UnitValue traits) < y@(UnitValue traits)
242   (x isConsistentWith: y) /\ [x value < (y as: x unit) value]
245 uv@(UnitValue traits) negated
246 [uv value negated as: uv unit].
248 uv@(UnitValue traits) reduced
249 "Answer the scalar part if the units have 'vanished'."
251   uv unit units isEmpty ifTrue: [uv value] ifFalse: [uv]
254 uv1@(UnitValue traits) factor: uv2@(UnitValue traits)
255 "Factor with respect to another unit or unitValue."
257   uv1 factor: uv2 unit
260 uv@(UnitValue traits) factor: u@(Unit traits)
262   uv as: (uv unit factor: u).
265 uv@(UnitValue traits) raisedTo: expon
267   uv unit: (uv unit raisedTo: expon) value: (uv value raisedTo: expon)
270 uv@(UnitValue traits) reciprocal
271 [uv raisedTo: -1].
273 uv@(UnitValue traits) sqrt
275   uv unit: (uv unit raisedTo: 1 / 2) value: (uv value sqrt)
278 uv@(UnitValue traits) ceiling
280   uv value ceiling as: uv unit
283 uv@(UnitValue traits) floor
285   uv value floor as: uv unit
288 uv@(UnitValue traits) roundTo: x
290   (uv value roundTo: x) as: uv unit
293 uv@(UnitValue traits) roundUpTo: x
295   (uv value roundUpTo: x) as: uv unit
298 uv@(UnitValue traits) truncateTo: x
300   (uv value truncateTo: x) as: uv unit
303 uv@(UnitValue traits) rounded
305   (uv value rounded) as: uv unit
308 numerics define: #CompoundUnit &parents: {Unit} &slots: {#units. #exponents}.
310 CompoundUnit traits compareAndHashUsingSlots: #{#units. #exponents}.
312 cu@(CompoundUnit traits) reciprocal
314   cu units: cu units
315      exponents: (cu exponents collect: #negated `er)
318 cu@(CompoundUnit traits) raisedTo: expon
320   cu units: cu units
321      exponents: (cu exponents collect: #(* expon) `er)
324 cu@(CompoundUnit traits) unitsAndExponentsDo: block
326   cu units with: cu exponents do: block
329 cu@(CompoundUnit traits) conversionFactor
330 [1].
332 cu@(CompoundUnit traits) printOn: s@(PrettyPrinterMixin traits)
333 [| first any count |
334   first := True.
335   any := False.
336   cu unitsAndExponentsDo: [| :unit :expon |
337     expon isPositive
338       ifTrue: [any := True.
339         first ifFalse: [s nextPut: $*].
340         first := False.
341         unit printOn: s.
342         expon ~= 1 ifTrue: [s nextPut: $^. expon printOn: s]]].
343   count := cu exponents inject: 0 into: [| :c :each |
344     each isNegative ifTrue: [c + 1] ifFalse: [c]].
345   count isPositive
346     ifTrue: [any ifFalse: [s nextPut: $1].
347       s nextPut: $/.
348       count > 1 ifTrue: [s nextPut: $(].
349       first := True.
350       cu unitsAndExponentsDo: [| :unit :expon |
351         expon ~= 1 ifTrue: [first ifFalse: [s nextPut: $*].
352         first := False.
353         unit printOn: s.
354         expon < -1 ifTrue: [s nextPut: $^. expon negated printOn: s]]].
355       count > 1 ifTrue: [s nextPut: $)]].
356   cu
359 cu@(CompoundUnit traits) printFullOn: s@(PrettyPrinterMixin traits) plural: b
360 [| pos neg |
361   pos := cu exponents anySatisfy: #isPositive `er.
362   neg := cu exponents anySatisfy: #isNegative `er.
363   pos ifTrue: [cu printUnitsWhereExponent: #isPositive `er
364                   on: s plural: b].
365   neg /\ pos ifTrue: [s nextPut: $\s].
366   neg ifTrue: [s ; 'per '.
367     cu printUnitsWhereExponent: #isNegative `er on: s plural: b].
368   cu
371 cu@(CompoundUnit traits) printUnitsWhereExponent: block on: s plural: plural
372 [| power first count index thisPlural |
373   first := True.
374   count := cu exponents count: block.
375   index := 0.
376   cu unitsAndExponentsDo: [| :unit :expon |
377     (block applyWith: expon)
378       ifTrue: [first ifTrue: [first := False] ifFalse: [s nextPut: $\s].
379         index += 1.
380         thisPlural := plural /\ [index = count].
381         power := expon abs.
382         (power is: Integer) /\ [power <= 3]
383           ifTrue: [power = 2 ifTrue: [s ; 'square '].
384             power = 3 ifTrue: [s ; 'cubic ']].
385         unit printFullOn: s plural: plural.
386         power > 3 \/ [(power is: Integer) not] ifTrue:
387           [s nextPut: $^. power printOn: s]]].
388   cu
391 cu1@(CompoundUnit traits) isConsistentWith: cu2@(CompoundUnit traits)
393   cu1 units = cu2 units /\ [cu1 bases = cu2 bases]
396 cu@(CompoundUnit traits) dimension
398   cu unitsAndExponentsDo: [| :unit :expon |
399     "TODO: assemble/return a compound dimension"
400   ].
403 numerics define: #ComplexUnit &parents: {CompoundUnit}
404   &slots: {#conversionFactor. #cachedBases}.
406 cu@(ComplexUnit traits) units: units exponents: expons
407 [| newCU |
408   newCU := cu clone `setting: #{#units. #exponents. #conversionFactor}
409     to: {units. expons. 1}.
410   newCU units with: newCU exponents do: [| :unit :expon |
411     newCU conversionFactor: newCU conversionFactor
412       * (unit conversionFactor raisedTo: expon)].
413   newCU
416 cu@(ComplexUnit traits) bases
417 "Calculating bases is expensive, so the values are cached."
419   cu cachedBases ifNil: [cu cachedBases := cu calculateBases]
422 cu@(ComplexUnit traits) calculateBases
423 [| bases unitDict newUs newExpons scratch |
424   cu unitsAndExponentsDo: [| :unit :expon |
425     bases := unit bases.
426     bases unitsAndExponentsDo: [| :subunit :subexpon |
427       scratch := subexpon * expon.
428       (unitDict includesKey: subunit)
429         ifTrue: [unitDict at: subunit := (unitDict at: subunit) + scratch]
430         ifFalse: [unitDict at: subunit := scratch]]].
431   newUs := ExtensibleArray new.
432   newExpons := ExtensibleArray new.
433   (unitDict keySet sortedBy: [| :l :r | l abbrev < r abbrev])
434     do: [| :unit |
435       scratch := unitDict at: unit.
436       scratch isZero ifFalse: [newUs add: unit. newExpons add: scratch]].
437   CompoundUnit units: newUs exponents: newExpons
440 cu1@(ComplexUnit traits) isConsistentWith: cu2@(ComplexUnit traits)
442   cu1 bases isConsistentWith: cu2 bases
445 numerics define: #ModifiedUnit &parents: {Unit} &slots: {#base. #modification}.
447 "A base unit with a modification that makes it incompatible with anything
448 not having the same modification, good for domain-specific use.
449 e.g. 1.6 moles -> 1.6 moles of sulfuric acid. (Strings not required)"
451 mu@(ModifiedUnit traits) base: u modification: mod
452 [mu clone `setting: #{#base. #modification} to: {u. mod}].
454 ModifiedUnit traits compareAndHashUsingSlots: #{#base. #modification}.
456 mu@(ModifiedUnit traits) bases
458   mu
461 mu@(ModifiedUnit traits) conversionFactor
463   mu base conversionFactor
466 mu@(ModifiedUnit traits) modify: mod
468   mu base: mu modification: mod
471 mu@(ModifiedUnit traits) printOn: s@(PrettyPrinterMixin traits)
472 [| mod |
473   mu base printOn: s.
474   s ; '('.
475   ((mod := mu modification) is: String)
476     ifTrue: [s ; mod]
477     ifFalse: [mod printOn: s].
478   s ; ')'.
479   mu
482 mu@(ModifiedUnit traits) printFullOn: s@(PrettyPrinterMixin traits) plural: plural
483 [| mod |
484   mu base printFullOn: s plural: plural.
485   s ; '( of '.
486   ((mod := mu modification) is: String)
487     ifTrue: [s ; mod]
488     ifFalse: [mod printOn: s].
489   s ; ')'.
490   mu
493 mu@(ModifiedUnit traits) isConsistentWith: cu@(ComplexUnit traits)
495   mu isConsistentWith: cu bases
498 mu1@(ModifiedUnit traits) isConsistentWith: mu2@(ModifiedUnit traits)
500   mu1 base = mu2 base /\ [mu1 modification = mu2 modification]
503 numerics define: #PrefixedUnit &parents: {Unit} &slots: {#base. #prefix}.
505 "A Unit with an SI Prefix attached."
507 pu@(PrefixedUnit traits) prefix: prefix base: unit
508 [pu clone `setting: #{#prefix. #base} to: {prefix. unit}].
510 pu@(PrefixedUnit traits) prefixedBy: prefix
511 "Combine the prefixes."
512 [pu clone `setting: #{#prefix} to: {newPU prefix * prefix}].
514 pu@(PrefixedUnit traits) dimension [pu base dimension].
516 pu@(PrefixedUnit traits) isConsistentWith: u@(Unit traits)
518   pu base isConsistentWith: u
521 u@(Unit traits) isConsistentWith: pu@(PrefixedUnit traits)
523   pu base isConsistentWith: u
526 pu@(PrefixedUnit traits) conversionFactor
528   pu prefix scalingFactor * pu base conversionFactor
531 pu@(PrefixedUnit traits) printOn: s@(PrettyPrinterMixin traits)
533   s ; pu prefix abbrev.
534   pu base printOn: s.
535   pu
538 pu@(PrefixedUnit traits) printFullOn: s@(PrettyPrinterMixin traits) plural: plural
540   s ; pu prefix prefixName.
541   pu base printFullOn: s plural: plural.
542   pu
545 numerics define: #SIPrefix &parents: {Cloneable}
546   &slots: {#abbrev. #prefixName. #scalingFactor}.
547 "SI Prefixes:
548  http://physics.nist.gov/cuu/Units/prefixes.html
549  http://www.bipm.org/en/si/prefixes.html
550 Main SI site:
551  http://www.bipm.org/en/si/
552 A Standard interchange format for SI units and numbers
553  http://swiss.csail.mit.edu/~jaffer/MIXF/"
555 units ensureNamespace: #Prefixes.
556 units Prefixes ensureNamespace: #ByName &delegate: True.
557 units Prefixes ensureNamespace: #ByAbbrev &delegate: True.
559 sip@(SIPrefix traits) name: name abbrev: abbrev scalingFactor: n
560 [| newSIP |
561   newSIP := sip clone `setting: #{#abbrev. #prefixName. #scalingFactor}
562     to: {abbrev. name. n}.
563   units Prefixes ByName addImmutableSlot: name intern valued: newSIP.
564   units Prefixes ByAbbrev addImmutableSlot: abbrev intern valued: newSIP.
565   newSIP
568 sip@(SIPrefix traits) named: name
570   units SIPrefixesByName at: name intern
573 sip@(SIPrefix traits) abbrev: name
575   units SIPrefixesByAbbrev at: name intern
578 u@(Unit traits) prefixedBy: prefix@(SIPrefix traits)
580   PrefixedUnit prefix: prefix base: u
583 p1@(SIPrefix traits) * p2@(SIPrefix traits)
584 [| scalingFactor newSIP |
585   scalingFactor := p1 scalingFactor * p2 scalingFactor.
586   units SIPrefixesByName keysAndValuesDo: [| :key :value |
587     value scalingFactor = scalingFactor ifTrue: [^ value]].
588   Nil
591 SIPrefix name: 'yotta' abbrev: 'Y' scalingFactor: (10 raisedTo: 24).
592 SIPrefix name: 'zetta' abbrev: 'Z' scalingFactor: (10 raisedTo: 21).
593 SIPrefix name: 'exa' abbrev: 'E' scalingFactor: (10 raisedTo: 18).
594 SIPrefix name: 'peta' abbrev: 'P' scalingFactor: (10 raisedTo: 15).
595 SIPrefix name: 'tera' abbrev: 'T' scalingFactor: (10 raisedTo: 12).
596 SIPrefix name: 'giga' abbrev: 'G' scalingFactor: (10 raisedTo: 9).
597 SIPrefix name: 'mega' abbrev: 'M' scalingFactor: (10 raisedTo: 6).
598 SIPrefix name: 'kilo' abbrev: 'k' scalingFactor: (10 raisedTo: 3).
599 SIPrefix name: 'hecto' abbrev: 'h' scalingFactor: (10 raisedTo: 2).
600 SIPrefix name: 'deca' abbrev: 'da' scalingFactor: (10 raisedTo: 1).
601 SIPrefix name: 'deci' abbrev: 'd' scalingFactor: (10 raisedTo: -1).
602 SIPrefix name: 'centi' abbrev: 'c' scalingFactor: (10 raisedTo: -2).
603 SIPrefix name: 'milli' abbrev: 'm' scalingFactor: (10 raisedTo: -3).
604 SIPrefix name: 'micro' abbrev: 'u' scalingFactor: (10 raisedTo: -6).
605 SIPrefix name: 'nano' abbrev: 'n' scalingFactor: (10 raisedTo: -9).
606 SIPrefix name: 'pico' abbrev: 'p' scalingFactor: (10 raisedTo: -12).
607 SIPrefix name: 'atto' abbrev: 'a' scalingFactor: (10 raisedTo: -15).
608 SIPrefix name: 'femto' abbrev: 'f' scalingFactor: (10 raisedTo: -18).
609 SIPrefix name: 'zepto' abbrev: 'z' scalingFactor: (10 raisedTo: -21).
610 SIPrefix name: 'yocto' abbrev: 'y' scalingFactor: (10 raisedTo: -24).
612 numerics define: #NamedUnit &parents: {Unit}
613   &slots: {#abbrev. #unitName. #pluralName}.
615 nu@(NamedUnit traits) name: n1 abbrev: ab &plural: np
616 [nu clone `setting: #{#abbrev. #unitName. #pluralName}
617     to: {ab. n1. np ifNil: [n1 plural]}].
619 nu@(NamedUnit traits) printOn: s@(PrettyPrinterMixin traits)
621   s ; nu abbrev.
622   nu
625 nu@(NamedUnit traits) printFullOn: s@(PrettyPrinterMixin traits) plural: plural
627   plural ifTrue: [s ; nu unitName] ifFalse: [s ; nu pluralName].
628   nu
631 numerics define: #BaseUnit &parents: {NamedUnit}.
633 "Defines core SI units and allows for basic extension."
635 bu@(BaseUnit traits) modify: mod
637   ModifiedUnit base: bu modification: mod
640 bu@(BaseUnit traits) bases
641 [bu].
643 bu@(BaseUnit traits) conversionFactor
644 [1].
646 bu1@(BaseUnit traits) isConsistentWith: bu2@(BaseUnit traits)
647 [bu1 == bu2].
649 x@(UnitValue traits) / y@(Unit traits)
650 [x / (1 of: y)].
652 bu@(BaseUnit traits) isConsistentWith: cu@(ComplexUnit traits)
653 [bu isConsistentWith: cu bases].
655 cu@(CompoundUnit traits) isConsistentWith: cu2@(BaseUnit traits)
656 "Compound units always have a non-trivial set of units."
657 [False].
659 mu@(ModifiedUnit traits) isConsistentWith: bu@(BaseUnit traits)
660 [False].
662 bu@(BaseUnit traits) isConsistentWith: mu@(ModifiedUnit traits)
663 [False].
665 _@(ModifiedUnit traits) is: _@(BaseUnit traits)
666 "Modified units are effectively new bases."
667 [True].
669 units ensureNamespace: #SI &delegate: True.
670 units SI ensureNamespace: #ByName &delegate: True.
671 units SI ensureNamespace: #ByAbbrev &delegate: True.
672 units SI ensureNamespace: #ByPluralName &delegate: True.
674 bu@(BaseUnit traits) name: n1 abbrev: ab dimension: dimension &plural: np
675 [| newBU n1s nps abs |
676   np `defaultsTo: n1 plural.
677   newBU := bu name: n1 abbrev: ab &plural: np.
678   [| :n | n of: newBU] asMethod: n1 intern on: {Number traits}.
679   [| :n | n of: newBU] asMethod: ab intern on: {Number traits}.
680   newBU traits addImmutableSlot: #dimension valued: dimension.
681   units SI ByName addImmutableSlot: n1 intern valued: newBU.
682   units SI ByAbbrev addImmutableSlot: ab intern valued: newBU.
683   units SI ByPluralName addImmutableSlot: np intern valued: newBU.
684   newBU
687 BaseUnit name: 'gram' abbrev: 'g' dimension: Mass.
688 BaseUnit name: 'meter' abbrev: 'm' dimension: Length.
689 BaseUnit name: 'second' abbrev: 's' dimension: Time.
690 BaseUnit name: 'candela' abbrev: 'c' dimension: Count &plural: 'candela'.
691 BaseUnit name: 'mole' abbrev: 'mol' dimension: Count.
692 BaseUnit name: 'kelvin' abbrev: 'K' dimension: Temperature &plural: 'kelvin'.
694 bu@(BaseUnit traits) named: name
696   name intern sendTo: {units SI ByName}
699 bu@(BaseUnit traits) abbrev: name
701   name intern sendTo: {units SI ByAbbrev}
704 bu@(BaseUnit traits) pluralNamed: name
706   name intern sendTo: {units SI ByPluralName}
709 cu@(ComplexUnit traits) isConsistentWith: bu@(BaseUnit traits)
710 [bu isConsistentWith: cu bases].
712 numerics define: #DerivedUnit &parents: {NamedUnit} &slots: {#unitValue}.
714 d@(DerivedUnit traits) dimension [d unitValue dimension].
716 "This defines a unit in terms of powers of other units, plus a scalar."
718 units ensureNamespace: #ByName &delegate: True.
719 units ensureNamespace: #ByAbbrev &delegate: True.
720 units ensureNamespace: #ByPluralName &delegate: True.
722 du@(DerivedUnit traits) name: n1 abbrev: ab value: val &plural: np
723 [| newU |
724   np `defaultsTo: n1 plural.
725   newU := du name: n1 abbrev: ab &plural: np.
726   newU unitValue := val.
727   [| :n | n of: newU] asMethod: n1 intern on: {Number traits}.
728   [| :n | n of: newU] asMethod: ab intern on: {Number traits}.
729   units ByName addImmutableSlot: n1 intern valued: newU.
730   units ByAbbrev addImmutableSlot: ab intern valued: newU.
731   units ByPluralName addImmutableSlot: np intern valued: newU.
732   newU
735 du@(DerivedUnit traits) unit
737   du unitValue unit
740 du@(DerivedUnit traits) dimension
742   du unitValue dimension
745 du@(DerivedUnit traits) bases
747   du unitValue unit bases
750 du@(DerivedUnit traits) conversionFactor
752   du unitValue value * du unitValue unit conversionFactor
755 du@(DerivedUnit traits) isConsistentWith: bu@(BaseUnit traits)
757   bu isConsistentWith: du unit
760 bu@(BaseUnit traits) isConsistentWith: du@(DerivedUnit traits)
762   bu isConsistentWith: du unit
765 DerivedUnit
766   name: 'centimeter'
767   abbrev: 'cm'
768   value: (1 of: (units m prefixedBy: units Prefixes c)).
770 DerivedUnit
771   name: 'kilometer'
772   abbrev: 'km'
773   value: (1 of: (units m prefixedBy: units Prefixes k)).
775 DerivedUnit
776   name: 'kilogram'
777   abbrev: 'kg'
778   value: (1 of: (units g prefixedBy: units Prefixes k)).
780 DerivedUnit
781   name: 'inch'
782   abbrev: 'in'
783   value: (2.54 of: units cm).
785 DerivedUnit
786   name: 'foot'
787   abbrev: 'ft'
788   value: (12 of: units in)
789   &plural: 'feet'.
791 DerivedUnit
792   name: 'yard'
793   abbrev: 'yd'
794   value: (3 of: units ft).
796 DerivedUnit
797   name: 'mile'
798   abbrev: 'mi'
799   value: (5280 of: units ft).
801 DerivedUnit
802   name: 'acre'
803   abbrev: 'acre'
804   value: (4046.87260987 of: units m squared).
806 DerivedUnit
807   name: 'newton'
808   abbrev: 'N'
809   value: (1 of: units kg * units m / units s squared)
810   &plural: 'newtons'.
812 DerivedUnit
813   name: 'minute'
814   abbrev: 'min'
815   value: (60 of: units s).
817 DerivedUnit
818   name: 'hour'
819   abbrev: 'h'
820   value: (60 of: units min).
822 DerivedUnit
823   name: 'day'
824   abbrev: 'd'
825   value: (24 of: units h).
827 DerivedUnit
828   name: 'year'
829   abbrev: 'yr'
830   value: (365.242198781 of: units d).
832 DerivedUnit
833   name: 'hertz'
834   abbrev: 'Hz'
835   value: ((1 of: units s) raisedTo: -1)
836   &plural: 'hertz'.
838 numerics define: #TemperatureUnit &parents: {DerivedUnit}
839   &slots: {#additiveFactor}.
841 tu@(TemperatureUnit traits) name: n1 abbrev: ab value: val additiveFactor: af &plural: np
843   (tu name: n1 abbrev: ab value: val &plural: np) `>> [additiveFactor := af. ]
846 TemperatureUnit
847   name: 'degree Rankine'
848   abbrev: 'R'
849   value: (5 / 9 of: units K)
850   additiveFactor: 0
851   &plural: 'degrees Rankine'.
853 TemperatureUnit
854   name: 'degree Fahrenheit'
855   abbrev: 'F'
856   value: (5 / 9 of: units K)
857   additiveFactor: -459.67
858   &plural: 'degrees Fahrenheit'.
860 TemperatureUnit
861   name: 'degree Celsius'
862   abbrev: 'C'
863   value: (1 of: units K)
864   additiveFactor: -273.15
865   &plural: 'degrees Celsius'.