@menu
* Introduction to linearalgebra::
* Functions and Variables for linearalgebra::
@end menu

@c -----------------------------------------------------------------------------
@node Introduction to linearalgebra, Functions and Variables for linearalgebra, linearalgebra, linearalgebra
@section Introduction to linearalgebra
@c -----------------------------------------------------------------------------

@code{linearalgebra} is a collection of functions for linear algebra.

Example:

@c ===beg===
@c M : matrix ([1, 2], [1, 2]);
@c nullspace (M);
@c columnspace (M);
@c ptriangularize (M - z*ident(2), z);
@c M : matrix ([1, 2, 3], [4, 5, 6], [7, 8, 9]) - z*ident(3);
@c MM : ptriangularize (M, z);
@c algebraic : true;
@c tellrat (MM [3, 3]);
@c MM : ratsimp (MM);
@c nullspace (MM);
@c M : matrix ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], 
@c                    [13, 14, 15, 16]);
@c columnspace (M);
@c apply ('orthogonal_complement, args (nullspace (transpose (M))));
@c ===end===
@example
(%i1) M : matrix ([1, 2], [1, 2]);
                            [ 1  2 ]
(%o1)                       [      ]
                            [ 1  2 ]
(%i2) nullspace (M);
                               [  1  ]
                               [     ]
(%o2)                     span([   1 ])
                               [ - - ]
                               [   2 ]
(%i3) columnspace (M);
                                [ 1 ]
(%o3)                      span([   ])
                                [ 1 ]
(%i4) ptriangularize (M - z*ident(2), z);
                         [ 1   2 - z   ]
(%o4)                    [             ]
                         [           2 ]
                         [ 0  3 z - z  ]
(%i5) M : matrix ([1, 2, 3], [4, 5, 6], [7, 8, 9]) - z*ident(3);
                     [ 1 - z    2      3   ]
                     [                     ]
(%o5)                [   4    5 - z    6   ]
                     [                     ]
                     [   7      8    9 - z ]
(%i6) MM : ptriangularize (M, z);
              [ 4  5 - z            6            ]
              [                                  ]
              [                2                 ]
              [     66        z    102 z   132   ]
              [ 0   --      - -- + ----- + ---   ]
(%o6)         [     49        7     49     49    ]
              [                                  ]
              [               3        2         ]
              [           49 z    245 z    147 z ]
              [ 0    0    ----- - ------ - ----- ]
              [            264      88      44   ]
(%i7) algebraic : true;
(%o7)                         true
(%i8) tellrat (MM [3, 3]);
                         3       2
(%o8)                  [z  - 15 z  - 18 z]
(%i9) MM : ratsimp (MM);
               [ 4  5 - z           6           ]
               [                                ]
               [                2               ]
(%o9)          [     66      7 z  - 102 z - 132 ]
               [ 0   --    - ------------------ ]
               [     49              49         ]
               [                                ]
               [ 0    0             0           ]
(%i10) nullspace (MM);
                        [        1         ]
                        [                  ]
                        [   2              ]
                        [  z  - 14 z - 16  ]
                        [  --------------  ]
(%o10)             span([        8         ])
                        [                  ]
                        [    2             ]
                        [   z  - 18 z - 12 ]
                        [ - -------------- ]
                        [         12       ]
(%i11) M : matrix ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12],
                   [13, 14, 15, 16]);
                       [ 1   2   3   4  ]
                       [                ]
                       [ 5   6   7   8  ]
(%o11)                 [                ]
                       [ 9   10  11  12 ]
                       [                ]
                       [ 13  14  15  16 ]
(%i12) columnspace (M);
                           [ 1  ]  [ 2  ]
                           [    ]  [    ]
                           [ 5  ]  [ 6  ]
(%o12)                span([    ], [    ])
                           [ 9  ]  [ 10 ]
                           [    ]  [    ]
                           [ 13 ]  [ 14 ]
