luv

Workshop wiki

compiler.lisp

arithmetic/lisp/compiler.lisp

system luv/arithmetic · 92 definitions · on GitHub

Common Lisp realization of backend-neutral compiled arithmetic.

Semantic checking has already happened in luv.ARITHMETIC.LANGUAGE. This file erases quantity boundaries into ordinary numerical code and compiles the resulting lambda. Runtime values are numbers and vectors, never quantity wrappers.

in-package#:luv.arithmetic.lisp
define-conditionlisp-arithmetic-error
error
definition:initarg:definition:initformnil:readerlisp-arithmetic-error-definition
expression:initarg:expression:initformnil:readerlisp-arithmetic-error-expression
reason:initarg:reason:readerlisp-arithmetic-error-reason
details:initarg:details:initformnil:readerlisp-arithmetic-error-details
:report
lambda
conditionstream
formatstream"Cannot realize arithmetic~@[ function ~S~]~@[ expression ~S~] in Lisp: ~A~@[ (~S)~]."
let
definition
lisp-arithmetic-error-definitioncondition
anddefinition
lang:arithmetic-object-namedefinition
let
expression
lisp-arithmetic-error-expressioncondition
lisp-arithmetic-error-reasoncondition
lisp-arithmetic-error-detailscondition
defunlisp-vector-length
leftright
unless
=
lengthleft
lengthright
error'lisp-arithmetic-error:reason:different-vector-lengths:details
list
lengthleft
lengthright
lengthleft
defunmap-lisp-vector
functionvector
let*
result
make-arraylength
dotimes
indexlengthresult
setf
arefresultindex
funcallfunction
arefvectorindex
defunmap-lisp-vectors
functionleftright
let*
result
make-arraylength
dotimes
indexlengthresult
setf
arefresultindex
funcallfunction
arefleftindex
arefrightindex
defgenericlisp-binary-operation
functionleftright
:documentation

Apply scalar function componentwise to two Lisp representations.

defmethodlisp-binary-operation
function
leftnumber
rightnumber
funcallfunctionleftright
defmethodlisp-binary-operation
function
leftvector
rightvector
defmethodlisp-binary-operation
function
leftvector
rightnumber
map-lisp-vector
lambda
component
funcallfunctioncomponentright
left
defmethodlisp-binary-operation
function
leftnumber
rightvector
map-lisp-vector
lambda
component
funcallfunctionleftcomponent
right
defmethodlisp-binary-operation
functionleftright
declare
ignorefunction
error'lisp-arithmetic-error:reason:unsupported-runtime-representations:details
list
type-ofleft
type-ofright
defgenericlisp-unary-operation
:documentation

Apply scalar function componentwise to one Lisp representation.

defmethodlisp-unary-operation
function
valuenumber
funcallfunctionvalue
defmethodlisp-unary-operation
declare
ignorefunction
error'lisp-arithmetic-error:reason:unsupported-runtime-representation:details
type-ofvalue
defunreduce-lisp-operation
functionoperandsidentity
ifoperands
reduce
lambda
leftright
restoperands
:initial-value
firstoperands
identity
defunlisp-add
&restoperands
defunlisp-subtract
&restoperands
unlessoperands
error'lisp-arithmetic-error:reason:subtraction-requires-operands
if
restoperands
lisp-binary-operation#'-0
firstoperands
defunlisp-multiply
&restoperands
defunlisp-divide
&restoperands
unlessoperands
error'lisp-arithmetic-error:reason:division-requires-operands
if
restoperands
lisp-binary-operation#'/1
firstoperands
defunlisp-min
&restoperands
unlessoperands
error'lisp-arithmetic-error:reason:minimum-requires-operands
defunlisp-max
&restoperands
unlessoperands
error'lisp-arithmetic-error:reason:maximum-requires-operands
defunlisp-expt
baseexponent
defgenericlisp-dot
leftright
defmethodlisp-dot
leftvector
rightvector
let
result0
dotimes
indexlengthresult
incfresult
*
arefleftindex
arefrightindex
defmethodlisp-dot
leftright
error'lisp-arithmetic-error:reason:dot-requires-vectors:details
list
type-ofleft
type-ofright
defunlisp-clamp
valuelowerupper
defunlisp-mix
fromtoamount
defunzero-like-number
number
if
floatpnumber
float0number
0
defunone-like-number
number
if
floatpnumber
float1number
1
defunlisp-step
edgevalue
lisp-binary-operation
lambda
edge-componentvalue-component
if
<value-componentedge-component
zero-like-numbervalue-component
one-like-numbervalue-component
edgevalue
defunlisp-smoothstep
loweruppervalue
let
lisp-multiplyprogressprogress
defgenericlisp-normalize
vector
defmethodlisp-normalize
vectorvector
let
magnitude
sqrt
lisp-dotvectorvector
lisp-dividevectormagnitude
defmethodlisp-normalize
vector
error'lisp-arithmetic-error:reason:normalize-requires-vector:details
type-ofvector
defgenericlisp-arithmetic-operator-function
operator
:documentation

