@c English version: 2011-06-30
@menu
* Introducción a linearalgebra::
* Funciones y variables para linearalgebra::
@end menu

@node Introducción a linearalgebra, Funciones y variables para linearalgebra, linearalgebra, linearalgebra
@section Introducción a linearalgebra

El paquete @code{linearalgebra} contiene una batería de
funciones para álgebra lineal.

Ejemplo:

@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],
@c             [9, 10, 11, 12], [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

@node Funciones y variables para linearalgebra,  , Introducción a linearalgebra, linearalgebra
@section Funciones y variables para linearalgebra

@deffn {Función} addmatrices (@var{f}, @var{M_1}, @dots{}, @var{M_n})

@c REWORD -- THE RESULT IS NOT GENERALLY THE SUM OF M_1, ..., M_N
Utiliza la función @var{f} como una función aditiva, devolviendo la
suma de las matrices @var{M_1}, @dots{}, @var{M_n}. La función @var{f} debe
ser tal que acepte un número arbitrario de argumentos; en otras palabras,
será una función n-aria de Maxima.

Ejemplos:

@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

@end deffn

@deffn {Función} blockmatrixp (@var{M})

Devuelve el valor @code{true} si y solo si @var{M} es una matriz
cuyos elementos son a su vez matrices.

@end deffn

@deffn {Función} columnop (@var{M}, @var{i}, @var{j}, @var{theta})

Si @var{M} es una matriz, devuelve la matriz que resulta de hacer la
operación columna @code{C_i <- C_i - @var{theta} * C_j}. Si @var{M}
carece de cualquiera de las filas @var{i} o @var{j}, devuelve un mensaje
de error.

@end deffn

@deffn {Función} columnswap (@var{M}, @var{i}, @var{j})

Si @var{M} es una matriz, intercambia las columnas @var{i} y @var{j}.
Si @var{M} carece de cualquiera de las filas @var{i} o @var{j}, devuelve 
un mensaje de error.

@end deffn

@deffn {Función} columnspace (@var{M})

Si @var{M} es una matriz, devuelve @code{span (v_1, ..., v_n)}, donde
el conjunto @code{@{v_1, ..., v_n@}} es la base del espacio generado por
las columnas de @var{M}.

@end deffn

@deffn {Función} copy (@var{e})

Devuelve una copia de la expresión @var{e} de Maxima. Aunque @var{e}
puede ser cualquier expresión de Maxima, la función @code{copy} es
especialmente útil cuando @var{e} es una lista o una matriz. 
Considérese el siguiente ejemplo:

@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
Veamos el mismo ejemplo siendo ahora @var{mm} una copia de @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
En esta ocasión, la asignación a @var{mm} no cambia el valor de @var{m}.

@end deffn

@deffn {Función} cholesky (@var{M})
@deffnx {Función} cholesky (@var{M}, @var{field})

Devuelve la factorización de Cholesky de la matriz autoadjunta 
(o hermítica) @var{M}. El valor por defecto del segundo argumento
es @code{generalring}. Para una descripción de los posibles valores para
@var{field}, véase @code{lu_factor}.

@end deffn

@deffn {Función} ctranspose (@var{M})

Devuelve la transpuesta compleja conjugada de la matriz @var{M}. La función
@code{ctranspose} utiliza @code{matrix_element_transpose} para transponer
cada elemento de la matriz.

@end deffn

@deffn {Función} diag_matrix (@var{d_1}, @var{d_2}, @dots{}, @var{d_n})

Devuelve una matriz diagonal con los elementos de la diagonal iguales a
@var{d_1}, @var{d_2}, @dots{}, @var{d_n}; cuando éstos son matrices, los
elementos nulos de la matriz devuelta son matrices nulas de tamaño 
apropiado. Por ejemplo:

@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
@end deffn

@deffn {Función} dotproduct (@var{u}, @var{v})

Devuelve el producto escalar de los vectores @var{u} y @var{v}. Equivale
a @code{conjugate (transpose (@var{u})) . @var{v}}. Los argumentos @var{u} y @var{v}
deben ser vectores columna.

@end deffn



@deffn {Función} eigens_by_jacobi (@var{A})
@deffnx {Función} eigens_by_jacobi (@var{A}, @var{field_type})

Calcula los valores y vectores propios de @var{A} por el método de
las rotaciones de Jacobi. @var{A} debe ser una matriz simétrica
(aunque no necesariamente definida o semidefinida positiva).
El argumento @var{field_type} indica el tipo numérico sobre el
que se realizan los cálculos, que puede ser tanto @code{floatfield}
como @code{bigfloatfield}. En caso de que no se especifique @var{field_type},
su valor por defecto será @code{floatfield}.

Los elementos de @var{A} deben ser números o expresiones reducibles
a números mediante la ejecución de @code{float} o @code{bfloat},
según sea el valor de @var{field_type}.

Ejemplos:
@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

@end deffn




@deffn {Función} get_lu_factors (@var{x}) 

Cuando @code{@var{x} = lu_factor (@var{A})}, entonces @code{get_lu_factors}
devuelve una lista de la forma @code{[P, L, U]}, donde @var{P} es una matriz
permutación, @var{L} es triangular inferior con unos en la diagonal y @var{U}
es triangular superior, verificándose que @code{@var{A} = @var{P} @var{L} @var{U}}.

@end deffn

@deffn {Función} hankel (@var{col})
@deffnx {Función} hankel (@var{col}, @var{row})

Devuelve la matriz de Hankel @var{H}. La primera columna de @var{H} coincide
con @var{col}, excepto en el primer elemento, la última fila de @var{H} es
@var{row}. El valor por defecto para @var{row} es el vector nulo con igual
número de elementos que @var{col}.

@end deffn

@deffn {Función} hessian (@var{f}, @var{x})

Devuelve la matriz hessiana de @var{f} con respecto de la lista de variables
@var{x}. El elemento @code{(i, j)}-ésimo de la matriz
hessiana es @code{diff(@var{f}, @var{x}[i], 1, @var{x}[j], 1)}.

Ejemplos:

@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
@end deffn

@deffn {Función} hilbert_matrix (@var{n})

Devuelve la matriz de Hilbert @var{n} por @var{n}. Si @var{n} no es
un entero positivo, emite un mensaje de error.

@end deffn

@deffn {Función} identfor (@var{M})
@deffnx {Función} identfor (@var{M}, @var{fld})

Devuelve una matriz identidad con la misma forma que la matriz
@var{M}. Los elementos de la diagonal de la matriz identidad son
la identidad multiplicativa del campo @var{fld}; el valor por
defecto para @var{fld} es @var{generalring}.

El primer argumento @var{M} debe ser una matriz cuadrada o no ser
matriz en absoluto. Si @var{M} es una matriz, sus elementos pueden
ser matrices cuadradas. La matriz puede tener bloques a cualquier nivel
finito de profundidad.

Véase también @code{zerofor}

@end deffn

@deffn {Función} invert_by_lu (@var{M}, @var{(rng generalring)})

Invierte la matriz @var{M} mediante la factorización LU, la cual
se hace utilizando el anillo @var{rng}.

@end deffn


@deffn {Función} jacobian (@var{f}, @var{x})

Devuelve la matriz jacobiana de la lista de funciones @var{f} respecto
de la lista de variables @var{x}. El elemento @code{(i, j)}-ésimo de
la matriz jacobiana es @code{diff(@var{f}[i], @var{x}[j])}.

Ejemplos:

@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
@end deffn


@deffn {Función} kronecker_product (@var{A}, @var{B})

Devuelve el producto de Kroneckerde las matrices @var{A} y @var{B}.

@end deffn

@deffn {Función} listp (@var{e}, @var{p})
@deffnx {Función} listp (@var{e})

Dado el argumento opcional @var{p}, devuelve @code{true} si @var{e} es
una lista de Maxima y @var{p} toma el valor @code{true} al aplicarlo
a cada elemento de la lista. Si a @code{listp} no se le suministra el
argumento opcional, devuelve @code{true} si @var{e} es una lista de Maxima.
En cualquier otro caso, el resultado es @code{false}.

@end deffn

@deffn {Función} locate_matrix_entry (@var{M}, @var{r_1}, @var{c_1}, @var{r_2}, @var{c_2}, @var{f}, @var{rel})

El primer argumento debe ser una matriz, mientras que los argumentos
desde @var{r_1} hasta @var{c_2} determinan la submatriz de @var{M} tomando
las filas desde @var{r_1} hasta @var{r_2} y las columnas desde @var{c_1}
hasta @var{c_2}.

La función @code{locate_matrix_entry} busca en la submatriz de @var{M}
un elemento que satisfaga cierta propiedad. hay tres posibilidades:

(1) @code{@var{rel} = 'bool} y @var{f} es un predicado: 

Rastrea la submatriz de izquierda a derecha y de arriba hacia abajo,
devolviendo el índice del primer elemento que 
satisface el predicado @var{f}; si ningún elemento lo satisface,
el resultado es @code{false}.

(2) @code{@var{rel} = 'max} y @var{f} una función real:

Rastrea la submatriz buscando el elemento que maximice @var{f},
devolviendo el índice correspondiente.

(3) @code{@var{rel} = 'min} y @var{f} una función real:

Rastrea la submatriz buscando el elemento que minimice @var{f},
devolviendo el índice correspondiente.

@end deffn

@deffn {Función} lu_backsub (@var{M}, @var{b})

Si @code{@var{M} = lu_factor (@var{A}, @var{field})}, entonces
@code{lu_backsub (@var{M}, @var{b})} resuelve el sistema de ecuaciones
lineales @code{@var{A} @var{x} = @var{b}}.

@end deffn

@deffn {Función} lu_factor (@var{M}, @var{field})

Devuelve una lista de la forma @code{[@var{LU}, @var{perm}, @var{fld}]},
o @code{[@var{LU}, @var{perm}, @var{fld}, @var{lower-cnd} @var{upper-cnd}]}, donde


@itemize @bullet
@item
La matriz @var{LU} contiene la factorización de @var{M} de forma empaquetada, lo
que significa tres cosas. En primer lugar, que las filas de @var{LU} están permutadas de
acuerdo con la lista @var{perm}; por ejemplo, si @var{perm} es la lista @code{[3,2,1]},
la primera fila de la factorización @var{LU} es la tercera fila de la matriz @var{LU}.
En segundo lugar, el factor triangular inferior de @var{M} es la parte triangular inferior
de @var{LU} con los elementos de la diagonal sustituidos por unos. Por último, el factor
triangular superior de @var{M} es la parte triangular superior de @var{LU}.

@item
Si el campo es @code{floatfield} o @code{complexfield}, los números @var{lower-cnd} y
@var{upper-cnd} son las cotas inferior y superior del número de condición de la norma
infinita de @var{M}. El número de condición no se puede estimar para todos los campos,
en cuyo caso @code{lu_factor} devuelve una lista de dos elementos. Tanto la cota inferior
como la superior pueden diferir de sus valores verdaderos. Véase también @code{mat_cond}.

@end itemize

El argumento @var{M} debe ser una matriz cuadrada.

El argumento opcional @var{fld} debe ser un símbolo que determine un anillo o
un campo. Los anillos y campos predefinidos son:

@enumerate a
@item
@code{generalring} -- el anillo de las expresiones de Maxima

@item
@code{floatfield} -- el campo de los números decimales en coma flotante de doble precisión

@item
@code{complexfield} -- el campo de los números complejos decimales en coma flotante de doble precisión

@item
@code{crering}  -- el anillo de las expresiones canónicas racionales (@i{Canonical Rational Expression} o CRE) de Maxima

@item
@code{rationalfield} -- el campo de los números racionales

@item
@code{runningerror} -- controla los errores de redondeo de las operaciones en coma flotante

@item
@code{noncommutingring} -- el anillo de las expresiones de Maxima en las que el producto es el operador no conmutativo "."

@end enumerate

Si el campo es @code{floatfield}, @code{complexfield} o @code{runningerror},
el algoritmo utiliza pivoteo parcial; para los demás campos, las filas se cambian 
cuando se necesita evitar pivotes nulos.

La suma aritmética en coma flotante no es asociativa, por lo que el
significado de 'campo' no coincide exactamente con su definición matemática.

Un elemento del campo @code{runningerror} consiste en una lista de Maxima
de la forma @code{[x,n]}, donde @var{x} es un número decimal en coma flotante 
y @code{n} un enetro. La diferencia relativa entre el valor real de @code{x} y 
@code{x} está aproximadamente acotado por el valor epsilon de la máquina 
multiplicado por @code{n}. 

No es posible la definición de un nuevo campo por parte del usuario, a menos
que éste tenga conocimientos de Common Lisp. Para hacerlo, el usuario debe
definir funciones para las operaciones aritméticas y para convertir de la
representación del campo a Maxima y al revés. Además, en los campos ordenados,
donde se hace uso del pivoteo parcial, el usuario debe definir funciones para el 
módulo y para comparar números del campo. Después de lo anterior, tan solo queda
definir una estructura Common Lisp @code{mring}. El fichero @code{mring} tiene
muchos ejemplos.

Para calcular la factorización, la primera tarea consiste en convertir cada elemento
de la matriz a un elemento del campo especificado. Si la conversión no es posible,
la factorización se detiene con un mensaje de error. Los elementos del campo
no necesitan ser expresiones de Maxima; por ejemplo, los elementos de @code{complexfield}
son números complejos de Common Lisp. Tras la factorización, los elementos de la
matriz deben convertirse nuevamente a expresiones de Maxima.

Véase también  @code{get_lu_factors}.


Ejemplos:

@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

@end deffn

@deffn {Función} mat_cond (@var{M}, 1)
@deffnx {Función} mat_cond (@var{M}, inf)

Devuelve el número de condición de la @var{p}-norma de la matriz
@var{M}. Los valores admisibles para  @var{p} son 1 y @var{inf}. Esta
función utiliza la factorización LU para invertir la matriz @var{M},
por lo que el tiempo de ejecución de @code{mat_cond} es proporcional al
cubo del tamaño de la matriz; @code{lu_factor} determina las cotas inferior
y superior para el número de condición de la norma infinita en un tiempo
proporcional al cuadrado del tamaño de la matriz.

@end deffn

@deffn {Función} mat_norm (@var{M}, 1)
@deffnx {Función} mat_norm (@var{M}, inf)
@deffnx {Función} mat_norm (@var{M}, frobenius)

Devuelve la @var{p}-norma de la matriz @var{M}. Los valores admisibles
para @var{p} son 1, @code{inf} y @code{frobenius} (la norma matricial de Frobenius).
La matriz @var{M} no debe contener bloques.
@end deffn

@deffn {Función} matrixp (@var{e}, @var{p})
@deffnx {Función} matrixp (@var{e})

Dado el argumento opcional @var{p}, devuelve @code{true} si @var{e} es
una matriz y @var{p} toma el valor @code{true} al aplicarlo
a cada elemento de la matriz. Si a @code{matrixp} no se le suministra el
argumento opcional, devuelve @code{true} si @var{e} es una matriz.
En cualquier otro caso, el resultado es @code{false}.

Véase también @code{blockmatrixp}

@end deffn

@deffn {Función} matrix_size (@var{M})

Devuelve una lista con el número de filas y columnas de la matriz @var{M}.

@end deffn

@deffn {Función} mat_fullunblocker (@var{M})

Si @var{M} es una matriz de bloques, transforma la matriz llevando todos
los elementos de los bloques al primer nivel. Si @var{M} es una matriz,
devuelve @var{M}; en cualquier otro caso, envía un mensaje de error.  

@end deffn

@deffn {Función} mat_trace (@var{M})

Calcula la traza de la matriz @var{M}. Si @var{M} no es una matriz, devuelve
una forma nominal. Si @var{M} es una matriz de bloques, @code{mat_trace(M)}
calcula el mismo valor que @code{mat_trace(mat_unblocker(m))}.

@end deffn

@deffn {Función} mat_unblocker (@var{M})

Si @var{M} es una matriz de bloques, deshace los bloques de un nivel. Si @var{M}
es una matriz, @code{mat_unblocker (M)} devuelve @var{M}; en cualquier otro caso, 
envía un mensaje de error.

Si todos los elementos de @var{M} son matrices, @code{mat_unblocker (M)} devuelve
una matriz sin bloques, pero si los elementos de @var{M} son a su vez matrices de
bloques, @code{mat_unblocker (M)} devuelve una matriz con el nivel de bloques
disminuido en uno.

En caso de trabajar con matrices de bloques, quizás sea conveniente darle a
@code{matrix_element_mult} el valor @code{"."} y a @code{matrix_element_transpose}
el valor @code{'transpose}. Véase también @code{mat_fullunblocker}.

Ejemplo:

@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

@end deffn



@deffn {Función} nullspace (@var{M})

Si @var{M} es una matriz, devuelve @code{span (v_1, ..., v_n)}, siendo 
@code{@{v_1, ..., v_n@}} la base del espacio nulo de @var{M}. Si el 
espacio nulo contiene un único elemento, devuelve @code{span ()}.

@end deffn

@deffn {Función} nullity (@var{M})

Si @var{M} es una matriz, devuelve la dimensión del espacio nulo de @var{M}.

@end deffn

@deffn {Función} orthogonal_complement (@var{v_1}, @dots{}, @var{v_n})

Devuelve @code{span (u_1, ..., u_m)}, siendo @code{@{u_1, ..., u_m@}} la base
del complemento ortogonal del conjunto @code{(v_1, ..., v_n)}, cuyos elementos
deben ser vectores columna.

@end deffn

@deffn {Función} polynomialp (@var{p}, @var{L}, @var{coeffp}, @var{exponp})
@deffnx {Función} polynomialp (@var{p}, @var{L}, @var{coeffp})
@deffnx {Función} polynomialp (@var{p}, @var{L})

Devuelve @code{true} si @var{p} es un polinomio cuyas variables son las
de la lista @var{L}, el predicado @var{coeffp} toma el valor @code{true} al
aplicarlo a cada coeficiente y el predicado @var{exponp} también alcanza el
valor @code{true} al ser aplicado a los exponentes de las variables listadas en
@var{L}. En caso de necesitar que @var{exponp} no sea un predicado por defecto,
se deberá especificar también el predicado @var{coeffp}, aunque aquí
se desee su comportamiento por defecto.

@c WORK THE FOLLOWING INTO THE PRECEDING
La instrucción @code{polynomialp (@var{p}, @var{L}, @var{coeffp})} equivale a
@code{polynomialp (@var{p}, @var{L}, @var{coeffp}, 'nonnegintegerp)}, al tiempo que
@code{polynomialp (@var{p}, @var{L})} equivale a
@code{polynomialp (@var{p}, L@var{,} 'constantp, 'nonnegintegerp)}.

No es necesario expandir el polinomio:

@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

Un ejemplo utilizando valores distintos a los utilizados por defecto en 
@var{coeffp} y en @var{exponp}:

@c ===beg===
@c polynomialp ((x + 1)*(x + 2)^(3/2), [x],
@c              numberp, numberp);
@c polynomialp ((x^(1/2) + 1)*(x + 2)^(3/2), [x],
@c              numberp, 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

Polinomios con dos 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

@end deffn

@deffn {Función} polytocompanion (@var{p}, @var{x})

Si @var{p} es un polinomio en @var{x}, devuelve la matriz compañera de @var{p}. Para
un polinomio mónico @var{p} de grado @var{n} se tiene
@code{@var{p} = (-1)^@var{n} charpoly (polytocompanion (@var{p}, @var{x}))}.

Si @var{p} no es un polinomio en  @var{x}, se devuelve un mensaje de error.

@end deffn

@deffn {Función} ptriangularize (@var{M}, @var{v})

Si @var{M} es una matriz en la que sus elementos son polinomios en @var{v},
devuelve una matriz @var{M2} tal que

@enumerate
@item
@var{M2} es triangular superior,

@item
@code{@var{M2} = @var{E_n} ... @var{E_1} @var{M}}, donde @var{E_1}, ...,
@var{E_n} son matrices elementales cuyos elementos son polinomios en @var{v},

@item
@code{|det (@var{M})| = |det (@var{M2})|},
@end enumerate

Nota: esta función no comprueba si los elementos de la matriz son
polinomios en @var{v}.
@end deffn

@deffn {Función} rowop (@var{M}, @var{i}, @var{j}, @var{theta})

Si @var{M} es una matriz, devuelve la matriz que resulta de relizar la
transformación @code{R_i <- R_i - theta * R_j} con las filas @code{R_i} y 
@code{R_j}. Si @var{M} no tiene estas filas, devuelve un mensaje de error.

@end deffn

@deffn {Función} rank (@var{M})

Calcula el rango de la matriz @var{M}. El rango es la dimensión del 
espacio columna. Ejemplo:
@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

@end deffn


@deffn {Función} rowswap (@var{M}, @var{i}, @var{j})

Si @var{M} es una matriz, intercambia las filas  @var{i} y @var{j}. Si @var{M}
carece de estas filas, devuelve un mensaje de error.

@end deffn

@deffn {Función} toeplitz (@var{col})
@deffnx {Función} toeplitz (@var{col}, @var{row})

Devuelve una  matriz de Toeplitz @var{T}. La primera columna de @var{T} es @var{col},
excepto su primer elemento. La primera fila de @var{T} es @var{row}. El valor por
defecto para @var{row} es el complejo conjugado de @var{col}. Ejemplo:
@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]);
@group

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

@end deffn

@deffn {Función} vandermonde_matrix ([@var{x_1}, ..., @var{x_n}])

Devuelve una matriz @var{n} por @var{n}, cuya @var{i}-ésima fila es
@code{[1, @var{x_i}, @var{x_i}^2, ... @var{x_i}^(@var{n}-1)]}. 

@end deffn

@deffn {Función} zerofor (@var{M})
@deffnx {Función}  zerofor (@var{M}, @var{fld})

Devuelve la matriz nula con la misma estructura que la matriz @var{M}.
Cada elemento de la matriz nula es la identidad aditiva del campo @var{fld};
el valor por defecto de @var{fld} es @var{generalring}.

El primer argumento de @var{M} debe ser una matriz cuadrada o no ser matriz en
absoluto. Si @var{M} es una matriz, cada uno de sus elementos puede ser una 
matriz cuadrada, por lo que @var{M} puede ser una matriz de Maxima definida por
bloques.

Véase también @code{identfor}.

@end deffn

@deffn {Función} zeromatrixp (@var{M})

Si @var{M} no es una matriz definida por bloques, devuelve @code{true} si
 @code{is (equal (@var{e}, 0))} es verdadero para todo elemento @var{e} de
@var{M}. Si @var{M} es una matriz por bloques, devuelve @code{true} si
@code{zeromatrixp} devuelve a su vez @code{true} para cada elemento de @var{e}.

@end deffn

