On SBCL, make sure that asdf:*centeral-registry*
contains
lisplab.asd
and type
CL-USER> (let ((*read-default-float-format* 'double-float)) (require :lisplab)) CL-USER> (in-package :ll))
The *read-default-float-format*
is only needed when requiring
for first time. The main package of Lisplab is lisplab, with nickname ll,
and the package lisplab-user, with nickname ll-user.
The matrix classes hierarchy has three lines of inheritance: on structure, on element type and on implementation. This hierarchy is similar to the stream example in Object-Oriented Programming in Common Lisp, by Sonya E. Keene.
Objects of the most important classes can be created by
read macros. For double-float matrices, matrix-dge
,
LL-USER> #md((1 2) (3 4)) #md(( 1.000 2.000 ) ( 3.000 4.000 ))
For complex double-float matrices, matrix-zge
,
LL-USER> #mz((1 2) (#c(1 2) #c(3 4))) #mz((#c( 1.0 0.0 ) #c( 2.0 0.0 )) (#c( 1.0 2.0 ) #c( 3.0 4.0 )))
Untyped matrices, matrix-ge
,
LL-USER> #mm(('a 'b) ('c 'd)) #mm((A B) (C D))
There are more matrix classes, but these are not exported. Even more matrix classes can be created dynamically, but these capabilities are not yet fully in use. See Structure.
There are many ways to create a matrix, such as
LL-USER> (dnew 0 2 2) #md(( 0.000 0.000 ) ( 0.000 0.000 )) LL-USER> (drow 1 2) #md(( 1.000 2.000 )) LL-USER> (dcol 1 2) #md(( 1.000 ) ( 2.000 )) LL-USER> (dmat '((1 2) (3 4))) #md(( 1.000 2.000 ) ( 3.000 4.000 ))
Similarly, there are znew
, zcol
, zrow
, and zmat
for complex double float matrices and
mnew
, mcol
, mrow
, and mmat
for any matrices. The latter take matrix class as first argument.
Often you want to create a matrix of the same type as a input
matrix. Then you can use mcreate
and mcreate*
for
extended syntax. They are useful when
creating methods that should operate on many matrix types.
To create matrices from something else, use convert
LL-USER> (convert '((1 2) (3 4)) '(:d :ge :any)) #md(( 1.000 2.000 ) ( 3.000 4.000 ))
Convert
also converts between matrix types. If the
matrix contents cannot be converted directly
(e.g., conversion from complex to real),
use copy-contents
instead.
Other matrix constructors are mcreate
, mcreate*
,
drange
, dgrid
, fmat
, funmat
.
The most fundamental constructor is make-matrix-instance
.
Lisplab matrices are zero-based and in column major order.
Matrix reference is with the settable generic function mref
LL-USER> (mref #md((1 2) (3 4)) 0 1) 2.0
Matrices can also list their elements as vectors
(similar to row-major-aref
for arrays). Vector access is with
the generic function vref
LL-USER> (vref #md((1 2) (3 4)) 1) 3.0
which is also settable.
Lisplab introduces general mathematical operators
.+
, .-
, .*
, ./
, and .^
.
These are generalization of
+
, -
, *
, /
, and ^
.
For numbers they work the same,
LL-USER> (.+ 1 2) 3
But the lisplab functions have a much wider functionality since
they are based on the binary generic functions
.add
, .sub
, .mul
, .div
, and .expt
.
On matrices the all functions starting with a dot works elementwise. Hence
LL-USER> (.sin (drow 0 1)) #md(( 0.000 0.8415 ))
The dotted operators ignores the internal structure of the matrices
LL-USER> (let ((a (drow 0 1)) (b (dcol 0.1 0.2))) (.+ a (.* b 2))) #md((0.2000 1.400 ))
The output need not have same type as the input
LL-USER> (.asin #md((1 2))) #mz((#c( 1.6 0.0 ) #c( 1.6 1.3 )))
The dotted functions and operators are optimized and very fast for the double-float matrices, but slow for the matrices with arbitrary element-types.
LL-USER> (.+ #mm((1/2 3/2)) 1) #mm((3/2 5/2))
The linear algebra functions feel and maybe also change the matrix structure. The linear algebra functions often start with m, although this conventions is not strictly followed. The number of linear algebra functions is small compared with LAPACK, but you will find matrix multiplication, matrix inversion, transpose, conjugate transpose, LU-decomposition and eigenvalues.
Matrix multiplication
LL-USER> (let ((a #md((1 0) (0 -1))) (b #md((0.1) (0.2)))) (m* a b)) #md((0.1000 ) (-.2000 ))
Matrix inversion
LL-USER> (minv #md((1 2) (-2 1))) #md((0.2000 -.4000 ) (0.4000 0.2000 ))
Transpose
LL-USER> (mtp #md((1 2) (-2 1))) #md(( 1.000 -2.000 ) ( 2.000 1.000 ))
Conjugate transpose
LL-USER> (mct #mz((1 (* 2 %i)) (-2 1))) #mz((#c( 1.0 -0.0 ) #c(-2.0 -0.0 )) (#c( 0.0 -2.0 ) #c( 1.0 -0.0 )))
Eigenvalues
LL-USER> (eigenvalues #md((1 2) (0 0.5))) #md(( 1.000 ) (0.5000 ))
Eigenvectors
LL-USER> (eigenvectors #md((1 2) (0 0.5))) ( #md(( 1.000 ) (0.5000 )) #md(( 1.000 -.9701 ) ( 0.000 0.2425 )))
Some of the linear algebra functions also work for general element matrices
LL-USER> (let ((a #mm((1 0) (0 -1))) (b #mm((1/2) (2/3)))) (m* a b)) #mm((1/2) (-2/3)) LL-USER> (minv #mm((1 2)(-2 1))) #mm((1/5 -2/5) (2/5 1/5))
Delimited files are read with dlmread
. Delimited files
are written with dlmwrite
. You can also write matrices
as images with pgmwrite
and pswrite
, writing
portable graymap and postscript respectively.
The class function-matrix
implements matrices with
functions and has no store, but where the elements are given by a function
LL-USER> (funmat '(2 2) (lambda (i j) (if (= i j) 1 0))) #<FUNCTION-MATRIX 2x2 1 0 0 1 {AC0F489}>
The similar macro fmat
creates functions of any type by a function.
Function matrices are also used to view a part or restructured other matrix
with view-matrix
, view-col
, or view-row
.
There are two methods for mapping of matrices: mmap
and
mmap-into
. For example
LL-USER> (mmap 'matrix-dge #'.re #mz((1 %i) (-%i 2))) #md(( 1.000 0.000 ) ( 0.000 2.000 ))
The output matrix takes the structure from the first arguments, but
ignores in general matrix structure. If first argument t
output
type is same as type of first matrix argument.
.sin
, .cos
, .sin
, .tan
,
.sinh
, .cosh
, .sinh
, .tanh
,
.asin
, .acos
, .asin
, .atan
,
.asinh
, .acosh
, .asinh
, .atanh
,
.conj
, .re
, .im
, .abs
,
.sqrt
, .exp
.
.besj
, .besy
,
.besi
, .besk
,
.besh1
, .besh2
,
.ai
, .gamma
.
Infix input is with the macro w/infix
LL-USER> (w/infix (let ((x 3)) (1 .+ 2 .* x))) 7
The w/infix
is compatible with the Lisp
semantics. The infix math also works with the
functions +, -, *, /
and ^
.