Return the ordinary Lisp function name implementing operator.

defmethodlisp-arithmetic-operator-function
operator
error'lisp-arithmetic-error:reason:unsupported-operator:detailsoperator
defmacrodefine-lisp-arithmetic-operator
operatorfunction
`
defmethodlisp-arithmetic-operator-function
operator
eql',operator
declare
ignoreoperator
',function

Scalar lowering. The generic realization above dispatches on numbers versus vectors at run time so one compiled function can serve every representation. A hot loop whose operands are known scalars wants the ordinary Common Lisp operators instead, so that declared integer or float types flow through the emitted arithmetic. The choice is made once, by the caller lowering an expression, and never per operation.

defvar*lisp-arithmetic-lowering*:generic

How lower-lisp-arithmetic-expression emits calls: :GENERIC uses the representation-dispatching lisp-add family; :SCALAR emits CL operators over declared scalar operands. #53Q1II

defgenericlisp-scalar-operator-form
operatoroperands
:documentation

Return the scalar Lisp form applying operator to lowered scalar operands.

defmethodlisp-scalar-operator-form
operatoroperands
declare
ignoreoperands
error'lisp-arithmetic-error:reason:unsupported-scalar-operator:detailsoperator
defmacrodefine-lisp-scalar-operator
operatorlambda-list&bodybody

Define operator's scalar lowering from its lowered operand forms.

let
operator-variable
gensym"OPERATOR"
operands
gensym"OPERANDS"
`
defmethodlisp-scalar-operator-form
,operator-variable
eql',operator
,operands
declare
ignore,operator-variable
destructuring-bind,lambda-list,operands,@body
macrolet
direct
&restoperators
`
progn,@
loopforoperatorinoperatorscollect`
define-lisp-scalar-operator,operator
&restoperands
cons',operatoroperands
define-lisp-scalar-operatorclamp
valuelowerupper
`
min
max,value,lower
,upper
define-lisp-scalar-operatormix
fromtoamount
let
from-name
gensym"FROM"
`
let
,from-name,from
+,from-name
*
-,to,from-name
,amount
define-lisp-scalar-operatorstep
edgevalue
`
if
<,value,edge
01
define-lisp-scalar-operatorsmoothstep
loweruppervalue
let
progress
gensym"PROGRESS"
lower-name
gensym"LOWER"
`
let*
,lower-name,lower
,progress
min
max
/
-,value,lower-name
-,upper,lower-name
0
1
*,progress,progress
-3
*2,progress
defunlisp-environment-value
targetenvironmentexpression
or
cdr
assoctargetenvironment:test#'eq
error'lisp-arithmetic-error:expressionexpression:reason:unbound-expression-target:details
defgenericlower-lisp-arithmetic-expression
expressionenvironment
:documentation

