luv

Workshop wiki

semantics.lisp

arithmetic/semantics.lisp

system luv/arithmetic · 127 definitions · on GitHub

Semantic arithmetic independent of any one execution backend.

Specifications are compile-time boundary objects. Runtime scalar and vector lanes remain ordinary unboxed data; an arithmetic graph, field operation, or shader compiler asks this protocol whether its operations are meaningful before choosing a backend representation.

in-package#:luv.arithmetic
defclassfactor-product
factors:initarg:factors:readerfactor-product-factors
:documentation

Internal canonical representation shared by dimensions and exact units.

defclassdimension
:documentation

A canonical product of symbolic base dimensions raised to rational powers.

defundimension-factors
factor-product-factorsdimension
defunfactor-name
factor
let
symbol
carfactor
formatnil"~A::~A"
or
and
symbol-packagesymbol
package-name
symbol-packagesymbol
""
symbol-namesymbol
defuncanonical-factors
factors
let
powers
make-hash-table:test#'eq
dolist
factorfactors
let
base
carfactor
exponent
if
and
consp
cdrfactor
null
cddrfactor
secondfactor
cdrfactor
unless
and
symbolpbase
rationalpexponent
error"Invalid symbolic factor ~S."factor
incf
gethashbasepowers0
exponent
sort
loopforbasebeingthehash-keysofpowersusing
hash-valueexponent
unless
zeropexponent
collect
consbaseexponent
#'string<:key#'factor-name
defunmake-dimension
&optionaldesignator

Return a canonical dimension from NIL, one base symbol, or factor pairs.

Each factor pair has the form (BASE EXPONENT), where EXPONENT is rational.

etypecasedesignator
null
make-instance'dimension:factorsnil
dimensiondesignator
symbol
make-instance'dimension:factors
list
consdesignator1
list
make-instance'dimension:factors
defmethodprint-object
stream
print-unreadable-object
productstream:typet
if
factor-product-factorsproduct
formatstream"~{~A~^ ~}"
mapcar
lambda
factor
if
=
cdrfactor
1
carfactor
formatnil"~A^~A"
carfactor
cdrfactor
factor-product-factorsproduct
write-string"1"stream
defunfactor-product=
leftright
equal
factor-product-factorsleft
factor-product-factorsright
defuncombined-factors
leftright
append
factor-product-factorsleft
factor-product-factorsright
defunscaled-factors
productexponent
mapcar
lambda
factor
list
carfactor
*exponent
cdrfactor
factor-product-factorsproduct
defunexponentiate-dimension
dimensionexponent
unless
rationalpexponent
error"A dimension exponent must be rational, not ~S."exponent
defundivide-dimensions
numeratordenominator
define-conditionundefined-unit
error
name:initarg:name:readerundefined-unit-name
:report
lambda
conditionstream
formatstream"No semantic unit definition exists for ~S."
undefined-unit-namecondition
defclassunit-definition
name:initarg:name:readerunit-definition-name
dimension:initarg:dimension:readerunit-definition-dimension
magnitude:initarg:magnitude:readerunit-definition-magnitude
basis:initarg:basis:readerunit-definition-basis
identity-p:initarg:identity-p:initformnil:readerunit-definition-identity-p
quantity-kind:initarg:quantity-kind:readerunit-definition-quantity-kind
:documentation

A named linear unit with a dimension, canonical basis, scale, and kind.

defgenericunit-definition-for
name
:documentation

Return the semantic definition of unit name, or signal undefined-unit.

defmethodunit-definition-for
name
error'undefined-unit:namename
defclassunit-expression
:documentation

A canonical product of defined named units.

defununit-expression-factors
unit
factor-product-factorsunit
defunraw-unit-expression
factors
make-instance'unit-expression:factors
defunmake-unit-expression
&optionaldesignator

Return a canonical unit expression from NIL, a defined unit, or factors.

Every symbolic factor must have a semantic unit definition. Exact unit identity remains visible here; conversions are requested separately.

etypecasedesignator
null
make-instance'unit-expression:factorsnil
unit-expressiondesignator
symbol
let
if
unit-definition-identity-pdefinition
raw-unit-expression
list
consdesignator1
list
dolist
factordesignator
defunmap-unit-expression-factors
functionunitinitial-value
reduce
lambda
resultfactor
funcallfunctionresult
cdrfactor
:initial-valueinitial-value
defununit-expression-dimension
unit

