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 `^`

.