Lower checked expression to ordinary Lisp using target-to-name environment.

defmethodlower-lisp-arithmetic-expression
environment
declare
ignoreenvironment
lang:arithmetic-literal-valueexpression
defmethodlower-lisp-arithmetic-expression
environment
lisp-environment-value
lang:arithmetic-reference-targetexpression
environmentexpression
defmethodlower-lisp-arithmetic-expression
environment
when
lang:arithmetic-call-parametersexpression
error'lisp-arithmetic-error:expressionexpression:reason:unsupported-call-parameters:details
lang:arithmetic-call-parametersexpression
let
operator
lang:arithmetic-call-operatorexpression
operands
mapcar
lambda
operand
lang:arithmetic-call-operandsexpression
ecase*lisp-arithmetic-lowering*
:generic
:scalar
defmethodlower-lisp-arithmetic-expression
environment
`
if,
lower-lisp-arithmetic-expression
lang:arithmetic-conditional-conditionexpression
environment
,
lower-lisp-arithmetic-expression
lang:arithmetic-conditional-consequentexpression
environment
,
lower-lisp-arithmetic-expression
lang:arithmetic-conditional-alternativeexpression
environment
defmethodlower-lisp-arithmetic-expression

Construction, assumption, interpretation, and representation are all compile-time semantic boundaries. Their runtime representation is the operand itself.

lower-lisp-arithmetic-expression
lang:arithmetic-quantity-boundary-operandexpression
environment
defmethodlower-lisp-arithmetic-expression
environment
let
operand
lower-lisp-arithmetic-expression
lang:arithmetic-unit-conversion-operandexpression
environment
factor
lang:arithmetic-unit-conversion-factorexpression
if
=factor1
operand
ecase*lisp-arithmetic-lowering*
:generic
list'lisp-multiplyfactoroperand
:scalar
list'*factoroperand
defmethodlower-lisp-arithmetic-expression
environment
let
call-environmentenvironment
lambda-bindingsnil
dolist
binding
lang:arithmetic-function-call-bindingsexpression
let*
value
lower-lisp-arithmetic-expression
lang:arithmetic-binding-expressionbinding
ifenvironmentcall-environment
name
gensym
formatnil"~A-"
lang:arithmetic-object-namebinding
push
listnamevalue
lambda-bindings
push
consbindingname
call-environment
let
result
lower-lisp-arithmetic-expression
lang:arithmetic-function-call-resultexpression
call-environment
`
let*,
nreverselambda-bindings
,result
defmethodlower-lisp-arithmetic-expression
environment
let*
index-name
gensym"INDEX-"
state-name
gensym"STATE-"
count
lower-lisp-arithmetic-expression
lang:arithmetic-counted-fold-countexpression
environment
initial
lower-lisp-arithmetic-expression
lang:arithmetic-counted-fold-initialexpression
environment
fold-environment
list*
cons
lang:arithmetic-counted-fold-index-bindingexpression
index-name
cons
lang:arithmetic-counted-fold-state-bindingexpression
state-name
environment
update-environmentfold-environment
update-bindingsnil
dolist
binding
lang:arithmetic-counted-fold-bindingsexpression
let
name
gensym
formatnil"~A-"
lang:arithmetic-object-namebinding
value
lower-lisp-arithmetic-expression
lang:arithmetic-binding-expressionbinding
update-environment
push
listnamevalue
update-bindings
push
consbindingname
update-environment
let
update
lower-lisp-arithmetic-expression
lang:arithmetic-counted-fold-updateexpression
update-environment
until
let
until
lang:arithmetic-counted-fold-untilexpression
anduntil
`
let
,state-name,initial
dotimes
,index-name,count,state-name
,@
whenuntil`
when,until
return,state-name
let*,
nreverseupdate-bindings
setf,state-name,update
defunarithmetic-definition-for-lisp
name
or
error'lisp-arithmetic-error:reason:undefined-arithmetic-function:detailsname
defgenericlower-arithmetic-function
:documentation