Return the physical dimension implied by unit's definitions.

defununit-expression-magnitude
unit

Return unit's scale relative to its canonical basis.

map-unit-expression-factors
lambda
magnitudedefinitionexponent
*magnitude
expt
unit-definition-magnitudedefinition
exponent
unit1
defununit-expression-basis
unit

Return unit expressed only in canonical basis units.

defununit-conversion-factor
sourcetarget

Return the numerical factor converting source values into target values.

defunexponentiate-unit-expression
unitexponent
unless
rationalpexponent
error"A unit exponent must be rational, not ~S."exponent
defclassquantity-kind-definition
name:initarg:name:readerquantity-kind-definition-name
parent:initarg:parent:initformnil:readerquantity-kind-definition-parent
dimension:initarg:dimension:readerquantity-kind-definition-dimension
:documentation

One node in the semantic hierarchy of kinds sharing physical dimensions.

defgenericquantity-kind-definition-for
name
:documentation

Return the inspectable definition of quantity kind name.

defmethodquantity-kind-definition-for
name
declare
ignorename
nil
defmacrodefine-semantic-definition
functionnamevalue-form

Define name as one inspectable value behind an EQL-specialized function.

let
argument
gensym"NAME"
`
defmethod,function
,argument
eql,name
declare
ignore,argument
load-time-value,value-form
defunmake-quantity-kind-definition
namedimensionparent
unless
symbolpname
error"A quantity kind needs a symbolic name, not ~S."name
let
when
andparent
or
nullparent-definition
not
dimension=dimension
quantity-kind-definition-dimensionparent-definition
error"Quantity kind ~S needs a defined parent of the same dimension, not ~S."nameparent
make-instance'quantity-kind-definition:namename:dimensiondimension:parentparent
defmacrodefine-quantity-kind
name&keydimensionparent

Define a semantic quantity kind through an inspectable EQL method.

`
defunquantity-kind-subkind-p
kindancestor

Whether kind is ancestor or reaches it through declared parent kinds.

loopwithseen=nilforname=kindthen
quantity-kind-definition-parentdefinition
fordefinition=whilenamewhen
eqnameancestor
returntdo
when
or
membernameseen
pushnameseen
finally
deftypequantity-character

The affine role of a value: a location, a non-negative amount from a true zero, or a signed difference between two of either.

'
member:point:absolute:difference
defclassquantity-definition
name:initarg:name:readerquantity-definition-name
kind:initarg:kind:readerquantity-definition-kind
components:initarg:components:initformnil:readerquantity-definition-components

Non-negativity is a declared fact about the named quantity, never derived from an equation: a defining equation captures dimension, not sign domain. It makes the quantity's default character :absolute and lets a later interpretation promise a non-negative amount. No lowering emits a check for it.

non-negative-p:initarg:non-negative-p:initformnil:readerquantity-definition-non-negative-p
character:initarg:character:initform:difference:readerquantity-definition-character
:documentation

A domain quantity name, its unit kind, homogeneous components, and the affine character its specifications take unless a use site says otherwise.

defgenericquantity-definition-for
name
:documentation

Return the inspectable definition of quantity name, or NIL.

defmethodquantity-definition-for
name
declare
ignorename
nil
defunmake-quantity-definition
namekind&keycomponentsnon-negative-p
characternilcharacter-supplied-p
unless
and
symbolpname
symbolpkind
error"Quantity ~S needs a defined symbolic kind, not ~S."namekind
unless
and
every#'symbolpcomponents
=
lengthcomponents
length
remove-duplicatescomponents
not
membernamecomponents
error"Quantity ~S needs distinct symbolic component names, not ~S."namecomponents
let
character
cond
character-supplied-pcharacter
non-negative-p:absolute
t:difference
unless
typepcharacter'quantity-character
error"Quantity ~S needs a character of :POINT, :ABSOLUTE, or :DIFFERENCE, not ~S."namecharacter
when
andnon-negative-p
eqcharacter:point
error"Quantity ~S cannot be both non-negative and a point."name
make-instance'quantity-definition:namename:kindkind:components
copy-listcomponents
:non-negative-p
not
nullnon-negative-p
:charactercharacter
defmacrodefine-quantity
name&keykindcomponentsnon-negative-p
characternilcharacter-supplied-p