(%i13) apply ('orthogonal_complement, args (nullspace (transpose (M))));
                           [ 0 ]  [  1  ]
                           [   ]  [     ]
                           [ 1 ]  [  0  ]
(%o13)                span([   ], [     ])
                           [ 2 ]  [ - 1 ]
                           [   ]  [     ]
                           [ 3 ]  [ - 2 ]
@end example

@opencatbox
@category{Linear algebra} @category{Share packages} @category{Package linearalgebra}
@closecatbox

@c -----------------------------------------------------------------------------
@need 800
@node Functions and Variables for linearalgebra,  , Introduction to linearalgebra, linearalgebra
@section Functions and Variables for linearalgebra
@c -----------------------------------------------------------------------------

@c -----------------------------------------------------------------------------
@anchor{addmatrices}
@deffn {Function} addmatrices (@var{f}, @var{M_1}, @dots{}, @var{M_n})

@c REWORD -- THE RESULT IS NOT GENERALLY THE SUM OF M_1, ..., M_N
Using the function @var{f} as the addition function, return the sum of the
matrices @var{M_1}, @dots{}, @var{M_n}.  The function @var{f} must accept any
number of arguments (a Maxima nary function).

Examples:

@c ===beg===
@c m1 : matrix([1,2],[3,4])$
@c m2 : matrix([7,8],[9,10])$
@c addmatrices('max,m1,m2);
@c addmatrices('max,m1,m2,5*m1);
@c ===end===
@example
(%i1) m1 : matrix([1,2],[3,4])$
(%i2) m2 : matrix([7,8],[9,10])$
(%i3) addmatrices('max,m1,m2);
(%o3) matrix([7,8],[9,10])
(%i4) addmatrices('max,m1,m2,5*m1);
(%o4) matrix([7,10],[15,20])
@end example

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{blockmatrixp}
@deffn {Function} blockmatrixp (@var{M})

Return true if and only if @var{M} is a matrix and every entry of 
@var{M} is a matrix.

@opencatbox
@category{Package linearalgebra} @category{Predicate functions}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{columnop}
@deffn {Function} columnop (@var{M}, @var{i}, @var{j}, @var{theta})

If @var{M} is a matrix, return the matrix that results from doing the column
operation @code{C_i <- C_i - @var{theta} * C_j}. If @var{M} doesn't have a row
@var{i} or @var{j}, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{columnswap}
@deffn {Function} columnswap (@var{M}, @var{i}, @var{j})

If @var{M} is a matrix, swap columns @var{i} and @var{j}.  If @var{M} doesn't
have a column @var{i} or @var{j}, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{columnspace}
@deffn {Function} columnspace (@var{M})

If @var{M} is a matrix, return @code{span (v_1, ..., v_n)}, where the set
@code{@{v_1, ..., v_n@}} is a basis for the column space of @var{M}.  The span 
of the empty set is @code{@{0@}}.  Thus, when the column space has only
one member, return @code{span ()}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{copy}
@deffn {Function} copy (@var{e})

Return a copy of the Maxima expression @var{e}.  Although @var{e} can be any
Maxima expression, the copy function is the most useful when @var{e} is either 
a list or a matrix; consider:

@c ===beg===
@c m : [1,[2,3]]$
@c mm : m$
@c mm[2][1] : x$
@c m;
@c mm;
@c ===end===
@example 
(%i1) m : [1,[2,3]]$
(%i2) mm : m$
(%i3) mm[2][1] : x$
(%i4) m;
(%o4)                      [1,[x,3]]
(%i5) mm;
(%o5)                      [1,[x,3]]
@end example

Let's try the same experiment, but this time let @var{mm} be a copy of @var{m}

@c ===beg===
@c m : [1,[2,3]]$
@c mm : copy(m)$
@c mm[2][1] : x$
@c m;
@c mm;
@c ===end===
@example
(%i6) m : [1,[2,3]]$
(%i7) mm : copy(m)$
(%i8) mm[2][1] : x$
(%i9) m;
(%o9)                     [1,[2,3]]
(%i10) mm;
(%o10)                    [1,[x,3]]
@end example

This time, the assignment to @var{mm} does not change the value of @var{m}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{cholesky}
@deffn  {Function} cholesky (@var{M})
@deffnx {Function} cholesky (@var{M}, @var{field})

Return the Cholesky factorization of the matrix selfadjoint (or hermitian)
matrix @var{M}.  The second argument defaults to 'generalring.' For a
description of the possible values for @var{field}, see @code{lu_factor}.

@opencatbox
@category{Matrix decompositions} @category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{ctranspose}
@deffn {Function} ctranspose (@var{M})

Return the complex conjugate transpose of the matrix @var{M}.  The function
@code{ctranspose} uses @code{matrix_element_transpose} to transpose each matrix
element.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{diag_matrix}
@deffn {Function} diag_matrix (@var{d_1}, @var{d_2}, @dots{}, @var{d_n})

Return a diagonal matrix with diagonal entries @var{d_1}, @var{d_2}, @dots{},
@var{d_n}.  When the diagonal entries are matrices, the zero entries of the
returned matrix are zero matrices of the appropriate size; for example:

@c ===beg===
@c diag_matrix(diag_matrix(1,2),diag_matrix(3,4));
@c diag_matrix(p,q);
@c ===end===
@example
(%i1) diag_matrix(diag_matrix(1,2),diag_matrix(3,4));

                            [ [ 1  0 ]  [ 0  0 ] ]
                            [ [      ]  [      ] ]
                            [ [ 0  2 ]  [ 0  0 ] ]
(%o1)                       [                    ]
                            [ [ 0  0 ]  [ 3  0 ] ]
                            [ [      ]  [      ] ]
                            [ [ 0  0 ]  [ 0  4 ] ]
(%i2) diag_matrix(p,q);

                                   [ p  0 ]
(%o2)                              [      ]
                                   [ 0  q ]
@end example

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{dotproduct}
@deffn {Function} dotproduct (@var{u}, @var{v})

Return the dotproduct of vectors @var{u} and @var{v}.  This is the same as
@code{conjugate (transpose (@var{u})) .  @var{v}}.  The arguments @var{u} and
@var{v} must be column vectors.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{eigens_by_jacobi}
@deffn  {Function} eigens_by_jacobi (@var{A})
@deffnx {Function} eigens_by_jacobi (@var{A}, @var{field_type})

Computes the eigenvalues and eigenvectors of @var{A} by the method of Jacobi
rotations.  @var{A} must be a symmetric matrix (but it need not be positive
definite nor positive semidefinite).  @var{field_type} indicates the
computational field, either @code{floatfield} or @code{bigfloatfield}.
If @var{field_type} is not specified, it defaults to @code{floatfield}.

The elements of @var{A} must be numbers or expressions which evaluate to numbers
via @code{float} or @code{bfloat} (depending on @var{field_type}).

Examples:

@c ===beg===
@c S : matrix ([1/sqrt(2), 1/sqrt(2)], [- 1/sqrt(2), 1/sqrt(2)]);
@c L : matrix ([sqrt(3), 0], [0, sqrt(5)]);
@c M : S . L . transpose (S);
@c eigens_by_jacobi (M);
@c float ([[sqrt(3), sqrt(5)], S]);
@c eigens_by_jacobi (M, bigfloatfield);
@c ===end===

@example
(%i1) S: matrix([1/sqrt(2), 1/sqrt(2)],[-1/sqrt(2), 1/sqrt(2)]);
                     [     1         1    ]
                     [  -------   ------- ]
                     [  sqrt(2)   sqrt(2) ]
(%o1)                [                    ]
                     [      1        1    ]
                     [ - -------  ------- ]
                     [   sqrt(2)  sqrt(2) ]
(%i2) L : matrix ([sqrt(3), 0], [0, sqrt(5)]);
                      [ sqrt(3)     0    ]
(%o2)                 [                  ]
                      [    0     sqrt(5) ]
(%i3) M : S . L . transpose (S);
            [ sqrt(5)   sqrt(3)  sqrt(5)   sqrt(3) ]
            [ ------- + -------  ------- - ------- ]
            [    2         2        2         2    ]
(%o3)       [                                      ]
            [ sqrt(5)   sqrt(3)  sqrt(5)   sqrt(3) ]
            [ ------- - -------  ------- + ------- ]
            [    2         2        2         2    ]
(%i4) eigens_by_jacobi (M);
The largest percent change was 0.1454972243679
The largest percent change was 0.0
number of sweeps: 2
number of rotations: 1
(%o4) [[1.732050807568877, 2.23606797749979], 
                        [  0.70710678118655   0.70710678118655 ]
                        [                                      ]]
                        [ - 0.70710678118655  0.70710678118655 ]
(%i5) float ([[sqrt(3), sqrt(5)], S]);
(%o5) [[1.732050807568877, 2.23606797749979], 
                        [  0.70710678118655   0.70710678118655 ]
                        [                                      ]]
                        [ - 0.70710678118655  0.70710678118655 ]
(%i6) eigens_by_jacobi (M, bigfloatfield);
The largest percent change was 1.454972243679028b-1
The largest percent change was 0.0b0
number of sweeps: 2
number of rotations: 1
(%o6) [[1.732050807568877b0, 2.23606797749979b0], 
                [  7.071067811865475b-1   7.071067811865475b-1 ]
                [                                              ]]
                [ - 7.071067811865475b-1  7.071067811865475b-1 ]
@end example

@opencatbox
@category{Matrix decompositions} @category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{get_lu_factors}
@deffn {Function} get_lu_factors (@var{x}) 

When @code{@var{x} = lu_factor (@var{A})}, then @code{get_lu_factors} returns a
list of the form @code{[P, L, U]}, where @var{P} is a permutation matrix,
@var{L} is lower triangular with ones on the diagonal, and @var{U} is upper
triangular, and @code{@var{A} = @var{P} @var{L} @var{U}}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{hankel}
@deffn  {Function} hankel (@var{col})
@deffnx {Function} hankel (@var{col}, @var{row})

Return a Hankel matrix @var{H}.  The first column of @var{H} is @var{col};
except for the first entry, the last row of @var{H} is @var{row}.  The
default for @var{row} is the zero vector with the same length as @var{col}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{hessian}
@deffn {Function} hessian (@var{f}, @var{x})

Returns the Hessian matrix of @var{f} with respect to the list of variables
@var{x}.  The @code{(i, j)}-th element of the Hessian matrix is
@code{diff(@var{f}, @var{x}[i], 1, @var{x}[j], 1)}.

Examples:

@c ===beg===
@c hessian (x * sin (y), [x, y]);
@c depends (F, [a, b]);
@c hessian (F, [a, b]);
@c ===end===
@example
(%i1) hessian (x * sin (y), [x, y]);
                     [   0       cos(y)   ]
(%o1)                [                    ]
                     [ cos(y)  - x sin(y) ]
(%i2) depends (F, [a, b]);
(%o2)                       [F(a, b)]
(%i3) hessian (F, [a, b]);
                        [   2      2   ]
                        [  d F    d F  ]
                        [  ---   ----- ]
                        [    2   da db ]
                        [  da          ]
(%o3)                   [              ]
                        [   2      2   ]
                        [  d F    d F  ]
                        [ -----   ---  ]
                        [ da db     2  ]
                        [         db   ]
@end example

@opencatbox
@category{Differential calculus} @category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{hilbert_matrix}
@deffn {Function} hilbert_matrix (@var{n})

Return the @var{n} by @var{n} Hilbert matrix.  When @var{n} isn't a positive
integer, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{identfor}
@deffn  {Function} identfor (@var{M})
@deffnx {Function} identfor (@var{M}, @var{fld})

Return an identity matrix that has the same shape as the matrix
@var{M}.  The diagonal entries of the identity matrix are the 
multiplicative identity of the field @var{fld}; the default for
@var{fld} is @var{generalring}.

The first argument @var{M} should be a square matrix or a non-matrix.  When
@var{M} is a matrix, each entry of @var{M} can be a square matrix -- thus
@var{M} can be a blocked Maxima matrix.  The matrix can be blocked to any
(finite) depth.

See also @code{zerofor}

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{invert_by_lu}
@deffn {Function} invert_by_lu (@var{M}, @var{(rng generalring)})

Invert a matrix @var{M} by using the LU factorization.  The LU factorization
is done using the ring @var{rng}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{jacobian}
@deffn {Function} jacobian (@var{f}, @var{x})

Returns the Jacobian matrix of the list of functions @var{f} with respect to
the list of variables @var{x}.  The @code{(i, j)}-th element of the Jacobian
matrix is @code{diff(@var{f}[i], @var{x}[j])}.

Examples:

@c ===beg===
@c jacobian ([sin (u - v), sin (u * v)], [u, v]);
@c depends ([F, G], [y, z]);
@c jacobian ([F, G], [y, z]);
@c ===end===
@example
(%i1) jacobian ([sin (u - v), sin (u * v)], [u, v]);
                  [ cos(v - u)  - cos(v - u) ]
(%o1)             [                          ]
                  [ v cos(u v)   u cos(u v)  ]
(%i2) depends ([F, G], [y, z]);
(%o2)                  [F(y, z), G(y, z)]
(%i3) jacobian ([F, G], [y, z]);
                           [ dF  dF ]
                           [ --  -- ]
                           [ dy  dz ]
(%o3)                      [        ]
                           [ dG  dG ]
                           [ --  -- ]
                           [ dy  dz ]
@end example

@opencatbox
@category{Differential calculus} @category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{kronecker_product}
@deffn {Function} kronecker_product (@var{A}, @var{B})

Return the Kronecker product of the matrices @var{A} and @var{B}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{listp}
@deffn  {Function} listp (@var{e}, @var{p})
@deffnx {Function} listp (@var{e})

Given an optional argument @var{p}, return @code{true} if @var{e} is a Maxima
list and @var{p} evaluates to @code{true} for every list element.  When
@code{listp} is not given the optional argument, return @code{true} if @var{e}
is a Maxima list.  In all other cases, return @code{false}.

@opencatbox
@category{Package linearalgebra} @category{Predicate functions}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{locate_matrix_entry}
@deffn {Function} locate_matrix_entry (@var{M}, @var{r_1}, @var{c_1}, @var{r_2}, @var{c_2}, @var{f}, @var{rel})

The first argument must be a matrix; the arguments
@var{r_1} through @var{c_2} determine a sub-matrix of @var{M} that consists of
rows @var{r_1} through @var{r_2} and columns @var{c_1} through @var{c_2}.

Find a entry in the sub-matrix @var{M} that satisfies some property.
Three cases:

(1) @code{@var{rel} = 'bool} and @var{f} a predicate: 

Scan the sub-matrix from left to right then top to bottom,
and return the index of the first entry that satisfies the 
predicate @var{f}.  If no matrix entry satisfies @var{f}, return @code{false}.

(2) @code{@var{rel} = 'max} and @var{f} real-valued:

Scan the sub-matrix looking for an entry that maximizes @var{f}.
Return the index of a maximizing entry.

(3) @code{@var{rel} = 'min} and @var{f} real-valued:

Scan the sub-matrix looking for an entry that minimizes @var{f}.
Return the index of a minimizing entry.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{lu_backsub}
@deffn {Function} lu_backsub (@var{M}, @var{b})

When @code{@var{M} = lu_factor (@var{A}, @var{field})},
then @code{lu_backsub (@var{M}, @var{b})} solves the linear
system @code{@var{A} @var{x} = @var{b}}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{lu_factor}
@deffn {Function} lu_factor (@var{M}, @var{field})

Return a list of the form @code{[@var{LU}, @var{perm}, @var{fld}]}, or
@code{[@var{LU}, @var{perm}, @var{fld}, @var{lower-cnd} @var{upper-cnd}]}, where

(1) The matrix @var{LU} contains the factorization of @var{M} in a packed form.
    Packed form means three things: First, the rows of @var{LU} are permuted
    according to the list @var{perm}.  If, for example, @var{perm} is the list
    @code{[3,2,1]}, the actual first row of the @var{LU} factorization is the
    third row of the matrix @var{LU}.  Second, the lower triangular factor of
    m is the lower triangular part of @var{LU} with the diagonal entries
    replaced by all ones.  Third, the upper triangular factor of @var{M} is the
    upper triangular part of @var{LU}.

(2) When the field is either @code{floatfield} or @code{complexfield}, the
    numbers @var{lower-cnd} and @var{upper-cnd} are lower and upper bounds for
    the infinity norm condition number of @var{M}.  For all fields, the
    condition number might not be estimated; for such fields, @code{lu_factor}
    returns a two item list.  Both the lower and upper bounds can differ from
    their true values by arbitrarily large factors.  (See also @code{mat_cond}.)
   
  The argument @var{M} must be a square matrix.

  The optional argument @var{fld} must be a symbol that determines a ring or
  field.  The pre-defined fields and rings are:

  (a) @code{generalring}      -- the ring of Maxima expressions,

  (b) @code{floatfield}       -- the field of floating point numbers of the
                                 type double,

  (c) @code{complexfield}     -- the field of complex floating point numbers of
                                 the type double,

  (d) @code{crering}          -- the ring of Maxima CRE expressions,

  (e) @code{rationalfield}    -- the field of rational numbers,

  (f) @code{runningerror}     -- track the all floating point rounding errors,

  (g) @code{noncommutingring} -- the ring of Maxima expressions where
                                 multiplication is the non-commutative dot
                                 operator.

When the field is @code{floatfield}, @code{complexfield}, or
@code{runningerror}, the algorithm uses partial pivoting; for all
other fields, rows are switched only when needed to avoid a zero
pivot.

Floating point addition arithmetic isn't associative, so the meaning
of 'field' differs from the mathematical definition.

A member of the field @code{runningerror} is a two member Maxima list
of the form @code{[x,n]},where @var{x} is a floating point number and
@code{n} is an integer.  The relative difference between the 'true'
value of @code{x} and @code{x} is approximately bounded by the machine
epsilon times @code{n}.  The running error bound drops some terms that
of the order the square of the machine epsilon.

There is no user-interface for defining a new field.  A user that is
familiar with Common Lisp should be able to define a new field.  To do
this, a user must define functions for the arithmetic operations and
functions for converting from the field representation to Maxima and
back.  Additionally, for ordered fields (where partial pivoting will be
used), a user must define functions for the magnitude and for
comparing field members.  After that all that remains is to define a
Common Lisp structure @code{mring}.  The file @code{mring} has many
examples.
 
To compute the factorization, the first task is to convert each matrix
entry to a member of the indicated field.  When conversion isn't
possible, the factorization halts with an error message.  Members of
the field needn't be Maxima expressions.  Members of the
@code{complexfield}, for example, are Common Lisp complex numbers.  Thus
after computing the factorization, the matrix entries must be
converted to Maxima expressions.

See also  @code{get_lu_factors}.

Examples:

@c ===beg===
@c w[i,j] := random (1.0) + %i * random (1.0);
@c showtime : true$
@c M : genmatrix (w, 100, 100)$
@c lu_factor (M, complexfield)$
@c lu_factor (M, generalring)$
@c showtime : false$
@c M : matrix ([1 - z, 3], [3, 8 - z]);
@c lu_factor (M, generalring);
@c get_lu_factors (%);
@c %[1] . %[2] . %[3];
@c ===end===
@example
(%i1) w[i,j] := random (1.0) + %i * random (1.0);
(%o1)          w     := random(1.) + %i random(1.)
                i, j
(%i2) showtime : true$
Evaluation took 0.00 seconds (0.00 elapsed)
(%i3) M : genmatrix (w, 100, 100)$
Evaluation took 7.40 seconds (8.23 elapsed)
(%i4) lu_factor (M, complexfield)$
Evaluation took 28.71 seconds (35.00 elapsed)
(%i5) lu_factor (M, generalring)$
Evaluation took 109.24 seconds (152.10 elapsed)
(%i6) showtime : false$

(%i7) M : matrix ([1 - z, 3], [3, 8 - z]); 
                        [ 1 - z    3   ]
(%o7)                   [              ]
                        [   3    8 - z ]
(%i8) lu_factor (M, generalring);
          [ 1 - z         3        ]
          [                        ]
(%o8)    [[   3            9       ], [1, 2], generalring]
          [ -----  - z - ----- + 8 ]
          [ 1 - z        1 - z     ]
(%i9) get_lu_factors (%);
                  [   1    0 ]  [ 1 - z         3        ]
        [ 1  0 ]  [          ]  [                        ]
(%o9)  [[      ], [   3      ], [                9       ]]
        [ 0  1 ]  [ -----  1 ]  [   0    - z - ----- + 8 ]
                  [ 1 - z    ]  [              1 - z     ]
(%i10) %[1] . %[2] . %[3];
                        [ 1 - z    3   ]
(%o10)                  [              ]
                        [   3    8 - z ]
@end example

@opencatbox
@category{Matrix decompositions} @category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{mat_cond}
@deffn  {Function} mat_cond (@var{M}, 1)
@deffnx {Function} mat_cond (@var{M}, inf)

Return the @var{p}-norm matrix condition number of the matrix
@var{m}.  The allowed values for @var{p} are 1 and @var{inf}.  This
function uses the LU factorization to invert the matrix @var{m}.  Thus
the running time for @code{mat_cond} is proportional to the cube of
the matrix size; @code{lu_factor} determines lower and upper bounds
for the infinity norm condition number in time proportional to the
square of the matrix size.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{mat_norm}
@deffn  {Function} mat_norm (@var{M}, 1)
@deffnx {Function} mat_norm (@var{M}, inf)
@deffnx {Function} mat_norm (@var{M}, frobenius)

Return the matrix @var{p}-norm of the matrix @var{M}.  The allowed values for
@var{p} are 1, @code{inf}, and @code{frobenius} (the Frobenius matrix norm).
The matrix @var{M} should be an unblocked matrix.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{linearalgebra_matrixp}
@deffn  {Function} matrixp (@var{e}, @var{p})
@deffnx {Function} matrixp (@var{e})

Given an optional argument @var{p}, return @code{true} if @var{e} is 
a matrix and @var{p} evaluates to @code{true} for every matrix element.
When @code{matrixp} is not given an optional argument, return @code{true} 
if @code{e} is a matrix.  In all other cases, return @code{false}.

See also @code{blockmatrixp}

@opencatbox
@category{Package linearalgebra} @category{Predicate functions}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{matrix_size}
@deffn {Function} matrix_size (@var{M})

Return a two member list that gives the number of rows and columns, respectively
of the matrix @var{M}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{mat_fullunblocker}
@deffn {Function} mat_fullunblocker (@var{M})

If @var{M} is a block matrix, unblock the matrix to all levels.  If @var{M} is
a matrix, return @var{M}; otherwise, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{mat_trace}
@deffn {Function} mat_trace (@var{M})

Return the trace of the matrix @var{M}.  If @var{M} isn't a matrix, return a
noun form.  When @var{M} is a block matrix, @code{mat_trace(M)} returns
the same value as does @code{mat_trace(mat_unblocker(m))}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{mat_unblocker}
@deffn {Function} mat_unblocker (@var{M})

If @var{M} is a block matrix, unblock @var{M} one level.  If @var{M} is a
matrix, @code{mat_unblocker (M)} returns @var{M}; otherwise, signal an error.

Thus if each entry of @var{M} is matrix, @code{mat_unblocker (M)} returns an 
unblocked matrix, but if each entry of @var{M} is a block matrix,
@code{mat_unblocker (M)} returns a block matrix with one less level of blocking.

If you use block matrices, most likely you'll want to set
@code{matrix_element_mult} to @code{"."} and @code{matrix_element_transpose} to
@code{'transpose}.  See also @code{mat_fullunblocker}.

Example:

@c ===beg===
@c A : matrix ([1, 2], [3, 4]);
@c B : matrix ([7, 8], [9, 10]);
@c matrix ([A, B]);
@c mat_unblocker (%);
@c ===end===
@example
(%i1) A : matrix ([1, 2], [3, 4]);
                            [ 1  2 ]
(%o1)                       [      ]
                            [ 3  4 ]
(%i2) B : matrix ([7, 8], [9, 10]);
                            [ 7  8  ]
(%o2)                       [       ]
                            [ 9  10 ]
(%i3) matrix ([A, B]);
@group
                     [ [ 1  2 ]  [ 7  8  ] ]
(%o3)                [ [      ]  [       ] ]
                     [ [ 3  4 ]  [ 9  10 ] ]
@end group
(%i4) mat_unblocker (%);
                         [ 1  2  7  8  ]
(%o4)                    [             ]
                         [ 3  4  9  10 ]
@end example

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{nullspace}
@deffn {Function} nullspace (@var{M})

If @var{M} is a matrix, return @code{span (v_1, ..., v_n)}, where the set
@code{@{v_1, ..., v_n@}} is a basis for the nullspace of @var{M}.  The span of
the empty set is @code{@{0@}}.  Thus, when the nullspace has only one member,
return @code{span ()}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{nullity}
@deffn {Function} nullity (@var{M})

If @var{M} is a matrix, return the dimension of the nullspace of @var{M}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{orthogonal_complement}
@deffn {Function} orthogonal_complement (@var{v_1}, @dots{}, @var{v_n})

Return @code{span (u_1, ..., u_m)}, where the set @code{@{u_1, ..., u_m@}} is a 
basis for the orthogonal complement of the set @code{(v_1, ..., v_n)}.

Each vector @var{v_1} through @var{v_n} must be a column vector.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{polynomialp}
@deffn  {Function} polynomialp (@var{p}, @var{L}, @var{coeffp}, @var{exponp})
@deffnx {Function} polynomialp (@var{p}, @var{L}, @var{coeffp})
@deffnx {Function} polynomialp (@var{p}, @var{L})

Return @code{true} if @var{p} is a polynomial in the variables in the list
@var{L}.  The predicate @var{coeffp} must evaluate to @code{true} for each
coefficient, and the predicate @var{exponp} must evaluate to @code{true} for all
exponents of the variables in @var{L}.  If you want to use a non-default value
for @var{exponp}, you must supply @var{coeffp} with a value even if you want
to use the default for @var{coeffp}.

@c WORK THE FOLLOWING INTO THE PRECEDING
The command @code{polynomialp (@var{p}, @var{L}, @var{coeffp})} is equivalent to
@code{polynomialp (@var{p}, @var{L}, @var{coeffp}, 'nonnegintegerp)} and the
command @code{polynomialp (@var{p}, @var{L})} is equivalent to
@code{polynomialp (@var{p}, L@var{,} 'constantp, 'nonnegintegerp)}.

The polynomial needn't be expanded:

@c ===beg===
@c polynomialp ((x + 1)*(x + 2), [x]);
@c polynomialp ((x + 1)*(x + 2)^a, [x]);
@c ===end===
@example
(%i1) polynomialp ((x + 1)*(x + 2), [x]);
(%o1)                         true
(%i2) polynomialp ((x + 1)*(x + 2)^a, [x]);
(%o2)                         false
@end example

An example using non-default values for coeffp and exponp:

@c ===beg===
@c polynomialp ((x + 1)*(x + 2)^(3/2), [x], numberp, numberp);
@c polynomialp ((x^(1/2) + 1)*(x + 2)^(3/2), [x], numberp, 
@c                                                        numberp);
@c ===end===
@example
(%i1) polynomialp ((x + 1)*(x + 2)^(3/2), [x], numberp, numberp);
(%o1)                         true
(%i2) polynomialp ((x^(1/2) + 1)*(x + 2)^(3/2), [x], numberp,
                                                        numberp);
(%o2)                         true
@end example

Polynomials with two variables:

@c ===beg===
@c polynomialp (x^2 + 5*x*y + y^2, [x]);
@c polynomialp (x^2 + 5*x*y + y^2, [x, y]);
@c ===end===
@example
(%i1) polynomialp (x^2 + 5*x*y + y^2, [x]);
(%o1)                         false
(%i2) polynomialp (x^2 + 5*x*y + y^2, [x, y]);
(%o2)                         true
@end example

@opencatbox
@category{Package linearalgebra} @category{Predicate functions}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{polytocompanion}
@deffn {Function} polytocompanion (@var{p}, @var{x})

If @var{p} is a polynomial in @var{x}, return the companion matrix of @var{p}.
For a monic polynomial @var{p} of degree @var{n}, we have
@code{@var{p} = (-1)^@var{n} charpoly (polytocompanion (@var{p}, @var{x}))}.

When @var{p} isn't a polynomial in @var{x}, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{ptringularize}
@deffn {Function} ptriangularize (@var{M}, @var{v})

If @var{M} is a matrix with each entry a polynomial in @var{v}, return 
a matrix @var{M2} such that

(1) @var{M2} is upper triangular,

(2) @code{@var{M2} = @var{E_n} ... @var{E_1} @var{M}},
where @var{E_1} through @var{E_n} are elementary matrices 
whose entries are polynomials in @var{v},

(3) @code{|det (@var{M})| = |det (@var{M2})|},

Note: This function doesn't check that every entry is a polynomial in @var{v}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{rowp}
@deffn {Function} rowop (@var{M}, @var{i}, @var{j}, @var{theta})

If @var{M} is a matrix, return the matrix that results from doing the
row operation @code{R_i <- R_i - theta * R_j}.  If @var{M} doesn't have a row
@var{i} or @var{j}, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox

@end deffn

@deffn {Function} rank (@var{M})

Return the rank of that matrix @var{M}.  The rank is the dimension of the
column space.  Example:

@c ===beg===
@c rank(matrix([1,2],[2,4]));
@c rank(matrix([1,b],[c,d]));
@c ===end===
@example
(%i1) rank(matrix([1,2],[2,4]));
(%o1)                                  1
(%i2) rank(matrix([1,b],[c,d]));
Proviso:  @{d - b c # 0@}
(%o2)                                  2
@end example

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{rowswap}
@deffn {Function} rowswap (@var{M}, @var{i}, @var{j})

If @var{M} is a matrix, swap rows @var{i} and @var{j}.  If @var{M} doesn't
have a row @var{i} or @var{j}, signal an error.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{toeplitz}
@deffn  {Function} toeplitz (@var{col})
@deffnx {Function} toeplitz (@var{col}, @var{row})

Return a Toeplitz matrix @var{T}.  The first first column of @var{T} is
@var{col}; except for the first entry, the first row of @var{T} is @var{row}.
The default for @var{row} is complex conjugate of @var{col}.  Example:

@c ===beg===
@c toeplitz([1,2,3],[x,y,z]);
@c toeplitz([1,1+%i]);
@c ==end===
@example
(%i1)  toeplitz([1,2,3],[x,y,z]);
@group
                                  [ 1  y  z ]
                                  [         ]
(%o1)                             [ 2  1  y ]
                                  [         ]
                                  [ 3  2  1 ]
@end group
(%i2)  toeplitz([1,1+%i]);

                              [   1     1 - %I ]
(%o2)                         [                ]
                              [ %I + 1    1    ]
@end example

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{vandermonde_matrix}
@deffn {Function} vandermonde_matrix ([@var{x_1}, ..., @var{x_n}])

Return a @var{n} by @var{n} matrix whose @var{i}-th row is 
@code{[1, @var{x_i}, @var{x_i}^2, ... @var{x_i}^(@var{n}-1)]}.

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{zerofor}
@deffn  {Function} zerofor (@var{M})
@deffnx {Function} zerofor (@var{M}, @var{fld})

Return a zero  matrix that has the same shape as the matrix
@var{M}.  Every entry of the zero matrix is the
additive identity of the field @var{fld}; the default for
@var{fld} is @var{generalring}.

The first argument @var{M} should be a square matrix or a
non-matrix.  When @var{M} is a matrix, each entry of @var{M} can be a
square matrix -- thus @var{M} can be a blocked Maxima matrix.  The
matrix can be blocked to any (finite) depth.

See also @code{identfor}

@opencatbox
@category{Package linearalgebra}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{zeromatrixp}
@deffn {Function} zeromatrixp (@var{M})

If @var{M} is not a block matrix, return @code{true} if
@code{is (equal (@var{e}, 0))} is true for each element @var{e} of the matrix
@var{M}.  If @var{M} is a block matrix, return @code{true} if @code{zeromatrixp}
evaluates to @code{true} for each element of @var{e}.

@opencatbox
@category{Package linearalgebra} @category{Predicate functions}
@closecatbox
@end deffn

