See also the page named to Units and Dimensions.
On Monday, August 22, 2005 8:20 AM Martin Rubey wrote:
In private communication, we developed the domain below, but your idea
is conceptually better, I think. The full blown thing would then be a
category Units, that has as domains Mass, Time, Length, ... I suppose.
fricas
(1) -> <spad>
fricas
)abbrev domain UNITS Units
Units(R: Field): Exports == Implementation where
  U == Fraction Polynomial Integer
  Exports == with
    "*": (%,%) -> %
    "+": (%,%) -> %
    coerce: % -> OutputForm
    withUnits: (R, U)  -> %
    setUnitSystem!: String -> String
  Implementation == add
    Rep := Record(expr: R, units: U) 
    system: String := "MKS"
    setUnitSystem! s == 
      t := system
      system := s
      t
    transform: U -> Record(scalar: R, units: U)
    transform u ==
      m := 'm::Symbol::Polynomial(Integer)::U
      v := u
      if system = "MKS"
      then v := eval(u, ['cm,        'dm], _
                        [m*1/100::U, m*1/10::U])$RationalFunction(Integer)
      s: Fraction Integer := leadingCoefficient(numer(v)) _
                           / leadingCoefficient(denom(v))
      r: U := leadingMonomial(numer(v))::U _
            / leadingMonomial(denom(v))::U _
            / s ::U
      [s::R, r]
    withUnits(e, u) == [e, u]::Rep
    x * y  == [(x::Rep).expr * (y::Rep).expr, (x::Rep).units * (y::Rep).units]
    x + y  == 
      ux := transform((x::Rep).units)
      uy := transform((y::Rep).units)
      if ux.units = uy.units
      then [(x::Rep).expr*ux.scalar + (y::Rep).expr*uy.scalar, ux.units]
      else error "+: Units have to match"
    coerce x == coerce((x::Rep).expr)$R * coerce((x::Rep).units)$U</spad>
fricas
Compiling FriCAS source code from file 
      /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/884360936492130004-25px001.spad
      using old system compiler.
   UNITS abbreviates domain Units 
------------------------------------------------------------------------
   initializing NRLIB UNITS for Units 
   compiling into NRLIB UNITS 
   compiling exported setUnitSystem! : String -> String
Time: 0.01 SEC.
   compiling local transform : Fraction Polynomial Integer -> Record(scalar: R,units: Fraction Polynomial Integer)
Time: 0.03 SEC.
   compiling exported withUnits : (R,Fraction Polynomial Integer) -> %
      UNITS;withUnits;RF%;3 is replaced by CONS 
Time: 0 SEC.
   compiling exported * : (%,%) -> %
Time: 0 SEC.
   compiling exported + : (%,%) -> %
Time: 0 SEC.
   compiling exported coerce : % -> OutputForm
Time: 0 SEC.
(time taken in buildFunctor:  0)
Time: 0 SEC.
   Cumulative Statistics for Constructor Units
      Time: 0.05 seconds
   finalizing NRLIB UNITS 
   Processing Units for Browser database:
--->-->Units(constructor): Not documented!!!!
--->-->Units((* (% % %))): Not documented!!!!
--->-->Units((+ (% % %))): Not documented!!!!
--->-->Units((coerce ((OutputForm) %))): Not documented!!!!
--->-->Units((withUnits (% R (Fraction (Polynomial (Integer)))))): Not documented!!!!
--->-->Units((setUnitSystem! ((String) (String)))): Not documented!!!!
--->-->Units(): Missing Description
; compiling file "/var/aw/var/LatexWiki/UNITS.NRLIB/UNITS.lsp" (written 08 AUG 2025 01:55:47 AM):
; wrote /var/aw/var/LatexWiki/UNITS.NRLIB/UNITS.fasl
; compilation finished in 0:00:00.016
------------------------------------------------------------------------
   Units is now explicitly exposed in frame initial 
   Units will be automatically loaded when needed from 
      /var/aw/var/LatexWiki/UNITS.NRLIB/UNITS 
For example:
fricas
x:=withUnits(2.1,m)
Type: Units(Float)
fricas
y:=withUnits(3.2,s)
Type: Units(Float)
fricas
x*y
Type: Units(Float)
fricas
z:=withUnits(z::Polynomial Float,kg)
Type: Units(Fraction(Polynomial(Float)))
fricas
z*z
Type: Units(Fraction(Polynomial(Float)))