Define quantity name and any homogeneous components as members of kind.

non-negative-p declares a non-negative amount and defaults its character to :ABSOLUTE. character may state :POINT, :ABSOLUTE, or :DIFFERENCE explicitly. Components inherit both.

let
character-options
andcharacter-supplied-p`
:character,character
`
progn
define-semantic-definitionquantity-definition-for,name
make-quantity-definition,name,kind:components',components:non-negative-p,non-negative-p,@character-options
,@
loopforcomponentincomponentscollect`
define-semantic-definitionquantity-definition-for,component
make-quantity-definition,component,kind:non-negative-p,non-negative-p,@character-options
',name
defununit-designator-quantity-kind
unit

Return the kind constraint of one named unit, or NIL for a compound unit.

cond
symbolpunit
unit-definition-quantity-kind
t
let
and
=
lengthfactors
1
=
cdarfactors
1
unit-definition-quantity-kind
defunvalidate-unit-admissibility
quantity-nameunitunit-dimension
let
whenquantity-name
let*
actual-kind
andquantity
quantity-definition-kindquantity
kind-definition
andactual-kind
unlessquantity
quantity-operation-error'make-quantity-specification
listquantity-nameunit
:undefined-quantity-definition
unless
andkind-definition
dimension=unit-dimension
quantity-kind-definition-dimensionkind-definition
quantity-operation-error'make-quantity-specification
listquantity-nameunit
:quantity-kind-dimension-mismatch
when
andrequired-kind
not
quantity-kind-subkind-pactual-kindrequired-kind
quantity-operation-error'make-quantity-specification
listquantity-nameunit
:unit-not-admissible-for-quantity
defunmake-unit-definition
name&key
dimensionnildimension-supplied-p
referencenilreference-supplied-p
magnitude1
identity-pquantity-kind
unless
and
symbolpname
realpmagnitude
pluspmagnitude
error"A unit needs a symbolic name and positive real magnitude: ~S, ~S."namemagnitude
when
anddimension-supplied-preference-supplied-p
error"Unit ~S cannot define both a base dimension and a reference unit."name
unless
ordimension-supplied-preference-supplied-p
error"Unit ~S needs either :DIMENSION or :REFERENCE."name
when
andidentity-p
orreference-supplied-p
/=magnitude1
error"Identity unit ~S must be a dimension-one base of magnitude one."name
unless
and
symbolpquantity-kind
error"Unit ~S needs a defined :QUANTITY-KIND, not ~S."namequantity-kind
let*
reference-expression
andreference-supplied-p
effective-dimension
ifreference-expression
unit-expression-dimensionreference-expression
effective-magnitude
*magnitude
ifreference-expression
unit-expression-magnitudereference-expression
1
basis
cond
reference-expression
unit-expression-basisreference-expression
identity-p
t
raw-unit-expression
list
consname1
make-instance'unit-definition:namename:dimensioneffective-dimension:magnitudeeffective-magnitude:basisbasis:identity-p
not
nullidentity-p
:quantity-kindquantity-kind
defmacrodefine-unit
name&restoptions

Define name as a semantic linear unit through an inspectable EQL method.

`

The roots are intentionally small: application domains add named quantities beneath these kinds without teaching the arithmetic core their vocabulary.

define-quantity-kind:dimensionless:dimensionnil
define-quantity-kind:length:dimension:length
define-quantity-kind:duration:dimension:duration
define-quantity-kind:frequency:dimension
:duration-1
define-quantity-kind:proportion:dimensionnil:parent:dimensionless
define-quantity-kind:angular-measure:dimensionnil:parent:dimensionless
define-quantity-kind:solid-angular-measure:dimensionnil:parent:dimensionless

A compact ISQ/SI-inspired seed vocabulary. More units extend the same open protocol; an unknown spelling is an error rather than an anonymous factor.