Lower a checked arithmetic definition or its symbolic name to a lambda.

defmethodlower-arithmetic-function
let
environmentnil
lambda-parametersnil
lambda-bindingsnil
dolist
parameter
lang:arithmetic-function-parametersdefinition
let
name
gensym
formatnil"~A-"
lang:arithmetic-object-nameparameter
pushnamelambda-parameters
push
consparametername
environment
setflambda-parameters
nreverselambda-parameters
dolist
binding
lang:arithmetic-function-bindingsdefinition
let*
value
lower-lisp-arithmetic-expression
lang:arithmetic-binding-expressionbinding
environment
name
gensym
formatnil"~A-"
lang:arithmetic-object-namebinding
push
listnamevalue
lambda-bindings
push
consbindingname
environment
let
result
lower-lisp-arithmetic-expression
lang:arithmetic-function-resultdefinition
environment
`
lambda,lambda-parameters,
iflambda-bindings`
let*,
nreverselambda-bindings
,result
result
defmacrodefine-lisp-arithmetic-function
nameparameters&bodybody

Define checked arithmetic name as both semantic source and a Lisp function.

let*`
progn
eval-when
:compile-toplevel:load-toplevel:execute
lang:define-arithmetic-function,name,parameters,@body
defun,name,
secondlambda-expression
,@
cddrlambda-expression
',name
defgenericcompile-arithmetic-function
:documentation

Compile a checked arithmetic definition or symbolic name to a function.

defclasslisp-arithmetic-realization
definition:initarg:definition:readerlisp-arithmetic-realization-definition
parameter-declarations:initarg:parameter-declarations:readerlisp-arithmetic-realization-parameter-declarations
result-declaration:initarg:result-declaration:readerlisp-arithmetic-realization-result-declaration
function:initarg:function:readerlisp-arithmetic-realization-function
:documentation

One checked arithmetic definition compiled for explicit Lisp types.

defunmake-lisp-arithmetic-realization
definition&keyparameter-representation-typesresult-representation-type

Compile definition and state the Lisp representations chosen for its ABI.

let
parameters
lang:arithmetic-function-parametersdefinition
unless
=
lengthparameters
lengthparameter-representation-types
error'lisp-arithmetic-error:definitiondefinition:reason:parameter-representation-arity:details
list
lengthparameters
lengthparameter-representation-types
make-instance'lisp-arithmetic-realization:definitiondefinition:parameter-declarations
mapcar
lambda
parameterrepresentation-type
math:make-represented-value-declaration:representation-typerepresentation-type:quantity-specification
lang:arithmetic-parameter-quantity-specificationparameter
:quantity-layout
lang:arithmetic-parameter-quantity-layoutparameter
:source-form
lang:arithmetic-object-source-formparameter
parametersparameter-representation-types
:result-declaration
let
result
lang:arithmetic-function-resultdefinition
math:make-represented-value-declaration:representation-typeresult-representation-type:quantity-specification
lang:arithmetic-expression-quantity-specificationresult
:quantity-layout
lang:arithmetic-expression-quantity-layoutresult
:source-form
lang:arithmetic-expression-source-formresult
:function
defunbind-lisp-arithmetic-realization
realizationactual-parameter-declarations&keyactual-result-declaration

Check one storage ABI against realization and return its raw Lisp function.

let
expected
lisp-arithmetic-realization-parameter-declarationsrealization
unless
=
lengthactual-parameter-declarations
lengthexpected
error'lisp-arithmetic-error:definition
lisp-arithmetic-realization-definitionrealization
:reason:storage-declaration-arity:details
list
lengthactual-parameter-declarations
lengthexpected
mapc#'math:ensure-declarations-compatibleactual-parameter-declarationsexpected
whenactual-result-declaration
math:ensure-declarations-compatibleactual-result-declaration
lisp-arithmetic-realization-result-declarationrealization
lisp-arithmetic-realization-functionrealization