define-unit:one:dimensionnil:identity-pt:quantity-kind:dimensionless
define-unit:percent:reference:one:magnitude1/100:quantity-kind:dimensionless
define-unit:per-mille:reference:one:magnitude1/1000:quantity-kind:dimensionless
define-unit:parts-per-million:reference:one:magnitude1/1000000:quantity-kind:dimensionless
define-unit:metre:dimension:length:quantity-kind:length
define-unit:kilometre:reference:metre:magnitude1000:quantity-kind:length
define-unit:second:dimension:duration:quantity-kind:duration
define-unit:hertz:reference'
:second-1
:quantity-kind:frequency
define-unit:radian:reference:one:quantity-kind:angular-measure
define-unit:steradian:reference:one:quantity-kind:solid-angular-measure

Canonical quantity names are useful at generic boundaries; applications normally add narrower names (opacity, texture coordinates, world distance) beneath the same kinds.

define-quantity:dimensionless:kind:dimensionless
define-quantity:proportion:kind:proportion
define-quantity:distance:kind:length
define-quantity:height:kind:length
define-quantity:width:kind:length
define-quantity:duration:kind:duration
define-quantity:frequency:kind:frequency
define-quantity:angle:kind:angular-measure
define-quantity:solid-angle:kind:solid-angular-measure
defclassquantity-specification
name:initarg:name:initformnil:readerquantity-specification-name
dimension:initarg:dimension:readerquantity-specification-dimension
unit:initarg:unit:readerquantity-specification-unit
kind:initarg:kind:initformnil:readerquantity-specification-kind
tensor-order:initarg:tensor-order:initform0:readerquantity-specification-tensor-order
character:initarg:character:initform:difference:readerquantity-specification-character
:documentation

The semantic meaning of a value, separate from its machine representation.

defunquantity-specification-affine-p
specification

Whether specification is an affine point; kept as the historical spelling.

eq
quantity-specification-characterspecification
:point
defunquantity-specification-absolute-p
specification
eq
quantity-specification-characterspecification
:absolute
defunquantity-specification-difference-p
specification
eq
quantity-specification-characterspecification
:difference
defunquantity-specification-non-negative-p
specification

Whether specification's named definition declares a non-negative amount.

Only a named absolute can promise this; anonymous derived results never do.

let*
name
quantity-specification-namespecification
anddefinition
quantity-definition-non-negative-pdefinition
defunresolve-quantity-character
namecharactercharacter-supplied-paffine-paffine-p-supplied-p

Choose a specification character from an explicit character, the historical affine-p spelling, or the named definition's default.

cond
andcharacter-supplied-paffine-p-supplied-p
not
eq
eqcharacter:point
not
nullaffine-p
error"Quantity ~S was given contradictory :CHARACTER ~S and :AFFINE-P ~S."namecharacteraffine-p
character-supplied-p
unless
typepcharacter'quantity-character
error"A quantity character must be :POINT, :ABSOLUTE, or :DIFFERENCE, not ~S."character
character
andaffine-p-supplied-paffine-p
:point
t

The definition supplies the default. An explicit :affine-p NIL says only "not a point": a declared absolute stays absolute, a declared point becomes a difference of that quantity.

let*
default
ifdefinition
quantity-definition-characterdefinition
:difference
if
andaffine-p-supplied-p
eqdefault:point
:differencedefault
defunmake-quantity-specification
name&key
dimensionnildimension-supplied-p
unit
tensor-order0
affine-pnilaffine-p-supplied-p
characternilcharacter-supplied-p
unless
typeptensor-order'
integer0*
error"A tensor order must be a non-negative integer, not ~S."tensor-order
let*
character
resolve-quantity-characternamecharactercharacter-supplied-paffine-paffine-p-supplied-p
unit-declares-dimension-p
unit-dimension
declared-dimension
effective-dimension
ifunit-declares-dimension-punit-dimensiondeclared-dimension
when
andunit-declares-dimension-pdimension-supplied-p
not
dimension=unit-dimensiondeclared-dimension
when
andkind-definition
not
dimension=effective-dimension
quantity-kind-definition-dimensionkind-definition
quantity-operation-error'make-quantity-specification
listnamedimensionunit
:quantity-kind-dimension-mismatch
whenunit-declares-dimension-p
validate-unit-admissibilitynameunitunit-dimension
make-instance'quantity-specification:namename:dimensioneffective-dimension:unitunit-expression:kind:tensor-ordertensor-order:charactercharacter
defmethodprint-object
stream
print-unreadable-object
specificationstream:typet
formatstream"~S~@[ <~S>~] ~A [~A] order ~D~@[ ~(~A~)~]"
quantity-specification-namespecification
quantity-specification-kindspecification
quantity-specification-dimensionspecification
quantity-specification-unitspecification
quantity-specification-tensor-orderspecification
let
character
quantity-specification-characterspecification
and
not
eqcharacter:difference
character
defunquantity-specification=
leftright
and
eq
quantity-specification-nameleft
quantity-specification-nameright
dimension=
quantity-specification-dimensionleft
quantity-specification-dimensionright
unit-expression=
quantity-specification-unitleft
quantity-specification-unitright
=
quantity-specification-tensor-orderleft
quantity-specification-tensor-orderright
eq
quantity-specification-characterleft
quantity-specification-characterright
defundimensionless-quantity-specification-p
specification&optionaltensor-order

Whether specification is linear, unitless, and optionally of tensor-order.

and
dimensionless-p
quantity-specification-dimensionspecification
unitless-p
quantity-specification-unitspecification
or
nulltensor-order
=tensor-order
quantity-specification-tensor-orderspecification
defuncopy-quantity-specification
source&key
name
quantity-specification-namesource
dimension
quantity-specification-dimensionsource
unit
quantity-specification-unitsource
tensor-order
quantity-specification-tensor-ordersource
character
quantity-specification-charactersource
character-supplied-p
affine-pnilaffine-p-supplied-p

Copy source, replacing only the explicitly supplied semantic fields.

character is the general control; the historical :affine-p keyword still sets or clears the point character.

make-quantity-specificationname:dimensiondimension:unitunit:tensor-ordertensor-order:character
cond
character-supplied-pcharacter
andaffine-p-supplied-paffine-p
:point
andaffine-p-supplied-p
eqcharacter:point
:difference
tcharacter
defclassquantity-projection
positions:initarg:positions:readerquantity-projection-positions
specification:initarg:specification:readerquantity-projection-specification
:documentation

One quantity occupying selected positions of a composite representation.

defunmake-quantity-projection
positionsspecification
unless
and
consppositions
every
lambda
typepposition'
integer0*
positions
=
lengthpositions
length
remove-duplicatespositions
error"Quantity projection positions must be distinct non-negative integers, not ~S."positions
check-typespecificationquantity-specification
make-instance'quantity-projection:positions
copy-listpositions
:specificationspecification
defclassquantity-layout
extent:initarg:extent:readerquantity-layout-extent
projections:initarg:projections:readerquantity-layout-projections
:documentation

Semantic quantities packed into disjoint positions of one representation.

defclassrepeated-quantity-layout
element-layout:initarg:element-layout:readerrepeated-quantity-layout-element-layout
stride:initarg:stride:readerrepeated-quantity-layout-stride
:documentation

A fixed product repeated through flat storage at a physical lane stride.

The inherited extent and projections describe one stride period so existing projection tools continue to inspect an element. ELEMENT-LAYOUT retains the unpadded product definition; no runtime element object is implied.

defunmake-quantity-layout
extentprojections
unless
typepextent'
integer1*
error"A quantity layout extent must be a positive integer, not ~S."extent
let
occupiednil
dolist
projectionprojections
check-typeprojectionquantity-projection
dolist
position
quantity-projection-positionsprojection
unless
<positionextent
error"Quantity projection position ~D is outside extent ~D."positionextent
when
memberpositionoccupied
error"Quantity layout position ~D is specified more than once."position
pushpositionoccupied
make-instance'quantity-layout:extentextent:projections
copy-listprojections
defunmake-repeated-quantity-layout
element-layout&keystride

Repeat element-layout through flat storage, optionally with lane padding.

check-typeelement-layoutquantity-layout
when
typepelement-layout'repeated-quantity-layout
error"A repeated quantity layout needs a fixed product element, not ~S."element-layout
let
physical-stride
orstride
quantity-layout-extentelement-layout
unless
and
typepphysical-stride'
integer1*
>=physical-stride
quantity-layout-extentelement-layout
error"Repeated layout stride ~S is smaller than element extent ~D."physical-stride
quantity-layout-extentelement-layout
make-instance'repeated-quantity-layout:extentphysical-stride:projections
copy-list
quantity-layout-projectionselement-layout
:element-layoutelement-layout:stridephysical-stride
defmethodprint-object
print-unreadable-object
layoutstream:typet
formatstream"~D lanes: ~{~S~^, ~}"
quantity-layout-extentlayout
mapcar
lambda
projection
list
quantity-projection-positionsprojection
quantity-specification-name
quantity-projection-specificationprojection
quantity-layout-projectionslayout
defmethodprint-object
print-unreadable-object
layoutstream:typet
formatstream"~S every ~D lanes"
repeated-quantity-layout-element-layoutlayout
repeated-quantity-layout-stridelayout
defunquantity-layout=
leftright
let
left-repeated-p
right-repeated-p
cond
andleft-repeated-pright-repeated-p
and
=
repeated-quantity-layout-strideleft
repeated-quantity-layout-strideright
quantity-layout=
repeated-quantity-layout-element-layoutleft
repeated-quantity-layout-element-layoutright
orleft-repeated-pright-repeated-p
nil
t
and
=
quantity-layout-extentleft
quantity-layout-extentright
=
length
quantity-layout-projectionsleft
length
quantity-layout-projectionsright
every
lambda
left-projection
let
right-projection
find
quantity-projection-positionsleft-projection
quantity-layout-projectionsright
:test#'equal:key#'quantity-projection-positions
andright-projection
quantity-specification=
quantity-projection-specificationleft-projection
quantity-projection-specificationright-projection
quantity-layout-projectionsleft
defunproject-quantity-layout
layoutpositions

Return the quantity exactly occupying positions in layout, or NIL.

let*
element-layout
if
repeated-quantity-layout-element-layoutlayout
layout
projection
findpositions
quantity-layout-projectionselement-layout
:test#'equal:key#'quantity-projection-positions
andprojection
quantity-projection-specificationprojection
defunquantity-component-names
quantity-name

Return the ordered homogeneous components declared for quantity-name.

let
anddefinition
quantity-definition-componentsdefinition
defunproject-quantity-specification
specificationpositionsextent

Derive the quantity selected from a homogeneous represented quantity.

Selecting every position in order preserves the whole. A single component of an anonymous quantity remains anonymous. A named quantity must explicitly publish ordered component names; no default silently calls one axis the whole.

check-typespecificationquantity-specification
cond
equalpositions
loopforpositionbelowextentcollectposition
specification
=
lengthpositions
1
let*
whole-name
quantity-specification-namespecification
component-names
andwhole-name
position
firstpositions
component-name
and
<position
lengthcomponent-names
nthpositioncomponent-names
when
andwhole-name
nullcomponent-name
quantity-operation-error'project
listspecificationpositions
:missing-quantity-component-definition
copy-quantity-specificationspecification:namecomponent-name:tensor-order0
t
quantity-operation-error'project
listspecificationpositions
:missing-quantity-projection-definition
define-conditionquantity-operation-error
error
operator:initarg:operator:readerquantity-operation-error-operator
specifications:initarg:specifications:readerquantity-operation-error-specifications
reason:initarg:reason:readerquantity-operation-error-reason
:report
lambda
conditionstream
formatstream"Cannot derive ~S over quantity specifications ~S: ~A."
quantity-operation-error-operatorcondition
quantity-operation-error-specificationscondition
quantity-operation-error-reasoncondition
defunquantity-operation-error
operatorspecificationsreason
error'quantity-operation-error:operatoroperator:specificationsspecifications:reasonreason
defunsame-quantity-space-p
leftright
and
eq
quantity-specification-nameleft
quantity-specification-nameright
dimension=
quantity-specification-dimensionleft
quantity-specification-dimensionright
=
quantity-specification-tensor-orderleft
quantity-specification-tensor-orderright
defunderived-specification
dimensionunittensor-order
make-quantity-specificationnil:dimensiondimension:unitunit:tensor-ordertensor-order
defunscalar-number-specification-p
specification
and
null
quantity-specification-namespecification
defunadditive-pair
operatorleftright
unless
quantity-operation-erroroperator
listleftright
:different-quantity-spaces
unless
unit-expression=
quantity-specification-unitleft
quantity-specification-unitright
quantity-operation-erroroperator
listleftright
:different-units

The affine table over point, absolute, and difference. A point is a location; an absolute is an amount from a true zero, forming a cone; a difference is signed. Adding a difference to an absolute keeps the zero anchor, so the result stays absolute; subtracting two absolutes yields a signed difference, and only an explicit interpretation recovers an absolute from it.

let
left-character
quantity-specification-characterleft
right-character
quantity-specification-characterright
flet
result
character
copy-quantity-specificationleft:charactercharacter
fail
reason
quantity-operation-erroroperator
listleftright
reason
ecaseoperator
+
cond
and
eqleft-character:point
eqright-character:point
fail:cannot-add-points
or
eqleft-character:point
eqright-character:point
result:point
or
eqleft-character:absolute
eqright-character:absolute
result:absolute
t
result:difference
-
cond
eqleft-character:point
result
if
eqright-character:point
:difference:point
eqright-character:point
fail:cannot-subtract-point-from-amount
and
eqleft-character:absolute
eqright-character:difference
result:absolute
t
result:difference
defunproduct-tensor-order
operatorleftright
let
left-order
quantity-specification-tensor-orderleft
right-order
quantity-specification-tensor-orderright
cond
zeropleft-order
right-order
zeropright-order
left-order
=left-orderright-order
left-order
t
quantity-operation-erroroperator
listleftright
:incompatible-tensor-orders
defunproduct-character
leftright

Products and quotients of two absolutes remain absolute; any signed factor makes the result a difference. Points never enter these operations.

if
and
eq
quantity-specification-characterleft
:absolute
eq
quantity-specification-characterright
:absolute
:absolute:difference
defunmultiplicative-pair
operatorleftright
when
quantity-operation-erroroperator
listleftright
:cannot-scale-affine-point

A bare number is a pure scale factor and preserves the other operand's character, so twice an amount is still an amount.

cond
t
copy-quantity-specification
derived-specification
multiply-dimensions
quantity-specification-dimensionleft
quantity-specification-dimensionright
multiply-unit-expressions
quantity-specification-unitleft
quantity-specification-unitright
product-tensor-orderoperatorleftright
:character
defuncompatible-pair
operatorleftright
unless
quantity-operation-erroroperator
listleftright
if
unit-expression=
quantity-specification-unitleft
quantity-specification-unitright
:incompatible-quantities:different-units
left
defuninterpret-quantity-specification
derivedinterpretation

Give a compatible anonymous derived specification an explicit meaning.

This is a semantic interpretation, never a numerical unit conversion. An already named quantity may only retain its name; anonymous derived results may acquire one when their dimension, exact unit, and tensor order agree with interpretation. Character must agree too, with one deliberate exception: a signed difference may be interpreted as an absolute. That is the explicit promotion the affine algebra otherwise never performs — the author asserts the amount is non-negative, and no lowering checks it (#PLRP3A). Points never cross to or from the other characters here.

unless
andderived
or
null
quantity-specification-namederived
eq
quantity-specification-namederived
quantity-specification-nameinterpretation
dimension=
quantity-specification-dimensionderived
quantity-specification-dimensioninterpretation
unit-expression=
quantity-specification-unitderived
quantity-specification-unitinterpretation
=
quantity-specification-tensor-orderderived
quantity-specification-tensor-orderinterpretation
let
from
quantity-specification-characterderived
to
quantity-specification-characterinterpretation
or
eqfromto
and
eqfrom:difference
eqto:absolute
quantity-operation-error'interpret
listderivedinterpretation
:incompatible-interpretation
interpretation
defunconvert-quantity-specification-unit
sourcetarget-unit

Return source expressed in target-unit and its required numeric factor.

The operation preserves semantic name, dimension, tensor order, and affine character. It is a linear unit conversion, not a semantic interpretation.

check-typesourcequantity-specification
let*
target-unit
factor
unit-conversion-factor
quantity-specification-unitsource
target-unit
target-dimension
unless
dimension=
quantity-specification-dimensionsource
target-dimension
quantity-operation-error'convert-unit
listsourcetarget-unit
:incompatible-dimensions
values
copy-quantity-specificationsource:dimensiontarget-dimension:unittarget-unit
factor
defgenericderive-quantity-specification
operator&restoperands
:documentation

Derive the semantic result of applying operator to quantity operands.

defmethodderive-quantity-specification
operator&restoperands
quantity-operation-erroroperatoroperands:unknown-operator
defunreduce-quantity-specifications
operatoroperandspair-function&optional
minimum1
when
<
lengthoperands
minimum
quantity-operation-erroroperatoroperands:missing-operands
reduce
lambda
leftright
funcallpair-functionoperatorleftright
operands
defmethodderive-quantity-specification
operator
eql'+
&restoperands
defmethodderive-quantity-specification
operator
eql'-
&restoperands
unlessoperands
quantity-operation-erroroperatoroperands:missing-operands
if
=
lengthoperands
1
let
operand
firstoperands

Negating an amount is never an amount. The source leaves open whether it errors or demotes to a difference; luv errors, so the demotion is a visible mark (subtract from zero, or interpret) rather than a silent character change.

case
quantity-specification-characteroperand
:point
quantity-operation-erroroperatoroperands:cannot-negate-point
:absolute
quantity-operation-erroroperatoroperands:cannot-negate-amount
operand
reduce
lambda
leftright
additive-pairoperatorleftright
restoperands
:initial-value
firstoperands
defmethodderive-quantity-specification
operator
eql'/
&restoperands
unless
=
lengthoperands
2
quantity-operation-erroroperatoroperands:division-arity
destructuring-bind
numeratordenominator
operands
when
quantity-operation-erroroperatoroperands:cannot-divide-affine-point
ifnumerator
copy-quantity-specification
derived-specification
divide-dimensions
quantity-specification-dimensionnumerator
quantity-specification-dimensiondenominator
divide-unit-expressions
quantity-specification-unitnumerator
quantity-specification-unitdenominator
product-tensor-orderoperatornumeratordenominator
:character
product-characternumeratordenominator
defmethodderive-quantity-specification
operator
eql'dot
&restoperands
unless
=
lengthoperands
2
quantity-operation-erroroperatoroperands:dot-arity
destructuring-bind
leftright
operands
when
or
/=
quantity-specification-tensor-orderleft
1
/=
quantity-specification-tensor-orderright
1
quantity-operation-erroroperatoroperands:dot-requires-vectors
derived-specification
multiply-dimensions
quantity-specification-dimensionleft
quantity-specification-dimensionright
multiply-unit-expressions
quantity-specification-unitleft
quantity-specification-unitright
0
defmethodderive-quantity-specification
operator
eql'min
&restoperands
defmethodderive-quantity-specification
operator
eql'max
&restoperands

Portable numerical operators extend the same open semantic protocol as Common Lisp arithmetic. Execution backends remain responsible for their representations and implementations; these methods state only the lawful quantity relationship.

defmethodderive-quantity-specification
operator
eql'clamp
&restoperands
unless
=
lengthoperands
3
quantity-operation-erroroperatoroperands:clamp-arity
defmethodderive-quantity-specification
operator
eql'step
&restoperands
unless
=
lengthoperands
2
quantity-operation-erroroperatoroperands:step-arity
let
compatible
make-quantity-specificationnil:tensor-order
quantity-specification-tensor-ordercompatible
defmethodderive-quantity-specification
operator
eql'mix
&restoperands
unless
=
lengthoperands
3
quantity-operation-erroroperatoroperands:mix-arity
destructuring-bind
fromtoamount
operands
let
unless
quantity-operation-erroroperatoroperands:mix-requires-dimensionless-scalar-amount
result
defmethodderive-quantity-specification
operator
&restoperands
unless
=
lengthoperands
3
quantity-operation-erroroperatoroperands:smoothstep-arity
let
compatible
make-quantity-specificationnil:tensor-order
quantity-specification-tensor-ordercompatible
defmethodderive-quantity-specification
operator
&restoperands
unless
=
lengthoperands
1
quantity-operation-erroroperatoroperands:normalize-arity
let
operand
firstoperands
unless
quantity-operation-erroroperatoroperands:normalize-requires-dimensionless-vector
operand
defmethodderive-quantity-specification
operator
eql'expt
&restoperands
unless
=
lengthoperands
2
quantity-operation-erroroperatoroperands:expt-arity
destructuring-bind
baseexponent
operands
unless
quantity-operation-erroroperatoroperands:expt-requires-dimensionless-operands
make-quantity-specificationnil:tensor-order
quantity-specification-tensor-orderbase