This is maxima.info, produced by makeinfo version 7.1 from maxima.texi.

This is a Texinfo Maxima Manual

   Copyright 1994,2001 William F. Schelter

INFO-DIR-SECTION Math
START-INFO-DIR-ENTRY
* Maxima: (maxima).     A computer algebra system.
END-INFO-DIR-ENTRY


File: maxima.info,  Node: Matrices and Linear Algebra,  Next: Package affine,  Prev: Numerical,  Up: Top

23 Matrices and Linear Algebra
******************************

* Menu:

* Introduction to Matrices and Linear Algebra::
* Functions and Variables for Matrices and Linear Algebra::


File: maxima.info,  Node: Introduction to Matrices and Linear Algebra,  Next: Functions and Variables for Matrices and Linear Algebra,  Prev: Matrices and Linear Algebra,  Up: Matrices and Linear Algebra

23.1 Introduction to Matrices and Linear Algebra
================================================

* Menu:

* Dot::
* Matrices::
* Vectors::
* eigen::


File: maxima.info,  Node: Dot,  Next: Matrices,  Prev: Introduction to Matrices and Linear Algebra,  Up: Introduction to Matrices and Linear Algebra

23.1.1 Dot
----------

The operator ‘.’ represents noncommutative multiplication and scalar
product.  When the operands are 1-column or 1-row matrices ‘a’ and ‘b’,
the expression ‘a.b’ is equivalent to ‘sum (a[i]*b[i], i, 1,
length(a))’.  If ‘a’ and ‘b’ are not complex, this is the scalar
product, also called the inner product or dot product, of ‘a’ and ‘b’.
The scalar product is defined as ‘conjugate(a).b’ when ‘a’ and ‘b’ are
complex; ‘innerproduct’ in the ‘eigen’ package provides the complex
scalar product.

   When the operands are more general matrices, the product is the
matrix product ‘a’ and ‘b’.  The number of rows of ‘b’ must equal the
number of columns of ‘a’, and the result has number of rows equal to the
number of rows of ‘a’ and number of columns equal to the number of
columns of ‘b’.

   To distinguish ‘.’ as an arithmetic operator from the decimal point
in a floating point number, it may be necessary to leave spaces on
either side.  For example, ‘5.e3’ is ‘5000.0’ but ‘5 . e3’ is ‘5’ times
‘e3’.

   There are several flags which govern the simplification of
expressions involving ‘.’, namely ‘dot0nscsimp’, ‘dot0simp’, ‘dot1simp’,
‘dotassoc’, ‘dotconstrules’, ‘dotdistrib’, ‘dotexptsimp’, ‘dotident’,
and ‘dotscrules’.


File: maxima.info,  Node: Matrices,  Next: Vectors,  Prev: Dot,  Up: Introduction to Matrices and Linear Algebra

23.1.2 Matrices
---------------

Matrices are handled with speed and memory-efficiency in mind.  This
means that assigning a matrix to a variable will create a reference to,
not a copy of the matrix.  If the matrix is modified all references to
the matrix point to the modified object (See ‘copymatrix’ for a way of
avoiding this):
     (%i1) M1: matrix([0,0],[0,0]);
                                 [ 0  0 ]
     (%o1)                       [      ]
                                 [ 0  0 ]
     (%i2) M2: M1;
                                 [ 0  0 ]
     (%o2)                       [      ]
                                 [ 0  0 ]
     (%i3) M1[1][1]: 2;
     (%o3)                           2
     (%i4) M2;
                                 [ 2  0 ]
     (%o4)                       [      ]
                                 [ 0  0 ]

   Converting a matrix to nested lists and vice versa works the
following way:
     (%i1) l: [[1,2],[3,4]];
     (%o1)                   [[1, 2], [3, 4]]
     (%i2) M1: apply('matrix,l);
                                 [ 1  2 ]
     (%o2)                       [      ]
                                 [ 3  4 ]
     (%i3) M2: transpose(M1);
                                 [ 1  3 ]
     (%o3)                       [      ]
                                 [ 2  4 ]
     (%i4) args(M2);
     (%o4)                   [[1, 3], [2, 4]]


File: maxima.info,  Node: Vectors,  Next: eigen,  Prev: Matrices,  Up: Introduction to Matrices and Linear Algebra

23.1.3 Vectors
--------------

‘vect’ is a package of functions for vector analysis.  ‘load ("vect")’
loads this package, and ‘demo ("vect")’ displays a demonstration.

   The vector analysis package can combine and simplify symbolic
expressions including dot products and cross products, together with the
gradient, divergence, curl, and Laplacian operators.  The distribution
of these operators over sums or products is governed by several flags,
as are various other expansions, including expansion into components in
any specific orthogonal coordinate systems.  There are also functions
for deriving the scalar or vector potential of a field.

   The ‘vect’ package contains these functions: ‘vectorsimp’,
‘scalefactors’, ‘express’, ‘potential’, and ‘vectorpotential’.

   By default the ‘vect’ package does not declare the dot operator to be
a commutative operator.  To get a commutative dot operator ‘.’, the
command ‘declare(".", commutative)’ must be executed.


File: maxima.info,  Node: eigen,  Prev: Vectors,  Up: Introduction to Matrices and Linear Algebra

23.1.4 eigen
------------

The package ‘eigen’ contains several functions devoted to the symbolic
computation of eigenvalues and eigenvectors.  Maxima loads the package
automatically if one of the functions ‘eigenvalues’ or ‘eigenvectors’ is
invoked.  The package may be loaded explicitly as ‘load ("eigen")’.

   ‘demo ("eigen")’ displays a demonstration of the capabilities of this
package.  ‘batch ("eigen")’ executes the same demonstration, but without
the user prompt between successive computations.

   The functions in the ‘eigen’ package are:
‘innerproduct’, ‘unitvector’, ‘columnvector’, ‘gramschmidt’,
‘eigenvalues’,
‘eigenvectors’, ‘uniteigenvectors’, and ‘similaritytransform’.


File: maxima.info,  Node: Functions and Variables for Matrices and Linear Algebra,  Prev: Introduction to Matrices and Linear Algebra,  Up: Matrices and Linear Algebra

23.2 Functions and Variables for Matrices and Linear Algebra
============================================================

 -- Function: addcol (<M>, <list_1>, ..., <list_n>)

     Appends the column(s) given by the one or more lists (or matrices)
     onto the matrix <M>.

     See also ‘addrow’ and ‘append’.

 -- Function: addrow (<M>, <list_1>, ..., <list_n>)

     Appends the row(s) given by the one or more lists (or matrices)
     onto the matrix <M>.

     See also ‘addcol’ and ‘append’.

 -- Function: adjoint (<M>)

     Returns the adjoint of the matrix <M>.  The adjoint matrix is the
     transpose of the matrix of cofactors of <M>.

 -- Function: augcoefmatrix ([<eqn_1>, ..., <eqn_m>], [<x_1>, ...,
          <x_n>])

     Returns the augmented coefficient matrix for the variables <x_1>,
     ..., <x_n> of the system of linear equations <eqn_1>, ..., <eqn_m>.
     This is the coefficient matrix with a column adjoined for the
     constant terms in each equation (i.e., those terms not dependent
     upon <x_1>, ..., <x_n>).

          (%i1) m: [2*x - (a - 1)*y = 5*b, c + b*y + a*x = 0]$
          (%i2) augcoefmatrix (m, [x, y]);
                                 [ 2  1 - a  - 5 b ]
          (%o2)                  [                 ]
                                 [ a    b      c   ]

 -- Function: cauchy_matrix
          cauchy_matrix ([<x_1>, <x_2>, ..., <x_m>], [<y_1>, <y_2>, ...,
          <y_n>])
          cauchy_matrix ([<x_1>, <x_2>, ..., <x_n>])

     Returns a ‘n’ by <m> Cauchy matrix with the elements <a[i,j]> =
     1/(<x_i>+<y_i>).  The second argument of ‘cauchy_matrix’ is
     optional.  For this case the elements of the Cauchy matrix are
     <a[i,j]> = 1/(<x_i>+<x_j>).

     Remark: In the literature the Cauchy matrix can be found defined in
     two forms.  A second definition is <a[i,j]> = 1/(<x_i>-<y_i>).

     Examples:

          (%i1) cauchy_matrix([x1, x2], [y1, y2]);
                                [    1        1    ]
                                [ -------  ------- ]
                                [ y1 + x1  y2 + x1 ]
          (%o1)                 [                  ]
                                [    1        1    ]
                                [ -------  ------- ]
                                [ y1 + x2  y2 + x2 ]

          (%i2) cauchy_matrix([x1, x2]);
                                [   1         1    ]
                                [  ----    ------- ]
                                [  2 x1    x2 + x1 ]
          (%o2)                 [                  ]
                                [    1       1     ]
                                [ -------   ----   ]
                                [ x2 + x1   2 x2   ]

 -- Function: charpoly (<M>, <x>)

     Returns the characteristic polynomial for the matrix <M> with
     respect to variable <x>.  That is, ‘determinant (<M> - diagmatrix
     (length (<M>), <x>))’.

          (%i1) a: matrix ([3, 1], [2, 4]);
                                      [ 3  1 ]
          (%o1)                       [      ]
                                      [ 2  4 ]
          (%i2) expand (charpoly (a, lambda));
                                     2
          (%o2)                lambda  - 7 lambda + 10
          (%i3) (programmode: true, solve (%));
          (%o3)               [lambda = 5, lambda = 2]
          (%i4) matrix ([x1], [x2]);
                                       [ x1 ]
          (%o4)                        [    ]
                                       [ x2 ]
          (%i5) ev (a . % - lambda*%, %th(2)[1]);
                                    [ x2 - 2 x1 ]
          (%o5)                     [           ]
                                    [ 2 x1 - x2 ]
          (%i6) %[1, 1] = 0;
          (%o6)                     x2 - 2 x1 = 0
          (%i7) x2^2 + x1^2 = 1;
                                      2     2
          (%o7)                     x2  + x1  = 1
          (%i8) solve ([%th(2), %], [x1, x2]);
                            1               2
          (%o8) [[x1 = - -------, x2 = - -------],
                         sqrt(5)         sqrt(5)

                                                       1             2
                                              [x1 = -------, x2 = -------]]
                                                    sqrt(5)       sqrt(5)

 -- Function: coefmatrix ([<eqn_1>, ..., <eqn_m>], [<x_1>, ..., <x_n>])

     Returns the coefficient matrix for the variables <x_1>, ..., <x_n>
     of the system of linear equations <eqn_1>, ..., <eqn_m>.

          (%i1) coefmatrix([2*x-(a-1)*y+5*b = 0, b*y+a*x = 3], [x,y]);
                                           [ 2  1 - a ]
          (%o1)                            [          ]
                                           [ a    b   ]

 -- Function: col (<M>, <i>)

     Returns the <i>'th column of the matrix <M>.  The return value is a
     matrix.

 -- Function: columnvector (<L>)
 -- Function: covect (<L>)

     Returns a matrix of one column and ‘length (<L>)’ rows, containing
     the elements of the list <L>.

     ‘covect’ is a synonym for ‘columnvector’.

     ‘load ("eigen")’ loads this function.

     This is useful if you want to use parts of the outputs of the
     functions in this package in matrix calculations.

     Example:

          (%i1) load ("eigen")$
          Warning - you are redefining the Macsyma function eigenvalues
          Warning - you are redefining the Macsyma function eigenvectors
          (%i2) columnvector ([aa, bb, cc, dd]);
                                       [ aa ]
                                       [    ]
                                       [ bb ]
          (%o2)                        [    ]
                                       [ cc ]
                                       [    ]
                                       [ dd ]

 -- Function: copymatrix (<M>)

     Returns a copy of the matrix <M>.  This is the only way to make a
     copy aside from copying <M> element by element.

     Note that an assignment of one matrix to another, as in ‘m2: m1’,
     does not copy ‘m1’.  An assignment ‘m2 [i,j]: x’ or ‘setelmx(x, i,
     j, m2)’ also modifies ‘m1 [i,j]’.  Creating a copy with
     ‘copymatrix’ and then using assignment creates a separate, modified
     copy.

 -- Function: determinant (<M>)

     Computes the determinant of <M> by a method similar to Gaussian
     elimination.

     The form of the result depends upon the setting of the switch
     ‘ratmx’.

     There is a special routine for computing sparse determinants which
     is called when the switches ‘ratmx’ and ‘sparse’ are both ‘true’.

 -- Option variable: detout
     Default value: ‘false’

     When ‘detout’ is ‘true’, the determinant of a matrix whose inverse
     is computed is factored out of the inverse.

     For this switch to have an effect ‘doallmxops’ and ‘doscmxops’
     should be ‘false’ (see their descriptions).  Alternatively this
     switch can be given to ‘ev’ which causes the other two to be set
     correctly.

     Example:

          (%i1) m: matrix ([a, b], [c, d]);
                                      [ a  b ]
          (%o1)                       [      ]
                                      [ c  d ]
          (%i2) detout: true$
          (%i3) doallmxops: false$
          (%i4) doscmxops: false$
          (%i5) invert (m);
                                    [  d   - b ]
                                    [          ]
                                    [ - c   a  ]
          (%o5)                     ------------
                                     a d - b c

 -- Function: diagmatrix (<n>, <x>)

     Returns a diagonal matrix of size <n> by <n> with the diagonal
     elements all equal to <x>.  ‘diagmatrix (<n>, 1)’ returns an
     identity matrix (same as ‘ident (<n>)’).

     <n> must evaluate to an integer, otherwise ‘diagmatrix’ complains
     with an error message.

     <x> can be any kind of expression, including another matrix.  If
     <x> is a matrix, it is not copied; all diagonal elements refer to
     the same instance, <x>.

 -- Option variable: doallmxops
     Default value: ‘true’

     When ‘doallmxops’ is ‘true’, all operations relating to matrices
     are carried out.  When it is ‘false’ then the setting of the
     individual ‘dot’ switches govern which operations are performed.

 -- Option variable: domxexpt
     Default value: ‘true’

     When ‘domxexpt’ is ‘true’, a matrix exponential, ‘exp (<M>)’ where
     <M> is a matrix, is interpreted as a matrix with element ‘[i,j]’
     equal to ‘exp (m[i,j])’.  Otherwise ‘exp (<M>)’ evaluates to ‘exp
     (<ev(M)>)’.

     ‘domxexpt’ affects all expressions of the form ‘<base>^<power>’
     where <base> is an expression assumed scalar or constant, and
     <power> is a list or matrix.

     Example:

          (%i1) m: matrix ([1, %i], [a+b, %pi]);
                                   [   1    %i  ]
          (%o1)                    [            ]
                                   [ b + a  %pi ]
          (%i2) domxexpt: false$
          (%i3) (1 - c)^m;
                                       [   1    %i  ]
                                       [            ]
                                       [ b + a  %pi ]
          (%o3)                 (1 - c)
          (%i4) domxexpt: true$
          (%i5) (1 - c)^m;
                            [                      %i  ]
                            [    1 - c      (1 - c)    ]
          (%o5)             [                          ]
                            [        b + a         %pi ]
                            [ (1 - c)       (1 - c)    ]

 -- Option variable: domxmxops
     Default value: ‘true’

     When ‘domxmxops’ is ‘true’, all matrix-matrix or matrix-list
     operations are carried out (but not scalar-matrix operations); if
     this switch is ‘false’ such operations are not carried out.

 -- Option variable: domxnctimes
     Default value: ‘false’

     When ‘domxnctimes’ is ‘true’, non-commutative products of matrices
     are carried out.

 -- Option variable: dontfactor
     Default value: ‘[]’

     ‘dontfactor’ may be set to a list of variables with respect to
     which factoring is not to occur.  (The list is initially empty.)
     Factoring also will not take place with respect to any variables
     which are less important, according the variable ordering assumed
     for canonical rational expression (CRE) form, than those on the
     ‘dontfactor’ list.

 -- Option variable: doscmxops
     Default value: ‘false’

     When ‘doscmxops’ is ‘true’, scalar-matrix operations are carried
     out.

 -- Option variable: doscmxplus
     Default value: ‘false’

     When ‘doscmxplus’ is ‘true’, scalar-matrix operations yield a
     matrix result.  This switch is not subsumed under ‘doallmxops’.

 -- Option variable: dot0nscsimp
     Default value: ‘true’

     When ‘dot0nscsimp’ is ‘true’, a non-commutative product of zero and
     a nonscalar term is simplified to a commutative product.

 -- Option variable: dot0simp
     Default value: ‘true’

     When ‘dot0simp’ is ‘true’, a non-commutative product of zero and a
     scalar term is simplified to a commutative product.

 -- Option variable: dot1simp
     Default value: ‘true’

     When ‘dot1simp’ is ‘true’, a non-commutative product of one and
     another term is simplified to a commutative product.

 -- Option variable: dotassoc
     Default value: ‘true’

     When ‘dotassoc’ is ‘true’, an expression ‘(A.B).C’ simplifies to
     ‘A.(B.C)’.

 -- Option variable: dotconstrules
     Default value: ‘true’

     When ‘dotconstrules’ is ‘true’, a non-commutative product of a
     constant and another term is simplified to a commutative product.
     Turning on this flag effectively turns on ‘dot0simp’,
     ‘dot0nscsimp’, and ‘dot1simp’ as well.

 -- Option variable: dotdistrib
     Default value: ‘false’

     When ‘dotdistrib’ is ‘true’, an expression ‘A.(B + C)’ simplifies
     to ‘A.B + A.C’.

 -- Option variable: dotexptsimp
     Default value: ‘true’

     When ‘dotexptsimp’ is ‘true’, an expression ‘A.A’ simplifies to
     ‘A^^2’.

 -- Option variable: dotident
     Default value: 1

     ‘dotident’ is the value returned by ‘X^^0’.

 -- Option variable: dotscrules
     Default value: ‘false’

     When ‘dotscrules’ is ‘true’, an expression ‘A.SC’ or ‘SC.A’
     simplifies to ‘SC*A’ and ‘A.(SC*B)’ simplifies to ‘SC*(A.B)’.

 -- Function: echelon (<M>)

     Returns the echelon form of the matrix <M>, as produced by Gaussian
     elimination.  The echelon form is computed from <M> by elementary
     row operations such that the first non-zero element in each row in
     the resulting matrix is one and the column elements under the first
     one in each row are all zero.

     ‘triangularize’ also carries out Gaussian elimination, but it does
     not normalize the leading non-zero element in each row.

     ‘lu_factor’ and ‘cholesky’ are other functions which yield
     triangularized matrices.

          (%i1) M: matrix ([3, 7, aa, bb], [-1, 8, 5, 2], [9, 2, 11, 4]);
                                 [  3   7  aa  bb ]
                                 [                ]
          (%o1)                  [ - 1  8  5   2  ]
                                 [                ]
                                 [  9   2  11  4  ]
          (%i2) echelon (M);
                            [ 1  - 8  - 5      - 2     ]
                            [                          ]
                            [         28       11      ]
                            [ 0   1   --       --      ]
          (%o2)             [         37       37      ]
                            [                          ]
                            [              37 bb - 119 ]
                            [ 0   0    1   ----------- ]
                            [              37 aa - 313 ]

 -- Function: eigenvalues (<M>)
 -- Function: eivals (<M>)

     Returns a list of two lists containing the eigenvalues of the
     matrix <M>.  The first sublist of the return value is the list of
     eigenvalues of the matrix, and the second sublist is the list of
     the multiplicities of the eigenvalues in the corresponding order.

     ‘eivals’ is a synonym for ‘eigenvalues’.

     ‘eigenvalues’ calls the function ‘solve’ to find the roots of the
     characteristic polynomial of the matrix.  Sometimes ‘solve’ may not
     be able to find the roots of the polynomial; in that case some
     other functions in this package (except ‘innerproduct’,
     ‘unitvector’, ‘columnvector’ and ‘gramschmidt’) will not work.
     Sometimes ‘solve’ may find only a subset of the roots of the
     polynomial.  This may happen when the factoring of the polynomial
     contains polynomials of degree 5 or more.  In such cases a warning
     message is displayed and the only the roots found and their
     corresponding multiplicities are returned.

     In some cases the eigenvalues found by ‘solve’ may be complicated
     expressions.  (This may happen when ‘solve’ returns a
     not-so-obviously real expression for an eigenvalue which is known
     to be real.)  It may be possible to simplify the eigenvalues using
     some other functions.

     The package ‘eigen.mac’ is loaded automatically when ‘eigenvalues’
     or ‘eigenvectors’ is referenced.  If ‘eigen.mac’ is not already
     loaded, ‘load ("eigen")’ loads it.  After loading, all functions
     and variables in the package are available.

 -- Function: eigenvectors (<M>)
 -- Function: eivects (<M>)

     Computes eigenvectors of the matrix <M>.  The return value is a
     list of two elements.  The first is a list of the eigenvalues of
     <M> and a list of the multiplicities of the eigenvalues.  The
     second is a list of lists of eigenvectors.  There is one list of
     eigenvectors for each eigenvalue.  There may be one or more
     eigenvectors in each list.

     ‘eivects’ is a synonym for ‘eigenvectors’.

     The package ‘eigen.mac’ is loaded automatically when ‘eigenvalues’
     or ‘eigenvectors’ is referenced.  If ‘eigen.mac’ is not already
     loaded, ‘load ("eigen")’ loads it.  After loading, all functions
     and variables in the package are available.

     Note that ‘eigenvectors’ internally calls ‘eigenvalues’ to obtain
     eigenvalues.  So, when ‘eigenvalues’ returns a subset of all the
     eigenvalues, the ‘eigenvectors’ returns the corresponding subset of
     the all the eigenvectors, with the same warning displayed as
     ‘eigenvalues’.

     The flags that affect this function are:

     ‘nondiagonalizable’ is set to ‘true’ or ‘false’ depending on
     whether the matrix is nondiagonalizable or diagonalizable after
     ‘eigenvectors’ returns.

     ‘hermitianmatrix’ when ‘true’, causes the degenerate eigenvectors
     of the Hermitian matrix to be orthogonalized using the Gram-Schmidt
     algorithm.

     ‘knowneigvals’ when ‘true’ causes the ‘eigen’ package to assume the
     eigenvalues of the matrix are known to the user and stored under
     the global name ‘listeigvals’.  ‘listeigvals’ should be set to a
     list similar to the output ‘eigenvalues’.

     The function ‘algsys’ is used here to solve for the eigenvectors.
     Sometimes if the eigenvalues are messy, ‘algsys’ may not be able to
     find a solution.  In some cases, it may be possible to simplify the
     eigenvalues by first finding them using ‘eigenvalues’ command and
     then using other functions to reduce them to something simpler.
     Following simplification, ‘eigenvectors’ can be called again with
     the ‘knowneigvals’ flag set to ‘true’.

     See also ‘eigenvalues’.

     Examples:

     A matrix which has just one eigenvector per eigenvalue.

          (%i1) M1: matrix ([11, -1], [1, 7]);
                                     [ 11  - 1 ]
          (%o1)                      [         ]
                                     [ 1    7  ]
          (%i2) [vals, vecs] : eigenvectors (M1);
          (%o2) [[[9 - sqrt(3), sqrt(3) + 9], [1, 1]],
                                  [[[1, sqrt(3) + 2]], [[1, 2 - sqrt(3)]]]]
          (%i3) for i thru length (vals[1]) do disp (val[i] = vals[1][i],
            mult[i] = vals[2][i], vec[i] = vecs[i]);
                                 val  = 9 - sqrt(3)
                                    1

                                      mult  = 1
                                          1

                              vec  = [[1, sqrt(3) + 2]]
                                 1

                                 val  = sqrt(3) + 9
                                    2

                                      mult  = 1
                                          2

                              vec  = [[1, 2 - sqrt(3)]]
                                 2

          (%o3)                         done

     A matrix which has two eigenvectors for one eigenvalue (namely 2).

          (%i1) M1: matrix ([0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 2, 0],
                            [0, 0, 0, 2]);
                                  [ 0  1  0  0 ]
                                  [            ]
                                  [ 0  0  0  0 ]
          (%o1)                   [            ]
                                  [ 0  0  2  0 ]
                                  [            ]
                                  [ 0  0  0  2 ]
          (%i2) [vals, vecs]: eigenvectors (M1);
          (%o2) [[[0, 2], [2, 2]], [[[1, 0, 0, 0]],
                                             [[0, 0, 1, 0], [0, 0, 0, 1]]]]
          (%i3) for i thru length (vals[1]) do disp (val[i] = vals[1][i],
            mult[i] = vals[2][i], vec[i] = vecs[i]);
                                      val  = 0
                                         1

                                      mult  = 2
                                          1

                                vec  = [[1, 0, 0, 0]]
                                   1

                                      val  = 2
                                         2

                                      mult  = 2
                                          2

                         vec  = [[0, 0, 1, 0], [0, 0, 0, 1]]
                            2

          (%o3)                         done

 -- Function: ematrix (<m>, <n>, <x>, <i>, <j>)

     Returns an <m> by <n> matrix, all elements of which are zero except
     for the ‘[<i>, <j>]’ element which is <x>.

 -- Function: entermatrix (<m>, <n>)

     Returns an <m> by <n> matrix, reading the elements interactively.

     If <n> is equal to <m>, Maxima prompts for the type of the matrix
     (diagonal, symmetric, antisymmetric, or general) and for each
     element.  Each response is terminated by a semicolon ‘;’ or dollar
     sign ‘$’.

     If <n> is not equal to <m>, Maxima prompts for each element.

     The elements may be any expressions, which are evaluated.
     ‘entermatrix’ evaluates its arguments.

          (%i1) n: 3$
          (%i2) m: entermatrix (n, n)$

          Is the matrix  1. Diagonal  2. Symmetric  3. Antisymmetric
          4. General
          Answer 1, 2, 3 or 4 :
          1$
          Row 1 Column 1:
          (a+b)^n$
          Row 2 Column 2:
          (a+b)^(n+1)$
          Row 3 Column 3:
          (a+b)^(n+2)$

          Matrix entered.
          (%i3) m;
                          [        3                     ]
                          [ (b + a)      0         0     ]
                          [                              ]
          (%o3)           [                  4           ]
                          [    0      (b + a)      0     ]
                          [                              ]
                          [                            5 ]
                          [    0         0      (b + a)  ]

 -- Function: genmatrix
          genmatrix (<a>, <i_2>, <j_2>, <i_1>, <j_1>)
          genmatrix (<a>, <i_2>, <j_2>, <i_1>)
          genmatrix (<a>, <i_2>, <j_2>)

     Returns a matrix generated from <a>, taking element ‘<a>[<i_1>,
     <j_1>]’ as the upper-left element and ‘<a>[<i_2>, <j_2>]’ as the
     lower-right element of the matrix.  Here <a> is a declared array
     (created by ‘array’ but not by ‘make_array’) or a ‘hashed array’,
     or a ‘memoizing function’, or a lambda expression of two arguments.
     (A ‘memoizing function’ is created like other functions with ‘:=’
     or ‘define’, but arguments are enclosed in square brackets instead
     of parentheses.)

     If <j_1> is omitted, it is assumed equal to <i_1>.  If both <j_1>
     and <i_1> are omitted, both are assumed equal to 1.

     If a selected element ‘i,j’ of the array is undefined, the matrix
     will contain a symbolic element ‘<a>[i,j]’.

     Examples:

          (%i1) h [i, j] := 1 / (i + j - 1);
                                              1
          (%o1)                  h     := ---------
                                  i, j    i + j - 1
          (%i2) genmatrix (h, 3, 3);
                                     [    1  1 ]
                                     [ 1  -  - ]
                                     [    2  3 ]
                                     [         ]
                                     [ 1  1  1 ]
          (%o2)                      [ -  -  - ]
                                     [ 2  3  4 ]
                                     [         ]
                                     [ 1  1  1 ]
                                     [ -  -  - ]
                                     [ 3  4  5 ]
          (%i3) array (a, fixnum, 2, 2);
          (%o3)                           a
          (%i4) a [1, 1] : %e;
          (%o4)                          %e
          (%i5) a [2, 2] : %pi;
          (%o5)                          %pi
          (%i6) genmatrix (a, 2, 2);
                                     [ %e   0  ]
          (%o6)                      [         ]
                                     [ 0   %pi ]
          (%i7) genmatrix (lambda ([i, j], j - i), 3, 3);
                                   [  0    1   2 ]
                                   [             ]
          (%o7)                    [ - 1   0   1 ]
                                   [             ]
                                   [ - 2  - 1  0 ]
          (%i8) genmatrix (B, 2, 2);
                                  [ B      B     ]
                                  [  1, 1   1, 2 ]
          (%o8)                   [              ]
                                  [ B      B     ]
                                  [  2, 1   2, 2 ]

 -- Function: gramschmidt
          gramschmidt (<x>)
          gramschmidt (<x>, <F>)

     Carries out the Gram-Schmidt orthogonalization algorithm on <x>,
     which is either a matrix or a list of lists.  <x> is not modified
     by ‘gramschmidt’.  The inner product employed by ‘gramschmidt’ is
     <F>, if present, otherwise the inner product is the function
     ‘innerproduct’.

     If <x> is a matrix, the algorithm is applied to the rows of <x>.
     If <x> is a list of lists, the algorithm is applied to the
     sublists, which must have equal numbers of elements.  In either
     case, the return value is a list of lists, the sublists of which
     are orthogonal and span the same space as <x>.  If the dimension of
     the span of <x> is less than the number of rows or sublists, some
     sublists of the return value are zero.

     ‘factor’ is called at each stage of the algorithm to simplify
     intermediate results.  As a consequence, the return value may
     contain factored integers.

     ‘load("eigen")’ loads this function.

     Example:

     Gram-Schmidt algorithm using default inner product function.

          (%i1) load ("eigen")$
          (%i2) x: matrix ([1, 2, 3], [9, 18, 30], [12, 48, 60]);
                                   [ 1   2   3  ]
                                   [            ]
          (%o2)                    [ 9   18  30 ]
                                   [            ]
                                   [ 12  48  60 ]
          (%i3) y: gramschmidt (x);
                                 2      2            4     3
                                3      3   3 5      2  3  2  3
          (%o3)  [[1, 2, 3], [- ---, - --, ---], [- ----, ----, 0]]
                                2 7    7   2 7       5     5
          (%i4) map (innerproduct, [y[1], y[2], y[3]], [y[2], y[3], y[1]]);
          (%o4)                       [0, 0, 0]

     Gram-Schmidt algorithm using a specified inner product function.

          (%i1) load ("eigen")$
          (%i2) ip (f, g) := integrate (f * g, u, a, b);
          (%o2)          ip(f, g) := integrate(f g, u, a, b)
          (%i3) y: gramschmidt ([1, sin(u), cos(u)], ip), a=-%pi/2, b=%pi/2;
                                         %pi cos(u) - 2
          (%o3)              [1, sin(u), --------------]
                                              %pi
          (%i4) map (ip, [y[1], y[2], y[3]], [y[2], y[3], y[1]]), a=-%pi/2,
                   b=%pi/2;
          (%o4)                       [0, 0, 0]

 -- Function: ident (<n>)

     Returns an <n> by <n> identity matrix.

 -- Function: innerproduct (<x>, <y>)
 -- Function: inprod (<x>, <y>)

     Returns the inner product (also called the scalar product or dot
     product) of <x> and <y>, which are lists of equal length, or both
     1-column or 1-row matrices of equal length.  The return value is
     ‘conjugate (x) . y’, where ‘.’ is the noncommutative multiplication
     operator.

     ‘load ("eigen")’ loads this function.

     ‘inprod’ is a synonym for ‘innerproduct’.

 -- Function: invert_by_adjoint (<M>)
     Returns the inverse of the matrix <M>.  The inverse is computed by
     the adjoint method.

     ‘invert_by_adjoint’ honors the ‘ratmx’ and ‘detout’ flags, the same
     as ‘invert’.

 -- Function: invert (<M>)

     Returns the inverse of the matrix <M>.  The inverse is computed via
     the LU decomposition.

     When ‘ratmx’ is ‘true’, elements of <M> are converted to canonical
     rational expressions (CRE), and the elements of the return value
     are also CRE.

     When ‘ratmx’ is ‘false’, elements of <M> are not converted to a
     common representation.  In particular, float and bigfloat elements
     are not converted to rationals.

     When ‘detout’ is ‘true’, the determinant is factored out of the
     inverse.  The global flags ‘doallmxops’ and ‘doscmxops’ must be
     ‘false’ to prevent the determinant from being absorbed into the
     inverse.  ‘xthru’ can multiply the determinant into the inverse.

     ‘invert’ does not apply any simplifications to the elements of the
     inverse apart from the default arithmetic simplifications.
     ‘ratsimp’ and ‘expand’ can apply additional simplifications.  In
     particular, when <M> has polynomial elements, ‘expand(invert(<M>))’
     might be preferable.

     ‘invert(<M>)’ is equivalent to ‘<M>^^-1’.

 -- Function: list_matrix_entries (<M>)

     Returns a list containing the elements of the matrix <M>.

     Example:

          (%i1) list_matrix_entries(matrix([a,b],[c,d]));
          (%o1)                     [a, b, c, d]

 -- Option variable: lmxchar
     Default value: ‘[’

     ‘lmxchar’ is the character displayed as the left delimiter of a
     matrix.  See also ‘rmxchar’.

     Example:

          (%i1) lmxchar: "|"$
          (%i2) matrix ([a, b, c], [d, e, f], [g, h, i]);
                                     | a  b  c ]
                                     |         ]
          (%o2)                      | d  e  f ]
                                     |         ]
                                     | g  h  i ]

 -- Function: matrix (<row_1>, ..., <row_n>)

     Returns a rectangular matrix which has the rows <row_1>, ...,
     <row_n>.  Each row is a list of expressions.  All rows must be the
     same length.

     The operations ‘+’ (addition), ‘-’ (subtraction), ‘*’
     (multiplication), and ‘/’ (division), are carried out element by
     element when the operands are two matrices, a scalar and a matrix,
     or a matrix and a scalar.  The operation ‘^’ (exponentiation,
     equivalently ‘**’) is carried out element by element if the
     operands are a scalar and a matrix or a matrix and a scalar, but
     not if the operands are two matrices.  All operations are normally
     carried out in full, including ‘.’ (noncommutative multiplication).

     Matrix multiplication is represented by the noncommutative
     multiplication operator ‘.’.  The corresponding noncommutative
     exponentiation operator is ‘^^’.  For a matrix ‘<A>’, ‘<A>.<A> =
     <A>^^2’ and ‘<A>^^-1’ is the inverse of <A>, if it exists.
     ‘<A>^^-1’ is equivalent to ‘invert(<A>)’.

     There are switches for controlling simplification of expressions
     involving dot and matrix-list operations.  These are ‘doallmxops’,
     ‘domxexpt’, ‘domxmxops’, ‘doscmxops’, and ‘doscmxplus’.

     There are additional options which are related to matrices.  These
     are: ‘lmxchar’, ‘rmxchar’, ‘ratmx’, ‘listarith’, ‘detout’,
     ‘scalarmatrix’ and ‘sparse’.

     There are a number of functions which take matrices as arguments or
     yield matrices as return values.  See ‘eigenvalues’,
     ‘eigenvectors’, ‘determinant’, ‘charpoly’, ‘genmatrix’, ‘addcol’,
     ‘addrow’, ‘copymatrix’, ‘transpose’, ‘echelon’, and ‘rank’.

     Examples:

        • Construction of matrices from lists.
          (%i1) x: matrix ([17, 3], [-8, 11]);
                                     [ 17   3  ]
          (%o1)                      [         ]
                                     [ - 8  11 ]
          (%i2) y: matrix ([%pi, %e], [a, b]);
                                     [ %pi  %e ]
          (%o2)                      [         ]
                                     [  a   b  ]
        • Addition, element by element.
          (%i3) x + y;
                                [ %pi + 17  %e + 3 ]
          (%o3)                 [                  ]
                                [  a - 8    b + 11 ]
        • Subtraction, element by element.
          (%i4) x - y;
                                [ 17 - %pi  3 - %e ]
          (%o4)                 [                  ]
                                [ - a - 8   11 - b ]
        • Multiplication, element by element.
          (%i5) x * y;
                                  [ 17 %pi  3 %e ]
          (%o5)                   [              ]
                                  [ - 8 a   11 b ]
        • Division, element by element.
          (%i6) x / y;
                                  [ 17       - 1 ]
                                  [ ---  3 %e    ]
                                  [ %pi          ]
          (%o6)                   [              ]
                                  [   8    11    ]
                                  [ - -    --    ]
                                  [   a    b     ]
        • Matrix to a scalar exponent, element by element.
          (%i7) x ^ 3;
                                   [ 4913    27  ]
          (%o7)                    [             ]
                                   [ - 512  1331 ]
        • Scalar base to a matrix exponent, element by element.
          (%i8) exp(y);
                                   [   %pi    %e ]
                                   [ %e     %e   ]
          (%o8)                    [             ]
                                   [    a     b  ]
                                   [  %e    %e   ]
        • Matrix base to a matrix exponent.  This is not carried out
          element by element.  See also ‘matrixexp’.
          (%i9) x ^ y;
                                          [ %pi  %e ]
                                          [         ]
                                          [  a   b  ]
                               [ 17   3  ]
          (%o9)                [         ]
                               [ - 8  11 ]
        • Noncommutative matrix multiplication.
          (%i10) x . y;
                            [ 3 a + 17 %pi  3 b + 17 %e ]
          (%o10)            [                           ]
                            [ 11 a - 8 %pi  11 b - 8 %e ]
          (%i11) y . x;
                          [ 17 %pi - 8 %e  3 %pi + 11 %e ]
          (%o11)          [                              ]
                          [  17 a - 8 b     11 b + 3 a   ]
        • Noncommutative matrix exponentiation.  A scalar base <b> to a
          matrix power <M> is carried out element by element and so
          ‘b^^m’ is the same as ‘b^m’.
          (%i12) x ^^ 3;
                                  [  3833   1719 ]
          (%o12)                  [              ]
                                  [ - 4584  395  ]
          (%i13) %e ^^ y;
                                   [   %pi    %e ]
                                   [ %e     %e   ]
          (%o13)                   [             ]
                                   [    a     b  ]
                                   [  %e    %e   ]
        • A matrix raised to a -1 exponent with noncommutative
          exponentiation is the matrix inverse, if it exists.
          (%i14) x ^^ -1;
                                   [ 11      3  ]
                                   [ ---  - --- ]
                                   [ 211    211 ]
          (%o14)                   [            ]
                                   [  8    17   ]
                                   [ ---   ---  ]
                                   [ 211   211  ]
          (%i15) x . (x ^^ -1);
                                      [ 1  0 ]
          (%o15)                      [      ]
                                      [ 0  1 ]

 -- Function: matrixexp
          matrixexp (<M>)
          matrixexp (<M>, <n>)
          matrixexp (<M>, <V>)

     Calculates the matrix exponential

     e^(M*V)

     .  Instead of the vector <V> a number <n> can be specified as the
     second argument.  If this argument is omitted ‘matrixexp’ replaces
     it by ‘1’.

     The matrix exponential of a matrix <M> can be expressed as a power
     series: e^M=sum(M^k/k!,0,inf)

 -- Function: matrixmap (<f>, <M>)

     Returns a matrix with element ‘i,j’ equal to ‘<f>(<M>[i,j])’.

     See also ‘map’, ‘fullmap’, ‘fullmapl’, and ‘apply’.

 -- Function: matrixp (<expr>)

     Returns ‘true’ if <expr> is a matrix, otherwise ‘false’.

 -- Option variable: matrix_element_add
     Default value: ‘+’

     ‘matrix_element_add’ is the operation invoked in place of addition
     in a matrix multiplication.  ‘matrix_element_add’ can be assigned
     any n-ary operator (that is, a function which handles any number of
     arguments).  The assigned value may be the name of an operator
     enclosed in quote marks, the name of a function, or a lambda
     expression.

     See also ‘matrix_element_mult’ and ‘matrix_element_transpose’.

     Example:

          (%i1) matrix_element_add: "*"$
          (%i2) matrix_element_mult: "^"$
          (%i3) aa: matrix ([a, b, c], [d, e, f]);
                                     [ a  b  c ]
          (%o3)                      [         ]
                                     [ d  e  f ]
          (%i4) bb: matrix ([u, v, w], [x, y, z]);
                                     [ u  v  w ]
          (%o4)                      [         ]
                                     [ x  y  z ]
          (%i5) aa . transpose (bb);
                               [  u  v  w   x  y  z ]
                               [ a  b  c   a  b  c  ]
          (%o5)                [                    ]
                               [  u  v  w   x  y  z ]
                               [ d  e  f   d  e  f  ]

 -- Option variable: matrix_element_mult
     Default value: ‘*’

     ‘matrix_element_mult’ is the operation invoked in place of
     multiplication in a matrix multiplication.  ‘matrix_element_mult’
     can be assigned any binary operator.  The assigned value may be the
     name of an operator enclosed in quote marks, the name of a
     function, or a lambda expression.

     The dot operator ‘.’ is a useful choice in some contexts.

     See also ‘matrix_element_add’ and ‘matrix_element_transpose’.

     Example:

          (%i1) matrix_element_add: lambda ([[x]], sqrt (apply ("+", x)))$
          (%i2) matrix_element_mult: lambda ([x, y], (x - y)^2)$
          (%i3) [a, b, c] . [x, y, z];
                                    2          2          2
          (%o3)         sqrt((c - z)  + (b - y)  + (a - x) )
          (%i4) aa: matrix ([a, b, c], [d, e, f]);
                                     [ a  b  c ]
          (%o4)                      [         ]
                                     [ d  e  f ]
          (%i5) bb: matrix ([u, v, w], [x, y, z]);
                                     [ u  v  w ]
          (%o5)                      [         ]
                                     [ x  y  z ]
          (%i6) aa . transpose (bb);
                         [             2          2          2  ]
                         [ sqrt((c - w)  + (b - v)  + (a - u) ) ]
          (%o6)  Col 1 = [                                      ]
                         [             2          2          2  ]
                         [ sqrt((f - w)  + (e - v)  + (d - u) ) ]

                                   [             2          2          2  ]
                                   [ sqrt((c - z)  + (b - y)  + (a - x) ) ]
                           Col 2 = [                                      ]
                                   [             2          2          2  ]
                                   [ sqrt((f - z)  + (e - y)  + (d - x) ) ]

 -- Option variable: matrix_element_transpose
     Default value: ‘false’

     ‘matrix_element_transpose’ is the operation applied to each element
     of a matrix when it is transposed.  ‘matrix_element_mult’ can be
     assigned any unary operator.  The assigned value may be the name of
     an operator enclosed in quote marks, the name of a function, or a
     lambda expression.

     When ‘matrix_element_transpose’ equals ‘transpose’, the ‘transpose’
     function is applied to every element.  When
     ‘matrix_element_transpose’ equals ‘nonscalars’, the ‘transpose’
     function is applied to every nonscalar element.  If some element is
     an atom, the ‘nonscalars’ option applies ‘transpose’ only if the
     atom is declared nonscalar, while the ‘transpose’ option always
     applies ‘transpose’.

     The default value, ‘false’, means no operation is applied.

     See also ‘matrix_element_add’ and ‘matrix_element_mult’.

     Examples:

          (%i1) declare (a, nonscalar)$
          (%i2) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o2)                   [              ]
                                  [      b       ]
          (%i3) matrix_element_transpose: nonscalars$
          (%i4) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o4)                   [              ]
                                  [      b       ]
          (%i5) matrix_element_transpose: transpose$
          (%i6) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o6)                   [              ]
                                  [ transpose(b) ]
          (%i7) matrix_element_transpose: lambda ([x], realpart(x)
                - %i*imagpart(x))$
          (%i8) m: matrix ([1 + 5*%i, 3 - 2*%i], [7*%i, 11]);
                               [ 5 %i + 1  3 - 2 %i ]
          (%o8)                [                    ]
                               [   7 %i       11    ]
          (%i9) transpose (m);
                                [ 1 - 5 %i  - 7 %i ]
          (%o9)                 [                  ]
                                [ 2 %i + 3    11   ]

 -- Function: mattrace (<M>)

     Returns the trace (that is, the sum of the elements on the main
     diagonal) of the square matrix <M>.

     ‘mattrace’ is called by ‘ncharpoly’, an alternative to Maxima's
     ‘charpoly’.

     ‘load ("nchrpl")’ loads this function.

 -- Function: minor (<M>, <i>, <j>)

     Returns the <i>, <j> minor of the matrix <M>.  That is, <M> with
     row <i> and column <j> removed.

 -- Function: ncharpoly (<M>, <x>)

     Returns the characteristic polynomial of the matrix <M> with
     respect to <x>.  This is an alternative to Maxima's ‘charpoly’.

     ‘ncharpoly’ works by computing traces of powers of the given
     matrix, which are known to be equal to sums of powers of the roots
     of the characteristic polynomial.  From these quantities the
     symmetric functions of the roots can be calculated, which are
     nothing more than the coefficients of the characteristic
     polynomial.  ‘charpoly’ works by forming the determinant of ‘<x> *
     ident [n] - a’.  Thus ‘ncharpoly’ wins, for example, in the case of
     large dense matrices filled with integers, since it avoids
     polynomial arithmetic altogether.

     ‘load ("nchrpl")’ loads this file.

 -- Function: newdet (<M>)

     Computes the determinant of the matrix <M> by the Johnson-Gentleman
     tree minor algorithm.  ‘newdet’ returns the result in CRE form.

 -- Function: permanent (<M>)

     Computes the permanent of the matrix <M> by the Johnson-Gentleman
     tree minor algorithm.  A permanent is like a determinant but with
     no sign changes.  ‘permanent’ returns the result in CRE form.

     See also ‘newdet’.

 -- Function: rank (<M>)

     Computes the rank of the matrix <M>.  That is, the order of the
     largest non-singular subdeterminant of <M>.

     <rank> may return the wrong answer if it cannot determine that a
     matrix element that is equivalent to zero is indeed so.

 -- Option variable: ratmx
     Default value: ‘false’

     When ‘ratmx’ is ‘false’, determinant and matrix addition,
     subtraction, and multiplication are performed in the representation
     of the matrix elements and cause the result of matrix inversion to
     be left in general representation.

     When ‘ratmx’ is ‘true’, the 4 operations mentioned above are
     performed in CRE form and the result of matrix inverse is in CRE
     form.  Note that this may cause the elements to be expanded
     (depending on the setting of ‘ratfac’) which might not always be
     desired.

 -- Function: row (<M>, <i>)

     Returns the <i>'th row of the matrix <M>.  The return value is a
     matrix.

 -- Option variable: rmxchar
     Default value: ‘]’

     ‘rmxchar’ is the character drawn on the right-hand side of a
     matrix.

     See also ‘lmxchar’.

 -- Option variable: scalarmatrixp
     Default value: ‘true’

     When ‘scalarmatrixp’ is ‘true’, then whenever a 1 x 1 matrix is
     produced as a result of computing the dot product of matrices it is
     simplified to a scalar, namely the sole element of the matrix.

     When ‘scalarmatrixp’ is ‘all’, then all 1 x 1 matrices are
     simplified to scalars.

     When ‘scalarmatrixp’ is ‘false’, 1 x 1 matrices are not simplified
     to scalars.

 -- Function: scalefactors (<coordinatetransform>)

     Here the argument <coordinatetransform> evaluates to the form
     ‘[[expression1, expression2, ...], indeterminate1, indeterminat2,
     ...]’, where the variables <indeterminate1>, <indeterminate2>, etc.
     are the curvilinear coordinate variables and where a set of
     rectangular Cartesian components is given in terms of the
     curvilinear coordinates by ‘[expression1, expression2, ...]’.
     ‘coordinates’ is set to the vector ‘[indeterminate1,
     indeterminate2,...]’, and ‘dimension’ is set to the length of this
     vector.  SF[1], SF[2], ..., SF[DIMENSION] are set to the coordinate
     scale factors, and ‘sfprod’ is set to the product of these scale
     factors.  Initially, ‘coordinates’ is ‘[X, Y, Z]’, ‘dimension’ is
     3, and SF[1]=SF[2]=SF[3]=SFPROD=1, corresponding to 3-dimensional
     rectangular Cartesian coordinates.  To expand an expression into
     physical components in the current coordinate system, there is a
     function with usage of the form

 -- Function: setelmx (<x>, <i>, <j>, <M>)

     Assigns <x> to the (<i>, <j>)'th element of the matrix <M>, and
     returns the altered matrix.

     ‘<M> [<i>, <j>]: <x>’ has the same effect, but returns <x> instead
     of <M>.

 -- Function: similaritytransform (<M>)
 -- Function: simtran (<M>)

     ‘similaritytransform’ computes a similarity transform of the matrix
     ‘M’.  It returns a list which is the output of the
     ‘uniteigenvectors’ command.  In addition if the flag
     ‘nondiagonalizable’ is ‘false’ two global matrices ‘leftmatrix’ and
     ‘rightmatrix’ are computed.  These matrices have the property that
     ‘leftmatrix . <M> . rightmatrix’ is a diagonal matrix with the
     eigenvalues of <M> on the diagonal.  If ‘nondiagonalizable’ is
     ‘true’ the left and right matrices are not computed.

     If the flag ‘hermitianmatrix’ is ‘true’ then ‘leftmatrix’ is the
     complex conjugate of the transpose of ‘rightmatrix’.  Otherwise
     ‘leftmatrix’ is the inverse of ‘rightmatrix’.

     ‘rightmatrix’ is the matrix the columns of which are the unit
     eigenvectors of <M>.  The other flags (see ‘eigenvalues’ and
     ‘eigenvectors’) have the same effects since ‘similaritytransform’
     calls the other functions in the package in order to be able to
     form ‘rightmatrix’.

     ‘load ("eigen")’ loads this function.

     ‘simtran’ is a synonym for ‘similaritytransform’.

 -- Option variable: sparse
     Default value: ‘false’

     When ‘sparse’ is ‘true’, and if ‘ratmx’ is ‘true’, then
     ‘determinant’ will use special routines for computing sparse
     determinants.

 -- Function: submatrix
          submatrix (<i_1>, ..., <i_m>, <M>, <j_1>, ..., <j_n>)
          submatrix (<i_1>, ..., <i_m>, <M>)
          submatrix (<M>, <j_1>, ..., <j_n>)

     Returns a new matrix composed of the matrix <M> with rows <i_1>,
     ..., <i_m> deleted, and columns <j_1>, ..., <j_n> deleted.

 -- Function: transpose (<M>)

     Returns the transpose of <M>.

     If <M> is a matrix, the return value is another matrix <N> such
     that ‘N[i,j] = M[j,i]’.

     If <M> is a list, the return value is a matrix <N> of ‘length (m)’
     rows and 1 column, such that ‘N[i,1] = M[i]’.

     Otherwise <M> is a symbol, and the return value is a noun
     expression ‘'transpose (<M>)’.

 -- Function: triangularize (<M>)

     Returns the upper triangular form of the matrix ‘M’, as produced by
     Gaussian elimination.  The return value is the same as ‘echelon’,
     except that the leading nonzero coefficient in each row is not
     normalized to 1.

     ‘lu_factor’ and ‘cholesky’ are other functions which yield
     triangularized matrices.

          (%i1) M: matrix ([3, 7, aa, bb], [-1, 8, 5, 2], [9, 2, 11, 4]);
                                 [  3   7  aa  bb ]
                                 [                ]
          (%o1)                  [ - 1  8  5   2  ]
                                 [                ]
                                 [  9   2  11  4  ]
          (%i2) triangularize (M);
                       [ - 1   8         5            2      ]
                       [                                     ]
          (%o2)        [  0   - 74     - 56         - 22     ]
                       [                                     ]
                       [  0    0    626 - 74 aa  238 - 74 bb ]

 -- Function: uniteigenvectors (<M>)
 -- Function: ueivects (<M>)

     Computes unit eigenvectors of the matrix <M>.  The return value is
     a list of lists, the first sublist of which is the output of the
     ‘eigenvalues’ command, and the other sublists of which are the unit
     eigenvectors of the matrix corresponding to those eigenvalues
     respectively.

     The flags mentioned in the description of the ‘eigenvectors’
     command have the same effects in this one as well.

     When ‘knowneigvects’ is ‘true’, the ‘eigen’ package assumes that
     the eigenvectors of the matrix are known to the user and are stored
     under the global name ‘listeigvects’.  ‘listeigvects’ should be set
     to a list similar to the output of the ‘eigenvectors’ command.

     If ‘knowneigvects’ is set to ‘true’ and the list of eigenvectors is
     given the setting of the flag ‘nondiagonalizable’ may not be
     correct.  If that is the case please set it to the correct value.
     The author assumes that the user knows what he is doing and will
     not try to diagonalize a matrix the eigenvectors of which do not
     span the vector space of the appropriate dimension.

     ‘load ("eigen")’ loads this function.

     ‘ueivects’ is a synonym for ‘uniteigenvectors’.

 -- Function: unitvector (<x>)
 -- Function: uvect (<x>)

     Returns <x>/norm(<x>); this is a unit vector in the same direction
     as <x>.

     ‘load ("eigen")’ loads this function.

     ‘uvect’ is a synonym for ‘unitvector’.

 -- Function: vectorpotential (<givencurl>)

     Returns the vector potential of a given curl vector, in the current
     coordinate system.  ‘potentialzeroloc’ has a similar role as for
     ‘potential’, but the order of the left-hand sides of the equations
     must be a cyclic permutation of the coordinate variables.

 -- Function: vectorsimp (<expr>)

     Applies simplifications and expansions according to the following
     global flags:

     ‘expandall’, ‘expanddot’, ‘expanddotplus’, ‘expandcross’, ‘expandcrossplus’,
     ‘expandcrosscross’, ‘expandgrad’, ‘expandgradplus’, ‘expandgradprod’,
     ‘expanddiv’, ‘expanddivplus’, ‘expanddivprod’, ‘expandcurl’, ‘expandcurlplus’,
     ‘expandcurlcurl’, ‘expandlaplacian’, ‘expandlaplacianplus’,
     and ‘expandlaplacianprod’.

     All these flags have default value ‘false’.  The ‘plus’ suffix
     refers to employing additivity or distributivity.  The ‘prod’
     suffix refers to the expansion for an operand that is any kind of
     product.

     ‘expandcrosscross’
          Simplifies p ~ (q ~ r) to (p . r)*q-(p . q)*r .
     ‘expandcurlcurl’
          Simplifies curl curl p to grad div p + div grad p .
     ‘expandlaplaciantodivgrad’
          Simplifies laplacian p to div grad p .
     ‘expandcross’
          Enables ‘expandcrossplus’ and ‘expandcrosscross’.
     ‘expandplus’
          Enables ‘expanddotplus’, ‘expandcrossplus’, ‘expandgradplus’,
          ‘expanddivplus’, ‘expandcurlplus’, and ‘expandlaplacianplus’.
     ‘expandprod’
          Enables ‘expandgradprod’, ‘expanddivprod’, and
          ‘expandlaplacianprod’.

     These flags have all been declared ‘evflag’.

 -- Option variable: vect_cross
     Default value: ‘false’

     When ‘vect_cross’ is ‘true’, it allows DIFF(X~Y,T) to work where ~
     is defined in SHARE;VECT (where VECT_CROSS is set to ‘true’,
     anyway.)

 -- Function: zeromatrix (<m>, <n>)

     Returns an <m> by <n> matrix, all elements of which are zero.


File: maxima.info,  Node: Package affine,  Next: Package itensor,  Prev: Matrices and Linear Algebra,  Up: Top

24 Package affine
*****************

* Menu:

* Introduction to Affine::
* Functions and Variables for Affine::


File: maxima.info,  Node: Introduction to Affine,  Next: Functions and Variables for Affine,  Prev: Package affine,  Up: Package affine

24.1 Introduction to Affine
===========================

‘affine’ is a package to work with groups of polynomials.


File: maxima.info,  Node: Functions and Variables for Affine,  Prev: Introduction to Affine,  Up: Package affine

24.2 Functions and Variables for Affine
=======================================

 -- Function: fast_linsolve ([<expr_1>, ..., <expr_m>], [<x_1>, ...,
          <x_n>])
     Solves the simultaneous linear equations <expr_1>, ..., <expr_m>
     for the variables <x_1>, ..., <x_n>.  Each <expr_i> may be an
     equation or a general expression; if given as a general expression,
     it is treated as an equation of the form ‘<expr_i> = 0’.

     The return value is a list of equations of the form ‘[<x_1> =
     <a_1>, ..., <x_n> = <a_n>]’ where <a_1>, ..., <a_n> are all free of
     <x_1>, ..., <x_n>.

     ‘fast_linsolve’ is faster than ‘linsolve’ for system of equations
     which are sparse.

     ‘load("affine")’ loads this function.

 -- Function: grobner_basis ([<expr_1>, ..., <expr_m>])
     Returns a Groebner basis for the equations <expr_1>, ..., <expr_m>.
     The function ‘polysimp’ can then be used to simplify other
     functions relative to the equations.

          grobner_basis ([3*x^2+1, y*x])$

          polysimp (y^2*x + x^3*9 + 2) ==> -3*x + 2

     ‘polysimp(f)’ yields 0 if and only if <f> is in the ideal generated
     by <expr_1>, ..., <expr_m>, that is, if and only if <f> is a
     polynomial combination of the elements of <expr_1>, ..., <expr_m>.

     ‘load("affine")’ loads this function.

 -- Function: set_up_dot_simplifications
          set_up_dot_simplifications (<eqns>, <check_through_degree>)
          set_up_dot_simplifications (<eqns>)

     The <eqns> are polynomial equations in non commutative variables.
     The value of ‘current_variables’ is the list of variables used for
     computing degrees.  The equations must be homogeneous, in order for
     the procedure to terminate.

     If you have checked overlapping simplifications in
     ‘dot_simplifications’ above the degree of <f>, then the following
     is true: ‘dotsimp (<f>)’ yields 0 if and only if <f> is in the
     ideal generated by the equations, i.e., if and only if <f> is a
     polynomial combination of the elements of the equations.

     The degree is that returned by ‘nc_degree’.  This in turn is
     influenced by the weights of individual variables.

     ‘load("affine")’ loads this function.

 -- Function: declare_weights (<x_1>, <w_1>, ..., <x_n>, <w_n>)
     Assigns weights <w_1>, ..., <w_n> to <x_1>, ..., <x_n>,
     respectively.  These are the weights used in computing ‘nc_degree’.

     ‘load("affine")’ loads this function.

 -- Function: nc_degree (<p>)
     Returns the degree of a noncommutative polynomial <p>.  See
     ‘declare_weights’.

     ‘load("affine")’ loads this function.

 -- Function: dotsimp (<f>)
     Returns 0 if and only if <f> is in the ideal generated by the
     equations, i.e., if and only if <f> is a polynomial combination of
     the elements of the equations.

     ‘load("affine")’ loads this function.

 -- Function: fast_central_elements ([<x_1>, ..., <x_n>], <n>)
     If ‘set_up_dot_simplifications’ has been previously done, finds the
     central polynomials in the variables <x_1>, ..., <x_n> in the given
     degree, <n>.

     For example:
          set_up_dot_simplifications ([y.x + x.y], 3);
          fast_central_elements ([x, y], 2);
          [y.y, x.x];

     ‘load("affine")’ loads this function.

 -- Function: check_overlaps (<n>, <add_to_simps>)
     Checks the overlaps thru degree <n>, making sure that you have
     sufficient simplification rules in each degree, for ‘dotsimp’ to
     work correctly.  This process can be speeded up if you know before
     hand what the dimension of the space of monomials is.  If it is of
     finite global dimension, then ‘hilbert’ should be used.  If you
     don't know the monomial dimensions, do not specify a
     ‘rank_function’.  An optional third argument ‘reset’, ‘false’ says
     don't bother to query about resetting things.

     ‘load("affine")’ loads this function.

 -- Function: mono ([<x_1>, ..., <x_n>], <n>)
     Returns the list of independent monomials relative to the current
     dot simplifications of degree <n> in the variables <x_1>, ...,
     <x_n>.

     ‘load("affine")’ loads this function.

 -- Function: monomial_dimensions (<n>)
     Compute the Hilbert series through degree <n> for the current
     algebra.

     ‘load("affine")’ loads this function.

 -- Function: extract_linear_equations ([<p_1>, ..., <p_n>], [<m_1>,
          ..., <m_n>])

     Makes a list of the coefficients of the noncommutative polynomials
     <p_1>, ..., <p_n> of the noncommutative monomials <m_1>, ...,
     <m_n>.  The coefficients should be scalars.  Use
     ‘list_nc_monomials’ to build the list of monomials.

     ‘load("affine")’ loads this function.

 -- Function: list_nc_monomials
          list_nc_monomials ([<p_1>, ..., <p_n>])
          list_nc_monomials (<p>)

     Returns a list of the non commutative monomials occurring in a
     polynomial <p> or a list of polynomials <p_1>, ..., <p_n>.

     ‘load("affine")’ loads this function.

 -- Option variable: all_dotsimp_denoms
     Default value: ‘false’

     When ‘all_dotsimp_denoms’ is a list, the denominators encountered
     by ‘dotsimp’ are appended to the list.  ‘all_dotsimp_denoms’ may be
     initialized to an empty list ‘[]’ before calling ‘dotsimp’.

     By default, denominators are not collected by ‘dotsimp’.


File: maxima.info,  Node: Package itensor,  Next: Package ctensor,  Prev: Package affine,  Up: Top

25 Package itensor
******************

* Menu:

* Introduction to itensor::
* Functions and Variables for itensor::


File: maxima.info,  Node: Introduction to itensor,  Next: Functions and Variables for itensor,  Prev: Package itensor,  Up: Package itensor

25.1 Introduction to itensor
============================

Maxima implements symbolic tensor manipulation of two distinct types:
component tensor manipulation (package ‘ctensor’) and indicial tensor
manipulation (package ‘itensor’).

   Nota bene: Please see the note on 'new tensor notation' below.

   Component tensor manipulation means that geometrical tensor objects
are represented as arrays or matrices.  Tensor operations such as
contraction or covariant differentiation are carried out by actually
summing over repeated (dummy) indices with ‘do’ statements.  That is,
one explicitly performs operations on the appropriate tensor components
stored in an array or matrix.

   Indicial tensor manipulation is implemented by representing tensors
as functions of their covariant, contravariant and derivative indices.
Tensor operations such as contraction or covariant differentiation are
performed by manipulating the indices themselves rather than the
components to which they correspond.

   These two approaches to the treatment of differential, algebraic and
analytic processes in the context of Riemannian geometry have various
advantages and disadvantages which reveal themselves only through the
particular nature and difficulty of the user's problem.  However, one
should keep in mind the following characteristics of the two
implementations:

   The representation of tensors and tensor operations explicitly in
terms of their components makes ‘ctensor’ easy to use.  Specification of
the metric and the computation of the induced tensors and invariants is
straightforward.  Although all of Maxima's powerful simplification
capacity is at hand, a complex metric with intricate functional and
coordinate dependencies can easily lead to expressions whose size is
excessive and whose structure is hidden.  In addition, many calculations
involve intermediate expressions which swell causing programs to
terminate before completion.  Through experience, a user can avoid many
of these difficulties.

   Because of the special way in which tensors and tensor operations are
represented in terms of symbolic operations on their indices,
expressions which in the component representation would be unmanageable
can sometimes be greatly simplified by using the special routines for
symmetrical objects in ‘itensor’.  In this way the structure of a large
expression may be more transparent.  On the other hand, because of the
special indicial representation in ‘itensor’, in some cases the user may
find difficulty with the specification of the metric, function
definition, and the evaluation of differentiated "indexed" objects.

   The ‘itensor’ package can carry out differentiation with respect to
an indexed variable, which allows one to use the package when dealing
with Lagrangian and Hamiltonian formalisms.  As it is possible to
differentiate a field Lagrangian with respect to an (indexed) field
variable, one can use Maxima to derive the corresponding Euler-Lagrange
equations in indicial form.  These equations can be translated into
component tensor (‘ctensor’) programs using the ‘ic_convert’ function,
allowing us to solve the field equations in a particular coordinate
representation, or to recast the equations of motion in Hamiltonian
form.  See ‘einhil.dem’ and ‘bradic.dem’ for two comprehensive examples.
The first, ‘einhil.dem’, uses the Einstein-Hilbert action to derive the
Einstein field tensor in the homogeneous and isotropic case (Friedmann
equations) and the spherically symmetric, static case (Schwarzschild
solution.)  The second, ‘bradic.dem’, demonstrates how to compute the
Friedmann equations from the action of Brans-Dicke gravity theory, and
also derives the Hamiltonian associated with the theory's scalar field.

25.1.1 New tensor notation
--------------------------

Earlier versions of the ‘itensor’ package in Maxima used a notation that
sometimes led to incorrect index ordering.  Consider the following, for
instance:

     (%i2) imetric(g);
     (%o2)                                done
     (%i3) ishow(g([],[j,k])*g([],[i,l])*a([i,j],[]))$
                                      i l  j k
     (%t3)                           g    g    a
                                                i j
     (%i4) ishow(contract(%))$
                                           k l
     (%t4)                                a

   This result is incorrect unless ‘a’ happens to be a symmetric tensor.
The reason why this happens is that although ‘itensor’ correctly
maintains the order within the set of covariant and contravariant
indices, once an index is raised or lowered, its position relative to
the other set of indices is lost.

   To avoid this problem, a new notation has been developed that remains
fully compatible with the existing notation and can be used
interchangeably.  In this notation, contravariant indices are inserted
in the appropriate positions in the covariant index list, but with a
minus sign prepended.  Functions like ‘contract_Itensor’ and ‘ishow’ are
now aware of this new index notation and can process tensors
appropriately.

   In this new notation, the previous example yields a correct result:

     (%i5) ishow(g([-j,-k],[])*g([-i,-l],[])*a([i,j],[]))$
                                      i l       j k
     (%t5)                           g    a    g
                                           i j
     (%i6) ishow(contract(%))$
                                           l k
     (%t6)                                a

   Presently, the only code that makes use of this notation is the
‘lc2kdt’ function.  Through this notation, it achieves consistent
results as it applies the metric tensor to resolve Levi-Civita symbols
without resorting to numeric indices.

   Since this code is brand new, it probably contains bugs.  While it
has been tested to make sure that it doesn't break anything using the
"old" tensor notation, there is a considerable chance that "new" tensors
will fail to interoperate with certain functions or features.  These
bugs will be fixed as they are encountered...  until then, caveat
emptor!

25.1.2 Indicial tensor manipulation
-----------------------------------

The indicial tensor manipulation package may be loaded by
‘load("itensor")’.  Demos are also available: try ‘demo("tensor")’.

   In ‘itensor’ a tensor is represented as an "indexed object" .  This
is a function of 3 groups of indices which represent the covariant,
contravariant and derivative indices.  The covariant indices are
specified by a list as the first argument to the indexed object, and the
contravariant indices by a list as the second argument.  If the indexed
object lacks either of these groups of indices then the empty list ‘[]’
is given as the corresponding argument.  Thus, ‘g([a,b],[c])’ represents
an indexed object called ‘g’ which has two covariant indices ‘(a,b)’,
one contravariant index (‘c’) and no derivative indices.

   The derivative indices, if they are present, are appended as
additional arguments to the symbolic function representing the tensor.
They can be explicitly specified by the user or be created in the
process of differentiation with respect to some coordinate variable.
Since ordinary differentiation is commutative, the derivative indices
are sorted alphanumerically, unless ‘iframe_flag’ is set to ‘true’,
indicating that a frame metric is being used.  This canonical ordering
makes it possible for Maxima to recognize that, for example,
‘t([a],[b],i,j)’ is the same as ‘t([a],[b],j,i)’.  Differentiation of an
indexed object with respect to some coordinate whose index does not
appear as an argument to the indexed object would normally yield zero.
This is because Maxima would not know that the tensor represented by the
indexed object might depend implicitly on the corresponding coordinate.
By modifying the existing Maxima function ‘diff’ in ‘itensor’, Maxima
now assumes that all indexed objects depend on any variable of
differentiation unless otherwise stated.  This makes it possible for the
summation convention to be extended to derivative indices.  It should be
noted that ‘itensor’ does not possess the capabilities of raising
derivative indices, and so they are always treated as covariant.

   The following functions are available in the tensor package for
manipulating indexed objects.  At present, with respect to the
simplification routines, it is assumed that indexed objects do not by
default possess symmetry properties.  This can be overridden by setting
the variable ‘allsym[false]’ to ‘true’, which will result in treating
all indexed objects completely symmetric in their lists of covariant
indices and symmetric in their lists of contravariant indices.

   The ‘itensor’ package generally treats tensors as opaque objects.
Tensorial equations are manipulated based on algebraic rules,
specifically symmetry and contraction rules.  In addition, the ‘itensor’
package understands covariant differentiation, curvature, and torsion.
Calculations can be performed relative to a metric of moving frame,
depending on the setting of the ‘iframe_flag’ variable.

   A sample session below demonstrates how to load the ‘itensor’
package, specify the name of the metric, and perform some simple
calculations.

     (%i1) load("itensor");
     (%o1)      /share/tensor/itensor.lisp
     (%i2) imetric(g);
     (%o2)                                done
     (%i3) components(g([i,j],[]),p([i,j],[])*e([],[]))$
     (%i4) ishow(g([k,l],[]))$
     (%t4)                               e p
                                            k l
     (%i5) ishow(diff(v([i],[]),t))$
     (%t5)                                  0
     (%i6) depends(v,t);
     (%o6)                               [v(t)]
     (%i7) ishow(diff(v([i],[]),t))$
                                         d
     (%t7)                               -- (v )
                                         dt   i
     (%i8) ishow(idiff(v([i],[]),j))$
     (%t8)                                v
                                           i,j
     (%i9) ishow(extdiff(v([i],[]),j))$
     (%t9)                             v    - v
                                        j,i    i,j
                                       -----------
                                            2
     (%i10) ishow(liediff(v,w([i],[])))$
                                    %3          %3
     (%t10)                        v   w     + v   w
                                        i,%3    ,i  %3
     (%i11) ishow(covdiff(v([i],[]),j))$
                                                   %4
     (%t11)                        v    - v   ichr2
                                    i,j    %4      i j
     (%i12) ishow(ev(%,ichr2))$
                     %4 %5
     (%t12) v    - (g      v   (e p       + e   p     - e p       - e    p
             i,j            %4     j %5,i    ,i  j %5      i j,%5    ,%5  i j

                                              + e p       + e   p    ))/2
                                                   i %5,j    ,j  i %5
     (%i13) iframe_flag:true;
     (%o13)                               true
     (%i14) ishow(covdiff(v([i],[]),j))$
                                                  %6
     (%t14)                        v    - v   icc2
                                    i,j    %6     i j
     (%i15) ishow(ev(%,icc2))$
                                                  %6
     (%t15)                        v    - v   ifc2
                                    i,j    %6     i j
     (%i16) ishow(radcan(ev(%,ifc2,ifc1)))$
                  %6 %7                    %6 %7
     (%t16) - (ifg      v   ifb       + ifg      v   ifb       - 2 v
                         %6    j %7 i             %6    i j %7      i,j

                                                  %6 %7
                                             - ifg      v   ifb      )/2
                                                         %6    %7 i j
     (%i17) ishow(canform(s([i,j],[])-s([j,i])))$
     (%t17)                            s    - s
                                        i j    j i
     (%i18) decsym(s,2,0,[sym(all)],[]);
     (%o18)                               done
     (%i19) ishow(canform(s([i,j],[])-s([j,i])))$
     (%t19)                                 0
     (%i20) ishow(canform(a([i,j],[])+a([j,i])))$
     (%t20)                            a    + a
                                        j i    i j
     (%i21) decsym(a,2,0,[anti(all)],[]);
     (%o21)                               done
     (%i22) ishow(canform(a([i,j],[])+a([j,i])))$
     (%t22)                                 0


File: maxima.info,  Node: Functions and Variables for itensor,  Prev: Introduction to itensor,  Up: Package itensor

25.2 Functions and Variables for itensor
========================================

25.2.1 Managing indexed objects
-------------------------------

 -- Function: dispcon
          dispcon (<tensor_1>, <tensor_2>, ...)
          dispcon (all)

     Displays the contraction properties of its arguments as were given
     to ‘defcon’.  ‘dispcon (all)’ displays all the contraction
     properties which were defined.

 -- Function: entertensor (<name>)

     is a function which, by prompting, allows one to create an indexed
     object called <name> with any number of tensorial and derivative
     indices.  Either a single index or a list of indices (which may be
     null) is acceptable input (see the example under ‘covdiff’).

 -- Function: changename (<old>, <new>, <expr>)

     will change the name of all indexed objects called <old> to <new>
     in <expr>.  <old> may be either a symbol or a list of the form
     ‘[<name>, <m>, <n>]’ in which case only those indexed objects
     called <name> with <m> covariant and <n> contravariant indices will
     be renamed to <new>.

 -- Function: listoftens

     Lists all tensors in a tensorial expression, complete with their
     indices.  E.g.,


          (%i6) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$
                                                   k
          (%t6)                        d e c    + a    b
                                            x y    i j  u,v
          (%i7) ishow(listoftens(%))$
                                         k
          (%t7)                        [a   , b   , c   , d]
                                         i j   u,v   x y


 -- Function: ishow (<expr>)

     displays <expr> with the indexed objects in it shown having their
     covariant indices as subscripts and contravariant indices as
     superscripts.  The derivative indices are displayed as subscripts,
     separated from the covariant indices by a comma (see the examples
     throughout this document).

 -- Function: indices (<expr>)

     Returns a list of two elements.  The first is a list of the free
     indices in <expr> (those that occur only once).  The second is the
     list of the dummy indices in <expr> (those that occur exactly
     twice) as the following example demonstrates.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i,j],[k,l],m,n)*b([k,o],[j,m,p],q,r))$
                                          k l      j m p
          (%t2)                          a        b
                                          i j,m n  k o,q r
          (%i3) indices(%);
          (%o3)                 [[l, p, i, n, o, q, r], [k, j, m]]


     A tensor product containing the same index more than twice is
     syntactically illegal.  ‘indices’ attempts to deal with these
     expressions in a reasonable manner; however, when it is called to
     operate upon such an illegal expression, its behavior should be
     considered undefined.

 -- Function: rename
          rename (<expr>)
          rename (<expr>, <count>)

     Returns an expression equivalent to <expr> but with the dummy
     indices in each term chosen from the set ‘[%1, %2,...]’, if the
     optional second argument is omitted.  Otherwise, the dummy indices
     are indexed beginning at the value of <count>.  Each dummy index in
     a product will be different.  For a sum, ‘rename’ will operate upon
     each term in the sum resetting the counter with each term.  In this
     way ‘rename’ can serve as a tensorial simplifier.  In addition, the
     indices will be sorted alphanumerically (if ‘allsym’ is ‘true’)
     with respect to covariant or contravariant indices depending upon
     the value of ‘flipflag’.  If ‘flipflag’ is ‘false’ then the indices
     will be renamed according to the order of the contravariant
     indices.  If ‘flipflag’ is ‘true’ the renaming will occur according
     to the order of the covariant indices.  It often happens that the
     combined effect of the two renamings will reduce an expression more
     than either one by itself.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) allsym:true;
          (%o2)                                true
          (%i3) g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%4],[%3])*
          ichr2([%2,%3],[u])*ichr2([%5,%6],[%1])*ichr2([%7,r],[%2])-
          g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%2],[u])*
          ichr2([%3,%5],[%1])*ichr2([%4,%6],[%3])*ichr2([%7,r],[%2]),noeval$
          (%i4) expr:ishow(%)$
                 %4 %5  %6 %7      %3         u          %1         %2
          (%t4) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %4      %2 %3      %5 %6      %7 r

                  %4 %5  %6 %7      u          %1         %3         %2
               - g      g      ichr2      ichr2      ichr2      ichr2
                                    %1 %2      %3 %5      %4 %6      %7 r
          (%i5) flipflag:true;
          (%o5)                                true
          (%i6) ishow(rename(expr))$
                 %2 %5  %6 %7      %4         u          %1         %3
          (%t6) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %2      %3 %4      %5 %6      %7 r

                  %4 %5  %6 %7      u          %1         %3         %2
               - g      g      ichr2      ichr2      ichr2      ichr2
                                    %1 %2      %3 %4      %5 %6      %7 r
          (%i7) flipflag:false;
          (%o7)                                false
          (%i8) rename(%th(2));
          (%o8)                                  0
          (%i9) ishow(rename(expr))$
                 %1 %2  %3 %4      %5         %6         %7        u
          (%t9) g      g      ichr2      ichr2      ichr2     ichr2
                                   %1 %6      %2 %3      %4 r      %5 %7

                  %1 %2  %3 %4      %6         %5         %7        u
               - g      g      ichr2      ichr2      ichr2     ichr2
                                    %1 %3      %2 %6      %4 r      %5 %7

 -- Option variable: flipflag
     Default value: ‘false’

     If ‘false’ then the indices will be renamed according to the order
     of the contravariant indices, otherwise according to the order of
     the covariant indices.

     If ‘flipflag’ is ‘false’ then ‘rename’ forms a list of the
     contravariant indices as they are encountered from left to right
     (if ‘true’ then of the covariant indices).  The first dummy index
     in the list is renamed to ‘%1’, the next to ‘%2’, etc.  Then
     sorting occurs after the ‘rename’-ing (see the example under
     ‘rename’).

 -- Function: defcon
          defcon (<tensor_1>)
          defcon (<tensor_1>, <tensor_2>, <tensor_3>)

     gives <tensor_1> the property that the contraction of a product of
     <tensor_1> and <tensor_2> results in <tensor_3> with the
     appropriate indices.  If only one argument, <tensor_1>, is given,
     then the contraction of the product of <tensor_1> with any indexed
     object having the appropriate indices (say ‘my_tensor’) will yield
     an indexed object with that name, i.e.  ‘my_tensor’, and with a new
     set of indices reflecting the contractions performed.  For example,
     if ‘imetric:g’, then ‘defcon(g)’ will implement the raising and
     lowering of indices through contraction with the metric tensor.
     More than one ‘defcon’ can be given for the same indexed object;
     the latest one given which applies in a particular contraction will
     be used.  ‘contractions’ is a list of those indexed objects which
     have been given contraction properties with ‘defcon’.

 -- Function: remcon
          remcon (<tensor_1>, ..., <tensor_n>)
          remcon (all)

     Removes all the contraction properties from the (<tensor_1>, ...,
     <tensor_n>).  ‘remcon(all)’ removes all contraction properties from
     all indexed objects.

 -- Function: contract (<expr>)

     Carries out the tensorial contractions in <expr> which may be any
     combination of sums and products.  This function uses the
     information given to the ‘defcon’ function.  For best results,
     ‘expr’ should be fully expanded.  ‘ratexpand’ is the fastest way to
     expand products and powers of sums if there are no variables in the
     denominators of the terms.  The ‘gcd’ switch should be ‘false’ if
     GCD cancellations are unnecessary.

 -- Function: indexed_tensor (<tensor>)

     Must be executed before assigning components to a <tensor> for
     which a built in value already exists as with ‘ichr1’, ‘ichr2’,
     ‘icurvature’.  See the example under ‘icurvature’.

 -- Function: components (<tensor>, <expr>)

     permits one to assign an indicial value to an expression <expr>
     giving the values of the components of <tensor>.  These are
     automatically substituted for the tensor whenever it occurs with
     all of its indices.  The tensor must be of the form
     ‘t([...],[...])’ where either list may be empty.  <expr> can be any
     indexed expression involving other objects with the same free
     indices as <tensor>.  When used to assign values to the metric
     tensor wherein the components contain dummy indices one must be
     careful to define these indices to avoid the generation of multiple
     dummy indices.  Removal of this assignment is given to the function
     ‘remcomps’.

     It is important to keep in mind that ‘components’ cares only about
     the valence of a tensor, not about any particular index ordering.
     Thus assigning components to, say, ‘x([i,-j],[])’, ‘x([-j,i],[])’,
     or ‘x([i],[j])’ all produce the same result, namely components
     being assigned to a tensor named ‘x’ with valence ‘(1,1)’.

     Components can be assigned to an indexed expression in four ways,
     two of which involve the use of the ‘components’ command:

     1) As an indexed expression.  For instance:

          (%i2) components(g([],[i,j]),e([],[i])*p([],[j]))$
          (%i3) ishow(g([],[i,j]))$
                                                i  j
          (%t3)                                e  p


     2) As a matrix:


          (%i5) lg:-ident(4)$lg[1,1]:1$lg;
                                      [ 1   0    0    0  ]
                                      [                  ]
                                      [ 0  - 1   0    0  ]
          (%o5)                       [                  ]
                                      [ 0   0   - 1   0  ]
                                      [                  ]
                                      [ 0   0    0   - 1 ]
          (%i6) components(g([i,j],[]),lg);
          (%o6)                                done
          (%i7) ishow(g([i,j],[]))$
          (%t7)                                g
                                                i j
          (%i8) g([1,1],[]);
          (%o8)                                  1
          (%i9) g([4,4],[]);
          (%o9)                                 - 1

     3) As a function.  You can use a Maxima function to specify the
     components of a tensor based on its indices.  For instance, the
     following code assigns ‘kdelta’ to ‘h’ if ‘h’ has the same number
     of covariant and contravariant indices and no derivative indices,
     and ‘g’ otherwise:


          (%i4) h(l1,l2,[l3]):=if length(l1)=length(l2) and length(l3)=0
            then kdelta(l1,l2) else apply(g,append([l1,l2], l3))$
          (%i5) ishow(h([i],[j]))$
                                                    j
          (%t5)                               kdelta
                                                    i
          (%i6) ishow(h([i,j],[k],l))$
                                               k
          (%t6)                               g
                                               i j,l

     4) Using Maxima's pattern matching capabilities, specifically the
     ‘defrule’ and ‘applyb1’ commands:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) matchdeclare(l1,listp);
          (%o2)                                done
          (%i3) defrule(r1,m(l1,[]),(i1:idummy(),
                g([l1[1],l1[2]],[])*q([i1],[])*e([],[i1])))$

          (%i4) defrule(r2,m([],l1),(i1:idummy(),
                w([],[l1[1],l1[2]])*e([i1],[])*q([],[i1])))$

          (%i5) ishow(m([i,n],[])*m([],[i,m]))$
                                              i m
          (%t5)                              m    m
                                                   i n
          (%i6) ishow(rename(applyb1(%,r1,r2)))$
                                     %1  %2  %3 m
          (%t6)                     e   q   w     q   e   g
                                                   %1  %2  %3 n

 -- Function: remcomps (<tensor>)

     Unbinds all values from <tensor> which were assigned with the
     ‘components’ function.

 -- Function: showcomps (<tensor>)

     Shows component assignments of a tensor, as made using the
     ‘components’ command.  This function can be particularly useful
     when a matrix is assigned to an indicial tensor using ‘components’,
     as demonstrated by the following example:


          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) load("itensor");
          (%o2)      /share/tensor/itensor.lisp
          (%i3) lg:matrix([sqrt(r/(r-2*m)),0,0,0],[0,r,0,0],
                          [0,0,sin(theta)*r,0],[0,0,0,sqrt((r-2*m)/r)]);
                  [         r                                     ]
                  [ sqrt(-------)  0       0              0       ]
                  [      r - 2 m                                  ]
                  [                                               ]
                  [       0        r       0              0       ]
          (%o3)   [                                               ]
                  [       0        0  r sin(theta)        0       ]
                  [                                               ]
                  [                                      r - 2 m  ]
                  [       0        0       0        sqrt(-------) ]
                  [                                         r     ]
          (%i4) components(g([i,j],[]),lg);
          (%o4)                                done
          (%i5) showcomps(g([i,j],[]));
                       [         r                                     ]
                       [ sqrt(-------)  0       0              0       ]
                       [      r - 2 m                                  ]
                       [                                               ]
                       [       0        r       0              0       ]
          (%t5) g    = [                                               ]
                 i j   [       0        0  r sin(theta)        0       ]
                       [                                               ]
                       [                                      r - 2 m  ]
                       [       0        0       0        sqrt(-------) ]
                       [                                         r     ]
          (%o5)                                false


     The ‘showcomps’ command can also display components of a tensor of
     rank higher than 2.

 -- Function: idummy ()

     Increments ‘icounter’ and returns as its value an index of the form
     ‘%n’ where n is a positive integer.  This guarantees that dummy
     indices which are needed in forming expressions will not conflict
     with indices already in use (see the example under ‘indices’).

 -- Option variable: idummyx
     Default value: ‘%’

     Is the prefix for dummy indices (see the example under ‘indices’).

 -- Option variable: icounter
     Default value: ‘1’

     Determines the numerical suffix to be used in generating the next
     dummy index in the tensor package.  The prefix is determined by the
     option ‘idummy’ (default: ‘%’).

 -- Function: kdelta (<L1>, <L2>)
     is the generalized Kronecker delta function defined in the
     ‘itensor’ package with <L1> the list of covariant indices and <L2>
     the list of contravariant indices.  ‘kdelta([i],[j])’ returns the
     ordinary Kronecker delta.  The command ‘ev(<expr>,kdelta)’ causes
     the evaluation of an expression containing ‘kdelta([],[])’ to the
     dimension of the manifold.

     In what amounts to an abuse of this notation, ‘itensor’ also allows
     ‘kdelta’ to have 2 covariant and no contravariant, or 2
     contravariant and no covariant indices, in effect providing a
     co(ntra)variant "unit matrix" capability.  This is strictly
     considered a programming aid and not meant to imply that
     ‘kdelta([i,j],[])’ is a valid tensorial object.

 -- Function: kdels (<L1>, <L2>)

     Symmetrized Kronecker delta, used in some calculations.  For
     instance:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) kdelta([1,2],[2,1]);
          (%o2)                                 - 1
          (%i3) kdels([1,2],[2,1]);
          (%o3)                                  1
          (%i4) ishow(kdelta([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  - kdelta  kdelta
                                       a       b         a       b
          (%i4) ishow(kdels([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  + kdelta  kdelta
                                       a       b         a       b


 -- Function: levi_civita (<L>)
     is the permutation (or Levi-Civita) tensor which yields 1 if the
     list <L> consists of an even permutation of integers, -1 if it
     consists of an odd permutation, and 0 if some indices in <L> are
     repeated.

 -- Function: lc2kdt (<expr>)
     Simplifies expressions containing the Levi-Civita symbol,
     converting these to Kronecker-delta expressions when possible.  The
     main difference between this function and simply evaluating the
     Levi-Civita symbol is that direct evaluation often results in
     Kronecker expressions containing numerical indices.  This is often
     undesirable as it prevents further simplification.  The ‘lc2kdt’
     function avoids this problem, yielding expressions that are more
     easily simplified with ‘rename’ or ‘contract’.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([k,l],[])*a([j],[k]))$
                                            i j  k
          (%t2)                  levi_civita    a  levi_civita
                                                 j            k l
          (%i3) ishow(ev(expr,levi_civita))$
                                            i j  k       1 2
          (%t3)                       kdelta    a  kdelta
                                            1 2  j       k l
          (%i4) ishow(ev(%,kdelta))$
                       i       j         j       i   k
          (%t4) (kdelta  kdelta  - kdelta  kdelta ) a
                       1       2         1       2   j

                                         1       2         2       1
                                  (kdelta  kdelta  - kdelta  kdelta )
                                         k       l         k       l
          (%i5) ishow(lc2kdt(expr))$
                               k       i       j    k       j       i
          (%t5)               a  kdelta  kdelta  - a  kdelta  kdelta
                               j       k       l    j       k       l
          (%i6) ishow(contract(expand(%)))$
                                           i           i
          (%t6)                           a  - a kdelta
                                           l           l

     The ‘lc2kdt’ function sometimes makes use of the metric tensor.  If
     the metric tensor was not defined previously with ‘imetric’, this
     results in an error.


          (%i7) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([],[k,l])*a([j,k],[]))$
                                           i j            k l
          (%t7)                 levi_civita    levi_civita    a
                                                               j k
          (%i8) ishow(lc2kdt(expr))$
          Maxima encountered a Lisp error:

           Error in $IMETRIC [or a callee]:
           $IMETRIC [or a callee] requires less than two arguments.

          Automatically continuing.
          To re-enable the Lisp debugger set *debugger-hook* to nil.
          (%i9) imetric(g);
          (%o9)                                done
          (%i10) ishow(lc2kdt(expr))$
                   %3 i       k   %4 j       l     %3 i       l   %4 j
          (%t10) (g     kdelta   g     kdelta   - g     kdelta   g
                              %3             %4               %3
                        k
                  kdelta  ) a
                        %4   j k
          (%i11) ishow(contract(expand(%)))$
                                            l i    l i  j
          (%t11)                           a    - g    a
                                                        j

 -- Function: lc_l
     Simplification rule used for expressions containing the unevaluated
     Levi-Civita symbol (‘levi_civita’).  Along with ‘lc_u’, it can be
     used to simplify many expressions more efficiently than the
     evaluation of ‘levi_civita’.  For example:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$
                                       i  j
          (%t2)                       a  a  levi_civita
                                                       i j k
          (%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$
                                                 i j k
          (%t3)                       levi_civita      a  a
                                                        i  j
          (%i4) canform(contract(expand(applyb1(el1,lc_l,lc_u))));
          (%t4)                                  0
          (%i5) canform(contract(expand(applyb1(el2,lc_l,lc_u))));
          (%t5)                                  0


 -- Function: lc_u

     Simplification rule used for expressions containing the unevaluated
     Levi-Civita symbol (‘levi_civita’).  Along with ‘lc_u’, it can be
     used to simplify many expressions more efficiently than the
     evaluation of ‘levi_civita’.  For details, see ‘lc_l’.

 -- Function: canten (<expr>)
     Simplifies <expr> by renaming (see ‘rename’) and permuting dummy
     indices.  ‘rename’ is restricted to sums of tensor products in
     which no derivatives are present.  As such it is limited and should
     only be used if ‘canform’ is not capable of carrying out the
     required simplification.

     The ‘canten’ function returns a mathematically correct result only
     if its argument is an expression that is fully symmetric in its
     indices.  For this reason, ‘canten’ returns an error if ‘allsym’ is
     not set to ‘true’.

 -- Function: concan (<expr>)
     Similar to ‘canten’ but also performs index contraction.

25.2.2 Tensor symmetries
------------------------

 -- Option variable: allsym
     Default value: ‘false’

     If ‘true’ then all indexed objects are assumed symmetric in all of
     their covariant and contravariant indices.  If ‘false’ then no
     symmetries of any kind are assumed in these indices.  Derivative
     indices are always taken to be symmetric unless ‘iframe_flag’ is
     set to ‘true’.

 -- Function: decsym (<tensor>, <m>, <n>, [<cov_1>, <cov_2>, ...],
          [<contr_1>, <contr_2>, ...])

     Declares symmetry properties for <tensor> of <m> covariant and <n>
     contravariant indices.  The <cov_i> and <contr_i> are
     pseudofunctions expressing symmetry relations among the covariant
     and contravariant indices respectively.  These are of the form
     ‘symoper(<index_1>, <index_2>,...)’ where ‘symoper’ is one of
     ‘sym’, ‘anti’ or ‘cyc’ and the <index_i> are integers indicating
     the position of the index in the <tensor>.  This will declare
     <tensor> to be symmetric, antisymmetric or cyclic respectively in
     the <index_i>.  ‘symoper(all)’ is also an allowable form which
     indicates all indices obey the symmetry condition.  For example,
     given an object ‘b’ with 5 covariant indices,
     ‘decsym(b,5,3,[sym(1,2),anti(3,4)],[cyc(all)])’ declares ‘b’
     symmetric in its first and second and antisymmetric in its third
     and fourth covariant indices, and cyclic in all of its
     contravariant indices.  Either list of symmetry declarations may be
     null.  The function which performs the simplifications is ‘canform’
     as the example below illustrates.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:contract( expand( a([i1, j1, k1], [])
                     *kdels([i, j, k], [i1, j1, k1])))$
          (%i3) ishow(expr)$
          (%t3)         a      + a      + a      + a      + a      + a
                         k j i    k i j    j k i    j i k    i k j    i j k
          (%i4) decsym(a,3,0,[sym(all)],[]);
          (%o4)                                done
          (%i5) ishow(canform(expr))$
          (%t5)                              6 a
                                                i j k
          (%i6) remsym(a,3,0);
          (%o6)                                done
          (%i7) decsym(a,3,0,[anti(all)],[]);
          (%o7)                                done
          (%i8) ishow(canform(expr))$
          (%t8)                                  0
          (%i9) remsym(a,3,0);
          (%o9)                                done
          (%i10) decsym(a,3,0,[cyc(all)],[]);
          (%o10)                               done
          (%i11) ishow(canform(expr))$
          (%t11)                        3 a      + 3 a
                                           i k j      i j k
          (%i12) dispsym(a,3,0);
          (%o12)                     [[cyc, [[1, 2, 3]], []]]


 -- Function: remsym (<tensor>, <m>, <n>)
     Removes all symmetry properties from <tensor> which has <m>
     covariant indices and <n> contravariant indices.

 -- Function: dispsym (<tensor>, <m>, <n>)
     Displays all of the defined symmetries from <tensor> which has <m>
     covariant indices and <n> contravariant indices.  See ‘decsym’ for
     an example.

 -- Function: canform
          canform (<expr>)
          canform (<expr>, <rename>)

     Simplifies <expr> by renaming dummy indices and reordering all
     indices as dictated by symmetry conditions imposed on them.  If
     ‘allsym’ is ‘true’ then all indices are assumed symmetric,
     otherwise symmetry information provided by ‘decsym’ declarations
     will be used.  The dummy indices are renamed in the same manner as
     in the ‘rename’ function.  When ‘canform’ is applied to a large
     expression the calculation may take a considerable amount of time.
     This time can be shortened by calling ‘rename’ on the expression
     first.  Also see the example under ‘decsym’.  Note: ‘canform’ may
     not be able to reduce an expression completely to its simplest form
     although it will always return a mathematically correct result.

     The optional second parameter <rename>, if set to ‘false’,
     suppresses renaming.

25.2.3 Indicial tensor calculus
-------------------------------

 -- Function: diff (<expr>, <v_1>, [<n_1>, [<v_2>, <n_2>] ...])

     is the usual Maxima differentiation function which has been
     expanded in its abilities for ‘itensor’.  It takes the derivative
     of <expr> with respect to <v_1> <n_1> times, with respect to <v_2>
     <n_2> times, etc.  For the tensor package, the function has been
     modified so that the <v_i> may be integers from 1 up to the value
     of the variable ‘dim’.  This will cause the differentiation to be
     carried out with respect to the <v_i>th member of the list
     ‘vect_coords’.  If ‘vect_coords’ is bound to an atomic variable,
     then that variable subscripted by <v_i> will be used for the
     variable of differentiation.  This permits an array of coordinate
     names or subscripted names like ‘x[1]’, ‘x[2]’, ...  to be used.

     A further extension adds the ability to ‘diff’ to compute
     derivatives with respect to an indexed variable.  In particular,
     the tensor package knows how to differentiate expressions
     containing combinations of the metric tensor and its derivatives
     with respect to the metric tensor and its first and second
     derivatives.  This capability is particularly useful when
     considering Lagrangian formulations of a gravitational theory,
     allowing one to derive the Einstein tensor and field equations from
     the action principle.

 -- Function: idiff (<expr>, <v_1>, [<n_1>, [<v_2>, <n_2>] ...])
     Indicial differentiation.  Unlike ‘diff’, which differentiates with
     respect to an independent variable, ‘idiff)’ can be used to
     differentiate with respect to a coordinate.  For an indexed object,
     this amounts to appending the <v_i> as derivative indices.
     Subsequently, derivative indices will be sorted, unless
     ‘iframe_flag’ is set to ‘true’.

     ‘idiff’ can also differentiate the determinant of the metric
     tensor.  Thus, if ‘imetric’ has been bound to ‘G’ then
     ‘idiff(determinant(g),k)’ will return ‘2 * determinant(g) *
     ichr2([%i,k],[%i])’ where the dummy index ‘%i’ is chosen
     appropriately.

 -- Function: liediff (<v>, <ten>)

     Computes the Lie-derivative of the tensorial expression <ten> with
     respect to the vector field <v>.  <ten> should be any indexed
     tensor expression; <v> should be the name (without indices) of a
     vector field.  For example:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$
                 k    %2            %2          %2
          (%t2) b   (v   a       + v   a     + v   a    )
                 ,l       i j,%2    ,j  i %2    ,i  %2 j

                                    %1  k        %1  k      %1  k
                                + (v   b      - b   v    + v   b   ) a
                                        ,%1 l    ,l  ,%1    ,l  ,%1   i j


 -- Function: rediff (<ten>)

     Evaluates all occurrences of the ‘idiff’ command in the tensorial
     expression <ten>.

 -- Function: undiff (<expr>)

     Returns an expression equivalent to <expr> but with all derivatives
     of indexed objects replaced by the noun form of the ‘idiff’
     function.  Its arguments would yield that indexed object if the
     differentiation were carried out.  This is useful when it is
     desired to replace a differentiated indexed object with some
     function definition resulting in <expr> and then carry out the
     differentiation by saying ‘ev(<expr>, idiff)’.

 -- Function: evundiff (<expr>)

     Equivalent to the execution of ‘undiff’, followed by ‘ev’ and
     ‘rediff’.

     The point of this operation is to easily evaluate expressions that
     cannot be directly evaluated in derivative form.  For instance, the
     following causes an error:

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) icurvature([i,j,k],[l],m);
          Maxima encountered a Lisp error:

           Error in $ICURVATURE [or a callee]:
           $ICURVATURE [or a callee] requires less than three arguments.

          Automatically continuing.
          To re-enable the Lisp debugger set *debugger-hook* to nil.

     However, if ‘icurvature’ is entered in noun form, it can be
     evaluated using ‘evundiff’:

          (%i3) ishow('icurvature([i,j,k],[l],m))$
                                                   l
          (%t3)                          icurvature
                                                   i j k,m
          (%i4) ishow(evundiff(%))$
                       l              l         %1           l           %1
          (%t4) - ichr2        - ichr2     ichr2      - ichr2       ichr2
                       i k,j m        %1 j      i k,m        %1 j,m      i k

                       l              l         %1           l           %1
                + ichr2        + ichr2     ichr2      + ichr2       ichr2
                       i j,k m        %1 k      i j,m        %1 k,m      i j

     Note: In earlier versions of Maxima, derivative forms of the
     Christoffel-symbols also could not be evaluated.  This has been
     fixed now, so ‘evundiff’ is no longer necessary for expressions
     like this:

          (%i5) imetric(g);
          (%o5)                                done
          (%i6) ishow(ichr2([i,j],[k],l))$
                 k %3
                g     (g         - g         + g        )
                        j %3,i l    i j,%3 l    i %3,j l
          (%t6) -----------------------------------------
                                    2

                                   k %3
                                  g     (g       - g       + g      )
                                   ,l     j %3,i    i j,%3    i %3,j
                                + -----------------------------------
                                                   2

 -- Function: flush (<expr>, <tensor_1>, <tensor_2>, ...)
     Set to zero, in <expr>, all occurrences of the <tensor_i> that have
     no derivative indices.

 -- Function: flushd (<expr>, <tensor_1>, <tensor_2>, ...)
     Set to zero, in <expr>, all occurrences of the <tensor_i> that have
     derivative indices.

 -- Function: flushnd (<expr>, <tensor>, <n>)
     Set to zero, in <expr>, all occurrences of the differentiated
     object <tensor> that have <n> or more derivative indices as the
     following example demonstrates.

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i],[J,r],k,r)+a([i],[j,r,s],k,r,s))$
                                          J r      j r s
          (%t2)                          a      + a
                                          i,k r    i,k r s
          (%i3) ishow(flushnd(%,a,3))$
                                               J r
          (%t3)                               a
                                               i,k r

 -- Function: coord (<tensor_1>, <tensor_2>, ...)

     Gives <tensor_i> the coordinate differentiation property that the
     derivative of contravariant vector whose name is one of the
     <tensor_i> yields a Kronecker delta.  For example, if ‘coord(x)’
     has been done then ‘idiff(x([],[i]),j)’ gives ‘kdelta([i],[j])’.
     ‘coord’ is a list of all indexed objects having this property.

 -- Function: remcoord
          remcoord (<tensor_1>, <tensor_2>, ...)
          remcoord (all)

     Removes the coordinate differentiation property from the ‘tensor_i’
     that was established by the function ‘coord’.  ‘remcoord(all)’
     removes this property from all indexed objects.

 -- Function: makebox (<expr>,<g>)
     Display <expr> using the metric <g> such that any tensor
     d'Alembertian occurring in <expr> will be indicated using the
     symbol ‘[]’.  For example, ‘[]p([m],[n])’ represents
     ‘g([],[i,j])*p([m],[n],i,j)’.

 -- Function: conmetderiv (<expr>, <tensor>)

     Simplifies expressions containing ordinary derivatives of both
     covariant and contravariant forms of the metric tensor (the current
     restriction).  For example, ‘conmetderiv’ can relate the derivative
     of the contravariant metric tensor with the Christoffel symbols as
     seen from the following:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(g([],[a,b],c))$
                                                a b
          (%t2)                                g
                                                ,c
          (%i3) ishow(conmetderiv(%,g))$
                                   %1 b      a       %1 a      b
          (%t3)                 - g     ichr2     - g     ichr2
                                             %1 c              %1 c

 -- Function: simpmetderiv
          simpmetderiv (<expr>)
          simpmetderiv (<expr>[, <stop>])

     Simplifies expressions containing products of the derivatives of
     the metric tensor.  Specifically, ‘simpmetderiv’ recognizes two
     identities:


             ab        ab           ab                 a
            g   g   + g   g     = (g   g  )   = (kdelta )   = 0
             ,d  bc        bc,d         bc ,d          c ,d


     hence


             ab          ab
            g   g   = - g   g
             ,d  bc          bc,d

     and


            ab          ab
           g   g     = g   g
            ,j  ab,i    ,i  ab,j


     which follows from the symmetries of the Christoffel symbols.

     The ‘simpmetderiv’ function takes one optional parameter which,
     when present, causes the function to stop after the first
     successful substitution in a product expression.  The
     ‘simpmetderiv’ function also makes use of the global variable
     ‘flipflag’ which determines how to apply a "canonical" ordering to
     the product indices.

     Put together, these capabilities can be used to achieve powerful
     simplifications that are difficult or impossible to accomplish
     otherwise.  This is demonstrated through the following example that
     explicitly uses the partial simplification features of
     ‘simpmetderiv’ to obtain a contractible expression:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                                done
          (%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([b,c],[],e))$
                                       a b  b c
          (%t3)                       g    g    g      g
                                                 a b,d  b c,e
          (%i4) ishow(canform(%))$

          errexp1 has improper indices
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i5) ishow(simpmetderiv(%))$
                                       a b  b c
          (%t5)                       g    g    g      g
                                                 a b,d  b c,e
          (%i6) flipflag:not flipflag;
          (%o6)                                true
          (%i7) ishow(simpmetderiv(%th(2)))$
                                         a b  b c
          (%t7)                         g    g    g    g
                                         ,d   ,e   a b  b c
          (%i8) flipflag:not flipflag;
          (%o8)                                false
          (%i9) ishow(simpmetderiv(%th(2),stop))$
                                         a b  b c
          (%t9)                       - g    g    g      g
                                              ,e   a b,d  b c
          (%i10) ishow(contract(%))$
                                              b c
          (%t10)                           - g    g
                                              ,e   c b,d


     See also ‘weyl.dem’ for an example that uses ‘simpmetderiv’ and
     ‘conmetderiv’ together to simplify contractions of the Weyl tensor.

 -- Function: flush1deriv (<expr>, <tensor>)

     Set to zero, in ‘expr’, all occurrences of ‘tensor’ that have
     exactly one derivative index.

25.2.4 Tensors in curved spaces
-------------------------------

 -- Function: imetric (<g>)
 -- System variable: imetric

     Specifies the metric by assigning the variable ‘imetric:<g>’ in
     addition, the contraction properties of the metric <g> are set up
     by executing the commands ‘defcon(<g>), defcon(<g>, <g>, kdelta)’.
     The variable ‘imetric’ (unbound by default), is bound to the
     metric, assigned by the ‘imetric(<g>)’ command.

 -- Function: idim (<n>)
     Sets the dimensions of the metric.  Also initializes the
     antisymmetry properties of the Levi-Civita symbols for the given
     dimension.

 -- Function: ichr1 ([<i>, <j>, <k>])
     Yields the Christoffel symbol of the first kind via the definition
                 (g      + g      - g     )/2 .
                   ik,j     jk,i     ij,k
     To evaluate the Christoffel symbols for a particular metric, the
     variable ‘imetric’ must be assigned a name as in the example under
     ‘chr2’.

 -- Function: ichr2 ([<i>, <j>], [<k>])
     Yields the Christoffel symbol of the second kind defined by the
     relation
                                 ks
             ichr2([i,j],[k]) = g    (g      + g      - g     )/2
                                       is,j     js,i     ij,s

 -- Function: icurvature ([<i>, <j>, <k>], [<h>])
     Yields the Riemann curvature tensor in terms of the Christoffel
     symbols of the second kind (‘ichr2’).  The following notation is
     used:
                      h             h            h         %1         h
            icurvature     = - ichr2      - ichr2     ichr2    + ichr2
                      i j k         i k,j        %1 j      i k        i j,k
                                      h          %1
                               + ichr2      ichr2
                                      %1 k       i j

 -- Function: covdiff (<expr>, <v_1>, <v_2>, ...)
     Yields the covariant derivative of <expr> with respect to the
     variables <v_i> in terms of the Christoffel symbols of the second
     kind (‘ichr2’).  In order to evaluate these, one should use
     ‘ev(<expr>,ichr2)’.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) entertensor()$
          Enter tensor name: a;
          Enter a list of the covariant indices: [i,j];
          Enter a list of the contravariant indices: [k];
          Enter a list of the derivative indices: [];
                                                k
          (%t2)                                a
                                                i j
          (%i3) ishow(covdiff(%,s))$
                       k         %1     k         %1     k
          (%t3)     - a     ichr2    - a     ichr2    + a
                       i %1      j s    %1 j      i s    i j,s

                       k     %1
                + ichr2     a
                       %1 s  i j
          (%i4) imetric:g;
          (%o4)                                  g
          (%i5) ishow(ev(%th(2),ichr2))$
                   %1 %4  k
                  g      a     (g       - g       + g      )
                          i %1   s %4,j    j s,%4    j %4,s
          (%t5) - ------------------------------------------
                                      2
              %1 %3  k
             g      a     (g       - g       + g      )
                     %1 j   s %3,i    i s,%3    i %3,s
           - ------------------------------------------
                                 2
              k %2  %1
             g     a    (g        - g        + g       )
                    i j   s %2,%1    %1 s,%2    %1 %2,s     k
           + ------------------------------------------- + a
                                  2                         i j,s
          (%i6)

 -- Function: lorentz_gauge (<expr>)
     Imposes the Lorentz condition by substituting 0 for all indexed
     objects in <expr> that have a derivative index identical to a
     contravariant index.

 -- Function: igeodesic_coords (<expr>, <name>)

     Causes undifferentiated Christoffel symbols and first derivatives
     of the metric tensor vanish in <expr>.  The <name> in the
     ‘igeodesic_coords’ function refers to the metric <name> (if it
     appears in <expr>) while the connection coefficients must be called
     with the names ‘ichr1’ and/or ‘ichr2’.  The following example
     demonstrates the verification of the cyclic identity satisfied by
     the Riemann curvature tensor using the ‘igeodesic_coords’ function.


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(icurvature([r,s,t],[u]))$
                       u            u         %1         u
          (%t2) - ichr2      - ichr2     ichr2    + ichr2
                       r t,s        %1 s      r t        r s,t

                                                        u         %1
                                                 + ichr2     ichr2
                                                        %1 t      r s
          (%i3) ishow(igeodesic_coords(%,ichr2))$
                                           u            u
          (%t3)                       ichr2      - ichr2
                                           r s,t        r t,s
          (%i4) ishow(igeodesic_coords(icurvature([r,s,t],[u]),ichr2)+
                      igeodesic_coords(icurvature([s,t,r],[u]),ichr2)+
                      igeodesic_coords(icurvature([t,r,s],[u]),ichr2))$
                       u            u            u            u
          (%t4) - ichr2      + ichr2      + ichr2      - ichr2
                       t s,r        t r,s        s t,r        s r,t

                                                       u            u
                                                - ichr2      + ichr2
                                                       r t,s        r s,t
          (%i5) canform(%);
          (%o5)                                  0


25.2.5 Moving frames
--------------------

Maxima now has the ability to perform calculations using moving frames.
These can be orthonormal frames (tetrads, vielbeins) or an arbitrary
frame.

   To use frames, you must first set ‘iframe_flag’ to ‘true’.  This
causes the Christoffel-symbols, ‘ichr1’ and ‘ichr2’, to be replaced by
the more general frame connection coefficients ‘icc1’ and ‘icc2’ in
calculations.  Specifically, the behavior of ‘covdiff’ and ‘icurvature’
is changed.

   The frame is defined by two tensors: the inverse frame field (‘ifri’,
the dual basis tetrad), and the frame metric ‘ifg’.  The frame metric is
the identity matrix for orthonormal frames, or the Lorentz metric for
orthonormal frames in Minkowski spacetime.  The inverse frame field
defines the frame base (unit vectors).  Contraction properties are
defined for the frame field and the frame metric.

   When ‘iframe_flag’ is true, many ‘itensor’ expressions use the frame
metric ‘ifg’ instead of the metric defined by ‘imetric’ for raising and
lowerind indices.

   IMPORTANT: Setting the variable ‘iframe_flag’ to ‘true’ does NOT
undefine the contraction properties of a metric defined by a call to
‘defcon’ or ‘imetric’.  If a frame field is used, it is best to define
the metric by assigning its name to the variable ‘imetric’ and NOT
invoke the ‘imetric’ function.

   Maxima uses these two tensors to define the frame coefficients
(‘ifc1’ and ‘ifc2’) which form part of the connection coefficients
(‘icc1’ and ‘icc2’), as the following example demonstrates:


     (%i1) load("itensor");
     (%o1)      /share/tensor/itensor.lisp
     (%i2) iframe_flag:true;
     (%o2)                                true
     (%i3) ishow(covdiff(v([],[i]),j))$
                                    i        i     %1
     (%t3)                         v   + icc2     v
                                    ,j       %1 j
     (%i4) ishow(ev(%,icc2))$
                                    %1     i       i
     (%t4)                         v   ifc2     + v
                                           %1 j    ,j
     (%i5) ishow(ev(%,ifc2))$
                               %1    i %2                i
     (%t5)                    v   ifg     ifc1        + v
                                              %1 j %2    ,j
     (%i6) ishow(ev(%,ifc1))$
                 %1    i %2
                v   ifg     (ifb        - ifb        + ifb       )
                                j %2 %1      %2 %1 j      %1 j %2     i
     (%t6)      -------------------------------------------------- + v
                                        2                             ,j
     (%i7) ishow(ifb([a,b,c]))$
                                                        %3    %4
     (%t7)               (ifri        - ifri       ) ifr   ifr
                              a %3,%4       a %4,%3     b     c


   An alternate method is used to compute the frame bracket (‘ifb’) if
the ‘iframe_bracket_form’ flag is set to ‘false’:


     (%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$
                                     %6    %5        %5      %6
     (%t8)              ifri     (ifr   ifr     - ifr     ifr  )
                            a %5     b     c,%6      b,%6    c


 -- Function: iframes ()

     Since in this version of Maxima, contraction identities for ‘ifr’
     and ‘ifri’ are always defined, as is the frame bracket (‘ifb’),
     this function does nothing.

 -- Variable: ifb

     The frame bracket.  The contribution of the frame metric to the
     connection coefficients is expressed using the frame bracket:


                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                  2


     The frame bracket itself is defined in terms of the frame field and
     frame metric.  Two alternate methods of computation are used
     depending on the value of ‘frame_bracket_form’.  If true (the
     default) or if the ‘itorsion_flag’ is ‘true’:


                    d      e                                      f
          ifb =  ifr    ifr   (ifri      - ifri      - ifri    itr   )
             abc    b      c       a d,e       a e,d       a f    d e



     Otherwise:


                       e      d        d      e
          ifb    = (ifr    ifr    - ifr    ifr   ) ifri
             abc       b      c,e      b,e    c        a d


 -- Variable: icc1

     Connection coefficients of the first kind.  In ‘itensor’, defined
     as


          icc1    = ichr1    - ikt1    - inmc1
              abc        abc       abc        abc


     In this expression, if ‘iframe_flag’ is true, the
     Christoffel-symbol ‘ichr1’ is replaced with the frame connection
     coefficient ‘ifc1’.  If ‘itorsion_flag’ is ‘false’, ‘ikt1’ will be
     omitted.  It is also omitted if a frame base is used, as the
     torsion is already calculated as part of the frame bracket.
     Lastly, of ‘inonmet_flag’ is ‘false’, ‘inmc1’ will not be present.

 -- Variable: icc2

     Connection coefficients of the second kind.  In ‘itensor’, defined
     as


              c         c        c         c
          icc2   = ichr2   - ikt2   - inmc2
              ab        ab       ab        ab


     In this expression, if ‘iframe_flag’ is true, the
     Christoffel-symbol ‘ichr2’ is replaced with the frame connection
     coefficient ‘ifc2’.  If ‘itorsion_flag’ is ‘false’, ‘ikt2’ will be
     omitted.  It is also omitted if a frame base is used, as the
     torsion is already calculated as part of the frame bracket.
     Lastly, of ‘inonmet_flag’ is ‘false’, ‘inmc2’ will not be present.

 -- Variable: ifc1

     Frame coefficient of the first kind (also known as Ricci-rotation
     coefficients.)  This tensor represents the contribution of the
     frame metric to the connection coefficient of the first kind.
     Defined as:


                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                   2



 -- Variable: ifc2

     Frame coefficient of the second kind.  This tensor represents the
     contribution of the frame metric to the connection coefficient of
     the second kind.  Defined as a permutation of the frame bracket
     (‘ifb’) with the appropriate indices raised and lowered as
     necessary:


              c       cd
          ifc2   = ifg   ifc1
              ab             abd


 -- Variable: ifr

     The frame field.  Contracts with the inverse frame field (‘ifri’)
     to form the frame metric (‘ifg’).

 -- Variable: ifri

     The inverse frame field.  Specifies the frame base (dual basis
     vectors).  Along with the frame metric, it forms the basis of all
     calculations based on frames.

 -- Variable: ifg

     The frame metric.  Defaults to ‘kdelta’, but can be changed using
     ‘components’.

 -- Variable: ifgi

     The inverse frame metric.  Contracts with the frame metric (‘ifg’)
     to ‘kdelta’.

 -- Option variable: iframe_bracket_form
     Default value: ‘true’

     Specifies how the frame bracket (‘ifb’) is computed.

25.2.6 Torsion and nonmetricity
-------------------------------

Maxima can now take into account torsion and nonmetricity.  When the
flag ‘itorsion_flag’ is set to ‘true’, the contribution of torsion is
added to the connection coefficients.  Similarly, when the flag
‘inonmet_flag’ is true, nonmetricity components are included.

 -- Variable: inm

     The nonmetricity vector.  Conformal nonmetricity is defined through
     the covariant derivative of the metric tensor.  Normally zero, the
     metric tensor's covariant derivative will evaluate to the following
     when ‘inonmet_flag’ is set to ‘true’:


          g     =- g  inm
           ij;k     ij   k


 -- Variable: inmc1

     Covariant permutation of the nonmetricity vector components.
     Defined as


                     g   inm  - inm  g   - g   inm
                      ab    c      a  bc    ac    b
          inmc1    = ------------------------------
               abc                 2


     (Substitute ‘ifg’ in place of ‘g’ if a frame metric is used.)

 -- Variable: inmc2

     Contravariant permutation of the nonmetricity vector components.
     Used in the connection coefficients if ‘inonmet_flag’ is ‘true’.
     Defined as:


                                c         c         cd
                    -inm  kdelta  - kdelta  inm  + g   inm  g
               c        a       b         a    b          d  ab
          inmc2   = -------------------------------------------
               ab                        2


     (Substitute ‘ifg’ in place of ‘g’ if a frame metric is used.)

 -- Variable: ikt1

     Covariant permutation of the torsion tensor (also known as
     contorsion).  Defined as:


                            d           d       d
                    -g   itr  - g    itr   - itr   g
                      ad    cb    bd    ca      ab  cd
          ikt1    = ----------------------------------
              abc                   2


     (Substitute ‘ifg’ in place of ‘g’ if a frame metric is used.)

 -- Variable: ikt2

     Contravariant permutation of the torsion tensor (also known as
     contorsion).  Defined as:


              c     cd
          ikt2   = g   ikt1
              ab           abd


     (Substitute ‘ifg’ in place of ‘g’ if a frame metric is used.)

 -- Variable: itr

     The torsion tensor.  For a metric with torsion, repeated covariant
     differentiation on a scalar function will not commute, as
     demonstrated by the following example:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric:g;
          (%o2)                                  g
          (%i3) covdiff( covdiff( f( [], []), i), j)
                                - covdiff( covdiff( f( [], []), j), i)$
          (%i4) ishow(%)$
                                             %4              %2
          (%t4)                    f    ichr2    - f    ichr2
                                    ,%4      j i    ,%2      i j
          (%i5) canform(%);
          (%o5)                                  0
          (%i6) itorsion_flag:true;
          (%o6)                                true
          (%i7) covdiff( covdiff( f( [], []), i), j)
                                - covdiff( covdiff( f( [], []), j), i)$
          (%i8) ishow(%)$
                                     %8             %6
          (%t8)             f    icc2    - f    icc2    - f     + f
                             ,%8     j i    ,%6     i j    ,j i    ,i j
          (%i9) ishow(canform(%))$
                                             %1             %1
          (%t9)                     f    icc2    - f    icc2
                                     ,%1     j i    ,%1     i j
          (%i10) ishow(canform(ev(%,icc2)))$
                                             %1             %1
          (%t10)                    f    ikt2    - f    ikt2
                                     ,%1     i j    ,%1     j i
          (%i11) ishow(canform(ev(%,ikt2)))$
                                %2 %1                    %2 %1
          (%t11)          f    g      ikt1       - f    g      ikt1
                           ,%2            i j %1    ,%2            j i %1
          (%i12) ishow(factor(canform(rename(expand(ev(%,ikt1))))))$
                                     %3 %2            %1       %1
                               f    g      g      (itr    - itr   )
                                ,%3         %2 %1     j i      i j
          (%t12)               ------------------------------------
                                                2
          (%i13) decsym(itr,2,1,[anti(all)],[]);
          (%o13)                               done
          (%i14) defcon(g,g,kdelta);
          (%o14)                               done
          (%i15) subst(g,nounify(g),%th(3))$
          (%i16) ishow(canform(contract(%)))$
                                                     %1
          (%t16)                           - f    itr
                                              ,%1    i j


25.2.7 Exterior algebra
-----------------------

The ‘itensor’ package can perform operations on totally antisymmetric
covariant tensor fields.  A totally antisymmetric tensor field of rank
(0,L) corresponds with a differential L-form.  On these objects, a
multiplication operation known as the exterior product, or wedge
product, is defined.

   Unfortunately, not all authors agree on the definition of the wedge
product.  Some authors prefer a definition that corresponds with the
notion of antisymmetrization: in these works, the wedge product of two
vector fields, for instance, would be defined as

                 a a  - a a
                  i j    j i
      a  /\ a  = -----------
       i     j        2

   More generally, the product of a p-form and a q-form would be defined
as

                            1     k1..kp l1..lq
     A       /\ B       = ------ D              A       B
      i1..ip     j1..jq   (p+q)!  i1..ip j1..jq  k1..kp  l1..lq

   where ‘D’ stands for the Kronecker-delta.

   Other authors, however, prefer a "geometric" definition that
corresponds with the notion of the volume element:

     a  /\ a  = a a  - a a
      i     j    i j    j i

   and, in the general case

                            1    k1..kp l1..lq
     A       /\ B       = ----- D              A       B
      i1..ip     j1..jq   p! q!  i1..ip j1..jq  k1..kp  l1..lq

   Since ‘itensor’ is a tensor algebra package, the first of these two
definitions appears to be the more natural one.  Many applications,
however, utilize the second definition.  To resolve this dilemma, a flag
has been implemented that controls the behavior of the wedge product: if
‘igeowedge_flag’ is ‘false’ (the default), the first, "tensorial"
definition is used, otherwise the second, "geometric" definition will be
applied.

 -- Operator: ~

     The wedge product operator is denoted by the tilde ‘~’.  This is a
     binary operator.  Its arguments should be expressions involving
     scalars, covariant tensors of rank one, or covariant tensors of
     rank ‘l’ that have been declared antisymmetric in all covariant
     indices.

     The behavior of the wedge product operator is controlled by the
     ‘igeowedge_flag’ flag, as in the following example:

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i])~b([j]))$
                                           a  b  - b  a
                                            i  j    i  j
          (%t2)                            -------------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(a([i,j])~b([k]))$
                                    a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j
          (%t4)                     ---------------------------
                                                 3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(a([i])~b([j]))$
          (%t6)                            a  b  - b  a
                                            i  j    i  j
          (%i7) ishow(a([i,j])~b([k]))$
          (%t7)                     a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j

 -- Operator: |

     The vertical bar ‘|’ denotes the "contraction with a vector" binary
     operation.  When a totally antisymmetric covariant tensor is
     contracted with a contravariant vector, the result is the same
     regardless which index was used for the contraction.  Thus, it is
     possible to define the contraction operation in an index-free
     manner.

     In the ‘itensor’ package, contraction with a vector is always
     carried out with respect to the first index in the literal sorting
     order.  This ensures better simplification of expressions involving
     the ‘|’ operator.  For instance:

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) decsym(a,2,0,[anti(all)],[]);
          (%o2)                                done
          (%i3) ishow(a([i,j],[])|v)$
                                              %1
          (%t3)                              v   a
                                                  %1 j
          (%i4) ishow(a([j,i],[])|v)$
                                               %1
          (%t4)                             - v   a
                                                   %1 j

     Note that it is essential that the tensors used with the ‘|’
     operator be declared totally antisymmetric in their covariant
     indices.  Otherwise, the results will be incorrect.

 -- Function: extdiff (<expr>, <i>)

     Computes the exterior derivative of <expr> with respect to the
     index <i>.  The exterior derivative is formally defined as the
     wedge product of the partial derivative operator and a differential
     form.  As such, this operation is also controlled by the setting of
     ‘igeowedge_flag’.  For instance:

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(extdiff(v([i]),j))$
                                            v    - v
                                             j,i    i,j
          (%t2)                             -----------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(extdiff(a([i,j]),k))$
                                     a      - a      + a
                                      j k,i    i k,j    i j,k
          (%t4)                      ------------------------
                                                3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(extdiff(v([i]),j))$
          (%t6)                             v    - v
                                             j,i    i,j
          (%i7) ishow(extdiff(a([i,j]),k))$
          (%t7)                    - (a      - a      + a     )
                                       k j,i    k i,j    j i,k


 -- Function: hodge (<expr>)

     Compute the Hodge-dual of <expr>.  For instance:


          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                            done
          (%i3) idim(4);
          (%o3)                            done
          (%i4) icounter:100;
          (%o4)                             100
          (%i5) decsym(A,3,0,[anti(all)],[])$

          (%i6) ishow(A([i,j,k],[]))$
          (%t6)                           A
                                           i j k
          (%i7) ishow(canform(hodge(%)))$
                                    %1 %2 %3 %4
                         levi_civita            g        A
                                                 %1 %102  %2 %3 %4
          (%t7)          -----------------------------------------
                                             6
          (%i8) ishow(canform(hodge(%)))$
                           %1 %2 %3 %8            %4 %5 %6 %7
          (%t8) levi_civita            levi_civita            g
                                                               %1 %106
                                       g        g        g      A         /6
                                        %2 %107  %3 %108  %4 %8  %5 %6 %7
          (%i9) lc2kdt(%)$

          (%i10) %,kdelta$

          (%i11) ishow(canform(contract(expand(%))))$
          (%t11)                     - A
                                        %106 %107 %108


 -- Option variable: igeowedge_flag
     Default value: ‘false’

     Controls the behavior of the wedge product and exterior derivative.
     When set to ‘false’ (the default), the notion of differential forms
     will correspond with that of a totally antisymmetric covariant
     tensor field.  When set to ‘true’, differential forms will agree
     with the notion of the volume element.

25.2.8 Exporting TeX expressions
--------------------------------

The ‘itensor’ package provides limited support for exporting tensor
expressions to TeX. Since ‘itensor’ expressions appear as function
calls, the regular Maxima ‘tex’ command will not produce the expected
output.  You can try instead the ‘tentex’ command, which attempts to
translate tensor expressions into appropriately indexed TeX objects.

 -- Function: tentex (<expr>)

     To use the ‘tentex’ function, you must first load ‘tentex’, as in
     the following example:

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) load("tentex");
          (%o2)       /share/tensor/tentex.lisp
          (%i3) idummyx:m;
          (%o3)                                  m
          (%i4) ishow(icurvature([j,k,l],[i]))$
                      m1       i           m1       i           i
          (%t4)  ichr2    ichr2     - ichr2    ichr2     - ichr2
                      j k      m1 l        j l      m1 k        j l,k

                                                                i
                                                         + ichr2
                                                                j k,l
          (%i5) tentex(%)$
          $$\Gamma_{j\,k}^{m_1}\,\Gamma_{l\,m_1}^{i}-\Gamma_{j\,l}^{m_1}\,
           \Gamma_{k\,m_1}^{i}-\Gamma_{j\,l,k}^{i}+\Gamma_{j\,k,l}^{i}$$

     Note the use of the ‘idummyx’ assignment, to avoid the appearance
     of the percent sign in the TeX expression, which may lead to
     compile errors.

     NB: This version of the ‘tentex’ function is somewhat experimental.

25.2.9 Interfacing with ctensor
-------------------------------

The ‘itensor’ package has the ability to generate Maxima code that can
then be executed in the context of the ‘ctensor’ package.  The function
that performs this task is ‘ic_convert’.

 -- Function: ic_convert (<eqn>)

     Converts the ‘itensor’ equation <eqn> to a ‘ctensor’ assignment
     statement.  Implied sums over dummy indices are made explicit while
     indexed objects are transformed into arrays (the array subscripts
     are in the order of covariant followed by contravariant indices of
     the indexed objects).  The derivative of an indexed object will be
     replaced by the noun form of ‘diff’ taken with respect to
     ‘ct_coords’ subscripted by the derivative index.  The Christoffel
     symbols ‘ichr1’ and ‘ichr2’ will be translated to ‘lcs’ and ‘mcs’,
     respectively and if ‘metricconvert’ is ‘true’ then all occurrences
     of the metric with two covariant (contravariant) indices will be
     renamed to ‘lg’ (‘ug’).  In addition, ‘do’ loops will be introduced
     summing over all free indices so that the transformed assignment
     statement can be evaluated by just doing ‘ev’.  The following
     examples demonstrate the features of this function.

          (%i1) load("itensor");
          (%o1)      /share/tensor/itensor.lisp
          (%i2) eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j)
                *b([i],[l,k]))$
                                       k        m   l k
          (%t2)                       t    = f a   b    g
                                       i j      ,j  i    l m
          (%i3) ic_convert(eqn);
          (%o3) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           g    , l, 1, dim), m, 1, dim)))
            l, m
          (%i4) imetric(g);
          (%o4)                                done
          (%i5) metricconvert:true;
          (%o5)                                true
          (%i6) ic_convert(eqn);
          (%o6) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           lg    , l, 1, dim), m, 1, dim)))
             l, m

25.2.10 Reserved words
----------------------

The following Maxima words are used by the ‘itensor’ package internally
and should not be redefined:

       Keyword    Comments
       ------------------------------------------
       indices2() Internal version of indices()
       conti      Lists contravariant indices
       covi       Lists covariant indices of an indexed object
       deri       Lists derivative indices of an indexed object
       name       Returns the name of an indexed object
       concan
       irpmon
       lc0
       _lc2kdt0
       _lcprod
       _extlc


File: maxima.info,  Node: Package ctensor,  Next: Package atensor,  Prev: Package itensor,  Up: Top

26 Package ctensor
******************

* Menu:

* Introduction to ctensor::
* Functions and Variables for ctensor::


File: maxima.info,  Node: Introduction to ctensor,  Next: Functions and Variables for ctensor,  Prev: Package ctensor,  Up: Package ctensor

26.1 Introduction to ctensor
============================

‘ctensor’ is a component tensor manipulation package.  To use the
‘ctensor’ package, type ‘load("ctensor")’.  To begin an interactive
session with ‘ctensor’, type ‘csetup()’.  You are first asked to specify
the dimension of the manifold.  If the dimension is 2, 3 or 4 then the
list of coordinates defaults to ‘[x,y]’, ‘[x,y,z]’ or ‘[x,y,z,t]’
respectively.  These names may be changed by assigning a new list of
coordinates to the variable ‘ct_coords’ (described below) and the user
is queried about this.  Care must be taken to avoid the coordinate names
conflicting with other object definitions.

   Next, the user enters the metric either directly or from a file by
specifying its ordinal position.  The metric is stored in the matrix
‘lg’.  Finally, the metric inverse is computed and stored in the matrix
‘ug’.  One has the option of carrying out all calculations in a power
series.

   A sample protocol is begun below for the static, spherically
symmetric metric (standard coordinates) which will be applied to the
problem of deriving Einstein's vacuum equations (which lead to the
Schwarzschild solution) as an example.  Many of the functions in
‘ctensor’ will be displayed for the standard metric as examples.

     (%i1) load("ctensor");
     (%o1)      /share/tensor/ctensor.mac
     (%i2) csetup();
     Enter the dimension of the coordinate system:
     4;
     Do you wish to change the coordinate names?
     n;
     Do you want to
     1. Enter a new metric?

     2. Enter a metric from a file?

     3. Approximate a metric with a Taylor series?
     1;

     Is the matrix  1. Diagonal  2. Symmetric  3. Antisymmetric  4. General
     Answer 1, 2, 3 or 4
     1;
     Row 1 Column 1:
     a;
     Row 2 Column 2:
     x^2;
     Row 3 Column 3:
     x^2*sin(y)^2;
     Row 4 Column 4:
     -d;

     Matrix entered.
     Enter functional dependencies with the DEPENDS function or 'N' if none
     depends([a,d],x);
     Do you wish to see the metric?
     y;
                               [ a  0       0        0  ]
                               [                        ]
                               [     2                  ]
                               [ 0  x       0        0  ]
                               [                        ]
                               [         2    2         ]
                               [ 0  0   x  sin (y)   0  ]
                               [                        ]
                               [ 0  0       0       - d ]
     (%o2)                                done
     (%i3) christof(mcs);
                                                 a
                                                  x
     (%t3)                          mcs        = ---
                                       1, 1, 1   2 a

                                                  1
     (%t4)                           mcs        = -
                                        1, 2, 2   x

                                                  1
     (%t5)                           mcs        = -
                                        1, 3, 3   x

                                                 d
                                                  x
     (%t6)                          mcs        = ---
                                       1, 4, 4   2 d

                                                   x
     (%t7)                          mcs        = - -
                                       2, 2, 1     a

                                                cos(y)
     (%t8)                         mcs        = ------
                                      2, 3, 3   sin(y)

                                                    2
                                               x sin (y)
     (%t9)                      mcs        = - ---------
                                   3, 3, 1         a

     (%t10)                   mcs        = - cos(y) sin(y)
                                 3, 3, 2

                                                 d
                                                  x
     (%t11)                         mcs        = ---
                                       4, 4, 1   2 a
     (%o11)                               done



File: maxima.info,  Node: Functions and Variables for ctensor,  Prev: Introduction to ctensor,  Up: Package ctensor

26.2 Functions and Variables for ctensor
========================================

26.2.1 Initialization and setup
-------------------------------

 -- Function: csetup ()
     A function in the ‘ctensor’ (component tensor) package which
     initializes the package and allows the user to enter a metric
     interactively.  See ‘ctensor’ for more details.

 -- Function: cmetric
          cmetric (<dis>)
          cmetric ()

     A function in the ‘ctensor’ (component tensor) package that
     computes the metric inverse and sets up the package for further
     calculations.

     If ‘cframe_flag’ is ‘false’, the function computes the inverse
     metric ‘ug’ from the (user-defined) matrix ‘lg’.  The metric
     determinant is also computed and stored in the variable ‘gdet’.
     Furthermore, the package determines if the metric is diagonal and
     sets the value of ‘diagmetric’ accordingly.  If the optional
     argument <dis> is present and not equal to ‘false’, the user is
     prompted to see the metric inverse.

     If ‘cframe_flag’ is ‘true’, the function expects that the values of
     ‘fri’ (the inverse frame matrix) and ‘lfg’ (the frame metric) are
     defined.  From these, the frame matrix ‘fr’ and the inverse frame
     metric ‘ufg’ are computed.

 -- Function: ct_coordsys
          ct_coordsys (<coordinate_system>, <extra_arg>)
          ct_coordsys (<coordinate_system>)

     Sets up a predefined coordinate system and metric.  The argument
     <coordinate_system> can be one of the following symbols:


           SYMBOL             Dim Coordinates     Description/comments
           ------------------------------------------------------------------
           cartesian2d           2  [x,y]             Cartesian 2D coordinate
                                                      system
           polar                 2  [r,phi]           Polar coordinate system
           elliptic              2  [u,v]             Elliptic coord. system
           confocalelliptic      2  [u,v]             Confocal elliptic
                                                      coordinates
           bipolar               2  [u,v]             Bipolar coord. system
           parabolic             2  [u,v]             Parabolic coord. system
           cartesian3d           3  [x,y,z]           Cartesian 3D coordinate
                                                      system
           polarcylindrical      3  [r,theta,z]       Polar 2D with
                                                      cylindrical z
           ellipticcylindrical   3  [u,v,z]           Elliptic 2D with
                                                      cylindrical z
           confocalellipsoidal   3  [u,v,w]           Confocal ellipsoidal
           bipolarcylindrical    3  [u,v,z]           Bipolar 2D with
                                                      cylindrical z
           paraboliccylindrical  3  [u,v,z]           Parabolic 2D with
                                                      cylindrical z
           paraboloidal          3  [u,v,phi]         Paraboloidal coords.
           conical               3  [u,v,w]           Conical coordinates
           toroidal              3  [phi,u,v]         Toroidal coordinates
           spherical             3  [r,theta,phi]     Spherical coord. system
           oblatespheroidal      3  [u,v,phi]         Oblate spheroidal
                                                      coordinates
           oblatespheroidalsqrt  3  [u,v,phi]
           prolatespheroidal     3  [u,v,phi]         Prolate spheroidal
                                                      coordinates
           prolatespheroidalsqrt 3  [u,v,phi]
           ellipsoidal           3  [r,theta,phi]     Ellipsoidal coordinates
           cartesian4d           4  [x,y,z,t]         Cartesian 4D coordinate
                                                      system
           spherical4d           4  [r,theta,eta,phi] Spherical 4D coordinate
                                                      system
           exteriorschwarzschild 4  [t,r,theta,phi]   Schwarzschild metric
           interiorschwarzschild 4  [t,z,u,v]         Interior Schwarzschild
                                                      metric
           kerr_newman           4  [t,r,theta,phi]   Charged axially
                                                      symmetric metric

     ‘coordinate_system’ can also be a list of transformation functions,
     followed by a list containing the coordinate variables.  For
     instance, you can specify a spherical metric as follows:


          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                r*sin(theta),[r,theta,phi]]);
          (%o2)                                done
          (%i3) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o3)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]
          (%i4) ct_coords;
          (%o4)                           [r, theta, phi]
          (%i5) dim;
          (%o5)                                  3


     Transformation functions can also be used when ‘cframe_flag’ is
     ‘true’:


          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) cframe_flag:true;
          (%o2)                                true
          (%i3) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                r*sin(theta),[r,theta,phi]]);
          (%o3)                                done
          (%i4) fri;
          (%o4)
           [cos(phi)cos(theta) -cos(phi) r sin(theta) -sin(phi) r cos(theta)]
           [                                                                ]
           [sin(phi)cos(theta) -sin(phi) r sin(theta)  cos(phi) r cos(theta)]
           [                                                                ]
           [    sin(theta)           r cos(theta)                0          ]

          (%i5) cmetric();
          (%o5)                                false
          (%i6) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o6)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]


     The optional argument <extra_arg> can be any one of the following:

     ‘cylindrical’ tells ‘ct_coordsys’ to attach an additional
     cylindrical coordinate.

     ‘minkowski’ tells ‘ct_coordsys’ to attach an additional coordinate
     with negative metric signature.

     ‘all’ tells ‘ct_coordsys’ to call ‘cmetric’ and ‘christof(false)’
     after setting up the metric.

     If the global variable ‘verbose’ is set to ‘true’, ‘ct_coordsys’
     displays the values of ‘dim’, ‘ct_coords’, and either ‘lg’ or ‘lfg’
     and ‘fri’, depending on the value of ‘cframe_flag’.

 -- Function: init_ctensor ()
     Initializes the ‘ctensor’ package.

     The ‘init_ctensor’ function reinitializes the ‘ctensor’ package.
     It removes all arrays and matrices used by ‘ctensor’, resets all
     flags, resets ‘dim’ to 4, and resets the frame metric to the
     Lorentz-frame.

26.2.2 The tensors of curved space
----------------------------------

The main purpose of the ‘ctensor’ package is to compute the tensors of
curved space(time), most notably the tensors used in general relativity.

   When a metric base is used, ‘ctensor’ can compute the following
tensors:


      lg  -- ug
        \      \
         lcs -- mcs -- ric -- uric
                   \      \       \
                    \      tracer - ein -- lein
                     \
                      riem -- lriem -- weyl
                          \
                           uriem



   ‘ctensor’ can also work using moving frames.  When ‘cframe_flag’ is
set to ‘true’, the following tensors can be calculated:


      lfg -- ufg
          \
      fri -- fr -- lcs -- mcs -- lriem -- ric -- uric
           \                       |  \      \       \
            lg -- ug               |   weyl   tracer - ein -- lein
                                   |\
                                   | riem
                                   |
                                   \uriem

 -- Function: christof (<dis>)
     A function in the ‘ctensor’ (component tensor) package.  It
     computes the Christoffel symbols of both kinds.  The argument <dis>
     determines which results are to be immediately displayed.  The
     Christoffel symbols of the first and second kinds are stored in the
     arrays ‘lcs[i,j,k]’ and ‘mcs[i,j,k]’ respectively and defined to be
     symmetric in the first two indices.  If the argument to ‘christof’
     is ‘lcs’ or ‘mcs’ then the unique non-zero values of ‘lcs[i,j,k]’
     or ‘mcs[i,j,k]’, respectively, will be displayed.  If the argument
     is ‘all’ then the unique non-zero values of ‘lcs[i,j,k]’ and
     ‘mcs[i,j,k]’ will be displayed.  If the argument is ‘false’ then
     the display of the elements will not occur.  The array elements
     ‘mcs[i,j,k]’ are defined in such a manner that the final index is
     contravariant.

 -- Function: ricci (<dis>)
     A function in the ‘ctensor’ (component tensor) package.  ‘ricci’
     computes the covariant (symmetric) components ‘ric[i,j]’ of the
     Ricci tensor.  If the argument <dis> is ‘true’, then the non-zero
     components are displayed.

 -- Function: uricci (<dis>)
     This function first computes the covariant components ‘ric[i,j]’ of
     the Ricci tensor.  Then the mixed Ricci tensor is computed using
     the contravariant metric tensor.  If the value of the argument
     <dis> is ‘true’, then these mixed components, ‘uric[i,j]’ (the
     index ‘i’ is covariant and the index ‘j’ is contravariant), will be
     displayed directly.  Otherwise, ‘ricci(false)’ will simply compute
     the entries of the array ‘uric[i,j]’ without displaying the
     results.

 -- Function: scurvature ()
     Returns the scalar curvature (obtained by contracting the Ricci
     tensor) of the Riemannian manifold with the given metric.

 -- Function: einstein (<dis>)
     A function in the ‘ctensor’ (component tensor) package.  ‘einstein’
     computes the mixed Einstein tensor after the Christoffel symbols
     and Ricci tensor have been obtained (with the functions ‘christof’
     and ‘ricci’).  If the argument <dis> is ‘true’, then the non-zero
     values of the mixed Einstein tensor ‘ein[i,j]’ will be displayed
     where ‘j’ is the contravariant index.  The variable ‘rateinstein’
     will cause the rational simplification on these components.  If
     ‘ratfac’ is ‘true’ then the components will also be factored.

 -- Function: leinstein (<dis>)
     Covariant Einstein-tensor.  ‘leinstein’ stores the values of the
     covariant Einstein tensor in the array ‘lein’.  The covariant
     Einstein-tensor is computed from the mixed Einstein tensor ‘ein’ by
     multiplying it with the metric tensor.  If the argument <dis> is
     ‘true’, then the non-zero values of the covariant Einstein tensor
     are displayed.

 -- Function: riemann (<dis>)
     A function in the ‘ctensor’ (component tensor) package.  ‘riemann’
     computes the Riemann curvature tensor from the given metric and the
     corresponding Christoffel symbols.  The following index conventions
     are used:

                          l      _l       _l       _l   _m    _l   _m
           R[i,j,k,l] =  R    = |      - |      + |    |   - |    |
                          ijk     ij,k     ik,j     mk   ij    mj   ik

     This notation is consistent with the notation used by the ‘itensor’
     package and its ‘icurvature’ function.  If the optional argument
     <dis> is ‘true’, the unique non-zero components ‘riem[i,j,k,l]’
     will be displayed.  As with the Einstein tensor, various switches
     set by the user control the simplification of the components of the
     Riemann tensor.  If ‘ratriemann’ is ‘true’, then rational
     simplification will be done.  If ‘ratfac’ is ‘true’ then each of
     the components will also be factored.

     If the variable ‘cframe_flag’ is ‘false’, the Riemann tensor is
     computed directly from the Christoffel-symbols.  If ‘cframe_flag’
     is ‘true’, the covariant Riemann-tensor is computed first from the
     frame field coefficients.

 -- Function: lriemann (<dis>)
     Covariant Riemann-tensor (‘lriem[]’).

     Computes the covariant Riemann-tensor as the array ‘lriem’.  If the
     argument <dis> is ‘true’, unique non-zero values are displayed.

     If the variable ‘cframe_flag’ is ‘true’, the covariant Riemann
     tensor is computed directly from the frame field coefficients.
     Otherwise, the (3,1) Riemann tensor is computed first.

     For information on index ordering, see ‘riemann’.

 -- Function: uriemann (<dis>)
     Computes the contravariant components of the Riemann curvature
     tensor as array elements ‘uriem[i,j,k,l]’.  These are displayed if
     <dis> is ‘true’.

 -- Function: rinvariant ()
     Forms the Kretschmann-invariant (‘kinvariant’) obtained by
     contracting the tensors

          lriem[i,j,k,l]*uriem[i,j,k,l].

     This object is not automatically simplified since it can be very
     large.

 -- Function: weyl (<dis>)
     Computes the Weyl conformal tensor.  If the argument <dis> is
     ‘true’, the non-zero components ‘weyl[i,j,k,l]’ will be displayed
     to the user.  Otherwise, these components will simply be computed
     and stored.  If the switch ‘ratweyl’ is set to ‘true’, then the
     components will be rationally simplified; if ‘ratfac’ is ‘true’
     then the results will be factored as well.

26.2.3 Taylor series expansion
------------------------------

The ‘ctensor’ package has the ability to truncate results by assuming
that they are Taylor-series approximations.  This behavior is controlled
by the ‘ctayswitch’ variable; when set to true, ‘ctensor’ makes use
internally of the function ‘ctaylor’ when simplifying results.

   The ‘ctaylor’ function is invoked by the following ‘ctensor’
functions:


         Function     Comments
         ---------------------------------
         christof()   For mcs only
         ricci()
         uricci()
         einstein()
         riemann()
         weyl()
         checkdiv()
 -- Function: ctaylor ()

     The ‘ctaylor’ function truncates its argument by converting it to a
     Taylor-series using ‘taylor’, and then calling ‘ratdisrep’.  This
     has the combined effect of dropping terms higher order in the
     expansion variable ‘ctayvar’.  The order of terms that should be
     dropped is defined by ‘ctaypov’; the point around which the series
     expansion is carried out is specified in ‘ctaypt’.

     As an example, consider a simple metric that is a perturbation of
     the Minkowski metric.  Without further restrictions, even a
     diagonal metric produces expressions for the Einstein tensor that
     are far too complex:


          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) derivabbrev:true;
          (%o3)                                true
          (%i4) ct_coords:[t,r,theta,phi];
          (%o4)                         [t, r, theta, phi]
          (%i5) lg:matrix([-1,0,0,0],[0,1,0,0],[0,0,r^2,0],
                          [0,0,0,r^2*sin(theta)^2]);
                                  [ - 1  0  0         0        ]
                                  [                            ]
                                  [  0   1  0         0        ]
                                  [                            ]
          (%o5)                   [          2                 ]
                                  [  0   0  r         0        ]
                                  [                            ]
                                  [              2    2        ]
                                  [  0   0  0   r  sin (theta) ]
          (%i6) h:matrix([h11,0,0,0],[0,h22,0,0],[0,0,h33,0],[0,0,0,h44]);
                                      [ h11   0    0    0  ]
                                      [                    ]
                                      [  0   h22   0    0  ]
          (%o6)                       [                    ]
                                      [  0    0   h33   0  ]
                                      [                    ]
                                      [  0    0    0   h44 ]
          (%i7) depends(l,r);
          (%o7)                               [l(r)]
          (%i8) lg:lg+l*h;
                [ h11 l - 1      0          0                 0            ]
                [                                                          ]
                [     0      h22 l + 1      0                 0            ]
                [                                                          ]
          (%o8) [                        2                                 ]
                [     0          0      r  + h33 l            0            ]
                [                                                          ]
                [                                    2    2                ]
                [     0          0          0       r  sin (theta) + h44 l ]
          (%i9) cmetric(false);
          (%o9)                                done
          (%i10) einstein(false);
          (%o10)                               done
          (%i11) ntermst(ein);
          [[1, 1], 62]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 24]
          [[2, 3], 0]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 0]
          [[3, 3], 46]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 46]
          (%o12)                               done


     However, if we recompute this example as an approximation that is
     linear in the variable ‘l’, we get much simpler expressions:


          (%i14) ctayswitch:true;
          (%o14)                               true
          (%i15) ctayvar:l;
          (%o15)                                 l
          (%i16) ctaypov:1;
          (%o16)                                 1
          (%i17) ctaypt:0;
          (%o17)                                 0
          (%i18) christof(false);
          (%o18)                               done
          (%i19) ricci(false);
          (%o19)                               done
          (%i20) einstein(false);
          (%o20)                               done
          (%i21) ntermst(ein);
          [[1, 1], 6]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 13]
          [[2, 3], 2]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 2]
          [[3, 3], 9]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 9]
          (%o21)                               done
          (%i22) ratsimp(ein[1,1]);
                                   2      2  4               2     2
          (%o22) - (((h11 h22 - h11 ) (l )  r  - 2 h33 l    r ) sin (theta)
                                        r               r r

                                      2               2      4    2
                        - 2 h44 l    r  - h33 h44 (l ) )/(4 r  sin (theta))
                                 r r                r




     This capability can be useful, for instance, when working in the
     weak field limit far from a gravitational source.

26.2.4 Frame fields
-------------------

When the variable ‘cframe_flag’ is set to true, the ‘ctensor’ package
performs its calculations using a moving frame.
 -- Function: frame_bracket (<fr>, <fri>, <diagframe>)
     The frame bracket (‘fb[]’).

     Computes the frame bracket according to the following definition:

             c          c         c        d     e
          ifb   = ( ifri    - ifri    ) ifr   ifr
             ab         d,e       e,d      a     b

26.2.5 Algebraic classification
-------------------------------

A new feature (as of November, 2004) of ‘ctensor’ is its ability to
compute the Petrov classification of a 4-dimensional spacetime metric.
For a demonstration of this capability, see the file
‘share/tensor/petrov.dem’.
 -- Function: nptetrad ()
     Computes a Newman-Penrose null tetrad (‘np’) and its raised-index
     counterpart (‘npi’).  See ‘petrov’ for an example.

     The null tetrad is constructed on the assumption that a
     four-dimensional orthonormal frame metric with metric signature
     (-,+,+,+) is being used.  The components of the null tetrad are
     related to the inverse frame matrix as follows:


          np  = (fri  + fri ) / sqrt(2)
            1       1      2

          np  = (fri  - fri ) / sqrt(2)
            2       1      2

          np  = (fri  + %i fri ) / sqrt(2)
            3       3         4

          np  = (fri  - %i fri ) / sqrt(2)
            4       3         4


 -- Function: psi (<dis>)
     Computes the five Newman-Penrose coefficients ‘psi[0]’...‘psi[4]’.
     If ‘dis’ is set to ‘true’, the coefficients are displayed.  See
     ‘petrov’ for an example.

     These coefficients are computed from the Weyl-tensor in a
     coordinate base.  If a frame base is used, the Weyl-tensor is first
     converted to a coordinate base, which can be a computationally
     expensive procedure.  For this reason, in some cases it may be more
     advantageous to use a coordinate base in the first place before the
     Weyl tensor is computed.  Note however, that constructing a
     Newman-Penrose null tetrad requires a frame base.  Therefore, a
     meaningful computation sequence may begin with a frame base, which
     is then used to compute ‘lg’ (computed automatically by ‘cmetric’)
     and then ‘ug’.  See ‘petrov’ for an example.  At this point, you
     can switch back to a coordinate base by setting ‘cframe_flag’ to
     false before beginning to compute the Christoffel symbols.
     Changing to a frame base at a later stage could yield inconsistent
     results, as you may end up with a mixed bag of tensors, some
     computed in a frame base, some in a coordinate base, with no means
     to distinguish between the two.

 -- Function: petrov ()
     Computes the Petrov classification of the metric characterized by
     ‘psi[0]’...‘psi[4]’.

     For example, the following demonstrates how to obtain the
     Petrov-classification of the Kerr metric:

          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) (cframe_flag:true,gcd:spmod,ctrgsimp:true,ratfac:true);
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) ug:invert(lg)$
          (%i5) weyl(false);
          (%o5)                                done
          (%i6) nptetrad(true);
          (%t6) np =

          [ sqrt(r - 2 m)           sqrt(r)                                 ]
          [---------------   ---------------------    0            0        ]
          [sqrt(2) sqrt(r)   sqrt(2) sqrt(r - 2 m)                          ]
          [                                                                 ]
          [ sqrt(r - 2 m)            sqrt(r)                                ]
          [---------------  - ---------------------   0            0        ]
          [sqrt(2) sqrt(r)    sqrt(2) sqrt(r - 2 m)                         ]
          [                                                                 ]
          [                                          r      %i r sin(theta) ]
          [       0                    0          -------   --------------- ]
          [                                       sqrt(2)       sqrt(2)     ]
          [                                                                 ]
          [                                          r       %i r sin(theta)]
          [       0                    0          -------  - ---------------]
          [                                       sqrt(2)        sqrt(2)    ]

                                       sqrt(r)         sqrt(r - 2 m)
          (%t7) npi = matrix([- ---------------------,---------------, 0, 0],
                                sqrt(2) sqrt(r - 2 m) sqrt(2) sqrt(r)

                    sqrt(r)            sqrt(r - 2 m)
          [- ---------------------, - ---------------, 0, 0],
             sqrt(2) sqrt(r - 2 m)    sqrt(2) sqrt(r)

                     1               %i
          [0, 0, ---------, --------------------],
                 sqrt(2) r  sqrt(2) r sin(theta)

                     1                 %i
          [0, 0, ---------, - --------------------])
                 sqrt(2) r    sqrt(2) r sin(theta)

          (%o7)                                done
          (%i7) psi(true);
          (%t8)                              psi  = 0
                                                0

          (%t9)                              psi  = 0
                                                1

                                                    m
          (%t10)                             psi  = --
                                                2    3
                                                    r

          (%t11)                             psi  = 0
                                                3

          (%t12)                             psi  = 0
                                                4
          (%o12)                               done
          (%i12) petrov();
          (%o12)                                 D


     The Petrov classification function is based on the algorithm
     published in "Classifying geometries in general relativity: III
     Classification in practice" by Pollney, Skea, and d'Inverno, Class.
     Quant.  Grav.  17 2885-2902 (2000).  Except for some simple test
     cases, the implementation is untested as of December 19, 2004, and
     is likely to contain errors.

26.2.6 Torsion and nonmetricity
-------------------------------

‘ctensor’ has the ability to compute and include torsion and
nonmetricity coefficients in the connection coefficients.

   The torsion coefficients are calculated from a user-supplied tensor
‘tr’, which should be a rank (2,1) tensor.  From this, the torsion
coefficients ‘kt’ are computed according to the following formulae:


                   m          m      m
            - g  tr   - g   tr   - tr   g
               im  kj    jm   ki     ij  km
     kt   = -------------------------------
       ijk                 2


       k     km
     kt   = g   kt
       ij         ijm


   Note that only the mixed-index tensor is calculated and stored in the
array ‘kt’.

   The nonmetricity coefficients are calculated from the user-supplied
nonmetricity vector ‘nm’.  From this, the nonmetricity coefficients
‘nmc’ are computed as follows:


                  k    k        km
            -nm  D  - D  nm  + g   nm  g
        k      i  j    i   j         m  ij
     nmc  = ------------------------------
        ij                2


   where D stands for the Kronecker-delta.

   When ‘ctorsion_flag’ is set to ‘true’, the values of ‘kt’ are
subtracted from the mixed-indexed connection coefficients computed by
‘christof’ and stored in ‘mcs’.  Similarly, if ‘cnonmet_flag’ is set to
‘true’, the values of ‘nmc’ are subtracted from the mixed-indexed
connection coefficients.

   If necessary, ‘christof’ calls the functions ‘contortion’ and
‘nonmetricity’ in order to compute ‘kt’ and ‘nm’.
 -- Function: contortion (<tr>)

     Computes the (2,1) contortion coefficients from the torsion tensor
     <tr>.

 -- Function: nonmetricity (<nm>)

     Computes the (2,1) nonmetricity coefficients from the nonmetricity
     vector <nm>.

26.2.7 Miscellaneous features
-----------------------------

 -- Function: ctransform (<M>)
     A function in the ‘ctensor’ (component tensor) package which will
     perform a coordinate transformation upon an arbitrary square
     symmetric matrix <M>.  The user must input the functions which
     define the transformation.  (Formerly called ‘transform’.)  These
     may also be supplied in the form of a list as an optional second
     argument.

 -- Function: findde (<A>, <n>)

     returns a list of the unique differential equations (expressions)
     corresponding to the elements of the <n> dimensional square array
     <A>.  Presently, <n> may be 2 or 3.  ‘deindex’ is a global list
     containing the indices of <A> corresponding to these unique
     differential equations.  For the Einstein tensor (‘ein’), which is
     a two dimensional array, if computed for the metric in the example
     below, ‘findde’ gives the following independent differential
     equations:

          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) dim:4;
          (%o3)                                  4
          (%i4) lg:matrix([a, 0, 0, 0], [ 0, x^2, 0, 0],
                                        [0, 0, x^2*sin(y)^2, 0], [0,0,0,-d]);
                                    [ a  0       0        0  ]
                                    [                        ]
                                    [     2                  ]
                                    [ 0  x       0        0  ]
          (%o4)                     [                        ]
                                    [         2    2         ]
                                    [ 0  0   x  sin (y)   0  ]
                                    [                        ]
                                    [ 0  0       0       - d ]
          (%i5) depends([a,d],x);
          (%o5)                            [a(x), d(x)]
          (%i6) ct_coords:[x,y,z,t];
          (%o6)                            [x, y, z, t]
          (%i7) cmetric();
          (%o7)                                done
          (%i8) einstein(false);
          (%o8)                                done
          (%i9) findde(ein,2);
                                                      2
          (%o9) [d  x - a d + d, 2 a d d    x - a (d )  x - a  d d  x
                  x                     x x         x        x    x

                                                        2          2
                                    + 2 a d d   - 2 a  d , a  x + a  - a]
                                             x       x      x
          (%i10) deindex;
          (%o10)                     [[1, 1], [2, 2], [4, 4]]

 -- Function: cograd ()
     Computes the covariant gradient of a scalar function allowing the
     user to choose the corresponding vector name as the example under
     ‘contragrad’ illustrates.

 -- Function: contragrad ()

     Computes the contravariant gradient of a scalar function allowing
     the user to choose the corresponding vector name as the example
     below for the Schwarzschild metric illustrates:

          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(f,r);
          (%o4)                               [f(r)]
          (%i5) cograd(f,g1);
          (%o5)                                done
          (%i6) listarray(g1);
          (%o6)                            [0, f , 0, 0]
                                                r
          (%i7) contragrad(f,g2);
          (%o7)                                done
          (%i8) listarray(g2);
                                         f  r - 2 f  m
                                          r        r
          (%o8)                      [0, -------------, 0, 0]
                                               r

 -- Function: dscalar ()
     computes the tensor d'Alembertian of the scalar function once
     dependencies have been declared upon the function.  For example:

          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(p,r);
          (%o4)                               [p(r)]
          (%i5) factor(dscalar(p));
                                    2
                              p    r  - 2 m p    r + 2 p  r - 2 m p
                               r r           r r        r          r
          (%o5)               --------------------------------------
                                                 2
                                                r

 -- Function: checkdiv ()

     computes the covariant divergence of the mixed second rank tensor
     (whose first index must be covariant) by printing the corresponding
     n components of the vector field (the divergence) where n = ‘dim’.
     If the argument to the function is ‘g’ then the divergence of the
     Einstein tensor will be formed and must be zero.  In addition, the
     divergence (vector) is given the array name ‘div’.

 -- Function: cgeodesic (<dis>)
     A function in the ‘ctensor’ (component tensor) package.
     ‘cgeodesic’ computes the geodesic equations of motion for a given
     metric.  They are stored in the array ‘geod[i]’.  If the argument
     <dis> is ‘true’ then these equations are displayed.

 -- Function: bdvac (<f>)

     generates the covariant components of the vacuum field equations of
     the Brans- Dicke gravitational theory.  The scalar field is
     specified by the argument <f>, which should be a (quoted) function
     name with functional dependencies, e.g., ‘'p(x)’.

     The components of the second rank covariant field tensor are
     represented by the array ‘bd’.

 -- Function: invariant1 ()

     generates the mixed Euler- Lagrange tensor (field equations) for
     the invariant density of R^2.  The field equations are the
     components of an array named ‘inv1’.

 -- Function: invariant2 ()

     *** NOT YET IMPLEMENTED ***

     generates the mixed Euler- Lagrange tensor (field equations) for
     the invariant density of ‘ric[i,j]*uriem[i,j]’.  The field
     equations are the components of an array named ‘inv2’.

 -- Function: bimetric ()

     *** NOT YET IMPLEMENTED ***

     generates the field equations of Rosen's bimetric theory.  The
     field equations are the components of an array named ‘rosen’.

26.2.8 Utility functions
------------------------

 -- Function: diagmatrixp (<M>,<n>)

     Returns ‘true’ if the first <n> rows and <n> columns of <M> form a
     diagonal matrix or (2D) array.

 -- Function: symmetricp (<M>, <n>)

     Returns ‘true’ if <M> is a <n> by <n> symmetric matrix or
     two-dimensional array, otherwise ‘false’.

     If <n> is less than the size of <M>, ‘symmetricp’ considers only
     the <n> by <n> submatrix (respectively, subarray) comprising rows 1
     through <n> and columns 1 through <n>.

 -- Function: ntermst (<f>)
     gives the user a quick picture of the "size" of the doubly
     subscripted tensor (array) <f>.  It prints two element lists where
     the second element corresponds to NTERMS of the components
     specified by the first elements.  In this way, it is possible to
     quickly find the non-zero expressions and attempt simplification.

 -- Function: cdisplay (<ten>)
     displays all the elements of the tensor <ten>, as represented by a
     multidimensional array.  Tensors of rank 0 and 1, as well as other
     types of variables, are displayed as with ‘ldisplay’.  Tensors of
     rank 2 are displayed as 2-dimensional matrices, while tensors of
     higher rank are displayed as a list of 2-dimensional matrices.  For
     instance, the Riemann-tensor of the Schwarzschild metric can be
     viewed as:

          (%i1) load("ctensor");
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) riemann(false);
          (%o4)                                done
          (%i5) cdisplay(riem);
                    [ 0               0                   0           0     ]
                    [                                                       ]
                    [                              2                        ]
                    [      3 m (r - 2 m)   m    2 m                         ]
                    [ 0  - ------------- + -- - ----      0           0     ]
                    [            4          3     4                         ]
                    [           r          r     r                          ]
                    [                                                       ]
          riem    = [                                m (r - 2 m)            ]
              1, 1  [ 0               0              -----------      0     ]
                    [                                     4                 ]
                    [                                    r                  ]
                    [                                                       ]
                    [                                           m (r - 2 m) ]
                    [ 0               0                   0     ----------- ]
                    [                                                4      ]
                    [                                               r       ]

                                          [    2 m (r - 2 m)       ]
                                          [ 0  -------------  0  0 ]
                                          [          4             ]
                                          [         r              ]
                               riem     = [                        ]
                                   1, 2   [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]

                                          [         m (r - 2 m)    ]
                                          [ 0  0  - -----------  0 ]
                                          [              4         ]
                                          [             r          ]
                               riem     = [                        ]
                                   1, 3   [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]

                                          [            m (r - 2 m) ]
                                          [ 0  0  0  - ----------- ]
                                          [                 4      ]
                                          [                r       ]
                               riem     = [                        ]
                                   1, 4   [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]

                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       2 m               ]
                                         [ - ------------  0  0  0 ]
                              riem     = [    2                    ]
                                  2, 1   [   r  (r - 2 m)          ]
                                         [                         ]
                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       0         0  0  0 ]

                       [     2 m                                         ]
                       [ ------------  0        0               0        ]
                       [  2                                              ]
                       [ r  (r - 2 m)                                    ]
                       [                                                 ]
                       [      0        0        0               0        ]
                       [                                                 ]
            riem     = [                         m                       ]
                2, 2   [      0        0  - ------------        0        ]
                       [                     2                           ]
                       [                    r  (r - 2 m)                 ]
                       [                                                 ]
                       [                                         m       ]
                       [      0        0        0         - ------------ ]
                       [                                     2           ]
                       [                                    r  (r - 2 m) ]

                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [            m          ]
                                          [ 0  0  ------------  0 ]
                               riem     = [        2              ]
                                   2, 3   [       r  (r - 2 m)    ]
                                          [                       ]
                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [ 0  0       0        0 ]

                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [               m       ]
                                          [ 0  0  0  ------------ ]
                               riem     = [           2           ]
                                   2, 4   [          r  (r - 2 m) ]
                                          [                       ]
                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [ 0  0  0       0       ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [ m          ]
                                         3, 1   [ -  0  0  0 ]
                                                [ r          ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [    m       ]
                                         3, 2   [ 0  -  0  0 ]
                                                [    r       ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                         [   m                      ]
                                         [ - -   0   0       0      ]
                                         [   r                      ]
                                         [                          ]
                                         [        m                 ]
                                         [  0   - -  0       0      ]
                              riem     = [        r                 ]
                                  3, 3   [                          ]
                                         [  0    0   0       0      ]
                                         [                          ]
                                         [              2 m - r     ]
                                         [  0    0   0  ------- + 1 ]
                                         [                 r        ]

                                              [ 0  0  0    0   ]
                                              [                ]
                                              [ 0  0  0    0   ]
                                              [                ]
                                   riem     = [            2 m ]
                                       3, 4   [ 0  0  0  - --- ]
                                              [             r  ]
                                              [                ]
                                              [ 0  0  0    0   ]

                                          [       0        0  0  0 ]
                                          [                        ]
                                          [       0        0  0  0 ]
                                          [                        ]
                               riem     = [       0        0  0  0 ]
                                   4, 1   [                        ]
                                          [      2                 ]
                                          [ m sin (theta)          ]
                                          [ -------------  0  0  0 ]
                                          [       r                ]

                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                               riem     = [ 0        0        0  0 ]
                                   4, 2   [                        ]
                                          [         2              ]
                                          [    m sin (theta)       ]
                                          [ 0  -------------  0  0 ]
                                          [          r             ]

                                        [ 0  0          0          0 ]
                                        [                            ]
                                        [ 0  0          0          0 ]
                                        [                            ]
                             riem     = [ 0  0          0          0 ]
                                 4, 3   [                            ]
                                        [                2           ]
                                        [         2 m sin (theta)    ]
                                        [ 0  0  - ---------------  0 ]
                                        [                r           ]

                     [        2                                             ]
                     [   m sin (theta)                                      ]
                     [ - -------------         0                0         0 ]
                     [         r                                            ]
                     [                                                      ]
                     [                         2                            ]
                     [                    m sin (theta)                     ]
          riem     = [        0         - -------------         0         0 ]
              4, 4   [                          r                           ]
                     [                                                      ]
                     [                                          2           ]
                     [                                   2 m sin (theta)    ]
                     [        0                0         ---------------  0 ]
                     [                                          r           ]
                     [                                                      ]
                     [        0                0                0         0 ]

          (%o5)                                done


 -- Function: deleten (<L>, <n>)
     Returns a new list consisting of <L> with the <n>'th element
     deleted.

26.2.9 Variables used by ‘ctensor’
----------------------------------

 -- Option variable: dim
     Default value: 4

     An option in the ‘ctensor’ (component tensor) package.  ‘dim’ is
     the dimension of the manifold with the default 4.  The command
     ‘dim: n’ will reset the dimension to any other value ‘n’.

 -- Option variable: diagmetric
     Default value: ‘false’

     An option in the ‘ctensor’ (component tensor) package.  If
     ‘diagmetric’ is ‘true’ special routines compute all geometrical
     objects (which contain the metric tensor explicitly) by taking into
     consideration the diagonality of the metric.  Reduced run times
     will, of course, result.  Note: this option is set automatically by
     ‘csetup’ if a diagonal metric is specified.

 -- Option variable: ctrgsimp

     Causes trigonometric simplifications to be used when tensors are
     computed.  Presently, ‘ctrgsimp’ affects only computations
     involving a moving frame.

 -- Option variable: cframe_flag

     Causes computations to be performed relative to a moving frame as
     opposed to a holonomic metric.  The frame is defined by the inverse
     frame array ‘fri’ and the frame metric ‘lfg’.  For computations
     using a Cartesian frame, ‘lfg’ should be the unit matrix of the
     appropriate dimension; for computations in a Lorentz frame, ‘lfg’
     should have the appropriate signature.

 -- Option variable: ctorsion_flag

     Causes the contortion tensor to be included in the computation of
     the connection coefficients.  The contortion tensor itself is
     computed by ‘contortion’ from the user-supplied tensor ‘tr’.

 -- Option variable: cnonmet_flag

     Causes the nonmetricity coefficients to be included in the
     computation of the connection coefficients.  The nonmetricity
     coefficients are computed from the user-supplied nonmetricity
     vector ‘nm’ by the function ‘nonmetricity’.

 -- Option variable: ctayswitch

     If set to ‘true’, causes some ‘ctensor’ computations to be carried
     out using Taylor-series expansions.  Presently, ‘christof’,
     ‘ricci’, ‘uricci’, ‘einstein’, and ‘weyl’ take into account this
     setting.

 -- Option variable: ctayvar

     Variable used for Taylor-series expansion if ‘ctayswitch’ is set to
     ‘true’.

 -- Option variable: ctaypov

     Maximum power used in Taylor-series expansion when ‘ctayswitch’ is
     set to ‘true’.

 -- Option variable: ctaypt

     Point around which Taylor-series expansion is carried out when
     ‘ctayswitch’ is set to ‘true’.

 -- System variable: gdet

     The determinant of the metric tensor ‘lg’.  Computed by ‘cmetric’
     when ‘cframe_flag’ is set to ‘false’.

 -- Option variable: ratchristof

     Causes rational simplification to be applied by ‘christof’.

 -- Option variable: rateinstein
     Default value: ‘true’

     If ‘true’ rational simplification will be performed on the non-zero
     components of Einstein tensors; if ‘ratfac’ is ‘true’ then the
     components will also be factored.

 -- Option variable: ratriemann
     Default value: ‘true’

     One of the switches which controls simplification of Riemann
     tensors; if ‘true’, then rational simplification will be done; if
     ‘ratfac’ is ‘true’ then each of the components will also be
     factored.

 -- Option variable: ratweyl
     Default value: ‘true’

     If ‘true’, this switch causes the ‘weyl’ function to apply rational
     simplification to the values of the Weyl tensor.  If ‘ratfac’ is
     ‘true’, then the components will also be factored.

 -- Variable: lfg
     The covariant frame metric.  By default, it is initialized to the
     4-dimensional Lorentz frame with signature (+,+,+,-).  Used when
     ‘cframe_flag’ is ‘true’.

 -- Variable: ufg
     The inverse frame metric.  Computed from ‘lfg’ when ‘cmetric’ is
     called while ‘cframe_flag’ is set to ‘true’.

 -- Variable: riem
     The (3,1) Riemann tensor.  Computed when the function ‘riemann’ is
     invoked.  For information about index ordering, see the description
     of ‘riemann’.

     If ‘cframe_flag’ is ‘true’, ‘riem’ is computed from the covariant
     Riemann-tensor ‘lriem’.

 -- Variable: lriem

     The covariant Riemann tensor.  Computed by ‘lriemann’.

 -- Variable: uriem

     The contravariant Riemann tensor.  Computed by ‘uriemann’.

 -- Variable: ric

     The covariant Ricci-tensor.  Computed by ‘ricci’.

 -- Variable: uric

     The mixed-index Ricci-tensor.  Computed by ‘uricci’.

 -- Variable: lg

     The metric tensor.  This tensor must be specified (as a ‘dim’ by
     ‘dim’ matrix) before other computations can be performed.

 -- Variable: ug

     The inverse of the metric tensor.  Computed by ‘cmetric’.

 -- Variable: weyl

     The Weyl tensor.  Computed by ‘weyl’.

 -- Variable: fb

     Frame bracket coefficients, as computed by ‘frame_bracket’.

 -- Variable: kinvariant

     The Kretschmann invariant.  Computed by ‘rinvariant’.

 -- Variable: np

     A Newman-Penrose null tetrad.  Computed by ‘nptetrad’.

 -- Variable: npi

     The raised-index Newman-Penrose null tetrad.  Computed by
     ‘nptetrad’.  Defined as ‘ug.np’.  The product ‘np.transpose(npi)’
     is constant:

          (%i39) trigsimp(np.transpose(npi));
                                        [  0   - 1  0  0 ]
                                        [                ]
                                        [ - 1   0   0  0 ]
          (%o39)                        [                ]
                                        [  0    0   0  1 ]
                                        [                ]
                                        [  0    0   1  0 ]

 -- Variable: tr

     User-supplied rank-3 tensor representing torsion.  Used by
     ‘contortion’.

 -- Variable: kt

     The contortion tensor, computed from ‘tr’ by ‘contortion’.

 -- Variable: nm

     User-supplied nonmetricity vector.  Used by ‘nonmetricity’.

 -- Variable: nmc

     The nonmetricity coefficients, computed from ‘nm’ by
     ‘nonmetricity’.

 -- System variable: tensorkill

     Variable indicating if the tensor package has been initialized.
     Set and used by ‘csetup’, reset by ‘init_ctensor’.

 -- Option variable: ct_coords
     Default value: ‘[]’

     An option in the ‘ctensor’ (component tensor) package.  ‘ct_coords’
     contains a list of coordinates.  While normally defined when the
     function ‘csetup’ is called, one may redefine the coordinates with
     the assignment ‘ct_coords: [j1, j2, ..., jn]’ where the j's are the
     new coordinate names.  See also ‘csetup’.

26.2.10 Reserved names
----------------------

The following names are used internally by the ‘ctensor’ package and
should not be redefined:

       Name         Description
       ---------------------------------------------------------------------
       _lg()        Evaluates to lfg if frame metric used, lg otherwise
       _ug()        Evaluates to ufg if frame metric used, ug otherwise
       cleanup()    Removes items from the deindex list
       contract4()  Used by psi()
       filemet()    Used by csetup() when reading the metric from a file
       findde1()    Used by findde()
       findde2()    Used by findde()
       findde3()    Used by findde()
       kdelt()      Kronecker-delta (not generalized)
       newmet()     Used by csetup() for setting up a metric interactively
       setflags()   Used by init_ctensor()
       readvalue()
       resimp()
       sermet()     Used by csetup() for entering a metric as Taylor-series
       txyzsum()
       tmetric()    Frame metric, used by cmetric() when cframe_flag:true
       triemann()   Riemann-tensor in frame base, used when cframe_flag:true
       tricci()     Ricci-tensor in frame base, used when cframe_flag:true
       trrc()       Ricci rotation coefficients, used by christof()
       yesp()

26.2.11 Changes
---------------

In November, 2004, the ‘ctensor’ package was extensively rewritten.
Many functions and variables have been renamed in order to make the
package compatible with the commercial version of Macsyma.

       New Name     Old Name        Description
       ---------------------------------------------------------------------
       ctaylor()    DLGTAYLOR()     Taylor-series expansion of an expression
       lgeod[]      EM              Geodesic equations
       ein[]        G[]             Mixed Einstein-tensor
       ric[]        LR[]            Mixed Ricci-tensor
       ricci()      LRICCICOM()     Compute the mixed Ricci-tensor
       ctaypov      MINP            Maximum power in Taylor-series expansion
       cgeodesic()  MOTION          Compute geodesic equations
       ct_coords    OMEGA           Metric coordinates
       ctayvar      PARAM           Taylor-series expansion variable
       lriem[]      R[]             Covariant Riemann-tensor
       uriemann()   RAISERIEMANN()  Compute the contravariant Riemann-tensor
       ratriemann   RATRIEMAN       Rational simplif. of the Riemann-tensor
       uric[]       RICCI[]         Contravariant Ricci-tensor
       uricci()     RICCICOM()      Compute the contravariant Ricci-tensor
       cmetric()    SETMETRIC()     Set up the metric
       ctaypt       TAYPT           Point for Taylor-series expansion
       ctayswitch   TAYSWITCH       Taylor-series setting switch
       csetup()     TSETUP()        Start interactive setup session
       ctransform() TTRANSFORM()    Interactive coordinate transformation
       uriem[]      UR[]            Contravariant Riemann-tensor
       weyl[]       W[]             (3,1) Weyl-tensor



File: maxima.info,  Node: Package atensor,  Next: Sums Products and Series,  Prev: Package ctensor,  Up: Top

27 Package atensor
******************

* Menu:

* Introduction to atensor::
* Functions and Variables for atensor::


File: maxima.info,  Node: Introduction to atensor,  Next: Functions and Variables for atensor,  Prev: Package atensor,  Up: Package atensor

27.1 Introduction to atensor
============================

‘atensor’ is an algebraic tensor manipulation package.  To use
‘atensor’, type ‘load("atensor")’, followed by a call to the
‘init_atensor’ function.

   The essence of ‘atensor’ is a set of simplification rules for the
noncommutative (dot) product operator ("‘.’").  ‘atensor’ recognizes
several algebra types; the corresponding simplification rules are put
into effect when the ‘init_atensor’ function is called.

   The capabilities of ‘atensor’ can be demonstrated by defining the
algebra of quaternions as a Clifford-algebra Cl(0,2) with two basis
vectors.  The three quaternionic imaginary units are then the two basis
vectors and their product, i.e.:

         i = v     j = v     k = v  . v
              1         2         1    2

   Although the ‘atensor’ package has a built-in definition for the
quaternion algebra, it is not used in this example, in which we
endeavour to build the quaternion multiplication table as a matrix:

     (%i1) load("atensor");
     (%o1)       /share/tensor/atensor.mac
     (%i2) init_atensor(clifford,0,0,2);
     (%o2)                                done
     (%i3) atensimp(v[1].v[1]);
     (%o3)                                 - 1
     (%i4) atensimp((v[1].v[2]).(v[1].v[2]));
     (%o4)                                 - 1
     (%i5) q:zeromatrix(4,4);
                                     [ 0  0  0  0 ]
                                     [            ]
                                     [ 0  0  0  0 ]
     (%o5)                           [            ]
                                     [ 0  0  0  0 ]
                                     [            ]
                                     [ 0  0  0  0 ]
     (%i6) q[1,1]:1;
     (%o6)                                  1
     (%i7) for i thru adim do q[1,i+1]:q[i+1,1]:v[i];
     (%o7)                                done
     (%i8) q[1,4]:q[4,1]:v[1].v[2];
     (%o8)                               v  . v
                                          1    2
     (%i9) for i from 2 thru 4 do for j from 2 thru 4 do
           q[i,j]:atensimp(q[i,1].q[1,j]);
     (%o9)                                done
     (%i10) q;
                        [    1        v         v      v  . v  ]
                        [              1         2      1    2 ]
                        [                                      ]
                        [   v         - 1     v  . v    - v    ]
                        [    1                 1    2      2   ]
     (%o10)             [                                      ]
                        [   v      - v  . v     - 1      v     ]
                        [    2        1    2              1    ]
                        [                                      ]
                        [ v  . v      v        - v       - 1   ]
                        [  1    2      2          1            ]

   ‘atensor’ recognizes as base vectors indexed symbols, where the
symbol is that stored in ‘asymbol’ and the index runs between 1 and
‘adim’.  For indexed symbols, and indexed symbols only, the bilinear
forms ‘sf’, ‘af’, and ‘av’ are evaluated.  The evaluation substitutes
the value of ‘aform[i,j]’ in place of ‘fun(v[i],v[j])’ where ‘v’
represents the value of ‘asymbol’ and ‘fun’ is either ‘af’ or ‘sf’; or,
it substitutes ‘v[aform[i,j]]’ in place of ‘av(v[i],v[j])’.

   Needless to say, the functions ‘sf’, ‘af’ and ‘av’ can be redefined.

   When the ‘atensor’ package is loaded, the following flags are set:

     dotscrules:true;
     dotdistrib:true;
     dotexptsimp:false;

   If you wish to experiment with a nonassociative algebra, you may also
consider setting ‘dotassoc’ to ‘false’.  In this case, however,
‘atensimp’ will not always be able to obtain the desired
simplifications.


File: maxima.info,  Node: Functions and Variables for atensor,  Prev: Introduction to atensor,  Up: Package atensor

27.2 Functions and Variables for atensor
========================================

 -- Function: init_atensor
          init_atensor (<alg_type>, <opt_dims>)
          init_atensor (<alg_type>)

     Initializes the ‘atensor’ package with the specified algebra type.
     <alg_type> can be one of the following:

     ‘universal’: The universal algebra has no commutation rules.

     ‘grassmann’: The Grassman algebra is defined by the commutation
     relation ‘u.v+v.u=0’.

     ‘clifford’: The Clifford algebra is defined by the commutation
     relation ‘u.v+v.u=-2*sf(u,v)’ where ‘sf’ is a symmetric
     scalar-valued function.  For this algebra, <opt_dims> can be up to
     three nonnegative integers, representing the number of positive,
     degenerate, and negative dimensions of the algebra, respectively.
     If any <opt_dims> values are supplied, ‘atensor’ will configure the
     values of ‘adim’ and ‘aform’ appropriately.  Otherwise, ‘adim’ will
     default to 0 and ‘aform’ will not be defined.

     ‘symmetric’: The symmetric algebra is defined by the commutation
     relation ‘u.v-v.u=0’.

     ‘symplectic’: The symplectic algebra is defined by the commutation
     relation ‘u.v-v.u=2*af(u,v)’ where ‘af’ is an antisymmetric
     scalar-valued function.  For the symplectic algebra, <opt_dims> can
     be up to two nonnegative integers, representing the nondegenerate
     and degenerate dimensions, respectively.  If any <opt_dims> values
     are supplied, ‘atensor’ will configure the values of ‘adim’ and
     ‘aform’ appropriately.  Otherwise, ‘adim’ will default to 0 and
     ‘aform’ will not be defined.

     ‘lie_envelop’: The algebra of the Lie envelope is defined by the
     commutation relation ‘u.v-v.u=2*av(u,v)’ where ‘av’ is an
     antisymmetric function.

     The ‘init_atensor’ function also recognizes several predefined
     algebra types:

     ‘complex’ implements the algebra of complex numbers as the Clifford
     algebra Cl(0,1).  The call ‘init_atensor(complex)’ is equivalent to
     ‘init_atensor(clifford,0,0,1)’.

     ‘quaternion’ implements the algebra of quaternions.  The call
     ‘init_atensor (quaternion)’ is equivalent to ‘init_atensor
     (clifford,0,0,2)’.

     ‘pauli’ implements the algebra of Pauli-spinors as the
     Clifford-algebra Cl(3,0).  A call to ‘init_atensor(pauli)’ is
     equivalent to ‘init_atensor(clifford,3)’.

     ‘dirac’ implements the algebra of Dirac-spinors as the
     Clifford-algebra Cl(3,1).  A call to ‘init_atensor(dirac)’ is
     equivalent to ‘init_atensor(clifford,3,0,1)’.

 -- Function: atensimp (<expr>)

     Simplifies an algebraic tensor expression <expr> according to the
     rules configured by a call to ‘init_atensor’.  Simplification
     includes recursive application of commutation relations and
     resolving calls to ‘sf’, ‘af’, and ‘av’ where applicable.  A
     safeguard is used to ensure that the function always terminates,
     even for complex expressions.

 -- Function: alg_type
     The algebra type.  Valid values are ‘universal’, ‘grassmann’,
     ‘clifford’, ‘symmetric’, ‘symplectic’ and ‘lie_envelop’.

 -- Variable: adim
     Default value: 0

     The dimensionality of the algebra.  ‘atensor’ uses the value of
     ‘adim’ to determine if an indexed object is a valid base vector.
     See ‘abasep’.

 -- Variable: aform
     Default value: ‘ident(3)’

     Default values for the bilinear forms ‘sf’, ‘af’, and ‘av’.  The
     default is the identity matrix ‘ident(3)’.

 -- Variable: asymbol
     Default value: ‘v’

     The symbol for base vectors.

 -- Function: sf (<u>, <v>)

     A symmetric scalar function that is used in commutation relations.
     The default implementation checks if both arguments are base
     vectors using ‘abasep’ and if that is the case, substitutes the
     corresponding value from the matrix ‘aform’.

 -- Function: af (<u>, <v>)

     An antisymmetric scalar function that is used in commutation
     relations.  The default implementation checks if both arguments are
     base vectors using ‘abasep’ and if that is the case, substitutes
     the corresponding value from the matrix ‘aform’.

 -- Function: av (<u>, <v>)

     An antisymmetric function that is used in commutation relations.
     The default implementation checks if both arguments are base
     vectors using ‘abasep’ and if that is the case, substitutes the
     corresponding value from the matrix ‘aform’.

     For instance:

          (%i1) load("atensor");
          (%o1)       /share/tensor/atensor.mac
          (%i2) adim:3;
          (%o2)                                  3
          (%i3) aform:matrix([0,3,-2],[-3,0,1],[2,-1,0]);
                                         [  0    3   - 2 ]
                                         [               ]
          (%o3)                          [ - 3   0    1  ]
                                         [               ]
                                         [  2   - 1   0  ]
          (%i4) asymbol:x;
          (%o4)                                  x
          (%i5) av(x[1],x[2]);
          (%o5)                                 x
                                                 3

 -- Function: abasep (<v>)

     Checks if its argument is an ‘atensor’ base vector.  That is, if it
     is an indexed symbol, with the symbol being the same as the value
     of ‘asymbol’, and the index having a numeric value between 1 and
     ‘adim’.


File: maxima.info,  Node: Sums Products and Series,  Next: Number Theory,  Prev: Package atensor,  Up: Top

28 Sums, Products, and Series
*****************************

* Menu:

* Functions and Variables for Sums and Products::
* Introduction to Series::
* Functions and Variables for Series::
* Introduction to Fourier series::
* Functions and Variables for Fourier series::
* Functions and Variables for Poisson series::


File: maxima.info,  Node: Functions and Variables for Sums and Products,  Next: Introduction to Series,  Prev: Sums Products and Series,  Up: Sums Products and Series

28.1 Functions and Variables for Sums and Products
==================================================

 -- Function: bashindices (<expr>)

     Transforms the expression <expr> by giving each summation and
     product a unique index.  This gives ‘changevar’ greater precision
     when it is working with summations or products.  The form of the
     unique index is ‘j<number>’.  The quantity <number> is determined
     by referring to ‘gensumnum’, which can be changed by the user.  For
     example, ‘gensumnum:0$’ resets it.

 -- Function: lsum (<expr>, <x>, <L>)

     Represents the sum of <expr> for each element <x> in <L>.  A noun
     form ‘'lsum’ is returned if the argument <L> does not evaluate to a
     list.

     Examples:

          (%i1) lsum (x^i, i, [1, 2, 7]);
                                      7    2
          (%o1)                      x  + x  + x
          (%i2) lsum (i^2, i, rootsof (x^3 - 1, x));
                               ====
                               \      2
          (%o2)                 >    i
                               /
                               ====
                                             3
                               i in rootsof(x  - 1, x)

 -- Function: intosum (<expr>)

     Moves multiplicative factors outside a summation to inside.  If the
     index is used in the outside expression, then the function tries to
     find a reasonable index, the same as it does for ‘sumcontract’.
     This is essentially the reverse idea of the ‘outative’ property of
     summations, but note that it does not remove this property, it only
     bypasses it.

     In some cases, a ‘scanmap (multthru, <expr>)’ may be necessary
     before the ‘intosum’.

 -- Option variable: simpproduct
     Default value: ‘false’

     When ‘simpproduct’ is ‘true’, the result of a ‘product’ is
     simplified.  This simplification may sometimes be able to produce a
     closed form.  If ‘simpproduct’ is ‘false’ or if the quoted form
     ‘'product’ is used, the value is a product noun form which is a
     representation of the pi notation used in mathematics.

 -- Function: product (<expr>, <i>, <i_0>, <i_1>)

     Represents a product of the values of <expr> as the index <i>
     varies from <i_0> to <i_1>.  The noun form ‘'product’ is displayed
     as an uppercase letter pi.

     ‘product’ evaluates <expr> and lower and upper limits <i_0> and
     <i_1>, ‘product’ quotes (does not evaluate) the index <i>.

     If the upper and lower limits differ by an integer, <expr> is
     evaluated for each value of the index <i>, and the result is an
     explicit product.

     Otherwise, the range of the index is indefinite.  Some rules are
     applied to simplify the product.  When the global variable
     ‘simpproduct’ is ‘true’, additional rules are applied.  In some
     cases, simplification yields a result which is not a product;
     otherwise, the result is a noun form ‘'product’.

     See also ‘nouns’ and ‘evflag’.

     Examples:

          (%i1) product (x + i*(i+1)/2, i, 1, 4);
          (%o1)           (x + 1) (x + 3) (x + 6) (x + 10)
          (%i2) product (i^2, i, 1, 7);
          (%o2)                       25401600
          (%i3) product (a[i], i, 1, 7);
          (%o3)                 a  a  a  a  a  a  a
                                 1  2  3  4  5  6  7
          (%i4) product (a(i), i, 1, 7);
          (%o4)          a(1) a(2) a(3) a(4) a(5) a(6) a(7)
          (%i5) product (a(i), i, 1, n);
                                       n
                                     /===\
                                      ! !
          (%o5)                       ! !  a(i)
                                      ! !
                                     i = 1
          (%i6) product (k, k, 1, n);
                                         n
                                       /===\
                                        ! !
          (%o6)                         ! !  k
                                        ! !
                                       k = 1
          (%i7) product (k, k, 1, n), simpproduct;
          (%o7)                          n!
          (%i8) product (integrate (x^k, x, 0, 1), k, 1, n);
                                       n
                                     /===\
                                      ! !    1
          (%o8)                       ! !  -----
                                      ! !  k + 1
                                     k = 1
          (%i9) product (if k <= 5 then a^k else b^k, k, 1, 10);
                                        15  40
          (%o9)                        a   b

 -- Option variable: simpsum
     Default value: ‘false’

     When ‘simpsum’ is ‘true’, the result of a ‘sum’ is simplified.
     This simplification may sometimes be able to produce a closed form.
     If ‘simpsum’ is ‘false’ or if the quoted form ‘'sum’ is used, the
     value is a sum noun form which is a representation of the sigma
     notation used in mathematics.

 -- Function: sum (<expr>, <i>, <i_0>, <i_1>)

     Represents a summation of the values of <expr> as the index <i>
     varies from <i_0> to <i_1>.  The noun form ‘'sum’ is displayed as
     an uppercase letter sigma.

     ‘sum’ evaluates its summand <expr> and lower and upper limits <i_0>
     and <i_1>, ‘sum’ quotes (does not evaluate) the index <i>.

     If the upper and lower limits differ by an integer, the summand
     <expr> is evaluated for each value of the summation index <i>, and
     the result is an explicit sum.

     Otherwise, the range of the index is indefinite.  Some rules are
     applied to simplify the summation.  When the global variable
     ‘simpsum’ is ‘true’, additional rules are applied.  In some cases,
     simplification yields a result which is not a summation; otherwise,
     the result is a noun form ‘'sum’.

     When the ‘evflag’ (evaluation flag) ‘cauchysum’ is ‘true’, a
     product of summations is expressed as a Cauchy product, in which
     the index of the inner summation is a function of the index of the
     outer one, rather than varying independently.

     The global variable ‘genindex’ is the alphabetic prefix used to
     generate the next index of summation, when an automatically
     generated index is needed.

     ‘gensumnum’ is the numeric suffix used to generate the next index
     of summation, when an automatically generated index is needed.
     When ‘gensumnum’ is ‘false’, an automatically-generated index is
     only ‘genindex’ with no numeric suffix.

     See also ‘lsum’, ‘sumcontract’, ‘intosum’, ‘bashindices’,
     ‘niceindices’, ‘nouns’, ‘evflag’, and *note Package zeilberger::

     Examples:

          (%i1) sum (i^2, i, 1, 7);
          (%o1)                          140
          (%i2) sum (a[i], i, 1, 7);
          (%o2)           a  + a  + a  + a  + a  + a  + a
                           7    6    5    4    3    2    1
          (%i3) sum (a(i), i, 1, 7);
          (%o3)    a(7) + a(6) + a(5) + a(4) + a(3) + a(2) + a(1)
          (%i4) sum (a(i), i, 1, n);
                                      n
                                     ====
                                     \
          (%o4)                       >    a(i)
                                     /
                                     ====
                                     i = 1
          (%i5) sum (2^i + i^2, i, 0, n);
                                    n
                                   ====
                                   \       i    2
          (%o5)                     >    (2  + i )
                                   /
                                   ====
                                   i = 0
          (%i6) sum (2^i + i^2, i, 0, n), simpsum;
                                        3      2
                             n + 1   2 n  + 3 n  + n
          (%o6)             2      + --------------- - 1
                                            6
          (%i7) sum (1/3^i, i, 1, inf);
                                      inf
                                      ====
                                      \     1
          (%o7)                        >    --
                                      /      i
                                      ====  3
                                      i = 1
          (%i8) sum (1/3^i, i, 1, inf), simpsum;
                                          1
          (%o8)                           -
                                          2
          (%i9) sum (i^2, i, 1, 4) * sum (1/i^2, i, 1, inf);
                                        inf
                                        ====
                                        \     1
          (%o9)                      30  >    --
                                        /      2
                                        ====  i
                                        i = 1
          (%i10) sum (i^2, i, 1, 4) * sum (1/i^2, i, 1, inf), simpsum;
                                            2
          (%o10)                       5 %pi
          (%i11) sum (integrate (x^k, x, 0, 1), k, 1, n);
                                      n
                                     ====
                                     \       1
          (%o11)                      >    -----
                                     /     k + 1
                                     ====
                                     k = 1
          (%i12) sum (if k <= 5 then a^k else b^k, k, 1, 10);
                    10    9    8    7    6    5    4    3    2
          (%o12)   b   + b  + b  + b  + b  + a  + a  + a  + a  + a

 -- Function: sumcontract (<expr>)

     Combines all sums of an addition that have upper and lower bounds
     that differ by constants.  The result is an expression containing
     one summation for each set of such summations added to all
     appropriate extra terms that had to be extracted to form this sum.
     ‘sumcontract’ combines all compatible sums and uses one of the
     indices from one of the sums if it can, and then try to form a
     reasonable index if it cannot use any supplied.

     It may be necessary to do an ‘intosum (<expr>)’ before the
     ‘sumcontract’.

 -- Option variable: sumexpand
     Default value: ‘false’

     When ‘sumexpand’ is ‘true’, products of sums and exponentiated sums
     simplify to nested sums.

     See also ‘cauchysum’.

     Examples:

          (%i1) sumexpand: true$
          (%i2) sum (f (i), i, 0, m) * sum (g (j), j, 0, n);
                               m      n
                              ====   ====
                              \      \
          (%o2)                >      >     f(i1) g(i2)
                              /      /
                              ====   ====
                              i1 = 0 i2 = 0
          (%i3) sum (f (i), i, 0, m)^2;
                               m      m
                              ====   ====
                              \      \
          (%o3)                >      >     f(i3) f(i4)
                              /      /
                              ====   ====
                              i3 = 0 i4 = 0


File: maxima.info,  Node: Introduction to Series,  Next: Functions and Variables for Series,  Prev: Functions and Variables for Sums and Products,  Up: Sums Products and Series

28.2 Introduction to Series
===========================

Maxima contains functions ‘taylor’ and ‘powerseries’ for finding the
series of differentiable functions.  It also has tools such as ‘nusum’
capable of finding the closed form of some series.  Operations such as
addition and multiplication work as usual on series.  This section
presents the global variables which control the expansion.


File: maxima.info,  Node: Functions and Variables for Series,  Next: Introduction to Fourier series,  Prev: Introduction to Series,  Up: Sums Products and Series

28.3 Functions and Variables for Series
=======================================

 -- Option variable: cauchysum
     Default value: ‘false’

     When multiplying together sums with ‘inf’ as their upper limit, if
     ‘sumexpand’ is ‘true’ and ‘cauchysum’ is ‘true’ then the Cauchy
     product will be used rather than the usual product.  In the Cauchy
     product the index of the inner summation is a function of the index
     of the outer one rather than varying independently.

     Example:

          (%i1) sumexpand: false$
          (%i2) cauchysum: false$
          (%i3) s: sum (f(i), i, 0, inf) * sum (g(j), j, 0, inf);
                                inf         inf
                                ====        ====
                                \           \
          (%o3)                ( >    f(i))  >    g(j)
                                /           /
                                ====        ====
                                i = 0       j = 0
          (%i4) sumexpand: true$
          (%i5) cauchysum: true$
          (%i6) expand(s,0,0);
                           inf     i1
                           ====   ====
                           \      \
          (%o6)             >      >     g(i1 - i2) f(i2)
                           /      /
                           ====   ====
                           i1 = 0 i2 = 0

 -- Function: deftaylor (<f_1>(<x_1>), <expr_1>, ..., <f_n>(<x_n>),
          <expr_n>)

     For each function <f_i> of one variable <x_i>, ‘deftaylor’ defines
     <expr_i> as the Taylor series about zero.  <expr_i> is typically a
     polynomial in <x_i> or a summation; more general expressions are
     accepted by ‘deftaylor’ without complaint.

     ‘powerseries (<f_i>(<x_i>), <x_i>, 0)’ returns the series defined
     by ‘deftaylor’.

     ‘deftaylor’ returns a list of the functions <f_1>, ..., <f_n>.
     ‘deftaylor’ evaluates its arguments.

     Example:

          (%i1) deftaylor (f(x), x^2 + sum(x^i/(2^i*i!^2), i, 4, inf));
          (%o1)                          [f]
          (%i2) powerseries (f(x), x, 0);
                                inf
                                ====      i1
                                \        x         2
          (%o2)                  >     -------- + x
                                /       i1    2
                                ====   2   i1!
                                i1 = 4
          (%i3) taylor (exp (sqrt (f(x))), x, 0, 4);
                                2         3          4
                               x    3073 x    12817 x
          (%o3)/T/     1 + x + -- + ------- + -------- + . . .
                               2     18432     307200

 -- Option variable: maxtayorder
     Default value: ‘true’

     When ‘maxtayorder’ is ‘true’, then during algebraic manipulation of
     (truncated) Taylor series, ‘taylor’ tries to retain as many terms
     as are known to be correct.

 -- Function: niceindices (<expr>)

     Renames the indices of sums and products in <expr>.  ‘niceindices’
     attempts to rename each index to the value of ‘niceindicespref[1]’,
     unless that name appears in the summand or multiplicand, in which
     case ‘niceindices’ tries the succeeding elements of
     ‘niceindicespref’ in turn, until an unused variable is found.  If
     the entire list is exhausted, additional indices are constructed by
     appending integers to the value of ‘niceindicespref[1]’, e.g.,
     ‘i0’, ‘i1’, ‘i2’, ...

     ‘niceindices’ returns an expression.  ‘niceindices’ evaluates its
     argument.

     Example:

          (%i1) niceindicespref;
          (%o1)                  [i, j, k, l, m, n]
          (%i2) product (sum (f (foo + i*j*bar), foo, 1, inf), bar, 1, inf);
                           inf    inf
                          /===\   ====
                           ! !    \
          (%o2)            ! !     >      f(bar i j + foo)
                           ! !    /
                          bar = 1 ====
                                  foo = 1
          (%i3) niceindices (%);
                               inf  inf
                              /===\ ====
                               ! !  \
          (%o3)                ! !   >    f(i j l + k)
                               ! !  /
                              l = 1 ====
                                    k = 1

 -- Option variable: niceindicespref
     Default value: ‘[i, j, k, l, m, n]’

     ‘niceindicespref’ is the list from which ‘niceindices’ takes the
     names of indices for sums and products.

     The elements of ‘niceindicespref’ are must be names of simple
     variables.

     Example:

          (%i1) niceindicespref: [p, q, r, s, t, u]$
          (%i2) product (sum (f (foo + i*j*bar), foo, 1, inf), bar, 1, inf);
                           inf    inf
                          /===\   ====
                           ! !    \
          (%o2)            ! !     >      f(bar i j + foo)
                           ! !    /
                          bar = 1 ====
                                  foo = 1
          (%i3) niceindices (%);
                               inf  inf
                              /===\ ====
                               ! !  \
          (%o3)                ! !   >    f(i j q + p)
                               ! !  /
                              q = 1 ====
                                    p = 1

 -- Function: nusum (<expr>, <x>, <i_0>, <i_1>)

     Carries out indefinite hypergeometric summation of <expr> with
     respect to <x> using a decision procedure due to R.W. Gosper.
     <expr> and the result must be expressible as products of integer
     powers, factorials, binomials, and rational functions.

     The terms "definite" and "indefinite summation" are used
     analogously to "definite" and "indefinite integration".  To sum
     indefinitely means to give a symbolic result for the sum over
     intervals of variable length, not just e.g.  0 to inf.  Thus, since
     there is no formula for the general partial sum of the binomial
     series, ‘nusum’ can't do it.

     ‘nusum’ and ‘unsum’ know a little about sums and differences of
     finite products.  See also ‘unsum’.

     Examples:

          (%i1) nusum (n*n!, n, 0, n);

          Dependent equations eliminated:  (1)
          (%o1)                     (n + 1)! - 1
          (%i2) nusum (n^4*4^n/binomial(2*n,n), n, 0, n);
                               4        3       2              n
                2 (n + 1) (63 n  + 112 n  + 18 n  - 22 n + 3) 4      2
          (%o2) ------------------------------------------------ - ------
                              693 binomial(2 n, n)                 3 11 7
          (%i3) unsum (%, n);
                                        4  n
                                       n  4
          (%o3)                   ----------------
                                  binomial(2 n, n)
          (%i4) unsum (prod (i^2, i, 1, n), n);
                              n - 1
                              /===\
                               ! !   2
          (%o4)              ( ! !  i ) (n - 1) (n + 1)
                               ! !
                              i = 1
          (%i5) nusum (%, n, 1, n);

          Dependent equations eliminated:  (2 3)
                                      n
                                    /===\
                                     ! !   2
          (%o5)                      ! !  i  - 1
                                     ! !
                                    i = 1

 -- Function: pade (<taylor_series>, <numer_deg_bound>,
          <denom_deg_bound>)

     Returns a list of all rational functions which have the given
     Taylor series expansion where the sum of the degrees of the
     numerator and the denominator is less than or equal to the
     truncation level of the power series, i.e.  are "best"
     approximants, and which additionally satisfy the specified degree
     bounds.

     <taylor_series> is an univariate Taylor series.  <numer_deg_bound>
     and <denom_deg_bound> are positive integers specifying degree
     bounds on the numerator and denominator.

     <taylor_series> can also be a Laurent series, and the degree bounds
     can be ‘inf’ which causes all rational functions whose total degree
     is less than or equal to the length of the power series to be
     returned.  Total degree is defined as ‘<numer_deg_bound> +
     <denom_deg_bound>’.  Length of a power series is defined as
     ‘"truncation level" + 1 - min(0, "order of series")’.

          (%i1) taylor (1 + x + x^2 + x^3, x, 0, 3);
                                        2    3
          (%o1)/T/             1 + x + x  + x  + . . .
          (%i2) pade (%, 1, 1);
                                           1
          (%o2)                       [- -----]
                                         x - 1
          (%i3) t: taylor(-(83787*x^10 - 45552*x^9 - 187296*x^8
                             + 387072*x^7 + 86016*x^6 - 1507328*x^5
                             + 1966080*x^4 + 4194304*x^3 - 25165824*x^2
                             + 67108864*x - 134217728)
                 /134217728, x, 0, 10);
                              2    3       4       5       6        7
                       x   3 x    x    15 x    23 x    21 x    189 x
          (%o3)/T/ 1 - - + ---- - -- - ----- + ----- - ----- - ------
                       2    16    32   1024    2048    32768   65536

                                            8         9          10
                                      5853 x    2847 x    83787 x
                                    + ------- + ------- - --------- + . . .
                                      4194304   8388608   134217728
          (%i4) pade (t, 4, 4);
          (%o4)                          []

     There is no rational function of degree 4 numerator/denominator,
     with this power series expansion.  You must in general have degree
     of the numerator and degree of the denominator adding up to at
     least the degree of the power series, in order to have enough
     unknown coefficients to solve.

          (%i5) pade (t, 5, 5);
                               5                4                 3
          (%o5) [- (520256329 x  - 96719020632 x  - 489651410240 x

                            2
           - 1619100813312 x  - 2176885157888 x - 2386516803584)

                         5                 4                  3
          /(47041365435 x  + 381702613848 x  + 1360678489152 x

                            2
           + 2856700692480 x  + 3370143559680 x + 2386516803584)]

 -- Function: powerseries (<expr>, <x>, <a>)

     Returns the general form of the power series expansion for <expr>
     in the variable <x> about the point <a> (which may be ‘inf’ for
     infinity):
                     inf
                     ====
                     \               n
                      >    b  (x - a)
                     /      n
                     ====
                     n = 0

     If ‘powerseries’ is unable to expand <expr>, ‘taylor’ may give the
     first several terms of the series.

     When ‘verbose’ is ‘true’, ‘powerseries’ prints progress messages.

          (%i1) verbose: true$
          (%i2) powerseries (log(sin(x)/x), x, 0);
          can't expand
                                           log(sin(x))
          so we'll try again after applying the rule:
                                                  d
                                                / -- (sin(x))
                                                [ dx
                                  log(sin(x)) = i ----------- dx
                                                ]   sin(x)
                                                /
          in the first simplification we have returned:
                                       /
                                       [
                                       i cot(x) dx - log(x)
                                       ]
                                       /
                              inf
                              ====        i1  2 i1             2 i1
                              \      (- 1)   2     bern(2 i1) x
                               >     ------------------------------
                              /                i1 (2 i1)!
                              ====
                              i1 = 1
          (%o2)                -------------------------------------
                                                2

 -- Option variable: psexpand
     Default value: ‘false’

     When ‘psexpand’ is ‘true’, an extended rational function expression
     is displayed fully expanded.  The switch ‘ratexpand’ has the same
     effect.

     When ‘psexpand’ is ‘false’, a multivariate expression is displayed
     just as in the rational function package.

     When ‘psexpand’ is ‘multi’, then terms with the same total degree
     in the variables are grouped together.

 -- Function: revert (<expr>, <x>)
 -- Function: revert2 (<expr>, <x>, <n>)

     These functions return the reversion of <expr>, a Taylor series
     about zero in the variable <x>.  ‘revert’ returns a polynomial of
     degree equal to the highest power in <expr>.  ‘revert2’ returns a
     polynomial of degree <n>, which may be greater than, equal to, or
     less than the degree of <expr>.

     ‘load ("revert")’ loads these functions.

     Examples:

          (%i1) load ("revert")$
          (%i2) t: taylor (exp(x) - 1, x, 0, 6);
                             2    3    4    5     6
                            x    x    x    x     x
          (%o2)/T/      x + -- + -- + -- + --- + --- + . . .
                            2    6    24   120   720
          (%i3) revert (t, x);
                         6       5       4       3       2
                     10 x  - 12 x  + 15 x  - 20 x  + 30 x  - 60 x
          (%o3)/R/ - --------------------------------------------
                                          60
          (%i4) ratexpand (%);
                               6    5    4    3    2
                              x    x    x    x    x
          (%o4)             - -- + -- - -- + -- - -- + x
                              6    5    4    3    2
          (%i5) taylor (log(x+1), x, 0, 6);
                              2    3    4    5    6
                             x    x    x    x    x
          (%o5)/T/       x - -- + -- - -- + -- - -- + . . .
                             2    3    4    5    6
          (%i6) ratsimp (revert (t, x) - taylor (log(x+1), x, 0, 6));
          (%o6)                           0
          (%i7) revert2 (t, x, 4);
                                    4    3    2
                                   x    x    x
          (%o7)                  - -- + -- - -- + x
                                   4    3    2

 -- Function: taylor
          taylor (<expr>, <x>, <a>, <n>)
          taylor (<expr>, [<x_1>, <x_2>, ...], <a>, <n>)
          taylor (<expr>, [<x>, <a>, <n>, 'asymp])
          taylor (<expr>, [<x_1>, <x_2>, ...], [<a_1>, <a_2>, ...],
          [<n_1>, <n_2>, ...])
          taylor (<expr>, [<x_1>, <a_1>, <n_1>], [<x_2>, <a_2>, <n_2>],
          ...)

     ‘taylor (<expr>, <x>, <a>, <n>)’ expands the expression <expr> in a
     truncated Taylor or Laurent series in the variable <x> around the
     point <a>, containing terms through ‘(<x> - <a>)^<n>’.

     If <expr> is of the form ‘<f>(<x>)/<g>(<x>)’ and ‘<g>(<x>)’ has no
     terms up to degree <n> then ‘taylor’ attempts to expand ‘<g>(<x>)’
     up to degree ‘2 <n>’.  If there are still no nonzero terms,
     ‘taylor’ doubles the degree of the expansion of ‘<g>(<x>)’ so long
     as the degree of the expansion is less than or equal to ‘<n>
     2^taylordepth’.

     ‘taylor (<expr>, [<x_1>, <x_2>, ...], <a>, <n>)’ returns a
     truncated power series of degree <n> in all variables <x_1>, <x_2>,
     ... about the point ‘(<a>, <a>, ...)’.

     ‘taylor (<expr>, [<x_1>, <a_1>, <n_1>], [<x_2>, <a_2>, <n_2>],
     ...)’ returns a truncated power series in the variables <x_1>,
     <x_2>, ... about the point ‘(<a_1>, <a_2>, ...)’, truncated at
     <n_1>, <n_2>, ...

     ‘taylor (<expr>, [<x_1>, <x_2>, ...], [<a_1>, <a_2>, ...], [<n_1>,
     <n_2>, ...])’ returns a truncated power series in the variables
     <x_1>, <x_2>, ... about the point ‘(<a_1>, <a_2>, ...)’, truncated
     at <n_1>, <n_2>, ...

     ‘taylor (<expr>, [<x>, <a>, <n>, 'asymp])’ returns an expansion of
     <expr> in negative powers of ‘<x> - <a>’.  The highest order term
     is ‘(<x> - <a>)^<-n>’.

     When ‘maxtayorder’ is ‘true’, then during algebraic manipulation of
     (truncated) Taylor series, ‘taylor’ tries to retain as many terms
     as are known to be correct.

     When ‘psexpand’ is ‘true’, an extended rational function expression
     is displayed fully expanded.  The switch ‘ratexpand’ has the same
     effect.  When ‘psexpand’ is ‘false’, a multivariate expression is
     displayed just as in the rational function package.  When
     ‘psexpand’ is ‘multi’, then terms with the same total degree in the
     variables are grouped together.

     See also the ‘taylor_logexpand’ switch for controlling expansion.

     Examples:

          (%i1) taylor (sqrt (sin(x) + a*x + 1), x, 0, 3);
                                     2             2
                       (a + 1) x   (a  + 2 a + 1) x
          (%o1)/T/ 1 + --------- - -----------------
                           2               8

                                             3      2             3
                                         (3 a  + 9 a  + 9 a - 1) x
                                       + -------------------------- + . . .
                                                     48
          (%i2) %^2;
                                              3
                                             x
          (%o2)/T/           1 + (a + 1) x - -- + . . .
                                             6
          (%i3) taylor (sqrt (x + 1), x, 0, 5);
                                 2    3      4      5
                            x   x    x    5 x    7 x
          (%o3)/T/      1 + - - -- + -- - ---- + ---- + . . .
                            2   8    16   128    256
          (%i4) %^2;
          (%o4)/T/                  1 + x + . . .
          (%i5) product ((1 + x^i)^2.5, i, 1, inf)/(1 + x^2);
                                   inf
                                  /===\
                                   ! !    i     2.5
                                   ! !  (x  + 1)
                                   ! !
                                  i = 1
          (%o5)                   -----------------
                                        2
                                       x  + 1
          (%i6) ev (taylor(%, x,  0, 3), keepfloat);
                                         2           3
          (%o6)/T/    1 + 2.5 x + 3.375 x  + 6.5625 x  + . . .
          (%i7) taylor (1/log (x + 1), x, 0, 3);
                                         2       3
                           1   1   x    x    19 x
          (%o7)/T/         - + - - -- + -- - ----- + . . .
                           x   2   12   24    720
          (%i8) taylor (cos(x) - sec(x), x, 0, 5);
                                          4
                                     2   x
          (%o8)/T/                - x  - -- + . . .
                                         6
          (%i9) taylor ((cos(x) - sec(x))^3, x, 0, 5);
          (%o9)/T/                    0 + . . .
          (%i10) taylor (1/(cos(x) - sec(x))^3, x, 0, 5);
                                                         2          4
                      1     1       11      347    6767 x    15377 x
          (%o10)/T/ - -- + ---- + ------ - ----- - ------- - --------
                       6      4        2   15120   604800    7983360
                      x    2 x    120 x

                                                                    + . . .
          (%i11) taylor (sqrt (1 - k^2*sin(x)^2), x, 0, 6);
                         2  2       4      2   4
                        k  x    (3 k  - 4 k ) x
          (%o11)/T/ 1 - ----- - ----------------
                          2            24

                                              6       4       2   6
                                         (45 k  - 60 k  + 16 k ) x
                                       - -------------------------- + . . .
                                                    720
          (%i12) taylor ((x + 1)^n, x, 0, 4);
                                2       2     3      2         3
                              (n  - n) x    (n  - 3 n  + 2 n) x
          (%o12)/T/ 1 + n x + ----------- + --------------------
                                   2                 6

                                         4      3       2         4
                                       (n  - 6 n  + 11 n  - 6 n) x
                                     + ---------------------------- + . . .
                                                    24
          (%i13) taylor (sin (y + x), x, 0, 3, y, 0, 3);
                         3                 2
                        y                 y
          (%o13)/T/ y - -- + . . . + (1 - -- + . . .) x
                        6                 2

                              3                       2
                         y   y            2      1   y            3
                    + (- - + -- + . . .) x  + (- - + -- + . . .) x  + . . .
                         2   12                  6   12
          (%i14) taylor (sin (y + x), [x, y], 0, 3);
                               3        2      2      3
                              x  + 3 y x  + 3 y  x + y
          (%o14)/T/   y + x - ------------------------- + . . .
                                          6
          (%i15) taylor (1/sin (y + x), x, 0, 3, y, 0, 3);
                    1   y              1    1               1            2
          (%o15)/T/ - + - + . . . + (- -- + - + . . .) x + (-- + . . .) x
                    y   6               2   6                3
                                       y                    y

                                                     1            3
                                                + (- -- + . . .) x  + . . .
                                                      4
                                                     y
          (%i16) taylor (1/sin (y + x), [x, y], 0, 3);
                                       3         2       2        3
                      1     x + y   7 x  + 21 y x  + 21 y  x + 7 y
          (%o16)/T/ ----- + ----- + ------------------------------- + . . .
                    x + y     6                   360

 -- Option variable: taylordepth
     Default value: 3

     If there are still no nonzero terms, ‘taylor’ doubles the degree of
     the expansion of ‘<g>(<x>)’ so long as the degree of the expansion
     is less than or equal to ‘<n> 2^taylordepth’.

 -- Function: taylorinfo (<expr>)

     Returns information about the Taylor series <expr>.  The return
     value is a list of lists.  Each list comprises the name of a
     variable, the point of expansion, and the degree of the expansion.

     ‘taylorinfo’ returns ‘false’ if <expr> is not a Taylor series.

     Example:

          (%i1) taylor ((1 - y^2)/(1 - x), x, 0, 3, [y, a, inf]);
                            2                       2
          (%o1)/T/ - (y - a)  - 2 a (y - a) + (1 - a )

                   2                        2
           + (1 - a  - 2 a (y - a) - (y - a) ) x

                   2                        2   2
           + (1 - a  - 2 a (y - a) - (y - a) ) x

                   2                        2   3
           + (1 - a  - 2 a (y - a) - (y - a) ) x  + . . .
          (%i2) taylorinfo(%);
          (%o2)               [[y, a, inf], [x, 0, 3]]

 -- Function: taylorp (<expr>)

     Returns ‘true’ if <expr> is a Taylor series, and ‘false’ otherwise.

 -- Option variable: taylor_logexpand
     Default value: ‘true’

     ‘taylor_logexpand’ controls expansions of logarithms in ‘taylor’
     series.

     When ‘taylor_logexpand’ is ‘true’, all logarithms are expanded
     fully so that zero-recognition problems involving logarithmic
     identities do not disturb the expansion process.  However, this
     scheme is not always mathematically correct since it ignores branch
     information.

     When ‘taylor_logexpand’ is set to ‘false’, then the only expansion
     of logarithms that occur is that necessary to obtain a formal power
     series.

 -- Option variable: taylor_order_coefficients
     Default value: ‘true’

     ‘taylor_order_coefficients’ controls the ordering of coefficients
     in a Taylor series.

     When ‘taylor_order_coefficients’ is ‘true’, coefficients of taylor
     series are ordered canonically.

 -- Function: taylor_simplifier (<expr>)

     Simplifies coefficients of the power series <expr>.  ‘taylor’ calls
     this function.

 -- Option variable: taylor_truncate_polynomials
     Default value: ‘true’

     When ‘taylor_truncate_polynomials’ is ‘true’, polynomials are
     truncated based upon the input truncation levels.

     Otherwise, polynomials input to ‘taylor’ are considered to have
     infinite precision.

 -- Function: taytorat (<expr>)

     Converts <expr> from ‘taylor’ form to canonical rational expression
     (CRE) form.  The effect is the same as ‘rat (ratdisrep (<expr>))’,
     but faster.

 -- Function: trunc (<expr>)

     Annotates the internal representation of the general expression
     <expr> so that it is displayed as if its sums were truncated Taylor
     series.  <expr> is not otherwise modified.

     Example:

          (%i1) expr: x^2 + x + 1;
                                      2
          (%o1)                      x  + x + 1
          (%i2) trunc (expr);
                                          2
          (%o2)                  1 + x + x  + . . .
          (%i3) is (expr = trunc (expr));
          (%o3)                         true

 -- Function: unsum (<f>, <n>)

     Returns the first backward difference ‘<f>(<n>) - <f>(<n> - 1)’.
     Thus ‘unsum’ in a sense is the inverse of ‘sum’.

     See also ‘nusum’.

     Examples:

          (%i1) g(p) := p*4^n/binomial(2*n,n);
                                               n
                                            p 4
          (%o1)               g(p) := ----------------
                                      binomial(2 n, n)
          (%i2) g(n^4);
                                        4  n
                                       n  4
          (%o2)                   ----------------
                                  binomial(2 n, n)
          (%i3) nusum (%, n, 0, n);
                               4        3       2              n
                2 (n + 1) (63 n  + 112 n  + 18 n  - 22 n + 3) 4      2
          (%o3) ------------------------------------------------ - ------
                              693 binomial(2 n, n)                 3 11 7
          (%i4) unsum (%, n);
                                        4  n
                                       n  4
          (%o4)                   ----------------
                                  binomial(2 n, n)

 -- Option variable: verbose
     Default value: ‘false’

     When ‘verbose’ is ‘true’, ‘powerseries’ prints progress messages.


File: maxima.info,  Node: Introduction to Fourier series,  Next: Functions and Variables for Fourier series,  Prev: Functions and Variables for Series,  Up: Sums Products and Series

28.4 Introduction to Fourier series
===================================

The ‘fourie’ package comprises functions for the symbolic computation of
Fourier series.  There are functions in the ‘fourie’ package to
calculate Fourier integral coefficients and some functions for
manipulation of expressions.


File: maxima.info,  Node: Functions and Variables for Fourier series,  Next: Functions and Variables for Poisson series,  Prev: Introduction to Fourier series,  Up: Sums Products and Series

28.5 Functions and Variables for Fourier series
===============================================

 -- Function: equalp (<x>, <y>)

     Returns ‘true’ if ‘equal (<x>, <y>)’ otherwise ‘false’ (doesn't
     give an error message like ‘equal (x, y)’ would do in this case).

 -- Function: remfun
          remfun (<f>, <expr>)
          remfun (<f>, <expr>, <x>)

     ‘remfun (<f>, <expr>)’ replaces all occurrences of ‘<f> (<arg>)’ by
     <arg> in <expr>.

     ‘remfun (<f>, <expr>, <x>)’ replaces all occurrences of ‘<f>
     (<arg>)’ by <arg> in <expr> only if <arg> contains the variable
     <x>.

 -- Function: funp
          funp (<f>, <expr>)
          funp (<f>, <expr>, <x>)

     ‘funp (<f>, <expr>)’ returns ‘true’ if <expr> contains the function
     <f>.

     ‘funp (<f>, <expr>, <x>)’ returns ‘true’ if <expr> contains the
     function <f> and the variable <x> is somewhere in the argument of
     one of the instances of <f>.

 -- Function: absint
          absint (<f>, <x>, <halfplane>)
          absint (<f>, <x>)
          absint (<f>, <x>, <a>, <b>)

     ‘absint (<f>, <x>, <halfplane>)’ returns the indefinite integral of
     <f> with respect to <x> in the given halfplane (‘pos’, ‘neg’, or
     ‘both’).  <f> may contain expressions of the form ‘abs (x)’, ‘abs
     (sin (x))’, ‘abs (a) * exp (-abs (b) * abs (x))’.

     ‘absint (<f>, <x>)’ is equivalent to ‘absint (<f>, <x>, pos)’.

     ‘absint (<f>, <x>, <a>, <b>)’ returns the definite integral of <f>
     with respect to <x> from <a> to <b>.  <f> may include absolute
     values.

 -- Function: fourier (<f>, <x>, <p>)

     Returns a list of the Fourier coefficients of ‘<f>(<x>)’ defined on
     the interval ‘[-p, p]’.

 -- Function: foursimp (<l>)

     Simplifies ‘sin (n %pi)’ to 0 if ‘sinnpiflag’ is ‘true’ and ‘cos (n
     %pi)’ to ‘(-1)^n’ if ‘cosnpiflag’ is ‘true’.

 -- Option variable: sinnpiflag
     Default value: ‘true’

     See ‘foursimp’.

 -- Option variable: cosnpiflag
     Default value: ‘true’

     See ‘foursimp’.

 -- Function: fourexpand (<l>, <x>, <p>, <limit>)

     Constructs and returns the Fourier series from the list of Fourier
     coefficients <l> up through <limit> terms (<limit> may be ‘inf’).
     <x> and <p> have same meaning as in ‘fourier’.

 -- Function: fourcos (<f>, <x>, <p>)

     Returns the Fourier cosine coefficients for ‘<f>(<x>)’ defined on
     ‘[0, <p>]’.

 -- Function: foursin (<f>, <x>, <p>)

     Returns the Fourier sine coefficients for ‘<f>(<x>)’ defined on
     ‘[0, <p>]’.

 -- Function: totalfourier (<f>, <x>, <p>)

     Returns ‘fourexpand (foursimp (fourier (<f>, <x>, <p>)), <x>, <p>,
     'inf)’.

 -- Function: fourint (<f>, <x>)

     Constructs and returns a list of the Fourier integral coefficients
     of ‘<f>(<x>)’ defined on ‘[minf, inf]’.

 -- Function: fourintcos (<f>, <x>)

     Returns the Fourier cosine integral coefficients for ‘<f>(<x>)’ on
     ‘[0, inf]’.

 -- Function: fourintsin (<f>, <x>)

     Returns the Fourier sine integral coefficients for ‘<f>(<x>)’ on
     ‘[0, inf]’.


File: maxima.info,  Node: Functions and Variables for Poisson series,  Prev: Functions and Variables for Fourier series,  Up: Sums Products and Series

28.6 Functions and Variables for Poisson series
===============================================

 -- Function: intopois (<a>)
     Converts <a> into a Poisson encoding.

 -- Function: outofpois (<a>)

     Converts <a> from Poisson encoding to general representation.  If
     <a> is not in Poisson form, ‘outofpois’ carries out the conversion,
     i.e., the return value is ‘outofpois (intopois (<a>))’.  This
     function is thus a canonical simplifier for sums of powers of sine
     and cosine terms of a particular type.

 -- Function: poisdiff (<a>, <b>)

     Differentiates <a> with respect to <b>.  <b> must occur only in the
     trig arguments or only in the coefficients.

 -- Function: poisexpt (<a>, <b>)

     Functionally identical to ‘intopois (<a>^<b>)’.  <b> must be a
     positive integer.

 -- Function: poisint (<a>, <b>)

     Integrates in a similarly restricted sense (to ‘poisdiff’).
     Non-periodic terms in <b> are dropped if <b> is in the trig
     arguments.

 -- Option variable: poislim
     Default value: 5

     ‘poislim’ determines the domain of the coefficients in the
     arguments of the trig functions.  The initial value of 5
     corresponds to the interval [-2^(5-1)+1,2^(5-1)], or [-15,16], but
     it can be set to [-2^(n-1)+1, 2^(n-1)].

 -- Function: poismap (<series>, <sinfn>, <cosfn>)

     will map the functions <sinfn> on the sine terms and <cosfn> on the
     cosine terms of the Poisson series given.  <sinfn> and <cosfn> are
     functions of two arguments which are a coefficient and a
     trigonometric part of a term in series respectively.

 -- Function: poisplus (<a>, <b>)

     Is functionally identical to ‘intopois (a + b)’.

 -- Function: poissimp (<a>)

     Converts <a> into a Poisson series for <a> in general
     representation.

 -- Special symbol: poisson

     The symbol ‘/P/’ follows the line label of Poisson series
     expressions.

 -- Function: poissubst (<a>, <b>, <c>)

     Substitutes <a> for <b> in <c>.  <c> is a Poisson series.

     (1) Where <B> is a variable <u>, <v>, <w>, <x>, <y>, or <z>, then
     <a> must be an expression linear in those variables (e.g., ‘6*u +
     4*v’).

     (2) Where <b> is other than those variables, then <a> must also be
     free of those variables, and furthermore, free of sines or cosines.

     ‘poissubst (<a>, <b>, <c>, <d>, <n>)’ is a special type of
     substitution which operates on <a> and <b> as in type (1) above,
     but where <d> is a Poisson series, expands ‘cos(<d>)’ and
     ‘sin(<d>)’ to order <n> so as to provide the result of substituting
     ‘<a> + <d>’ for <b> in <c>.  The idea is that <d> is an expansion
     in terms of a small parameter.  For example, ‘poissubst (u, v,
     cos(v), %e, 3)’ yields ‘cos(u)*(1 - %e^2/2) - sin(u)*(%e -
     %e^3/6)’.

 -- Function: poistimes (<a>, <b>)

     Is functionally identical to ‘intopois (<a>*<b>)’.

 -- Function: poistrim ()

     is a reserved function name which (if the user has defined it) gets
     applied during Poisson multiplication.  It is a predicate function
     of 6 arguments which are the coefficients of the <u>, <v>, ..., <z>
     in a term.  Terms for which ‘poistrim’ is ‘true’ (for the
     coefficients of that term) are eliminated during multiplication.

 -- Function: printpois (<a>)

     Prints a Poisson series in a readable format.  In common with
     ‘outofpois’, it will convert <a> into a Poisson encoding first, if
     necessary.


File: maxima.info,  Node: Number Theory,  Next: Package sym,  Prev: Sums Products and Series,  Up: Top

29 Number Theory
****************

* Menu:

* Functions and Variables for Number Theory::


File: maxima.info,  Node: Functions and Variables for Number Theory,  Prev: Number Theory,  Up: Number Theory

29.1 Functions and Variables for Number Theory
==============================================

 -- Function: bern (<n>)

     Returns the <n>'th Bernoulli number for integer <n>.  Bernoulli
     numbers equal to zero are suppressed if ‘zerobern’ is ‘false’.

     See also ‘burn’.

          (%i1) zerobern: true$
          (%i2) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                                1  1       1      1        1
          (%o2)           [1, - -, -, 0, - --, 0, --, 0, - --]
                                2  6       30     42       30
          (%i3) zerobern: false$
          (%i4) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                                1  1    1   1     1   5     691   7
          (%o4)           [1, - -, -, - --, --, - --, --, - ----, -]
                                2  6    30  42    30  66    2730  6

 -- Function: bernpoly (<x>, <n>)

     Returns the <n>'th Bernoulli polynomial in the variable <x>.

 -- Function: bfzeta (<s>, <n>)

     Returns the Riemann zeta function for the argument <s>.  The return
     value is a big float (bfloat); <n> is the number of digits in the
     return value.

 -- Function: bfhzeta (<s>, <h>, <n>)

     Returns the Hurwitz zeta function for the arguments <s> and <h>.
     The return value is a big float (bfloat); <n> is the number of
     digits in the return value.

     The Hurwitz zeta function is defined as

                                  inf
                                  ====
                                  \        1
                   zeta (s,h)  =   >    --------
                                  /            s
                                  ====  (k + h)
                                  k = 0

     ‘load ("bffac")’ loads this function.

 -- Function: burn (<n>)

     Returns a rational number, which is an approximation of the <n>'th
     Bernoulli number for integer <n>.  ‘burn’ exploits the observation
     that (rational) Bernoulli numbers can be approximated by
     (transcendental) zetas with tolerable efficiency:

                             n - 1  1 - 2 n
                        (- 1)      2        zeta(2 n) (2 n)!
               B(2 n) = ------------------------------------
                                          2 n
                                       %pi

     ‘burn’ may be more efficient than ‘bern’ for large, isolated <n> as
     ‘bern’ computes all the Bernoulli numbers up to index <n> before
     returning.  ‘burn’ invokes the approximation for even integers ‘n >
     255’.  For odd integers and ‘n <= 255’ the function ‘bern’ is
     called.

     ‘load ("bffac")’ loads this function.  See also ‘bern’.

 -- Function: solve_congruences ([<r_1>, ..., <r_n>], [<m_1>, ...,
          <m_n>])

     Solves the system of congruences ‘x = r_1 mod m_1’, ..., ‘x = r_n
     mod m_n’.  The remainders <r_n> may be arbitrary integers while the
     moduli <m_n> have to be positive and pairwise coprime integers.

          (%i1) mods : [1000, 1001, 1003, 1007];
          (%o1)                   [1000, 1001, 1003, 1007]
          (%i2) lreduce('gcd, mods);
          (%o2)                               1
          (%i3) x : random(apply("*", mods));
          (%o3)                         685124877004
          (%i4) rems : map(lambda([z], mod(x, z)), mods);
          (%o4)                       [4, 568, 54, 624]
          (%i5) solve_congruences(rems, mods);
          (%o5)                         685124877004
          (%i6) solve_congruences([1, 2], [3, n]);
          (%o6)               solve_congruences([1, 2], [3, n])
          (%i7) %, n = 4;
          (%o7)                              10

 -- Function: cf (<expr>)

     Computes a continued fraction approximation.  <expr> is an
     expression comprising continued fractions, square roots of
     integers, and literal real numbers (integers, rational numbers,
     ordinary floats, and bigfloats).  ‘cf’ computes exact expansions
     for rational numbers, but expansions are truncated at ‘ratepsilon’
     for ordinary floats and ‘10^(-fpprec)’ for bigfloats.

     Operands in the expression may be combined with arithmetic
     operators.  Maxima does not know about operations on continued
     fractions outside of ‘cf’.

     ‘cf’ evaluates its arguments after binding ‘listarith’ to ‘false’.
     ‘cf’ returns a continued fraction, represented as a list.

     A continued fraction ‘a + 1/(b + 1/(c + ...))’ is represented by
     the list ‘[a, b, c, ...]’.  The list elements ‘a’, ‘b’, ‘c’, ...
     must evaluate to integers.  <expr> may also contain ‘sqrt (n)’
     where ‘n’ is an integer.  In this case ‘cf’ will give as many terms
     of the continued fraction as the value of the variable ‘cflength’
     times the period.

     A continued fraction can be evaluated to a number by evaluating the
     arithmetic representation returned by ‘cfdisrep’.  See also
     ‘cfexpand’ for another way to evaluate a continued fraction.

     See also ‘cfdisrep’, ‘cfexpand’, and ‘cflength’.

     Examples:

        • <expr> is an expression comprising continued fractions and
          square roots of integers.

               (%i1) cf ([5, 3, 1]*[11, 9, 7] + [3, 7]/[4, 3, 2]);
               (%o1)               [59, 17, 2, 1, 1, 1, 27]
               (%i2) cf ((3/17)*[1, -2, 5]/sqrt(11) + (8/13));
               (%o2)        [0, 1, 1, 1, 3, 2, 1, 4, 1, 9, 1, 9, 2]

        • ‘cflength’ controls how many periods of the continued fraction
          are computed for algebraic, irrational numbers.

               (%i1) cflength: 1$
               (%i2) cf ((1 + sqrt(5))/2);
               (%o2)                    [1, 1, 1, 1, 2]
               (%i3) cflength: 2$
               (%i4) cf ((1 + sqrt(5))/2);
               (%o4)               [1, 1, 1, 1, 1, 1, 1, 2]
               (%i5) cflength: 3$
               (%i6) cf ((1 + sqrt(5))/2);
               (%o6)           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]

        • A continued fraction can be evaluated by evaluating the
          arithmetic representation returned by ‘cfdisrep’.

               (%i1) cflength: 3$
               (%i2) cfdisrep (cf (sqrt (3)))$
               (%i3) ev (%, numer);
               (%o3)                   1.731707317073171

        • Maxima does not know about operations on continued fractions
          outside of ‘cf’.

               (%i1) cf ([1,1,1,1,1,2] * 3);
               (%o1)                     [4, 1, 5, 2]
               (%i2) cf ([1,1,1,1,1,2]) * 3;
               (%o2)                  [3, 3, 3, 3, 3, 6]

 -- Function: cfdisrep (<list>)

     Constructs and returns an ordinary arithmetic expression of the
     form ‘a + 1/(b + 1/(c + ...))’ from the list representation of a
     continued fraction ‘[a, b, c, ...]’.

          (%i1) cf ([1, 2, -3] + [1, -2, 1]);
          (%o1)                     [1, 1, 1, 2]
          (%i2) cfdisrep (%);
                                            1
          (%o2)                     1 + ---------
                                              1
                                        1 + -----
                                                1
                                            1 + -
                                                2

 -- Function: cfexpand (<x>)

     Returns a matrix of the numerators and denominators of the last
     (column 1) and next-to-last (column 2) convergents of the continued
     fraction <x>.

          (%i1) cf (rat (ev (%pi, numer)));

          `rat' replaced 3.141592653589793 by 103993/33102 =3.141592653011902
          (%o1)                  [3, 7, 15, 1, 292]
          (%i2) cfexpand (%);
                                   [ 103993  355 ]
          (%o2)                    [             ]
                                   [ 33102   113 ]
          (%i3) %[1,1]/%[2,1], numer;
          (%o3)                   3.141592653011902

 -- Option variable: cflength
     Default value: 1

     ‘cflength’ controls the number of terms of the continued fraction
     the function ‘cf’ will give, as the value ‘cflength’ times the
     period.  Thus the default is to give one period.

          (%i1) cflength: 1$
          (%i2) cf ((1 + sqrt(5))/2);
          (%o2)                    [1, 1, 1, 1, 2]
          (%i3) cflength: 2$
          (%i4) cf ((1 + sqrt(5))/2);
          (%o4)               [1, 1, 1, 1, 1, 1, 1, 2]
          (%i5) cflength: 3$
          (%i6) cf ((1 + sqrt(5))/2);
          (%o6)           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]

 -- Function: divsum
          divsum (<n>, <k>)
          divsum (<n>)

     ‘divsum (<n>, <k>)’ returns the sum of the divisors of <n> raised
     to the <k>'th power.

     ‘divsum (<n>)’ returns the sum of the divisors of <n>.

          (%i1) divsum (12);
          (%o1)                          28
          (%i2) 1 + 2 + 3 + 4 + 6 + 12;
          (%o2)                          28
          (%i3) divsum (12, 2);
          (%o3)                          210
          (%i4) 1^2 + 2^2 + 3^2 + 4^2 + 6^2 + 12^2;
          (%o4)                          210

 -- Function: euler (<n>)

     Returns the <n>'th Euler number for nonnegative integer <n>.  Euler
     numbers equal to zero are suppressed if ‘zerobern’ is ‘false’.

     For the Euler-Mascheroni constant, see ‘%gamma’.

          (%i1) zerobern: true$
          (%i2) map (euler, [0, 1, 2, 3, 4, 5, 6]);
          (%o2)               [1, 0, - 1, 0, 5, 0, - 61]
          (%i3) zerobern: false$
          (%i4) map (euler, [0, 1, 2, 3, 4, 5, 6]);
          (%o4)               [1, - 1, 5, - 61, 1385, - 50521, 2702765]

 -- Option variable: factors_only
     Default value: ‘false’

     Controls the value returned by ‘ifactors’.  The default ‘false’
     causes ‘ifactors’ to provide information about multiplicities of
     the computed prime factors.  If ‘factors_only’ is set to ‘true’,
     ‘ifactors’ returns nothing more than a list of prime factors.

     Example: See ‘ifactors’.

 -- Function: fib (<n>)

     Returns the <n>'th Fibonacci number.  ‘fib(0)’ is equal to 0 and
     ‘fib(1)’ equal to 1, and ‘fib (-<n>)’ equal to ‘(-1)^(<n> + 1) *
     fib(<n>)’.

          (%i1) map (fib, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o1)           [- 3, 2, - 1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21]

 -- Function: fibtophi (<expr>)

     Expresses Fibonacci numbers in <expr> in terms of the constant
     ‘%phi’, which is ‘(1 + sqrt(5))/2’, approximately 1.61803399.

     Examples:

          (%i1) fibtophi (fib (n));
                                     n             n
                                 %phi  - (1 - %phi)
          (%o1)                  -------------------
                                     2 %phi - 1
          (%i2) fib (n-1) + fib (n) - fib (n+1);
          (%o2)          - fib(n + 1) + fib(n) + fib(n - 1)
          (%i3) fibtophi (%);
                      n + 1             n + 1       n             n
                  %phi      - (1 - %phi)        %phi  - (1 - %phi)
          (%o3) - --------------------------- + -------------------
                          2 %phi - 1                2 %phi - 1
                                                    n - 1             n - 1
                                                %phi      - (1 - %phi)
                                              + ---------------------------
                                                        2 %phi - 1
          (%i4) ratsimp (%);
          (%o4)                           0

 -- Function: ifactors (<n>)

     For a positive integer <n> returns the factorization of <n>.  If
     ‘n=p1^e1..pk^nk’ is the decomposition of <n> into prime factors,
     ifactors returns ‘[[p1, e1], ... , [pk, ek]]’.

     Factorization methods used are trial divisions by primes up to
     9973, Pollard's rho and p-1 method and elliptic curves.

     If the variable ‘ifactor_verbose’ is set to ‘true’ ifactor produces
     detailed output about what it is doing including immediate feedback
     as soon as a factor has been found.

     The value returned by ‘ifactors’ is controlled by the option
     variable ‘factors_only’.  The default ‘false’ causes ‘ifactors’ to
     provide information about the multiplicities of the computed prime
     factors.  If ‘factors_only’ is set to ‘true’, ‘ifactors’ simply
     returns the list of prime factors.

          (%i1) ifactors(51575319651600);
          (%o1)     [[2, 4], [3, 2], [5, 2], [1583, 1], [9050207, 1]]
          (%i2) apply("*", map(lambda([u], u[1]^u[2]), %));
          (%o2)                        51575319651600
          (%i3) ifactors(51575319651600), factors_only : true;
          (%o3)                   [2, 3, 5, 1583, 9050207]

 -- Function: igcdex (<n>, <k>)

     Returns a list ‘[<a>, <b>, <u>]’ where <u> is the greatest common
     divisor of <n> and <k>, and <u> is equal to ‘<a> <n> + <b> <k>’.
     The arguments <n> and <k> must be integers.

     ‘igcdex’ implements the Euclidean algorithm.  See also ‘gcdex’.

     The command ‘load("gcdex")’ loads the function.

     Examples:

          (%i1) load("gcdex")$

          (%i2) igcdex(30,18);
          (%o2)                      [- 1, 2, 6]
          (%i3) igcdex(1526757668, 7835626735736);
          (%o3)            [845922341123, - 164826435, 4]
          (%i4) igcdex(fib(20), fib(21));
          (%o4)                   [4181, - 2584, 1]

 -- Function: inrt (<x>, <n>)

     Returns the integer <n>'th root of the absolute value of <x>.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], inrt (10^a, 3)), l);
          (%o2) [2, 4, 10, 21, 46, 100, 215, 464, 1000, 2154, 4641, 10000]

 -- Function: inv_mod (<n>, <m>)

     Computes the inverse of <n> modulo <m>.  ‘inv_mod (n,m)’ returns
     ‘false’, if <n> is a zero divisor modulo <m>.

          (%i1) inv_mod(3, 41);
          (%o1)                           14
          (%i2) ratsimp(3^-1), modulus = 41;
          (%o2)                           14
          (%i3) inv_mod(3, 42);
          (%o3)                          false

 -- Function: isqrt (<x>)

     Returns the "integer square root" of the absolute value of <x>,
     which is an integer.

 -- Function: jacobi (<p>, <q>)

     Returns the Jacobi symbol of <p> and <q>.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], jacobi (a, 9)), l);
          (%o2)         [1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0]

 -- Function: lcm (<expr_1>, ..., <expr_n>)

     Returns the least common multiple of its arguments.  The arguments
     may be general expressions as well as integers.

     ‘load ("functs")’ loads this function.

 -- Function: lucas (<n>)

     Returns the <n>'th Lucas number.  ‘lucas(0)’ is equal to 2 and
     ‘lucas(1)’ equal to 1, and in general, ‘lucas(<n>) = lucas(<n>-1) +
     lucas(<n>-2)’.  Also ‘lucas(-<n>)’ is equal to ‘(-1)^(-<n>) *
     lucas(<n>)’.

          (%i1) map (lucas, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o1)    [7, - 4, 3, - 1, 2, 1, 3, 4, 7, 11, 18, 29, 47]

 -- Function: mod (<x>, <y>)

     If <x> and <y> are real numbers and <y> is nonzero, return ‘<x> -
     <y> * floor(<x> / <y>)’.  Further for all real <x>, we have ‘mod
     (<x>, 0) = <x>’.  For a discussion of the definition ‘mod (<x>, 0)
     = <x>’, see Section 3.4, of "Concrete Mathematics," by Graham,
     Knuth, and Patashnik.  The function ‘mod (<x>, 1)’ is a sawtooth
     function with period 1 with ‘mod (1, 1) = 0’ and ‘mod (0, 1) = 0’.

     To find the principal argument (a number in the interval ‘(-%pi,
     %pi]’) of a complex number, use the function ‘<x> |-> %pi - mod
     (%pi - <x>, 2*%pi)’, where <x> is an argument.

     When <x> and <y> are constant expressions (‘10 * %pi’, for
     example), ‘mod’ uses the same big float evaluation scheme that
     ‘floor’ and ‘ceiling’ uses.  Again, it's possible, although
     unlikely, that ‘mod’ could return an erroneous value in such cases.

     For nonnumerical arguments <x> or <y>, ‘mod’ knows several
     simplification rules:

          (%i1) mod (x, 0);
          (%o1)                           x
          (%i2) mod (a*x, a*y);
          (%o2)                      a mod(x, y)
          (%i3) mod (0, x);
          (%o3)                           0

 -- Function: next_prime (<n>)

     Returns the smallest prime bigger than <n>.

          (%i1) next_prime(27);
          (%o1)                       29

 -- Function: partfrac (<expr>, <var>)

     Expands the expression <expr> in partial fractions with respect to
     the main variable <var>.  ‘partfrac’ does a complete partial
     fraction decomposition.  The algorithm employed is based on the
     fact that the denominators of the partial fraction expansion (the
     factors of the original denominator) are relatively prime.  The
     numerators can be written as linear combinations of denominators,
     and the expansion falls out.

     ‘partfrac’ ignores the value ‘true’ of the option variable
     ‘keepfloat’.

          (%i1) 1/(1+x)^2 - 2/(1+x) + 2/(2+x);
                                2       2        1
          (%o1)               ----- - ----- + --------
                              x + 2   x + 1          2
                                              (x + 1)
          (%i2) ratsimp (%);
                                           x
          (%o2)                 - -------------------
                                   3      2
                                  x  + 4 x  + 5 x + 2
          (%i3) partfrac (%, x);
                                2       2        1
          (%o3)               ----- - ----- + --------
                              x + 2   x + 1          2
                                              (x + 1)

 -- Function: power_mod (<a>, <n>, <m>)

     Uses a modular algorithm to compute ‘a^n mod m’ where <a> and <n>
     are integers and <m> is a positive integer.  If <n> is negative,
     ‘inv_mod’ is used to find the modular inverse.

          (%i1) power_mod(3, 15, 5);
          (%o1)                          2
          (%i2) mod(3^15,5);
          (%o2)                          2
          (%i3) power_mod(2, -1, 5);
          (%o3)                          3
          (%i4) inv_mod(2,5);
          (%o4)                          3

 -- Function: primep (<n>)

     Primality test.  If ‘primep (<n>)’ returns ‘false’, <n> is a
     composite number and if it returns ‘true’, <n> is a prime number
     with very high probability.

     For <n> less than 3317044064679887385961981 a deterministic version
     of Miller-Rabin's test is used.  If ‘primep (<n>)’ returns ‘true’,
     then <n> is a prime number.

     For <n> bigger than 3317044064679887385961981 ‘primep’ uses
     ‘primep_number_of_tests’ Miller-Rabin's pseudo-primality tests and
     one Lucas pseudo-primality test.  The probability that a non-prime
     <n> will pass one Miller-Rabin test is less than 1/4.  Using the
     default value 25 for ‘primep_number_of_tests’, the probability of
     <n> being composite is much smaller that 10^-15.

 -- Option variable: primep_number_of_tests
     Default value: 25

     Number of Miller-Rabin's tests used in ‘primep’.

 -- Function: primes (<start>, <end>)

     Returns the list of all primes from <start> to <end>.

          (%i1) primes(3, 7);
          (%o1)                     [3, 5, 7]

 -- Function: prev_prime (<n>)

     Returns the greatest prime smaller than <n>.

          (%i1) prev_prime(27);
          (%o1)                       23

 -- Function: qunit (<n>)

     Returns the principal unit of the real quadratic number field ‘sqrt
     (<n>)’ where <n> is an integer, i.e., the element whose norm is
     unity.  This amounts to solving Pell's equation ‘a^2 - <n> b^2 =
     1’.

          (%i1) qunit (17);
          (%o1)                     sqrt(17) + 4
          (%i2) expand (% * (sqrt(17) - 4));
          (%o2)                           1

 -- Function: totient (<n>)

     Returns the number of integers less than or equal to <n> which are
     relatively prime to <n>.

 -- Option variable: zerobern
     Default value: ‘true’

     When ‘zerobern’ is ‘false’, ‘bern’ excludes the Bernoulli numbers
     and ‘euler’ excludes the Euler numbers which are equal to zero.
     See ‘bern’ and ‘euler’.

 -- Function: zeta (<n>)

     Returns the Riemann zeta function.  If <n> is a negative integer,
     0, or a positive even integer, the Riemann zeta function simplifies
     to an exact value.  For a positive even integer the option variable
     ‘zeta%pi’ has to be ‘true’ in addition (See ‘zeta%pi’).  For a
     floating point or bigfloat number the Riemann zeta function is
     evaluated numerically.  Maxima returns a noun form ‘zeta (<n>)’ for
     all other arguments, including rational noninteger, and complex
     arguments, or for even integers, if ‘zeta%pi’ has the value
     ‘false’.

     ‘zeta(1)’ is undefined, but Maxima knows the limit ‘limit(zeta(x),
     x, 1)’ from above and below.

     The Riemann zeta function distributes over lists, matrices, and
     equations.

     See also ‘bfzeta’ and ‘zeta%pi’.

     Examples:

          (%i1) zeta([-2, -1, 0, 0.5, 2, 3, 1+%i]);
                                                       2
                      1     1                       %pi
          (%o1) [0, - --, - -, - 1.460354508809586, ----, zeta(3),
                      12    2                        6
                                                              zeta(%i + 1)]
          (%i2) limit(zeta(x),x,1,plus);
          (%o2)                          inf
          (%i3) limit(zeta(x),x,1,minus);
          (%o3)                         minf

 -- Option variable: zeta%pi
     Default value: ‘true’

     When ‘zeta%pi’ is ‘true’, ‘zeta’ returns an expression proportional
     to ‘%pi^n’ for even integer ‘n’.  Otherwise, ‘zeta’ returns a noun
     form ‘zeta (n)’ for even integer ‘n’.

     Examples:

          (%i1) zeta%pi: true$
          (%i2) zeta (4);
                                           4
                                        %pi
          (%o2)                         ----
                                         90
          (%i3) zeta%pi: false$
          (%i4) zeta (4);
          (%o4)                        zeta(4)

 -- Function: zn_add_table (<n>)

     Shows an addition table of all elements in (Z/<n>Z).

     See also ‘zn_mult_table’, ‘zn_power_table’.

 -- Function: zn_characteristic_factors (<n>)

     Returns a list containing the characteristic factors of the totient
     of <n>.

     Using the characteristic factors a multiplication group modulo <n>
     can be expressed as a group direct product of cyclic subgroups.

     In case the group itself is cyclic the list only contains the
     totient and using ‘zn_primroot’ a generator can be computed.  If
     the totient splits into more than one characteristic factors
     ‘zn_factor_generators’ finds generators of the corresponding
     subgroups.

     Each of the ‘r’ factors in the list divides the right following
     factors.  For the last factor ‘f_r’ therefore holds ‘a^f_r = 1 (mod
     n)’ for all ‘a’ coprime to <n>.  This factor is also known as
     Carmichael function or Carmichael lambda.

     If ‘n > 2’, then ‘totient(n)/2^r’ is the number of quadratic
     residues, and each of these has ‘2^r’ square roots.

     See also ‘totient’, ‘zn_primroot’, ‘zn_factor_generators’.

     Examples:

     The multiplication group modulo ‘14’ is cyclic and its ‘6’ elements
     can be generated by a primitive root.

          (%i1) [zn_characteristic_factors(14), phi: totient(14)];
          (%o1)                              [[6], 6]
          (%i2) [zn_factor_generators(14), g: zn_primroot(14)];
          (%o2)                              [[3], 3]
          (%i3) M14: makelist(power_mod(g,i,14), i,0,phi-1);
          (%o3)                         [1, 3, 9, 13, 11, 5]

     The multiplication group modulo ‘15’ is not cyclic and its ‘8’
     elements can be generated by two factor generators.

          (%i1) [[f1,f2]: zn_characteristic_factors(15), totient(15)];
          (%o1)                             [[2, 4], 8]
          (%i2) [[g1,g2]: zn_factor_generators(15), zn_primroot(15)];
          (%o2)                           [[11, 7], false]
          (%i3) UG1: makelist(power_mod(g1,i,15), i,0,f1-1);
          (%o3)                               [1, 11]
          (%i4) UG2: makelist(power_mod(g2,i,15), i,0,f2-1);
          (%o4)                            [1, 7, 4, 13]
          (%i5) M15: create_list(mod(i*j,15), i,UG1, j,UG2);
          (%o5)                      [1, 7, 4, 13, 11, 2, 14, 8]

     For the last characteristic factor ‘4’ it holds that ‘a^4 = 1 (mod
     15)’ for all ‘a’ in ‘M15’.

     ‘M15’ has two characteristic factors and therefore ‘8/2^2’
     quadratic residues, and each of these has ‘2^2’ square roots.

          (%i6) zn_power_table(15);
                                         [ 1   1  1   1 ]
                                         [              ]
                                         [ 2   4  8   1 ]
                                         [              ]
                                         [ 4   1  4   1 ]
                                         [              ]
                                         [ 7   4  13  1 ]
          (%o6)                          [              ]
                                         [ 8   4  2   1 ]
                                         [              ]
                                         [ 11  1  11  1 ]
                                         [              ]
                                         [ 13  4  7   1 ]
                                         [              ]
                                         [ 14  1  14  1 ]
          (%i7) map(lambda([i], zn_nth_root(i,2,15)), [1,4]);
          (%o7)                   [[1, 4, 11, 14], [2, 7, 8, 13]]

 -- Function: zn_carmichael_lambda (<n>)

     Returns ‘1’ if <n> is ‘1’ and otherwise the greatest characteristic
     factor of the totient of <n>.

     For remarks and examples see ‘zn_characteristic_factors’.

 -- Function: zn_determinant (<matrix>, <p>)

     Uses the technique of LU-decomposition to compute the determinant
     of <matrix> over (Z/<p>Z). <p> must be a prime.

     However if the determinant is equal to zero the LU-decomposition
     might fail.  In that case ‘zn_determinant’ computes the determinant
     non-modular and reduces thereafter.

     See also ‘zn_invert_by_lu’.

     Examples:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) m : matrix([2,4,1],[3,1,4],[4,3,2]);
                                         [ 2  4  1 ]
                                         [         ]
          (%o3)                          [ 3  1  4 ]
                                         [         ]
                                         [ 4  3  2 ]
          (%i4) zn_determinant(m, 5);
          (%o4)                               0

 -- Function: zn_factor_generators (<n>)

     Returns a list containing factor generators corresponding to the
     characteristic factors of the totient of <n>.

     For remarks and examples see ‘zn_characteristic_factors’.

 -- Function: zn_invert_by_lu (<matrix>, <p>)

     Uses the technique of LU-decomposition to compute the modular
     inverse of <matrix> over (Z/<p>Z). <p> must be a prime and <matrix>
     invertible.  ‘zn_invert_by_lu’ returns ‘false’ if <matrix> is not
     invertible.

     See also ‘zn_determinant’.

     Example:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) mi : zn_invert_by_lu(m, 5);
                                          [ 3  4 ]
          (%o3)                           [      ]
                                          [ 1  2 ]
          (%i4) matrixmap(lambda([a], mod(a, 5)), m . mi);
                                          [ 1  0 ]
          (%o4)                           [      ]
                                          [ 0  1 ]

 -- Function: zn_log
          zn_log (<a>, <g>, <n>)
          zn_log (<a>, <g>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Computes the discrete logarithm.  Let (Z/<n>Z)* be a cyclic group,
     <g> a primitive root modulo <n> or a generator of a subgroup of
     (Z/<n>Z)* and let <a> be a member of this group.  ‘zn_log (a, g,
     n)’ then solves the congruence ‘g^x = a mod n’.  Please note that
     if <a> is not a power of <g> modulo <n>, ‘zn_log’ will not
     terminate.

     The applied algorithm needs a prime factorization of ‘zn_order(g)’
     resp.  ‘totient(n)’ in case <g> is a primitive root modulo <n>.  A
     precomputed list of factors of ‘zn_order(g)’ might be used as the
     optional fourth argument.  This list must be of the same form as
     the list returned by ‘ifactors(zn_order(g))’ using the default
     option ‘factors_only : false’.  However, compared to the running
     time of the logarithm algorithm providing the list of factors has
     only a quite small effect.

     The algorithm uses a Pohlig-Hellman-reduction and Pollard's
     Rho-method for discrete logarithms.  The running time of ‘zn_log’
     primarily depends on the bitlength of the greatest prime factor of
     ‘zn_order(g)’.

     See also ‘zn_primroot’, ‘zn_order’, ‘ifactors’, ‘totient’.

     Examples:

     ‘zn_log (a, g, n)’ solves the congruence ‘g^x = a mod n’.

          (%i1) n : 22$
          (%i2) g : zn_primroot(n);
          (%o2)                               7
          (%i3) ord_7 : zn_order(7, n);
          (%o3)                              10
          (%i4) powers_7 : makelist(power_mod(g, x, n), x, 0, ord_7 - 1);
          (%o4)              [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i5) zn_log(9, g, n);
          (%o5)                               8
          (%i6) map(lambda([x], zn_log(x, g, n)), powers_7);
          (%o6)                [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
          (%i7) ord_5 : zn_order(5, n);
          (%o7)                               5
          (%i8) powers_5 : makelist(power_mod(5,x,n), x, 0, ord_5 - 1);
          (%o8)                       [1, 5, 3, 15, 9]
          (%i9) zn_log(9, 5, n);
          (%o9)                               4

     The optional fourth argument must be of the same form as the list
     returned by ‘ifactors(zn_order(g))’.  The running time primarily
     depends on the bitlength of the totient's greatest prime factor.

          (%i1) (p : 2^127-1, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors(p - 1)$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                              43
          (%i4) a : power_mod(g, 4711, p)$
          (%i5) zn_log(a, g, p, ifs);
          (%o5)                             4711
          (%i6) f_max : last(ifs);
          (%o6)                       [77158673929, 1]
          (%i7) ord_5 : zn_order(5,p,ifs)$
          (%i8) (p - 1)/ord_5;
          (%o8)                              73
          (%i9) ifs_5 : ifactors(ord_5)$
          (%i10) a : power_mod(5, 4711, p)$
          (%i11) zn_log(a, 5, p, ifs_5);
          (%o11)                            4711

 -- Function: zn_mult_table
          zn_mult_table (<n>)
          zn_mult_table (<n>, <gcd>)

     Without the optional argument <gcd> ‘zn_mult_table(n)’ shows a
     multiplication table of all elements in (Z/<n>Z)* which are all
     elements coprime to <n>.

     The optional second argument <gcd> allows to select a specific
     subset of (Z/<n>Z). If <gcd> is an integer, a multiplication table
     of all residues ‘x’ with ‘gcd(x,n) = ’<gcd> are returned.
     Additionally row and column headings are added for better
     readability.  If necessary, these can be easily removed by
     ‘submatrix(1, table, 1)’.

     If <gcd> is set to ‘all’, the table is printed for all non-zero
     elements in (Z/<n>Z).

     The second example shows an alternative way to create a
     multiplication table for subgroups.

     See also ‘zn_add_table’, ‘zn_power_table’.

     Examples:

     The default table shows all elements in (Z/<n>Z)* and allows to
     demonstrate and study basic properties of modular multiplication
     groups.  E.g.  the principal diagonal contains all quadratic
     residues, each row and column contains every element, the tables
     are symmetric, etc..

     If <gcd> is set to ‘all’, the table is printed for all non-zero
     elements in (Z/<n>Z).

          (%i1) zn_mult_table(8);
                                          [ 1  3  5  7 ]
                                          [            ]
                                          [ 3  1  7  5 ]
          (%o1)                           [            ]
                                          [ 5  7  1  3 ]
                                          [            ]
                                          [ 7  5  3  1 ]
          (%i2) zn_mult_table(8, all);
                                      [ 1  2  3  4  5  6  7 ]
                                      [                     ]
                                      [ 2  4  6  0  2  4  6 ]
                                      [                     ]
                                      [ 3  6  1  4  7  2  5 ]
                                      [                     ]
          (%o2)                       [ 4  0  4  0  4  0  4 ]
                                      [                     ]
                                      [ 5  2  7  4  1  6  3 ]
                                      [                     ]
                                      [ 6  4  2  0  6  4  2 ]
                                      [                     ]
                                      [ 7  6  5  4  3  2  1 ]

     If <gcd> is an integer, row and column headings are added for
     better readability.

     If the subset chosen by <gcd> is a group there is another way to
     create a multiplication table.  An isomorphic mapping from a group
     with ‘1’ as identity builds a table which is easy to read.  The
     mapping is accomplished via CRT.

     In the second version of ‘T36_4’ the identity, here ‘28’, is placed
     in the top left corner, just like in table ‘T9’.

          (%i1) T36_4: zn_mult_table(36,4);
                                  [ *   4   8   16  20  28  32 ]
                                  [                            ]
                                  [ 4   16  32  28  8   4   20 ]
                                  [                            ]
                                  [ 8   32  28  20  16  8   4  ]
                                  [                            ]
          (%o1)                   [ 16  28  20  4   32  16  8  ]
                                  [                            ]
                                  [ 20  8   16  32  4   20  28 ]
                                  [                            ]
                                  [ 28  4   8   16  20  28  32 ]
                                  [                            ]
                                  [ 32  20  4   8   28  32  16 ]
          (%i2) T9: zn_mult_table(36/4);
                                       [ 1  2  4  5  7  8 ]
                                       [                  ]
                                       [ 2  4  8  1  5  7 ]
                                       [                  ]
                                       [ 4  8  7  2  1  5 ]
          (%o2)                        [                  ]
                                       [ 5  1  2  7  8  4 ]
                                       [                  ]
                                       [ 7  5  1  8  4  2 ]
                                       [                  ]
                                       [ 8  7  5  4  2  1 ]
          (%i3) T36_4: matrixmap(lambda([x], solve_congruences([0,x],[4,9])), T9);
                                    [ 28  20  4   32  16  8  ]
                                    [                        ]
                                    [ 20  4   8   28  32  16 ]
                                    [                        ]
                                    [ 4   8   16  20  28  32 ]
          (%o3)                     [                        ]
                                    [ 32  28  20  16  8   4  ]
                                    [                        ]
                                    [ 16  32  28  8   4   20 ]
                                    [                        ]
                                    [ 8   16  32  4   20  28 ]

 -- Function: zn_nth_root
          zn_nth_root (<x>, <n>, <m>)
          zn_nth_root (<x>, <n>, <m>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Returns a list with all <n>-th roots of <x> from the multiplication
     subgroup of (Z/<m>Z) which contains <x>, or ‘false’, if <x> is no
     <n>-th power modulo <m> or not contained in any multiplication
     subgroup of (Z/<m>Z).

     <x> is an element of a multiplication subgroup modulo <m>, if the
     greatest common divisor ‘g = gcd(x,m)’ is coprime to ‘m/g’.

     ‘zn_nth_root’ is based on an algorithm by Adleman, Manders and
     Miller and on theorems about modulo multiplication groups by Daniel
     Shanks.

     The algorithm needs a prime factorization of the modulus <m>.  So
     in case the factorization of <m> is known, the list of factors can
     be passed as the fourth argument.  This optional argument must be
     of the same form as the list returned by ‘ifactors(m)’ using the
     default option ‘factors_only: false’.

     Examples:

     A power table of the multiplication group modulo ‘14’ followed by a
     list of lists containing all <n>-th roots of ‘1’ with <n> from ‘1’
     to ‘6’.

          (%i1) zn_power_table(14);
                                   [ 1   1   1   1   1   1 ]
                                   [                       ]
                                   [ 3   9   13  11  5   1 ]
                                   [                       ]
                                   [ 5   11  13  9   3   1 ]
          (%o1)                    [                       ]
                                   [ 9   11  1   9   11  1 ]
                                   [                       ]
                                   [ 11  9   1   11  9   1 ]
                                   [                       ]
                                   [ 13  1   13  1   13  1 ]
          (%i2) makelist(zn_nth_root(1,n,14), n,1,6);
          (%o2)  [[1], [1, 13], [1, 9, 11], [1, 13], [1], [1, 3, 5, 9, 11, 13]]

     In the following example <x> is not coprime to <m>, but is a member
     of a multiplication subgroup of (Z/<m>Z) and any <n>-th root is a
     member of the same subgroup.

     The residue class ‘3’ is no member of any multiplication subgroup
     of (Z/63Z) and is therefore not returned as a third root of ‘27’.

     Here ‘zn_power_table’ shows all residues ‘x’ in (Z/63Z) with
     ‘gcd(x,63) = 9’.  This subgroup is isomorphic to (Z/7Z)* and its
     identity ‘36’ is computed via CRT.

          (%i1) m: 7*9$

          (%i2) zn_power_table(m,9);
                                   [ 9   18  36  9   18  36 ]
                                   [                        ]
                                   [ 18  9   36  18  9   36 ]
                                   [                        ]
                                   [ 27  36  27  36  27  36 ]
          (%o2)                    [                        ]
                                   [ 36  36  36  36  36  36 ]
                                   [                        ]
                                   [ 45  9   27  18  54  36 ]
                                   [                        ]
                                   [ 54  18  27  9   45  36 ]
          (%i3) zn_nth_root(27,3,m);
          (%o3)                           [27, 45, 54]
          (%i4) id7:1$  id63_9: solve_congruences([id7,0],[7,9]);
          (%o5)                                36

     In the following RSA-like example, where the modulus ‘N’ is
     squarefree, i.e.  it splits into exclusively first power factors,
     every ‘x’ from ‘0’ to ‘N-1’ is contained in a multiplication
     subgroup.

     The process of decryption needs the ‘e’-th root.  ‘e’ is coprime to
     ‘totient(N)’ and therefore the ‘e’-th root is unique.  In this case
     ‘zn_nth_root’ effectively performs CRT-RSA. (Please note that
     ‘flatten’ removes braces but no solutions.)

          (%i1) [p,q,e]: [5,7,17]$  N: p*q$

          (%i3) xs: makelist(x,x,0,N-1)$

          (%i4) ys: map(lambda([x],power_mod(x,e,N)),xs)$

          (%i5) zs: flatten(map(lambda([y], zn_nth_root(y,e,N)), ys))$

          (%i6) is(zs = xs);
          (%o6)                             true

     In the following example the factorization of the modulus is known
     and passed as the fourth argument.

          (%i1) p: 2^107-1$  q: 2^127-1$  N: p*q$

          (%i4) ibase: obase: 16$

          (%i5) msg: 11223344556677889900aabbccddeeff$

          (%i6) enc: power_mod(msg, 10001, N);
          (%o6)    1a8db7892ae588bdc2be25dd5107a425001fe9c82161abc673241c8b383
          (%i7) zn_nth_root(enc, 10001, N, [[p,1],[q,1]]);
          (%o7)               [11223344556677889900aabbccddeeff]

 -- Function: zn_order
          zn_order (<x>, <n>)
          zn_order (<x>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Returns the order of <x> if it is a unit of the finite group
     (Z/<n>Z)* or returns ‘false’.  <x> is a unit modulo <n> if it is
     coprime to <n>.

     The applied algorithm needs a prime factorization of ‘totient(n)’.
     This factorization might be time consuming in some cases and it can
     be useful to factor first and then to pass the list of factors to
     ‘zn_log’ as the third argument.  The list must be of the same form
     as the list returned by ‘ifactors(totient(n))’ using the default
     option ‘factors_only : false’.

     See also ‘zn_primroot’, ‘ifactors’, ‘totient’.

     Examples:

     ‘zn_order’ computes the order of the unit <x> in (Z/<n>Z)*.

          (%i1) n: 22$
          (%i2) g: zn_primroot(n);
          (%o2)                            7
          (%i3) units_22: sublist(makelist(i,i,1,21), lambda([x], gcd(x,n)=1));
          (%o3)          [1, 3, 5, 7, 9, 13, 15, 17, 19, 21]
          (%i4) (ord_7: zn_order(7, n)) = totient(n);
          (%o4)                        10 = 10
          (%i5) powers_7: makelist(power_mod(g,i,n), i,0,ord_7 - 1);
          (%o5)          [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i6) map(lambda([x], zn_order(x, n)), powers_7);
          (%o6)          [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i7) map(lambda([x], ord_7/gcd(x,ord_7)), makelist(i,i,0,ord_7-1));
          (%o7)         [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i8) totient(totient(n));
          (%o8)                          4

     The optional third argument must be of the same form as the list
     returned by ‘ifactors(totient(n))’.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                         true
          (%i2) ifs: ifactors( totient(p) )$
          (%i3) g: zn_primroot(p, ifs);
          (%o3)                           3
          (%i4) is( (ord_3 : zn_order(g, p, ifs)) = totient(p) );
          (%o4)                         true
          (%i5) map(lambda([x], ord_3/zn_order(x,p,ifs)), makelist(i,i,2,15));
          (%o5)    [22, 1, 44, 10, 5, 2, 22, 2, 8, 2, 1, 1, 20, 1]

 -- Function: zn_power_table
          zn_power_table (<n>)
          zn_power_table (<n>, <gcd>)
          zn_power_table (<n>, <gcd>, <max_exp>)

     Without any optional argument ‘zn_power_table(n)’ shows a power
     table of all elements in (Z/<n>Z)* which are all residue classes
     coprime to <n>.  The exponent loops from ‘1’ to the greatest
     characteristic factor of ‘totient(n)’ (also known as Carmichael
     function or Carmichael lambda) and the table ends with a column of
     ones on the right side.

     The optional second argument <gcd> allows to select powers of a
     specific subset of (Z/<n>Z). If <gcd> is an integer, powers of all
     residue classes ‘x’ with ‘gcd(x,n) = ’<gcd> are returned, i.e.  the
     default value for <gcd> is ‘1’.  If <gcd> is set to ‘all’, the
     table contains powers of all elements in (Z/<n>Z).

     If the optional third argument <max_exp> is given, the exponent
     loops from ‘1’ to <max_exp>.

     See also ‘zn_add_table’, ‘zn_mult_table’.

     Examples:

     The default which is <gcd>‘ = 1’ allows to demonstrate and study
     basic theorems of e.g.  Fermat and Euler.

     The argument <gcd> allows to select subsets of (Z/<n>Z) and to
     study multiplication subgroups and isomorphisms.  E.g.  the groups
     ‘G10’ and ‘G10_2’ are under multiplication both isomorphic to ‘G5’.
     ‘1’ is the identity in ‘G5’.  So are ‘1’ resp.  ‘6’ the identities
     in ‘G10’ resp.  ‘G10_2’.  There are corresponding mappings for
     primitive roots, n-th roots, etc..

          (%i1) zn_power_table(10);
                                        [ 1  1  1  1 ]
                                        [            ]
                                        [ 3  9  7  1 ]
          (%o1)                         [            ]
                                        [ 7  9  3  1 ]
                                        [            ]
                                        [ 9  1  9  1 ]
          (%i2) zn_power_table(10,2);
                                        [ 2  4  8  6 ]
                                        [            ]
                                        [ 4  6  4  6 ]
          (%o2)                         [            ]
                                        [ 6  6  6  6 ]
                                        [            ]
                                        [ 8  4  2  6 ]
          (%i3) zn_power_table(10,5);
          (%o3)                         [ 5  5  5  5 ]
          (%i4) zn_power_table(10,10);
          (%o4)                         [ 0  0  0  0 ]
          (%i5) G5: [1,2,3,4];
          (%o6)                          [1, 2, 3, 4]
          (%i6) G10_2: map(lambda([x], solve_congruences([0,x],[2,5])), G5);
          (%o6)                          [6, 2, 8, 4]
          (%i7) G10: map(lambda([x], power_mod(3, zn_log(x,2,5), 10)), G5);
          (%o7)                          [1, 3, 7, 9]

     If <gcd> is set to ‘all’, the table contains powers of all elements
     in (Z/<n>Z).

     The third argument <max_exp> allows to set the highest exponent.
     The following table shows a very small example of RSA.

          (%i1) N:2*5$ phi:totient(N)$ e:7$ d:inv_mod(e,phi)$

          (%i5) zn_power_table(N, all, e*d);
                [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 ]
                [                                                               ]
                [ 1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 ]
                [                                                               ]
                [ 2  4  8  6  2  4  8  6  2  4  8  6  2  4  8  6  2  4  8  6  2 ]
                [                                                               ]
                [ 3  9  7  1  3  9  7  1  3  9  7  1  3  9  7  1  3  9  7  1  3 ]
                [                                                               ]
                [ 4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4 ]
          (%o5) [                                                               ]
                [ 5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5 ]
                [                                                               ]
                [ 6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6 ]
                [                                                               ]
                [ 7  9  3  1  7  9  3  1  7  9  3  1  7  9  3  1  7  9  3  1  7 ]
                [                                                               ]
                [ 8  4  2  6  8  4  2  6  8  4  2  6  8  4  2  6  8  4  2  6  8 ]
                [                                                               ]
                [ 9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9 ]

 -- Function: zn_primroot
          zn_primroot (<n>)
          zn_primroot (<n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     If the multiplicative group (Z/<n>Z)* is cyclic, ‘zn_primroot’
     computes the smallest primitive root modulo <n>.  (Z/<n>Z)* is
     cyclic if <n> is equal to ‘2’, ‘4’, ‘p^k’ or ‘2*p^k’, where ‘p’ is
     prime and greater than ‘2’ and ‘k’ is a natural number.
     ‘zn_primroot’ performs an according pretest if the option variable
     ‘zn_primroot_pretest’ (default: ‘false’) is set to ‘true’.  In any
     case the computation is limited by the upper bound
     ‘zn_primroot_limit’.

     If (Z/<n>Z)* is not cyclic or if there is no primitive root up to
     ‘zn_primroot_limit’, ‘zn_primroot’ returns ‘false’.

     The applied algorithm needs a prime factorization of ‘totient(n)’.
     This factorization might be time consuming in some cases and it can
     be useful to factor first and then to pass the list of factors to
     ‘zn_log’ as an additional argument.  The list must be of the same
     form as the list returned by ‘ifactors(totient(n))’ using the
     default option ‘factors_only : false’.

     See also ‘zn_primroot_p’, ‘zn_order’, ‘ifactors’, ‘totient’.

     Examples:

     ‘zn_primroot’ computes the smallest primitive root modulo <n> or
     returns ‘false’.

          (%i1) n : 14$
          (%i2) g : zn_primroot(n);
          (%o2)                               3
          (%i3) zn_order(g, n) = totient(n);
          (%o3)                             6 = 6
          (%i4) n : 15$
          (%i5) zn_primroot(n);
          (%o5)                             false

     The optional second argument must be of the same form as the list
     returned by ‘ifactors(totient(n))’.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                               3
          (%i4) [time(%o2), time(%o3)];
          (%o4)                    [[15.556972], [0.004]]
          (%i5) is(zn_order(g, p, ifs) = p - 1);
          (%o5)                             true
          (%i6) n : 2^142 + 216$
          (%i7) ifs : ifactors(totient(n))$
          (%i8) zn_primroot(n, ifs),
                zn_primroot_limit : 200, zn_primroot_verbose : true;
          `zn_primroot' stopped at zn_primroot_limit = 200
          (%o8)                             false

 -- Option variable: zn_primroot_limit
     Default value: ‘1000’

     If ‘zn_primroot’ cannot find a primitive root, it stops at this
     upper bound.  If the option variable ‘zn_primroot_verbose’
     (default: ‘false’) is set to ‘true’, a message will be printed when
     ‘zn_primroot_limit’ is reached.

 -- Function: zn_primroot_p
          zn_primroot_p (<x>, <n>)
          zn_primroot_p (<x>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Checks whether <x> is a primitive root in the multiplicative group
     (Z/<n>Z)*.

     The applied algorithm needs a prime factorization of ‘totient(n)’.
     This factorization might be time consuming and in case
     ‘zn_primroot_p’ will be consecutively applied to a list of
     candidates it can be useful to factor first and then to pass the
     list of factors to ‘zn_log’ as a third argument.  The list must be
     of the same form as the list returned by ‘ifactors(totient(n))’
     using the default option ‘factors_only : false’.

     See also ‘zn_primroot’, ‘zn_order’, ‘ifactors’, ‘totient’.

     Examples:

     ‘zn_primroot_p’ as a predicate function.

          (%i1) n : 14$
          (%i2) units_14 : sublist(makelist(i,i,1,13), lambda([i], gcd(i, n) = 1));
          (%o2)                     [1, 3, 5, 9, 11, 13]
          (%i3) zn_primroot_p(13, n);
          (%o3)                            false
          (%i4) sublist(units_14, lambda([x], zn_primroot_p(x, n)));
          (%o4)                            [3, 5]
          (%i5) map(lambda([x], zn_order(x, n)), units_14);
          (%o5)                      [1, 6, 6, 3, 3, 2]

     The optional third argument must be of the same form as the list
     returned by ‘ifactors(totient(n))’.

          (%i1) (p: 2^142 + 217, primep(p));
          (%o1)                         true
          (%i2) ifs: ifactors( totient(p) )$
          (%i3) sublist(makelist(i,i,1,50), lambda([x], zn_primroot_p(x,p,ifs)));
          (%o3)  [3, 12, 13, 15, 21, 24, 26, 27, 29, 33, 38, 42, 48]
          (%i4) [time(%o2), time(%o3)];
          (%o4)                  [[7.748484], [0.036002]]

 -- Option variable: zn_primroot_pretest
     Default value: ‘false’

     The multiplicative group (Z/<n>Z)* is cyclic if <n> is equal to
     ‘2’, ‘4’, ‘p^k’ or ‘2*p^k’, where ‘p’ is prime and greater than ‘2’
     and ‘k’ is a natural number.

     ‘zn_primroot_pretest’ controls whether ‘zn_primroot’ will check if
     one of these cases occur before it computes the smallest primitive
     root.  Only if ‘zn_primroot_pretest’ is set to ‘true’ this pretest
     will be performed.

 -- Option variable: zn_primroot_verbose
     Default value: ‘false’

     Controls whether ‘zn_primroot’ prints a message when reaching
     ‘zn_primroot_limit’.


File: maxima.info,  Node: Package sym,  Next: Groups,  Prev: Number Theory,  Up: Top

30 Package sym
**************

* Menu:

* Introduction to Symmetries::
* Functions and Variables for Symmetries::


File: maxima.info,  Node: Introduction to Symmetries,  Next: Functions and Variables for Symmetries,  Prev: Package sym,  Up: Package sym

30.1 Introduction to Symmetries
===============================

‘sym’ is a package for working with symmetric groups of polynomials.

   It was written for Macsyma-Symbolics by Annick Valibouze
(<http://www-calfor.lip6.fr/~avb/>).  The algorithms are described in
the following papers:

  1. Fonctions symétriques et changements de bases.  Annick Valibouze.
     EUROCAL'87 (Leipzig, 1987), 323-332, Lecture Notes in Comput.  Sci
     378.  Springer, Berlin, 1989.
     <http://www.stix.polytechnique.fr/publications/1984-1994.html>

  2. Résolvantes et fonctions symétriques.  Annick Valibouze.
     Proceedings of the ACM-SIGSAM 1989 International Symposium on
     Symbolic and Algebraic Computation, ISSAC'89 (Portland, Oregon).
     ACM Press, 390-399, 1989.
     <http://www-calfor.lip6.fr/~avb/DonneesTelechargeables/MesArticles/issac89ACMValibouze.pdf>

  3. Symbolic computation with symmetric polynomials, an extension to
     Macsyma.  Annick Valibouze.  Computers and Mathematics (MIT, USA,
     June 13-17, 1989), Springer-Verlag, New York Berlin, 308-320, 1989.
     <http://www.stix.polytechnique.fr/publications/1984-1994.html>

  4. Théorie de Galois Constructive.  Annick Valibouze.  Mémoire
     d'habilitation à diriger les recherches (HDR), Université P. et M.
     Curie (Paris VI), 1994.


File: maxima.info,  Node: Functions and Variables for Symmetries,  Prev: Introduction to Symmetries,  Up: Package sym

30.2 Functions and Variables for Symmetries
===========================================

30.2.1 Changing bases
---------------------

 -- Function: comp2pui (<n>, <L>)
     implements passing from the complete symmetric functions given in
     the list <L> to the elementary symmetric functions from 0 to <n>.
     If the list <L> contains fewer than <n+1> elements, it will be
     completed with formal values of the type <h1>, <h2>, etc.  If the
     first element of the list <L> exists, it specifies the size of the
     alphabet, otherwise the size is set to <n>.

          (%i1) comp2pui (3, [4, g]);
                                  2                    2
          (%o1)    [4, g, 2 h2 - g , 3 h3 - g h2 + g (g  - 2 h2)]

 -- Function: ele2pui (<m>, <L>)
     goes from the elementary symmetric functions to the complete
     functions.  Similar to ‘comp2ele’ and ‘comp2pui’.

     Other functions for changing bases: ‘comp2ele’.

 -- Function: ele2comp (<m>, <L>)
     Goes from the elementary symmetric functions to the compete
     functions.  Similar to ‘comp2ele’ and ‘comp2pui’.

     Other functions for changing bases: ‘comp2ele’.

 -- Function: elem (<ele>, <sym>, <lvar>)
     decomposes the symmetric polynomial <sym>, in the variables
     contained in the list <lvar>, in terms of the elementary symmetric
     functions given in the list <ele>.  If the first element of <ele>
     is given, it will be the size of the alphabet, otherwise the size
     will be the degree of the polynomial <sym>.  If values are missing
     in the list <ele>, formal values of the type <e1>, <e2>, etc.  will
     be added.  The polynomial <sym> may be given in three different
     forms: contracted (‘elem’ should then be 1, its default value),
     partitioned (‘elem’ should be 3), or extended (i.e.  the entire
     polynomial, and ‘elem’ should then be 2).  The function ‘pui’ is
     used in the same way.

     On an alphabet of size 3 with <e1>, the first elementary symmetric
     function, with value 7, the symmetric polynomial in 3 variables
     whose contracted form (which here depends on only two of its
     variables) is <x^4-2*x*y> decomposes as follows in elementary
     symmetric functions:

          (%i1) elem ([3, 7], x^4 - 2*x*y, [x, y]);
          (%o1) 7 (e3 - 7 e2 + 7 (49 - e2)) + 21 e3

                                                   + (- 2 (49 - e2) - 2) e2
          (%i2) ratsimp (%);
                                        2
          (%o2)             28 e3 + 2 e2  - 198 e2 + 2401

     Other functions for changing bases: ‘comp2ele’.

 -- Function: mon2schur (<L>)
     The list <L> represents the Schur function S_L: we have L = [i_1,
     i_2, ..., i_q], with i_1 <= i_2 <= ... <= i_q.  The Schur function
     S_[i_1, i_2, ..., i_q] is the minor of the infinite matrix h_[i-j],
     i <= 1, j <= 1, consisting of the q first rows and the columns 1 +
     i_1, 2 + i_2, ..., q + i_q.

     This Schur function can be written in terms of monomials by using
     ‘treinat’ and ‘kostka’.  The form returned is a symmetric
     polynomial in a contracted representation in the variables
     x_1,x_2,...

          (%i1) mon2schur ([1, 1, 1]);
          (%o1)                       x1 x2 x3
          (%i2) mon2schur ([3]);
                                            2        3
          (%o2)                x1 x2 x3 + x1  x2 + x1
          (%i3) mon2schur ([1, 2]);
                                                2
          (%o3)                  2 x1 x2 x3 + x1  x2

     which means that for 3 variables this gives:

             2 x1 x2 x3 + x1^2 x2 + x2^2 x1 + x1^2 x3 + x3^2 x1
              + x2^2 x3 + x3^2 x2
     Other functions for changing bases: ‘comp2ele’.

 -- Function: multi_elem (<l_elem>, <multi_pc>, <l_var>)
     decomposes a multi-symmetric polynomial in the multi-contracted
     form <multi_pc> in the groups of variables contained in the list of
     lists <l_var> in terms of the elementary symmetric functions
     contained in <l_elem>.

          (%i1) multi_elem ([[2, e1, e2], [2, f1, f2]], a*x + a^2 + x^3,
                [[x, y], [a, b]]);
                                                            3
          (%o1)         - 2 f2 + f1 (f1 + e1) - 3 e1 e2 + e1
          (%i2) ratsimp (%);
                                   2                       3
          (%o2)         - 2 f2 + f1  + e1 f1 - 3 e1 e2 + e1

     Other functions for changing bases: ‘comp2ele’.

 -- Function: multi_pui
     is to the function ‘pui’ what the function ‘multi_elem’ is to the
     function ‘elem’.

          (%i1) multi_pui ([[2, p1, p2], [2, t1, t2]], a*x + a^2 + x^3,
                [[x, y], [a, b]]);
                                                      3
                                          3 p1 p2   p1
          (%o1)              t2 + p1 t1 + ------- - ---
                                             2       2

 -- Function: pui (<L>, <sym>, <lvar>)
     decomposes the symmetric polynomial <sym>, in the variables in the
     list <lvar>, in terms of the power functions in the list <L>.  If
     the first element of <L> is given, it will be the size of the
     alphabet, otherwise the size will be the degree of the polynomial
     <sym>.  If values are missing in the list <L>, formal values of the
     type <p1>, <p2> , etc.  will be added.  The polynomial <sym> may be
     given in three different forms: contracted (‘elem’ should then be
     1, its default value), partitioned (‘elem’ should be 3), or
     extended (i.e.  the entire polynomial, and ‘elem’ should then be
     2).  The function ‘pui’ is used in the same way.

          (%i1) pui;
          (%o1)                           1
          (%i2) pui ([3, a, b], u*x*y*z, [x, y, z]);
                                 2
                             a (a  - b) u   (a b - p3) u
          (%o2)              ------------ - ------------
                                  6              3
          (%i3) ratsimp (%);
                                                 3
                                (2 p3 - 3 a b + a ) u
          (%o3)                 ---------------------
                                          6
     Other functions for changing bases: ‘comp2ele’.

 -- Function: pui2comp (<n>, <lpui>)
     renders the list of the first <n> complete functions (with the
     length first) in terms of the power functions given in the list
     <lpui>.  If the list <lpui> is empty, the cardinal is <n>,
     otherwise it is its first element (as in ‘comp2ele’ and
     ‘comp2pui’).

          (%i1) pui2comp (2, []);
                                                 2
                                          p2 + p1
          (%o1)                   [2, p1, --------]
                                             2
          (%i2) pui2comp (3, [2, a1]);
                                                      2
                                           a1 (p2 + a1 )
                                   2  p3 + ------------- + a1 p2
                            p2 + a1              2
          (%o2)     [2, a1, --------, --------------------------]
                               2                  3
          (%i3) ratsimp (%);
                                      2                     3
                               p2 + a1   2 p3 + 3 a1 p2 + a1
          (%o3)        [2, a1, --------, --------------------]
                                  2               6
     Other functions for changing bases: ‘comp2ele’.

 -- Function: pui2ele (<n>, <lpui>)
     effects the passage from power functions to the elementary
     symmetric functions.  If the flag ‘pui2ele’ is ‘girard’, it will
     return the list of elementary symmetric functions from 1 to <n>,
     and if the flag is ‘close’, it will return the <n>-th elementary
     symmetric function.

     Other functions for changing bases: ‘comp2ele’.

 -- Function: puireduc (<n>, <lpui>)
     <lpui> is a list whose first element is an integer <m>.  ‘puireduc’
     gives the first <n> power functions in terms of the first <m>.

          (%i1) puireduc (3, [2]);
                                                   2
                                             p1 (p1  - p2)
          (%o1)          [2, p1, p2, p1 p2 - -------------]
                                                   2
          (%i2) ratsimp (%);
                                                     3
                                         3 p1 p2 - p1
          (%o2)              [2, p1, p2, -------------]
                                               2

 -- Function: schur2comp (<P>, <l_var>)
     <P> is a polynomial in the variables of the list <l_var>.  Each of
     these variables represents a complete symmetric function.  In
     <l_var> the <i>-th complete symmetric function is represented by
     the concatenation of the letter ‘h’ and the integer <i>: ‘h<i>’.
     This function expresses <P> in terms of Schur functions.

          (%i1) schur2comp (h1*h2 - h3, [h1, h2, h3]);
          (%o1)                         s
                                         1, 2
          (%i2) schur2comp (a*h3, [h3]);
          (%o2)                         s  a
                                         3

30.2.2 Changing representations
-------------------------------

 -- Function: cont2part (<pc>, <lvar>)
     returns the partitioned polynomial associated to the contracted
     form <pc> whose variables are in <lvar>.

          (%i1) pc: 2*a^3*b*x^4*y + x^5;
                                     3    4      5
          (%o1)                   2 a  b x  y + x
          (%i2) cont2part (pc, [x, y]);
                                             3
          (%o2)              [[1, 5, 0], [2 a  b, 4, 1]]

 -- Function: contract (<psym>, <lvar>)
     returns a contracted form (i.e.  a monomial orbit under the action
     of the symmetric group) of the polynomial <psym> in the variables
     contained in the list <lvar>.  The function ‘explose’ performs the
     inverse operation.  The function ‘tcontract’ tests the symmetry of
     the polynomial.

          (%i1) psym: explose (2*a^3*b*x^4*y, [x, y, z]);
                   3      4      3      4      3    4        3    4
          (%o1) 2 a  b y z  + 2 a  b x z  + 2 a  b y  z + 2 a  b x  z

                                                     3      4      3    4
                                                + 2 a  b x y  + 2 a  b x  y
          (%i2) contract (psym, [x, y, z]);
                                        3    4
          (%o2)                      2 a  b x  y

 -- Function: explose (<pc>, <lvar>)
     returns the symmetric polynomial associated with the contracted
     form <pc>.  The list <lvar> contains the variables.

          (%i1) explose (a*x + 1, [x, y, z]);
          (%o1)                  a z + a y + a x + 1

 -- Function: part2cont (<ppart>, <lvar>)
     goes from the partitioned form to the contracted form of a
     symmetric polynomial.  The contracted form is rendered with the
     variables in <lvar>.

          (%i1) part2cont ([[2*a^3*b, 4, 1]], [x, y]);
                                        3    4
          (%o1)                      2 a  b x  y

 -- Function: partpol (<psym>, <lvar>)
     <psym> is a symmetric polynomial in the variables of the list
     <lvar>.  This function returns its partitioned representation.

          (%i1) partpol (-a*(x + y) + 3*x*y, [x, y]);
          (%o1)               [[3, 1, 1], [- a, 1, 0]]

 -- Function: tcontract (<pol>, <lvar>)
     tests if the polynomial <pol> is symmetric in the variables of the
     list <lvar>.  If so, it returns a contracted representation like
     the function ‘contract’.

 -- Function: tpartpol (<pol>, <lvar>)
     tests if the polynomial <pol> is symmetric in the variables of the
     list <lvar>.  If so, it returns its partitioned representation like
     the function ‘partpol’.

30.2.3 Groups and orbits
------------------------

 -- Function: direct ([<p_1>, ..., <p_n>], <y>, <f>, [<lvar_1>, ...,
          <lvar_n>])
     calculates the direct image (see M. Giusti, D. Lazard et A.
     Valibouze, ISSAC 1988, Rome) associated to the function <f>, in the
     lists of variables <lvar_1>, ..., <lvar_n>, and in the polynomials
     <p_1>, ..., <p_n> in a variable <y>.  The arity of the function <f>
     is important for the calculation.  Thus, if the expression for <f>
     does not depend on some variable, it is useless to include this
     variable, and not including it will also considerably reduce the
     amount of computation.

          (%i1) direct ([z^2  - e1* z + e2, z^2  - f1* z + f2],
                        z, b*v + a*u, [[u, v], [a, b]]);
                 2
          (%o1) y  - e1 f1 y

                                           2            2             2   2
                            - 4 e2 f2 - (e1  - 2 e2) (f1  - 2 f2) + e1  f1
                          + -----------------------------------------------
                                                   2
          (%i2) ratsimp (%);
                        2                2                   2
          (%o2)        y  - e1 f1 y + (e1  - 4 e2) f2 + e2 f1
          (%i3) ratsimp (direct ([z^3-e1*z^2+e2*z-e3,z^2  - f1* z + f2],
                        z, b*v + a*u, [[u, v], [a, b]]));
                 6            5         2                        2    2   4
          (%o3) y  - 2 e1 f1 y  + ((2 e1  - 6 e2) f2 + (2 e2 + e1 ) f1 ) y

                                    3                               3   3
           + ((9 e3 + 5 e1 e2 - 2 e1 ) f1 f2 + (- 2 e3 - 2 e1 e2) f1 ) y

                   2       2        4    2
           + ((9 e2  - 6 e1  e2 + e1 ) f2

                              2       2       2                   2    4
           + (- 9 e1 e3 - 6 e2  + 3 e1  e2) f1  f2 + (2 e1 e3 + e2 ) f1 )

            2          2                      2     3          2
           y  + (((9 e1  - 27 e2) e3 + 3 e1 e2  - e1  e2) f1 f2

                           2            2    3                5
           + ((15 e2 - 2 e1 ) e3 - e1 e2 ) f1  f2 - 2 e2 e3 f1 ) y

                     2                   3           3     2   2    3
           + (- 27 e3  + (18 e1 e2 - 4 e1 ) e3 - 4 e2  + e1  e2 ) f2

                   2      3                   3    2   2
           + (27 e3  + (e1  - 9 e1 e2) e3 + e2 ) f1  f2

                             2    4        2   6
           + (e1 e2 e3 - 9 e3 ) f1  f2 + e3  f1

     Finding the polynomial whose roots are the sums a+u where a is a
     root of z^2 - e_1 z + e_2 and u is a root of z^2 - f_1 z + f_2.

          (%i1) ratsimp (direct ([z^2 - e1* z + e2, z^2 - f1* z + f2],
                                    z, a + u, [[u], [a]]));
                 4                    3             2
          (%o1) y  + (- 2 f1 - 2 e1) y  + (2 f2 + f1  + 3 e1 f1 + 2 e2

               2   2                              2               2
           + e1 ) y  + ((- 2 f1 - 2 e1) f2 - e1 f1  + (- 2 e2 - e1 ) f1

                            2                     2            2
           - 2 e1 e2) y + f2  + (e1 f1 - 2 e2 + e1 ) f2 + e2 f1  + e1 e2 f1

               2
           + e2

     ‘direct’ accepts two flags: ‘elementaires’ and ‘puissances’
     (default) which allow decomposing the symmetric polynomials
     appearing in the calculation into elementary symmetric functions,
     or power functions, respectively.

     Functions of ‘sym’ used in this function:

     ‘multi_orbit’ (so ‘orbit’), ‘pui_direct’, ‘multi_elem’ (so ‘elem’),
     ‘multi_pui’ (so ‘pui’), ‘pui2ele’, ‘ele2pui’ (if the flag ‘direct’
     is in ‘puissances’).

 -- Function: multi_orbit (<P>, [<lvar_1>, <lvar_2>,..., <lvar_p>])

     <P> is a polynomial in the set of variables contained in the lists
     <lvar_1>, <lvar_2>, ..., <lvar_p>.  This function returns the orbit
     of the polynomial <P> under the action of the product of the
     symmetric groups of the sets of variables represented in these <p>
     lists.

          (%i1) multi_orbit (a*x + b*y, [[x, y], [a, b]]);
          (%o1)                [b y + a x, a y + b x]
          (%i2) multi_orbit (x + y + 2*a, [[x, y], [a, b, c]]);
          (%o2)        [y + x + 2 c, y + x + 2 b, y + x + 2 a]
     Also see: ‘orbit’ for the action of a single symmetric group.

 -- Function: multsym (<ppart_1>, <ppart_2>, <n>)
     returns the product of the two symmetric polynomials in <n>
     variables by working only modulo the action of the symmetric group
     of order <n>.  The polynomials are in their partitioned form.

     Given the 2 symmetric polynomials in <x>, <y>: ‘3*(x + y) + 2*x*y’
     and ‘5*(x^2 + y^2)’ whose partitioned forms are ‘[[3, 1], [2, 1,
     1]]’ and ‘[[5, 2]]’, their product will be

          (%i1) multsym ([[3, 1], [2, 1, 1]], [[5, 2]], 2);
          (%o1)         [[10, 3, 1], [15, 3, 0], [15, 2, 1]]
     that is ‘10*(x^3*y + y^3*x) + 15*(x^2*y + y^2*x) + 15*(x^3 + y^3)’.

     Functions for changing the representations of a symmetric
     polynomial:

     ‘contract’, ‘cont2part’, ‘explose’, ‘part2cont’, ‘partpol’,
     ‘tcontract’, ‘tpartpol’.

 -- Function: orbit (<P>, <lvar>)
     computes the orbit of the polynomial <P> in the variables in the
     list <lvar> under the action of the symmetric group of the set of
     variables in the list <lvar>.

          (%i1) orbit (a*x + b*y, [x, y]);
          (%o1)                [a y + b x, b y + a x]
          (%i2) orbit (2*x + x^2, [x, y]);
                                  2         2
          (%o2)                 [y  + 2 y, x  + 2 x]
     See also ‘multi_orbit’ for the action of a product of symmetric
     groups on a polynomial.

 -- Function: pui_direct (<orbite>, [<lvar_1>, ..., <lvar_n>], [<d_1>,
          <d_2>, ..., <d_n>])

     Let <f> be a polynomial in <n> blocks of variables <lvar_1>, ...,
     <lvar_n>.  Let <c_i> be the number of variables in <lvar_i>, and
     <SC> be the product of <n> symmetric groups of degree <c_1>, ...,
     <c_n>.  This group acts naturally on <f>.  The list <orbite> is the
     orbit, denoted ‘<SC>(<f>)’, of the function <f> under the action of
     <SC>.  (This list may be obtained by the function ‘multi_orbit’.)
     The <di> are integers s.t.  c_1 <= d_1, c_2 <= d_2, ..., c_n <=
     d_n.

     Let <SD> be the product of the symmetric groups S_[d_1] x S_[d_2] x
     ... x S_[d_n].  The function ‘pui_direct’ returns the first <n>
     power functions of ‘<SD>(<f>)’ deduced from the power functions of
     ‘<SC>(<f>)’, where <n> is the size of ‘<SD>(<f>)’.

     The result is in multi-contracted form w.r.t.  <SD>, i.e.  only one
     element is kept per orbit, under the action of <SD>.

          (%i1) l: [[x, y], [a, b]];
          (%o1)                   [[x, y], [a, b]]
          (%i2) pui_direct (multi_orbit (a*x + b*y, l), l, [2, 2]);
                                                 2  2
          (%o2)               [a x, 4 a b x y + a  x ]
          (%i3) pui_direct (multi_orbit (a*x + b*y, l), l, [3, 2]);
                                       2  2     2    2        3  3
          (%o3) [2 a x, 4 a b x y + 2 a  x , 3 a  b x  y + 2 a  x ,

              2  2  2  2      3    3        4  4
          12 a  b  x  y  + 4 a  b x  y + 2 a  x ,

              3  2  3  2      4    4        5  5
          10 a  b  x  y  + 5 a  b x  y + 2 a  x ,

              3  3  3  3       4  2  4  2      5    5        6  6
          40 a  b  x  y  + 15 a  b  x  y  + 6 a  b x  y + 2 a  x ]
          (%i4) pui_direct ([y + x + 2*c, y + x + 2*b, y + x + 2*a],
                [[x, y], [a, b, c]], [2, 3]);
                                       2              2
          (%o4) [3 x + 2 a, 6 x y + 3 x  + 4 a x + 4 a ,

                           2                   3        2       2        3
                        9 x  y + 12 a x y + 3 x  + 6 a x  + 12 a  x + 8 a ]

30.2.4 Partitions
-----------------

 -- Function: kostka (<part_1>, <part_2>)
     written by P. Esperet, calculates the Kostka number of the
     partition <part_1> and <part_2>.

          (%i1) kostka ([3, 3, 3], [2, 2, 2, 1, 1, 1]);
          (%o1)                           6

 -- Function: lgtreillis (<n>, <m>)
     returns the list of partitions of weight <n> and length <m>.

          (%i1) lgtreillis (4, 2);
          (%o1)                   [[3, 1], [2, 2]]
     Also see: ‘ltreillis’, ‘treillis’ and ‘treinat’.

 -- Function: ltreillis (<n>, <m>)
     returns the list of partitions of weight <n> and length less than
     or equal to <m>.

          (%i1) ltreillis (4, 2);
          (%o1)               [[4, 0], [3, 1], [2, 2]]
     Also see: ‘lgtreillis’, ‘treillis’ and ‘treinat’.

 -- Function: treillis (<n>)
     returns all partitions of weight <n>.

          (%i1) treillis (4);
          (%o1)    [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]

     See also: ‘lgtreillis’, ‘ltreillis’ and ‘treinat’.

 -- Function: treinat (<part>)
     returns the list of partitions inferior to the partition <part>
     w.r.t.  the natural order.

          (%i1) treinat ([5]);
          (%o1)                         [[5]]
          (%i2) treinat ([1, 1, 1, 1, 1]);
          (%o2) [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1],

                                                           [1, 1, 1, 1, 1]]
          (%i3) treinat ([3, 2]);
          (%o3)                 [[5], [4, 1], [3, 2]]

     See also: ‘lgtreillis’, ‘ltreillis’ and ‘treillis’.

30.2.5 Polynomials and their roots
----------------------------------

 -- Function: ele2polynome (<L>, <z>)
     returns the polynomial in <z> s.t.  the elementary symmetric
     functions of its roots are in the list ‘<L> = [<n>, <e_1>, ...,
     <e_n>]’, where <n> is the degree of the polynomial and <e_i> the
     <i>-th elementary symmetric function.

          (%i1) ele2polynome ([2, e1, e2], z);
                                    2
          (%o1)                    z  - e1 z + e2
          (%i2) polynome2ele (x^7 - 14*x^5 + 56*x^3  - 56*x + 22, x);
          (%o2)          [7, 0, - 14, 0, 56, 0, - 56, - 22]
          (%i3) ele2polynome ([7, 0, -14, 0, 56, 0, -56, -22], x);
                            7       5       3
          (%o3)            x  - 14 x  + 56 x  - 56 x + 22
     The inverse: ‘polynome2ele (<P>, <z>)’.

     Also see: ‘polynome2ele’, ‘pui2polynome’.

 -- Function: polynome2ele (<P>, <x>)
     gives the list ‘<l> = [<n>, <e_1>, ..., <e_n>]’ where <n> is the
     degree of the polynomial <P> in the variable <x> and <e_i> is the
     <i>-the elementary symmetric function of the roots of <P>.

          (%i1) polynome2ele (x^7 - 14*x^5 + 56*x^3 - 56*x + 22, x);
          (%o1)          [7, 0, - 14, 0, 56, 0, - 56, - 22]
          (%i2) ele2polynome ([7, 0, -14, 0, 56, 0, -56, -22], x);
                            7       5       3
          (%o2)            x  - 14 x  + 56 x  - 56 x + 22
     The inverse: ‘ele2polynome (<l>, <x>)’

 -- Function: prodrac (<L>, <k>)
     <L> is a list containing the elementary symmetric functions on a
     set <A>.  ‘prodrac’ returns the polynomial whose roots are the <k>
     by <k> products of the elements of <A>.

     Also see ‘somrac’.

 -- Function: pui2polynome (<x>, <lpui>)
     calculates the polynomial in <x> whose power functions of the roots
     are given in the list <lpui>.

          (%i1) pui;
          (%o1)                           1
          (%i2) kill(labels);
          (%o0)                         done
          (%i1) polynome2ele (x^3 - 4*x^2 + 5*x - 1, x);
          (%o1)                     [3, 4, 5, 1]
          (%i2) ele2pui (3, %);
          (%o2)                     [3, 4, 6, 7]
          (%i3) pui2polynome (x, %);
                                  3      2
          (%o3)                  x  - 4 x  + 5 x - 1
     See also: ‘polynome2ele’, ‘ele2polynome’.

 -- Function: somrac (<L>, <k>)
     The list <L> contains elementary symmetric functions of a
     polynomial <P> .  The function computes the polynomial whose roots
     are the <k> by <k> distinct sums of the roots of <P>.

     Also see ‘prodrac’.

30.2.6 Resolvents
-----------------

 -- Function: resolvante (<P>, <x>, <f>, [<x_1>,..., <x_d>])
     calculates the resolvent of the polynomial <P> in <x> of degree ‘n
     >= d’ by the function <f> expressed in the variables <x_1>, ...,
     <x_d>.  For efficiency of computation it is important to not
     include in the list ‘[<x_1>, ..., <x_d>]’ variables which do not
     appear in the transformation function <f>.

     To increase the efficiency of the computation one may set flags in
     ‘resolvante’ so as to use appropriate algorithms:

     If the function <f> is unitary:
        • A polynomial in a single variable,
        • linear,
        • alternating,
        • a sum,
        • symmetric,
        • a product,
        • the function of the Cayley resolvent (usable up to degree 5)

               (x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x1 -
                    (x1*x3 + x3*x5 + x5*x2 + x2*x4 + x4*x1))^2

          general,
     the flag of ‘resolvante’ may be, respectively:
        • unitaire,
        • lineaire,
        • alternee,
        • somme,
        • produit,
        • cayley,
        • generale.

          (%i1) resolvante: unitaire$
          (%i2) resolvante (x^7 - 14*x^5 + 56*x^3 - 56*x + 22, x, x^3 - 1,
                [x]);

          " resolvante unitaire " [7, 0, 28, 0, 168, 0, 1120, - 154, 7840,
                                   - 2772, 56448, - 33880,

          413952, - 352352, 3076668, - 3363360, 23114112, - 30494464,

          175230832, - 267412992, 1338886528, - 2292126760]
            3       6      3       9      6      3
          [x  - 1, x  - 2 x  + 1, x  - 3 x  + 3 x  - 1,

           12      9      6      3       15      12       9       6      3
          x   - 4 x  + 6 x  - 4 x  + 1, x   - 5 x   + 10 x  - 10 x  + 5 x

                 18      15       12       9       6      3
           - 1, x   - 6 x   + 15 x   - 20 x  + 15 x  - 6 x  + 1,

           21      18       15       12       9       6      3
          x   - 7 x   + 21 x   - 35 x   + 35 x  - 21 x  + 7 x  - 1]
          [- 7, 1127, - 6139, 431767, - 5472047, 201692519, - 3603982011]
                 7      6        5         4          3           2
          (%o2) y  + 7 y  - 539 y  - 1841 y  + 51443 y  + 315133 y

                                                        + 376999 y + 125253
          (%i3) resolvante: lineaire$
          (%i4) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3]);

          " resolvante lineaire "
                 24       20         16            12             8
          (%o4) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i5) resolvante: general$
          (%i6) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3]);

          " resolvante generale "
                 24       20         16            12             8
          (%o6) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i7) resolvante (x^4 - 1, x, x1 + 2*x2 + 3*x3, [x1, x2, x3, x4]);

          " resolvante generale "
                 24       20         16            12             8
          (%o7) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i8) direct ([x^4 - 1], x, x1 + 2*x2 + 3*x3, [[x1, x2, x3]]);
                 24       20         16            12             8
          (%o8) y   + 80 y   + 7520 y   + 1107200 y   + 49475840 y

                                                              4
                                                 + 344489984 y  + 655360000
          (%i9) resolvante :lineaire$
          (%i10) resolvante (x^4 - 1, x, x1 + x2 + x3, [x1, x2, x3]);

          " resolvante lineaire "
                                        4
          (%o10)                       y  - 1
          (%i11) resolvante: symetrique$
          (%i12) resolvante (x^4 - 1, x, x1 + x2 + x3, [x1, x2, x3]);

          " resolvante symetrique "
                                        4
          (%o12)                       y  - 1
          (%i13) resolvante (x^4 + x + 1, x, x1 - x2, [x1, x2]);

          " resolvante symetrique "
                                     6      2
          (%o13)                    y  - 4 y  - 1
          (%i14) resolvante: alternee$
          (%i15) resolvante (x^4 + x + 1, x, x1 - x2, [x1, x2]);

          " resolvante alternee "
                      12      8       6        4        2
          (%o15)     y   + 8 y  + 26 y  - 112 y  + 216 y  + 229
          (%i16) resolvante: produit$
          (%i17) resolvante (x^7 - 7*x + 3, x, x1*x2*x3, [x1, x2, x3]);

          " resolvante produit "
                  35      33         29        28         27        26
          (%o17) y   - 7 y   - 1029 y   + 135 y   + 7203 y   - 756 y

                   24           23          22            21           20
           + 1323 y   + 352947 y   - 46305 y   - 2463339 y   + 324135 y

                    19           18             17              15
           - 30618 y   - 453789 y   - 40246444 y   + 282225202 y

                       14              12             11            10
           - 44274492 y   + 155098503 y   + 12252303 y   + 2893401 y

                        9            8            7             6
           - 171532242 y  + 6751269 y  + 2657205 y  - 94517766 y

                      5             3
           - 3720087 y  + 26040609 y  + 14348907
          (%i18) resolvante: symetrique$
          (%i19) resolvante (x^7 - 7*x + 3, x, x1*x2*x3, [x1, x2, x3]);

          " resolvante symetrique "
                  35      33         29        28         27        26
          (%o19) y   - 7 y   - 1029 y   + 135 y   + 7203 y   - 756 y

                   24           23          22            21           20
           + 1323 y   + 352947 y   - 46305 y   - 2463339 y   + 324135 y

                    19           18             17              15
           - 30618 y   - 453789 y   - 40246444 y   + 282225202 y

                       14              12             11            10
           - 44274492 y   + 155098503 y   + 12252303 y   + 2893401 y

                        9            8            7             6
           - 171532242 y  + 6751269 y  + 2657205 y  - 94517766 y

                      5             3
           - 3720087 y  + 26040609 y  + 14348907
          (%i20) resolvante: cayley$
          (%i21) resolvante (x^5 - 4*x^2 + x + 1, x, a, []);

          " resolvante de Cayley "
                  6       5         4          3            2
          (%o21) x  - 40 x  + 4080 x  - 92928 x  + 3772160 x  + 37880832 x

                                                                 + 93392896

     For the Cayley resolvent, the 2 last arguments are neutral and the
     input polynomial must necessarily be of degree 5.

     See also:
     ‘resolvante_bipartite’, ‘resolvante_produit_sym’,
     ‘resolvante_unitaire’, ‘resolvante_alternee1’, ‘resolvante_klein’,
     ‘resolvante_klein3’, ‘resolvante_vierer’, ‘resolvante_diedrale’.

 -- Function: resolvante_alternee1 (<P>, <x>)
     calculates the transformation ‘<P>(<x>)’ of degree <n> by the
     function product(x_i - x_j, 1 <= i < j <= n - 1).

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante’, ‘resolvante_klein’, ‘resolvante_klein3’,
     ‘resolvante_vierer’, ‘resolvante_diedrale’, ‘resolvante_bipartite’.

 -- Function: resolvante_bipartite (<P>, <x>)
     calculates the transformation of ‘<P>(<x>)’ of even degree <n> by
     the function x_1 x_2 ... x_[n/2] + x_[n/2 + 1] ... x_n.

          (%i1) resolvante_bipartite (x^6 + 108, x);
                        10        8           6             4
          (%o1)        y   - 972 y  + 314928 y  - 34012224 y

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante’, ‘resolvante_klein’, ‘resolvante_klein3’,
     ‘resolvante_vierer’, ‘resolvante_diedrale’, ‘resolvante_alternee1’.

 -- Function: resolvante_diedrale (<P>, <x>)
     calculates the transformation of ‘<P>(<x>)’ by the function ‘<x_1>
     <x_2> + <x_3> <x_4>’.

          (%i1) resolvante_diedrale (x^5 - 3*x^4 + 1, x);
                 15       12       11       10        9         8         7
          (%o1) x   - 21 x   - 81 x   - 21 x   + 207 x  + 1134 x  + 2331 x

                  6         5          4          3          2
           - 945 x  - 4970 x  - 18333 x  - 29079 x  - 20745 x  - 25326 x

           - 697

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante_alternee1’, ‘resolvante_klein’, ‘resolvante_klein3’,
     ‘resolvante_vierer’, ‘resolvante’.

 -- Function: resolvante_klein (<P>, <x>)
     calculates the transformation of ‘<P>(<x>)’ by the function ‘<x_1>
     <x_2> <x_4> + <x_4>’.

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante_alternee1’, ‘resolvante’, ‘resolvante_klein3’,
     ‘resolvante_vierer’, ‘resolvante_diedrale’.

 -- Function: resolvante_klein3 (<P>, <x>)
     calculates the transformation of ‘<P>(<x>)’ by the function ‘<x_1>
     <x_2> <x_4> + <x_4>’.

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante_alternee1’, ‘resolvante_klein’, ‘resolvante’,
     ‘resolvante_vierer’, ‘resolvante_diedrale’.

 -- Function: resolvante_produit_sym (<P>, <x>)
     calculates the list of all product resolvents of the polynomial
     ‘<P>(<x>)’.

          (%i1) resolvante_produit_sym (x^5 + 3*x^4 + 2*x - 1, x);
                  5      4             10      8       7       6       5
          (%o1) [y  + 3 y  + 2 y - 1, y   - 2 y  - 21 y  - 31 y  - 14 y

              4       3      2       10      8       7    6       5       4
           - y  + 14 y  + 3 y  + 1, y   + 3 y  + 14 y  - y  - 14 y  - 31 y

                 3      2       5      4
           - 21 y  - 2 y  + 1, y  - 2 y  - 3 y - 1, y - 1]
          (%i2) resolvante: produit$
          (%i3) resolvante (x^5 + 3*x^4 + 2*x - 1, x, a*b*c, [a, b, c]);

          " resolvante produit "
                 10      8       7    6        5       4       3     2
          (%o3) y   + 3 y  + 14 y  - y  - 14 y  - 31 y  - 21 y  - 2 y  + 1

     See also:
     ‘resolvante’, ‘resolvante_unitaire’,
     ‘resolvante_alternee1’, ‘resolvante_klein’,
     ‘resolvante_klein3’, ‘resolvante_vierer’,
     ‘resolvante_diedrale’.

 -- Function: resolvante_unitaire (<P>, <Q>, <x>)
     computes the resolvent of the polynomial ‘<P>(<x>)’ by the
     polynomial ‘<Q>(<x>)’.

     See also:
     ‘resolvante_produit_sym’, ‘resolvante’,
     ‘resolvante_alternee1’, ‘resolvante_klein’, ‘resolvante_klein3’,
     ‘resolvante_vierer’, ‘resolvante_diedrale’.

 -- Function: resolvante_vierer (<P>, <x>)
     computes the transformation of ‘<P>(<x>)’ by the function ‘<x_1>
     <x_2> - <x_3> <x_4>’.

     See also:
     ‘resolvante_produit_sym’, ‘resolvante_unitaire’,
     ‘resolvante_alternee1’, ‘resolvante_klein’, ‘resolvante_klein3’,
     ‘resolvante’, ‘resolvante_diedrale’.

30.2.7 Miscellaneous
--------------------

 -- Function: multinomial (<r>, <part>)
     where <r> is the weight of the partition <part>.  This function
     returns the associate multinomial coefficient: if the parts of
     <part> are <i_1>, <i_2>, ..., <i_k>, the result is ‘<r>!/(<i_1>!
     <i_2>! ... <i_k>!)’.

 -- Function: permut (<L>)
     returns the list of permutations of the list <L>.


File: maxima.info,  Node: Groups,  Next: Runtime Environment,  Prev: Package sym,  Up: Top

31 Groups
*********

* Menu:

* Functions and Variables for Groups::


File: maxima.info,  Node: Functions and Variables for Groups,  Prev: Groups,  Up: Groups

31.1 Functions and Variables for Groups
=======================================

 -- Function: todd_coxeter
          todd_coxeter (<relations>, <subgroup>)
          todd_coxeter (<relations>)

     Find the order of G/H where G is the Free Group modulo <relations>,
     and H is the subgroup of G generated by <subgroup>.  <subgroup> is
     an optional argument, defaulting to [].  In doing this it produces
     a multiplication table for the right action of G on G/H, where the
     cosets are enumerated [H,Hg2,Hg3,...].  This can be seen internally
     in the variable ‘todd_coxeter_state’.

     Example:

          (%i1) symet(n):=create_list(
                  if (j - i) = 1 then (p(i,j))^^3 else
                      if (not i = j) then (p(i,j))^^2 else
                          p(i,i) , j, 1, n-1, i, 1, j);
                                                                 <3>
          (%o1) symet(n) := create_list(if j - i = 1 then p(i, j)

                                          <2>
           else (if not i = j then p(i, j)    else p(i, i)), j, 1, n - 1,

          i, 1, j)
          (%i2) p(i,j) := concat(x,i).concat(x,j);
          (%o2)        p(i, j) := concat(x, i) . concat(x, j)
          (%i3) symet(5);
                   <2>           <3>    <2>           <2>           <3>
          (%o3) [x1   , (x1 . x2)   , x2   , (x1 . x3)   , (x2 . x3)   ,

                      <2>           <2>           <2>           <3>    <2>
                    x3   , (x1 . x4)   , (x2 . x4)   , (x3 . x4)   , x4   ]
          (%i4) todd_coxeter(%o3);

          Rows tried 426
          (%o4)                          120
          (%i5) todd_coxeter(%o3,[x1]);

          Rows tried 213
          (%o5)                          60
          (%i6) todd_coxeter(%o3,[x1,x2]);

          Rows tried 71
          (%o6)                          20


File: maxima.info,  Node: Runtime Environment,  Next: Miscellaneous Options,  Prev: Groups,  Up: Top

32 Runtime Environment
**********************

* Menu:

* Introduction for Runtime Environment::
* Interrupts::
* Functions and Variables for Runtime Environment::


File: maxima.info,  Node: Introduction for Runtime Environment,  Next: Interrupts,  Prev: Runtime Environment,  Up: Runtime Environment

32.1 Introduction for Runtime Environment
=========================================

‘maxima-init.mac’ is a file which is loaded automatically when Maxima
starts.  You can use ‘maxima-init.mac’ to customize your Maxima
environment.  ‘maxima-init.mac’, if it exists, is typically placed in
the directory named by ‘maxima_userdir’, although it can be in any
directory searched by the function ‘file_search’.

   Here is an example ‘maxima-init.mac’ file:

     setup_autoload ("specfun.mac", ultraspherical, assoc_legendre_p);
     showtime:all;

   In this example, ‘setup_autoload’ tells Maxima to load the specified
file (‘specfun.mac’) if any of the functions (‘ultraspherical’,
‘assoc_legendre_p’) are called but not yet defined.  Thus you needn't
remember to load the file before calling the functions.

   The statement ‘showtime: all’ tells Maxima to set the ‘showtime’
variable.  The ‘maxima-init.mac’ file can contain any other assignments
or other Maxima statements.


File: maxima.info,  Node: Interrupts,  Next: Functions and Variables for Runtime Environment,  Prev: Introduction for Runtime Environment,  Up: Runtime Environment

32.2 Interrupts
===============

The user can stop a time-consuming computation with the ^C (control-C)
character.  The default action is to stop the computation and print
another user prompt.  In this case, it is not possible to restart a
stopped computation.

   If the Lisp variable ‘*debugger-hook*’ is set to ‘nil’, by executing

     :lisp (setq *debugger-hook* nil)

then upon receiving ^C, Maxima will enter the Lisp debugger, and the
user may use the debugger to inspect the Lisp environment.  The stopped
computation can be restarted by entering ‘continue’ in the Lisp
debugger.  The means of returning to Maxima from the Lisp debugger
(other than running the computation to completion) is different for each
version of Lisp.

   On Unix systems, the character ^Z (control-Z) causes Maxima to stop
altogether, and control is returned to the shell prompt.  The ‘fg’
command causes Maxima to resume from the point at which it was stopped.


File: maxima.info,  Node: Functions and Variables for Runtime Environment,  Prev: Interrupts,  Up: Runtime Environment

32.3 Functions and Variables for Runtime Environment
====================================================

 -- System variable: maxima_tempdir

     ‘maxima_tempdir’ names the directory in which Maxima creates some
     temporary files.  In particular, temporary files for plotting are
     created in ‘maxima_tempdir’.

     The initial value of ‘maxima_tempdir’ is the user's home directory,
     if Maxima can locate it; otherwise Maxima makes a guess about a
     suitable directory.

     ‘maxima_tempdir’ may be assigned a string which names a directory.

 -- System variable: maxima_userdir

     ‘maxima_userdir’ names a directory which Maxima searches to find
     Maxima and Lisp files.  (Maxima searches some other directories as
     well; ‘file_search_maxima’ and ‘file_search_lisp’ are the complete
     lists.)

     The initial value of ‘maxima_userdir’ is a subdirectory of the
     user's home directory, if Maxima can locate it; otherwise Maxima
     makes a guess about a suitable directory.

     ‘maxima_userdir’ may be assigned a string which names a directory.
     However, assigning to ‘maxima_userdir’ does not automatically
     change ‘file_search_maxima’ and ‘file_search_lisp’; those variables
     must be changed separately.

 -- Function: room
          room ()
          room (true)
          room (false)

     Prints out a description of the state of storage and stack
     management in Maxima.  ‘room’ calls the Lisp function of the same
     name.

        • ‘room ()’ prints out a moderate description.
        • ‘room (true)’ prints out a verbose description.
        • ‘room (false)’ prints out a terse description.

 -- Function: sstatus (<keyword>, <item>)

     When <keyword> is the symbol ‘feature’, <item> is put on the list
     of system features.  After ‘sstatus (keyword, item)’ is executed,
     ‘status (feature, item)’ returns ‘true’.  If <keyword> is the
     symbol ‘nofeature’, <item> is deleted from the list of system
     features.  This can be useful for package writers, to keep track of
     what features they have loaded in.

     See also ‘status’.

 -- Function: status
          status (feature)
          status (feature, <item>)

     Returns information about the presence or absence of certain
     system-dependent features.

        • ‘status (feature)’ returns a list of system features.  These
          include Lisp version, operating system type, etc.  The list
          may vary from one Lisp type to another.

        • ‘status (feature, item)’ returns ‘true’ if <item> is on the
          list of items returned by ‘status (feature)’ and ‘false’
          otherwise.  ‘status’ quotes the argument <item>.  The
          quote-quote operator ‘''’ defeats quotation.  A feature whose
          name contains a special character, such as a hyphen, must be
          given as a string argument.  For example, ‘status (feature,
          "ansi-cl")’.

     See also ‘sstatus’.

     The variable ‘features’ contains a list of features which apply to
     mathematical expressions.  See ‘features’ and ‘featurep’ for more
     information.

 -- Function: system (<command>)

     Executes <command> as a separate process.  The command is passed to
     the default shell for execution.  ‘system’ is not supported by all
     operating systems, but generally exists in Unix and Unix-like
     environments.

     Supposing ‘_hist.out’ is a list of frequencies which you wish to
     plot as a bar graph using ‘xgraph’.

          (%i1) (with_stdout("_hist.out",
                     for i:1 thru length(hist) do (
                       print(i,hist[i]))),
                 system("xgraph -bar -brw .7 -nl < _hist.out"));

     In order to make the plot be done in the background (returning
     control to Maxima) and remove the temporary file after it is done
     do:

          system("(xgraph -bar -brw .7 -nl < _hist.out;  rm -f _hist.out)&")

 -- Function: time (%o1, %o2, %o3, ...)

     Returns a list of the times, in seconds, taken to compute the
     output lines ‘%o1’, ‘%o2’, ‘%o3’, ... The time returned is Maxima's
     estimate of the internal computation time, not the elapsed time.
     ‘time’ can only be applied to output line variables; for any other
     variables, ‘time’ returns ‘unknown’.

     Set ‘showtime: true’ to make Maxima print out the computation time
     and elapsed time with each output line.

 -- Function: timedate
          timedate (<T>, <tz_offset>)
          timedate (<T>)
          timedate ()

     ‘timedate(<T>, <tz_offset>)’ returns a string representing the time
     <T> in the time zone <tz_offset>.  The string format is ‘YYYY-MM-DD
     HH:MM:SS.NNN[+|-]ZZ:ZZ’ (using as many digits as necessary to
     represent the fractional part) if <T> has a nonzero fractional
     part, or ‘YYYY-MM-DD HH:MM:SS[+|-]ZZ:ZZ’ if its fractional part is
     zero.

     <T> measures time, in seconds, since midnight, January 1, 1900, in
     the GMT time zone.

     <tz_offset> measures the offset of the time zone, in hours, east
     (positive) or west (negative) of GMT. <tz_offset> must be an
     integer, rational, or float between -24 and 24, inclusive.  If
     <tz_offset> is not a multiple of 1/60, it is rounded to the nearest
     multiple of 1/60.

     ‘timedate(<T>)’ is equivalent to ‘timedate(<T>, <tz_offset>)’ with
     <tz_offset> equal to the offset of the local time zone.

     ‘timedate()’ is equivalent to ‘timedate(absolute_real_time())’.
     That is, it returns the current time in the local time zone.

     Example:

     ‘timedate’ with no argument returns a string representing the
     current time and date.

          (%i1) d : timedate ();
          (%o1)                      2010-06-08 04:08:09+01:00
          (%i2) print ("timedate reports current time", d) $
          timedate reports current time 2010-06-08 04:08:09+01:00

     ‘timedate’ with an argument returns a string representing the
     argument.

          (%i1) timedate (0);
          (%o1)                      1900-01-01 01:00:00+01:00
          (%i2) timedate (absolute_real_time () - 7*24*3600);
          (%o2)                      2010-06-01 04:19:51+01:00

     ‘timedate’ with optional timezone offset.

          (%i1) timedate (1000000000, -9.5);
          (%o1)               1931-09-09 16:16:40-09:30

 -- Function: parse_timedate
          parse_timedate (<S>)

     Parses a string <S> representing a date or date and time of day and
     returns the number of seconds since midnight, January 1, 1900 GMT.
     If there is a nonzero fractional part, the value returned is a
     rational number, otherwise, it is an integer.  ‘parse_timedate’
     returns ‘false’ if it cannot parse <S> according to any of the
     allowed formats.

     The string <S> must have one of the following formats, optionally
     followed by a timezone designation:

        • ‘YYYY-MM-DD[ T]hh:mm:ss[,.]nnn’
        • ‘YYYY-MM-DD[ T]hh:mm:ss’
        • ‘YYYY-MM-DD’

     where the fields are year, month, day, hours, minutes, seconds, and
     fraction of a second, and square brackets indicate acceptable
     alternatives.  The fraction may contain one or more digits.

     Except for the fraction of a second, each field must have exactly
     the number of digits indicated: four digits for the year, and two
     for the month, day of the month, hours, minutes, and seconds.

     A timezone designation must have one of the following forms:

        • ‘[+-]hh:mm’
        • ‘[+-]hhmm’
        • ‘[+-]hh’
        • ‘Z’

     where ‘hh’ and ‘mm’ indicate hours and minutes east (‘+’) or west
     (‘-’) of GMT. The timezone may be from +24 hours (inclusive) to -24
     hours (inclusive).

     A literal character ‘Z’ is equivalent to ‘+00:00’ and its variants,
     indicating GMT.

     If no timezone is indicated, the time is assumed to be in the local
     time zone.

     Any leading or trailing whitespace (space, tab, newline, and
     carriage return) is ignored, but any other leading or trailing
     characters cause ‘parse_timedate’ to fail and return ‘false’.

     See also ‘timedate’ and ‘absolute_real_time’.

     Examples:

     Midnight, January 1, 1900, in the local time zone, in each
     acceptable format.  The result is the number of seconds the local
     time zone is ahead (negative result) or behind (positive result)
     GMT. In this example, the local time zone is 8 hours behind GMT.

          (%i1) parse_timedate ("1900-01-01 00:00:00,000");
          (%o1)                         28800
          (%i2) parse_timedate ("1900-01-01 00:00:00.000");
          (%o2)                         28800
          (%i3) parse_timedate ("1900-01-01T00:00:00,000");
          (%o3)                         28800
          (%i4) parse_timedate ("1900-01-01T00:00:00.000");
          (%o4)                         28800
          (%i5) parse_timedate ("1900-01-01 00:00:00");
          (%o5)                         28800
          (%i6) parse_timedate ("1900-01-01T00:00:00");
          (%o6)                         28800
          (%i7) parse_timedate ("1900-01-01");
          (%o7)                         28800

     Midnight, January 1, 1900, GMT, in different indicated time zones.

          (%i1) parse_timedate ("1900-01-01 19:00:00+19:00");
          (%o1)                           0
          (%i2) parse_timedate ("1900-01-01 07:00:00+07:00");
          (%o2)                           0
          (%i3) parse_timedate ("1900-01-01 01:00:00+01:00");
          (%o3)                           0
          (%i4) parse_timedate ("1900-01-01Z");
          (%o4)                           0
          (%i5) parse_timedate ("1899-12-31 21:00:00-03:00");
          (%o5)                           0
          (%i6) parse_timedate ("1899-12-31 13:00:00-11:00");
          (%o6)                           0
          (%i7) parse_timedate ("1899-12-31 08:00:00-16:00");
          (%o7)                           0

 -- Function: encode_time
          encode_time (<year>, <month>, <day>, <hours>, <minutes>,
          <seconds>, <tz_offset>)
          encode_time (<year>, <month>, <day>, <hours>, <minutes>,
          <seconds>)

     Given a time and date specified by <year>, <month>, <day>, <hours>,
     <minutes>, and <seconds>, ‘encode_time’ returns the number of
     seconds (possibly including a fractional part) since midnight,
     January 1, 1900 GMT.

     <year> must be an integer greater than or equal to 1899.  However,
     1899 is allowed only if the resulting encoded time is greater than
     or equal to 0.

     <month> must be an integer from 1 to 12, inclusive.

     <day> must be an integer from 1 to <n>, inclusive, where <n> is the
     number of days in the month specified by <month>.

     <hours> must be an integer from 0 to 23, inclusive.

     <minutes> must be an integer from 0 to 59, inclusive.

     <seconds> must be an integer, rational, or float greater than or
     equal to 0 and less than 60.  When <seconds> is not an integer,
     ‘encode_time’ returns a rational, such that the fractional part of
     the return value is equal to the fractional part of <seconds>.
     Otherwise, <seconds> is an integer, and the return value is
     likewise an integer.

     <tz_offset> measures the offset of the time zone, in hours, east
     (positive) or west (negative) of GMT. <tz_offset> must be an
     integer, rational, or float between -24 and 24, inclusive.  If
     <tz_offset> is not a multiple of 1/3600, it is rounded to the
     nearest multiple of 1/3600.

     If <tz_offset> is not present, the offset of the local time zone is
     assumed.

     See also ‘decode_time’.

     Examples:

          (%i1) encode_time (1900, 1, 1, 0, 0, 0, 0);
          (%o1)                           0
          (%i2) encode_time (1970, 1, 1, 0, 0, 0, 0);
          (%o2)                      2208988800
          (%i3) encode_time (1970, 1, 1, 8, 30, 0, 8.5);
          (%o3)                      2208988800
          (%i4) encode_time (1969, 12, 31, 16, 0, 0, -8);
          (%o4)                      2208988800
          (%i5) encode_time (1969, 12, 31, 16, 0, 1/1000, -8);
                                    2208988800001
          (%o5)                     -------------
                                        1000
          (%i6) % - 2208988800;
                                         1
          (%o6)                         ----
                                        1000

 -- Function: decode_time
          decode_time (<T>, <tz_offset>)
          decode_time (<T>)

     Given the number of seconds (possibly including a fractional part)
     since midnight, January 1, 1900 GMT, returns the date and time as
     represented by a list comprising the year, month, day of the month,
     hours, minutes, seconds, and time zone offset.

     <tz_offset> measures the offset of the time zone, in hours, east
     (positive) or west (negative) of GMT. <tz_offset> must be an
     integer, rational, or float between -24 and 24, inclusive.  If
     <tz_offset> is not a multiple of 1/3600, it is rounded to the
     nearest multiple of 1/3600.

     If <tz_offset> is not present, the offset of the local time zone is
     assumed.

     See also ‘encode_time’.

     Examples:

          (%i1) decode_time (0, 0);
          (%o1)               [1900, 1, 1, 0, 0, 0, 0]
          (%i2) decode_time (0);
          (%o2)             [1899, 12, 31, 16, 0, 0, - 8]
          (%i3) decode_time (2208988800, 9.25);
                                                    37
          (%o3)              [1970, 1, 1, 9, 15, 0, --]
                                                    4
          (%i4) decode_time (2208988800);
          (%o4)             [1969, 12, 31, 16, 0, 0, - 8]
          (%i5) decode_time (2208988800 + 1729/1000, -6);
                                                1729
          (%o5)           [1969, 12, 31, 18, 0, ----, - 6]
                                                1000
          (%i6) decode_time (2208988800 + 1729/1000);
                                                1729
          (%o6)           [1969, 12, 31, 16, 0, ----, - 8]
                                                1000

 -- Function: absolute_real_time ()

     Returns the number of seconds since midnight, January 1, 1900 GMT.
     The return value is an integer.

     See also ‘elapsed_real_time’ and ‘elapsed_run_time’.

     Example:

          (%i1) absolute_real_time ();
          (%o1)                      3385045277
          (%i2) 1900 + absolute_real_time () / (365.25 * 24 * 3600);
          (%o2)                   2007.265612087104

 -- Function: elapsed_real_time ()

     Returns the number of seconds (including fractions of a second)
     since Maxima was most recently started or restarted.  The return
     value is a floating-point number.

     See also ‘absolute_real_time’ and ‘elapsed_run_time’.

     Example:

          (%i1) elapsed_real_time ();
          (%o1)                       2.559324
          (%i2) expand ((a + b)^500)$
          (%i3) elapsed_real_time ();
          (%o3)                       7.552087

 -- Function: elapsed_run_time ()

     Returns an estimate of the number of seconds (including fractions
     of a second) which Maxima has spent in computations since Maxima
     was most recently started or restarted.  The return value is a
     floating-point number.

     See also ‘absolute_real_time’ and ‘elapsed_real_time’.

     Example:

          (%i1) elapsed_run_time ();
          (%o1)                         0.04
          (%i2) expand ((a + b)^500)$
          (%i3) elapsed_run_time ();
          (%o3)                         1.26


File: maxima.info,  Node: Miscellaneous Options,  Next: Rules and Patterns,  Prev: Runtime Environment,  Up: Top

33 Miscellaneous Options
************************

* Menu:

* Introduction to Miscellaneous Options::
* Share::
* Functions and Variables for Miscellaneous Options::


File: maxima.info,  Node: Introduction to Miscellaneous Options,  Next: Share,  Prev: Miscellaneous Options,  Up: Miscellaneous Options

33.1 Introduction to Miscellaneous Options
==========================================

In this section various options are discussed which have a global effect
on the operation of Maxima.  Also various lists such as the list of all
user defined functions, are discussed.


File: maxima.info,  Node: Share,  Next: Functions and Variables for Miscellaneous Options,  Prev: Introduction to Miscellaneous Options,  Up: Miscellaneous Options

33.2 Share
==========

The Maxima "share" directory contains programs and other files of
interest to Maxima users, but not part of the core implementation of
Maxima.  These programs are typically loaded via ‘load’ or
‘setup_autoload’.

   ‘:lisp *maxima-sharedir*’ displays the location of the share
directory within the user's file system.


File: maxima.info,  Node: Functions and Variables for Miscellaneous Options,  Prev: Share,  Up: Miscellaneous Options

33.3 Functions and Variables for Miscellaneous Options
======================================================

 -- System variable: askexp

     When ‘asksign’ is called, ‘askexp’ is the expression ‘asksign’ is
     testing.

     At one time, it was possible for a user to inspect ‘askexp’ by
     entering a Maxima break with control-A.

 -- Option variable: genindex
     Default value: ‘i’

     ‘genindex’ is the alphabetic prefix used to generate the next
     variable of summation when necessary.

 -- Option variable: gensumnum
     Default value: 0

     ‘gensumnum’ is the numeric suffix used to generate the next
     variable of summation.  If it is set to ‘false’ then the index will
     consist only of ‘genindex’ with no numeric suffix.

 -- Function: gensym
          gensym ()
          gensym (<x>)

     ‘gensym()’ creates and returns a fresh symbol.

     The name of the new symbol is the concatenation of a prefix, which
     defaults to "g", and a suffix, which is an integer that defaults to
     the value of an internal counter.

     If <x> is supplied, and is a string, then that string is used as a
     prefix instead of "g" for this call to gensym only.

     If <x> is supplied, and is a nonnegative integer, then that
     integer, instead of the value of the internal counter, is used as
     the suffix for this call to gensym only.

     If and only if no explicit suffix is supplied, the internal counter
     is incremented after it is used.

     Examples:

          (%i1) gensym();
          (%o1)                         g887
          (%i2) gensym("new");
          (%o2)                        new888
          (%i3) gensym(123);
          (%o3)                         g123

 -- Option variable: packagefile
     Default value: ‘false’

     Package designers who use ‘save’ or ‘translate’ to create packages
     (files) for others to use may want to set ‘packagefile: true’ to
     prevent information from being added to Maxima's information-lists
     (e.g.  ‘values’, ‘functions’) except where necessary when the file
     is loaded in.  In this way, the contents of the package will not
     get in the user's way when he adds his own data.  Note that this
     will not solve the problem of possible name conflicts.  Also note
     that the flag simply affects what is output to the package file.
     Setting the flag to ‘true’ is also useful for creating Maxima init
     files.

 -- Function: remvalue
          remvalue (<name_1>, ..., <name_n>)
          remvalue remvalue (all)

     Removes the values of user variables <name_1>, ..., <name_n> (which
     can be subscripted) from the system.

     ‘remvalue (all)’ removes the values of all variables in ‘values’,
     the list of all variables given names by the user (as opposed to
     those which are automatically assigned by Maxima).

     See also ‘values’.

 -- Function: rncombine (<expr>)

     Transforms <expr> by combining all terms of <expr> that have
     identical denominators or denominators that differ from each other
     by numerical factors only.  This is slightly different from the
     behavior of ‘combine’, which collects terms that have identical
     denominators.

     Setting ‘pfeformat: true’ and using ‘combine’ yields results
     similar to those that can be obtained with ‘rncombine’, but
     ‘rncombine’ takes the additional step of cross-multiplying
     numerical denominator factors.  This results in neater forms, and
     the possibility of recognizing some cancellations.

     ‘load("rncomb")’ loads this function.

 -- Function: setup_autoload (<filename>, <function_1>, ...,
          <function_n>)

     Specifies that if any of <function_1>, ..., <function_n> are
     referenced and not yet defined, <filename> is loaded via ‘load’.
     <filename> usually contains definitions for the functions
     specified, although that is not enforced.

     ‘setup_autoload’ does not work for ‘memoizing functions’.

     ‘setup_autoload’ quotes its arguments.

     Example:

          (%i1) legendre_p (1, %pi);
          (%o1)                  legendre_p(1, %pi)
          (%i2) setup_autoload ("specfun.mac", legendre_p, ultraspherical);
          (%o2)                         done
          (%i3) ultraspherical (2, 1/2, %pi);
          Warning - you are redefining the Macsyma function ultraspherical
          Warning - you are redefining the Macsyma function legendre_p
                                      2
                           3 (%pi - 1)
          (%o3)            ------------ + 3 (%pi - 1) + 1
                                2
          (%i4) legendre_p (1, %pi);
          (%o4)                          %pi
          (%i5) legendre_q (1, %pi);
                                        %pi + 1
                                %pi log(-------)
                                        1 - %pi
          (%o5)                 ---------------- - 1
                                       2

 -- Function: tcl_output
          tcl_output (<list>, <i0>, <skip>)
          tcl_output (<list>, <i0>)
          tcl_output ([<list_1>, ..., <list_n>], <i>)

     Prints elements of a list enclosed by curly braces ‘{ }’, suitable
     as part of a program in the Tcl/Tk language.

     ‘tcl_output (<list>, <i0>, <skip>)’ prints <list>, beginning with
     element <i0> and printing elements ‘<i0> + <skip>’, ‘<i0> + 2
     <skip>’, etc.

     ‘tcl_output (<list>, <i0>)’ is equivalent to ‘tcl_output (<list>,
     <i0>, 2)’.

     ‘tcl_output ([<list_1>, ..., <list_n>], <i>)’ prints the <i>'th
     elements of <list_1>, ..., <list_n>.

     Examples:

          (%i1) tcl_output ([1, 2, 3, 4, 5, 6], 1, 3)$

           {1.000000000     4.000000000
           }
          (%i2) tcl_output ([1, 2, 3, 4, 5, 6], 2, 3)$

           {2.000000000     5.000000000
           }
          (%i3) tcl_output ([3/7, 5/9, 11/13, 13/17], 1)$

           {((RAT SIMP) 3 7) ((RAT SIMP) 11 13)
           }
          (%i4) tcl_output ([x1, y1, x2, y2, x3, y3], 2)$

           {$Y1 $Y2 $Y3
           }
          (%i5) tcl_output ([[1, 2, 3], [11, 22, 33]], 1)$

           {SIMP 1.000000000     11.00000000
           }


File: maxima.info,  Node: Rules and Patterns,  Next: Sets,  Prev: Miscellaneous Options,  Up: Top

34 Rules and Patterns
*********************

* Menu:

* Introduction to Rules and Patterns::
* Functions and Variables for Rules and Patterns::


File: maxima.info,  Node: Introduction to Rules and Patterns,  Next: Functions and Variables for Rules and Patterns,  Prev: Rules and Patterns,  Up: Rules and Patterns

34.1 Introduction to Rules and Patterns
=======================================

This section describes user-defined pattern matching and simplification
rules.  There are two groups of functions which implement somewhat
different pattern matching schemes.  In one group are ‘tellsimp’,
‘tellsimpafter’, ‘defmatch’, ‘defrule’, ‘apply1’, ‘applyb1’, and
‘apply2’.  In the other group are ‘let’ and ‘letsimp’.  Both schemes
define patterns in terms of pattern variables declared by
‘matchdeclare’.

   Pattern-matching rules defined by ‘tellsimp’ and ‘tellsimpafter’ are
applied automatically by the Maxima simplifier.  Rules defined by
‘defmatch’, ‘defrule’, and ‘let’ are applied by an explicit function
call.

   There are additional mechanisms for rules applied to polynomials by
‘tellrat’, and for commutative and noncommutative algebra in ‘affine’
package.


File: maxima.info,  Node: Functions and Variables for Rules and Patterns,  Prev: Introduction to Rules and Patterns,  Up: Rules and Patterns

34.2 Functions and Variables for Rules and Patterns
===================================================

 -- Function: apply1 (<expr>, <rule_1>, ..., <rule_n>)

     Repeatedly applies <rule_1> to <expr> until it fails, then
     repeatedly applies the same rule to all subexpressions of <expr>,
     left to right, until <rule_1> has failed on all subexpressions.
     Call the result of transforming <expr> in this manner <expr_2>.
     Then <rule_2> is applied in the same fashion starting at the top of
     <expr_2>.  When <rule_n> fails on the final subexpression, the
     result is returned.

     ‘maxapplydepth’ is the depth of the deepest subexpressions
     processed by ‘apply1’ and ‘apply2’.

     See also ‘applyb1’, ‘apply2’ and ‘let’.

 -- Function: apply2 (<expr>, <rule_1>, ..., <rule_n>)

     If <rule_1> fails on a given subexpression, then <rule_2> is
     repeatedly applied, etc.  Only if all rules fail on a given
     subexpression is the whole set of rules repeatedly applied to the
     next subexpression.  If one of the rules succeeds, then the same
     subexpression is reprocessed, starting with the first rule.

     ‘maxapplydepth’ is the depth of the deepest subexpressions
     processed by ‘apply1’ and ‘apply2’.

     See also ‘apply1’ and ‘let’.

 -- Function: applyb1 (<expr>, <rule_1>, ..., <rule_n>)

     Repeatedly applies <rule_1> to the deepest subexpression of <expr>
     until it fails, then repeatedly applies the same rule one level
     higher (i.e., larger subexpressions), until <rule_1> has failed on
     the top-level expression.  Then <rule_2> is applied in the same
     fashion to the result of <rule_1>.  After <rule_n> has been applied
     to the top-level expression, the result is returned.

     ‘applyb1’ is similar to ‘apply1’ but works from the bottom up
     instead of from the top down.

     ‘maxapplyheight’ is the maximum height which ‘applyb1’ reaches
     before giving up.

     See also ‘apply1’, ‘apply2’ and ‘let’.

 -- Option variable: current_let_rule_package
     Default value: ‘default_let_rule_package’

     ‘current_let_rule_package’ is the name of the rule package that is
     used by functions in the ‘let’ package (‘letsimp’, etc.)  if no
     other rule package is specified.  This variable may be assigned the
     name of any rule package defined via the ‘let’ command.

     If a call such as ‘letsimp (expr, rule_pkg_name)’ is made, the rule
     package ‘rule_pkg_name’ is used for that function call only, and
     the value of ‘current_let_rule_package’ is not changed.

 -- Option variable: default_let_rule_package
     Default value: ‘default_let_rule_package’

     ‘default_let_rule_package’ is the name of the rule package used
     when one is not explicitly set by the user with ‘let’ or by
     changing the value of ‘current_let_rule_package’.

 -- Function: defmatch
          defmatch (<progname>, <pattern>, <x_1>, ..., <x_n>)
          defmatch (<progname>, <pattern>)

     Defines a function ‘<progname>(<expr>, <x_1>, ..., <x_n>)’ which
     tests <expr> to see if it matches <pattern>.

     <pattern> is an expression containing the pattern arguments <x_1>,
     ..., <x_n> (if any) and some pattern variables (if any).  The
     pattern arguments are given explicitly as arguments to ‘defmatch’
     while the pattern variables are declared by the ‘matchdeclare’
     function.  Any variable not declared as a pattern variable in
     ‘matchdeclare’ or as a pattern argument in ‘defmatch’ matches only
     itself.

     The first argument to the created function <progname> is an
     expression to be matched against the pattern and the other
     arguments are the actual arguments which correspond to the dummy
     variables <x_1>, ..., <x_n> in the pattern.

     If the match is successful, <progname> returns a list of equations
     whose left sides are the pattern arguments and pattern variables,
     and whose right sides are the subexpressions which the pattern
     arguments and variables matched.  The pattern variables, but not
     the pattern arguments, are assigned the subexpressions they match.
     If the match fails, <progname> returns ‘false’.

     A literal pattern (that is, a pattern which contains neither
     pattern arguments nor pattern variables) returns ‘true’ if the
     match succeeds.

     See also ‘matchdeclare’, ‘defrule’, ‘tellsimp’ and ‘tellsimpafter’.

     Examples:

     Define a function ‘linearp(expr, x)’ which tests ‘expr’ to see if
     it is of the form ‘a*x + b’ such that ‘a’ and ‘b’ do not contain
     ‘x’ and ‘a’ is nonzero.  This match function matches expressions
     which are linear in any variable, because the pattern argument ‘x’
     is given to ‘defmatch’.

          (%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
                              freeof(x));
          (%o1)                         done
          (%i2) defmatch (linearp, a*x + b, x);
          (%o2)                        linearp
          (%i3) linearp (3*z + (y + 1)*z + y^2, z);
                                   2
          (%o3)              [b = y , a = y + 4, x = z]
          (%i4) a;
          (%o4)                         y + 4
          (%i5) b;
                                          2
          (%o5)                          y
          (%i6) x;
          (%o6)                           x

     Define a function ‘linearp(expr)’ which tests ‘expr’ to see if it
     is of the form ‘a*x + b’ such that ‘a’ and ‘b’ do not contain ‘x’
     and ‘a’ is nonzero.  This match function only matches expressions
     linear in ‘x’, not any other variable, because no pattern argument
     is given to ‘defmatch’.

          (%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
                              freeof(x));
          (%o1)                         done
          (%i2) defmatch (linearp, a*x + b);
          (%o2)                        linearp
          (%i3) linearp (3*z + (y + 1)*z + y^2);
          (%o3)                         false
          (%i4) linearp (3*x + (y + 1)*x + y^2);
                                       2
          (%o4)                  [b = y , a = y + 4]

     Define a function ‘checklimits(expr)’ which tests ‘expr’ to see if
     it is a definite integral.

          (%i1) matchdeclare ([a, f], true);
          (%o1)                         done
          (%i2) constinterval (l, h) := constantp (h - l);
          (%o2)        constinterval(l, h) := constantp(h - l)
          (%i3) matchdeclare (b, constinterval (a));
          (%o3)                         done
          (%i4) matchdeclare (x, atom);
          (%o4)                         done
          (%i5) simp : false;
          (%o5)                         false
          (%i6) defmatch (checklimits, 'integrate (f, x, a, b));
          (%o6)                      checklimits
          (%i7) simp : true;
          (%o7)                         true
          (%i8) 'integrate (sin(t), t, %pi + x, 2*%pi + x);
                                 x + 2 %pi
                                /
                                [
          (%o8)                 I          sin(t) dt
                                ]
                                /
                                 x + %pi
          (%i9) checklimits (%);
          (%o9)    [b = x + 2 %pi, a = x + %pi, x = t, f = sin(t)]

 -- Function: defrule (<rulename>, <pattern>, <replacement>)

     Defines and names a replacement rule for the given pattern.  If the
     rule named <rulename> is applied to an expression (by ‘apply1’,
     ‘applyb1’, or ‘apply2’), every subexpression matching the pattern
     will be replaced by the replacement.  All variables in the
     replacement which have been assigned values by the pattern match
     are assigned those values in the replacement which is then
     simplified.

     The rules themselves can be treated as functions which transform an
     expression by one operation of the pattern match and replacement.
     If the match fails, the rule function returns ‘false’.

 -- Function: disprule
          disprule (<rulename_1>, ..., <rulename_2>)
          disprule (all)

     Display rules with the names <rulename_1>, ..., <rulename_n>, as
     returned by ‘defrule’, ‘tellsimp’, or ‘tellsimpafter’, or a pattern
     defined by ‘defmatch’.  Each rule is displayed with an intermediate
     expression label (‘%t’).

     ‘disprule (all)’ displays all rules.

     ‘disprule’ quotes its arguments.  ‘disprule’ returns the list of
     intermediate expression labels corresponding to the displayed
     rules.

     See also ‘letrules’, which displays rules defined by ‘let’.

     Examples:

          (%i1) tellsimpafter (foo (x, y), bar (x) + baz (y));
          (%o1)                   [foorule1, false]
          (%i2) tellsimpafter (x + y, special_add (x, y));
          (%o2)                   [+rule1, simplus]
          (%i3) defmatch (quux, mumble (x));
          (%o3)                         quux
          (%i4) disprule (foorule1, ?\+rule1, quux);
          (%t4)        foorule1 : foo(x, y) -> baz(y) + bar(x)

          (%t5)          +rule1 : y + x -> special_add(x, y)

          (%t6)                quux : mumble(x) -> []

          (%o6)                    [%t4, %t5, %t6]
          (%i7) ev(%);
          (%o7) [foorule1 : foo(x, y) -> baz(y) + bar(x),
               +rule1 : y + x -> special_add(x, y), quux : mumble(x) -> []]

 -- Function: let
          let (<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>)
          let ([<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>],
          <package_name>)

     Defines a substitution rule for ‘letsimp’ such that <prod> is
     replaced by <repl>.  <prod> is a product of positive or negative
     powers of the following terms:

        • Atoms which ‘letsimp’ will search for literally unless
          previous to calling ‘letsimp’ the ‘matchdeclare’ function is
          used to associate a predicate with the atom.  In this case
          ‘letsimp’ will match the atom to any term of a product
          satisfying the predicate.
        • Kernels such as ‘sin(x)’, ‘n!’, ‘f(x,y)’, etc.  As with atoms
          above ‘letsimp’ will look for a literal match unless
          ‘matchdeclare’ is used to associate a predicate with the
          argument of the kernel.

     A term to a positive power will only match a term having at least
     that power.  A term to a negative power on the other hand will only
     match a term with a power at least as negative.  In the case of
     negative powers in <prod> the switch ‘letrat’ must be set to
     ‘true’.  See also ‘letrat’.

     If a predicate is included in the ‘let’ function followed by a list
     of arguments, a tentative match (i.e.  one that would be accepted
     if the predicate were omitted) is accepted only if ‘predname
     (arg_1', ..., arg_n')’ evaluates to ‘true’ where <arg_i'> is the
     value matched to <arg_i>.  The <arg_i> may be the name of any atom
     or the argument of any kernel appearing in <prod>.  <repl> may be
     any rational expression.  If any of the atoms or arguments from
     <prod> appear in <repl> the appropriate substitutions are made.

     The global flag ‘letrat’ controls the simplification of quotients
     by ‘letsimp’.  When ‘letrat’ is ‘false’, ‘letsimp’ simplifies the
     numerator and denominator of <expr> separately, and does not
     simplify the quotient.  Substitutions such as ‘n!/n’ goes to
     ‘(n-1)!’ then fail.  When ‘letrat’ is ‘true’, then the numerator,
     denominator, and the quotient are simplified in that order.

     These substitution functions allow you to work with several rule
     packages at once.  Each rule package can contain any number of
     ‘let’ rules and is referenced by a user-defined name.  The command
     ‘let ([<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>],
     <package_name>)’ adds the rule <predname> to the rule package
     <package_name>.  The command ‘letsimp (<expr>, <package_name>)’
     applies the rules in <package_name>.  ‘letsimp (<expr>,
     <package_name1>, <package_name2>, ...)’ is equivalent to ‘letsimp
     (<expr>, <package_name1>)’ followed by ‘letsimp (%,
     <package_name2>)’, ...

     ‘current_let_rule_package’ is the name of the rule package that is
     presently being used.  This variable may be assigned the name of
     any rule package defined via the ‘let’ command.  Whenever any of
     the functions comprising the ‘let’ package are called with no
     package name, the package named by ‘current_let_rule_package’ is
     used.  If a call such as ‘letsimp (<expr>, <rule_pkg_name>)’ is
     made, the rule package <rule_pkg_name> is used for that ‘letsimp’
     command only, and ‘current_let_rule_package’ is not changed.  If
     not otherwise specified, ‘current_let_rule_package’ defaults to
     ‘default_let_rule_package’.

          (%i1) matchdeclare ([a, a1, a2], true)$
          (%i2) oneless (x, y) := is (x = y-1)$
          (%i3) let (a1*a2!, a1!, oneless, a2, a1);
          (%o3)         a1 a2! --> a1! where oneless(a2, a1)
          (%i4) letrat: true$
          (%i5) let (a1!/a1, (a1-1)!);
                                  a1!
          (%o5)                   --- --> (a1 - 1)!
                                  a1
          (%i6) letsimp (n*m!*(n-1)!/m);
          (%o6)                      (m - 1)! n!
          (%i7) let (sin(a)^2, 1 - cos(a)^2);
                                  2               2
          (%o7)                sin (a) --> 1 - cos (a)
          (%i8) letsimp (sin(x)^4);
                                  4           2
          (%o8)                cos (x) - 2 cos (x) + 1

 -- Option variable: letrat
     Default value: ‘false’

     When ‘letrat’ is ‘false’, ‘letsimp’ simplifies the numerator and
     denominator of a ratio separately, and does not simplify the
     quotient.

     When ‘letrat’ is ‘true’, the numerator, denominator, and their
     quotient are simplified in that order.

          (%i1) matchdeclare (n, true)$
          (%i2) let (n!/n, (n-1)!);
                                   n!
          (%o2)                    -- --> (n - 1)!
                                   n
          (%i3) letrat: false$
          (%i4) letsimp (a!/a);
                                         a!
          (%o4)                          --
                                         a
          (%i5) letrat: true$
          (%i6) letsimp (a!/a);
          (%o6)                       (a - 1)!

 -- Function: letrules
          letrules ()
          letrules (<package_name>)

     Displays the rules in a rule package.  ‘letrules ()’ displays the
     rules in the current rule package.  ‘letrules (<package_name>)’
     displays the rules in <package_name>.

     The current rule package is named by ‘current_let_rule_package’.
     If not otherwise specified, ‘current_let_rule_package’ defaults to
     ‘default_let_rule_package’.

     See also ‘disprule’, which displays rules defined by ‘tellsimp’ and
     ‘tellsimpafter’.

 -- Function: letsimp
          letsimp (<expr>)
          letsimp (<expr>, <package_name>)
          letsimp (<expr>, <package_name_1>, ..., <package_name_n>)

     Repeatedly applies the substitution rules defined by ‘let’ until no
     further change is made to <expr>.

     ‘letsimp (<expr>)’ uses the rules from ‘current_let_rule_package’.

     ‘letsimp (<expr>, <package_name>)’ uses the rules from
     <package_name> without changing ‘current_let_rule_package’.

     ‘letsimp (<expr>, <package_name_1>, ..., <package_name_n>)’ is
     equivalent to ‘letsimp (<expr>, <package_name_1>)’, followed by
     ‘letsimp (%, <package_name_2>)’, and so on.

     See also ‘let’.  For other ways to do substitutions see also
     ‘subst’, ‘psubst’, ‘at’ and ‘ratsubst’.

          (%i1) e0: e(k) = -(9*y(k))/(5*z)-u(k-1)/(5*z)+(4*y(k))/(5*z^2)
                           +(3*u(k-1))/(5*z^2)+y(k)-(2*u(k-1))/5;
                          9 y(k)    u(k - 1)   4 y(k)   3 u(k - 1)
          (%o1) e(k) = (- ------) - -------- + ------ + ---------- + y(k)
                           5 z        5 z          2          2
                                                5 z        5 z
                                                                 2 u(k - 1)
                                                               - ----------
                                                                     5
          (%i2) matchdeclare(h,any)$
          (%i3) let(u(h)/z,u(h-1));
                                  u(h)
          (%o3)                   ---- --> u(h - 1)
                                   z
          (%i4) let(y(h)/z, y(h-1));
                                  y(h)
          (%o4)                   ---- --> y(h - 1)
                                   z
          (%i5) e1:letsimp(e0);
                          2 u(k - 1)           3 u(k - 3)   4 y(k - 2)
          (%o5) e(k) = (- ----------) + y(k) + ---------- + ----------
                              5                    5            5
                                                 u(k - 2)       9 y(k - 1)
                                            + (- --------) + (- ----------)
                                                    5               5

 -- Option variable: let_rule_packages
     Default value: ‘[default_let_rule_package]’

     ‘let_rule_packages’ is a list of all user-defined let rule packages
     plus the default package ‘default_let_rule_package’.

 -- Function: matchdeclare (<a_1>, <pred_1>, ..., <a_n>, <pred_n>)

     Associates a predicate <pred_k> with a variable or list of
     variables <a_k> so that <a_k> matches expressions for which the
     predicate returns anything other than ‘false’.

     A predicate is the name of a function, or a lambda expression, or a
     function call or lambda call missing the last argument, or ‘true’
     or ‘all’.  Any expression matches ‘true’ or ‘all’.  If the
     predicate is specified as a function call or lambda call, the
     expression to be tested is appended to the list of arguments; the
     arguments are evaluated at the time the match is evaluated.
     Otherwise, the predicate is specified as a function name or lambda
     expression, and the expression to be tested is the sole argument.
     A predicate function need not be defined when ‘matchdeclare’ is
     called; the predicate is not evaluated until a match is attempted.

     A predicate may return a Boolean expression as well as ‘true’ or
     ‘false’.  Boolean expressions are evaluated by ‘is’ within the
     constructed rule function, so it is not necessary to call ‘is’
     within the predicate.

     If an expression satisfies a match predicate, the match variable is
     assigned the expression, except for match variables which are
     operands of addition ‘+’ or multiplication ‘*’.  Only addition and
     multiplication are handled specially; other n-ary operators (both
     built-in and user-defined) are treated like ordinary functions.

     In the case of addition and multiplication, the match variable may
     be assigned a single expression which satisfies the match
     predicate, or a sum or product (respectively) of such expressions.
     Such multiple-term matching is greedy: predicates are evaluated in
     the order in which their associated variables appear in the match
     pattern, and a term which satisfies more than one predicate is
     taken by the first predicate which it satisfies.  Each predicate is
     tested against all operands of the sum or product before the next
     predicate is evaluated.  In addition, if 0 or 1 (respectively)
     satisfies a match predicate, and there are no other terms which
     satisfy the predicate, 0 or 1 is assigned to the match variable
     associated with the predicate.

     The algorithm for processing addition and multiplication patterns
     makes some match results (for example, a pattern in which a "match
     anything" variable appears) dependent on the ordering of terms in
     the match pattern and in the expression to be matched.  However, if
     all match predicates are mutually exclusive, the match result is
     insensitive to ordering, as one match predicate cannot accept terms
     matched by another.

     Calling ‘matchdeclare’ with a variable <a> as an argument changes
     the ‘matchdeclare’ property for <a>, if one was already declared;
     only the most recent ‘matchdeclare’ is in effect when a rule is
     defined.  Later changes to the ‘matchdeclare’ property (via
     ‘matchdeclare’ or ‘remove’) do not affect existing rules.

     ‘propvars (matchdeclare)’ returns the list of all variables for
     which there is a ‘matchdeclare’ property.  ‘printprops (<a>,
     matchdeclare)’ returns the predicate for variable ‘a’.  ‘printprops
     (all, matchdeclare)’ returns the list of predicates for all
     ‘matchdeclare’ variables.  ‘remove (<a>, matchdeclare)’ removes the
     ‘matchdeclare’ property from <a>.

     The functions ‘defmatch’, ‘defrule’, ‘tellsimp’, ‘tellsimpafter’,
     and ‘let’ construct rules which test expressions against patterns.

     ‘matchdeclare’ quotes its arguments.  ‘matchdeclare’ always returns
     ‘done’.

     Examples:

     A predicate is the name of a function, or a lambda expression, or a
     function call or lambda call missing the last argument, or ‘true’
     or ‘all’.

          (%i1) matchdeclare (aa, integerp);
          (%o1)                         done
          (%i2) matchdeclare (bb, lambda ([x], x > 0));
          (%o2)                         done
          (%i3) matchdeclare (cc, freeof (%e, %pi, %i));
          (%o3)                         done
          (%i4) matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728));
          (%o4)                         done
          (%i5) matchdeclare (ee, true);
          (%o5)                         done
          (%i6) matchdeclare (ff, all);
          (%o6)                         done

     If an expression satisfies a match predicate, the match variable is
     assigned the expression.

          (%i1) matchdeclare (aa, integerp, bb, atom);
          (%o1)                         done
          (%i2) defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]);
                              aa
          (%o2)        r1 : bb   -> [integer = aa, atom = bb]
          (%i3) r1 (%pi^8);
          (%o3)               [integer = 8, atom = %pi]

     In the case of addition and multiplication, the match variable may
     be assigned a single expression which satisfies the match
     predicate, or a sum or product (respectively) of such expressions.

          (%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
          (%o1)                         done
          (%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
                         bb]);
          (%o2)  r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
          (%i3) r1 (8 + a*b + sin(x));
          (%o3)     [all atoms = 8, all nonatoms = sin(x) + a b]
          (%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
                         bb]);
          (%o4)   r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
          (%i5) r2 (8 * (a + b) * sin(x));
          (%o5)    [all atoms = 8, all nonatoms = (b + a) sin(x)]

     When matching arguments of ‘+’ and ‘*’, if all match predicates are
     mutually exclusive, the match result is insensitive to ordering, as
     one match predicate cannot accept terms matched by another.

          (%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
          (%o1)                         done
          (%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
                         bb]);
          (%o2)  r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
          (%i3) r1 (8 + a*b + %pi + sin(x) - c + 2^n);
                                                               n
          (%o3) [all atoms = %pi + 8, all nonatoms = sin(x) + 2  - c + a b]
          (%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
                         bb]);
          (%o4)   r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
          (%i5) r2 (8 * (a + b) * %pi * sin(x) / c * 2^n);
                                                          n + 3
                                                 (b + a) 2      sin(x)
          (%o5) [all atoms = %pi, all nonatoms = ---------------------]
                                                           c

     The functions ‘propvars’ and ‘printprops’ return information about
     match variables.

          (%i1) matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp);
          (%o1)                         done
          (%i2) matchdeclare (ff, floatnump, gg, lambda ([x], x > 100));
          (%o2)                         done
          (%i3) propvars (matchdeclare);
          (%o3)             [aa, bb, cc, dd, ee, ff, gg]
          (%i4) printprops (ee, matchdeclare);
          (%o4)                    [integerp(ee)]
          (%i5) printprops (gg, matchdeclare);
          (%o5)              [lambda([x], x > 100, gg)]
          (%i6) printprops (all, matchdeclare);
          (%o6) [lambda([x], x > 100, gg), floatnump(ff), integerp(ee),
                                integerp(dd), atom(cc), atom(bb), atom(aa)]

 -- Option variable: maxapplydepth
     Default value: 10000

     ‘maxapplydepth’ is the maximum depth to which ‘apply1’ and ‘apply2’
     will delve.

 -- Option variable: maxapplyheight
     Default value: 10000

     ‘maxapplyheight’ is the maximum height to which ‘applyb1’ will
     reach before giving up.

 -- Function: remlet
          remlet (<prod>, <name>)
          remlet ()
          remlet (all)
          remlet (all, <name>)

     Deletes the substitution rule, ‘prod --> repl’, most recently
     defined by the ‘let’ function.  If name is supplied the rule is
     deleted from the rule package name.

     ‘remlet()’ and ‘remlet(all)’ delete all substitution rules from the
     current rule package.  If the name of a rule package is supplied,
     e.g.  ‘remlet (all, <name>)’, the rule package <name> is also
     deleted.

     If a substitution is to be changed using the same product, ‘remlet’
     need not be called, just redefine the substitution using the same
     product (literally) with the ‘let’ function and the new replacement
     and/or predicate name.  Should ‘remlet (<prod>)’ now be called the
     original substitution rule is revived.

     See also ‘remrule’, which removes a rule defined by ‘tellsimp’ or
     ‘tellsimpafter’.

 -- Function: remrule
          remrule (<op>, <rulename>)
          remrule (<op>, all)

     Removes rules defined by ‘tellsimp’ or ‘tellsimpafter’.

     ‘remrule (<op>, <rulename>)’ removes the rule with the name
     <rulename> from the operator <op>.  When <op> is a built-in or
     user-defined operator (as defined by ‘infix’, ‘prefix’, etc.), <op>
     and <rulename> must be enclosed in double quote marks.

     ‘remrule (<op>, all)’ removes all rules for the operator <op>.

     See also ‘remlet’, which removes a rule defined by ‘let’.

     Examples:

          (%i1) tellsimp (foo (aa, bb), bb - aa);
          (%o1)                   [foorule1, false]
          (%i2) tellsimpafter (aa + bb, special_add (aa, bb));
          (%o2)                   [+rule1, simplus]
          (%i3) infix ("@@");
          (%o3)                          @@
          (%i4) tellsimp (aa @@ bb, bb/aa);
          (%o4)                   [@@rule1, false]
          (%i5) tellsimpafter (quux (%pi, %e), %pi - %e);
          (%o5)                  [quuxrule1, false]
          (%i6) tellsimpafter (quux (%e, %pi), %pi + %e);
          (%o6)             [quuxrule2, quuxrule1, false]
          (%i7) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e),
                 quux (%e, %pi)];
                                               bb
          (%o7) [bb - aa, special_add(aa, bb), --, %pi - %e, %pi + %e]
                                               aa
          (%i8) remrule (foo, foorule1);
          (%o8)                          foo
          (%i9) remrule ("+", ?\+rule1);
          (%o9)                           +
          (%i10) remrule ("@@", ?\@\@rule1);
          (%o10)                         @@
          (%i11) remrule (quux, all);
          (%o11)                        quux
          (%i12) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e),
                  quux (%e, %pi)];
          (%o12) [foo(aa, bb), bb + aa, aa @@ bb, quux(%pi, %e),
                                                             quux(%e, %pi)]

 -- Function: tellsimp (<pattern>, <replacement>)

     is similar to ‘tellsimpafter’ but places new information before old
     so that it is applied before the built-in simplification rules.

     ‘tellsimp’ is used when it is important to modify the expression
     before the simplifier works on it, for instance if the simplifier
     "knows" something about the expression, but what it returns is not
     to your liking.  If the simplifier "knows" something about the main
     operator of the expression, but is simply not doing enough for you,
     you probably want to use ‘tellsimpafter’.

     The pattern may not be a sum, product, single variable, or number.

     The system variable ‘rules’ is the list of rules defined by
     ‘defrule’, ‘defmatch’, ‘tellsimp’, and ‘tellsimpafter’.

     Examples:

          (%i1) matchdeclare (x, freeof (%i));
          (%o1)                         done
          (%i2) %iargs: false$
          (%i3) tellsimp (sin(%i*x), %i*sinh(x));
          (%o3)                 [sinrule1, simp-%sin]
          (%i4) trigexpand (sin (%i*y + x));
          (%o4)         sin(x) cos(%i y) + %i cos(x) sinh(y)
          (%i5) %iargs:true$
          (%i6) errcatch(0^0);
           0
          0  has been generated
          (%o6)                          []
          (%i7) ev (tellsimp (0^0, 1), simp: false);
          (%o7)                  [^rule1, simpexpt]
          (%i8) 0^0;
          (%o8)                           1
          (%i9) remrule ("^", %th(2)[1]);
          (%o9)                           ^
          (%i10) tellsimp (sin(x)^2, 1 - cos(x)^2);
          (%o10)                 [^rule2, simpexpt]
          (%i11) (1 + sin(x))^2;
                                                2
          (%o11)                    (sin(x) + 1)
          (%i12) expand (%);
                                             2
          (%o12)               2 sin(x) - cos (x) + 2
          (%i13) sin(x)^2;
                                            2
          (%o13)                     1 - cos (x)
          (%i14) kill (rules);
          (%o14)                        done
          (%i15) matchdeclare (a, true);
          (%o15)                        done
          (%i16) tellsimp (sin(a)^2, 1 - cos(a)^2);
          (%o16)                 [^rule3, simpexpt]
          (%i17) sin(y)^2;
                                            2
          (%o17)                     1 - cos (y)

 -- Function: tellsimpafter (<pattern>, <replacement>)

     Defines a simplification rule which the Maxima simplifier applies
     after built-in simplification rules.  <pattern> is an expression,
     comprising pattern variables (declared by ‘matchdeclare’) and other
     atoms and operators, considered literals for the purpose of pattern
     matching.  <replacement> is substituted for an actual expression
     which matches <pattern>; pattern variables in <replacement> are
     assigned the values matched in the actual expression.

     <pattern> may be any nonatomic expression in which the main
     operator is not a pattern variable; the simplification rule is
     associated with the main operator.  The names of functions (with
     one exception, described below), lists, and arrays may appear in
     <pattern> as the main operator only as literals (not pattern
     variables); this rules out expressions such as ‘aa(x)’ and ‘bb[y]’
     as patterns, if ‘aa’ and ‘bb’ are pattern variables.  Names of
     functions, lists, and arrays which are pattern variables may appear
     as operators other than the main operator in <pattern>.

     There is one exception to the above rule concerning names of
     functions.  The name of a subscripted function in an expression
     such as ‘aa[x](y)’ may be a pattern variable, because the main
     operator is not ‘aa’ but rather the Lisp atom ‘mqapply’.  This is a
     consequence of the representation of expressions involving
     subscripted functions.

     Simplification rules are applied after evaluation (if not
     suppressed through quotation or the flag ‘noeval’).  Rules
     established by ‘tellsimpafter’ are applied in the order they were
     defined, and after any built-in rules.  Rules are applied
     bottom-up, that is, applied first to subexpressions before
     application to the whole expression.  It may be necessary to
     repeatedly simplify a result (for example, via the quote-quote
     operator ‘''’ or the flag ‘infeval’) to ensure that all rules are
     applied.

     Pattern variables are treated as local variables in simplification
     rules.  Once a rule is defined, the value of a pattern variable
     does not affect the rule, and is not affected by the rule.  An
     assignment to a pattern variable which results from a successful
     rule match does not affect the current assignment (or lack of it)
     of the pattern variable.  However, as with all atoms in Maxima, the
     properties of pattern variables (as declared by ‘put’ and related
     functions) are global.

     The rule constructed by ‘tellsimpafter’ is named after the main
     operator of <pattern>.  Rules for built-in operators, and
     user-defined operators defined by ‘infix’, ‘prefix’, ‘postfix’,
     ‘matchfix’, and ‘nofix’, have names which are Lisp identifiers.
     Rules for other functions have names which are Maxima identifiers.

     The treatment of noun and verb forms is slightly confused.  If a
     rule is defined for a noun (or verb) form and a rule for the
     corresponding verb (or noun) form already exists, the newly-defined
     rule applies to both forms (noun and verb).  If a rule for the
     corresponding verb (or noun) form does not exist, the newly-defined
     rule applies only to the noun (or verb) form.

     The rule constructed by ‘tellsimpafter’ is an ordinary Lisp
     function.  If the name of the rule is ‘$foorule1’, the construct
     ‘:lisp (trace $foorule1)’ traces the function, and ‘:lisp
     (symbol-function '$foorule1)’ displays its definition.

     ‘tellsimpafter’ quotes its arguments.  ‘tellsimpafter’ returns the
     list of rules for the main operator of <pattern>, including the
     newly established rule.

     See also ‘matchdeclare’, ‘defmatch’, ‘defrule’, ‘tellsimp’, ‘let’,
     ‘kill’, ‘remrule’ and ‘clear_rules’.

     Examples:

     <pattern> may be any nonatomic expression in which the main
     operator is not a pattern variable.

          (%i1) matchdeclare (aa, atom, [ll, mm], listp, xx, true)$
          (%i2) tellsimpafter (sin (ll), map (sin, ll));
          (%o2)                 [sinrule1, simp-%sin]
          (%i3) sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi);
                              1     1     sqrt(3)
          (%o3)              [-, -------, -------, 1, 0]
                              2  sqrt(2)     2
          (%i4) tellsimpafter (ll^mm, map ("^", ll, mm));
          (%o4)                  [^rule1, simpexpt]
          (%i5) [a, b, c]^[1, 2, 3];
                                          2   3
          (%o5)                      [a, b , c ]
          (%i6) tellsimpafter (foo (aa (xx)), aa (foo (xx)));
          (%o6)                   [foorule1, false]
          (%i7) foo (bar (u - v));
          (%o7)                    bar(foo(u - v))

     Rules are applied in the order they were defined.  If two rules can
     match an expression, the rule which was defined first is applied.

          (%i1) matchdeclare (aa, integerp);
          (%o1)                         done
          (%i2) tellsimpafter (foo (aa), bar_1 (aa));
          (%o2)                   [foorule1, false]
          (%i3) tellsimpafter (foo (aa), bar_2 (aa));
          (%o3)              [foorule2, foorule1, false]
          (%i4) foo (42);
          (%o4)                       bar_1(42)

     Pattern variables are treated as local variables in simplification
     rules.  (Compare to ‘defmatch’, which treats pattern variables as
     global variables.)

          (%i1) matchdeclare (aa, integerp, bb, atom);
          (%o1)                         done
          (%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
          (%o2)                   [foorule1, false]
          (%i3) bb: 12345;
          (%o3)                         12345
          (%i4) foo (42, %e);
          (%o4)                 bar(aa = 42, bb = %e)
          (%i5) bb;
          (%o5)                         12345

     As with all atoms, properties of pattern variables are global even
     though values are local.  In this example, an assignment property
     is declared via ‘define_variable’.  This is a property of the atom
     ‘bb’ throughout Maxima.

          (%i1) matchdeclare (aa, integerp, bb, atom);
          (%o1)                         done
          (%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
          (%o2)                   [foorule1, false]
          (%i3) foo (42, %e);
          (%o3)                 bar(aa = 42, bb = %e)
          (%i4) define_variable (bb, true, boolean);
          (%o4)                         true
          (%i5) foo (42, %e);
          translator: bb was declared with mode boolean, but it has value:
                                                                         %e
           -- an error. To debug this try: debugmode(true);

     Rules are named after main operators.  Names of rules for built-in
     and user-defined operators are Lisp identifiers, while names for
     other functions are Maxima identifiers.

          (%i1) tellsimpafter (foo (%pi + %e), 3*%pi);
          (%o1)                   [foorule1, false]
          (%i2) tellsimpafter (foo (%pi * %e), 17*%e);
          (%o2)              [foorule2, foorule1, false]
          (%i3) tellsimpafter (foo (%i ^ %e), -42*%i);
          (%o3)         [foorule3, foorule2, foorule1, false]
          (%i4) tellsimpafter (foo (9) + foo (13), quux (22));
          (%o4)                   [+rule1, simplus]
          (%i5) tellsimpafter (foo (9) * foo (13), blurf (22));
          (%o5)                  [*rule1, simptimes]
          (%i6) tellsimpafter (foo (9) ^ foo (13), mumble (22));
          (%o6)                  [^rule1, simpexpt]
          (%i7) rules;
          (%o7) [foorule1, foorule2, foorule3, +rule1, *rule1, ^rule1]
          (%i8) foorule_name: first (%o1);
          (%o8)                       foorule1
          (%i9) plusrule_name: first (%o4);
          (%o9)                        +rule1
          (%i10) remrule (foo, foorule1);
          (%o10)                         foo
          (%i11) remrule ("^", ?\^rule1);
          (%o11)                          ^
          (%i12) rules;
          (%o12)        [foorule2, foorule3, +rule1, *rule1]

     A worked example: anticommutative multiplication.

          (%i1) gt (i, j) := integerp(j) and i < j;
          (%o1)          gt(i, j) := integerp(j) and (i < j)
          (%i2) matchdeclare (i, integerp, j, gt(i));
          (%o2)                         done
          (%i3) tellsimpafter (s[i]^^2, 1);
          (%o3)                 [^^rule1, simpncexpt]
          (%i4) tellsimpafter (s[i] . s[j], -s[j] . s[i]);
          (%o4)                   [.rule1, simpnct]
          (%i5) s[1] . (s[1] + s[2]);
          (%o5)                    s  . (s  + s )
                                    1     2    1
          (%i6) expand (%);
          (%o6)                      1 - s  . s
                                          2    1
          (%i7) factor (expand (sum (s[i], i, 0, 9)^^5));
          (%o7) 100 (s  + s  + s  + s  + s  + s  + s  + s  + s  + s )
                      9    8    7    6    5    4    3    2    1    0

 -- Function: clear_rules ()

     Executes ‘kill (rules)’ and then resets the next rule number to 1
     for addition ‘+’, multiplication ‘*’, and exponentiation ‘^’.


File: maxima.info,  Node: Sets,  Next: Function Definition,  Prev: Rules and Patterns,  Up: Top

35 Sets
*******

* Menu:

* Introduction to Sets::
* Functions and Variables for Sets::


File: maxima.info,  Node: Introduction to Sets,  Next: Functions and Variables for Sets,  Prev: Sets,  Up: Sets

35.1 Introduction to Sets
=========================

Maxima provides set functions, such as intersection and union, for
finite sets that are defined by explicit enumeration.  Maxima treats
lists and sets as distinct objects.  This feature makes it possible to
work with sets that have members that are either lists or sets.

   In addition to functions for finite sets, Maxima provides some
functions related to combinatorics; these include the Stirling numbers
of the first and second kind, the Bell numbers, multinomial
coefficients, partitions of nonnegative integers, and a few others.
Maxima also defines a Kronecker delta function.

35.1.1 Usage
------------

To construct a set with members ‘a_1, ..., a_n’, write ‘set(a_1, ...,
a_n)’ or ‘{a_1, ..., a_n}’; to construct the empty set, write ‘set()’ or
‘{}’.  In input, ‘set(...)’ and ‘{ ... }’ are equivalent.  Sets are
always displayed with curly braces.

   If a member is listed more than once, simplification eliminates the
redundant member.

     (%i1) set();
     (%o1)                          {}
     (%i2) set(a, b, a);
     (%o2)                        {a, b}
     (%i3) set(a, set(b));
     (%o3)                       {a, {b}}
     (%i4) set(a, [b]);
     (%o4)                       {a, [b]}
     (%i5) {};
     (%o5)                          {}
     (%i6) {a, b, a};
     (%o6)                        {a, b}
     (%i7) {a, {b}};
     (%o7)                       {a, {b}}
     (%i8) {a, [b]};
     (%o8)                       {a, [b]}

   Two would-be elements <x> and <y> are redundant (i.e., considered the
same for the purpose of set construction) if and only if ‘is(<x> = <y>)’
yields ‘true’.  Note that ‘is(equal(<x>, <y>))’ can yield ‘true’ while
‘is(<x> = <y>)’ yields ‘false’; in that case the elements <x> and <y>
are considered distinct.

     (%i1) x: a/c + b/c;
                                   b   a
     (%o1)                         - + -
                                   c   c
     (%i2) y: a/c + b/c;
                                   b   a
     (%o2)                         - + -
                                   c   c
     (%i3) z: (a + b)/c;
                                   b + a
     (%o3)                         -----
                                     c
     (%i4) is (x = y);
     (%o4)                         true
     (%i5) is (y = z);
     (%o5)                         false
     (%i6) is (equal (y, z));
     (%o6)                         true
     (%i7) y - z;
                                b + a   b   a
     (%o7)                    - ----- + - + -
                                  c     c   c
     (%i8) ratsimp (%);
     (%o8)                           0
     (%i9) {x, y, z};
                               b + a  b   a
     (%o9)                    {-----, - + -}
                                 c    c   c

   To construct a set from the elements of a list, use ‘setify’.

     (%i1) setify ([b, a]);
     (%o1)                        {a, b}

   Set members ‘x’ and ‘y’ are equal provided ‘is(x = y)’ evaluates to
‘true’.  Thus ‘rat(x)’ and ‘x’ are equal as set members; consequently,

     (%i1) {x, rat(x)};
     (%o1)                          {x}

   Further, since ‘is((x - 1)*(x + 1) = x^2 - 1)’ evaluates to ‘false’,
‘(x - 1)*(x + 1)’ and ‘x^2 - 1’ are distinct set members; thus

     (%i1) {(x - 1)*(x + 1), x^2 - 1};
                                            2
     (%o1)               {(x - 1) (x + 1), x  - 1}

   To reduce this set to a singleton set, apply ‘rat’ to each set
member:

     (%i1) {(x - 1)*(x + 1), x^2 - 1};
                                            2
     (%o1)               {(x - 1) (x + 1), x  - 1}
     (%i2) map (rat, %);
                                   2
     (%o2)/R/                    {x  - 1}

   To remove redundancies from other sets, you may need to use other
simplification functions.  Here is an example that uses ‘trigsimp’:

     (%i1) {1, cos(x)^2 + sin(x)^2};
                                 2         2
     (%o1)                {1, sin (x) + cos (x)}
     (%i2) map (trigsimp, %);
     (%o2)                          {1}

   A set is simplified when its members are non-redundant and sorted.
The current version of the set functions uses the Maxima function
‘orderlessp’ to order sets; however, future versions of the set
functions might use a different ordering function.

   Some operations on sets, such as substitution, automatically force a
re-simplification; for example,

     (%i1) s: {a, b, c}$
     (%i2) subst (c=a, s);
     (%o2)                        {a, b}
     (%i3) subst ([a=x, b=x, c=x], s);
     (%o3)                          {x}
     (%i4) map (lambda ([x], x^2), set (-1, 0, 1));
     (%o4)                        {0, 1}

   Maxima treats lists and sets as distinct objects; functions such as
‘union’ and ‘intersection’ complain if any argument is not a set.  If
you need to apply a set function to a list, use the ‘setify’ function to
convert it to a set.  Thus

     (%i1) union ([1, 2], {a, b});
     Function union expects a set, instead found [1,2]
      -- an error.  Quitting.  To debug this try debugmode(true);
     (%i2) union (setify ([1, 2]), {a, b});
     (%o2)                     {1, 2, a, b}

   To extract all set elements of a set ‘s’ that satisfy a predicate
‘f’, use ‘subset(s, f)’.  (A predicate is a boolean-valued function.)
For example, to find the equations in a given set that do not depend on
a variable ‘z’, use

     (%i1) subset ({x + y + z, x - y + 4, x + y - 5},
                                         lambda ([e], freeof (z, e)));
     (%o1)               {- y + x + 4, y + x - 5}

   The section *note Functions and Variables for Sets:: has a complete
list of the set functions in Maxima.

35.1.2 Set Member Iteration
---------------------------

There two ways to to iterate over set members.  One way is the use
‘map’; for example:

     (%i1) map (f, {a, b, c});
     (%o1)                  {f(a), f(b), f(c)}

   The other way is to use ‘for <x> in <s> do’

     (%i1) s: {a, b, c};
     (%o1)                       {a, b, c}
     (%i2) for si in s do print (concat (si, 1));
     a1
     b1
     c1
     (%o2)                         done

   The Maxima functions ‘first’ and ‘rest’ work correctly on sets.
Applied to a set, ‘first’ returns the first displayed element of a set;
which element that is may be implementation-dependent.  If ‘s’ is a set,
then ‘rest(s)’ is equivalent to ‘disjoin(first(s), s)’.  Currently,
there are other Maxima functions that work correctly on sets.  In future
versions of the set functions, ‘first’ and ‘rest’ may function
differently or not at all.

   Maxima's ‘orderless’ and ‘ordergreat’ mechanisms are incompatible
with the set functions.  If you need to use either ‘orderless’ or
‘ordergreat’, call those functions before constructing any sets, and do
not call ‘unorder’.

35.1.3 Authors
--------------

Stavros Macrakis of Cambridge, Massachusetts and Barton Willis of the
University of Nebraska at Kearney (UNK) wrote the Maxima set functions
and their documentation.


File: maxima.info,  Node: Functions and Variables for Sets,  Prev: Introduction to Sets,  Up: Sets

35.2 Functions and Variables for Sets
=====================================

 -- Function: adjoin (<x>, <a>)

     Returns the union of the set <a> with ‘{<x>}’.

     ‘adjoin’ complains if <a> is not a literal set.

     ‘adjoin(<x>, <a>)’ and ‘union(set(<x>), <a>)’ are equivalent;
     however, ‘adjoin’ may be somewhat faster than ‘union’.

     See also ‘disjoin’.

     Examples:

          (%i1) adjoin (c, {a, b});
          (%o1)                       {a, b, c}
          (%i2) adjoin (a, {a, b});
          (%o2)                        {a, b}

 -- Function: belln (<n>)

     Represents the n-th Bell number.  ‘belln(n)’ is the number of
     partitions of a set with <n> members.

     For nonnegative integers <n>, ‘belln(<n>)’ simplifies to the n-th
     Bell number.  ‘belln’ does not simplify for any other arguments.

     ‘belln’ distributes over equations, lists, matrices, and sets.

     Examples:

     ‘belln’ applied to nonnegative integers.

          (%i1) makelist (belln (i), i, 0, 6);
          (%o1)               [1, 1, 2, 5, 15, 52, 203]
          (%i2) is (cardinality (set_partitions ({})) = belln (0));
          (%o2)                         true
          (%i3) is (cardinality (set_partitions ({1, 2, 3, 4, 5, 6})) =
                                 belln (6));
          (%o3)                         true

     ‘belln’ applied to arguments which are not nonnegative integers.

          (%i1) [belln (x), belln (sqrt(3)), belln (-9)];
          (%o1)        [belln(x), belln(sqrt(3)), belln(- 9)]

 -- Function: cardinality (<a>)

     Returns the number of distinct elements of the set <a>.

     ‘cardinality’ ignores redundant elements even when simplification
     is disabled.

     Examples:

          (%i1) cardinality ({});
          (%o1)                           0
          (%i2) cardinality ({a, a, b, c});
          (%o2)                           3
          (%i3) simp : false;
          (%o3)                         false
          (%i4) cardinality ({a, a, b, c});
          (%o4)                           3

 -- Function: cartesian_product (<b_1>, ... , <b_n>)
     Returns a set of lists of the form ‘[<x_1>, ..., <x_n>]’, where
     <x_1>, ..., <x_n> are elements of the sets <b_1>, ...  , <b_n>,
     respectively.

     ‘cartesian_product’ complains if any argument is not a literal set.

     See also ‘cartesian_product_list’.

     Examples:

          (%i1) cartesian_product ({0, 1});
          (%o1)                      {[0], [1]}
          (%i2) cartesian_product ({0, 1}, {0, 1});
          (%o2)           {[0, 0], [0, 1], [1, 0], [1, 1]}
          (%i3) cartesian_product ({x}, {y}, {z});
          (%o3)                      {[x, y, z]}
          (%i4) cartesian_product ({x}, {-1, 0, 1});
          (%o4)              {[x, - 1], [x, 0], [x, 1]}

 -- Function: cartesian_product_list (<b_1>, ... , <b_n>)
     Returns a list of lists of the form ‘[<x_1>, ..., <x_n>]’, where
     <x_1>, ..., <x_n> are elements of the lists <b_1>, ...  , <b_n>,
     respectively, comprising all possible combinations of the elements
     of <b_1>, ...  , <b_n>.

     The list returned by ‘cartesian_product_list’ is equivalent to the
     following recursive definition.  Let <L> be the list returned by
     ‘cartesian_product_list(<b_2>, ..., <b_n>)’.  Then
     ‘cartesian_product_list(<b_1>, <b_2>, ..., <b_n>)’ (i.e., <b_1> in
     addition to <b_2>, ..., <b_n>) returns a list comprising each
     element of <L> appended to the first element of <b_1>, each element
     of <L> appended to the second element of <b_1>, each element of <L>
     appended to the third element of <b_1>, etc.  The order of the list
     returned by ‘cartesian_product_list(<b_1>, <b_2>, ..., <b_n>)’ may
     therefore be summarized by saying the lesser indices (1, 2, 3, ...)
     vary more slowly than the greater indices.

     The list returned by ‘cartesian_product_list’ contains duplicate
     elements if any argument <b_1>, ..., <b_n> contains duplicates.  In
     this respect, ‘cartesian_product_list’ differs from
     ‘cartesian_product’, which returns no duplicates.  Also, the
     ordering of the list returned ‘cartesian_product_list’ is
     determined by the order of the elements of <b_1>, ..., <b_n>.
     Again, this differs from ‘cartesian_product’, which returns a set
     (with order determined by ‘orderlessp’).

     The length of the list returned by ‘cartesian_product_list’ is
     equal to the product of the lengths of the arguments <b_1>, ...,
     <b_n>.

     See also ‘cartesian_product’.

     ‘cartesian_product_list’ complains if any argument is not a list.

     Examples:

     ‘cartesian_product_list’ returns a list of lists comprising all
     possible combinations.

          (%i1) cartesian_product_list ([0, 1]);
          (%o1)                      [[0], [1]]
          (%i2) cartesian_product_list ([0, 1], [0, 1]);
          (%o2)           [[0, 0], [0, 1], [1, 0], [1, 1]]
          (%i3) cartesian_product_list ([x], [y], [z]);
          (%o3)                      [[x, y, z]]
          (%i4) cartesian_product_list ([x], [-1, 0, 1]);
          (%o4)              [[x, - 1], [x, 0], [x, 1]]
          (%i5) cartesian_product_list ([a, h, e], [c, b, 4]);
          (%o5) [[a, c], [a, b], [a, 4], [h, c], [h, b], [h, 4], [e, c],
                                                            [e, b], [e, 4]]

     The order of the list returned by ‘cartesian_product_list’ may be
     summarized by saying the lesser indices vary more slowly than the
     greater indices.

          (%i1) cartesian_product_list ([1, 2, 3], [a, b], [i, ii]);
          (%o1) [[1, a, i], [1, a, ii], [1, b, i], [1, b, ii], [2, a, i],
          [2, a, ii], [2, b, i], [2, b, ii], [3, a, i], [3, a, ii],
          [3, b, i], [3, b, ii]]

     The list returned by ‘cartesian_product_list’ contains duplicate
     elements if any argument contains duplicates.

          (%i1) cartesian_product_list ([e, h], [3, 7, 3]);
          (%o1)   [[e, 3], [e, 7], [e, 3], [h, 3], [h, 7], [h, 3]]

     The length of the list returned by ‘cartesian_product_list’ is
     equal to the product of the lengths of the arguments.

          (%i1) foo: cartesian_product_list ([1, 1, 2, 2, 3], [h, z, h]);
          (%o1) [[1, h], [1, z], [1, h], [1, h], [1, z], [1, h], [2, h],
            [2, z], [2, h], [2, h], [2, z], [2, h], [3, h], [3, z], [3, h]]
          (%i2) is (length (foo) = 5*3);
          (%o2)                         true

 -- Function: disjoin (<x>, <a>)
     Returns the set <a> without the member <x>.  If <x> is not a member
     of <a>, return <a> unchanged.

     ‘disjoin’ complains if <a> is not a literal set.

     ‘disjoin(<x>, <a>)’, ‘delete(<x>, <a>)’, and ‘setdifference(<a>,
     set(<x>))’ are all equivalent.  Of these, ‘disjoin’ is generally
     faster than the others.

     Examples:

          (%i1) disjoin (a, {a, b, c, d});
          (%o1)                       {b, c, d}
          (%i2) disjoin (a + b, {5, z, a + b, %pi});
          (%o2)                      {5, %pi, z}
          (%i3) disjoin (a - b, {5, z, a + b, %pi});
          (%o3)                  {5, %pi, b + a, z}

 -- Function: disjointp (<a>, <b>)
     Returns ‘true’ if and only if the sets <a> and <b> are disjoint.

     ‘disjointp’ complains if either <a> or <b> is not a literal set.

     Examples:

          (%i1) disjointp ({a, b, c}, {1, 2, 3});
          (%o1)                         true
          (%i2) disjointp ({a, b, 3}, {1, 2, 3});
          (%o2)                         false

 -- Function: divisors (<n>)

     Represents the set of divisors of <n>.

     ‘divisors(<n>)’ simplifies to a set of integers when <n> is a
     nonzero integer.  The set of divisors includes the members 1 and
     <n>.  The divisors of a negative integer are the divisors of its
     absolute value.

     ‘divisors’ distributes over equations, lists, matrices, and sets.

     Examples:

     We can verify that 28 is a perfect number: the sum of its divisors
     (except for itself) is 28.

          (%i1) s: divisors(28);
          (%o1)                 {1, 2, 4, 7, 14, 28}
          (%i2) lreduce ("+", args(s)) - 28;
          (%o2)                          28

     ‘divisors’ is a simplifying function.  Substituting 8 for ‘a’ in
     ‘divisors(a)’ yields the divisors without reevaluating
     ‘divisors(8)’.

          (%i1) divisors (a);
          (%o1)                      divisors(a)
          (%i2) subst (8, a, %);
          (%o2)                     {1, 2, 4, 8}

     ‘divisors’ distributes over equations, lists, matrices, and sets.

          (%i1) divisors (a = b);
          (%o1)               divisors(a) = divisors(b)
          (%i2) divisors ([a, b, c]);
          (%o2)        [divisors(a), divisors(b), divisors(c)]
          (%i3) divisors (matrix ([a, b], [c, d]));
                            [ divisors(a)  divisors(b) ]
          (%o3)             [                          ]
                            [ divisors(c)  divisors(d) ]
          (%i4) divisors ({a, b, c});
          (%o4)        {divisors(a), divisors(b), divisors(c)}

 -- Function: elementp (<x>, <a>)
     Returns ‘true’ if and only if <x> is a member of the set <a>.

     ‘elementp’ complains if <a> is not a literal set.

     Examples:

          (%i1) elementp (sin(1), {sin(1), sin(2), sin(3)});
          (%o1)                         true
          (%i2) elementp (sin(1), {cos(1), cos(2), cos(3)});
          (%o2)                         false

 -- Function: emptyp (<a>)
     Return ‘true’ if and only if <a> is the empty set or the empty
     list.

     Examples:

          (%i1) map (emptyp, [{}, []]);
          (%o1)                     [true, true]
          (%i2) map (emptyp, [a + b, {{}}, %pi]);
          (%o2)                 [false, false, false]

 -- Function: equiv_classes (<s>, <F>)
     Returns a set of the equivalence classes of the set <s> with
     respect to the equivalence relation <F>.

     <F> is a function of two variables defined on the Cartesian product
     of <s> with <s>.  The return value of <F> is either ‘true’ or
     ‘false’, or an expression <expr> such that ‘is(<expr>)’ is either
     ‘true’ or ‘false’.

     When <F> is not an equivalence relation, ‘equiv_classes’ accepts it
     without complaint, but the result is generally incorrect in that
     case.

     Examples:

     The equivalence relation is a lambda expression which returns
     ‘true’ or ‘false’.

          (%i1) equiv_classes ({1, 1.0, 2, 2.0, 3, 3.0},
                                  lambda ([x, y], is (equal (x, y))));
          (%o1)            {{1, 1.0}, {2, 2.0}, {3, 3.0}}

     The equivalence relation is the name of a relational function which
     ‘is’ evaluates to ‘true’ or ‘false’.

          (%i1) equiv_classes ({1, 1.0, 2, 2.0, 3, 3.0}, equal);
          (%o1)            {{1, 1.0}, {2, 2.0}, {3, 3.0}}

     The equivalence classes are numbers which differ by a multiple of
     3.

          (%i1) equiv_classes ({1, 2, 3, 4, 5, 6, 7},
                               lambda ([x, y], remainder (x - y, 3) = 0));
          (%o1)              {{1, 4, 7}, {2, 5}, {3, 6}}

 -- Function: every
          every (<f>, <s>)
          every (<f>, <L_1>, ..., <L_n>)

     Returns ‘true’ if the predicate <f> is ‘true’ for all given
     arguments.

     Given one set as the second argument, ‘every(<f>, <s>)’ returns
     ‘true’ if ‘is(<f>(<a_i>))’ returns ‘true’ for all <a_i> in <s>.
     ‘every’ may or may not evaluate <f> for all <a_i> in <s>.  Since
     sets are unordered, ‘every’ may evaluate ‘<f>(<a_i>)’ in any order.

     Given one or more lists as arguments, ‘every(<f>, <L_1>, ...,
     <L_n>)’ returns ‘true’ if ‘is(<f>(<x_1>, ..., <x_n>))’ returns
     ‘true’ for all <x_1>, ..., <x_n> in <L_1>, ..., <L_n>,
     respectively.  ‘every’ may or may not evaluate <f> for every
     combination <x_1>, ..., <x_n>.  ‘every’ evaluates lists in the
     order of increasing index.

     Given an empty set ‘{}’ or empty lists ‘[]’ as arguments, ‘every’
     returns ‘true’.

     When the global flag ‘maperror’ is ‘true’, all lists <L_1>, ...,
     <L_n> must have equal lengths.  When ‘maperror’ is ‘false’, list
     arguments are effectively truncated to the length of the shortest
     list.

     Return values of the predicate <f> which evaluate (via ‘is’) to
     something other than ‘true’ or ‘false’ are governed by the global
     flag ‘prederror’.  When ‘prederror’ is ‘true’, such values are
     treated as ‘false’, and the return value from ‘every’ is ‘false’.
     When ‘prederror’ is ‘false’, such values are treated as ‘unknown’,
     and the return value from ‘every’ is ‘unknown’.

     Examples:

     ‘every’ applied to a single set.  The predicate is a function of
     one argument.

          (%i1) every (integerp, {1, 2, 3, 4, 5, 6});
          (%o1)                         true
          (%i2) every (atom, {1, 2, sin(3), 4, 5 + y, 6});
          (%o2)                         false

     ‘every’ applied to two lists.  The predicate is a function of two
     arguments.

          (%i1) every ("=", [a, b, c], [a, b, c]);
          (%o1)                         true
          (%i2) every ("#", [a, b, c], [a, b, c]);
          (%o2)                         false

     Return values of the predicate <f> which evaluate to something
     other than ‘true’ or ‘false’ are governed by the global flag
     ‘prederror’.

          (%i1) prederror : false;
          (%o1)                         false
          (%i2) map (lambda ([a, b], is (a < b)), [x, y, z],
                             [x^2, y^2, z^2]);
          (%o2)              [unknown, unknown, unknown]
          (%i3) every ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o3)                        unknown
          (%i4) prederror : true;
          (%o4)                         true
          (%i5) every ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o5)                         false

 -- Function: extremal_subset
          extremal_subset (<s>, <f>, max)
          extremal_subset (<s>, <f>, min)

     Returns the subset of <s> for which the function <f> takes on
     maximum or minimum values.

     ‘extremal_subset(<s>, <f>, max)’ returns the subset of the set or
     list <s> for which the real-valued function <f> takes on its
     maximum value.

     ‘extremal_subset(<s>, <f>, min)’ returns the subset of the set or
     list <s> for which the real-valued function <f> takes on its
     minimum value.

     Examples:

          (%i1) extremal_subset ({-2, -1, 0, 1, 2}, abs, max);
          (%o1)                       {- 2, 2}
          (%i2) extremal_subset ({sqrt(2), 1.57, %pi/2}, sin, min);
          (%o2)                       {sqrt(2)}

 -- Function: flatten (<expr>)

     Collects arguments of subexpressions which have the same operator
     as <expr> and constructs an expression from these collected
     arguments.

     Subexpressions in which the operator is different from the main
     operator of ‘expr’ are copied without modification, even if they,
     in turn, contain some subexpressions in which the operator is the
     same as for ‘expr’.

     It may be possible for ‘flatten’ to construct expressions in which
     the number of arguments differs from the declared arguments for an
     operator; this may provoke an error message from the simplifier or
     evaluator.  ‘flatten’ does not try to detect such situations.

     Expressions with special representations, for example, canonical
     rational expressions (CRE), cannot be flattened; in such cases,
     ‘flatten’ returns its argument unchanged.

     Examples:

     Applied to a list, ‘flatten’ gathers all list elements that are
     lists.

          (%i1) flatten ([a, b, [c, [d, e], f], [[g, h]], i, j]);
          (%o1)            [a, b, c, d, e, f, g, h, i, j]

     Applied to a set, ‘flatten’ gathers all members of set elements
     that are sets.

          (%i1) flatten ({a, {b}, {{c}}});
          (%o1)                       {a, b, c}
          (%i2) flatten ({a, {[a], {a}}});
          (%o2)                       {a, [a]}

     ‘flatten’ is similar to the effect of declaring the main operator
     n-ary.  However, ‘flatten’ has no effect on subexpressions which
     have an operator different from the main operator, while an n-ary
     declaration affects those.

          (%i1) expr: flatten (f (g (f (f (x)))));
          (%o1)                     f(g(f(f(x))))
          (%i2) declare (f, nary);
          (%o2)                         done
          (%i3) ev (expr);
          (%o3)                      f(g(f(x)))

     ‘flatten’ treats subscripted functions the same as any other
     operator.

          (%i1) flatten (f[5] (f[5] (x, y), z));
          (%o1)                      f (x, y, z)
                                      5

     It may be possible for ‘flatten’ to construct expressions in which
     the number of arguments differs from the declared arguments for an
     operator;

          (%i1) 'mod (5, 'mod (7, 4));
          (%o1)                   mod(5, mod(7, 4))
          (%i2) flatten (%);
          (%o2)                     mod(5, 7, 4)
          (%i3) ''%, nouns;
          Wrong number of arguments to mod
           -- an error.  Quitting.  To debug this try debugmode(true);

 -- Function: full_listify (<a>)
     Replaces every set operator in <a> by a list operator, and returns
     the result.  ‘full_listify’ replaces set operators in nested
     subexpressions, even if the main operator is not ‘set’.

     ‘listify’ replaces only the main operator.

     Examples:

          (%i1) full_listify ({a, b, {c, {d, e, f}, g}});
          (%o1)               [a, b, [c, [d, e, f], g]]
          (%i2) full_listify (F (G ({a, b, H({c, d, e})})));
          (%o2)              F(G([a, b, H([c, d, e])]))

 -- Function: fullsetify (<a>)
     When <a> is a list, replaces the list operator with a set operator,
     and applies ‘fullsetify’ to each member which is a set.  When <a>
     is not a list, it is returned unchanged.

     ‘setify’ replaces only the main operator.

     Examples:

     In line ‘(%o2)’, the argument of ‘f’ isn't converted to a set
     because the main operator of ‘f([b])’ isn't a list.

          (%i1) fullsetify ([a, [a]]);
          (%o1)                       {a, {a}}
          (%i2) fullsetify ([a, f([b])]);
          (%o2)                      {a, f([b])}

 -- Function: identity (<x>)

     Returns <x> for any argument <x>.

     Examples:

     ‘identity’ may be used as a predicate when the arguments are
     already Boolean values.

          (%i1) every (identity, [true, true]);
          (%o1)                         true

 -- Function: integer_partitions
          integer_partitions (<n>)
          integer_partitions (<n>, <len>)

     Returns integer partitions of <n>, that is, lists of integers which
     sum to <n>.

     ‘integer_partitions(<n>)’ returns the set of all partitions of the
     integer <n>.  Each partition is a list sorted from greatest to
     least.

     ‘integer_partitions(<n>, <len>)’ returns all partitions that have
     length <len> or less; in this case, zeros are appended to each
     partition with fewer than <len> terms to make each partition have
     exactly <len> terms.  Each partition is a list sorted from greatest
     to least.

     A list [a_1, ..., a_m] is a partition of a nonnegative integer n
     when (1) each a_i is a nonzero integer, and (2) a_1 + ... + a_m =
     n. Thus 0 has no partitions.

     Examples:

          (%i1) integer_partitions (3);
          (%o1)               {[1, 1, 1], [2, 1], [3]}
          (%i2) s: integer_partitions (25)$
          (%i3) cardinality (s);
          (%o3)                         1958
          (%i4) map (lambda ([x], apply ("+", x)), s);
          (%o4)                         {25}
          (%i5) integer_partitions (5, 3);
          (%o5) {[2, 2, 1], [3, 1, 1], [3, 2, 0], [4, 1, 0], [5, 0, 0]}
          (%i6) integer_partitions (5, 2);
          (%o6)               {[3, 2], [4, 1], [5, 0]}

     To find all partitions that satisfy a condition, use the function
     ‘subset’; here is an example that finds all partitions of 10 that
     consist of prime numbers.

          (%i1) s: integer_partitions (10)$
          (%i2) cardinality (s);
          (%o2)                          42
          (%i3) xprimep(x) := integerp(x) and (x > 1) and primep(x)$
          (%i4) subset (s, lambda ([x], every (xprimep, x)));
          (%o4) {[2, 2, 2, 2, 2], [3, 3, 2, 2], [5, 3, 2], [5, 5], [7, 3]}

 -- Function: intersect (<a_1>, ..., <a_n>)

     ‘intersect’ is the same as ‘intersection’, which see.

 -- Function: intersection (<a_1>, ..., <a_n>)
     Returns a set containing the elements that are common to the sets
     <a_1> through <a_n>.

     ‘intersection’ complains if any argument is not a literal set.

     Examples:

          (%i1) S_1 : {a, b, c, d};
          (%o1)                     {a, b, c, d}
          (%i2) S_2 : {d, e, f, g};
          (%o2)                     {d, e, f, g}
          (%i3) S_3 : {c, d, e, f};
          (%o3)                     {c, d, e, f}
          (%i4) S_4 : {u, v, w};
          (%o4)                       {u, v, w}
          (%i5) intersection (S_1, S_2);
          (%o5)                          {d}
          (%i6) intersection (S_2, S_3);
          (%o6)                       {d, e, f}
          (%i7) intersection (S_1, S_2, S_3);
          (%o7)                          {d}
          (%i8) intersection (S_1, S_2, S_3, S_4);
          (%o8)                          {}

 -- Function: kron_delta (<x1>, <x2>, ..., <xp>)

     Represents the Kronecker delta function.

     ‘kron_delta’ simplifies to 1 when <xi> and <yj> are equal for all
     pairs of arguments, and it simplifies to 0 when <xi> and <yj> are
     not equal for some pair of arguments.  Equality is determined using
     ‘is(equal(xi,xj))’ and inequality by ‘is(notequal(xi,xj))’.  For
     exactly one argument, ‘kron_delta’ signals an error.

     Examples:

          (%i1) kron_delta(a,a);
          (%o1)                                  1
          (%i2) kron_delta(a,b,a,b);
          (%o2)                          kron_delta(a, b)
          (%i3) kron_delta(a,a,b,a+1);
          (%o3)                                  0
          (%i4) assume(equal(x,y));
          (%o4)                            [equal(x, y)]
          (%i5) kron_delta(x,y);
          (%o5)                                  1

 -- Function: listify (<a>)

     Returns a list containing the members of <a> when <a> is a set.
     Otherwise, ‘listify’ returns <a>.

     ‘full_listify’ replaces all set operators in <a> by list operators.

     Examples:

          (%i1) listify ({a, b, c, d});
          (%o1)                     [a, b, c, d]
          (%i2) listify (F ({a, b, c, d}));
          (%o2)                    F({a, b, c, d})

 -- Function: makeset (<expr>, <x>, <s>)

     Returns a set with members generated from the expression <expr>,
     where <x> is a list of variables in <expr>, and <s> is a set or
     list of lists.  To generate each set member, <expr> is evaluated
     with the variables <x> bound in parallel to a member of <s>.

     Each member of <s> must have the same length as <x>.  The list of
     variables <x> must be a list of symbols, without subscripts.  Even
     if there is only one symbol, <x> must be a list of one element, and
     each member of <s> must be a list of one element.

     See also ‘makelist’.

     Examples:

          (%i1) makeset (i/j, [i, j], [[1, a], [2, b], [3, c], [4, d]]);
                                     1  2  3  4
          (%o1)                     {-, -, -, -}
                                     a  b  c  d
          (%i2) S : {x, y, z}$
          (%i3) S3 : cartesian_product (S, S, S);
          (%o3) {[x, x, x], [x, x, y], [x, x, z], [x, y, x], [x, y, y],
          [x, y, z], [x, z, x], [x, z, y], [x, z, z], [y, x, x],
          [y, x, y], [y, x, z], [y, y, x], [y, y, y], [y, y, z],
          [y, z, x], [y, z, y], [y, z, z], [z, x, x], [z, x, y],
          [z, x, z], [z, y, x], [z, y, y], [z, y, z], [z, z, x],
          [z, z, y], [z, z, z]}
          (%i4) makeset (i + j + k, [i, j, k], S3);
          (%o4) {3 x, 3 y, y + 2 x, 2 y + x, 3 z, z + 2 x, z + y + x,
                                                 z + 2 y, 2 z + x, 2 z + y}
          (%i5) makeset (sin(x), [x], {[1], [2], [3]});
          (%o5)               {sin(1), sin(2), sin(3)}

 -- Function: moebius (<n>)

     Represents the Moebius function.

     When <n> is product of k distinct primes, ‘moebius(<n>)’ simplifies
     to (-1)^k; when <n> = 1, it simplifies to 1; and it simplifies to 0
     for all other positive integers.

     ‘moebius’ distributes over equations, lists, matrices, and sets.

     Examples:

          (%i1) moebius (1);
          (%o1)                           1
          (%i2) moebius (2 * 3 * 5);
          (%o2)                          - 1
          (%i3) moebius (11 * 17 * 29 * 31);
          (%o3)                           1
          (%i4) moebius (2^32);
          (%o4)                           0
          (%i5) moebius (n);
          (%o5)                      moebius(n)
          (%i6) moebius (n = 12);
          (%o6)                    moebius(n) = 0
          (%i7) moebius ([11, 11 * 13, 11 * 13 * 15]);
          (%o7)                      [- 1, 1, 1]
          (%i8) moebius (matrix ([11, 12], [13, 14]));
                                     [ - 1  0 ]
          (%o8)                      [        ]
                                     [ - 1  1 ]
          (%i9) moebius ({21, 22, 23, 24});
          (%o9)                      {- 1, 0, 1}

 -- Function: multinomial_coeff
          multinomial_coeff (<a_1>, ..., <a_n>)
          multinomial_coeff ()

     Returns the multinomial coefficient.

     When each <a_k> is a nonnegative integer, the multinomial
     coefficient gives the number of ways of placing ‘<a_1> + ... +
     <a_n>’ distinct objects into n boxes with <a_k> elements in the
     k'th box.  In general, ‘multinomial_coeff (<a_1>, ..., <a_n>)’
     evaluates to ‘(<a_1> + ... + <a_n>)!/(<a_1>! ... <a_n>!)’.

     ‘multinomial_coeff()’ (with no arguments) evaluates to 1.

     ‘minfactorial’ may be able to simplify the value returned by
     ‘multinomial_coeff’.

     Examples:

          (%i1) multinomial_coeff (1, 2, x);
                                      (x + 3)!
          (%o1)                       --------
                                        2 x!
          (%i2) minfactorial (%);
                               (x + 1) (x + 2) (x + 3)
          (%o2)                -----------------------
                                          2
          (%i3) multinomial_coeff (-6, 2);
                                       (- 4)!
          (%o3)                       --------
                                      2 (- 6)!
          (%i4) minfactorial (%);
          (%o4)                          10

 -- Function: num_distinct_partitions
          num_distinct_partitions (<n>)
          num_distinct_partitions (<n>, list)

     Returns the number of distinct integer partitions of <n> when <n>
     is a nonnegative integer.  Otherwise, ‘num_distinct_partitions’
     returns a noun expression.

     ‘num_distinct_partitions(<n>, list)’ returns a list of the number
     of distinct partitions of 1, 2, 3, ..., <n>.

     A distinct partition of <n> is a list of distinct positive integers
     k_1, ..., k_m such that <n> = k_1 + ... + k_m.

     Examples:

          (%i1) num_distinct_partitions (12);
          (%o1)                          15
          (%i2) num_distinct_partitions (12, list);
          (%o2)      [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 15]
          (%i3) num_distinct_partitions (n);
          (%o3)              num_distinct_partitions(n)

 -- Function: num_partitions
          num_partitions (<n>)
          num_partitions (<n>, list)

     Returns the number of integer partitions of <n> when <n> is a
     nonnegative integer.  Otherwise, ‘num_partitions’ returns a noun
     expression.

     ‘num_partitions(<n>, list)’ returns a list of the number of integer
     partitions of 1, 2, 3, ..., <n>.

     For a nonnegative integer <n>, ‘num_partitions(<n>)’ is equal to
     ‘cardinality(integer_partitions(<n>))’; however, ‘num_partitions’
     does not actually construct the set of partitions, so it is much
     faster.

     Examples:

          (%i1) num_partitions (5) = cardinality (integer_partitions (5));
          (%o1)                         7 = 7
          (%i2) num_partitions (8, list);
          (%o2)            [1, 1, 2, 3, 5, 7, 11, 15, 22]
          (%i3) num_partitions (n);
          (%o3)                   num_partitions(n)

 -- Function: partition_set (<a>, <f>)

     Partitions the set <a> according to the predicate <f>.

     ‘partition_set’ returns a list of two sets.  The first set
     comprises the elements of <a> for which <f> evaluates to ‘false’,
     and the second comprises any other elements of <a>.
     ‘partition_set’ does not apply ‘is’ to the return value of <f>.

     ‘partition_set’ complains if <a> is not a literal set.

     See also ‘subset’.

     Examples:

          (%i1) partition_set ({2, 7, 1, 8, 2, 8}, evenp);
          (%o1)                   [{1, 7}, {2, 8}]
          (%i2) partition_set ({x, rat(y), rat(y) + z, 1},
                               lambda ([x], ratp(x)));
          (%o2)/R/              [{1, x}, {y, y + z}]

 -- Function: permutations (<a>)

     Returns a set of all distinct permutations of the members of the
     list or set <a>.  Each permutation is a list, not a set.

     When <a> is a list, duplicate members of <a> are included in the
     permutations.

     ‘permutations’ complains if <a> is not a literal list or set.

     See also ‘random_permutation’.

     Examples:

          (%i1) permutations ([a, a]);
          (%o1)                       {[a, a]}
          (%i2) permutations ([a, a, b]);
          (%o2)           {[a, a, b], [a, b, a], [b, a, a]}

 -- Function: powerset
          powerset (<a>)
          powerset (<a>, <n>)

     Returns the set of all subsets of <a>, or a subset of that set.

     ‘powerset(<a>)’ returns the set of all subsets of the set <a>.
     ‘powerset(<a>)’ has ‘2^cardinality(<a>)’ members.

     ‘powerset(<a>, <n>)’ returns the set of all subsets of <a> that
     have cardinality <n>.

     ‘powerset’ complains if <a> is not a literal set, or if <n> is not
     a nonnegative integer.

     Examples:

          (%i1) powerset ({a, b, c});
          (%o1) {{}, {a}, {a, b}, {a, b, c}, {a, c}, {b}, {b, c}, {c}}
          (%i2) powerset ({w, x, y, z}, 4);
          (%o2)                    {{w, x, y, z}}
          (%i3) powerset ({w, x, y, z}, 3);
          (%o3)     {{w, x, y}, {w, x, z}, {w, y, z}, {x, y, z}}
          (%i4) powerset ({w, x, y, z}, 2);
          (%o4)   {{w, x}, {w, y}, {w, z}, {x, y}, {x, z}, {y, z}}
          (%i5) powerset ({w, x, y, z}, 1);
          (%o5)                 {{w}, {x}, {y}, {z}}
          (%i6) powerset ({w, x, y, z}, 0);
          (%o6)                         {{}}

 -- Function: random_permutation (<a>)

     Returns a random permutation of the set or list <a>, as constructed
     by the Knuth shuffle algorithm.

     The return value is a new list, which is distinct from the argument
     even if all elements happen to be the same.  However, the elements
     of the argument are not copied.

     Examples:

          (%i1) random_permutation ([a, b, c, 1, 2, 3]);
          (%o1)                  [c, 1, 2, 3, a, b]
          (%i2) random_permutation ([a, b, c, 1, 2, 3]);
          (%o2)                  [b, 3, 1, c, a, 2]
          (%i3) random_permutation ({x + 1, y + 2, z + 3});
          (%o3)                 [y + 2, z + 3, x + 1]
          (%i4) random_permutation ({x + 1, y + 2, z + 3});
          (%o4)                 [x + 1, y + 2, z + 3]

 -- Function: setdifference (<a>, <b>)

     Returns a set containing the elements in the set <a> that are not
     in the set <b>.

     ‘setdifference’ complains if either <a> or <b> is not a literal
     set.

     Examples:

          (%i1) S_1 : {a, b, c, x, y, z};
          (%o1)                  {a, b, c, x, y, z}
          (%i2) S_2 : {aa, bb, c, x, y, zz};
          (%o2)                 {aa, bb, c, x, y, zz}
          (%i3) setdifference (S_1, S_2);
          (%o3)                       {a, b, z}
          (%i4) setdifference (S_2, S_1);
          (%o4)                     {aa, bb, zz}
          (%i5) setdifference (S_1, S_1);
          (%o5)                          {}
          (%i6) setdifference (S_1, {});
          (%o6)                  {a, b, c, x, y, z}
          (%i7) setdifference ({}, S_1);
          (%o7)                          {}

 -- Function: setequalp (<a>, <b>)

     Returns ‘true’ if sets <a> and <b> have the same number of elements
     and ‘is(<x> = <y>)’ is ‘true’ for ‘x’ in the elements of <a> and
     ‘y’ in the elements of <b>, considered in the order determined by
     ‘listify’.  Otherwise, ‘setequalp’ returns ‘false’.

     Examples:

          (%i1) setequalp ({1, 2, 3}, {1, 2, 3});
          (%o1)                         true
          (%i2) setequalp ({a, b, c}, {1, 2, 3});
          (%o2)                         false
          (%i3) setequalp ({x^2 - y^2}, {(x + y) * (x - y)});
          (%o3)                         false

 -- Function: setify (<a>)

     Constructs a set from the elements of the list <a>.  Duplicate
     elements of the list <a> are deleted and the elements are sorted
     according to the predicate ‘orderlessp’.

     ‘setify’ complains if <a> is not a literal list.

     Examples:

          (%i1) setify ([1, 2, 3, a, b, c]);
          (%o1)                  {1, 2, 3, a, b, c}
          (%i2) setify ([a, b, c, a, b, c]);
          (%o2)                       {a, b, c}
          (%i3) setify ([7, 13, 11, 1, 3, 9, 5]);
          (%o3)                {1, 3, 5, 7, 9, 11, 13}

 -- Function: setp (<a>)

     Returns ‘true’ if and only if <a> is a Maxima set.

     ‘setp’ returns ‘true’ for unsimplified sets (that is, sets with
     redundant members) as well as simplified sets.

     ‘setp’ is equivalent to the Maxima function ‘setp(a) := not atom(a)
     and op(a) = 'set’.

     Examples:

          (%i1) simp : false;
          (%o1)                         false
          (%i2) {a, a, a};
          (%o2)                       {a, a, a}
          (%i3) setp (%);
          (%o3)                         true

 -- Function: set_partitions
          set_partitions (<a>)
          set_partitions (<a>, <n>)

     Returns the set of all partitions of <a>, or a subset of that set.

     ‘set_partitions(<a>, <n>)’ returns a set of all decompositions of
     <a> into <n> nonempty disjoint subsets.

     ‘set_partitions(<a>)’ returns the set of all partitions.

     ‘stirling2’ returns the cardinality of the set of partitions of a
     set.

     A set of sets P is a partition of a set S when

       1. each member of P is a nonempty set,
       2. distinct members of P are disjoint,
       3. the union of the members of P equals S.

     Examples:

     The empty set is a partition of itself, the conditions 1 and 2
     being vacuously true.

          (%i1) set_partitions ({});
          (%o1)                         {{}}

     The cardinality of the set of partitions of a set can be found
     using ‘stirling2’.

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) cardinality(p) = stirling2 (6, 3);
          (%o3)                        90 = 90

     Each member of ‘p’ should have <n> = 3 members; let's check.

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) map (cardinality, p);
          (%o3)                          {3}

     Finally, for each member of ‘p’, the union of its members should
     equal ‘s’; again let's check.

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) map (lambda ([x], apply (union, listify (x))), p);
          (%o3)                 {{0, 1, 2, 3, 4, 5}}

 -- Function: some
          some (<f>, <a>)
          some (<f>, <L_1>, ..., <L_n>)

     Returns ‘true’ if the predicate <f> is ‘true’ for one or more given
     arguments.

     Given one set as the second argument, ‘some(<f>, <s>)’ returns
     ‘true’ if ‘is(<f>(<a_i>))’ returns ‘true’ for one or more <a_i> in
     <s>.  ‘some’ may or may not evaluate <f> for all <a_i> in <s>.
     Since sets are unordered, ‘some’ may evaluate ‘<f>(<a_i>)’ in any
     order.

     Given one or more lists as arguments, ‘some(<f>, <L_1>, ...,
     <L_n>)’ returns ‘true’ if ‘is(<f>(<x_1>, ..., <x_n>))’ returns
     ‘true’ for one or more <x_1>, ..., <x_n> in <L_1>, ..., <L_n>,
     respectively.  ‘some’ may or may not evaluate <f> for some
     combinations <x_1>, ..., <x_n>.  ‘some’ evaluates lists in the
     order of increasing index.

     Given an empty set ‘{}’ or empty lists ‘[]’ as arguments, ‘some’
     returns ‘false’.

     When the global flag ‘maperror’ is ‘true’, all lists <L_1>, ...,
     <L_n> must have equal lengths.  When ‘maperror’ is ‘false’, list
     arguments are effectively truncated to the length of the shortest
     list.

     Return values of the predicate <f> which evaluate (via ‘is’) to
     something other than ‘true’ or ‘false’ are governed by the global
     flag ‘prederror’.  When ‘prederror’ is ‘true’, such values are
     treated as ‘false’.  When ‘prederror’ is ‘false’, such values are
     treated as ‘unknown’.

     Examples:

     ‘some’ applied to a single set.  The predicate is a function of one
     argument.

          (%i1) some (integerp, {1, 2, 3, 4, 5, 6});
          (%o1)                         true
          (%i2) some (atom, {1, 2, sin(3), 4, 5 + y, 6});
          (%o2)                         true

     ‘some’ applied to two lists.  The predicate is a function of two
     arguments.

          (%i1) some ("=", [a, b, c], [a, b, c]);
          (%o1)                         true
          (%i2) some ("#", [a, b, c], [a, b, c]);
          (%o2)                         false

     Return values of the predicate <f> which evaluate to something
     other than ‘true’ or ‘false’ are governed by the global flag
     ‘prederror’.

          (%i1) prederror : false;
          (%o1)                         false
          (%i2) map (lambda ([a, b], is (a < b)), [x, y, z],
                     [x^2, y^2, z^2]);
          (%o2)              [unknown, unknown, unknown]
          (%i3) some ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o3)                        unknown
          (%i4) some ("<", [x, y, z], [x^2, y^2, z + 1]);
          (%o4)                         true
          (%i5) prederror : true;
          (%o5)                         true
          (%i6) some ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o6)                         false
          (%i7) some ("<", [x, y, z], [x^2, y^2, z + 1]);
          (%o7)                         true

 -- Function: stirling1 (<n>, <m>)

     Represents the Stirling number of the first kind.

     When <n> and <m> are nonnegative integers, the magnitude of
     ‘stirling1 (<n>, <m>)’ is the number of permutations of a set with
     <n> members that have <m> cycles.

     ‘stirling1’ is a simplifying function.  Maxima knows the following
     identities:

       1. stirling1(1,k) = kron_delta(1,k), k >= 0,(see
          <https://dlmf.nist.gov/26.8.E2>)
       2. stirling1(n,n) = 1, n >= 0 (see
          <https://dlmf.nist.gov/26.8.E1>)
       3. stirling1(n,n-1) = -binomial(n,2), n >= 1, (see
          <https://dlmf.nist.gov/26.8.E16>)
       4. stirling1(n,0) = kron_delta(n,0), n >=0 (see
          <https://dlmf.nist.gov/26.8.E14> and
          <https://dlmf.nist.gov/26.8.E1>)
       5. stirling1(n,1) =(-1)^(n-1) (n-1)!, n >= 1 (see
          <https://dlmf.nist.gov/26.8.E14>)
       6. stirling1(n,k) = 0, n >= 0 and k > n.

     These identities are applied when the arguments are literal
     integers or symbols declared as integers, and the first argument is
     nonnegative.  ‘stirling1’ does not simplify for non-integer
     arguments.

     Examples:

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling1 (n, n);
          (%o3)                           1

 -- Function: stirling2 (<n>, <m>)

     Represents the Stirling number of the second kind.

     When <n> and <m> are nonnegative integers, ‘stirling2 (<n>, <m>)’
     is the number of ways a set with cardinality <n> can be partitioned
     into <m> disjoint subsets.

     ‘stirling2’ is a simplifying function.  Maxima knows the following
     identities.

       1. stirling2(n,0) = 1, n >= 1 (see
          <https://dlmf.nist.gov/26.8.E17> and stirling2(0,0) = 1)
       2. stirling2(n,n) = 1, n >= 0, (see
          <https://dlmf.nist.gov/26.8.E4>)
       3. stirling2(n,1) = 1, n >= 1, (see
          <https://dlmf.nist.gov/26.8.E17> and stirling2(0,1) = 0)
       4. stirling2(n,2) = 2^(n-1) -1, n >= 1, (see
          <https://dlmf.nist.gov/26.8.E17>)
       5. stirling2(n,n-1) = binomial(n,2), n>= 1 (see
          <https://dlmf.nist.gov/26.8.E16>)
       6. stirling2(n,k) = 0, n >= 0 and k > n.

     These identities are applied when the arguments are literal
     integers or symbols declared as integers, and the first argument is
     nonnegative.  ‘stirling2’ does not simplify for non-integer
     arguments.

     Examples:

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling2 (n, n);
          (%o3)                           1

     ‘stirling2’ does not simplify for non-integer arguments.

          (%i1) stirling2 (%pi, %pi);
          (%o1)                  stirling2(%pi, %pi)

 -- Function: subset (<a>, <f>)

     Returns the subset of the set <a> that satisfies the predicate <f>.

     ‘subset’ returns a set which comprises the elements of <a> for
     which <f> returns anything other than ‘false’.  ‘subset’ does not
     apply ‘is’ to the return value of <f>.

     ‘subset’ complains if <a> is not a literal set.

     See also ‘partition_set’.

     Examples:

          (%i1) subset ({1, 2, x, x + y, z, x + y + z}, atom);
          (%o1)                     {1, 2, x, z}
          (%i2) subset ({1, 2, 7, 8, 9, 14}, evenp);
          (%o2)                      {2, 8, 14}

 -- Function: subsetp (<a>, <b>)

     Returns ‘true’ if and only if the set <a> is a subset of <b>.

     ‘subsetp’ complains if either <a> or <b> is not a literal set.

     Examples:

          (%i1) subsetp ({1, 2, 3}, {a, 1, b, 2, c, 3});
          (%o1)                         true
          (%i2) subsetp ({a, 1, b, 2, c, 3}, {1, 2, 3});
          (%o2)                         false

 -- Function: symmdifference (<a_1>, ..., <a_n>)

     Returns the symmetric difference of sets <a_1>, ..., <a_n>.

     Given two arguments, ‘symmdifference (<a>, <b>)’ is the same as
     ‘union (setdifference (<a>, <b>), setdifference (<b>, <a>))’.

     ‘symmdifference’ complains if any argument is not a literal set.

     Examples:

          (%i1) S_1 : {a, b, c};
          (%o1)                       {a, b, c}
          (%i2) S_2 : {1, b, c};
          (%o2)                       {1, b, c}
          (%i3) S_3 : {a, b, z};
          (%o3)                       {a, b, z}
          (%i4) symmdifference ();
          (%o4)                          {}
          (%i5) symmdifference (S_1);
          (%o5)                       {a, b, c}
          (%i6) symmdifference (S_1, S_2);
          (%o6)                        {1, a}
          (%i7) symmdifference (S_1, S_2, S_3);
          (%o7)                        {1, b, z}
          (%i8) symmdifference ({}, S_1, S_2, S_3);
          (%o8)                        {1,b, z}

 -- Function: union (<a_1>, ..., <a_n>)
     Returns the union of the sets <a_1> through <a_n>.

     ‘union()’ (with no arguments) returns the empty set.

     ‘union’ complains if any argument is not a literal set.

     Examples:

          (%i1) S_1 : {a, b, c + d, %e};
          (%o1)                   {%e, a, b, d + c}
          (%i2) S_2 : {%pi, %i, %e, c + d};
          (%o2)                 {%e, %i, %pi, d + c}
          (%i3) S_3 : {17, 29, 1729, %pi, %i};
          (%o3)                {17, 29, 1729, %i, %pi}
          (%i4) union ();
          (%o4)                          {}
          (%i5) union (S_1);
          (%o5)                   {%e, a, b, d + c}
          (%i6) union (S_1, S_2);
          (%o6)              {%e, %i, %pi, a, b, d + c}
          (%i7) union (S_1, S_2, S_3);
          (%o7)       {17, 29, 1729, %e, %i, %pi, a, b, d + c}
          (%i8) union ({}, S_1, S_2, S_3);
          (%o8)       {17, 29, 1729, %e, %i, %pi, a, b, d + c}


File: maxima.info,  Node: Function Definition,  Next: Program Flow,  Prev: Sets,  Up: Top

36 Function Definition
**********************

* Menu:

* Introduction to Function Definition::
* Function::
* Macros::
* Functions and Variables for Function Definition::


File: maxima.info,  Node: Introduction to Function Definition,  Next: Function,  Prev: Function Definition,  Up: Function Definition

36.1 Introduction to Function Definition
========================================


File: maxima.info,  Node: Function,  Next: Macros,  Prev: Introduction to Function Definition,  Up: Function Definition

36.2 Function
=============

36.2.1 Ordinary functions
-------------------------

To define a function in Maxima you use the ‘:=’ operator.  E.g.

     f(x) := sin(x)

defines a function ‘f’.  Anonymous functions may also be created using
‘lambda’.  For example

     lambda ([i, j], ...)

can be used instead of ‘f’ where

     f(i,j) := block ([], ...);
     map (lambda ([i], i+1), l)

would return a list with 1 added to each term.

   You may also define a function with a variable number of arguments,
by having a final argument which is assigned to a list of the extra
arguments:

     (%i1) f ([u]) := u;
     (%o1)                      f([u]) := u
     (%i2) f (1, 2, 3, 4);
     (%o2)                     [1, 2, 3, 4]
     (%i3) f (a, b, [u]) := [a, b, u];
     (%o3)               f(a, b, [u]) := [a, b, u]
     (%i4) f (1, 2, 3, 4, 5, 6);
     (%o4)                 [1, 2, [3, 4, 5, 6]]

   The right hand side of a function is an expression.  Thus if you want
a sequence of expressions, you do

     f(x) := (expr1, expr2, ...., exprn);

   and the value of <exprn> is what is returned by the function.

   If you wish to make a ‘return’ from some expression inside the
function then you must use ‘block’ and ‘return’.

     block ([], expr1, ..., if (a > 10) then return(a), ..., exprn)

   is itself an expression, and so could take the place of the right
hand side of a function definition.  Here it may happen that the return
happens earlier than the last expression.

   The first ‘[]’ in the block, may contain a list of variables and
variable assignments, such as ‘[a: 3, b, c: []]’, which would cause the
three variables ‘a’,‘b’,and ‘c’ to not refer to their global values, but
rather have these special values for as long as the code executes inside
the ‘block’, or inside functions called from inside the ‘block’.  This
is called dynamic binding, since the variables last from the start of
the block to the time it exits.  Once you return from the ‘block’, or
throw out of it, the old values (if any) of the variables will be
restored.  It is certainly a good idea to protect your variables in this
way.  Note that the assignments in the block variables, are done in
parallel.  This means, that if you had used ‘c: a’ in the above, the
value of ‘c’ would have been the value of ‘a’ at the time you just
entered the block, but before ‘a’ was bound.  Thus doing something like

     block ([a: a], expr1, ... a: a+3, ..., exprn)

   will protect the external value of ‘a’ from being altered, but would
let you access what that value was.  Thus the right hand side of the
assignments, is evaluated in the entering context, before any binding
occurs.  Using just ‘block ([x], ...)’ would cause the ‘x’ to have
itself as value, just as if it would have if you entered a fresh Maxima
session.

   The actual arguments to a function are treated in exactly same way as
the variables in a block.  Thus in

     f(x) := (expr1, ..., exprn);

   and

     f(1);

   we would have a similar context for evaluation of the expressions as
if we had done

     block ([x: 1], expr1, ..., exprn)

   Inside functions, when the right hand side of a definition, may be
computed at runtime, it is useful to use ‘define’ and possibly ‘buildq’.

36.2.2 Memoizing Functions
--------------------------

A memoizing function caches the result the first time it is called with
a given argument, and returns the stored value, without recomputing it,
when that same argument is given.  Memoizing functions are often called
array function and are in fact handled like arrays in many ways:

   The names of memoizing functions are appended to the global list
‘arrays’ (not the global list ‘functions’).  ‘arrayinfo’ returns the
list of arguments for which there are stored values, and ‘listarray’
returns the stored values.  ‘dispfun’ and ‘fundef’ return the array
function definition.

   ‘arraymake’ constructs an array function call, analogous to ‘funmake’
for ordinary functions.  ‘arrayapply’ applies an array function to its
arguments, analogous to ‘apply’ for ordinary functions.  There is
nothing exactly analogous to ‘map’ for array functions, although
‘map(lambda([<x>], <a>[<x>]), <L>)’ or ‘makelist(<a>[<x>], <x>, <L>)’,
where <L> is a list, are not too far off the mark.

   ‘remarray’ removes an array function definition (including any stored
function values), analogous to ‘remfunction’ for ordinary functions.

   ‘kill(<a>[<x>])’ removes the value of the array function <a> stored
for the argument <x>; the next time <a> is called with argument <x>, the
function value is recomputed.  However, there is no way to remove all of
the stored values at once, except for ‘kill(<a>)’ or ‘remarray(<a>)’,
which also remove the function definition.

   Examples

   If evaluating the function needs much time and only a limited number
of points is ever evaluated (which means not much time is spent looking
up results in a long list of cached results) Memoizing functions can
speed up calculations considerably.
     (%i1) showtime:true$
     Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes.
     (%i2) a[x]:=float(sum(sin(x*t),t,1,10000));
     Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes.
     (%o2)        a  := float(sum(sin(x t), t, 1, 10000))
                   x
     (%i3) a[1];
     Evaluation took 5.1250 seconds (5.1260 elapsed) using 775.250 MB.
     (%o3)                   1.633891021792447
     (%i4) a[1];
     Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes.
     (%o4)                   1.633891021792447

   As the memoizing function is only evaluated once for each input value
changes in variables the memoizing function uses are not considered for
values that are already cached:
     (%i1) a[x]:=b*x;
     (%o1)                       a  := b x
                                  x
     (%i2) b:1;
     (%o2)                           1
     (%i3) a[2];
     (%o3)                           2
     (%i4) b:2;
     (%o4)                           2
     (%i5) a[1];
     (%o5)                           2
     (%i6) a[2];
     (%o6)                           2


File: maxima.info,  Node: Macros,  Next: Functions and Variables for Function Definition,  Prev: Function,  Up: Function Definition

36.3 Macros
===========

 -- Function: buildq (<L>, <expr>)

     Substitutes variables named by the list <L> into the expression
     <expr>, in parallel, without evaluating <expr>.  The resulting
     expression is simplified, but not evaluated, after ‘buildq’ carries
     out the substitution.

     The elements of <L> are symbols or assignment expressions
     ‘<symbol>: <value>’, evaluated in parallel.  That is, the binding
     of a variable on the right-hand side of an assignment is the
     binding of that variable in the context from which ‘buildq’ was
     called, not the binding of that variable in the variable list <L>.
     If some variable in <L> is not given an explicit assignment, its
     binding in ‘buildq’ is the same as in the context from which
     ‘buildq’ was called.

     Then the variables named by <L> are substituted into <expr> in
     parallel.  That is, the substitution for every variable is
     determined before any substitution is made, so the substitution for
     one variable has no effect on any other.

     If any variable <x> appears as ‘splice (<x>)’ in <expr>, then <x>
     must be bound to a list, and the list is spliced (interpolated)
     into <expr> instead of substituted.

     Any variables in <expr> not appearing in <L> are carried into the
     result verbatim, even if they have bindings in the context from
     which ‘buildq’ was called.

     Examples

     ‘a’ is explicitly bound to ‘x’, while ‘b’ has the same binding
     (namely 29) as in the calling context, and ‘c’ is carried through
     verbatim.  The resulting expression is not evaluated until the
     explicit evaluation ‘''%’.

          (%i1) (a: 17, b: 29, c: 1729)$
          (%i2) buildq ([a: x, b], a + b + c);
          (%o2)                      x + c + 29
          (%i3) ''%;
          (%o3)                       x + 1758

     ‘e’ is bound to a list, which appears as such in the arguments of
     ‘foo’, and interpolated into the arguments of ‘bar’.

          (%i1) buildq ([e: [a, b, c]], foo (x, e, y));
          (%o1)                 foo(x, [a, b, c], y)
          (%i2) buildq ([e: [a, b, c]], bar (x, splice (e), y));
          (%o2)                  bar(x, a, b, c, y)

     The result is simplified after substitution.  If simplification
     were applied before substitution, these two results would be the
     same.

          (%i1) buildq ([e: [a, b, c]], splice (e) + splice (e));
          (%o1)                    2 c + 2 b + 2 a
          (%i2) buildq ([e: [a, b, c]], 2 * splice (e));
          (%o2)                        2 a b c

     The variables in <L> are bound in parallel; if bound sequentially,
     the first result would be ‘foo (b, b)’.  Substitutions are carried
     out in parallel; compare the second result with the result of
     ‘subst’, which carries out substitutions sequentially.

          (%i1) buildq ([a: b, b: a], foo (a, b));
          (%o1)                       foo(b, a)
          (%i2) buildq ([u: v, v: w, w: x, x: y, y: z, z: u],
                        bar (u, v, w, x, y, z));
          (%o2)                 bar(v, w, x, y, z, u)
          (%i3) subst ([u=v, v=w, w=x, x=y, y=z, z=u],
                       bar (u, v, w, x, y, z));
          (%o3)                 bar(u, u, u, u, u, u)

     Construct a list of equations with some variables or expressions on
     the left-hand side and their values on the right-hand side.
     ‘macroexpand’ shows the expression returned by ‘show_values’.

          (%i1) show_values ([L]) ::= buildq ([L], map ("=", 'L, L));
          (%o1)   show_values([L]) ::= buildq([L], map("=", 'L, L))
          (%i2) (a: 17, b: 29, c: 1729)$
          (%i3) show_values (a, b, c - a - b);
          (%o3)          [a = 17, b = 29, c - b - a = 1683]
          (%i4) macroexpand (show_values (a, b, c - a - b));
          (%o4)    map(=, '([a, b, c - b - a]), [a, b, c - b - a])

     Given a function of several arguments, create another function for
     which some of the arguments are fixed.

          (%i1) curry (f, [a]) :=
                  buildq ([f, a], lambda ([[x]], apply (f, append (a, x))))$
          (%i2) by3 : curry ("*", 3);
          (%o2)        lambda([[x]], apply(*, append([3], x)))
          (%i3) by3 (a + b);
          (%o3)                       3 (b + a)

 -- Function: macroexpand (<expr>)

     Returns the macro expansion of <expr> without evaluating it, when
     ‘expr’ is a macro function call.  Otherwise, ‘macroexpand’ returns
     <expr>.

     If the expansion of <expr> yields another macro function call, that
     macro function call is also expanded.

     ‘macroexpand’ quotes its argument.  However, if the expansion of a
     macro function call has side effects, those side effects are
     executed.

     See also ‘::=’, ‘macros’, and ‘macroexpand1’..

     Examples

          (%i1) g (x) ::= x / 99;
                                              x
          (%o1)                      g(x) ::= --
                                              99
          (%i2) h (x) ::= buildq ([x], g (x - a));
          (%o2)            h(x) ::= buildq([x], g(x - a))
          (%i3) a: 1234;
          (%o3)                         1234
          (%i4) macroexpand (h (y));
                                        y - a
          (%o4)                         -----
                                         99
          (%i5) h (y);
                                      y - 1234
          (%o5)                       --------
                                         99

 -- Function: macroexpand1 (<expr>)

     Returns the macro expansion of <expr> without evaluating it, when
     ‘expr’ is a macro function call.  Otherwise, ‘macroexpand1’ returns
     <expr>.

     ‘macroexpand1’ quotes its argument.  However, if the expansion of a
     macro function call has side effects, those side effects are
     executed.

     If the expansion of <expr> yields another macro function call, that
     macro function call is not expanded.

     See also ‘::=’, ‘macros’, and ‘macroexpand’.

     Examples

          (%i1) g (x) ::= x / 99;
                                              x
          (%o1)                      g(x) ::= --
                                              99
          (%i2) h (x) ::= buildq ([x], g (x - a));
          (%o2)            h(x) ::= buildq([x], g(x - a))
          (%i3) a: 1234;
          (%o3)                         1234
          (%i4) macroexpand1 (h (y));
          (%o4)                       g(y - a)
          (%i5) h (y);
                                      y - 1234
          (%o5)                       --------
                                         99

 -- Global variable: macros
     Default value: ‘[]’

     ‘macros’ is the list of user-defined macro functions.  The macro
     function definition operator ‘::=’ puts a new macro function onto
     this list, and ‘kill’, ‘remove’, and ‘remfunction’ remove macro
     functions from the list.

     See also ‘infolists’.

 -- Function: splice (<a>)

     Splices (interpolates) the list named by the atom <a> into an
     expression, but only if ‘splice’ appears within ‘buildq’;
     otherwise, ‘splice’ is treated as an undefined function.  If
     appearing within ‘buildq’ as <a> alone (without ‘splice’), <a> is
     substituted (not interpolated) as a list into the result.  The
     argument of ‘splice’ can only be an atom; it cannot be a literal
     list or an expression which yields a list.

     Typically ‘splice’ supplies the arguments for a function or
     operator.  For a function ‘f’, the expression ‘f (splice (<a>))’
     within ‘buildq’ expands to ‘f (<a>[1], <a>[2], <a>[3], ...)’.  For
     an operator ‘o’, the expression ‘"o" (splice (<a>))’ within
     ‘buildq’ expands to ‘"o" (<a>[1], <a>[2], <a>[3], ...)’, where ‘o’
     may be any type of operator (typically one which takes multiple
     arguments).  Note that the operator must be enclosed in double
     quotes ‘"’.

     Examples

          (%i1) buildq ([x: [1, %pi, z - y]], foo (splice (x)) / length (x));
                                 foo(1, %pi, z - y)
          (%o1)                -----------------------
                               length([1, %pi, z - y])
          (%i2) buildq ([x: [1, %pi]], "/" (splice (x)));
                                          1
          (%o2)                          ---
                                         %pi
          (%i3) matchfix ("<>", "<>");
          (%o3)                          <>
          (%i4) buildq ([x: [1, %pi, z - y]], "<>" (splice (x)));
          (%o4)                   <>1, %pi, z - y<>


File: maxima.info,  Node: Functions and Variables for Function Definition,  Prev: Macros,  Up: Function Definition

36.4 Functions and Variables for Function Definition
====================================================

 -- Function: apply (<F>, [<x_1>, ..., <x_n>])

     Constructs and evaluates an expression ‘<F>(<arg_1>, ...,
     <arg_n>)’.

     ‘apply’ does not attempt to distinguish a ‘memoizing function’ from
     an ordinary function; when <F> is the name of a memoizing function,
     ‘apply’ evaluates ‘<F>(...)’ (that is, a function call with
     parentheses instead of square brackets).  ‘arrayapply’ evaluates a
     function call with square brackets in this case.

     See also ‘funmake’ and ‘args’.

     Examples:

     ‘apply’ evaluates its arguments.  In this example, ‘min’ is applied
     to the value of ‘L’.

          (%i1) L : [1, 5, -10.2, 4, 3];
          (%o1)                 [1, 5, - 10.2, 4, 3]
          (%i2) apply (min, L);
          (%o2)                        - 10.2

     ‘apply’ evaluates arguments, even if the function <F> quotes them.

          (%i1) F (x) := x / 1729;
                                             x
          (%o1)                     F(x) := ----
                                            1729
          (%i2) fname : F;
          (%o2)                           F
          (%i3) dispfun (F);
                                             x
          (%t3)                     F(x) := ----
                                            1729

          (%o3)                         [%t3]
          (%i4) dispfun (fname);
          fundef: no such function: fname
           -- an error. To debug this try: debugmode(true);
          (%i5) apply (dispfun, [fname]);
                                             x
          (%t5)                     F(x) := ----
                                            1729

          (%o5)                         [%t5]

     ‘apply’ evaluates the function name <F>.  Single quote ‘'’ defeats
     evaluation.  ‘demoivre’ is the name of a global variable and also a
     function.

          (%i1) demoivre;
          (%o1)                         false
          (%i2) demoivre (exp (%i * x));
          (%o2)                  %i sin(x) + cos(x)
          (%i3) apply (demoivre, [exp (%i * x)]);
          apply: found false where a function was expected.
           -- an error. To debug this try: debugmode(true);
          (%i4) apply ('demoivre, [exp (%i * x)]);
          (%o4)                  %i sin(x) + cos(x)

     How to convert a nested list into a matrix:

          (%i1) a:[[1,2],[3,4]];
          (%o1)                   [[1, 2], [3, 4]]
          (%i2) apply(matrix,a);
                                      [ 1  2 ]
          (%o2)                       [      ]
                                      [ 3  4 ]

 -- Function: block
          block ([<v_1>, ..., <v_m>], <expr_1>, ..., <expr_n>)
          block (<expr_1>, ..., <expr_n>)

     The function ‘block’ allows to make the variables <v_1>, ..., <v_m>
     to be local for a sequence of commands.  If these variables are
     already bound ‘block’ saves the current values of the variables
     <v_1>, ..., <v_m> (if any) upon entry to the block, then unbinds
     the variables so that they evaluate to themselves; The local
     variables may be bound to arbitrary values within the block but
     when the block is exited the saved values are restored, and the
     values assigned within the block are lost.

     If there is no need to define local variables then the list at the
     beginning of the ‘block’ command may be omitted.  In this case if
     neither ‘return’ nor ‘go’ are used ‘block’ behaves similar to the
     following construct:

          ( expr_1, expr_2,... , expr_n );

     <expr_1>, ..., <expr_n> will be evaluated in sequence and the value
     of the last expression will be returned.  The sequence can be
     modified by the ‘go’, ‘throw’, and ‘return’ functions.  The last
     expression is <expr_n> unless ‘return’ or an expression containing
     ‘throw’ is evaluated.

     The declaration ‘local(<v_1>, ..., <v_m>)’ within ‘block’ saves the
     properties associated with the symbols <v_1>, ..., <v_m>, removes
     any properties before evaluating other expressions, and restores
     any saved properties on exit from the block.  Some declarations are
     implemented as properties of a symbol, including ‘:=’, ‘array’,
     ‘dependencies’, ‘atvalue’, ‘matchdeclare’, ‘atomgrad’, ‘constant’,
     ‘nonscalar’, ‘assume’, and some others.  The effect of ‘local’ is
     to make such declarations effective only within the block;
     otherwise declarations within a block are actually global
     declarations.

     ‘block’ may appear within another ‘block’.  Local variables are
     established each time a new ‘block’ is evaluated.  Local variables
     appear to be global to any enclosed blocks.  If a variable is
     non-local in a block, its value is the value most recently assigned
     by an enclosing block, if any, otherwise, it is the value of the
     variable in the global environment.  This policy may coincide with
     the usual understanding of "dynamic scope".

     The value of the block is the value of the last statement or the
     value of the argument to the function ‘return’ which may be used to
     exit explicitly from the block.  The function ‘go’ may be used to
     transfer control to the statement of the block that is tagged with
     the argument to ‘go’.  To tag a statement, precede it by an atomic
     argument as another statement in the block.  For example: ‘block
     ([x], x:1, loop, x: x+1, ..., go(loop), ...)’.  The argument to
     ‘go’ must be the name of a tag appearing within the block.  One
     cannot use ‘go’ to transfer to a tag in a block other than the one
     containing the ‘go’.

     Blocks typically appear on the right side of a function definition
     but can be used in other places as well.

     See also ‘return’ and ‘go’.

 -- Function: break (<expr_1>, ..., <expr_n>)

     Evaluates and prints <expr_1>, ..., <expr_n> and then causes a
     Maxima break at which point the user can examine and change his
     environment.  Upon typing ‘exit;’ the computation resumes.

 -- Function: catch (<expr_1>, ..., <expr_n>)

     Evaluates <expr_1>, ..., <expr_n> one by one; if any leads to the
     evaluation of an expression of the form ‘throw (arg)’, then the
     value of the ‘catch’ is the value of ‘throw (arg)’, and no further
     expressions are evaluated.  This "non-local return" thus goes
     through any depth of nesting to the nearest enclosing ‘catch’.  If
     there is no ‘catch’ enclosing a ‘throw’, an error message is
     printed.

     If the evaluation of the arguments does not lead to the evaluation
     of any ‘throw’ then the value of ‘catch’ is the value of <expr_n>.

          (%i1) lambda ([x], if x < 0 then throw(x) else f(x))$
          (%i2) g(l) := catch (map (''%, l))$
          (%i3) g ([1, 2, 3, 7]);
          (%o3)               [f(1), f(2), f(3), f(7)]
          (%i4) g ([1, 2, -3, 7]);
          (%o4)                          - 3

     The function ‘g’ returns a list of ‘f’ of each element of ‘l’ if
     ‘l’ consists only of non-negative numbers; otherwise, ‘g’ "catches"
     the first negative element of ‘l’ and "throws" it up.

 -- Function: compfile
          compfile (<filename>, <f_1>, ..., <f_n>)
          compfile (<filename>, functions)
          compfile (<filename>, all)

     Translates Maxima functions into Lisp and writes the translated
     code into the file <filename>.

     ‘compfile(<filename>, <f_1>, ..., <f_n>)’ translates the specified
     functions.  ‘compfile (<filename>, functions)’ and ‘compfile
     (<filename>, all)’ translate all user-defined functions.

     The Lisp translations are not evaluated, nor is the output file
     processed by the Lisp compiler.  ‘translate’ creates and evaluates
     Lisp translations.  ‘compile_file’ translates Maxima into Lisp, and
     then executes the Lisp compiler.

     See also ‘translate’, ‘translate_file’, and ‘compile_file’.

 -- Function: compile
          compile (<f_1>, ..., <f_n>)
          compile (functions)
          compile (all)

     Translates Maxima functions <f_1>, ..., <f_n> into Lisp, evaluates
     the Lisp translations, and calls the Lisp function ‘COMPILE’ on
     each translated function.  ‘compile’ returns a list of the names of
     the compiled functions.

     ‘compile (all)’ or ‘compile (functions)’ compiles all user-defined
     functions.

     ‘compile’ quotes its arguments; the quote-quote operator ‘''’
     defeats quotation.

     Compiling a function to native code can mean a big increase in
     speed and might cause the memory footprint to reduce drastically.
     Code tends to be especially effective when the flexibility it needs
     to provide is limited.  If compilation doesn't provide the speed
     that is needed a few ways to limit the code's functionality are the
     following:
        • If the function accesses global variables the complexity of
          the function can be drastically be reduced by limiting these
          variables to one data type, for example using ‘mode_declare’
          or a statement like the following one: ‘put(x_1, bigfloat,
          numerical_type)’
        • The compiler might warn about undeclared variables if text
          could either be a named option to a command or (if they are
          assigned a value to) the name of a variable.  Prepending the
          option with a single quote ‘'’ tells the compiler that the
          text is meant as an option.

 -- Function: define
          define (<f>(<x_1>, ..., <x_n>), <expr>)
          define (<f>[<x_1>, ..., <x_n>], <expr>)
          define (<f>[<x_1>, ..., <x_n>](<y_1>, ..., <y_m>), <expr>)
          define (funmake (<f>, [<x_1>, ..., <x_n>]), <expr>)
          define (arraymake (<f>, [<x_1>, ..., <x_n>]), <expr>)
          define (ev (<expr_1>), <expr_2>)

     Defines a function named <f> with arguments <x_1>, ..., <x_n> and
     function body <expr>.  ‘define’ always evaluates its second
     argument (unless explicitly quoted).  The function so defined may
     be an ordinary Maxima function (with arguments enclosed in
     parentheses) or a ‘memoizing function’ (with arguments enclosed in
     square brackets).

     When the last or only function argument <x_n> is a list of one
     element, the function defined by ‘define’ accepts a variable number
     of arguments.  Actual arguments are assigned one-to-one to formal
     arguments <x_1>, ..., <x_(n - 1)>, and any further actual
     arguments, if present, are assigned to <x_n> as a list.

     When the first argument of ‘define’ is an expression of the form
     ‘<f>(<x_1>, ..., <x_n>)’ or ‘<f>[<x_1>, ..., <x_n>]’, the function
     arguments are evaluated but <f> is not evaluated, even if there is
     already a function or variable by that name.

     When the first argument is an expression with operator ‘funmake’,
     ‘arraymake’, or ‘ev’, the first argument is evaluated; this allows
     for the function name to be computed, as well as the body.

     All function definitions appear in the same namespace; defining a
     function ‘f’ within another function ‘g’ does not automatically
     limit the scope of ‘f’ to ‘g’.  However, ‘local(f)’ makes the
     definition of function ‘f’ effective only within the block or other
     compound expression in which ‘local’ appears.

     If some formal argument <x_k> is a quoted symbol (after
     evaluation), the function defined by ‘define’ does not evaluate the
     corresponding actual argument.  Otherwise all actual arguments are
     evaluated.

     See also ‘:=’ and ‘::=’.

     Examples:

     ‘define’ always evaluates its second argument (unless explicitly
     quoted).

          (%i1) expr : cos(y) - sin(x);
          (%o1)                    cos(y) - sin(x)
          (%i2) define (F1 (x, y), expr);
          (%o2)              F1(x, y) := cos(y) - sin(x)
          (%i3) F1 (a, b);
          (%o3)                    cos(b) - sin(a)
          (%i4) F2 (x, y) := expr;
          (%o4)                   F2(x, y) := expr
          (%i5) F2 (a, b);
          (%o5)                    cos(y) - sin(x)

     The function defined by ‘define’ may be an ordinary Maxima function
     or a ‘memoizing function’.

          (%i1) define (G1 (x, y), x.y - y.x);
          (%o1)               G1(x, y) := x . y - y . x
          (%i2) define (G2 [x, y], x.y - y.x);
          (%o2)                G2     := x . y - y . x
                                 x, y

     When the last or only function argument <x_n> is a list of one
     element, the function defined by ‘define’ accepts a variable number
     of arguments.

          (%i1) define (H ([L]), '(apply ("+", L)));
          (%o1)                H([L]) := apply("+", L)
          (%i2) H (a, b, c);
          (%o2)                       c + b + a

     When the first argument is an expression with operator ‘funmake’,
     ‘arraymake’, or ‘ev’, the first argument is evaluated.

          (%i1) [F : I, u : x];
          (%o1)                        [I, x]
          (%i2) funmake (F, [u]);
          (%o2)                         I(x)
          (%i3) define (funmake (F, [u]), cos(u) + 1);
          (%o3)                  I(x) := cos(x) + 1
          (%i4) define (arraymake (F, [u]), cos(u) + 1);
          (%o4)                   I  := cos(x) + 1
                                   x
          (%i5) define (foo (x, y), bar (y, x));
          (%o5)                foo(x, y) := bar(y, x)
          (%i6) define (ev (foo (x, y)), sin(x) - cos(y));
          (%o6)             bar(y, x) := sin(x) - cos(y)

 -- Function: define_variable (<name>, <default_value>, <mode>)

     Introduces a global variable into the Maxima environment.
     ‘define_variable’ is useful in user-written packages, which are
     often translated or compiled as it gives the compiler hints of the
     type ("mode") of a variable and therefore avoids requiring it to
     generate generic code that can deal with every variable being an
     integer, float, maxima object, array etc.

     ‘define_variable’ carries out the following steps:

       1. ‘mode_declare (<name>, <mode>)’ declares the mode ("type") of
          <name> to the translator which can considerably speed up
          compiled code as it allows having to create generic code.  See
          ‘mode_declare’ for a list of the possible modes.

       2. If the variable is unbound, <default_value> is assigned to
          <name>.

       3. Associates <name> with a test function to ensure that <name>
          is only assigned values of the declared mode.

     The ‘value_check’ property can be assigned to any variable which
     has been defined via ‘define_variable’ with a mode other than
     ‘any’.  The ‘value_check’ property is a lambda expression or the
     name of a function of one variable, which is called when an attempt
     is made to assign a value to the variable.  The argument of the
     ‘value_check’ function is the would-be assigned value.

     ‘define_variable’ evaluates ‘default_value’, and quotes ‘name’ and
     ‘mode’.  ‘define_variable’ returns the current value of ‘name’,
     which is ‘default_value’ if ‘name’ was unbound before, and
     otherwise it is the previous value of ‘name’.

     Examples:

     ‘foo’ is a Boolean variable, with the initial value ‘true’.

          (%i1) define_variable (foo, true, boolean);
          (%o1)                         true
          (%i2) foo;
          (%o2)                         true
          (%i3) foo: false;
          (%o3)                         false
          (%i4) foo: %pi;
          translator: foo was declared with mode boolean
                                                    , but it has value: %pi
           -- an error. To debug this try: debugmode(true);
          (%i5) foo;
          (%o5)                         false

     ‘bar’ is an integer variable, which must be prime.

          (%i1) define_variable (bar, 2, integer);
          (%o1)                           2
          (%i2) qput (bar, prime_test, value_check);
          (%o2)                      prime_test
          (%i3) prime_test (y) := if not primep(y) then
                                     error (y, "is not prime.");
          (%o3) prime_test(y) := if not primep(y)
                                             then error(y, "is not prime.")
          (%i4) bar: 1439;
          (%o4)                         1439
          (%i5) bar: 1440;
          1440 is not prime.
          #0: prime_test(y=1440)
           -- an error. To debug this try: debugmode(true);
          (%i6) bar;
          (%o6)                         1439

     ‘baz_quux’ is a variable which cannot be assigned a value.  The
     mode ‘any_check’ is like ‘any’, but ‘any_check’ enables the
     ‘value_check’ mechanism, and ‘any’ does not.

          (%i1) define_variable (baz_quux, 'baz_quux, any_check);
          (%o1)                       baz_quux
          (%i2) F: lambda ([y], if y # 'baz_quux then
                           error ("Cannot assign to `baz_quux'."));
          (%o2) lambda([y], if y # 'baz_quux
                                  then error(Cannot assign to `baz_quux'.))
          (%i3) qput (baz_quux, ''F, value_check);
          (%o3) lambda([y], if y # 'baz_quux
                                  then error(Cannot assign to `baz_quux'.))
          (%i4) baz_quux: 'baz_quux;
          (%o4)                       baz_quux
          (%i5) baz_quux: sqrt(2);
          Cannot assign to `baz_quux'.
          #0: lambda([y],if y # 'baz_quux then
                      error("Cannot assign to `baz_quux'."))(y=sqrt(2))
           -- an error. To debug this try: debugmode(true);
          (%i6) baz_quux;
          (%o6)                       baz_quux

 -- Function: dispfun
          dispfun (<f_1>, ..., <f_n>)
          dispfun (all)

     Displays the definition of the user-defined functions <f_1>, ...,
     <f_n>.  Each argument may be the name of a macro (defined with
     ‘::=’), an ordinary function (defined with ‘:=’ or ‘define’), an
     array function (defined with ‘:=’ or ‘define’, but enclosing
     arguments in square brackets ‘[ ]’), a subscripted function
     (defined with ‘:=’ or ‘define’, but enclosing some arguments in
     square brackets and others in parentheses ‘( )’), one of a family
     of subscripted functions selected by a particular subscript value,
     or a subscripted function defined with a constant subscript.

     ‘dispfun (all)’ displays all user-defined functions as given by the
     ‘functions’, ‘arrays’, and ‘macros’ lists, omitting subscripted
     functions defined with constant subscripts.

     ‘dispfun’ creates an intermediate expression label (‘%t1’, ‘%t2’,
     etc.)  for each displayed function, and assigns the function
     definition to the label.  In contrast, ‘fundef’ returns the
     function definition.

     ‘dispfun’ quotes its arguments; the quote-quote operator ‘''’
     defeats quotation.  ‘dispfun’ returns the list of intermediate
     expression labels corresponding to the displayed functions.

     Examples:

          (%i1) m(x, y) ::= x^(-y);
                                               - y
          (%o1)                   m(x, y) ::= x
          (%i2) f(x, y) :=  x^(-y);
                                               - y
          (%o2)                    f(x, y) := x
          (%i3) g[x, y] :=  x^(-y);
                                              - y
          (%o3)                     g     := x
                                     x, y
          (%i4) h[x](y) :=  x^(-y);
                                              - y
          (%o4)                     h (y) := x
                                     x
          (%i5) i[8](y) :=  8^(-y);
                                              - y
          (%o5)                     i (y) := 8
                                     8
          (%i6) dispfun (m, f, g, h, h[5], h[10], i[8]);
                                               - y
          (%t6)                   m(x, y) ::= x

                                               - y
          (%t7)                    f(x, y) := x

                                              - y
          (%t8)                     g     := x
                                     x, y

                                              - y
          (%t9)                     h (y) := x
                                     x

                                              1
          (%t10)                     h (y) := --
                                      5        y
                                              5

                                               1
          (%t11)                    h  (y) := ---
                                     10         y
                                              10

                                              - y
          (%t12)                    i (y) := 8
                                     8

          (%o12)       [%t6, %t7, %t8, %t9, %t10, %t11, %t12]
          (%i13) ''%;
                               - y              - y            - y
          (%o13) [m(x, y) ::= x   , f(x, y) := x   , g     := x   ,
                                                      x, y
                            - y           1              1             - y
                  h (y) := x   , h (y) := --, h  (y) := ---, i (y) := 8   ]
                   x              5        y   10         y   8
                                          5             10

 -- Function: fullmap (<f>, <expr_1>, ...)

     Similar to ‘map’, but ‘fullmap’ keeps mapping down all
     subexpressions until the main operators are no longer the same.

     ‘fullmap’ is used by the Maxima simplifier for certain matrix
     manipulations; thus, Maxima sometimes generates an error message
     concerning ‘fullmap’ even though ‘fullmap’ was not explicitly
     called by the user.

     Examples:

          (%i1) a + b * c;
          (%o1)                        b c + a
          (%i2) fullmap (g, %);
          (%o2)                   g(b) g(c) + g(a)
          (%i3) map (g, %th(2));
          (%o3)                     g(b c) + g(a)

 -- Function: fullmapl (<f>, <list_1>, ...)

     Similar to ‘fullmap’, but ‘fullmapl’ only maps onto lists and
     matrices.

     Example:

          (%i1) fullmapl ("+", [3, [4, 5]], [[a, 1], [0, -1.5]]);
          (%o1)                [[a + 3, 4], [4, 3.5]]

 -- System variable: functions
     Default value: ‘[]’

     ‘functions’ is the list of ordinary Maxima functions in the current
     session.  An ordinary function is a function constructed by
     ‘define’ or ‘:=’ and called with parentheses ‘()’.  A function may
     be defined at the Maxima prompt or in a Maxima file loaded by
     ‘load’ or ‘batch’.

     ‘Memoizing functions’ (called with square brackets, e.g., ‘F[x]’)
     and subscripted functions (called with square brackets and
     parentheses, e.g., ‘F[x](y)’) are listed by the global variable
     ‘arrays’, and not by ‘functions’.

     Lisp functions are not kept on any list.

     Examples:

          (%i1) F_1 (x) := x - 100;
          (%o1)                   F_1(x) := x - 100
          (%i2) F_2 (x, y) := x / y;
                                                x
          (%o2)                    F_2(x, y) := -
                                                y
          (%i3) define (F_3 (x), sqrt (x));
          (%o3)                   F_3(x) := sqrt(x)
          (%i4) G_1 [x] := x - 100;
          (%o4)                    G_1  := x - 100
                                      x
          (%i5) G_2 [x, y] := x / y;
                                               x
          (%o5)                     G_2     := -
                                       x, y    y
          (%i6) define (G_3 [x], sqrt (x));
          (%o6)                    G_3  := sqrt(x)
                                      x
          (%i7) H_1 [x] (y) := x^y;
                                                y
          (%o7)                     H_1 (y) := x
                                       x
          (%i8) functions;
          (%o8)              [F_1(x), F_2(x, y), F_3(x)]
          (%i9) arrays;
          (%o9)                 [G_1, G_2, G_3, H_1]

 -- Function: fundef (<f>)

     Returns the definition of the function <f>.

     The argument may be
        • the name of a macro (defined with ‘::=’),
        • an ordinary function (defined with ‘:=’ or ‘define’),
        • a ‘memoizing function’ (defined with ‘:=’ or ‘define’, but
          enclosing arguments in square brackets ‘[ ]’),
        • a subscripted function (defined with ‘:=’ or ‘define’, but
          enclosing some arguments in square brackets and others in
          parentheses ‘( )’),
        • one of a family of subscripted functions selected by a
          particular subscript value,
        • or a subscripted function defined with a constant subscript.

     ‘fundef’ quotes its argument; the quote-quote operator ‘''’ defeats
     quotation.

     ‘fundef (<f>)’ returns the definition of <f>.  In contrast,
     ‘dispfun (<f>)’ creates an intermediate expression label and
     assigns the definition to the label.

 -- Function: funmake (<F>, [<arg_1>, ..., <arg_n>])

     Returns an expression ‘<F>(<arg_1>, ..., <arg_n>)’.  The return
     value is simplified, but not evaluated, so the function <F> is not
     called, even if it exists.

     ‘funmake’ does not attempt to distinguish ‘memoizing functions’
     from ordinary functions; when <F> is the name of a memoizing
     function, ‘funmake’ returns ‘<F>(...)’ (that is, a function call
     with parentheses instead of square brackets).  ‘arraymake’ returns
     a function call with square brackets in this case.

     ‘funmake’ evaluates its arguments.

     See also ‘apply’ and ‘args’.

     Examples:

     ‘funmake’ applied to an ordinary Maxima function.

          (%i1) F (x, y) := y^2 - x^2;
                                             2    2
          (%o1)                  F(x, y) := y  - x
          (%i2) funmake (F, [a + 1, b + 1]);
          (%o2)                    F(a + 1, b + 1)
          (%i3) ''%;
                                        2          2
          (%o3)                  (b + 1)  - (a + 1)

     ‘funmake’ applied to a macro.

          (%i1) G (x) ::= (x - 1)/2;
                                            x - 1
          (%o1)                    G(x) ::= -----
                                              2
          (%i2) funmake (G, [u]);
          (%o2)                         G(u)
          (%i3) ''%;
                                        u - 1
          (%o3)                         -----
                                          2

     ‘funmake’ applied to a subscripted function.

          (%i1) H [a] (x) := (x - 1)^a;
                                                  a
          (%o1)                   H (x) := (x - 1)
                                   a
          (%i2) funmake (H [n], [%e]);
                                                 n
          (%o2)               lambda([x], (x - 1) )(%e)
          (%i3) ''%;
                                              n
          (%o3)                       (%e - 1)
          (%i4) funmake ('(H [n]), [%e]);
          (%o4)                        H (%e)
                                        n
          (%i5) ''%;
                                              n
          (%o5)                       (%e - 1)

     ‘funmake’ applied to a symbol which is not a defined function of
     any kind.

          (%i1) funmake (A, [u]);
          (%o1)                         A(u)
          (%i2) ''%;
          (%o2)                         A(u)

     ‘funmake’ evaluates its arguments, but not the return value.

          (%i1) det(a,b,c) := b^2 -4*a*c;
                                              2
          (%o1)              det(a, b, c) := b  - 4 a c
          (%i2) (x : 8, y : 10, z : 12);
          (%o2)                          12
          (%i3) f : det;
          (%o3)                          det
          (%i4) funmake (f, [x, y, z]);
          (%o4)                    det(8, 10, 12)
          (%i5) ''%;
          (%o5)                         - 284

     Maxima simplifies ‘funmake’'s return value.

          (%i1) funmake (sin, [%pi / 2]);
          (%o1)                           1

 -- Function: lambda
          lambda ([<x_1>, ..., <x_m>], <expr_1>, ..., <expr_n>)
          lambda ([[<L>]], <expr_1>, ..., <expr_n>)
          lambda ([<x_1>, ..., <x_m>, [<L>]], <expr_1>, ..., <expr_n>)

     Defines and returns a lambda expression (that is, an anonymous
     function).  The function may have required arguments <x_1>, ...,
     <x_m> and/or optional arguments <L>, which appear within the
     function body as a list.  The return value of the function is
     <expr_n>.  A lambda expression can be assigned to a variable and
     evaluated like an ordinary function.  A lambda expression may
     appear in some contexts in which a function name is expected.

     When the function is evaluated, unbound local variables <x_1>, ...,
     <x_m> are created.  ‘lambda’ may appear within ‘block’ or another
     ‘lambda’; local variables are established each time another ‘block’
     or ‘lambda’ is evaluated.  Local variables appear to be global to
     any enclosed ‘block’ or ‘lambda’.  If a variable is not local, its
     value is the value most recently assigned in an enclosing ‘block’
     or ‘lambda’, if any, otherwise, it is the value of the variable in
     the global environment.  This policy may coincide with the usual
     understanding of "dynamic scope".

     After local variables are established, <expr_1> through <expr_n>
     are evaluated in turn.  The special variable ‘%%’, representing the
     value of the preceding expression, is recognized.  ‘throw’ and
     ‘catch’ may also appear in the list of expressions.

     ‘return’ cannot appear in a lambda expression unless enclosed by
     ‘block’, in which case ‘return’ defines the return value of the
     block and not of the lambda expression, unless the block happens to
     be <expr_n>.  Likewise, ‘go’ cannot appear in a lambda expression
     unless enclosed by ‘block’.

     ‘lambda’ quotes its arguments; the quote-quote operator ‘''’
     defeats quotation.

     Examples:

        • A lambda expression can be assigned to a variable and
          evaluated like an ordinary function.

          (%i1) f: lambda ([x], x^2);
                                                2
          (%o1)                    lambda([x], x )
          (%i2) f(a);
                                          2
          (%o2)                          a

        • A lambda expression may appear in contexts in which a function
          evaluation is expected.

          (%i1) lambda ([x], x^2) (a);
                                          2
          (%o1)                          a
          (%i2) apply (lambda ([x], x^2), [a]);
                                          2
          (%o2)                          a
          (%i3) map (lambda ([x], x^2), [a, b, c, d, e]);
                                  2   2   2   2   2
          (%o3)                 [a , b , c , d , e ]

        • Argument variables are local variables.  Other variables
          appear to be global variables.  Global variables are evaluated
          at the time the lambda expression is evaluated, unless some
          special evaluation is forced by some means, such as ‘''’.

          (%i1) a: %pi$
          (%i2) b: %e$
          (%i3) g: lambda ([a], a*b);
          (%o3)                   lambda([a], a b)
          (%i4) b: %gamma$
          (%i5) g(1/2);
                                       %gamma
          (%o5)                        ------
                                         2
          (%i6) g2: lambda ([a], a*''b);
          (%o6)                 lambda([a], a %gamma)
          (%i7) b: %e$
          (%i8) g2(1/2);
                                       %gamma
          (%o8)                        ------
                                         2

        • Lambda expressions may be nested.  Local variables within the
          outer lambda expression appear to be global to the inner
          expression unless masked by local variables of the same names.

          (%i1) h: lambda ([a, b], h2: lambda ([a], a*b), h2(1/2));
                                                             1
          (%o1)     lambda([a, b], h2 : lambda([a], a b), h2(-))
                                                             2
          (%i2) h(%pi, %gamma);
                                       %gamma
          (%o2)                        ------
                                         2

        • Since ‘lambda’ quotes its arguments, lambda expression ‘i’
          below does not define a "multiply by ‘a’" function.  Such a
          function can be defined via ‘buildq’, as in lambda expression
          ‘i2’ below.

          (%i1) i: lambda ([a], lambda ([x], a*x));
          (%o1)             lambda([a], lambda([x], a x))
          (%i2) i(1/2);
          (%o2)                   lambda([x], a x)
          (%i3) i2: lambda([a], buildq([a: a], lambda([x], a*x)));
          (%o3)    lambda([a], buildq([a : a], lambda([x], a x)))
          (%i4) i2(1/2);
                                              1
          (%o4)                  lambda([x], (-) x)
                                              2
          (%i5) i2(1/2)(%pi);
                                         %pi
          (%o5)                          ---
                                          2

        • A lambda expression may take a variable number of arguments,
          which are indicated by ‘[<L>]’ as the sole or final argument.
          The arguments appear within the function body as a list.

          (%i1) f : lambda ([aa, bb, [cc]], aa * cc + bb);
          (%o1)          lambda([aa, bb, [cc]], aa cc + bb)
          (%i2) f (foo, %i, 17, 29, 256);
          (%o2)       [17 foo + %i, 29 foo + %i, 256 foo + %i]
          (%i3) g : lambda ([[aa]], apply ("+", aa));
          (%o3)             lambda([[aa]], apply(+, aa))
          (%i4) g (17, 29, x, y, z, %e);
          (%o4)                  z + y + x + %e + 46

 -- Function: local (<v_1>, ..., <v_n>)

     Saves the properties associated with the symbols <v_1>, ..., <v_n>,
     removes any properties before evaluating other expressions, and
     restores any saved properties on exit from the block or other
     compound expression in which ‘local’ appears.

     Some declarations are implemented as properties of a symbol,
     including ‘:=’, ‘array’, ‘dependencies’, ‘atvalue’, ‘matchdeclare’,
     ‘atomgrad’, ‘constant’, ‘nonscalar’, ‘assume’, and some others.
     The effect of ‘local’ is to make such declarations effective only
     within the block or other compound expression in which ‘local’
     appears; otherwise such declarations are global declarations.

     ‘local’ can only appear in ‘block’ or in the body of a function
     definition or ‘lambda’ expression, and only one occurrence is
     permitted in each.

     ‘local’ quotes its arguments.  ‘local’ returns ‘done’.

     Example:

     A local function definition.

          (%i1) foo (x) := 1 - x;
          (%o1)                    foo(x) := 1 - x
          (%i2) foo (100);
          (%o2)                         - 99
          (%i3) block (local (foo), foo (x) := 2 * x, foo (100));
          (%o3)                          200
          (%i4) foo (100);
          (%o4)                         - 99

 -- Option variable: macroexpansion
     Default value: ‘false’

     ‘macroexpansion’ controls whether the expansion (that is, the
     return value) of a macro function is substituted for the macro
     function call.  A substitution may speed up subsequent expression
     evaluations, at the cost of storing the expansion.

     ‘false’
          The expansion of a macro function is not substituted for the
          macro function call.
     ‘expand’
          The first time a macro function call is evaluated, the
          expansion is stored.  The expansion is not recomputed on
          subsequent calls; any side effects (such as ‘print’ or
          assignment to global variables) happen only when the macro
          function call is first evaluated.  Expansion in an expression
          does not affect other expressions which have the same macro
          function call.
     ‘displace’
          The first time a macro function call is evaluated, the
          expansion is substituted for the call, thus modifying the
          expression from which the macro function was called.  The
          expansion is not recomputed on subsequent calls; any side
          effects happen only when the macro function call is first
          evaluated.  Expansion in an expression does not affect other
          expressions which have the same macro function call.

     Examples

     When ‘macroexpansion’ is ‘false’, a macro function is called every
     time the calling expression is evaluated, and the calling
     expression is not modified.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: false;
          (%o4)                         false
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                            h(x)
          (%t6)                     f(x) := ----
                                            g(x)

          (%o6)                         [%t6]
          (%i7) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

     When ‘macroexpansion’ is ‘expand’, a macro function is called once,
     and the calling expression is not modified.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: expand;
          (%o4)                        expand
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                mmacroexpanded(x - 99, h(x))
          (%t6)         f(x) := ----------------------------
                                mmacroexpanded(x + 99, g(x))

          (%o6)                         [%t6]
          (%i7) f (a * b);
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

     When ‘macroexpansion’ is ‘displace’, a macro function is called
     once, and the calling expression is modified.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: displace;
          (%o4)                       displace
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                           x - 99
          (%t6)                    f(x) := ------
                                           x + 99

          (%o6)                         [%t6]
          (%i7) f (a * b);
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

 -- Function: mode_declare (<y_1>, <mode_1>, ..., <y_n>, <mode_n>)
 -- Function: modedeclare (<y_1>, <mode_1>, ..., <y_n>, <mode_n>)

     A ‘mode_declare’ informs the compiler which type (lisp programmers
     name the type: "mode") a function parameter or its return value
     will be of.  This can greatly boost the efficiency of the code the
     compiler generates: Without knowing the type of all variables and
     knowing the return value of all functions a function uses in
     advance very generic (and thus potentially slow) code needs to be
     generated.

     The arguments of ‘mode_declare’ are pairs consisting of a variable
     (or a list of variables all having the same mode) and a mode.
     Available modes ("types") are:
          array            an declared array (see the detailed description below)
          boolean          true or false
          integer          integers (including arbitrary-size integers)
          fixnum           integers (excluding arbitrary-size integers)
          float            machine-size floating-point numbers
          real             machine-size floating-point or integer
          number           Numbers
          any              any kind of object (useful for arrays of any)

     A function parameter named ‘a’ can be declared as an array filled
     with elements of the type ‘t’ the following way:
          mode_declare (a, array(t, dim1, dim2, ...))
     If none of the elements of the array ‘a’ needs to be checked if it
     still doesn't contain a value additional code can be omitted by
     declaring this fact, too:
          mode_declare (a, array (t, complete, dim1, dim2, ...))
     The ‘complete’ has no effect if all array elements are of the type
     ‘fixnum’ or ‘float’: Machine-sized numbers inevitably contain a
     value (and will automatically be initialized to 0 in most lisp
     implementations).

     Another way to tell that all entries of the array ‘a’ are of the
     type ("mode") ‘m’ and have been assigned a value to would be:
          mode_declare (completearray (a), m))

     Numeric code using arrays might run faster still if the size of the
     array is known at compile time, as well, as in:
          mode_declare (completearray (a [10, 10]), float)
     for a floating point number array named ‘a’ which is 10 x 10.

     ‘mode_declare’ also can be used in order to declare the type of the
     result of a function.  In this case the function compilation needs
     to be preceded by another ‘mode_declare’ statement.  For example
     the expression,
          mode_declare ([function (f_1, f_2, ...)], fixnum)
     declares that the values returned by ‘f_1’, ‘f_2’, ... are
     single-word integers.

     ‘modedeclare’ is a synonym for ‘mode_declare’.

     If the type of function parameters and results doesn't match the
     declaration by ‘mode_declare’ the function may misbehave or a
     warning or an error might occur, see ‘mode_checkp’,
     ‘mode_check_errorp’ and ‘mode_check_warnp’.

     See ‘mode_identity’ for declaring the type of lists and
     ‘define_variable’ for declaring the type of all global variables
     compiled code uses, as well.

     Example:
          (%i1) square_float(f):=(
               mode_declare(f,float),
               f*f
           );
          (%o1)   square_float(f) := (mode_declare(f, float), f f)
          (%i2) mode_declare([function(f)],float);
          (%o2)                    [[function(f)]]
          (%i3) compile(square_float);
          (%o3)                    [square_float]
          (%i4) square_float(100.0);
          (%o4)                        10000.0

 -- Option variable: mode_checkp
     Default value: ‘true’

     When ‘mode_checkp’ is ‘true’, ‘mode_declare’ does not only define
     which type a variable will be of so the compiler can generate more
     efficient code, but will also create a runtime warning if the
     variable isn't of the variable type the code was compiled to deal
     with.

          (%i1) mode_checkp:true;
          (%o1)                         true
          (%i2) square(f):=(
              mode_declare(f,float),
              f^2);
                                                             2
          (%o2)       square(f) := (mode_declare(f, float), f )
          (%i3) compile(square);
          (%o3)                       [square]
          (%i4) square(2.3);
          (%o4)                   5.289999999999999
          (%i5) square(4);
          Maxima encountered a Lisp error:

           The value
             4
           is not of type
             DOUBLE-FLOAT
           when binding $F

          Automatically continuing.
          To enable the Lisp debugger set *debugger-hook* to nil.

 -- Option variable: mode_check_errorp
     Default value: ‘false’

     When ‘mode_check_errorp’ is ‘true’, ‘mode_declare’ calls error.

 -- Option variable: mode_check_warnp
     Default value: ‘true’

     When ‘mode_check_warnp’ is ‘true’, mode errors are described.

 -- Function: mode_identity (<arg_1>, <arg_2>)

     ‘mode_identity’ works similar to ‘mode_declare’, but is used for
     informing the compiler that a thing like a ‘macro’ or a list
     operation will only return a specific type of object.  The purpose
     of doing so is that maxima supports many objects: Machine integers,
     arbitrary length integers, equations, machine floats, big floats,
     which means that for everything that deals with return values of
     operations that can result in any object the compiler needs to
     output generic (and therefore potentially slow) code.

     The first argument to ‘mode_identity’ is the type of return value
     something will return (for possible types see ‘mode_declare’).
     (i.e., one of ‘float’, ‘fixnum’, ‘number’, The second argument is
     the expression that will return an object of this type.

     If the the return value of this expression is of a type the code
     was not compiled for error or warning is signalled.

     If you knew that ‘first (l)’ returned a number then you could write

          mode_identity (number, first (l)).
     However, if you need this construct more often it would be more
     efficient to define a function that returns a number fist:
          firstnumb (x) ::= buildq ([x], mode_identity (number, first(x)));
          compile(firstnumb)
     ‘firstnumb’ now can be used every time you need the first element
     of a list that is guaranteed to be filled with numbers.

 -- Function: remfunction
          remfunction (<f_1>, ..., <f_n>)
          remfunction (all)

     Unbinds the function definitions of the symbols <f_1>, ..., <f_n>.
     The arguments may be the names of ordinary functions (created by
     ‘:=’ or ‘define’) or macro functions (created by ‘::=’).

     ‘remfunction (all)’ unbinds all function definitions.

     ‘remfunction’ quotes its arguments.

     ‘remfunction’ returns a list of the symbols for which the function
     definition was unbound.  ‘false’ is returned in place of any symbol
     for which there is no function definition.

     ‘remfunction’ does not apply to ‘memoizing functions’ or
     subscripted functions.  ‘remarray’ applies to those types of
     functions.

 -- Option variable: savedef
     Default value: ‘true’

     When ‘savedef’ is ‘true’, the Maxima version of a user function is
     preserved when the function is translated.  This permits the
     definition to be displayed by ‘dispfun’ and allows the function to
     be edited.

     When ‘savedef’ is ‘false’, the names of translated functions are
     removed from the ‘functions’ list.

 -- Function: translate
          translate (<f_1>, ..., <f_n>)
          translate (functions)
          translate (all)

     Translates the user-defined functions <f_1>, ..., <f_n> from the
     Maxima language into Lisp and evaluates the Lisp translations.
     Typically the translated functions run faster than the originals.

     ‘translate (all)’ or ‘translate (functions)’ translates all
     user-defined functions.

     Functions to be translated should include a call to ‘mode_declare’
     at the beginning when possible in order to produce more efficient
     code.  For example:

          f (x_1, x_2, ...) := block ([v_1, v_2, ...],
              mode_declare (v_1, mode_1, v_2, mode_2, ...), ...)

     where the <x_1>, <x_2>, ... are the parameters to the function and
     the <v_1>, <v_2>, ... are the local variables.

     The names of translated functions are removed from the ‘functions’
     list if ‘savedef’ is ‘false’ (see below) and are added to the
     ‘props’ lists.

     Functions should not be translated unless they are fully debugged.

     Expressions are assumed simplified; if they are not, correct but
     non-optimal code gets generated.  Thus, the user should not set the
     ‘simp’ switch to ‘false’ which inhibits simplification of the
     expressions to be translated.

     The switch ‘translate’, if ‘true’, causes automatic translation of
     a user's function to Lisp.

     Note that translated functions may not run identically to the way
     they did before translation as certain incompatibilities may exist
     between the Lisp and Maxima versions.  Principally, the ‘rat’
     function with more than one argument and the ‘ratvars’ function
     should not be used if any variables are ‘mode_declare’'d canonical
     rational expressions (CRE). Also the ‘prederror: false’ setting
     will not translate.

     ‘savedef’ - if ‘true’ will cause the Maxima version of a user
     function to remain when the function is ‘translate’'d.  This
     permits the definition to be displayed by ‘dispfun’ and allows the
     function to be edited.

     ‘transrun’ - if ‘false’ will cause the interpreted version of all
     functions to be run (provided they are still around) rather than
     the translated version.

     The result returned by ‘translate’ is a list of the names of the
     functions translated.

 -- Function: translate_file
          translate_file (<maxima_filename>)
          translate_file (<maxima_filename>, <lisp_filename>)

     Translates a file of Maxima code into a file of Lisp code.
     ‘translate_file’ returns a list of three filenames: the name of the
     Maxima file, the name of the Lisp file, and the name of file
     containing additional information about the translation.
     ‘translate_file’ evaluates its arguments.

     ‘translate_file ("foo.mac"); load("foo.LISP")’ is the same as the
     command ‘batch ("foo.mac")’ except for certain restrictions, the
     use of ‘''’ and ‘%’, for example.

     ‘translate_file (<maxima_filename>)’ translates a Maxima file
     <maxima_filename> into a similarly-named Lisp file.  For example,
     ‘foo.mac’ is translated into ‘foo.LISP’.  The Maxima filename may
     include a directory name or names, in which case the Lisp output
     file is written to the same directory from which the Maxima input
     comes.

     ‘translate_file (<maxima_filename>, <lisp_filename>)’ translates a
     Maxima file <maxima_filename> into a Lisp file <lisp_filename>.
     ‘translate_file’ ignores the filename extension, if any, of
     ‘lisp_filename’; the filename extension of the Lisp output file is
     always ‘LISP’.  The Lisp filename may include a directory name or
     names, in which case the Lisp output file is written to the
     specified directory.

     ‘translate_file’ also writes a file of translator warning messages
     of various degrees of severity.  The filename extension of this
     file is ‘UNLISP’.  This file may contain valuable information,
     though possibly obscure, for tracking down bugs in translated code.
     The ‘UNLISP’ file is always written to the same directory from
     which the Maxima input comes.

     ‘translate_file’ emits Lisp code which causes some declarations and
     definitions to take effect as soon as the Lisp code is compiled.
     See ‘compile_file’ for more on this topic.

     See also
     ‘tr_array_as_ref’
     ‘tr_bound_function_applyp’,
     ‘tr_exponent’
     ‘tr_file_tty_messagesp’,
     ‘tr_float_can_branch_complex’,
     ‘tr_function_call_default’,
     ‘tr_numer’,
     ‘tr_optimize_max_loop’,
     ‘tr_state_vars’,
     ‘tr_warnings_get’,
     ‘tr_warn_bad_function_calls’
     ‘tr_warn_fexpr’,
     ‘tr_warn_meval’,
     ‘tr_warn_mode’,
     ‘tr_warn_undeclared’,
     and ‘tr_warn_undefined_variable’.

 -- Option variable: transrun
     Default value: ‘true’

     When ‘transrun’ is ‘false’ will cause the interpreted version of
     all functions to be run (provided they are still around) rather
     than the translated version.

 -- Option variable: tr_array_as_ref
     Default value: ‘true’

     If ‘translate_fast_arrays’ is ‘false’, array references in Lisp
     code emitted by ‘translate_file’ are affected by ‘tr_array_as_ref’.
     When ‘tr_array_as_ref’ is ‘true’, array names are evaluated,
     otherwise array names appear as literal symbols in translated code.

     ‘tr_array_as_ref’ has no effect if ‘translate_fast_arrays’ is
     ‘true’.

 -- Option variable: tr_bound_function_applyp
     Default value: ‘true’

     When ‘tr_bound_function_applyp’ is ‘true’ and
     ‘tr_function_call_default’ is ‘general’, if a bound variable (such
     as a function argument) is found being used as a function then
     Maxima will rewrite that function call using ‘apply’ and print a
     warning message.

     For example, if ‘g’ is defined by ‘g(f,x) := f(x+1)’ then
     translating ‘g’ will cause Maxima to print a warning and rewrite
     ‘f(x+1)’ as ‘apply(f,[x+1])’.

          (%i1) f (x) := x^2$
          (%i2) g (f) := f (3)$
          (%i3) tr_bound_function_applyp : true$
          (%i4) translate (g)$
          warning: f is a bound variable in f(3), but it is used as a function.
          note: instead I'll translate it as: apply(f,[3])
          (%i5) g (lambda ([x], x));
          (%o5)                           3
          (%i6) tr_bound_function_applyp : false$
          (%i7) translate (g)$
          (%i8) g (lambda ([x], x));
          (%o8)                           9

 -- Option variable: tr_file_tty_messagesp
     Default value: ‘false’

     When ‘tr_file_tty_messagesp’ is ‘true’, messages generated by
     ‘translate_file’ during translation of a file are displayed on the
     console and inserted into the UNLISP file.  When ‘false’, messages
     about translation of the file are only inserted into the UNLISP
     file.

 -- Option variable: tr_float_can_branch_complex
     Default value: ‘true’

     Tells the Maxima-to-Lisp translator to assume that the functions
     ‘acos’, ‘asin’, ‘asec’, ‘acsc’, ‘acosh’, ‘asech’, ‘atanh’, ‘acoth’,
     ‘log’ and ‘sqrt’ can return complex results.

     When it is ‘true’ then ‘acos(x)’ is of mode ‘any’ even if ‘x’ is of
     mode ‘float’ (as set by ‘mode_declare’).  When ‘false’ then
     ‘acos(x)’ is of mode ‘float’ if and only if ‘x’ is of mode ‘float’.

 -- Option variable: tr_function_call_default
     Default value: ‘general’

     ‘false’ means give up and call ‘meval’, ‘expr’ means assume Lisp
     fixed arg function.  ‘general’, the default gives code good for
     ‘mexprs’ and ‘mlexprs’ but not ‘macros’.  ‘general’ assures
     variable bindings are correct in compiled code.  In ‘general’ mode,
     when translating F(X), if F is a bound variable, then it assumes
     that ‘apply (f, [x])’ is meant, and translates a such, with
     appropriate warning.  There is no need to turn this off.  With the
     default settings, no warning messages implies full compatibility of
     translated and compiled code with the Maxima interpreter.

 -- Option variable: tr_numer
     Default value: ‘false’

     When ‘tr_numer’ is ‘true’, ‘numer’ properties are used for atoms
     which have them, e.g.  ‘%pi’.

 -- Option variable: tr_optimize_max_loop
     Default value: 100

     ‘tr_optimize_max_loop’ is the maximum number of times the
     macro-expansion and optimization pass of the translator will loop
     in considering a form.  This is to catch macro expansion errors,
     and non-terminating optimization properties.

 -- System variable: tr_state_vars
     Default value:
          [translate_fast_arrays, tr_function_call_default, tr_bound_function_applyp,
          tr_array_as_ref, tr_numer, tr_float_can_branch_complex, define_variable]

     The list of the switches that affect the form of the translated
     output.  This information is useful to system people when trying to
     debug the translator.  By comparing the translated product to what
     should have been produced for a given state, it is possible to
     track down bugs.

 -- Function: tr_warnings_get ()

     Prints a list of warnings which have been given by the translator
     during the current translation.

 -- Option variable: tr_warn_bad_function_calls
     Default value: ‘true’

     - Gives a warning when when function calls are being made which may
     not be correct due to improper declarations that were made at
     translate time.

 -- Option variable: tr_warn_fexpr
     Default value: ‘compfile’

     - Gives a warning if any FEXPRs are encountered.  FEXPRs should not
     normally be output in translated code, all legitimate special
     program forms are translated.

 -- Option variable: tr_warn_meval
     Default value: ‘compfile’

     - Gives a warning if the function ‘meval’ gets called.  If ‘meval’
     is called that indicates problems in the translation.

 -- Option variable: tr_warn_mode
     Default value: ‘all’

     - Gives a warning when variables are assigned values inappropriate
     for their mode.

 -- Option variable: tr_warn_undeclared
     Default value: ‘compile’

     - Determines when to send warnings about undeclared variables to
     the TTY.

 -- Option variable: tr_warn_undefined_variable
     Default value: ‘all’

     - Gives a warning when undefined global variables are seen.

 -- Function: compile_file
          compile_file (<filename>)
          compile_file (<filename>, <compiled_filename>)
          compile_file (<filename>, <compiled_filename>,
          <lisp_filename>)

     Translates the Maxima file <filename> into Lisp, and executes the
     Lisp compiler.  The compiled code is not loaded into Maxima.

     ‘compile_file’ returns a list of the names of four files: the
     original Maxima file, the Lisp translation, notes on translation,
     and the compiled code.  If the compilation fails, the fourth item
     is ‘false’.

     Some declarations and definitions take effect as soon as the Lisp
     code is compiled (without loading the compiled code).  These
     include functions defined with the ‘:=’ operator, macros define
     with the ‘::=’ operator, ‘alias’, ‘declare’, ‘define_variable’,
     ‘mode_declare’, and ‘infix’, ‘matchfix’, ‘nofix’, ‘postfix’,
     ‘prefix’, and ‘compfile’.

     Assignments and function calls are not evaluated until the compiled
     code is loaded.  In particular, within the Maxima file, assignments
     to the translation flags (‘tr_numer’, etc.)  have no effect on the
     translation.

     <filename> may not contain ‘:lisp’ statements.

     ‘compile_file’ evaluates its arguments.

 -- Function: declare_translated (<f_1>, <f_2>, ...)

     When translating a file of Maxima code to Lisp, it is important for
     the translator to know which functions it sees in the file are to
     be called as translated or compiled functions, and which ones are
     just Maxima functions or undefined.  Putting this declaration at
     the top of the file, lets it know that although a symbol does which
     does not yet have a Lisp function value, will have one at call
     time.  ‘(MFUNCTION-CALL fn arg1 arg2 ...)’ is generated when the
     translator does not know ‘fn’ is going to be a Lisp function.


File: maxima.info,  Node: Program Flow,  Next: Debugging,  Prev: Function Definition,  Up: Top

37 Program Flow
***************

* Menu:

* Lisp and Maxima::
* Garbage Collection::
* Introduction to Program Flow::
* Functions and Variables for Program Flow::


File: maxima.info,  Node: Lisp and Maxima,  Next: Garbage Collection,  Prev: Program Flow,  Up: Program Flow

37.1 Lisp and Maxima
====================

Maxima is a fairly complete programming language.  But since it is
written in Lisp, it additionally can provide easy access to Lisp
functions and variables from Maxima and vice versa.  Lisp and Maxima
symbols are distinguished by a naming convention.  A Lisp symbol which
begins with a dollar sign ‘$’ corresponds to a Maxima symbol without the
dollar sign.

   A Maxima symbol which begins with a question mark ‘?’ corresponds to
a Lisp symbol without the question mark.  For example, the Maxima symbol
‘foo’ corresponds to the Lisp symbol ‘$FOO’, while the Maxima symbol
‘?foo’ corresponds to the Lisp symbol ‘FOO’.  Note that ‘?foo’ is
written without a space between ‘?’ and ‘foo’; otherwise it might be
mistaken for ‘describe ("foo")’.

   Hyphen ‘-’, asterisk ‘*’, or other special characters in Lisp symbols
must be escaped by backslash ‘\’ where they appear in Maxima code.  For
example, the Lisp identifier ‘*foo-bar*’ is written ‘?\*foo\-bar\*’ in
Maxima.

   Lisp code may be executed from within a Maxima session.  A single
line of Lisp (containing one or more forms) may be executed by the
special command ‘:lisp’.  For example,

     (%i1) :lisp (foo $x $y)

calls the Lisp function ‘foo’ with Maxima variables ‘x’ and ‘y’ as
arguments.  The ‘:lisp’ construct can appear at the interactive prompt
or in a file processed by ‘batch’ or ‘demo’, but not in a file processed
by ‘load’, ‘batchload’, ‘translate_file’, or ‘compile_file’.

   The function ‘to_lisp’ opens an interactive Lisp session.  Entering
‘(to-maxima)’ closes the Lisp session and returns to Maxima.

   Lisp functions and variables which are to be visible in Maxima as
functions and variables with ordinary names (no special punctuation)
must have Lisp names beginning with the dollar sign ‘$’.

   Maxima is case-sensitive, distinguishing between lowercase and
uppercase letters in identifiers.  There are some rules governing the
translation of names between Lisp and Maxima.

  1. A Lisp identifier not enclosed in vertical bars corresponds to a
     Maxima identifier in lowercase.  Whether the Lisp identifier is
     uppercase, lowercase, or mixed case, is ignored.  E.g., Lisp
     ‘$foo’, ‘$FOO’, and ‘$Foo’ all correspond to Maxima ‘foo’.  But
     this is because ‘$foo’, ‘$FOO’ and ‘$Foo’ are converted by the Lisp
     reader by default to the Lisp symbol ‘$FOO’.
  2. A Lisp identifier which is all uppercase or all lowercase and
     enclosed in vertical bars corresponds to a Maxima identifier with
     case reversed.  That is, uppercase is changed to lowercase and
     lowercase to uppercase.  E.g., Lisp ‘|$FOO|’ and ‘|$foo|’
     correspond to Maxima ‘foo’ and ‘FOO’, respectively.
  3. A Lisp identifier which is mixed uppercase and lowercase and
     enclosed in vertical bars corresponds to a Maxima identifier with
     the same case.  E.g., Lisp ‘|$Foo|’ corresponds to Maxima ‘Foo’.

   The ‘#$’ Lisp macro allows the use of Maxima expressions in Lisp
code.  ‘#$<expr>$’ expands to a Lisp expression equivalent to the Maxima
expression <expr>.

     (msetq $foo #$[x, y]$)

This has the same effect as entering

     (%i1) foo: [x, y];

The Lisp function ‘displa’ prints an expression in Maxima format.

     (%i1) :lisp #$[x, y, z]$
     ((MLIST SIMP) $X $Y $Z)
     (%i1) :lisp (displa '((MLIST SIMP) $X $Y $Z))
     [x, y, z]
     NIL

   Functions defined in Maxima are not ordinary Lisp functions.  The
Lisp function ‘mfuncall’ calls a Maxima function.  For example:

     (%i1) foo(x,y) := x*y$
     (%i2) :lisp (mfuncall '$foo 'a 'b)
     ((MTIMES SIMP) A B)

   Some Lisp functions are shadowed in the Maxima package, namely the
following.

   complement     continue      //
   float          functionp     array
   exp            listen        signum
   atan           asin          acos
   asinh          acosh         atanh
   tanh           cosh          sinh
   tan            break         gcd


File: maxima.info,  Node: Garbage Collection,  Next: Introduction to Program Flow,  Prev: Lisp and Maxima,  Up: Program Flow

37.2 Garbage Collection
=======================

One of the advantages of using lisp is that it uses "Garbage
Collection".  In other words it automatically takes care of freeing
memory occupied for example of intermediate results that were used
during symbolic computation.

   Garbage Collection avoids many errors frequently found in C programs
(memory being freed too early, multiple times or not at all).

 -- Function: garbage_collect ()

     Tries to manually trigger the lisp's garbage collection.  This
     rarely is necessary as the lisp will employ an excellent algorithm
     for determining when to start garbage collection.

     If maxima knows how to do manually trigger the garbage collection
     for the current lisp ‘garbage_collect’ returns ‘true’, else
     ‘false’.


File: maxima.info,  Node: Introduction to Program Flow,  Next: Functions and Variables for Program Flow,  Prev: Garbage Collection,  Up: Program Flow

37.3 Introduction to Program Flow
=================================

Maxima provides a ‘do’ loop for iteration, as well as more primitive
constructs such as ‘go’.


File: maxima.info,  Node: Functions and Variables for Program Flow,  Prev: Introduction to Program Flow,  Up: Program Flow

37.4 Functions and Variables for Program Flow
=============================================

 -- Function: backtrace
          backtrace ()
          backtrace (<n>)

     Prints the call stack, that is, the list of functions which called
     the currently active function.

     ‘backtrace ()’ prints the entire call stack.

     ‘backtrace (<n>)’ prints the <n> most recent functions, including
     the currently active function.

     ‘backtrace’ can be called from a script, a function, or the
     interactive prompt (not only in a debugging context).

     Examples:

        • ‘backtrace ()’ prints the entire call stack.

               (%i1) h(x) := g(x/7)$
               (%i2) g(x) := f(x-11)$
               (%i3) f(x) := e(x^2)$
               (%i4) e(x) := (backtrace(), 2*x + 13)$
               (%i5) h(10);
               #0: e(x=4489/49)
               #1: f(x=-67/7)
               #2: g(x=10/7)
               #3: h(x=10)
                                             9615
               (%o5)                         ----
                                              49

        • ‘backtrace (<n>)’ prints the <n> most recent functions,
          including the currently active function.

               (%i1) h(x) := (backtrace(1), g(x/7))$
               (%i2) g(x) := (backtrace(1), f(x-11))$
               (%i3) f(x) := (backtrace(1), e(x^2))$
               (%i4) e(x) := (backtrace(1), 2*x + 13)$
               (%i5) h(10);
               #0: h(x=10)
               #0: g(x=10/7)
               #0: f(x=-67/7)
               #0: e(x=4489/49)
                                             9615
               (%o5)                         ----
                                              49

 -- Special operator: do
 -- Special operator: while
 -- Special operator: unless
 -- Special operator: for
 -- Special operator: from
 -- Special operator: thru
 -- Special operator: step
 -- Special operator: next
 -- Special operator: in

     The ‘do’ statement is used for performing iteration.  The general
     form of the ‘do’ statements maxima supports is:

        • ‘for <variable>: <initial_value> step <increment> thru <limit>
          do <body>’
        • ‘for <variable>: <initial_value> step <increment> while
          <condition> do <body>’
        • ‘for <variable>: <initial_value> step <increment> unless
          <condition> do <body>’
        • ‘for <variable> in <list> do <body>’

     If the loop is expected to generate a list as output the command
     ‘makelist’ may be the appropriate command to use instead, *Note
     Performance considerations for Lists::.

     <initial_value>, <increment>, <limit>, and <body> can be any
     expression.  <list> is a list.  If the increment is 1 then "‘step
     1’" may be omitted; As always, if ‘body’ needs to contain more than
     one command these commands can be specified as a comma-separated
     list surrounded by parenthesis or as a ‘block’.  Due to its great
     generality the ‘do’ statement will be described in two parts.  The
     first form of the ‘do’ statement (which is shown in the first three
     items above) is analogous to that used in several other programming
     languages (Fortran, Algol, PL/I, etc.); then the other features
     will be mentioned.

     The execution of the ‘do’ statement proceeds by first assigning the
     <initial_value> to the <variable> (henceforth called the
     control-variable).  Then: (1) If the control-variable has exceeded
     the limit of a ‘thru’ specification, or if the condition of the
     ‘unless’ is ‘true’, or if the condition of the ‘while’ is ‘false’
     then the ‘do’ terminates.  (2) The <body> is evaluated.  (3) The
     increment is added to the control-variable.  The process from (1)
     to (3) is performed repeatedly until the termination condition is
     satisfied.  One may also give several termination conditions in
     which case the ‘do’ terminates when any of them is satisfied.

     In general the ‘thru’ test is satisfied when the control-variable
     is greater than the <limit> if the <increment> was non-negative, or
     when the control-variable is less than the <limit> if the
     <increment> was negative.  The <increment> and <limit> may be
     non-numeric expressions as long as this inequality can be
     determined.  However, unless the <increment> is syntactically
     negative (e.g.  is a negative number) at the time the ‘do’
     statement is input, Maxima assumes it will be positive when the
     ‘do’ is executed.  If it is not positive, then the ‘do’ may not
     terminate properly.

     Note that the <limit>, <increment>, and termination condition are
     evaluated each time through the loop.  Thus if any of these involve
     much computation, and yield a result that does not change during
     all the executions of the <body>, then it is more efficient to set
     a variable to their value prior to the ‘do’ and use this variable
     in the ‘do’ form.

     The value normally returned by a ‘do’ statement is the atom ‘done’.
     However, the function ‘return’ may be used inside the <body> to
     exit the ‘do’ prematurely and give it any desired value.  Note
     however that a ‘return’ within a ‘do’ that occurs in a ‘block’ will
     exit only the ‘do’ and not the ‘block’.  Note also that the ‘go’
     function may not be used to exit from a ‘do’ into a surrounding
     ‘block’.

     The control-variable is always local to the ‘do’ and thus any
     variable may be used without affecting the value of a variable with
     the same name outside of the ‘do’.  The control-variable is unbound
     after the ‘do’ terminates.

          (%i1) for a:-3 thru 26 step 7 do display(a)$
                                       a = - 3

                                        a = 4

                                       a = 11

                                       a = 18

                                       a = 25

          (%i1) s: 0$
          (%i2) for i: 1 while i <= 10 do s: s+i;
          (%o2)                         done
          (%i3) s;
          (%o3)                          55

     Note that the condition ‘while i <= 10’ is equivalent to ‘unless i
     > 10’ and also ‘thru 10’.

          (%i1) series: 1$
          (%i2) term: exp (sin (x))$
          (%i3) for p: 1 unless p > 7 do
                    (term: diff (term, x)/p,
                     series: series + subst (x=0, term)*x^p)$
          (%i4) series;
                            7    6     5    4    2
                           x    x     x    x    x
          (%o4)            -- - --- - -- - -- + -- + x + 1
                           90   240   15   8    2

     which gives 8 terms of the Taylor series for ‘e^sin(x)’.

          (%i1) poly: 0$
          (%i2) for i: 1 thru 5 do
                    for j: i step -1 thru 1 do
                        poly: poly + i*x^j$
          (%i3) poly;
                            5      4       3       2
          (%o3)          5 x  + 9 x  + 12 x  + 14 x  + 15 x
          (%i4) guess: -3.0$
          (%i5) for i: 1 thru 10 do
                    (guess: subst (guess, x, 0.5*(x + 10/x)),
                     if abs (guess^2 - 10) < 0.00005 then return (guess));
          (%o5)                  - 3.162280701754386

     This example computes the negative square root of 10 using the
     Newton- Raphson iteration a maximum of 10 times.  Had the
     convergence criterion not been met the value returned would have
     been ‘done’.

     Instead of always adding a quantity to the control-variable one may
     sometimes wish to change it in some other way for each iteration.
     In this case one may use ‘next <expression>’ instead of ‘step
     <increment>’.  This will cause the control-variable to be set to
     the result of evaluating <expression> each time through the loop.

          (%i6) for count: 2 next 3*count thru 20 do display (count)$
                                      count = 2

                                      count = 6

                                     count = 18

     As an alternative to ‘for <variable>: <value> ...do...’ the syntax
     ‘for <variable> from <value> ...do...’ may be used.  This permits
     the ‘from <value>’ to be placed after the ‘step’ or ‘next’ value or
     after the termination condition.  If ‘from <value>’ is omitted then
     1 is used as the initial value.

     Sometimes one may be interested in performing an iteration where
     the control-variable is never actually used.  It is thus
     permissible to give only the termination conditions omitting the
     initialization and updating information as in the following example
     to compute the square-root of 5 using a poor initial guess.

          (%i1) x: 1000$
          (%i2) thru 20 do x: 0.5*(x + 5.0/x)$
          (%i3) x;
          (%o3)                   2.23606797749979
          (%i4) sqrt(5), numer;
          (%o4)                   2.23606797749979

     If it is desired one may even omit the termination conditions
     entirely and just give ‘do <body>’ which will continue to evaluate
     the <body> indefinitely.  In this case the function ‘return’ should
     be used to terminate execution of the ‘do’.

          (%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x),
                    do (y: ev(df), x: x - f(x)/y,
                        if abs (f (x)) < 5e-6 then return (x)))$
          (%i2) sqr (x) := x^2 - 5.0$
          (%i3) newton (sqr, 1000);
          (%o3)                   2.236068027062195

     (Note that ‘return’, when executed, causes the current value of ‘x’
     to be returned as the value of the ‘do’.  The ‘block’ is exited and
     this value of the ‘do’ is returned as the value of the ‘block’
     because the ‘do’ is the last statement in the block.)

     One other form of the ‘do’ is available in Maxima.  The syntax is:

          for <variable> in <list> <end_tests> do <body>

     The elements of <list> are any expressions which will successively
     be assigned to the ‘variable’ on each iteration of the <body>.  The
     optional termination tests <end_tests> can be used to terminate
     execution of the ‘do’; otherwise it will terminate when the <list>
     is exhausted or when a ‘return’ is executed in the <body>.  (In
     fact, ‘list’ may be any non-atomic expression, and successive parts
     are taken.)

          (%i1)  for f in [log, rho, atan] do ldisp(f(1))$
          (%t1)                                  0
          (%t2)                                rho(1)
                                               %pi
          (%t3)                                 ---
                                                4
          (%i4) ev(%t3,numer);
          (%o4)                             0.78539816

 -- Function: errcatch (<expr_1>, ..., <expr_n>)

     Evaluates <expr_1>, ..., <expr_n> one by one and returns
     ‘[<expr_n>]’ (a list) if no error occurs.  If an error occurs in
     the evaluation of any argument, ‘errcatch’ prevents the error from
     propagating and returns the empty list ‘[]’ without evaluating any
     more arguments.

     ‘errcatch’ is useful in ‘batch’ files where one suspects an error
     might occur which would terminate the ‘batch’ if the error weren't
     caught.

     See also ‘errormsg’.

 -- Function: error (<expr_1>, ..., <expr_n>)
 -- System variable: error

     Evaluates and prints <expr_1>, ..., <expr_n>, and then causes an
     error return to top level Maxima or to the nearest enclosing
     ‘errcatch’.

     The variable ‘error’ is set to a list describing the error.  The
     first element of ‘error’ is a format string, which merges all the
     strings among the arguments <expr_1>, ..., <expr_n>, and the
     remaining elements are the values of any non-string arguments.

     ‘errormsg()’ formats and prints ‘error’.  This is effectively
     reprinting the most recent error message.

 -- Function: warning (<expr_1>, ..., <expr_n>)

     Evaluates and prints <expr_1>, ..., <expr_n>, as a warning message
     that is formatted in a standard way so a maxima front-end may be
     able to recognize the warning and to format it accordingly.

     The function ‘warning’ always returns false.

 -- Option variable: error_size
     Default value: 60

     ‘error_size’ modifies error messages according to the size of
     expressions which appear in them.  If the size of an expression (as
     determined by the Lisp function ‘ERROR-SIZE’) is greater than
     ‘error_size’, the expression is replaced in the message by a
     symbol, and the symbol is assigned the expression.  The symbols are
     taken from the list ‘error_syms’.

     Otherwise, the expression is smaller than ‘error_size’, and the
     expression is displayed in the message.

     See also ‘error’ and ‘error_syms’.

     Example:

     The size of ‘U’, as determined by ‘ERROR-SIZE’, is 24.

          (%i1) U: (C^D^E + B + A)/(cos(X-1) + 1)$

          (%i2) error_size: 20$

          (%i3) error ("Example expression is", U);

          Example expression is errexp1
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i4) errexp1;
                                      E
                                     D
                                    C   + B + A
          (%o4)                    --------------
                                   cos(X - 1) + 1
          (%i5) error_size: 30$

          (%i6) error ("Example expression is", U);

                                   E
                                  D
                                 C   + B + A
          Example expression is --------------
                                cos(X - 1) + 1
           -- an error.  Quitting.  To debug this try debugmode(true);

 -- Option variable: error_syms
     Default value: ‘[errexp1, errexp2, errexp3]’

     In error messages, expressions larger than ‘error_size’ are
     replaced by symbols, and the symbols are set to the expressions.
     The symbols are taken from the list ‘error_syms’.  The first
     too-large expression is replaced by ‘error_syms[1]’, the second by
     ‘error_syms[2]’, and so on.

     If there are more too-large expressions than there are elements of
     ‘error_syms’, symbols are constructed automatically, with the
     <n>-th symbol equivalent to ‘concat ('errexp, <n>)’.

     See also ‘error’ and ‘error_size’.

 -- Function: errormsg ()

     Reprints the most recent error message.  The variable ‘error’ holds
     the message, and ‘errormsg’ formats and prints it.

 -- Option variable: errormsg
     Default value: ‘true’

     When ‘false’ the output of error messages is suppressed.

     The option variable ‘errormsg’ can not be set in a block to a local
     value.  The global value of ‘errormsg’ is always present.

          (%i1) errormsg;
          (%o1)                         true
          (%i2) sin(a,b);
          sin: wrong number of arguments.
           -- an error. To debug this try: debugmode(true);
          (%i3) errormsg: false;
          (%o3)                         false
          (%i4) sin(a,b);
           -- an error. To debug this try: debugmode(true);

     The option variable ‘errormsg’ can not be set in a block to a local
     value.

          (%i1) f(bool):=block([errormsg:bool],
                               print ("value of errormsg is",errormsg))$
          (%i2) errormsg:true;
          (%o2)                         true
          (%i3) f(false);
          value of errormsg is true
          (%o3)                         true
          (%i4) errormsg:false;
          (%o4)                         false
          (%i5) f(true);
          value of errormsg is false
          (%o5)                         false

 -- Function: go (<tag>)

     is used within a ‘block’ to transfer control to the statement of
     the block which is tagged with the argument to ‘go’.  To tag a
     statement, precede it by an atomic argument as another statement in
     the ‘block’.  For example:

          block ([x], x:1, loop, x+1, ..., go(loop), ...)

     The argument to ‘go’ must be the name of a tag appearing in the
     same ‘block’.  One cannot use ‘go’ to transfer to tag in a ‘block’
     other than the one containing the ‘go’.

 -- Special operator: if

     Represents conditional evaluation.  Various forms of ‘if’
     expressions are recognized.

     ‘if <cond_1> then <expr_1> else <expr_0>’ evaluates to <expr_1> if
     <cond_1> evaluates to ‘true’, otherwise the expression evaluates to
     <expr_0>.

     The command ‘if <cond_1> then <expr_1> elseif <cond_2> then
     <expr_2> elseif ... else <expr_0>’ evaluates to <expr_k> if
     <cond_k> is ‘true’ and all preceding conditions are ‘false’.  If
     none of the conditions are ‘true’, the expression evaluates to
     ‘expr_0’.

     A trailing ‘else false’ is assumed if ‘else’ is missing.  That is,
     the command ‘if <cond_1> then <expr_1>’ is equivalent to ‘if
     <cond_1> then <expr_1> else false’, and the command ‘if <cond_1>
     then <expr_1> elseif ... elseif <cond_n> then <expr_n>’ is
     equivalent to ‘if <cond_1> then <expr_1> elseif ... elseif <cond_n>
     then <expr_n> else false’.

     The alternatives <expr_0>, ..., <expr_n> may be any Maxima
     expressions, including nested ‘if’ expressions.  The alternatives
     are neither simplified nor evaluated unless the corresponding
     condition is ‘true’.

     The conditions <cond_1>, ..., <cond_n> are expressions which
     potentially or actually evaluate to ‘true’ or ‘false’.  When a
     condition does not actually evaluate to ‘true’ or ‘false’, the
     behavior of ‘if’ is governed by the global flag ‘prederror’.  When
     ‘prederror’ is ‘true’, it is an error if any evaluated condition
     does not evaluate to ‘true’ or ‘false’.  Otherwise, conditions
     which do not evaluate to ‘true’ or ‘false’ are accepted, and the
     result is a conditional expression.

     Among other elements, conditions may comprise relational and
     logical operators as follows.

          Operation              Symbol         Type
          -------------------------------------------------------------
          less than              ‘<’            relational infix
          less than or equal     ‘<=’           relational infix
          to
          equality (syntactic)   ‘=’            relational infix
          equality (value)       ‘equal’        relational function
          negation of equal      ‘notequal’     relational function
          greater than or        ‘>=’           relational infix
          equal to
          greater than           ‘>’            relational infix
          and                    ‘and’          logical infix
          or                     ‘or’           logical infix
          not                    ‘not’          logical infix

 -- Function: map (<f>, <expr_1>, ..., <expr_n>)

     Returns an expression whose leading operator is the same as that of
     the expressions <expr_1>, ..., <expr_n> but whose subparts are the
     results of applying <f> to the corresponding subparts of the
     expressions.  <f> is either the name of a function of n arguments
     or is a ‘lambda’ form of n arguments.

     ‘maperror’ - if ‘false’ will cause all of the mapping functions to
     (1) stop when they finish going down the shortest <expr_i> if not
     all of the <expr_i> are of the same length and (2) apply <f> to
     [<expr_1>, <expr_2>, ...] if the <expr_i> are not all the same type
     of object.  If ‘maperror’ is ‘true’ then an error message will be
     given in the above two instances.

     One of the uses of this function is to ‘map’ a function (e.g.
     ‘partfrac’) onto each term of a very large expression where it
     ordinarily wouldn't be possible to use the function on the entire
     expression due to an exhaustion of list storage space in the course
     of the computation.

     See also ‘scanmap’, ‘maplist’, ‘outermap’, ‘matrixmap’ and ‘apply’.

          (%i1) map(f,x+a*y+b*z);
          (%o1)                        f(b z) + f(a y) + f(x)
          (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2));
                                     1       1        1
          (%o2)                     ----- - ----- + -------- + x
                                   x + 2   x + 1          2
                                                   (x + 1)
          (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y);
                                                1
          (%o3)                            y + ----- + 1
                                              x + 1
          (%i4) map("=",[a,b],[-0.5,3]);
          (%o4)                          [a = - 0.5, b = 3]



 -- Function: mapatom (<expr>)

     Returns ‘true’ if and only if <expr> is treated by the mapping
     routines as an atom.  "Mapatoms" are atoms, numbers (including
     rational numbers), subscripted variables and structure references.

 -- Option variable: maperror
     Default value: ‘true’

     When ‘maperror’ is ‘false’, causes all of the mapping functions,
     for example

          map (<f>, <expr_1>, <expr_2>, ...)

     to (1) stop when they finish going down the shortest <expr_i> if
     not all of the <expr_i> are of the same length and (2) apply <f> to
     [<expr_1>, <expr_2>, ...] if the <expr_i> are not all the same type
     of object.

     If ‘maperror’ is ‘true’ then an error message is displayed in the
     above two instances.

 -- Option variable: mapprint
     Default value: ‘true’

     When ‘mapprint’ is ‘true’, various information messages from ‘map’,
     ‘maplist’, and ‘fullmap’ are produced in certain situations.  These
     include situations where ‘map’ would use ‘apply’, or ‘map’ is
     truncating on the shortest list.

     If ‘mapprint’ is ‘false’, these messages are suppressed.

 -- Function: maplist (<f>, <expr_1>, ..., <expr_n>)

     Returns a list of the applications of <f> to the parts of the
     expressions <expr_1>, ..., <expr_n>.  <f> is the name of a
     function, or a lambda expression.

     ‘maplist’ differs from ‘map(<f>, <expr_1>, ..., <expr_n>)’ which
     returns an expression with the same main operator as <expr_i> has
     (except for simplifications and the case where ‘map’ does an
     ‘apply’).

 -- Option variable: prederror
     Default value: ‘false’

     When ‘prederror’ is ‘true’, an error message is displayed whenever
     the predicate of an ‘if’ statement or an ‘is’ function fails to
     evaluate to either ‘true’ or ‘false’.

     If ‘false’, ‘unknown’ is returned instead in this case.  The
     ‘prederror: false’ mode is not supported in translated code;
     however, ‘maybe’ is supported in translated code.

     See also ‘is’ and ‘maybe’.

 -- Function: return (<value>)
     May be used to exit explicitly from the current ‘block’, ‘while’,
     ‘for’ or ‘do’ loop bringing its argument.  It therefore can be
     compared with the ‘return’ statement found in other programming
     languages but it yields one difference: In maxima only returns from
     the current block, not from the entire function it was called in.
     In this aspect it more closely resembles the ‘break’ statement from
     C.

          (%i1) for i:1 thru 10 do o:i;
          (%o1)                         done
          (%i2) for i:1 thru 10 do if i=3 then return(i);
          (%o2)                           3
          (%i3) for i:1 thru 10 do
              (
                  block([i],
                      i:3,
                      return(i)
                  ),
                  return(8)
              );
          (%o3)                           8
          (%i4) block([i],
              i:4,
              block([o],
                  o:5,
                  return(o)
              ),
              return(i),
              return(10)
           );
          (%o4)                           4

     See also ‘for’, ‘while’, ‘do’ and ‘block’.

 -- Function: scanmap
          scanmap (<f>, <expr>)
          scanmap (<f>, <expr>, bottomup)

     Recursively applies <f> to <expr>, in a top down manner.  This is
     most useful when complete factorization is desired, for example:

          (%i1) exp:(a^2+2*a+1)*y + x^2$
          (%i2) scanmap(factor,exp);
                                              2      2
          (%o2)                         (a + 1)  y + x

     Note the way in which ‘scanmap’ applies the given function ‘factor’
     to the constituent subexpressions of <expr>; if another form of
     <expr> is presented to ‘scanmap’ then the result may be different.
     Thus, ‘%o2’ is not recovered when ‘scanmap’ is applied to the
     expanded form of ‘exp’:

          (%i3) scanmap(factor,expand(exp));
                                     2                  2
          (%o3)                      a  y + 2 a y + y + x

     Here is another example of the way in which ‘scanmap’ recursively
     applies a given function to all subexpressions, including
     exponents:

          (%i4) expr : u*v^(a*x+b) + c$
          (%i5) scanmap('f, expr);
                              f(f(f(a) f(x)) + f(b))
          (%o5) f(f(f(u) f(f(v)                      )) + f(c))

     ‘scanmap (<f>, <expr>, bottomup)’ applies <f> to <expr> in a
     bottom-up manner.  E.g., for undefined ‘f’,

          scanmap(f,a*x+b) ->
             f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b))
          scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b)
              -> f(f(a)*f(x))+f(b) ->
               f(f(f(a)*f(x))+f(b))

     In this case, you get the same answer both ways.

 -- Function: throw (<expr>)

     Evaluates <expr> and throws the value back to the most recent
     ‘catch’.  ‘throw’ is used with ‘catch’ as a nonlocal return
     mechanism.

 -- Function: outermap (<f>, <a_1>, ..., <a_n>)

     Applies the function <f> to each one of the elements of the outer
     product <a_1> cross <a_2> ... cross <a_n>.

     <f> is the name of a function of n arguments or a lambda expression
     of n arguments.  Each argument <a_k> may be a list or nested list,
     or a matrix, or any other kind of expression.

     The ‘outermap’ return value is a nested structure.  Let <x> be the
     return value.  Then <x> has the same structure as the first list,
     nested list, or matrix argument, ‘<x>[i_1]...[i_m]’ has the same
     structure as the second list, nested list, or matrix argument,
     ‘<x>[i_1]...[i_m][j_1]...[j_n]’ has the same structure as the third
     list, nested list, or matrix argument, and so on, where <m>, <n>,
     ... are the numbers of indices required to access the elements of
     each argument (one for a list, two for a matrix, one or more for a
     nested list).  Arguments which are not lists or matrices have no
     effect on the structure of the return value.

     Note that the effect of ‘outermap’ is different from that of
     applying <f> to each one of the elements of the outer product
     returned by ‘cartesian_product’.  ‘outermap’ preserves the
     structure of the arguments in the return value, while
     ‘cartesian_product’ does not.

     ‘outermap’ evaluates its arguments.

     See also ‘map’, ‘maplist’, and ‘apply’.

     Examples:

     Elementary examples of ‘outermap’.  To show the argument
     combinations more clearly, ‘F’ is left undefined.

          (%i1) outermap (F, [a, b, c], [1, 2, 3]);
          (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)],
                                               [F(c, 1), F(c, 2), F(c, 3)]]
          (%i2) outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4]));
                   [ [ F(a, 1)  F(a, 2) ]  [ F(b, 1)  F(b, 2) ] ]
                   [ [                  ]  [                  ] ]
                   [ [ F(a, 3)  F(a, 4) ]  [ F(b, 3)  F(b, 4) ] ]
          (%o2)    [                                            ]
                   [ [ F(c, 1)  F(c, 2) ]  [ F(d, 1)  F(d, 2) ] ]
                   [ [                  ]  [                  ] ]
                   [ [ F(c, 3)  F(c, 4) ]  [ F(d, 3)  F(d, 4) ] ]
          (%i3) outermap (F, [a, b], x, matrix ([1, 2], [3, 4]));
                 [ F(a, x, 1)  F(a, x, 2) ]  [ F(b, x, 1)  F(b, x, 2) ]
          (%o3) [[                        ], [                        ]]
                 [ F(a, x, 3)  F(a, x, 4) ]  [ F(b, x, 3)  F(b, x, 4) ]
          (%i4) outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y]));
                 [ [ F(a, 1, x) ]  [ F(a, 2, x) ] ]
          (%o4) [[ [            ]  [            ] ],
                 [ [ F(a, 1, y) ]  [ F(a, 2, y) ] ]
                                        [ [ F(b, 1, x) ]  [ F(b, 2, x) ] ]
                                        [ [            ]  [            ] ]]
                                        [ [ F(b, 1, y) ]  [ F(b, 2, y) ] ]
          (%i5) outermap ("+", [a, b, c], [1, 2, 3]);
          (%o5) [[a + 1, a + 2, a + 3], [b + 1, b + 2, b + 3],
                                                     [c + 1, c + 2, c + 3]]

     A closer examination of the ‘outermap’ return value.  The first,
     second, and third arguments are a matrix, a list, and a matrix,
     respectively.  The return value is a matrix.  Each element of that
     matrix is a list, and each element of each list is a matrix.

          (%i1) arg_1 :  matrix ([a, b], [c, d]);
                                      [ a  b ]
          (%o1)                       [      ]
                                      [ c  d ]
          (%i2) arg_2 : [11, 22];
          (%o2)                       [11, 22]
          (%i3) arg_3 : matrix ([xx, yy]);
          (%o3)                      [ xx  yy ]
          (%i4) xx_0 : outermap (lambda ([x, y, z], x / y + z), arg_1,
                                                             arg_2, arg_3);
                         [  [      a        a  ]  [      a        a  ]  ]
                         [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                         [  [      11       11 ]  [      22       22 ]  ]
          (%o4)  Col 1 = [                                              ]
                         [  [      c        c  ]  [      c        c  ]  ]
                         [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                         [  [      11       11 ]  [      22       22 ]  ]
                           [  [      b        b  ]  [      b        b  ]  ]
                           [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                           [  [      11       11 ]  [      22       22 ]  ]
                   Col 2 = [                                              ]
                           [  [      d        d  ]  [      d        d  ]  ]
                           [ [[ xx + --  yy + -- ], [ xx + --  yy + -- ]] ]
                           [  [      11       11 ]  [      22       22 ]  ]
          (%i5) xx_1 : xx_0 [1][1];
                     [      a        a  ]  [      a        a  ]
          (%o5)     [[ xx + --  yy + -- ], [ xx + --  yy + -- ]]
                     [      11       11 ]  [      22       22 ]
          (%i6) xx_2 : xx_0 [1][1] [1];
                                [      a        a  ]
          (%o6)                 [ xx + --  yy + -- ]
                                [      11       11 ]
          (%i7) xx_3 : xx_0 [1][1] [1] [1][1];
                                            a
          (%o7)                        xx + --
                                            11
          (%i8) [op (arg_1), op (arg_2), op (arg_3)];
          (%o8)                  [matrix, [, matrix]
          (%i9) [op (xx_0), op (xx_1), op (xx_2)];
          (%o9)                  [matrix, [, matrix]

     ‘outermap’ preserves the structure of the arguments in the return
     value, while ‘cartesian_product’ does not.

          (%i1) outermap (F, [a, b, c], [1, 2, 3]);
          (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)],
                                               [F(c, 1), F(c, 2), F(c, 3)]]
          (%i2) setify (flatten (%));
          (%o2) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3),
                                                 F(c, 1), F(c, 2), F(c, 3)}
          (%i3) map (lambda ([L], apply (F, L)),
                               cartesian_product ({a, b, c}, {1, 2, 3}));
          (%o3) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3),
                                                 F(c, 1), F(c, 2), F(c, 3)}
          (%i4) is (equal (%, %th (2)));
          (%o4)                         true


File: maxima.info,  Node: Debugging,  Next: Package alt-display,  Prev: Program Flow,  Up: Top

38 Debugging
************

* Menu:

* Source Level Debugging::
* Keyword Commands::
* Functions and Variables for Debugging::


File: maxima.info,  Node: Source Level Debugging,  Next: Keyword Commands,  Up: Debugging

38.1 Source Level Debugging
===========================

Maxima has a built-in source level debugger.  The user can set a
breakpoint at a function, and then step line by line from there.  The
call stack may be examined, together with the variables bound at that
level.

   The command ‘:help’ or ‘:h’ shows the list of debugger commands.  (In
general, commands may be abbreviated if the abbreviation is unique.  If
not unique, the alternatives will be listed.)  Within the debugger, the
user can also use any ordinary Maxima functions to examine, define, and
manipulate variables and expressions.

   A breakpoint is set by the ‘:br’ command at the Maxima prompt.
Within the debugger, the user can advance one line at a time using the
‘:n’ ("next") command.  The ‘:bt’ ("backtrace") command shows a list of
stack frames.  The ‘:r’ ("resume") command exits the debugger and
continues with execution.  These commands are demonstrated in the
example below.

     (%i1) load ("/tmp/foobar.mac");

     (%o1)                           /tmp/foobar.mac

     (%i2) :br foo
     Turning on debugging debugmode(true)
     Bkpt 0 for foo (in /tmp/foobar.mac line 1)

     (%i2) bar (2,3);
     Bkpt 0:(foobar.mac 1)
     /tmp/foobar.mac:1::

     (dbm:1) :bt                        <-- :bt typed here gives a backtrace
     #0: foo(y=5)(foobar.mac line 1)
     #1: bar(x=2,y=3)(foobar.mac line 9)

     (dbm:1) :n                         <-- Here type :n to advance line
     (foobar.mac 2)
     /tmp/foobar.mac:2::

     (dbm:1) :n                         <-- Here type :n to advance line
     (foobar.mac 3)
     /tmp/foobar.mac:3::

     (dbm:1) u;                         <-- Investigate value of u
     28

     (dbm:1) u: 33;                     <-- Change u to be 33
     33

     (dbm:1) :r                         <-- Type :r to resume the computation

     (%o2)                                1094

   The file ‘/tmp/foobar.mac’ is the following:

     foo(y) := block ([u:y^2],
       u: u+3,
       u: u^2,
       u);

     bar(x,y) := (
       x: x+2,
       y: y+2,
       x: foo(y),
       x+y);

   USE OF THE DEBUGGER THROUGH EMACS

   If the user is running the code under GNU emacs in a shell window
(dbl shell), or is running the graphical interface version, Xmaxima,
then if he stops at a break point, he will see his current position in
the source file which will be displayed in the other half of the window,
either highlighted in red, or with a little arrow pointing at the right
line.  He can advance single lines at a time by typing M-n (Alt-n).

   Under Emacs you should run in a ‘dbl’ shell, which requires the
‘dbl.el’ file in the elisp directory.  Make sure you install the elisp
files or add the Maxima elisp directory to your path: e.g., add the
following to your ‘.emacs’ file or the ‘site-init.el’

     (setq load-path (cons "/usr/share/maxima/5.9.1/emacs" load-path))
     (autoload 'dbl "dbl")

   then in emacs

     M-x dbl

   should start a shell window in which you can run programs, for
example Maxima, gcl, gdb etc.  This shell window also knows about source
level debugging, and display of source code in the other window.

   The user may set a break point at a certain line of the file by
typing ‘C-x space’.  This figures out which function the cursor is in,
and then it sees which line of that function the cursor is on.  If the
cursor is on, say, line 2 of ‘foo’, then it will insert in the other
window the command, "‘:br foo 2’", to break ‘foo’ at its second line.
To have this enabled, the user must have maxima-mode.el turned on in the
window in which the file ‘foobar.mac’ is visiting.  There are additional
commands available in that file window, such as evaluating the function
into the Maxima, by typing ‘Alt-Control-x’.


File: maxima.info,  Node: Keyword Commands,  Next: Functions and Variables for Debugging,  Prev: Source Level Debugging,  Up: Debugging

38.2 Keyword Commands
=====================

Keyword commands are special keywords which are not interpreted as
Maxima expressions.  A keyword command can be entered at the Maxima
prompt or the debugger prompt, although not at the break prompt.
Keyword commands start with a colon, '‘:’'.  For example, to evaluate a
Lisp form you may type ‘:lisp’ followed by the form to be evaluated.

     (%i1) :lisp (+ 2 3)
     5

   The number of arguments taken depends on the particular command.
Also, you need not type the whole command, just enough to be unique
among the break keywords.  Thus ‘:br’ would suffice for ‘:break’.

   The keyword commands are listed below.

‘:break F n’
     Set a breakpoint in function ‘F’ at line offset ‘n’ from the
     beginning of the function.  If ‘F’ is given as a string, then it is
     assumed to be a file, and ‘n’ is the offset from the beginning of
     the file.  The offset is optional.  If not given, it is assumed to
     be zero (first line of the function or file).
‘:bt’
     Print a backtrace of the stack frames
‘:continue’
     Continue the computation
‘:delete’
     Delete the specified breakpoints, or all if none are specified
‘:disable’
     Disable the specified breakpoints, or all if none are specified
‘:enable’
     Enable the specified breakpoints, or all if none are specified
‘:frame n’
     Print stack frame ‘n’, or the current frame if none is specified
‘:help’
     Print help on a debugger command, or all commands if none is
     specified
‘:info’
     Print information about item
‘:lisp some-form’
     Evaluate ‘some-form’ as a Lisp form
‘:lisp-quiet some-form’
     Evaluate Lisp form ‘some-form’ without any output
‘:next’
     Like ‘:step’, except ‘:next’ steps over function calls
‘:quit’
     Quit the current debugger level without completing the computation
‘:resume’
     Continue the computation
‘:step’
     Continue the computation until it reaches a new source line
‘:top’
     Return to the Maxima prompt (from any debugger level) without
     completing the computation

   Note: Keyword commands must (currently) start at the beginning of a
line.  Not even a single space character is allowed before the colon.


File: maxima.info,  Node: Functions and Variables for Debugging,  Prev: Keyword Commands,  Up: Debugging

38.3 Functions and Variables for Debugging
==========================================

 -- Option variable: debugmode
     Default value: ‘false’

     When ‘debugmode’ is ‘true’, Maxima will start the Maxima debugger
     when a Maxima error occurs.  At this point the user may enter
     commands to examine the call stack, set breakpoints, step through
     Maxima code, and so on.  See ‘debugging’ for a list of Maxima
     debugger commands.

     When ‘debugmode’ is ‘lisp’, Maxima will start the Lisp debugger
     when a Maxima error occurs.

     In either case, enabling ‘debugmode’ will not catch Lisp errors.

 -- Option variable: refcheck
     Default value: ‘false’

     When ‘refcheck’ is ‘true’, Maxima prints a message each time a
     bound variable is used for the first time in a computation.

 -- Option variable: setcheck
     Default value: ‘false’

     If ‘setcheck’ is set to a list of variables (which can be
     subscripted), Maxima prints a message whenever the variables, or
     subscripted occurrences of them, are bound with the ordinary
     assignment operator ‘:’, the ‘::’ assignment operator, or function
     argument binding, but not the function assignment ‘:=’ nor the
     macro assignment ‘::=’ operators.  The message comprises the name
     of the variable and the value it is bound to.

     ‘setcheck’ may be set to ‘all’ or ‘true’ thereby including all
     variables.

     Each new assignment of ‘setcheck’ establishes a new list of
     variables to check, and any variables previously assigned to
     ‘setcheck’ are forgotten.

     The names assigned to ‘setcheck’ must be quoted if they would
     otherwise evaluate to something other than themselves.  For
     example, if ‘x’, ‘y’, and ‘z’ are already bound, then enter

          setcheck: ['x, 'y, 'z]$

     to put them on the list of variables to check.

     No printout is generated when a variable on the ‘setcheck’ list is
     assigned to itself, e.g., ‘X: 'X’.

 -- Option variable: setcheckbreak
     Default value: ‘false’

     When ‘setcheckbreak’ is ‘true’, Maxima will present a break prompt
     whenever a variable on the ‘setcheck’ list is assigned a new value.
     The break occurs before the assignment is carried out.  At this
     point, ‘setval’ holds the value to which the variable is about to
     be assigned.  Hence, one may assign a different value by assigning
     to ‘setval’.

     See also ‘setcheck’ and ‘setval’.

 -- System variable: setval

     Holds the value to which a variable is about to be set when a
     ‘setcheckbreak’ occurs.  Hence, one may assign a different value by
     assigning to ‘setval’.

     See also ‘setcheck’ and ‘setcheckbreak’.

 -- Function: timer (<f_1>, ..., <f_n>)
          timer (all)
          timer ()

     Given functions <f_1>, ..., <f_n>, ‘timer’ puts each one on the
     list of functions for which timing statistics are collected.
     ‘timer(f)$ timer(g)$’ puts ‘f’ and then ‘g’ onto the list; the list
     accumulates from one call to the next.

     ‘timer(all)’ puts all user-defined functions (as named by the
     global variable ‘functions’) on the list of timed functions.

     With no arguments, ‘timer’ returns the list of timed functions.

     Maxima records how much time is spent executing each function on
     the list of timed functions.  ‘timer_info’ returns the timing
     statistics, including the average time elapsed per function call,
     the number of calls, and the total time elapsed.  ‘untimer’ removes
     functions from the list of timed functions.

     ‘timer’ quotes its arguments.  ‘f(x) := x^2$ g:f$ timer(g)$’ does
     not put ‘f’ on the timer list.

     If ‘trace(f)’ is in effect, then ‘timer(f)’ has no effect; ‘trace’
     and ‘timer’ cannot both be in effect at the same time.

     See also ‘timer_devalue’.

 -- Function: untimer (<f_1>, ..., <f_n>)
          untimer ()

     Given functions <f_1>, ..., <f_n>, ‘untimer’ removes each function
     from the timer list.

     With no arguments, ‘untimer’ removes all functions currently on the
     timer list.

     After ‘untimer (f)’ is executed, ‘timer_info (f)’ still returns
     previously collected timing statistics, although ‘timer_info()’
     (with no arguments) does not return information about any function
     not currently on the timer list.  ‘timer (f)’ resets all timing
     statistics to zero and puts ‘f’ on the timer list again.

 -- Option variable: timer_devalue
     Default value: ‘false’

     When ‘timer_devalue’ is ‘true’, Maxima subtracts from each timed
     function the time spent in other timed functions.  Otherwise, the
     time reported for each function includes the time spent in other
     functions.  Note that time spent in untimed functions is not
     subtracted from the total time.

     See also ‘timer’ and ‘timer_info’.

 -- Function: timer_info (<f_1>, ..., <f_n>)
          timer_info ()

     Given functions <f_1>, ..., <f_n>, ‘timer_info’ returns a matrix
     containing timing information for each function.  With no
     arguments, ‘timer_info’ returns timing information for all
     functions currently on the timer list.

     The matrix returned by ‘timer_info’ contains the function name,
     time per function call, number of function calls, total time, and
     ‘gctime’, which meant "garbage collection time" in the original
     Macsyma but is now always zero.

     The data from which ‘timer_info’ constructs its return value can
     also be obtained by the ‘get’ function:

          get(f, 'calls);  get(f, 'runtime);  get(f, 'gctime);

     See also ‘timer’.

 -- Function: trace (<f_1>, ..., <f_n>)
          trace (all)
          trace ()

     Given functions <f_1>, ..., <f_n>, ‘trace’ instructs Maxima to
     print out debugging information whenever those functions are
     called.  ‘trace(f)$ trace(g)$’ puts ‘f’ and then ‘g’ onto the list
     of functions to be traced; the list accumulates from one call to
     the next.

     ‘trace(all)’ puts all user-defined functions (as named by the
     global variable ‘functions’) on the list of functions to be traced.

     With no arguments, ‘trace’ returns a list of all the functions
     currently being traced.

     The ‘untrace’ function disables tracing.  See also ‘trace_options’.

     ‘trace’ quotes its arguments.  Thus, ‘f(x) := x^2$ g:f$ trace(g)$’
     does not put ‘f’ on the trace list.

     When a function is redefined, it is removed from the timer list.
     Thus after ‘timer(f)$ f(x) := x^2$’, function ‘f’ is no longer on
     the timer list.

     If ‘timer (f)’ is in effect, then ‘trace (f)’ has no effect;
     ‘trace’ and ‘timer’ can't both be in effect for the same function.

 -- Function: trace_options (<f>, <option_1>, ..., <option_n>)
          trace_options (<f>)

     Sets the trace options for function <f>.  Any previous options are
     superseded.  ‘trace_options (<f>, ...)’ has no effect unless ‘trace
     (<f>)’ is also called (either before or after ‘trace_options’).

     ‘trace_options (<f>)’ resets all options to their default values.

     The option keywords are:

        • ‘noprint’ Do not print a message at function entry and exit.
        • ‘break’ Put a breakpoint before the function is entered, and
          after the function is exited.  See ‘break’.
        • ‘lisp_print’ Display arguments and return values as Lisp
          objects.
        • ‘info’ Print ‘-> true’ at function entry and exit.
        • ‘errorcatch’ Catch errors, giving the option to signal an
          error, retry the function call, or specify a return value.

     Trace options are specified in two forms.  The presence of the
     option keyword alone puts the option into effect unconditionally.
     (Note that option <foo> is not put into effect by specifying
     ‘<foo>: true’ or a similar form; note also that keywords need not
     be quoted.)  Specifying the option keyword with a predicate
     function makes the option conditional on the predicate.

     The argument list to the predicate function is always ‘[level,
     direction, function, item]’ where ‘level’ is the recursion level
     for the function, ‘direction’ is either ‘enter’ or ‘exit’,
     ‘function’ is the name of the function, and ‘item’ is the argument
     list (on entering) or the return value (on exiting).

     Here is an example of unconditional trace options:

          (%i1) ff(n) := if equal(n, 0) then 1 else n * ff(n - 1)$

          (%i2) trace (ff)$

          (%i3) trace_options (ff, lisp_print, break)$

          (%i4) ff(3);

     Here is the same function, with the ‘break’ option conditional on a
     predicate:

          (%i5) trace_options (ff, break(pp))$

          (%i6) pp (level, direction, function, item) := block (print (item),
              return (function = 'ff and level = 3 and direction = exit))$

          (%i7) ff(6);

 -- Function: untrace
          untrace (<f_1>, ..., <f_n>)
          untrace ()

     Given functions <f_1>, ..., <f_n>, ‘untrace’ disables tracing
     enabled by the ‘trace’ function.  With no arguments, ‘untrace’
     disables tracing for all functions.

     ‘untrace’ returns a list of the functions for which it disabled
     tracing.


File: maxima.info,  Node: Package alt-display,  Next: Package asympa,  Prev: Debugging,  Up: Top

39 Package alt-display
**********************

* Menu:

* Introduction to alt-display::
* Functions and Variables for alt-display::


File: maxima.info,  Node: Introduction to alt-display,  Next: Functions and Variables for alt-display,  Prev: Package alt-display,  Up: Package alt-display

39.1 Introduction to alt-display
================================

The _alt-display_ package provides a means to change the way that Maxima
displays its output.  The <*alt-display1d*> and <*alt-display2d*> Lisp
hooks were introduced to Maxima in 2002, but were not easily accessible
from the Maxima REPL until the introduction of this package.

   The package provides a general purpose function to define alternative
display functions, and a separate function to set the display function.
The package also provides customized display functions to produce output
in TeX, Texinfo, XML and all three output formats within Texinfo.

   Here is a sample session:

     (%i1) load("alt-display.mac")$
     (%i2) set_alt_display(2,tex_display)$

     (%i3) x/(x^2+y^2) = 1;
     \mbox{\tt\red({\it \%o_3}) \black}$${{x}\over{y^2+x^2}}=1$$

     (%i4) set_alt_display(2,mathml_display)$

     (%i5) x/(x^2+y^2) = 1;
     <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi>mlabel</mi>
     <mfenced separators=""><msub><mi>%o</mi> <mn>5</mn></msub>
     <mo>,</mo><mfrac><mrow><mi>x</mi> </mrow> <mrow><msup><mrow>
     <mi>y</mi> </mrow> <mn>2</mn> </msup> <mo>+</mo> <msup><mrow>
     <mi>x</mi> </mrow> <mn>2</mn> </msup> </mrow></mfrac> <mo>=</mo>
     <mn>1</mn> </mfenced> </math>

     (%i6) set_alt_display(2,multi_display_for_texinfo)$

     (%i7) x/(x^2+y^2) = 1;

     @iftex
     @tex
     \mbox{\tt\red({\it \%o_7}) \black}$${{x}\over{y^2+x^2}}=1$$
     @end tex
     @end iftex
     @ifhtml
     @html

     <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi>mlabel</mi>
     <mfenced separators=""><msub><mi>%o</mi> <mn>7</mn></msub>
     <mo>,</mo><mfrac><mrow><mi>x</mi> </mrow> <mrow><msup><mrow>
     <mi>y</mi> </mrow> <mn>2</mn> </msup> <mo>+</mo> <msup><mrow>
     <mi>x</mi> </mrow> <mn>2</mn> </msup> </mrow></mfrac> <mo>=</mo>
     <mn>1</mn> </mfenced> </math>
     @end html
     @end ifhtml
     @ifinfo
     @example
     (%o7) x/(y^2+x^2) = 1
     @end example
     @end ifinfo

   If the alternative display function causes an error, the error is
trapped and the display function is reset to the default display.  In
the following example, the ‘error’ function is set to display the
output.  This throws an error, which is handled by resetting the
2d-display to the default.

     (%i8) set_alt_display(2,?error)$

     (%i9) x;

     Error in *alt-display2d*.
     Message: Condition designator ((MLABEL) $%O9 $X) is not of type
             (OR SYMBOL STRING FUNCTION).
     *alt-display2d* reset to nil.
      -- an error. To debug this try: debugmode(true);

     (%i10) x;
     (%o10)                                 x


File: maxima.info,  Node: Functions and Variables for alt-display,  Prev: Introduction to alt-display,  Up: Package alt-display

39.2 Functions and Variables for alt-display
============================================

 -- Function: alt_display_output_type (<form>)

     Determine the type of output to be printed.  <Form> must be a lisp
     form suitable for printing via Maxima's built-in ‘displa’ function.
     At present, this function returns one of three values: <text>,
     <label> or <unknown>.

     An example where ‘alt_display_output_type’ is used.  In
     ‘my_display’, a text form is printed between a pair of tags TEXT;>>
     and <<TEXT; while a label form is printed between a pair tags
     OUT;>> and <<OUT; in addition to the usual output label.

     The function ‘set_prompt’ also ensures that input labels are
     printed between matching PROMPT;>> and <<PROMPT; tags.

     Thanks to Eric Stemmler
     (https://sourceforge.net/p/maxima/mailman/maxima-discuss/thread/7792c096-7e07-842d-0c3a-b2f039ef1f15%40gmail.com/#msg37235035).

     (%i1) (load("mactex-utilities"), load("alt-display.mac")) $
     
     (%i2) define_alt_display(my_display(form),
     block([type,txttmplt,labtmplt], 
     txttmplt:"~%TEXT;>>~%~a~%<<TEXT;~%",
     labtmplt:"~%OUT;>>~%(~a) ~a~a~a~%<<OUT;~%",
     type:alt_display_output_type(form),
     if type='text then 
        printf(true,txttmplt,first(form))
     else if type='label then 
          printf(true,labtmplt,first(form),"$$",tex1(second(form)),"$$")
     else 
          block([alt_display1d:false, alt_display2d:false], displa(form)))) $
     
     (%i3) (set_prompt('prefix, "PROMPT;>>",'suffix, "<<PROMPT;"), 
           set_alt_display(1,my_display)) $
     
     PROMPT;>>(%i4) <<PROMPT;integrate(x^n,x);
     PROMPT;>>
     TEXT;>>
     Is n equal to -1?
     <<TEXT;
     <<PROMPT;
     n;
     
     OUT;>>
     (%o4) $$\frac{x^{n+1}}{n+1}$$
     <<OUT;
     PROMPT;>>(%i5) <<PROMPT;

 -- Function: define_alt_display (<function>(<input>), <expr>)
     This function is similar to ‘define’: it evaluates its arguments
     and expands into a function definition.  The <function> is a
     function of a single input <input>.  For convenience, a
     substitution is applied to <expr> after evaluation, to provide easy
     access to Lisp variable names.

     Set a time-stamp on each prompt:
          (%i1) load("alt-display.mac")$

          (%i2) display2d: false$

          (%i3) define_alt_display(time_stamp(x),
                          block([alt_display1d:false,alt_display2d:false],
                                prompt_prefix:printf(false,"~a~%",timedate()),
                                displa(x)));

          (%o3) time_stamp(x):=block(
                           [\*alt\-display1d\*:false,
                            \*alt\-display2d\*:false],
                           \*prompt\-prefix\*
                            :printf(false,"~a~%",timedate()),displa(x))
          (%i4) set_alt_display(1,time_stamp);

          (%o4) done
          2017-11-27 16:15:58-06:00
          (%i5)

     The input line ‘%i3’ defines ‘time_stamp’ using
     ‘define_alt_display’.  The output line ‘%o3’ shows that the Maxima
     variable names ‘alt_display1d’, ‘alt_display2d’ and ‘prompt_prefix’
     have been replaced by their Lisp translations, as has ‘displa’ been
     replaced by ‘?displa’ (the display function).

     The display variables ‘alt_display1d’ and ‘alt_display2d’ are both
     bound to ‘false’ in the body of ‘time_stamp’ to prevent an infinite
     recursion in ‘displa’.

 -- Function: info_display (<form>)
     This is an alias for the default 1-d display function.  It may be
     used as an alternative 1-d or 2-d display function.

          (%i1) load("alt-display.mac")$

          (%i2) set_alt_display(2,info_display);

          (%o2) done
          (%i3) x/y;

          (%o3) x/y

 -- Function: mathml_display (<form>)
     Produces MathML output.

          (%i1) load("alt-display.mac")$

          (%i2) set_alt_display(2,mathml_display);
          <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi>mlabel</mi>
           <mfenced separators=""><msub><mi>%o</mi> <mn>2</mn></msub>
           <mo>,</mo><mi>done</mi> </mfenced> </math>

 -- Function: tex_display (<form>)
     Produces TeX output.

          (%i2) set_alt_display(2,tex_display);
          \mbox{\tt\red({\it \%o_2}) \black}$$\mathbf{done}$$
          (%i3) x/(x^2+y^2);
          \mbox{\tt\red({\it \%o_3}) \black}$${{x}\over{y^2+x^2}}$$

 -- Function: multi_display_for_texinfo (<form>)
     Produces Texinfo output using all three display functions.

          (%i2) set_alt_display(2,multi_display_for_texinfo)$

          (%i3) x/(x^2+y^2);

          @iftex
          @tex
          \mbox{\tt\red({\it \%o_3}) \black}$${{x}\over{y^2+x^2}}$$
          @end tex
          @end iftex
          @ifhtml
          @html

             <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi>mlabel</mi>
             <mfenced separators=""><msub><mi>%o</mi> <mn>3</mn></msub>
             <mo>,</mo><mfrac><mrow><mi>x</mi> </mrow> <mrow><msup><mrow>
             <mi>y</mi> </mrow> <mn>2</mn> </msup> <mo>+</mo> <msup><mrow>
             <mi>x</mi> </mrow> <mn>2</mn> </msup> </mrow></mfrac> </mfenced> </math>
          @end html
          @end ifhtml
          @ifinfo
          @example
          (%o3) x/(y^2+x^2)
          @end example
          @end ifinfo

 -- Functions: reset_displays ()
     Resets the prompt prefix and suffix to the empty string, and sets
     both 1-d and 2-d display functions to the default.

 -- Function: set_alt_display (<num>, <display-function>)
     The input <num> is the display to set; it may be either 1 or 2.
     The second input <display-function> is the display function to use.
     The display function may be either a Maxima function or a ‘lambda’
     expression.

     Here is an example where the display function is a ‘lambda’
     expression; it just displays the result as TeX.
          (%i1) load("alt-display.mac")$

          (%i2) set_alt_display(2, lambda([form], tex(?caddr(form))))$

          (%i3) integrate(exp(-t^2),t,0,inf);
          $${{\sqrt{\pi}}\over{2}}$$

     A user-defined display function should take care that it _prints_
     its output.  A display function that returns a string will appear
     to display nothing, nor cause any errors.

 -- Function: set_prompt (<fix>, <expr>)
     Set the prompt prefix or suffix to <expr>.  The input <fix> must
     evaluate to one of ‘prefix’, ‘suffix’, ‘general’, ‘prolog’ or
     ‘epilog’.  The input <expr> must evaluate to either a string or
     ‘false’; if ‘false’, the <fix> is reset to the default value.

          (%i1) load("alt-display.mac")$
          (%i2) set_prompt('prefix,printf(false,"It is now: ~a~%",timedate()))$

          It is now: 2014-01-07 15:23:23-05:00
          (%i3)

     The following example shows the effect of each option, except
     ‘prolog’.  Note that the ‘epilog’ prompt is printed as Maxima
     closes down.  The ‘general’ is printed between the end of input and
     the output, unless the input line ends in ‘$’.

     Here is an example to show where the prompt strings are placed.

          (%i1) load("alt-display.mac")$

          (%i2) set_prompt(prefix, "<<prefix>> ", suffix, "<<suffix>> ",
                           general, printf(false,"<<general>>~%"),
                           epilog, printf(false,"<<epilog>>~%"));

          (%o2)                                done
          <<prefix>> (%i3) <<suffix>> x/y;
          <<general>>
                                                 x
          (%o3)                                  -
                                                 y
          <<prefix>> (%i4) <<suffix>> quit();
          <<general>>
          <<epilog>>

     Here is an example that shows how to colorize the input and output
     when Maxima is running in a terminal or terminal emulator like
     Emacs(1).

          (%i1) load("alt-display.mac")$

          (%i2) cs(s) := printf(false,"~a[~am",ascii(27),s)$

          (%i3) set_prompt(prefix,cs("1;31"),suffix,cs("0;32"),general,cs("1;34"),epilog,cs("00;"));
          (%o3)                                done
          [1;31m(%i4)[0;32m integrate(exp(-x^2),x,0,inf);[1;34m
                                             sqrt(%pi)
          (%o4)                              ---------
                                                 2
          [1;31m(%i5)[00;m

     Each prompt string starts with the ASCII escape character (27)
     followed by an open square bracket (91); each string ends with a
     lower-case m (109).  The webpages
     <https://misc.flogisoft.com/bash/tip_colors_and_formatting> and
     <https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html> provide
     information on how to use control strings to set the terminal
     colors.

   ---------- Footnotes ----------

   (1) Readers using the ‘info’ reader in ‘Emacs’ will see the actual
prompt strings; other readers will see the colorized output


File: maxima.info,  Node: Package asympa,  Next: Package augmented_lagrangian,  Prev: Package alt-display,  Up: Top

40 Package asympa
*****************

* Menu:

* Introduction to asympa::
* Functions and variables for asympa::


File: maxima.info,  Node: Introduction to asympa,  Next: Functions and variables for asympa,  Prev: Package asympa,  Up: Package asympa

40.1 Introduction to asympa
===========================

 -- Function: asympa
     ‘asympa’ is a package for asymptotic analysis.  The package
     contains simplification functions for asymptotic analysis,
     including the "big O" and "little o" functions that are widely used
     in complexity analysis and numerical analysis.

     ‘load ("asympa")’ loads this package.


File: maxima.info,  Node: Functions and variables for asympa,  Prev: Introduction to asympa,  Up: Package asympa

40.2 Functions and variables for asympa
=======================================


File: maxima.info,  Node: Package augmented_lagrangian,  Next: Package bernstein,  Prev: Package asympa,  Up: Top

41 Package augmented_lagrangian
*******************************

* Menu:

* Functions and Variables for augmented_lagrangian::


File: maxima.info,  Node: Functions and Variables for augmented_lagrangian,  Prev: Package augmented_lagrangian,  Up: Package augmented_lagrangian

41.1 Functions and Variables for augmented_lagrangian
=====================================================

 -- Function: augmented_lagrangian_method
          augmented_lagrangian_method (<FOM>, <xx>, <C>, <yy>)
          augmented_lagrangian_method (<FOM>, <xx>, <C>, <yy>,
          optional_args)
          augmented_lagrangian_method ([<FOM>, <grad>], <xx>, <C>, <yy>)

          augmented_lagrangian_method ([<FOM>, <grad>], <xx>, <C>, <yy>,
          optional_args)

     Returns an approximate minimum of the expression <FOM> with respect
     to the variables <xx>, holding the constraints <C> equal to zero.
     <yy> is a list of initial guesses for <xx>.  The method employed is
     the augmented Lagrangian method (see Refs [1] and [2]).

     <grad>, if present, is the gradient of <FOM> with respect to <xx>,
     represented as a list of expressions, one for each variable in
     <xx>.  If not present, the gradient is constructed automatically.

     <FOM> and each element of <grad>, if present, must be ordinary
     expressions, not names of functions or lambda expressions.

     ‘optional_args’ represents additional arguments, specified as
     ‘<symbol> = <value>’.  The optional arguments recognized are:

     ‘niter’
          Number of iterations of the augmented Lagrangian algorithm
     ‘lbfgs_tolerance’
          Tolerance supplied to LBFGS
     ‘iprint’
          IPRINT parameter (a list of two integers which controls
          verbosity) supplied to LBFGS
     ‘%lambda’
          Initial value of ‘%lambda’ to be used for calculating the
          augmented Lagrangian

     This implementation minimizes the augmented Lagrangian by applying
     the limited-memory BFGS (LBFGS) algorithm, which is a quasi-Newton
     algorithm.

     ‘load("augmented_lagrangian")’ loads this function.

     See also *note Package lbfgs::

     References:

     [1]
     <http://www-fp.mcs.anl.gov/otc/Guide/OptWeb/continuous/constrained/nonlinearcon/auglag.html>

     [2] <http://www.cs.ubc.ca/spider/ascher/542/chap10.pdf>

     Examples:

          (%i1) load ("lbfgs");
          (%o1)  /home/gunter/src/maxima-code/share/lbfgs/lbfgs.mac
          (%i2) load ("augmented_lagrangian");
          (%o2) /home/gunter/src/maxima-code/share/contrib/augmented_lagra\
          ngian.mac
          (%i3) FOM: x^2 + 2*y^2;
                                         2    2
          (%o3)                       2 y  + x
          (%i4) xx: [x, y];
          (%o4)                        [x, y]
          (%i5) C: [x + y - 1];
          (%o5)                      [y + x - 1]
          (%i6) yy: [1, 1];
          (%o6)                        [1, 1]
          (%i7) augmented_lagrangian_method(FOM, xx, C, yy, iprint=[-1,0]);
          (%o7) [[x = 0.666659841080023, y = 0.333340272455448],
                                           %lambda = [- 1.333337940892518]]

     Same example as before, but this time the gradient is supplied as
     an argument.

          (%i1) load ("lbfgs")$
          (%i2) load ("augmented_lagrangian")$
          (%i3) FOM: x^2 + 2*y^2;
                                         2    2
          (%o3)                       2 y  + x
          (%i4) xx: [x, y];
          (%o4)                        [x, y]
          (%i5) grad : [2*x, 4*y];
          (%o5)                      [2 x, 4 y]
          (%i6) C: [x + y - 1];
          (%o6)                      [y + x - 1]
          (%i7) yy: [1, 1];
          (%o7)                        [1, 1]
          (%i8) augmented_lagrangian_method ([FOM, grad], xx, C, yy,
                                       iprint = [-1, 0]);
          (%o8) [[x = 0.6666598410800247, y = 0.3333402724554464],
                                           %lambda = [- 1.333337940892525]]


File: maxima.info,  Node: Package bernstein,  Next: Package bitwise,  Prev: Package augmented_lagrangian,  Up: Top

42 Package bernstein
********************

* Menu:

* Functions and Variables for Bernstein::


File: maxima.info,  Node: Functions and Variables for Bernstein,  Prev: Package bernstein,  Up: Package bernstein

42.1 Functions and Variables for Bernstein
==========================================

 -- Function: bernstein_poly (<k>, <n>, <x>)

     Provided ‘k’ is not a negative integer, the Bernstein polynomials
     are defined by ‘bernstein_poly(k,n,x) = binomial(n,k) x^k
     (1-x)^(n-k)’; for a negative integer ‘k’, the Bernstein polynomial
     ‘bernstein_poly(k,n,x)’ vanishes.  When either ‘k’ or ‘n’ are non
     integers, the option variable ‘bernstein_explicit’ controls the
     expansion of the Bernstein polynomials into its explicit form;
     example:

          (%i1) load("bernstein")$

          (%i2) bernstein_poly(k,n,x);
          (%o2)                bernstein_poly(k, n, x)
          (%i3) bernstein_poly(k,n,x), bernstein_explicit : true;
                                                 n - k  k
          (%o3)            binomial(n, k) (1 - x)      x

     The Bernstein polynomials have both a gradef property and an
     integrate property:

          (%i4) diff(bernstein_poly(k,n,x),x);
          (%o4) (bernstein_poly(k - 1, n - 1, x)
                                           - bernstein_poly(k, n - 1, x)) n
          (%i5) integrate(bernstein_poly(k,n,x),x);
          (%o5)
                                                                      k + 1
           hypergeometric([k + 1, k - n], [k + 2], x) binomial(n, k) x
           ----------------------------------------------------------------
                                        k + 1

     For numeric inputs, both real and complex, the Bernstein
     polynomials evaluate to a numeric result:

          (%i6) bernstein_poly(5,9, 1/2 + %i);
                                  39375 %i   39375
          (%o6)                   -------- + -----
                                    128       256
          (%i7) bernstein_poly(5,9, 0.5b0 + %i);
          (%o7)           3.076171875b2 %i + 1.5380859375b2

     To use ‘bernstein_poly’, first ‘load("bernstein")’.

 -- Variable: bernstein_explicit
     Default value: ‘false’

     When either ‘k’ or ‘n’ are non integers, the option variable
     ‘bernstein_explicit’ controls the expansion of ‘bernstein(k,n,x)’
     into its explicit form; example:

          (%i1) bernstein_poly(k,n,x);
          (%o1)                bernstein_poly(k, n, x)
          (%i2) bernstein_poly(k,n,x), bernstein_explicit : true;
                                                 n - k  k
          (%o2)            binomial(n, k) (1 - x)      x
     When both ‘k’ and ‘n’ are explicitly integers, ‘bernstein(k,n,x)’
     _always_ expands to its explicit form.

 -- Function: multibernstein_poly (<[k1,k2,..., kp]>, <[n1,n2,..., np]>,
          <[x1,x2,..., xp]>)

     The multibernstein polynomial ‘multibernstein_poly (<[k1, k2, ...,
     kp]>, <[n1, n2, ..., np]>, <[x1, x2, ..., xp]>)’ is the product of
     bernstein polynomials ‘bernstein_poly(k1, n1, x1)
     bernstein_poly(k2, n2, x2) ... bernstein_poly(kp, np, xp)’.

     To use ‘multibernstein_poly’, first ‘load("bernstein")’.

 -- Function: bernstein_approx (<f>, <[x1, x1, ..., xn]>, n)

     Return the ‘n’-th order uniform Bernstein polynomial approximation
     for the function ‘(x1, x2, ..., xn) |--> f’.  Examples

          (%i1) bernstein_approx(f(x),[x], 2);
                           2       1                          2
          (%o1)      f(1) x  + 2 f(-) (1 - x) x + f(0) (1 - x)
                                   2
          (%i2) bernstein_approx(f(x,y),[x,y], 2);
                         2  2       1                2
          (%o2) f(1, 1) x  y  + 2 f(-, 1) (1 - x) x y
                                    2
                            2  2          1   2
           + f(0, 1) (1 - x)  y  + 2 f(1, -) x  (1 - y) y
                                          2
                 1  1                               1         2
           + 4 f(-, -) (1 - x) x (1 - y) y + 2 f(0, -) (1 - x)  (1 - y) y
                 2  2                               2
                      2        2       1                      2
           + f(1, 0) x  (1 - y)  + 2 f(-, 0) (1 - x) x (1 - y)
                                       2
                            2        2
           + f(0, 0) (1 - x)  (1 - y)

     To use ‘bernstein_approx’, first ‘load("bernstein")’.

 -- Function: bernstein_expand (<e>, <[x1, x1, ..., xn]>)

     Express the _polynomial_ ‘e’ exactly as a linear combination of
     multi-variable Bernstein polynomials.

          (%i1) bernstein_expand(x*y+1,[x,y]);
          (%o1)    2 x y + (1 - x) y + x (1 - y) + (1 - x) (1 - y)
          (%i2) expand(%);
          (%o2)                        x y + 1

     Maxima signals an error when the first argument isn't a polynomial.

     To use ‘bernstein_expand’, first ‘load("bernstein")’.


File: maxima.info,  Node: Package bitwise,  Next: Package bode,  Prev: Package bernstein,  Up: Top

43 Package bitwise
******************

The package ‘bitwise’ provides functions that allow to manipulate bits
of integer constants.  As always maxima attempts to simplify the result
of the operation if the actual value of a constant isn't known
considering attributes that might be known for the variables, see the
‘declare’ mechanism.

* Menu:

* Functions and Variables for bitwise::


File: maxima.info,  Node: Functions and Variables for bitwise,  Prev: Top,  Up: Top

43.1 Functions and Variables for bitwise
========================================

 -- Function: bit_not (<int>)

     Inverts all bits of a signed integer.  The result of this action
     reads ‘-int - 1’.

          (%i1) load("bitwise")$
          (%i2) bit_not(i);
          (%o2)                      bit_not(i)
          (%i3) bit_not(bit_not(i));
          (%o3)                           i
          (%i4) bit_not(3);
          (%o4)                          - 4
          (%i5) bit_not(100);
          (%o5)                         - 101
          (%i6) bit_not(-101);
          (%o6)                          100

 -- Function: bit_and (<int1>, ...)

     This function calculates a bitwise ‘and’ of two or more signed
     integers.

          (%i1) load("bitwise")$
          (%i2) bit_and(i,i);
          (%o2)                           i
          (%i3) bit_and(i,i,i);
          (%o3)                           i
          (%i4) bit_and(1,3);
          (%o4)                           1
          (%i5) bit_and(-7,7);
          (%o5)                           1

     If it is known if one of the parameters to ‘bit_and’ is even this
     information is taken into consideration by the function.
          (%i1) load("bitwise")$
          (%i2) declare(e,even,o,odd);
          (%o2)                         done
          (%i3) bit_and(1,e);
          (%o3)                           0
          (%i4) bit_and(1,o);
          (%o4)                           1

 -- Function: bit_or (<int1>, ...)

     This function calculates a bitwise ‘or’ of two or more signed
     integers.

          (%i1) load("bitwise")$
          (%i2) bit_or(i,i);
          (%o2)                           i
          (%i3) bit_or(i,i,i);
          (%o3)                           i
          (%i4) bit_or(1,3);
          (%o4)                           3
          (%i5) bit_or(-7,7);
          (%o5)                          - 1

     If it is known if one of the parameters to ‘bit_or’ is even this
     information is taken into consideration by the function.
          (%i1) load("bitwise")$
          (%i2) declare(e,even,o,odd);
          (%o2)                         done
          (%i3) bit_or(1,e);
          (%o3)                         e + 1
          (%i4) bit_or(1,o);
          (%o4)                           o

 -- Function: bit_xor (<int1>, ...)

     This function calculates a bitwise ‘or’ of two or more signed
     integers.

          (%i1) load("bitwise")$
          (%i2) bit_xor(i,i);
          (%o2)                           0
          (%i3) bit_xor(i,i,i);
          (%o3)                           i
          (%i4) bit_xor(1,3);
          (%o4)                           2
          (%i5) bit_xor(-7,7);
          (%o5)                          - 2

     If it is known if one of the parameters to ‘bit_xor’ is even this
     information is taken into consideration by the function.
          (%i1) load("bitwise")$
          (%i2) declare(e,even,o,odd);
          (%o2)                         done
          (%i3) bit_xor(1,e);
          (%o3)                         e + 1
          (%i4) bit_xor(1,o);
          (%o4)                         o - 1

 -- Function: bit_lsh (<int>, <nBits>)

     This function shifts all bits of the signed integer ‘int’ to the
     left by ‘nBits’ bits.  The width of the integer is extended by
     ‘nBits’ for this process.  The result of ‘bit_lsh’ therefore is
     ‘int * 2’.

          (%i1) load("bitwise")$
          (%i2) bit_lsh(0,1);
          (%o2)                           0
          (%i3) bit_lsh(1,0);
          (%o3)                           1
          (%i4) bit_lsh(1,1);
          (%o4)                           2
          (%i5) bit_lsh(1,i);
          (%o5)                     bit_lsh(1, i)
          (%i6) bit_lsh(-3,1);
          (%o6)                          - 6
          (%i7) bit_lsh(-2,1);
          (%o7)                          - 4

 -- Function: bit_rsh (<int>, <nBits>)

     This function shifts all bits of the signed integer ‘int’ to the
     right by ‘nBits’ bits.  The width of the integer is reduced by
     ‘nBits’ for this process.

          (%i1) load("bitwise")$
          (%i2) bit_rsh(0,1);
          (%o2)                           0
          (%i3) bit_rsh(2,0);
          (%o3)                           2
          (%i4) bit_rsh(2,1);
          (%o4)                           1
          (%i5) bit_rsh(2,2);
          (%o5)                           0
          (%i6) bit_rsh(-3,1);
          (%o6)                          - 2
          (%i7) bit_rsh(-2,1);
          (%o7)                          - 1
          (%i8) bit_rsh(-2,2);
          (%o8)                          - 1

 -- Function: bit_length (<int>)

     determines how many bits a variable needs to be long in order to
     store the number ‘int’.  This function only operates on positive
     numbers.

          (%i1) load("bitwise")$
          (%i2) bit_length(0);
          (%o2)                           0
          (%i3) bit_length(1);
          (%o3)                           1
          (%i4) bit_length(7);
          (%o4)                           3
          (%i5) bit_length(8);
          (%o5)                           4

 -- Function: bit_onep (<int>, <nBit>)

     determines if bits ‘nBit’ is set in the signed integer ‘int’.

          (%i1) load("bitwise")$
          (%i2) bit_onep(85,0);
          (%o2)                         true
          (%i3) bit_onep(85,1);
          (%o3)                         false
          (%i4) bit_onep(85,2);
          (%o4)                         true
          (%i5) bit_onep(85,3);
          (%o5)                         false
          (%i6) bit_onep(85,100);
          (%o6)                         false
          (%i7) bit_onep(i,100);
          (%o7)                   bit_onep(i, 100)

     For signed numbers the sign bit is interpreted to be more than
     ‘nBit’ to the left of the leftmost bit of ‘int’ that reads ‘1’.
          (%i1) load("bitwise")$
          (%i2) bit_onep(-2,0);
          (%o2)                         false
          (%i3) bit_onep(-2,1);
          (%o3)                         true
          (%i4) bit_onep(-2,2);
          (%o4)                         true
          (%i5) bit_onep(-2,3);
          (%o5)                         true
          (%i6) bit_onep(-2,4);
          (%o6)                         true

     If it is known if the number to be tested is even this information
     is taken into consideration by the function.
          (%i1) load("bitwise")$
          (%i2) declare(e,even,o,odd);
          (%o2)                         done
          (%i3) bit_onep(e,0);
          (%o3)                         false
          (%i4) bit_onep(o,0);
          (%o4)                         true


File: maxima.info,  Node: Package bode,  Next: Package celine,  Prev: Package bitwise,  Up: Top

44 Package bode
***************

* Menu:

* Functions and Variables for bode::


File: maxima.info,  Node: Functions and Variables for bode,  Prev: Package bode,  Up: Package bode

44.1 Functions and Variables for bode
=====================================

 -- Function: bode_gain (<H>, <range>, ...<plot_opts>...)
     Function to draw Bode gain plots.

     Examples (1 through 7 from
          <http://www.swarthmore.edu/NatSci/echeeve1/Ref/Bode/BodeHow.html>,
     8 from Ron Crummett):
          (%i1) load("bode")$

          (%i2) H1 (s) := 100 * (1 + s) / ((s + 10) * (s + 100))$

          (%i3) bode_gain (H1 (s), [w, 1/1000, 1000])$

          (%i4) H2 (s) := 1 / (1 + s/omega0)$

          (%i5) bode_gain (H2 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i6) H3 (s) := 1 / (1 + s/omega0)^2$

          (%i7) bode_gain (H3 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i8) H4 (s) := 1 + s/omega0$

          (%i9) bode_gain (H4 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i10) H5 (s) := 1/s$

          (%i11) bode_gain (H5 (s), [w, 1/1000, 1000])$

          (%i12) H6 (s) := 1/((s/omega0)^2 + 2 * zeta * (s/omega0) + 1)$

          (%i13) bode_gain (H6 (s), [w, 1/1000, 1000]),
                            omega0 = 10, zeta = 1/10$

          (%i14) H7 (s) := (s/omega0)^2 + 2 * zeta * (s/omega0) + 1$

          (%i15) bode_gain (H7 (s), [w, 1/1000, 1000]),
                            omega0 = 10, zeta = 1/10$

          (%i16) H8 (s) := 0.5 / (0.0001 * s^3 + 0.002 * s^2 + 0.01 * s)$

          (%i17) bode_gain (H8 (s), [w, 1/1000, 1000])$

     To use this function write first ‘load("bode")’.  See also
     ‘bode_phase’.

 -- Function: bode_phase (<H>, <range>, ...<plot_opts>...)
     Function to draw Bode phase plots.

     Examples (1 through 7 from
          <http://www.swarthmore.edu/NatSci/echeeve1/Ref/Bode/BodeHow.html>,
     8 from Ron Crummett):
          (%i1) load("bode")$

          (%i2) H1 (s) := 100 * (1 + s) / ((s + 10) * (s + 100))$

          (%i3) bode_phase (H1 (s), [w, 1/1000, 1000])$

          (%i4) H2 (s) := 1 / (1 + s/omega0)$

          (%i5) bode_phase (H2 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i6) H3 (s) := 1 / (1 + s/omega0)^2$

          (%i7) bode_phase (H3 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i8) H4 (s) := 1 + s/omega0$

          (%i9) bode_phase (H4 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i10) H5 (s) := 1/s$

          (%i11) bode_phase (H5 (s), [w, 1/1000, 1000])$

          (%i12) H6 (s) := 1/((s/omega0)^2 + 2 * zeta * (s/omega0) + 1)$

          (%i13) bode_phase (H6 (s), [w, 1/1000, 1000]),
                             omega0 = 10, zeta = 1/10$

          (%i14) H7 (s) := (s/omega0)^2 + 2 * zeta * (s/omega0) + 1$

          (%i15) bode_phase (H7 (s), [w, 1/1000, 1000]),
                             omega0 = 10, zeta = 1/10$

          (%i16) H8 (s) := 0.5 / (0.0001 * s^3 + 0.002 * s^2 + 0.01 * s)$

          (%i17) bode_phase (H8 (s), [w, 1/1000, 1000])$

          (%i18) block ([bode_phase_unwrap : false],
                        bode_phase (H8 (s), [w, 1/1000, 1000]));

          (%i19) block ([bode_phase_unwrap : true],
                        bode_phase (H8 (s), [w, 1/1000, 1000]));

     To use this function write first ‘load("bode")’.  See also
     ‘bode_gain’.


File: maxima.info,  Node: Package celine,  Next: Package clebsch_gordan,  Prev: Package bode,  Up: Top

45 Package celine
*****************

* Menu:

* Introduction to celine::


File: maxima.info,  Node: Introduction to celine,  Up: Package celine

45.1 Introduction to celine
===========================

Maxima implementation of Sister Celine's method.  Barton Willis wrote
this code.  It is released under the Creative Commons CC0 license
(https://creativecommons.org/about/cc0).

   Celine's method is described in Sections 4.1-4.4 of the book "A=B",
by Marko Petkovsek, Herbert S. Wilf, and Doron Zeilberger.  This book is
available at <http://www.math.rutgers.edu/~zeilberg/AeqB.pdf>

   Let f = F(n,k).  The function celine returns a set of recursion
relations for F of the form

   p_0(n) * fff(n,k) + p_1(n) * fff(n+1,k) + ...  + p_p(n) *
fff(n+p,k+q),

   where p_0 through p_p are polynomials.  If Maxima is unable to
determine that sum(sum(a(i,j) * F(n+i,k+j),i,0,p),j,0,q) / F(n,k) is a
rational function of n and k, celine returns the empty set.  When f
involves parameters (variables other than n or k), celine might make
assumptions about these parameters.  Using 'put' with a key of
'proviso,' Maxima saves these assumptions on the input label.

   To use this function, first load the package integer_sequence,
opsubst, and to_poly_solve.

   Examples:

     (%i1) load("integer_sequence")$
     (%i2) load("opsubst")$
     (%i3) load("to_poly_solve")$
     (%i4) load("celine")$
     (%i5) celine(n!,n,k,1,0);
     (%o5)       {fff(n + 1, k) - n fff(n, k) - fff(n, k)}

   Verification that this result is correct:
     (%i1) load("integer_sequence")$
     (%i2) load("opsubst")$
     (%i3) load("to_poly_solve")$
     (%i4) load("celine")$
     (%i5) g1:{fff(n+1,k)-n*fff(n,k)-fff(n,k)};
     (%o5)       {fff(n + 1, k) - n fff(n, k) - fff(n, k)}
     (%i6) ratsimp(minfactorial(first(g1))),fff(n,k) := n!;
     (%o6)                           0

   An example with parameters including the test that the result of the
example is correct:
     (%i1) load("integer_sequence")$
     (%i2) load("opsubst")$
     (%i3) load("to_poly_solve")$
     (%i4) load("celine")$
     (%i5) e : pochhammer(a,k) * pochhammer(-k,n) / (pochhammer(b,k));
                                (a)  (- k)
                                   k      n
     (%o5)                      -----------
                                   (b)
                                      k
     (%i6) recur : celine(e,n,k,2,1);
     (%o6) {fff(n + 2, k + 1) - fff(n + 2, k) - b fff(n + 1, k + 1)
      + n ((- fff(n + 1, k + 1)) + 2 fff(n + 1, k) - a fff(n, k)
      - fff(n, k)) + a (fff(n + 1, k) - fff(n, k)) + 2 fff(n + 1, k)
         2
      - n  fff(n, k)}
     (%i7) /* Test this result for correctness */
     (%i8) first(%), fff(n,k) := ''(e)$
     (%i9) makefact(makegamma(%))$
     (%o9)                           0
     (%i10) minfactorial(factor(minfactorial(factor(%))));

   The proviso data suggests that setting a = b may result in a lower
order recursion which is shown by the following example:
     (%i1) load("integer_sequence")$
     (%i2) load("opsubst")$
     (%i3) load("to_poly_solve")$
     (%i4) load("celine")$
     (%i5) e : pochhammer(a,k) * pochhammer(-k,n) / (pochhammer(b,k));
                                (a)  (- k)
                                   k      n
     (%o5)                      -----------
                                   (b)
                                      k
     (%i6) recur : celine(e,n,k,2,1);
     (%o6) {fff(n + 2, k + 1) - fff(n + 2, k) - b fff(n + 1, k + 1)
      + n ((- fff(n + 1, k + 1)) + 2 fff(n + 1, k) - a fff(n, k)
      - fff(n, k)) + a (fff(n + 1, k) - fff(n, k)) + 2 fff(n + 1, k)
         2
      - n  fff(n, k)}
     (%i7) get('%,'proviso);
     (%o7)                         false
     (%i8) celine(subst(b=a,e),n,k,1,1);
     (%o8) {fff(n + 1, k + 1) - fff(n + 1, k) + n fff(n, k)
                                                          + fff(n, k)}


File: maxima.info,  Node: Package clebsch_gordan,  Next: Package cobyla,  Prev: Package celine,  Up: Top

46 Package clebsch_gordan
*************************

* Menu:

* Functions and Variables for clebsch_gordan::


File: maxima.info,  Node: Functions and Variables for clebsch_gordan,  Prev: Package clebsch_gordan,  Up: Package clebsch_gordan

46.1 Functions and Variables for clebsch_gordan
===============================================

 -- Function: clebsch_gordan (<j1>, <j2>, <m1>, <m2>, <j>, <m>)

     Compute the Clebsch-Gordan coefficient <j1, j2, m1, m2 | j, m>.

 -- Function: racah_v (<a>, <b>, <c>, <a1>, <b1>, <c1>)

     Compute Racah's V coefficient (computed in terms of a related
     Clebsch-Gordan coefficient).

 -- Function: racah_w (<j1>, <j2>, <j5>, <j4>, <j3>, <j6>)

     Compute Racah's W coefficient (computed in terms of a Wigner 6j
     symbol)

 -- Function: wigner_3j (<j1>, <j2>, <j3>, <m1>, <m2>, <m3>)

     Compute Wigner's 3j symbol (computed in terms of a related
     Clebsch-Gordan coefficient).

 -- Function: wigner_6j (<j1>, <j2>, <j3>, <j4>, <j5>, <j6>)

     Compute Wigner's 6j symbol.

 -- Function: wigner_9j (<a>, <b>, <c>, <d>, <e>, <f>, <g>, <h>, <i>,
          <j>,)

     Compute Wigner's 9j symbol.


File: maxima.info,  Node: Package cobyla,  Next: Package colnew,  Prev: Package clebsch_gordan,  Up: Top

47 Package cobyla
*****************

* Menu:

* Introduction to cobyla::
* Functions and Variables for cobyla::
* Examples for cobyla::


File: maxima.info,  Node: Introduction to cobyla,  Next: Functions and Variables for cobyla,  Prev: Package cobyla,  Up: Package cobyla

47.1 Introduction to cobyla
===========================

‘fmin_cobyla’ is a Common Lisp translation (via ‘f2cl’) of the Fortran
constrained optimization routine COBYLA by Powell[1][2][3].

   COBYLA minimizes an objective function F(X) subject to M inequality
constraints of the form g(X) >= 0 on X, where X is a vector of variables
that has N components.

   Equality constraints g(X) = 0 can often be implemented by a pair of
inequality constraints g(X)>=0 and -g(X)>= 0. Maxima's interface to
COBYLA allows equality constraints and internally converts the equality
constraints to a pair of inequality constraints.

   The algorithm employs linear approximations to the objective and
constraint functions, the approximations being formed by linear
interpolation at N+1 points in the space of the variables.  The
interpolation points are regarded as vertices of a simplex.  The
parameter <RHO> controls the size of the simplex and it is reduced
automatically from <RHOBEG> to <RHOEND>.  For each <RHO> the subroutine
tries to achieve a good vector of variables for the current size, and
then <RHO> is reduced until the value <RHOEND> is reached.  Therefore,
<RHOBEG> and <RHOEND> should be set to reasonable initial changes to and
the required accuracy in the variables respectively, but this accuracy
should be viewed as a subject for experimentation because it is not
guaranteed.  The routine treats each constraint individually when
calculating a change to the variables, rather than lumping the
constraints together into a single penalty function.  The name of the
subroutine is derived from the phrase Constrained Optimization BY Linear
Approximations.

   References:

   [1] Fortran Code is from
<http://plato.asu.edu/sub/nlores.html#general>

   [2] M. J. D. Powell, "A direct search optimization method that models
the objective and constraint functions by linear interpolation," in
Advances in Optimization and Numerical Analysis, eds.  S. Gomez and
J.-P. Hennart (Kluwer Academic: Dordrecht, 1994), p.  51-67.

   [3] M. J. D. Powell, "Direct search algorithms for optimization
calculations," Acta Numerica 7, 287-336 (1998).  Also available as
University of Cambridge, Department of Applied Mathematics and
Theoretical Physics, Numerical Analysis Group, Report NA1998/04 from
<http://www.damtp.cam.ac.uk/user/na/reports.html>


File: maxima.info,  Node: Functions and Variables for cobyla,  Next: Examples for cobyla,  Prev: Introduction to cobyla,  Up: Package cobyla

47.2 Functions and Variables for cobyla
=======================================

 -- Function: fmin_cobyla
          fmin_cobyla (<F>, <X>, <Y>)
          fmin_cobyla (<F>, <X>, <Y>, optional_args)

     Returns an approximate minimum of the expression <F> with respect
     to the variables <X>, subject to an optional set of constraints.
     <Y> is a list of initial guesses for <X>.

     <F> must be ordinary expressions, not names of functions or lambda
     expressions.

     ‘optional_args’ represents additional arguments, specified as
     ‘<symbol> = <value>’.  The optional arguments recognized are:

     ‘constraints’
          List of inequality and equality constraints that must be
          satisfied by <X>.  The inequality constraints must be actual
          inequalities of the form g(<X>) >= h(<X>) or g(<X>) <= h(<X>).
          The equality constraints must be of the form g(<X>) = h(<X>).

     ‘rhobeg’
          Initial value of the internal <RHO> variable which controls
          the size of simplex.  (Defaults to 1.0)
     ‘rhoend’
          The desired final value rho parameter.  It is approximately
          the accuracy in the variables.  (Defaults to 1d-6.)
     ‘iprint’
          Verbose output level.  (Defaults to 0)
             • 0 - No output
             • 1 - Summary at the end of the calculation
             • 2 - Each new value of RHO and SIGMA is printed, including
               the vector of variables, some function information when
               RHO is reduced.
             • 3 - Like 2, but information is printed when F(X) is
               computed.
     ‘maxfun’
          The maximum number of function evaluations.  (Defaults to
          1000).

     On return, a vector is given:
       1. The value of the variables giving the minimum.  This is a list
          of elements of the form ‘<var> = <value>’ for each of the
          variables listed in <X>.
       2. The minimized function value
       3. The number of function evaluations.
       4. Return code with the following meanings
               0 - No errors.
               1 - Limit on maximum number of function evaluations
               reached.
               2 - Rounding errors inhibiting progress.
               -1 - <MAXCV> value exceeds <RHOEND>.  This indicates that
               the constraints were probably not satisfied.  User should
               investigate the value of the constraints.

     <MAXCV> stands for "MAXimum Constraint Violation" and is the value
     of max(0.0, -c1(x), -c2(x),...-cm(x)) where ck(x) denotes the k'th
     constraint function.  (Note that maxima allows constraints of the
     form f(x) = g(x), which are internally converted to f(x)-g(x) >= 0
     and g(x)-f(x) >= 0 which is required by COBYLA).

     ‘load("fmin_cobyla")’ loads this function.

 -- Function: bf_fmin_cobyla
          bf_fmin_cobyla (<F>, <X>, <Y>)
          bf_fmin_cobyla (<F>, <X>, <Y>, optional_args)

     This function is identical to ‘fmin_cobyla’, except that bigfloat
     operations are used, and the default value for <rhoend> is
     ‘10^(fpprec/2)’.

     See ‘fmin_cobyla’ for more information.

     ‘load("bf_fmin_cobyla")’ loads this function.


File: maxima.info,  Node: Examples for cobyla,  Prev: Functions and Variables for cobyla,  Up: Package cobyla

47.3 Examples for cobyla
========================

Minimize x_1 x_2 with 1-x1^2-x2^2 >= 0.

   The theoretical solution is

   x_1 = 1/sqrt(2)

   x_2 = -1/sqrt(2)

     (%i1) load("fmin_cobyla")$
     (%i2) fmin_cobyla(x1*x2, [x1, x2], [1,1],
                       constraints = [x1^2+x2^2<=1], iprint=1);
        Normal return from subroutine COBYLA

        NFVALS =   66   F =-5.000000E-01    MAXCV = 1.999845E-12
        X = 7.071058E-01  -7.071077E-01
     (%o2) [[x1 = 0.70710584934848, x2 = - 0.7071077130248],
            - 0.49999999999926, [[-1.999955756559757e-12],[]], 66]

   Here is the same example but the constraint is x1^2+x2^2 <= -1 which
is impossible over the reals.

     (%i1) fmin_cobyla(x1*x2, [x1, x2], [1,1],
              constraints = [x1^2+x2^2 <= -1], iprint=1);
        Normal return from subroutine COBYLA

        NFVALS =   65   F = 3.016417E-13    MAXCV = 1.000000E+00
        X =-3.375179E-07  -8.937057E-07
     (%o1) [[x1 = - 3.375178983064622e-7, x2 = - 8.937056510780022e-7],
                                                     3.016416530564557e-13, 65, - 1]
     (%i2) subst(%o1[2], [x1^2+x2^2 <= -1]);
     (%o2)                 [- 6.847914590915444e-13 <= - 1]

   We see the return code (‘%o1[4]’) is -1 indicating that the
constraints may not be satisfied.  Substituting the solution into the
constraint equation as shown in ‘%o2’ shows that the constraint is, of
course, violated.

   There are additional examples in the share/cobyla/ex directory and in
share/cobyla/rtest_cobyla.mac.


File: maxima.info,  Node: Package colnew,  Next: Package combinatorics,  Prev: Package cobyla,  Up: Top

48 Package colnew
*****************

* Menu:

* Introduction to colnew::
* Functions and Variables for colnew::
* Examples for colnew::
* References for colnew::


File: maxima.info,  Node: Introduction to colnew,  Next: Functions and Variables for colnew,  Prev: Package colnew,  Up: Package colnew

48.1 Introduction to colnew
===========================

<colnew> solves mixed-order systems of boundary-value problems (BVPs) in
ordinary differential equations(ODEs).  It is a Common Lisp translation
(via <f2cl>) of the Fortran routine COLNEW (Bader&Ascher 1987).

   The method uses collocation at Gaussian points and interpolation
using basis functions.  Approximate solutions are computed on a sequence
of automatically selected meshes until a user-specified set of
tolerances is satisfied.  A damped Newton's method is used for the
nonlinear iteration.

   COLNEW has some advanced features:

   • Continuation: Most iterative numerical solvers require an initial
     guess.  There are parameter dependent problems that have an obvious
     solution for a special value of the parameter (for example a
     coupling constant vanishes).  One can then slowly vary the
     parameter, solving the problem numerically using as a guess the
     previous solution, until one gets into a strong coupling regime,
     hence the name continuation.  Sometimes an artificial parameter is
     introduced to allow the use of continuation.

   • Singularities: Another interesting feature of COLNEW is that one
     can manage singularities in the differential equation by setting
     interior "boundary points" on the singularities.  This is because
     the differential equation is only imposed in the interior of the
     intervals, but the solution is checked for continuity and
     continuity of the derivative on the boundary of the intervals.

   • Stiff differential equations: COLNEW is can be used for solving
     some stiff differential equations due to the use of adaptive
     meshes.

   The maxima interface to COLNEW exposes the full power and complexity
of the Fortran 77 implementation.

   COLNEW is a modification of the package COLSYS (Ascher 1981a,b).  It
incorporates a new basis representation replacing B-splines, and
improvements for the linear and nonlinear algebraic equation solvers.
The package can be referenced as either COLNEW or COLSYS.

   Many practical problems that are not in the standard form accepted by
COLNEW can be converted into this form.  See (Asher&Russell 1981).


File: maxima.info,  Node: Functions and Variables for colnew,  Next: Examples for colnew,  Prev: Introduction to colnew,  Up: Package colnew

48.2 Functions and Variables for colnew
=======================================

 -- Function: colnew_expert
          colnew_expert (<ncomp>, <m>, <aleft>, <aright>, <zeta>,
          <ipar>, <ltol>, <tol>, <fixpnt>, <ispace>, <fspace>, <iflag>,
          <fsub>, <dfsub>, <gsub>, <dgsub>, <guess>)

     <colnew_expert> solves mixed-order systems of boundary-value
     problems (BVPs) in ordinary differential equations (ODEs) using a
     numerical collocation method.

     <colnew_expert> returns the list [<iflag>, <fspace>, <ispace>].
     <iflag> is an error flag.  Lists <fspace> and <ispace> contain the
     state of the solution and can be: used by ‘colnew_appsln’ to
     calculate solution values at arbitrary points in the solution
     domain; and passed back to <colnew_expert> to restart the solution
     process with different arguments.

     The function arguments are:

     ‘ncomp’
          Number of differential equations (ncomp ≤ 20)

     ‘m’
          Integer list of length <ncomp>.  m[j] is the order of the j-th
          differential equation, with 1 ≤ m[j] ≤ 4 and mstar = sum(m[j])
          ≤ 40.

     ‘aleft’
          Left end of interval

     ‘aright’
          Right end of interval

     ‘zeta’
          Real list of length <mstar>.  zeta[j] is the j-th boundary or
          side condition point.  The list zeta must be ordered, with
          zeta[j] ≤ zeta[j+1].  All side condition points must be mesh
          points in all meshes used, see description of ipar[11] and
          fixpnt below.

     ‘ipar’
          A integer list of length 11.  The parameters in ipar are:

             • <ipar[1]>
                  • 0, if the problem is linear
                  • 1, if the problem is nonlinear

             • <ipar[2]> ( = k )
               Number of collocation points per subinterval , where
               max(m[i]) ≤ k ≤ 7.
               If <ipar[2]>=0 then colnew sets k = max(max(m[i])+1,
               5-max(m[i]))

             • <ipar[3]> ( = n )
               Number of subintervals in the initial mesh.
               If <ipar[3]> = 0 then colnew arbitrarily sets n = 5.

             • <ipar[4]> ( = ntol )
               Number of solution and derivative tolerances.
               Require 0 < <ntol> ≤ <mstar>.

             • <ipar[5]> ( = ndimf )
               The length of list <fspace>.  Its size provides a
               constraint on <nmax>.  Choose ipar[5] according to the
               formula ipar[5] ≥ nmax*nsizef where nsizef = 4 + 3 *
               mstar + (5+kd) * kdm + (2*mstar-nrec) * 2*mstar.

             • <ipar[6]> ( = ndimi )
               The length of list <ispace>.  Its size provides a
               constraint on <nmax>, the maximum number of subintervals.
               Choose <ipar[6]> according to the formula ipar[6] ≥
               nmax*nsizei where nsizei = 3 + kdm with kdm = kd + mstar
               kd = k * ncomp
               nrec = number of right end boundary conditions.

             • <ipar[7]> ( = iprint )
               output control
                  • -1, for full diagnostic printout
                  • 0, for selected printout
                  • 1, for no printout

             • <ipar[8]> ( = iread )
                  • 0, causes colnew to generate a uniform initial mesh.
                  • 1, if the initial mesh is provided by the user.  it
                    is defined in fspace as follows: the mesh
                    aleft=x[1]<x[2]< ...  <x[n]<x[n+1]=aright will
                    occupy fspace[1], ..., fspace[n+1].  the user needs
                    to supply only the interior mesh points fspace[j] =
                    x[j], j = 2, ..., n.
                  • 2, if the initial mesh is supplied by the user as
                    with <ipar[8]>=1, and in addition no adaptive mesh
                    selection is to be done.

             • <ipar[9]> ( = iguess )
                  • 0, if no initial guess for the solution is provided
                  • 1, if an initial guess is provided by the user in
                    subroutine guess.
                  • 2, if an initial mesh and approximate solution
                    coefficients are provided by the user in <fspace>.
                    (the former and new mesh are the same).
                  • 3, if a former mesh and approximate solution
                    coefficients are provided by the user in <fspace>,
                    and the new mesh is to be taken twice as coarse;
                    i.e.,every second point from the former mesh.
                  • 4, if in addition to a former initial mesh and
                    approximate solution coefficients, a new mesh is
                    provided in <fspace> as well.  (see description of
                    output for further details on iguess = 2, 3, and 4.)

             • <ipar[10]>
                  • 0, if the problem is regular
                  • 1, if the first relax factor is =rstart, and the
                    nonlinear iteration does not rely on past covergence
                    (use for an extra sensitive nonlinear problem only).
                  • 2, if we are to return immediately upon (a) two
                    successive nonconvergences, or (b) after obtaining
                    error estimate for the first time.

             • <ipar[11]> ( = nfxpnt , the dimension of fixpnt)
               The number of fixed points in the mesh other than <aleft>
               and <aright>.  The code requires that all side condition
               points other than <aleft> and <aright> (see description
               of <zeta>) must be included as fixed points in <fixpnt>.

     ‘ltol’
          A list of length <ntol=ipar[4]>.  <ltol[j]=k> specifies that
          the j-th tolerance in <tol> controls the error in the k-th
          component of z(u).

          The list <ltol> must be ordered with 1 ≤ ltol[1] < ltol[2] <
          ... < ltol[ntol] ≤ mstar.

     ‘tol’
          An list of length <ntol=ipar[4]>.  <tol[j]> is the error
          tolerance on the ltol[j]-th component of z(u).

          Thus, the code attempts to satisfy for j=1,...,ntol on each
          subinterval abs(z(v)-z(u))[k] ≤ tol(j)*abs(z(u))[k]+tol(j) if
          v(x) is the approximate solution vector.

     ‘fixpnt’
          An list of length <ipar[11]>.  It contains the points, other
          than <aleft> and <aright>, which are to be included in every
          mesh.  All side condition points other than <aleft> and
          <aright> (see <zeta>) be included as fixed points in <fixpnt>.

     ‘ispace’
          An integer work list of length <ipar[6]>.

     ‘fspace’
          A real work list of length <ipar[5]>.

     ‘fsub’
          <fsub> is a function f(x,z1,...,z[mstar]) which realizes the
          system of ODEs.

          It returns a list of <ncomp> values, one for each ODE. Each
          value is the highest order derivative in each ode in terms of
          of x,z1,...,z[mstar] .

     ‘dfsub’
          <dfsub> is a function df(x,z1,...,z[mstar]) for evaluating the
          Jacobian of f.

     ‘gsub’
          Name of subroutine gsub(i,z1,z2,...,z[mstar]) for evaluating
          the i-th component of the boundary value function
          g(z1,...,z[mstar]).  The independent variable x is not an
          argument of g.  The value <x=zeta[i]> must be substituted in
          advance.

     ‘dgsub’
          Name of subroutine dgsub(i,z1,...,z[mstar]) for evaluating the
          i-th row of the Jacobian of g(z1,...,z[mstar]).

     ‘guess’
          Name of subroutine to evaluate the initial approximation for
          (u(x)) and for dmval(u(x))= vector of the mj-th derivatives of
          u(x).  This subroutine is needed only if using <ipar(9)> = 1.

     The return value of <colnew_expert> is the list <[iflag, fspace,
     ispace]>, where:

     ‘iflag’
          The mode of return from <colnew_expert>.
             • = 1 for normal return
             • = 0 if the collocation matrix is singular.
             • = -1 if the expected no.  of subintervals exceeds storage
               specifications.
             • = -2 if the nonlinear iteration has not converged.
             • = -3 if there is an input data error.

     ‘fspace’
          A list of floats of length <ipar[5]>.

     ‘ispace’
          A list of integers of length <ipar[6]>.

     ‘colnew_appsln’ uses <fspace> and <ispace> to calculate solution
     values at arbitrary points.  The lists can also be used to restart
     the solution process with modified meshes and parameters.

 -- Function: colnew_appsln
          colnew_appsln (<x>, <zlen>, <fspace>, <ispace>)

     Return a list of solution values from ‘colnew_expert’ results.

     The function arguments are:

     ‘x’
          List of x-coordinates to calculate solution.
     ‘zlen’
          <mstar>, the length of the solution list z
     ‘fspace’
          List <fspace> returned from ‘colnew_expert’.
     ‘ispace’
          List <ispace> returned from ‘colnew_expert’.


File: maxima.info,  Node: Examples for colnew,  Next: References for colnew,  Prev: Functions and Variables for colnew,  Up: Package colnew

48.3 Examples for colnew
========================

COLNEW is best learned by example.

48.3.1 Example 1: A uniformly loaded beam of variable stiffness
---------------------------------------------------------------

The problem describes a uniformly loaded beam of variable stiffness,
simply supported at both ends.

   The problem from (Gawain&Bell 1978) and is Example 1 from (Ascher
1981a).  The maxima code is in file share/colnew/prob1.mac and a Fortran
implementation is in share/colnew/ex1.

The differential equation is

   (x^3 u'')'' = x^3 u'''' + 6 x^2 u''' + 6x u'' = 1 over 1 ≤ x ≤ 2

with boundary conditions

              u(1) = 0, u''(1) = 0, u(2) = 0, u''(2) = 0

The exact solution is

   u(x) = (1/4) (10 ln(2) - 3) (1-x) + (1/2) (1/x + (3+x) ln(x) - x)

There is <nconc> = 1 differential equation of fourth order.  The list of
orders <m> = [4] and <mstar> = sum(m[j]) = 4.

The unknown vector of length <mstar> is

                 z(x) = [z_1(x),z_2(x),z_3(x),z_4(x)]

                     =[u(x),u'(x),u''(x),u'''(x)].

The differential equation is expressed as

       u''''(x) = F(x,z_1,z_2,z_3,z_4) = 1 - 6 x^2 z_3 - 6x z_2

   There are <mstar=4> boundary conditions.  They are given by a
function G(z_1,z_2,z_3,z_4) that returns a list of length mstar.  The
j-th boundary condition applies at <x = zeta[j]> and is satisfied when
<g[j] = 0>.  We have

j           zeta[j]     Condition    g[j]
-------------------------------------------------
1           1.0         u=0          z_1
2           1.0         u''=0        z_3
3           2.0         u=0          z_1
4           2.0         u''=0        z_3

   giving zeta = [1.0,1,0,2.0,2.0] and G(z_1,z_2,z_3,z_4) = [z_1, z_3,
z_1, z_3].

   The Jacobians <df> and <dg> of <f> and <g> respectively are
determined symbolically.

   The solution uses the default five collocation points per subinterval
and the first mesh contains only one subinterval.  The maximum error
magnitude in the approximate solution is evaluated at 100 equidistant
points by function ‘colnew_appsln’ using the results returned by COLNEW
and compared to the estimates from the code.

     (%i1) load("colnew")$

     (%i2) /* One differential equation of order 4 */
      m : [4];

     (%o2)                          [4]
     (%i3) /* Location of boundary conditions */
      zeta : float([1,1,2,2]);

     (%o3)                 [1.0, 1.0, 2.0, 2.0]
     (%i4) /* Set up parameter array.  Use defaults for all except as shown */
      ipar : makelist(0,k,1,11);
     (%o4)           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     (%i5) /* initial mesh size */
      ipar[3] : 1$
     (%i6) /* number of tolerances */
      ipar[4] : 2$
     (%i7) /* size of real work array */
      ipar[5] : 2000$
     (%i8) /* size of integer work array */
      ipar[6] : 200$

     (%i9) /* Two error tolerances (on u and its second derivative) */
      ltol : [1, 3];
     (%o9)                        [1, 3]
     (%i10) tol : [1d-7, 1d-7];

     (%o10)                  [1.0e-7, 1.0e-7]
     (%i11) /* Real work array */
      fspace : makelist(0d0, k, 1, ipar[5])$
     (%i12) /* Integer work array */
      ispace : makelist(0, k, 1, ipar[6])$
     (%i13) /* no internal fixed points */
      fixpnt : []$

     (%i14) /* Define the equations */
      fsub(x, z1, z2, z3, z4) := [(1-6*x^2*z4-6*x*z3)/x^3];
                                               2
                                        1 - 6 x  z4 + (- 6) x z3
     (%o14) fsub(x, z1, z2, z3, z4) := [------------------------]
                                                    3
                                                   x
     (%i15) df : jacobian(fsub(x,z1, z2, z3, z4),[z1,z2,z3,z4]);
                            [         6     6 ]
     (%o15)                 [ 0  0  - --  - - ]
                            [          2    x ]
                            [         x       ]
     (%i16) define(dfsub(x, z1, z2, z3, z4), df);

                                          [         6     6 ]
     (%o16)   dfsub(x, z1, z2, z3, z4) := [ 0  0  - --  - - ]
                                          [          2    x ]
                                          [         x       ]
     (%i17) g(z1, z2, z3, z4) := [z1, z3, z1, z3];
     (%o17)        g(z1, z2, z3, z4) := [z1, z3, z1, z3]
     (%i18) gsub(i, z1, z2, z3, z4) :=
      subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], g(z1, z2, z3, z4)[i]);

     (%o18) gsub(i, z1, z2, z3, z4) :=
     subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4],
     g(z1, z2, z3, z4) )
                      i
     (%i19) dg:jacobian(g(z1, z2, z3, z4), [z1,z2,z3,z4]);
                              [ 1  0  0  0 ]
                              [            ]
                              [ 0  0  1  0 ]
     (%o19)                   [            ]
                              [ 1  0  0  0 ]
                              [            ]
                              [ 0  0  1  0 ]
     (%i20) dgsub(i, z1, z2, z3, z4) :=
      subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], row(dg, i)[1]);

     (%o20) dgsub(i, z1, z2, z3, z4) :=
          subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], row(dg, i) )
                                                                    1
     (%i21) /* Exact solution */
       exact(x) := [.25*(10.*log(2.)-3.)*(1.-x) + .5*(1./x+(3.+x)*log(x)-x),
                  -.25*(10.*log(2.)-3.) + .5*(-1./x/x+log(x)+(3.+x)/x-1.),
                  .5*(2./x**3+1./x-3./x/x),
                  .5*(-6./x**4-1./x/x+6./x**3)]$

     (%i22) [iflag, fspace, ispace] :
      colnew_expert(1, m, 1d0, 2d0, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
                  0, fsub, dfsub, gsub, dgsub, dummy)$


      VERSION *COLNEW* OF COLSYS .


      THE MAXIMUM NUMBER OF SUBINTERVALS IS MIN (  12 (ALLOWED FROM FSPACE),  16 (ALLOWED FROM ISPACE) )

      THE NEW MESH (OF    1 SUBINTERVALS),
         1.000000    2.000000

      THE NEW MESH (OF    2 SUBINTERVALS),
         1.000000    1.500000    2.000000

      THE NEW MESH (OF    4 SUBINTERVALS),
         1.000000    1.250000    1.500000    1.750000    2.000000
     (%i23) /* Calculate the error at 101 points using the known exact solution */
      block([x : 1,
            err : makelist(0d0, k, 1, 4),
            j],
       for j : 1 thru 101 do
         block([],
           zval : colnew_appsln([x], 4, fspace, ispace)[1],
           u : float(exact(x)),
           err : map(lambda([a,b], max(a,b)), err, abs(u-zval)),
           x : x + 0.01),
       print("The exact errors are:"),
       printf(true, "   ~{ ~11,4e~}~%", err));
     The exact errors are:
          1.7389E-10   6.2679E-9   2.1843E-7   9.5743E-6
     (%o23)                        false

48.3.2 Example 2: Deformation of a spherical cap
------------------------------------------------

These equations describe the small finite deformation of a thin shallow
spherical cap of constant thickness subject to a quadratically varying
axisymmetric external pressure distribution superimposed on a uniform
internal pressure distribution.  The problem is described in (Parker&Wan
1984) and is Example 2 from (Ascher 1981a).  The maxima code is in file
share/colnew/prob2.mac and a Fortran implementation is in
share/colnew/ex2.

   There are two nonlinear differential equations for φ and ψ over 0 < x
< 1.

   (ε^4/μ)[φ'' + (1/x) φ' - (1/x^2) φ] + ψ (1-φ/x) - φ = - γ x
(1-(1/2)x^2)

   μ [ψ'' + (1/x) ψ' - (1/x^2)ψ] - φ(1-φ/(2x)) = 0

   subject to boundary conditions φ = 0 and x ψ' - 0.3 ψ + 0.7 x = 0 at
x=0 and x=1.

   For ε = μ = 0.01, two solutions exists.  These are obtained by
starting the nonlinear iteration from two different guesses to the
solution: initially with the default initial guess; and secondly, with
the initial conditions given by the function <solutn>.

   There are <nconc> = 2 differential equations of second order.  The
list of orders <m> = [2,2] and <mstar> = sum(m[i]) = 4.

   The vector of unknowns of length <mstar>=4 is z(x) = [ φ(x), φ'(x),
ψ(x), ψ'(x)].

   The differential equation is expressed as

   [φ''(x), ψ''(x)]

   =F(x,z_1,z_2,z_3,z_4)

   =[z_1/x^2 - z_2/x + (z_1-z_3 (1-z_1/x) - γ x (1-x^2/2))/(ε^4/μ),
z_3/x^2 - z_4/x + z_1 (1-z_1/(2x))/μ]

   There are four boundary conditions given by list zeta and function
G(z_1,z_2,z_3,z_4).

j       zeta[j] Condition                     g[j]
----------------------------------------------------------------------------
1       0.0     φ = 0                         z_1
2       0.0     x ψ' - 0.3 ψ + 0.7 x = 0      z_3
3       1.0     φ = 0                         z_1
4       1.0     x ψ' - 0.3 ψ + 0.7 x = 0      z_4 - 0.3 z_3 + 0.7

   giving zeta=[0.0,0.0,1.0,1.0] and G(z_1,z_2,z_3,z_4)=[z_1, z_3, z_1,
z_4-0.3*z_3+0.7]

   Note that <x> is not an argument of function <G>.  The value of
<x=zeta[j]> must be substituted.

     (%i1) load("colnew")$

     (%i2) /* Define constants */
      gamma : 1.1;
     (%o2)                          1.1
     (%i3) eps : 0.01;
     (%o3)                         0.01
     (%i4) dmu : eps;
     (%o4)                         0.01
     (%i5) eps4mu : eps^4/dmu;
     (%o5)                        1.0e-6
     (%i6) xt : sqrt(2*(gamma-1)/gamma);
     (%o6)                  0.42640143271122105
     (%i7) /* Number of differential equations */
      ncomp : 2;
     (%o7)                           2
     (%i8) /* Orders */
      m : [2, 2];

     (%o8)                        [2, 2]
     (%i9) /* Interval ends */
      aleft : 0.0;
     (%o9)                          0.0
     (%i10) aright : 1.0;

     (%o10)                         1.0
     (%i11) /* Locations of side conditions */
      zeta : float([0, 0, 1, 1])$
     (%i12) /* Set up parameter array.  */
      ipar : makelist(0,k,1,11);
     (%o12)          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     (%i13) /* Non-linear prob */
      ipar[1] : 1;
     (%o13)                          1
     (%i14) /* 4 collocation points per subinterval */
      ipar[2] : 4;
     (%o14)                          4
     (%i15) /* Initial uniform mesh of 10 subintervals */
      ipar[3] : 10;
     (%o15)                         10
     (%i16) ipar[8] : 0;
     (%o16)                          0
     (%i17) /* Size of fspace, ispace */
      ipar[5] : 40000;
     (%o17)                        40000
     (%i18) ipar[6] : 2500;
     (%o18)                        2500
     (%i19) /* No output */
      ipar[7] : 1;
     (%o19)                          1
     (%i20) /* No initial approx is provided */
      ipar[9] : 0;
     (%o20)                          0
     (%i21) /* Regular problem */
      ipar[10] : 0;
     (%o21)                          0
     (%i22) /* No fixed points in mesh */
      ipar[11] : 0;
     (%o22)                          0
     (%i23) /* Tolerances on all components */
      ipar[4] : 4;

     (%o23)                          4
     (%i24) /* Two error tolerances (on u and its second derivative */
      ltol : [1, 2, 3, 4];
     (%o24)                    [1, 2, 3, 4]
     (%i25) tol : [1d-5, 1d-5, 1d-5, 1d-5];

     (%o25)          [1.0e-5, 1.0e-5, 1.0e-5, 1.0e-5]
     (%i26) fspace : makelist(0d0, k, 1, ipar[5])$
     (%i27) ispace : makelist(0, k, 1, ipar[6])$
     (%i28) fixpnt : []$

     (%i29) /* Define the equations */
      fsub(x, z1, z2, z3, z4) :=
      [z1/x/x - z2/x + (z1-z3*(1-z1/x) - gamma*x*(1-x*x/2))/eps4mu,
       z3/x/x - z4/x + z1*(1-z1/2/x)/dmu];

     (%o29) fsub(x, z1, z2, z3, z4) :=
      z1                     z1                     x x
      --        z1 - z3 (1 - --) + (- gamma) x (1 - ---)
      x    z2                x                       2
     [-- - -- + ----------------------------------------,
      x    x                     eps4mu
                       z1
                       --
     z3                2
     --        z1 (1 - --)
     x    z4           x
     -- - -- + -----------]
     x    x        dmu
     (%i30) df : jacobian(fsub(x,z1, z2, z3, z4),[z1,z2,z3,z4]);
     (%o30)
           [             z3        1      1             z1           ]
           [  1000000.0 (-- + 1) + --   - -  1000000.0 (-- - 1)   0  ]
           [             x          2     x             x            ]
           [                       x                                 ]
           [                                                         ]
           [            z1     50.0 z1               1             1 ]
           [ 100.0 (1 - ---) - -------   0           --          - - ]
           [            2 x       x                   2            x ]
           [                                         x               ]
     (%i31) dfsub(x, z1, z2, z3, z4) :=
       subst(['x=x,'z1=z1,'z2=z2,'z3=z3,'z4=z4], df);

     (%o31) dfsub(x, z1, z2, z3, z4) :=
           subst(['x = x, 'z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], df)
     (%i32) g(z1, z2, z3, z4) := [z1, z3, z1, z4 - 0.3*z3 + .7];
     (%o32) g(z1, z2, z3, z4) := [z1, z3, z1, z4 - 0.3 z3 + 0.7]
     (%i33) gsub(i, z1, z2, z3, z4) :=
         subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], g(z1, z2, z3, z4)[i]);

     (%o33) gsub(i, z1, z2, z3, z4) :=
     subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4],
     g(z1, z2, z3, z4) )
                      i
     (%i34) dg:jacobian(g(z1, z2, z3, z4), [z1,z2,z3,z4]);
                            [ 1  0    0    0 ]
                            [                ]
                            [ 0  0    1    0 ]
     (%o34)                 [                ]
                            [ 1  0    0    0 ]
                            [                ]
                            [ 0  0  - 0.3  1 ]
     (%i35) dgsub(i, z1, z2, z3, z4) := subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], row(dg, i)[1]);

     (%o35) dgsub(i, z1, z2, z3, z4) :=
          subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], row(dg, i) )
                                                                    1
     (%i36) /* Initial approximation function for second run */
      solutn(x) :=
      block([cons : gamma*x*(1-0.5*x*x),
            dcons : gamma*(1-1.5*x*x),
            d2cons : -3*gamma*x],
       if is(x > xt) then
         [[0, 0, -cons, -dcons],
          [0, -d2cons]]
       else
         [[2*x, 2, -2*x + cons, -2 + dcons],
          [0, d2cons]]);

     (%o36) solutn(x) := block([cons : gamma x (1 - 0.5 x x),
     dcons : gamma (1 - 1.5 x x), d2cons : - 3 gamma x],
     if is(x > xt) then [[0, 0, - cons, - dcons], [0, - d2cons]]
      else [[2 x, 2, - 2 x + cons, - 2 + dcons], [0, d2cons]])
     (%i37) /* First run with default initial guess */
      [iflag, fspace, ispace] :
      colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
      0, fsub, dfsub, gsub, dgsub, dummy)$

     (%i38) /* Check return status iflag, 1 = success */
      iflag;

     (%o38)                          1
     (%i39) /* Print values of solution at x = 0,.05,...,1 */
      x : 0;
     (%o39)                          0
     (%i40) for j : 1 thru 21 do
      block([],
        zval : colnew_appsln([x], 4, fspace, ispace)[1],
        printf(true, "~5,2f  ~{~15,5e~}~%", x, zval),
        x : x + 0.05);

      0.00       0.00000E+0     4.73042E-2   -3.39927E-32    -1.10497E+0
      0.05       2.36520E-3     4.73037E-2    -5.51761E-2    -1.10064E+0
      0.10       4.73037E-3     4.73030E-2    -1.09919E-1    -1.08765E+0
      0.15       7.09551E-3     4.73030E-2    -1.63796E-1    -1.06600E+0
      0.20       9.46069E-3     4.73039E-2    -2.16375E-1    -1.03569E+0
      0.25       1.18259E-2     4.73040E-2    -2.67221E-1    -9.96720E-1
      0.30       1.41911E-2     4.73020E-2    -3.15902E-1    -9.49092E-1
      0.35       1.65562E-2     4.72980E-2    -3.61986E-1    -8.92804E-1
      0.40       1.89215E-2     4.72993E-2    -4.05038E-1    -8.27857E-1
      0.45       2.12850E-2     4.72138E-2    -4.44627E-1    -7.54252E-1
      0.50       2.36370E-2     4.67629E-2    -4.80320E-1    -6.72014E-1
      0.55       2.59431E-2     4.51902E-2    -5.11686E-1    -5.81260E-1
      0.60       2.81093E-2     4.07535E-2    -5.38310E-1    -4.82374E-1
      0.65       2.99126E-2     2.98538E-2    -5.59805E-1    -3.76416E-1
      0.70       3.08743E-2     5.53985E-3    -5.75875E-1    -2.65952E-1
      0.75       3.00326E-2    -4.51680E-2    -5.86417E-1    -1.56670E-1
      0.80       2.55239E-2    -1.46617E-1    -5.91753E-1    -6.04539E-2
      0.85       1.37512E-2    -3.46952E-1    -5.93069E-1    -1.40102E-3
      0.90      -1.25155E-2    -7.52826E-1    -5.93303E-1    -2.86234E-2
      0.95      -6.94274E-2    -1.65084E+0    -5.99062E-1    -2.48115E-1
      1.00      2.64233E-14     1.19263E+2    -6.25420E-1    -8.87626E-1
     (%o40)                        done
     (%i41) /* Second run with initial guess */
      ipar[9] : 1;
     (%o41)                          1
     (%i42) [iflag, fspace, ispace] :
      colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
      0, fsub, dfsub, gsub, dgsub, solutn)$

     (%i43) /* Check return status iflag, 1 = success */
      iflag;

     (%o43)                          1
     (%i44) /* Print values of solution at x = 0,.05,...,1 */
      x : 0;
     (%o44)                          0
     (%i45) for j : 1 thru 21 do
      block([],
        zval : colnew_appsln([x], 4, fspace, ispace)[1],
        printf(true, "~5,2f  ~{~15,5e~}~%", x, zval),
        x : x + 0.05);
      0.00       0.00000E+0     2.04139E+0     0.00000E+0    -9.03975E-1
      0.05       1.02070E-1     2.04139E+0    -4.52648E-2    -9.07936E-1
      0.10       2.04139E-1     2.04139E+0    -9.09256E-2    -9.19819E-1
      0.15       3.06209E-1     2.04140E+0    -1.37379E-1    -9.39624E-1
      0.20       4.08279E-1     2.04141E+0    -1.85020E-1    -9.67352E-1
      0.25       5.10351E-1     2.04152E+0    -2.34246E-1    -1.00301E+0
      0.30       6.12448E-1     2.04303E+0    -2.85454E-1    -1.04663E+0
      0.35       7.15276E-1     2.10661E+0    -3.39053E-1    -1.09916E+0
      0.40       8.32131E-1    -2.45181E-1    -3.96124E-1    -1.20544E+0
      0.45       1.77510E-2    -3.57554E+0    -4.45400E-1    -7.13543E-1
      0.50       2.25122E-2     1.23608E-1    -4.80360E-1    -6.70074E-1
      0.55       2.58693E-2     4.85257E-2    -5.11692E-1    -5.81075E-1
      0.60       2.80994E-2     4.11112E-2    -5.38311E-1    -4.82343E-1
      0.65       2.99107E-2     2.99116E-2    -5.59805E-1    -3.76409E-1
      0.70       3.08739E-2     5.55200E-3    -5.75875E-1    -2.65950E-1
      0.75       3.00325E-2    -4.51649E-2    -5.86417E-1    -1.56669E-1
      0.80       2.55239E-2    -1.46616E-1    -5.91753E-1    -6.04538E-2
      0.85       1.37512E-2    -3.46952E-1    -5.93069E-1    -1.40094E-3
      0.90      -1.25155E-2    -7.52826E-1    -5.93303E-1    -2.86233E-2
      0.95      -6.94274E-2    -1.65084E+0    -5.99062E-1    -2.48115E-1
      1.00      2.65413E-14     1.19263E+2    -6.25420E-1    -8.87626E-1
     (%o45)                        done

   Columns 1 (x) and 2 (φ) of the two sets of results can be compared
with Figure 1 in (Ascher 1981a).

48.3.3 Example 3: Rotating flow of viscous incompressible fluid
---------------------------------------------------------------

Example 3 from (Ascher 1981a) describes the velocities in the boundary
layer produced by the rotating flow of a viscous incompressible fluid
over a stationary infinite disk (Gawain&Bell 1978).

   The solution uses a number of techniques to obtain convergence.
Refer to (Ascher 1981a) for details.

   The code is in directory share/colnew.  The maxima code is in file
prob3.mac.  The reference Fortran implementation is in directory ex3.

48.3.4 Example 4: Quantum Neumann equation
------------------------------------------

A more sophisticated example is (Bellon&Talon 2005), which deals with
singularities in the solution domain, provides an initial quess to the
solution and uses continuation to solve the system of non-linear
differential equations.

   The code is in directory share/colnew.  The maxima code is in file
prob4.mac.  The Fortran implementation is in directory ex4.

48.3.5 Example 5: Simple example of continuation
------------------------------------------------

This example (Ascher et al, 1995, Example 9.2) solves a numerically
difficult boundary value problem using continuation.

The linear differential equation is
       ε u'' + x u' = -ε π^2 cos(πx) - (πx) sin(πx), -1 < x < 1

with boundary conditions
                          u(-1)=-2 and u(1)=0

The exact solution is
           u(x) = cos(πx) + erf(x/sqrt(2ε))/erf(1/sqrt(2ε))

   When ε is small the solution has a rapid transition near x=0 and is
difficult to solve numerically.  COLNEW is able to solve the problem for
directly for ε=1.0e-6, but here we will use continuation to solve it
succesively for ε=[1e-2,1e-3,1e-4,1e-5,1e-6].

   There is <nconc> = 1 differential equation of second order.  The list
of orders <m> = [2] and <mstar> = sum(m[j]) = 2.

   The unknown vector of length <mstar> is z(x) = [z_1(x),z_2(x)] =
[u(x),u'(x)].

   The differential equation is expressed as [u''(x)] = F(x,z_1,z_2) =
[-(x/ε)z_2 - π^2cos(πx) - (πx/ε)sin(πx)]

   There are <mstar=2> boundary conditions.  They are given by a
function G(z_1,z_2) that returns a list of length mstar.  The j-th
boundary condition applies at <x = zeta[j]> and is satisfied when <g[j]
= 0>.  We have

j           zeta[j]     Condition    g[j]
-------------------------------------------------
1           -1.0        u=-2         z_1+2
2           1.0         u=0          z_1

   giving zeta = [-1.0,1,0] and G(z_1,z_2) = [z_1+2, z_1].

   The Jacobians <df> and <dg> of <f> and <g> respectively are
determined symbolically.

   The ODE will be solved for multiple values of ε.  The functions
<fsub>, <dfsub>, <gsub> and <dgsub> are defined before <e> is set, so
that it can be changed in the program.

     (%i1) load("colnew")$
     (%i2) kill(e,x,z1,z2)$
     (%i3) /* Exact solution */
      exact(x):=cos(%pi*x)+erf(x/sqrt(2*e))/erf(1/sqrt(2*e))$
     (%i4) /* Define the equations.  Do this before e is defined */
      f: [-(x/e)*z2 - %pi^2*cos(%pi*x) - (%pi*x/e)*sin(%pi*x)];
                  x z2   %pi x sin(%pi x)      2
     (%o4)     [- ---- - ---------------- - %pi  cos(%pi x)]
                   e            e
     (%i5) define(fsub(x,z1,z2),f);
                                 x z2   %pi x sin(%pi x)
     (%o5) fsub(x, z1, z2) := [- ---- - ----------------
                                  e            e
                                                         2
                                                    - %pi  cos(%pi x)]
     (%i6) df: jacobian(f,[z1,z2]);
                                [      x ]
     (%o6)                      [ 0  - - ]
                                [      e ]
     (%i7) define(dfsub(x,z1,z2),df);
                                          [      x ]
     (%o7)            dfsub(x, z1, z2) := [ 0  - - ]
                                          [      e ]
     (%i8) /* Build the functions gsub and dgsub
        Use define and buildq to remove dependence on g and dg */
      g: [z1+2,z1];
     (%o8)                     [z1 + 2, z1]
     (%i9) define(gsub(i,z1,z2),buildq([g],g[i]));
     (%o9)           gsub(i, z1, z2) := [z1 + 2, z1]
                                                    i
     (%i10) dg: jacobian(g,[z1,z2]);
                                 [ 1  0 ]
     (%o10)                      [      ]
                                 [ 1  0 ]
     (%i11) define(
      dgsub(i,z1,z2),
      buildq([val:makelist(dg[i],i,1,length(dg))],block([dg:val],dg[i])));
     (%o11) dgsub(i, z1, z2) := block([dg : [[1, 0], [1, 0]]], dg )
                                                                 i
     (%i12) /* Define constant epsilon */
      e : 0.01$
     (%i13) /* Number of differential equations */
      ncomp : 1$
     (%i14) /* Orders */
      m : [2]$
     (%i15) /* Interval ends */
      aleft:-1.0$
     (%i16) aright:1.0$
     (%i17) /* Locations of side conditions */
      zeta : float([-1, 1])$
     (%i18) /* Set up parameter array.  */
      ipar : makelist(0,k,1,11)$
     (%i19) /* linear prob */
      ipar[1] : 0$
     (%i20) /* 5 collocation points per subinterval */
      ipar[2] : 5$
     (%i21) /* Initial uniform mesh of 1 subintervals */
      ipar[3] : 1$
     (%i22) ipar[8] : 0$
     (%i23) /* Size of fspace, ispace */
      ipar[5] : 10000$
     (%i24) ipar[6] :  1000$
     (%i25) /* No output.  Don't do this for development. */
      ipar[7]:1$
     (%i26) /* No initial guess is provided */
      ipar[9] : 0$
     (%i27) /* Regular problem */
      ipar[10] : 0$
     (%i28) /* No fixed points in mesh */
      ipar[11] : 0$
     (%i29) /* Tolerances on two components */
      ipar[4] : 2$
     (%i30) /* Two error tolerances (on u and its derivative)
        Relatively large tolerances to keep the example small */
      ltol : [1, 2]$
     (%i31) tol : [1e-4, 1e-4]$
     (%i32) fspace : makelist(0e0, k, 1, ipar[5])$
     (%i33) ispace : makelist(0, k, 1, ipar[6])$
     (%i34) fixpnt : []$
     (%i35) /* First run with default initial guess.
        Returns iflag. 1 = success */
      ([iflag, fspace, ispace] :
       colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol,
       fixpnt, ispace, fspace,
       0, fsub, dfsub, gsub, dgsub, dummy),
       if (iflag#1) then error("On return from colnew_expert: iflag = ",iflag),
       iflag);
     (%o35)                          1
     (%i36) /* Function to generate equally spaced list of values */
      xlist(xmin,xmax,n):=block([dx:(xmax-xmin)/n],makelist(i,i,0,n)*dx+xmin)$
     (%i37) /* x values for solution.  Cluster around x=0 */
      X: xlist(aleft,aright,500)$
     (%i38) /* Generate solution values for z1=u(x) */
      ans:colnew_appsln(X,2,fspace,ispace)$
     (%i39) z:maplist(first,ans)$
     (%i40) Z:[z]$
     (%i41) /* Compare with exact solution and report */
      y:float(map(exact,X))$
     (%i42) maxerror:apply(max,abs(y-z));
     (%o42)                6.881499912125832e-7
     (%i43) printf(true," e: ~8,3e  iflag ~3d  Mesh size ~3d  max error ~8,3e~%",
       e,iflag,ispace[1],maxerror);
      e: 1.000E-2  iflag   1  Mesh size  16  max error 6.881E-7
     (%o43)                        false
     (%i44) /* Now use continuation to solve for progressively smaller e
        Use previous solution as initial guess and every second point
        from previous mesh as initial mesh */
      ipar[9] : 3$
     (%i45) /* Run COLNEW using continuation for new value of e
        Set new mesh size ipar[3] from previous size ispace[1]
        Push list of values of z1=u(x) on to list Z */
      run_it(e_):=block(
       e:e_,
       ipar[3]:ispace[1],
       [iflag, fspace, ispace]:
          colnew_expert(ncomp,m,aleft,aright,zeta,ipar,ltol,tol,fixpnt,
          ispace,fspace,0,fsub,dfsub,gsub,dgsub,dummy),
       if (iflag#1) then error("On return from colnew_expert: iflag =",iflag),
       ans:colnew_appsln(X,2,fspace,ispace),
       z:maplist(first,ans),
       push(z,Z),
       y:float(map(exact,X)),
       maxerror:apply(max,abs(y-z)),
       printf(true," e: ~8,3e  iflag ~3d  Mesh size ~3d  max error ~8,3e~%",
         e,iflag,ispace[1],maxerror),
       iflag
      )$
     (%i46) for e_ in [1e-3,1e-4,1e-5,1e-6] do run_it(e_)$
      e: 1.000E-3  iflag   1  Mesh size  20  max error 3.217E-7
      e: 1.000E-4  iflag   1  Mesh size  40  max error 3.835E-7
      e: 1.000E-5  iflag   1  Mesh size  38  max error 8.690E-9
      e: 1.000E-6  iflag   1  Mesh size  60  max error 6.313E-7
     (%i47) /* Z is list of solutions z1 = u(x).  Restore order. */
      Z:reverse(Z)$
     (%i48) /* Plot z1=u(x) for each value of e
      plot2d([
       [discrete,X,Z[1]], [discrete,X,Z[2]], [discrete,X,Z[3]],
       [discrete,X,Z[4]], [discrete,X,Z[5]]],
       [legend,"e=1e-2","e=1e-3","e=1e-4","e=1e-5","e=1e-6"],
       [xlabel,"x"],[ylabel,"u(x)"],
       [png_file,"./colnew-ex5.png"]); */
      done$


File: maxima.info,  Node: References for colnew,  Prev: Examples for colnew,  Up: Package colnew

48.4 References for colnew
==========================

(Gawain&Bell 1978) T. H. Gawain and R. E. Ball, Improved Finite
Difference Formulas for Boundary Value Problems, International Journal
for Numerical Methods in Engineering 12, no.  7 (1978) 1151–60.
doi:10.1002/nme.1620120706 (https://doi.org/10.1002/nme.1620120706)

   (Ascher 1979a) U. Ascher, J. Christiansen and R. D. Russell, A
collocation solver for mixed order systems of boundary value problems,
Math.  Comp.  33 (1979), 659-679, doi:10.1090/S0025-5718-1979-0521281-7
(https:/doi.org/10.1090/S0025-5718-1979-0521281-7)

   (Ascher 1979b) U. Ascher, J. Christiansen and R. D. Russell, COLSYS -
a collocation code for boundary value problems, in Codes for
boundary-value problems in ordinary differential equations, Lecture
Notes in Computer Science 76, Springer Verlag, B. Childs et.  al.
(eds.)  (1979), 164-185, ISBN 978-3-540-09554-5

   (Ascher 1981a) U. Ascher, J. Christiansen and R. D. Russell,
Collocation software for boundary-value odes, ACM Trans.  Math Software
7 (1981), 209-222.  doi:10.1145/355945.355950
(https:/doi.org/10.1145/355945.355950)

   (Ascher 1981b) U. Ascher, U., J. Christiansen, and R. D. Russell.
‘Algorithm 569: COLSYS: Collocation Software for Boundary-Value ODEs
[D2]’.  ACM Transactions on Mathematical Software 7, no.  2 (June 1981):
223–29.  doi:10.1145/355945.355951
(https:/doi.org/10.1145/355945.355951)

   (Asher&Russell 1981) U. Ascher and R. D. Russell.  ‘Reformulation of
Boundary Value Problems into “Standard” Form’.  SIAM Review 23, no.  2
(April 1981), 238–54, doi:10.1137/1023039
(https:/doi.org/10.1137/1023039)

   (Parker&Wan 1984) David F. Parker and Frederic Y. M. Wan, ‘Finite
Polar Dimpling of Shallow Caps Under Sub-Buckling Axisymmetric Pressure
Distributions’.  SIAM Journal on Applied Mathematics 44, no.  2 (April
1984): 301–26, doi:10.1137/0144022 (https://doi.org/10.1137/0144022)

   (Bader&Ascher 1987) G. Bader and U. Ascher, A new basis
implementation for a mixed order boundary value ode solver, SIAM J.
Scient.  Stat.  Comput.  (1987), 483-500, doi:10.1137/0908047
(https://doi.org/10.1137/0908047)

   (Ascher et al, 1995) Uri M. Ascher, Robert M. M. Mattheij, and Robert
D. Russell.  Numerical Solution of Boundary Value Problems for Ordinary
Differential Equations.  Classics in Applied Mathematics 13, SIAM,
(1995), ISBN 978-0-89871-354-1

   (Bellon&Talon 2005) M. Bellon, M. Talon, Spectrum of the quantum
Neumann model, Physics Letters A, Volume 337, Issues 4–6, pp 360-368,
doi:10.1016/j.physleta.2005.02.002
(https://doi.org/10.1016/j.physleta.2005.02.002) arXiv:hep-th/0407005
(https://arxiv.org/abs/hep-th/0407005)


File: maxima.info,  Node: Package combinatorics,  Next: Package contrib_ode,  Prev: Package colnew,  Up: Top

49 Package combinatorics
************************

* Menu:

* Introduction to combinatorics::
* Functions and Variables for Combinatorics::


File: maxima.info,  Node: Introduction to combinatorics,  Next: Functions and Variables for Combinatorics,  Prev: Package combinatorics,  Up: Package combinatorics

49.1 Package combinatorics
==========================

The ‘combinatorics’ package provides several functions to work with
permutations and to permute elements of a list.  The permutations of
degree _n_ are all the _n_!  possible orderings of the first _n_
positive integers, 1, 2, ..., _n_.  The functions in this packages
expect a permutation to be represented by a list of those integers.

   Cycles are represented as a list of two or more integers _i_1_,
_i_2_, ..., _i_m_, all different.  Such a list represents a permutation
where the integer _i_2_ appears in the _i_1_th position, the integer
_i_3_ appears in the _i_2_th position and so on, until the integer
_i_1_, which appears in the _i_m_th position.

   For instance, [4, 2, 1, 3] is one of the 24 permutations of degree
four, which can also be represented by the cycle [1, 4, 3].  The
functions where cycles are used to represent permutations also require
the order of the permutation to avoid ambiguity.  For instance, the same
cycle [1, 4, 3] could refer to the permutation of order 6: [4, 2, 1, 3,
5, 6].  A product of cycles must be represented by a list of cycles; the
cycles at the end of the list are applied first.  For example, [[2, 4],
[1, 3, 6, 5]] is equivalent to the permutation [3, 4, 6, 2, 1, 5].

   A cycle can be written in several ways.  for instance, [1, 3, 6, 5],
[3, 6, 5, 1] and [6, 5, 1, 3] are all equivalent.  The canonical form
used in the package is the one that places the lowest index in the first
place.  A cycle with only two indices is also called a transposition and
if the two indices are consecutive, it is called an adjacent
transposition.

   To run an interactive tutorial, use the command ‘demo
(combinatorics)’.  Since this is an additional package, it must be
loaded with the command ‘load("combinatorics")’.


File: maxima.info,  Node: Functions and Variables for Combinatorics,  Prev: Introduction to combinatorics,  Up: Package combinatorics

49.2 Functions and Variables for Combinatorics
==============================================

 -- Function: apply_cycles (<cl>,<l>)

     Permutes the list or set <l> applying to it the list of cycles
     <cl>.  The cycles at the end of the list are applied first and the
     first cycle in the list <cl> is the last one to be applied.

     See also ‘permute’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) lis1:[a,b*c^2,4,z,x/y,1/2,ff23(x),0];
                                  2        x  1
          (%o2)            [a, b c , 4, z, -, -, ff23(x), 0]
                                           y  2
          (%i3) apply_cycles ([[1, 6], [2, 6, 5, 7]], lis1);
                            x  1                       2
          (%o3)            [-, -, 4, z, ff23(x), a, b c , 0]
                            y  2

 -- Function: cyclep (<c>, <n>)

     Returns true if <c> is a valid cycle of order <n> namely, a list of
     non-repeated positive integers less or equal to <n>.  Otherwise, it
     returns false.

     See also ‘permp’.

     Examples:

          (%i1) load("combinatorics")$
          (%i2) cyclep ([-2,3,4], 5);
          (%o2)                          false
          (%i3) cyclep ([2,3,4,2], 5);
          (%o3)                          false
          (%i4) cyclep ([6,3,4], 5);
          (%o4)                          false
          (%i5) cyclep ([6,3,4], 6);
          (%o5)                          true

 -- Function: perm_cycles (<p>)

     Returns permutation <p> as a product of cycles.  The cycles are
     written in a canonical form, in which the lowest index in the cycle
     is placed in the first position.

     See also ‘perm_decomp’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_cycles ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                 [[1, 4], [2, 6, 5, 7]]

 -- Function: perm_decomp (<p>)

     Returns the minimum set of adjacent transpositions whose product
     equals the given permutation <p>.

     See also ‘perm_cycles’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_decomp ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2) [[6, 7], [5, 6], [6, 7], [3, 4], [4, 5], [2, 3], [3, 4],
                                      [4, 5], [5, 6], [1, 2], [2, 3], [3, 4]]

 -- Function: perm_inverse (<p>)

     Returns the inverse of a permutation of <p>, namely, a permutation
     <q> such that the products <pq> and <qp> are equal to the identity
     permutation: [1, 2, 3, ..., <n>], where <n> is the length of <p>.

     See also ‘permult’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_inverse ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                [4, 7, 3, 1, 6, 2, 5, 8]

 -- Function: perm_length (<p>)

     Determines the minimum number of adjacent transpositions necessary
     to write permutation <p> as a product of adjacent transpositions.
     An adjacent transposition is a cycle with only two numbers, which
     are consecutive integers.

     See also ‘perm_decomp’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_length ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                           12

 -- Function: perm_lex_next (<p>)

     Returns the permutation that comes after the given permutation <p>,
     in the sequence of permutations in lexicographic order.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_lex_next ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                [4, 6, 3, 1, 7, 5, 8, 2]

 -- Function: perm_lex_rank (<p>)

     Finds the position of permutation <p>, an integer from 1 to the
     degree <n> of the permutation, in the sequence of permutations in
     lexicographic order.

     See also ‘perm_lex_unrank’ and ‘perms_lex’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_lex_rank ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                          18255

 -- Function: perm_lex_unrank (<n>, <i>)

     Returns the _n_-degree permutation at position <i> (from 1 to _n_!)
     in the lexicographic ordering of permutations.

     See also ‘perm_lex_rank’ and ‘perms_lex’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_lex_unrank (8, 18255);
          (%o2)                [4, 6, 3, 1, 7, 5, 2, 8]

 -- Function: perm_next (<p>)

     Returns the permutation that comes after the given permutation <p>,
     in the sequence of permutations in Trotter-Johnson order.

     See also ‘perms’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_next ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                [4, 6, 3, 1, 7, 5, 8, 2]

 -- Function: perm_parity (<p>)

     Finds the parity of permutation <p>: 0 if the minimum number of
     adjacent transpositions necessary to write permutation <p> as a
     product of adjacent transpositions is even, or 1 if that number is
     odd.

     See also ‘perm_decomp’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_parity ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                            0

 -- Function: perm_rank (<p>)

     Finds the position of permutation <p>, an integer from 1 to the
     degree <n> of the permutation, in the sequence of permutations in
     Trotter-Johnson order.

     See also ‘perm_unrank’ and ‘perms’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_rank ([4, 6, 3, 1, 7, 5, 2, 8]);
          (%o2)                          19729

 -- Function: perm_undecomp (<cl>, <n>)

     Converts the list of cycles <cl> of degree <n> into an <n> degree
     permutation, equal to their product.

     See also ‘perm_decomp’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_undecomp ([[1,6],[2,6,5,7]], 8);
          (%o2)                [5, 6, 3, 4, 7, 1, 2, 8]

 -- Function: perm_unrank (<n>, <i>)

     Returns the _n_-degree permutation at position <i> (from 1 to _n_!)
     in the Trotter-Johnson ordering of permutations.

     See also ‘perm_rank’ and ‘perms’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) perm_unrank (8, 19729);
          (%o2)                [4, 6, 3, 1, 7, 5, 2, 8]

 -- Function: permp (<p>)

     Returns true if <p> is a valid permutation namely, a list of length
     <n>, whose elements are all the positive integers from 1 to <n>,
     without repetitions.  Otherwise, it returns false.

     Examples:

          (%i1) load("combinatorics")$
          (%i2) permp ([2,0,3,1]);
          (%o2)                          false
          (%i3) permp ([2,1,4,3]);
          (%o3)                          true

 -- Function: perms
          perms (<n>)
          perms (<n>, <i>)
          perms (<n>, <i>, <j>)

     ‘perms(<n>)’ returns a list of all _n_-degree permutations in the
     so-called Trotter-Johnson order.

     ‘perms(<n>, <i>)’ returns the _n_-degree permutation which is at
     the _i_th position (from 1 to _n_!)  in the Trotter-Johnson
     ordering of the permutations.

     ‘perms(<n>, <i>, <j>)’ returns a list of the _n_-degree
     permutations between positions <i> and <j> in the Trotter-Johnson
     ordering of the permutations.

     The sequence of permutations in Trotter-Johnson order starts with
     the identity permutation and each consecutive permutation can be
     obtained from the previous one a by single adjacent transposition.

     See also ‘perm_next’, ‘perm_rank’ and ‘perm_unrank’.

     Examples:

          (%i1) load("combinatorics")$
          (%i2) perms (4);
          (%o2) [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [4, 1, 2, 3],
          [4, 1, 3, 2], [1, 4, 3, 2], [1, 3, 4, 2], [1, 3, 2, 4],
          [3, 1, 2, 4], [3, 1, 4, 2], [3, 4, 1, 2], [4, 3, 1, 2],
          [4, 3, 2, 1], [3, 4, 2, 1], [3, 2, 4, 1], [3, 2, 1, 4],
          [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 3, 1], [4, 2, 3, 1],
          [4, 2, 1, 3], [2, 4, 1, 3], [2, 1, 4, 3], [2, 1, 3, 4]]
          (%i3) perms (4, 12);
          (%o3)                     [[4, 3, 1, 2]]
          (%i4) perms (4, 12, 14);
          (%o4)       [[4, 3, 1, 2], [4, 3, 2, 1], [3, 4, 2, 1]]

 -- Function: perms_lex
          perms_lex (<n>)
          perms_lex (<n>, <i>)
          perms_lex (<n>, <i>, <j>)

     ‘perms_lex(<n>)’ returns a list of all _n_-degree permutations in
     the so-called lexicographic order.

     ‘perms_lex(<n>, <i>)’ returns the _n_-degree permutation which is
     at the _i_th position (from 1 to _n_!)  in the lexicographic
     ordering of the permutations.

     ‘perms_lex(<n>, <i>, <j>)’ returns a list of the _n_-degree
     permutations between positions <i> and <j> in the lexicographic
     ordering of the permutations.

     The sequence of permutations in lexicographic order starts with all
     the permutations with the lowest index, 1, followed by all
     permutations starting with the following index, 2, and so on.  The
     permutations starting by an index _i_ are the permutations of the
     first _n_ integers different from _i_ and they are also placed in
     lexicographic order, where the permutations with the lowest of
     those integers are placed first and so on.

     See also ‘perm_lex_next’, ‘perm_lex_rank’ and ‘perm_lex_unrank’.

     Examples:

          (%i1) load("combinatorics")$
          (%i2) perms_lex (4);
          (%o2) [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2],
          [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3],
          [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1],
          [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1],
          [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2],
          [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]
          (%i3) perms_lex (4, 12);
          (%o3)                     [[2, 4, 3, 1]]
          (%i4) perms_lex (4, 12, 14);
          (%o4)       [[2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2]]

 -- Function: permult (<p_1>, ..., <p_m>)

     Returns the product of two or more permutations <p_1>, ..., <p_m>.

     Example:

          (%i1) load("combinatorics")$
          (%i2) permult ([2,3,1], [3,1,2], [2,1,3]);
          (%o2)                        [2, 1, 3]

 -- Function: permute (<p>, <l>)

     Applies the permutation <p> to the elements of the list (or set)
     <l>.

     Example:

          (%i1) load("combinatorics")$
          (%i2) lis1: [a,b*c^2,4,z,x/y,1/2,ff23(x),0];
                                  2        x  1
          (%o2)            [a, b c , 4, z, -, -, ff23(x), 0]
                                           y  2
          (%i3) permute ([4, 6, 3, 1, 7, 5, 2, 8], lis1);
                               1                 x     2
          (%o3)            [z, -, 4, a, ff23(x), -, b c , 0]
                               2                 y

 -- Function: random_perm (<n>)

     Returns a random permutation of degree <n>.

     See also ‘random_permutation’.

     Example:

          (%i1) load("combinatorics")$
          (%i2) random_perm (7);
          (%o2)                  [6, 3, 4, 7, 5, 1, 2]


File: maxima.info,  Node: Package contrib_ode,  Next: Package descriptive,  Prev: Package combinatorics,  Up: Top

50 Package contrib_ode
**********************

* Menu:

* Introduction to contrib_ode::
* Functions and Variables for contrib_ode::
* Possible improvements to contrib_ode::
* Test cases for contrib_ode::
* References for contrib_ode::


File: maxima.info,  Node: Introduction to contrib_ode,  Next: Functions and Variables for contrib_ode,  Prev: Package contrib_ode,  Up: Package contrib_ode

50.1 Introduction to contrib_ode
================================

Maxima's ordinary differential equation (ODE) solver ‘ode2’ solves
elementary linear ODEs of first and second order.  The function
‘contrib_ode’ extends ‘ode2’ with additional methods for linear and
non-linear first order ODEs and linear homogeneous second order ODEs.
The code is still under development and the calling sequence may change
in future releases.  Once the code has stabilized it may be moved from
the contrib directory and integrated into Maxima.

   This package must be loaded with the command ‘load("contrib_ode")’
before use.

   The calling convention for ‘contrib_ode’ is identical to ‘ode2’.  It
takes three arguments: an ODE (only the left hand side need be given if
the right hand side is 0), the dependent variable, and the independent
variable.  When successful, it returns a list of solutions.

   The form of the solution differs from ‘ode2’.  As non-linear
equations can have multiple solutions, ‘contrib_ode’ returns a list of
solutions.  Each solution can have a number of forms:
   • an explicit solution for the dependent variable,

   • an implicit solution for the dependent variable,

   • a parametric solution in terms of variable ‘%t’, or

   • a transformation into another ODE in variable ‘%u’.

   ‘contrib_ode’ uses the global variables ‘%c’, ‘%k1’, ‘%k2’, ‘method’
and ‘yp’ similarly to ‘ode2’.

   If ‘contrib_ode’ cannot obtain a solution for whatever reason, it
returns ‘false’, after perhaps printing out an error message.

   It is necessary to return a list of solutions, as even first order
non-linear ODEs can have multiple solutions.  For example:

     (%i1) load("contrib_ode")$
     (%i2) eqn:x*'diff(y,x)^2-(1+x*y)*'diff(y,x)+y=0;
                         dy 2             dy
     (%o2)            x (--)  - (1 + x y) -- + y = 0
                         dx               dx
     (%i3) contrib_ode(eqn,y,x);
                         dy 2             dy
     (%t3)            x (--)  - (1 + x y) -- + y = 0
                         dx               dx

                   first order equation not linear in y'

                                                  x
     (%o3)             [y = log(x) + %c, y = %c %e ]
     (%i4) method;
     (%o4)                        factor

   Nonlinear ODEs can have singular solutions without constants of
integration, as in the second solution of the following example:

     (%i1) load("contrib_ode")$
     (%i2) eqn:'diff(y,x)^2+x*'diff(y,x)-y=0;
                            dy 2     dy
     (%o2)                 (--)  + x -- - y = 0
                            dx       dx
     (%i3) contrib_ode(eqn,y,x);
                            dy 2     dy
     (%t3)                 (--)  + x -- - y = 0
                            dx       dx

                   first order equation not linear in y'

                                                2
                                      2        x
     (%o3)              [y = %c x + %c , y = - --]
                                               4
     (%i4) method;
     (%o4)                       clairaut

   The following ODE has two parametric solutions in terms of the dummy
variable ‘%t’.  In this case the parametric solutions can be manipulated
to give explicit solutions.

     (%i1) load("contrib_ode")$
     (%i2) eqn:'diff(y,x)=(x+y)^2;
                               dy          2
     (%o2)                     -- = (x + y)
                               dx
     (%i3) contrib_ode(eqn,y,x);
     (%o3) [[x = %c - atan(sqrt(%t)), y = (- x) - sqrt(%t)],
                          [x = atan(sqrt(%t)) + %c, y = sqrt(%t) - x]]
     (%i4) method;
     (%o4)                       lagrange

   The following example (Kamke 1.112) demonstrates an implicit
solution.

     (%i1) load("contrib_ode")$
     (%i2) assume(x>0,y>0);
     (%o2)                    [x > 0, y > 0]
     (%i3) eqn:x*'diff(y,x)-x*sqrt(y^2+x^2)-y;
                          dy           2    2
     (%o3)              x -- - x sqrt(y  + x ) - y
                          dx
     (%i4) contrib_ode(eqn,y,x);
                                       y
     (%o4)                  [x - asinh(-) = %c]
                                       x
     (%i5) method;
     (%o5)                          lie

   The following Riccati equation is transformed into a linear second
order ODE in the variable ‘%u’.  Maxima is unable to solve the new ODE,
so it is returned unevaluated.
     (%i1) load("contrib_ode")$
     (%i2) eqn:x^2*'diff(y,x)=a+b*x^n+c*x^2*y^2;
                         2 dy      2  2      n
     (%o2)              x  -- = c x  y  + b x  + a
                           dx
     (%i3) contrib_ode(eqn,y,x);
                    d%u
                    ---                            2
                    dx        2  a       n - 2    d %u
     (%o3)  [[y = - ----, %u c  (-- + b x     ) + ---- c = 0]]
                    %u c          2                 2
                                 x                dx
     (%i4) method;
     (%o4)                        riccati

   For first order ODEs ‘contrib_ode’ calls ‘ode2’.  It then tries the
following methods: factorization, Clairaut, Lagrange, Riccati, Abel and
Lie symmetry methods.  The Lie method is not attempted on Abel equations
if the Abel method fails, but it is tried if the Riccati method returns
an unsolved second order ODE.

   For second order ODEs ‘contrib_ode’ calls ‘ode2’ then ‘odelin’.

   Extensive debugging traces and messages are displayed if the command
‘put('contrib_ode,true,'verbose)’ is executed.


File: maxima.info,  Node: Functions and Variables for contrib_ode,  Next: Possible improvements to contrib_ode,  Prev: Introduction to contrib_ode,  Up: Package contrib_ode

50.2 Functions and Variables for contrib_ode
============================================

 -- Function: contrib_ode (<eqn>, <y>, <x>)

     Returns a list of solutions of the ODE <eqn> with independent
     variable <x> and dependent variable <y>.

 -- Function: odelin (<eqn>, <y>, <x>)

     ‘odelin’ solves linear homogeneous ODEs of first and second order
     with independent variable <x> and dependent variable <y>.  It
     returns a fundamental solution set of the ODE.

     For second order ODEs, ‘odelin’ uses a method, due to Bronstein and
     Lafaille, that searches for solutions in terms of given special
     functions.

          (%i1) load("contrib_ode")$
          (%i2) odelin(x*(x+1)*'diff(y,x,2)+(x+5)*'diff(y,x,1)+(-4)*y,y,x);
                 gauss_a(- 6, - 2, - 3, - x)  gauss_b(- 6, - 2, - 3, - x)
          (%o2) {---------------------------, ---------------------------}
                              4                            4
                             x                            x

 -- Function: ode_check (<eqn>, <soln>)

     Returns the value of ODE <eqn> after substituting a possible
     solution <soln>.  The value is equivalent to zero if <soln> is a
     solution of <eqn>.

          (%i1) load("contrib_ode")$
          (%i2) eqn:'diff(y,x,2)+(a*x+b)*y;
                                   2
                                  d y
          (%o2)                   --- + (b + a x) y
                                    2
                                  dx
          (%i3) ans:[y = bessel_y(1/3,2*(a*x+b)^(3/2)/(3*a))*%k2*sqrt(a*x+b)
                   +bessel_j(1/3,2*(a*x+b)^(3/2)/(3*a))*%k1*sqrt(a*x+b)];
                                            3/2
                              1  2 (b + a x)
          (%o3) [y = bessel_y(-, --------------) %k2 sqrt(a x + b)
                              3       3 a
                                                    3/2
                                      1  2 (b + a x)
                           + bessel_j(-, --------------) %k1 sqrt(a x + b)]
                                      3       3 a
          (%i4) ode_check(eqn,ans[1]);
          (%o4)                           0

 -- Function: gauss_a (<a>, <b>, <c>, <x>)

     ‘gauss_a(a,b,c,x)’ and ‘gauss_b(a,b,c,x)’ are 2F1 hypergeometric
     functions.  They represent any two independent solutions of the
     hypergeometric differential equation ‘x*(1-x) diff(y,x,2) +
     [c-(a+b+1)x] diff(y,x) - a*b*y = 0’ (A&S 15.5.1).

     The only use of these functions is in solutions of ODEs returned by
     ‘odelin’ and ‘contrib_ode’.  The definition and use of these
     functions may change in future releases of Maxima.

     See also ‘gauss_b’, ‘dgauss_a’ and ‘gauss_b’.

 -- Function: gauss_b (<a>, <b>, <c>, <x>)
     See ‘gauss_a’.

 -- Function: dgauss_a (<a>, <b>, <c>, <x>)
     The derivative with respect to <x> of ‘gauss_a’‘(<a>, <b>, <c>,
     <x>)’.

 -- Function: dgauss_b (<a>, <b>, <c>, <x>)
     The derivative with respect to <x> of ‘gauss_b’‘(<a>, <b>, <c>,
     <x>)’.

 -- Function: kummer_m (<a>, <b>, <x>)

     Kummer's M function, as defined in Abramowitz and Stegun, Handbook
     of Mathematical Functions, Section 13.1.2.

     The only use of this function is in solutions of ODEs returned by
     ‘odelin’ and ‘contrib_ode’.  The definition and use of this
     function may change in future releases of Maxima.

     See also ‘kummer_u’, ‘dkummer_m’, and ‘dkummer_u’.

 -- Function: kummer_u (<a>, <b>, <x>)

     Kummer's U function, as defined in Abramowitz and Stegun, Handbook
     of Mathematical Functions, Section 13.1.3.

     See ‘kummer_m’.

 -- Function: dkummer_m (<a>, <b>, <x>)
     The derivative with respect to <x> of ‘kummer_m’‘(<a>, <b>, <x>)’.

 -- Function: dkummer_u (<a>, <b>, <x>)
     The derivative with respect to <x> of ‘kummer_u’‘(<a>, <b>, <x>)’.

 -- Function: bessel_simplify (<expr>)
     Simplifies expressions containing Bessel functions ‘bessel_j’,
     ‘bessel_y’, ‘bessel_i’, ‘bessel_k’, ‘hankel_1’, ‘hankel_2’,
     ‘struve_h’ and ‘struve_l’.  Recurrence relations (DLMF
     §10.6(i))(A&S 9.1.27) are used to replace functions of highest
     order n by functions of order n-1 and n-2.

     This process is repeated until all the orders differ by less than
     2.

          (%i1) load("contrib_ode")$
          (%i2) bessel_simplify(4*bessel_j(n,x^2)*(x^2-n^2/x^2)
            +x*((bessel_j(n-2,x^2)-bessel_j(n,x^2))*x
            -(bessel_j(n,x^2)-bessel_j(n+2,x^2))*x)
            -2*bessel_j(n+1,x^2)+2*bessel_j(n-1,x^2));
          (%o2)                           0
          (%i3) bessel_simplify( -2*bessel_j(1,z)*z^3 - 10*bessel_j(2,z)*z^2
           + 15*%pi*bessel_j(1,z)*struve_h(3,z)*z - 15*%pi*struve_h(1,z)
             *bessel_j(3,z)*z - 15*%pi*bessel_j(0,z)*struve_h(2,z)*z
           + 15*%pi*struve_h(0,z)*bessel_j(2,z)*z - 30*%pi*bessel_j(1,z)
             *struve_h(2,z) + 30*%pi*struve_h(1,z)*bessel_j(2,z));
          (%o3)                           0

 -- Function: expintegral_e_simplify (<expr>)
     Simplify expressions containing exponential integral
     ‘expintegral_e’ using the recurrence (A&S 5.1.14).

     expintegral_e(n+1,z) = (1/n) * (exp(-z)-z*expintegral_e(n,z)) n =
     1,2,3 ....


File: maxima.info,  Node: Possible improvements to contrib_ode,  Next: Test cases for contrib_ode,  Prev: Functions and Variables for contrib_ode,  Up: Package contrib_ode

50.3 Possible improvements to contrib_ode
=========================================

These routines are work in progress.  I still need to:

   • Extend the FACTOR method ‘ode1_factor’ to work for multiple roots.

   • Extend the FACTOR method ‘ode1_factor’ to attempt to solve higher
     order factors.  At present it only attempts to solve linear
     factors.

   • Fix the LAGRANGE routine ‘ode1_lagrange’ to prefer real roots over
     complex roots.

   • Add additional methods for Riccati equations.

   • Improve the detection of Abel equations of second kind.  The
     existing pattern matching is weak.

   • Work on the Lie symmetry group routine ‘ode1_lie’.  There are quite
     a few problems with it: some parts are unimplemented; some test
     cases seem to run forever; other test cases crash; yet others
     return very complex "solutions".  I wonder if it really ready for
     release yet.

   • Add more test cases.


File: maxima.info,  Node: Test cases for contrib_ode,  Next: References for contrib_ode,  Prev: Possible improvements to contrib_ode,  Up: Package contrib_ode

50.4 Test cases for contrib_ode
===============================

The routines have been tested on a approximately one thousand test cases
from Murphy, Kamke, Zwillinger and elsewhere.  These are included in the
tests subdirectory.

   • The Clairaut routine ‘ode1_clairaut’ finds all known solutions,
     including singular solutions, of the Clairaut equations in Murphy
     and Kamke.

   • The other routines often return a single solution when multiple
     solutions exist.

   • Some of the "solutions" from ‘ode1_lie’ are overly complex and
     impossible to check.

   • There are some crashes.


File: maxima.info,  Node: References for contrib_ode,  Prev: Test cases for contrib_ode,  Up: Package contrib_ode

50.5 References for contrib_ode
===============================

  1. E. Kamke, Differentialgleichungen Lösungsmethoden und Lösungen, Vol
     1, Geest & Portig, Leipzig, 1961

  2. G. M. Murphy, Ordinary Differential Equations and Their Solutions,
     Van Nostrand, New York, 1960

  3. D. Zwillinger, Handbook of Differential Equations, 3rd edition,
     Academic Press, 1998

  4. F. Schwarz, Symmetry Analysis of Abel's Equation, Studies in
     Applied Mathematics, 100:269-294 (1998)

  5. F. Schwarz, Algorithmic Solution of Abel's Equation, Computing 61,
     39-49 (1998)

  6. E. S. Cheb-Terrab, A. D. Roche, Symmetries and First Order ODE
     Patterns, Computer Physics Communications 113 (1998), p 239.
     (<http://lie.uwaterloo.ca/papers/ode_vii.pdf>)

  7. E. S. Cheb-Terrab, T. Kolokolnikov, First Order ODEs, Symmetries
     and Linear Transformations, European Journal of Applied
     Mathematics, Vol.  14, No.  2, pp.  231-246 (2003).
     (<http://arxiv.org/abs/math-ph/0007023>,
     <http://lie.uwaterloo.ca/papers/ode_iv.pdf>)

  8. G. W. Bluman, S. C. Anco, Symmetry and Integration Methods for
     Differential Equations, Springer, (2002)

  9. M. Bronstein, S. Lafaille, Solutions of linear ordinary
     differential equations in terms of special functions, Proceedings
     of ISSAC 2002, Lille, ACM Press, 23-28.
     (<http://www-sop.inria.fr/cafe/Manuel.Bronstein/publications/issac2002.pdf>)


File: maxima.info,  Node: Package descriptive,  Next: Package diag,  Prev: Package contrib_ode,  Up: Top

51 Package descriptive
**********************

* Menu:

* Introduction to descriptive::
* Functions and Variables for data manipulation::
* Functions and Variables for descriptive statistics::
* Functions and Variables for statistical graphs::


File: maxima.info,  Node: Introduction to descriptive,  Next: Functions and Variables for data manipulation,  Prev: Package descriptive,  Up: Package descriptive

51.1 Introduction to descriptive
================================

Package ‘descriptive’ contains a set of functions for making descriptive
statistical computations and graphing.  Together with the source code
there are three data sets in your Maxima tree: ‘pidigits.data’,
‘wind.data’ and ‘biomed.data’.

   Any statistics manual can be used as a reference to the functions in
package ‘descriptive’.

   For comments, bugs or suggestions, please contact me at <'riotorto AT
yahoo DOT com'>.

   Here is a simple example on how the descriptive functions in
‘descriptive’ do they work, depending on the nature of their arguments,
lists or matrices,

     (%i1) load ("descriptive")$
     (%i2) /* univariate sample */   mean ([a, b, c]);
                                 c + b + a
     (%o2)                       ---------
                                     3
     (%i3) matrix ([a, b], [c, d], [e, f]);
                                 [ a  b ]
                                 [      ]
     (%o3)                       [ c  d ]
                                 [      ]
                                 [ e  f ]
     (%i4) /* multivariate sample */ mean (%);
                           e + c + a  f + d + b
     (%o4)                [---------, ---------]
                               3          3

   Note that in multivariate samples the mean is calculated for each
column.

   In case of several samples with possible different sizes, the Maxima
function ‘map’ can be used to get the desired results for each sample,

     (%i1) load ("descriptive")$
     (%i2) map (mean, [[a, b, c], [d, e]]);
                             c + b + a  e + d
     (%o2)                  [---------, -----]
                                 3        2

   In this case, two samples of sizes 3 and 2 were stored into a list.

   Univariate samples must be stored in lists like

     (%i1) s1 : [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
     (%o1)           [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

   and multivariate samples in matrices as in

     (%i1) s2 : matrix ([13.17, 9.29], [14.71, 16.88], [18.50, 16.88],
                  [10.58, 6.63], [13.33, 13.25], [13.21,  8.12]);
                             [ 13.17  9.29  ]
                             [              ]
                             [ 14.71  16.88 ]
                             [              ]
                             [ 18.5   16.88 ]
     (%o1)                   [              ]
                             [ 10.58  6.63  ]
                             [              ]
                             [ 13.33  13.25 ]
                             [              ]
                             [ 13.21  8.12  ]

   In this case, the number of columns equals the random variable
dimension and the number of rows is the sample size.

   Data can be introduced by hand, but big samples are usually stored in
plain text files.  For example, file ‘pidigits.data’ contains the first
100 digits of number ‘%pi’:
           3
           1
           4
           1
           5
           9
           2
           6
           5
           3 ...

   In order to load these digits in Maxima,

     (%i1) s1 : read_list (file_search ("pidigits.data"))$
     (%i2) length (s1);
     (%o2)                          100

   On the other hand, file ‘wind.data’ contains daily average wind
speeds at 5 meteorological stations in the Republic of Ireland (This is
part of a data set taken at 12 meteorological stations.  The original
file is freely downloadable from the StatLib Data Repository and its
analysis is discussed in Haslett, J., Raftery, A. E. (1989) <Space-time
Modelling with Long-memory Dependence: Assessing Ireland's Wind Power
Resource, with Discussion>.  Applied Statistics 38, 1-50).  This loads
the data:

     (%i1) s2 : read_matrix (file_search ("wind.data"))$
     (%i2) length (s2);
     (%o2)                          100
     (%i3) s2 [%]; /* last record */
     (%o3)            [3.58, 6.0, 4.58, 7.62, 11.25]

   Some samples contain non numeric data.  As an example, file
‘biomed.data’ (which is part of another bigger one downloaded from the
StatLib Data Repository) contains four blood measures taken from two
groups of patients, ‘A’ and ‘B’, of different ages,

     (%i1) s3 : read_matrix (file_search ("biomed.data"))$
     (%i2) length (s3);
     (%o2)                          100
     (%i3) s3 [1]; /* first record */
     (%o3)            [A, 30, 167.0, 89.0, 25.6, 364]

   The first individual belongs to group ‘A’, is 30 years old and
his/her blood measures were 167.0, 89.0, 25.6 and 364.

   One must take care when working with categorical data.  In the next
example, symbol ‘a’ is assigned a value in some previous moment and then
a sample with categorical value ‘a’ is taken,

     (%i1) a : 1$
     (%i2) matrix ([a, 3], [b, 5]);
                                 [ 1  3 ]
     (%o2)                       [      ]
                                 [ b  5 ]


File: maxima.info,  Node: Functions and Variables for data manipulation,  Next: Functions and Variables for descriptive statistics,  Prev: Introduction to descriptive,  Up: Package descriptive

51.2 Functions and Variables for data manipulation
==================================================

 -- Function: build_sample
          build_sample (<list>)
          build_sample (<matrix>)

     Builds a sample from a table of absolute frequencies.  The input
     table can be a matrix or a list of lists, all of them of equal
     size.  The number of columns or the length of the lists must be
     greater than 1.  The last element of each row or list is
     interpreted as the absolute frequency.  The output is always a
     sample in matrix form.

     Examples:

     Univariate frequency table.

          (%i1) load ("descriptive")$
          (%i2) sam1: build_sample([[6,1], [j,2], [2,1]]);
                                        [ 6 ]
                                        [   ]
                                        [ j ]
          (%o2)                         [   ]
                                        [ j ]
                                        [   ]
                                        [ 2 ]
          (%i3) mean(sam1);
                                        j + 4
          (%o3)                        [-----]
                                          2
          (%i4) barsplot(sam1) $

     Multivariate frequency table.

          (%i1) load ("descriptive")$
          (%i2) sam2: build_sample([[6,3,1], [5,6,2], [u,2,1],[6,8,2]]) ;
                                      [ 6  3 ]
                                      [      ]
                                      [ 5  6 ]
                                      [      ]
                                      [ 5  6 ]
          (%o2)                       [      ]
                                      [ u  2 ]
                                      [      ]
                                      [ 6  8 ]
                                      [      ]
                                      [ 6  8 ]
          (%i3) cov(sam2);
                [   2                 2                            ]
                [  u  + 158   (u + 28)     2 u + 174   11 (u + 28) ]
                [  -------- - ---------    --------- - ----------- ]
          (%o3) [     6          36            6           12      ]
                [                                                  ]
                [ 2 u + 174   11 (u + 28)            21            ]
                [ --------- - -----------            --            ]
                [     6           12                 4             ]
          (%i4) barsplot(sam2, grouping=stacked) $

 -- Function: continuous_freq
          continuous_freq (<data>)
          continuous_freq (<data>, <m>)

     Divides the range of <data> into intervals, and counts how many
     values fall into each one.

     A value <x> falls into an interval with left and right endpoints
     <a> and <b> if and only if ‘<x> > <a>’ and ‘<x> <= <b>’, except for
     the first (least or leftmost) interval, for which ‘<x> >= <a>’ and
     ‘<x> <= <b>’.  That is, an interval excludes its left endpoint and
     includes its right endpoint, except for the first interval, which
     includes both the left and right endpoints.

     <data> must be a list of numbers, or 1-dimensional array (as
     created by ‘make_array’).

     <m> is optional, and equals either the number of classes (10 by
     default), or a list of two elements (the least and greatest values
     to be counted), or a list of three elements (the least and greatest
     values to be counted, and the number of classes), or a set
     containing the endpoints of the class intervals.

     It is assumed that class intervals are contiguous.  That is, the
     right endpoint of one interval is equal to the left endpoint of the
     next.

     ‘continuous_freq’ returns a list of two lists.  The first list
     comprises all the endpoints of the class intervals, concatenated
     into a single list.  The second list contains the class counts for
     the intervals corresponding to elements of the first list.

     If sample values are all equal, this function returns exactly one
     class of width 2.

     Examples:

     Optional argument indicates the number of classes we want.  The
     first list in the output contains the interval limits, and the
     second the corresponding counts: there are 16 digits inside the
     interval ‘[0, 1.8]’, 24 digits in ‘(1.8, 3.6]’, and so on.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) continuous_freq (s1, 5);
                         9  18  27  36
          (%o3)     [[0, -, --, --, --, 9], [16, 24, 18, 17, 25]]
                         5  5   5   5

     Optional argument indicates we want 7 classes with limits -2 and
     12:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) continuous_freq (s1, [-2,12,7]);
          (%o3) [[- 2, 0, 2, 4, 6, 8, 10, 12], [8, 20, 22, 17, 20, 13, 0]]

     Optional argument indicates we want the default number of classes
     with limits -2 and 12:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) continuous_freq (s1, [-2,12]);
                         3  4  11  18     32  39  46  53
          (%o3) [[- 2, - -, -, --, --, 5, --, --, --, --, 12],
                         5  5  5   5      5   5   5   5
                                        [0, 8, 20, 12, 18, 9, 8, 25, 0, 0]]

     The first argument may be an array.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) a1 : make_array (fixnum, length (s1)) $
          (%i4) fillarray (a1, s1);
          (%o4) {Lisp Array: #(3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2\
           6 4 3 3 8 3 2 7 9 5
                         0 2 8 8 4 1 9 7 1 6 9 3 9 9 3 7 5 1 0 5 8 2 0 9 7\
           4 9 4 4 5 9 2
                         3 0 7 8 1 6 4 0 6 2 8 6 2 0 8 9 9 8 6 2 8 0 3 4 8\
           2 5 3 4 2 1 1
                         7 0 6 7)}
          (%i5) continuous_freq (a1);
                     9   9  27  18  9  27  63  36  81
          (%o5) [[0, --, -, --, --, -, --, --, --, --, 9],
                     10  5  10  5   2  5   10  5   10
                                       [8, 8, 12, 12, 10, 8, 9, 8, 12, 13]]

 -- Function: discrete_freq (<data>)

     Counts absolute frequencies in discrete samples, both numeric and
     categorical.  Its sole argument is a list, or 1-dimensional array
     (as created by ‘make_array’).

     Examples:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) discrete_freq (s1);
          (%o3) [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
                                       [8, 8, 12, 12, 10, 8, 9, 8, 12, 13]]

     In the return value, the first list gives the sample values, and
     the second, their absolute frequencies.

     The argument may be an array.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) a1 : make_array (fixnum, length (s1)) $
          (%i4) fillarray (a1, s1);
          (%o4) {Lisp Array: #(3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2\
           6 4 3 3 8 3 2 7 9 5
                         0 2 8 8 4 1 9 7 1 6 9 3 9 9 3 7 5 1 0 5 8 2 0 9 7\
           4 9 4 4 5 9 2
                         3 0 7 8 1 6 4 0 6 2 8 6 2 0 8 9 9 8 6 2 8 0 3 4 8\
           2 5 3 4 2 1 1
                         7 0 6 7)}
          (%i5) discrete_freq (a1);
          (%o5) [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
                                       [8, 8, 12, 12, 10, 8, 9, 8, 12, 13]]

 -- Function: standardize
          standardize (<list>)
          standardize (<matrix>)

     Subtracts to each element of the list the sample mean and divides
     the result by the standard deviation.  When the input is a matrix,
     ‘standardize’ subtracts to each row the multivariate mean, and then
     divides each component by the corresponding standard deviation.

 -- Function: subsample
          subsample (<data_matrix>, <predicate_function>)
          subsample (<data_matrix>, <predicate_function>, <col_num1>,
          <col_num2>, ...)

     This is a sort of variant of the Maxima ‘submatrix’ function.  The
     first argument is the data matrix, the second is a predicate
     function and optional additional arguments are the numbers of the
     columns to be taken.

     Examples:

     These are multivariate records in which the wind speed in the first
     meteorological station were greater than 18.  See that in the
     lambda expression the <i>-th component is referred to as ‘v[i]’.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) subsample (s2, lambda([v], v[1] > 18));
                        [ 19.38  15.37  15.12  23.09  25.25 ]
                        [                                   ]
                        [ 18.29  18.66  19.08  26.08  27.63 ]
          (%o3)         [                                   ]
                        [ 20.25  21.46  19.95  27.71  23.38 ]
                        [                                   ]
                        [ 18.79  18.96  14.46  26.38  21.84 ]

     In the following example, we request only the first, second and
     fifth components of those records with wind speeds greater or equal
     than 16 in station number 1 and less than 25 knots in station
     number 4.  The sample contains only data from stations 1, 2 and 5.
     In this case, the predicate function is defined as an ordinary
     Maxima function.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) g(x):= x[1] >= 16 and x[4] < 25$
          (%i4) subsample (s2, g, 1, 2, 5);
                               [ 19.38  15.37  25.25 ]
                               [                     ]
                               [ 17.33  14.67  19.58 ]
          (%o4)                [                     ]
                               [ 16.92  13.21  21.21 ]
                               [                     ]
                               [ 17.25  18.46  23.87 ]

     Here is an example with the categorical variables of ‘biomed.data’.
     We want the records corresponding to those patients in group ‘B’
     who are older than 38 years.

          (%i1) load ("descriptive")$
          (%i2) s3 : read_matrix (file_search ("biomed.data"))$
          (%i3) h(u):= u[1] = B and u[2] > 38 $
          (%i4) subsample (s3, h);
                          [ B  39  28.0  102.3  17.1  146 ]
                          [                               ]
                          [ B  39  21.0  92.4   10.3  197 ]
                          [                               ]
                          [ B  39  23.0  111.5  10.0  133 ]
                          [                               ]
                          [ B  39  26.0  92.6   12.3  196 ]
          (%o4)           [                               ]
                          [ B  39  25.0  98.7   10.0  174 ]
                          [                               ]
                          [ B  39  21.0  93.2   5.9   181 ]
                          [                               ]
                          [ B  39  18.0  95.0   11.3  66  ]
                          [                               ]
                          [ B  39  39.0  88.5   7.6   168 ]

     Probably, the statistical analysis will involve only the blood
     measures,

          (%i1) load ("descriptive")$
          (%i2) s3 : read_matrix (file_search ("biomed.data"))$
          (%i3) subsample (s3, lambda([v], v[1] = B and v[2] > 38),
                     3, 4, 5, 6);
                             [ 28.0  102.3  17.1  146 ]
                             [                        ]
                             [ 21.0  92.4   10.3  197 ]
                             [                        ]
                             [ 23.0  111.5  10.0  133 ]
                             [                        ]
                             [ 26.0  92.6   12.3  196 ]
          (%o3)              [                        ]
                             [ 25.0  98.7   10.0  174 ]
                             [                        ]
                             [ 21.0  93.2   5.9   181 ]
                             [                        ]
                             [ 18.0  95.0   11.3  66  ]
                             [                        ]
                             [ 39.0  88.5   7.6   168 ]

     This is the multivariate mean of ‘s3’,

          (%i1) load ("descriptive")$
          (%i2) s3 : read_matrix (file_search ("biomed.data"))$
          (%i3) mean (s3);
                 13 B + 7 A  317
          (%o3) [----------, ---, 87.178, 0.06 NA + 81.44999999999999,
                     20      10
                                                              3 NA + 19587
                                          18.122999999999998, ------------]
                                                                  100

     Here, the first component is meaningless, since ‘A’ and ‘B’ are
     categorical, the second component is the mean age of individuals in
     rational form, and the fourth and last values exhibit some strange
     behaviour.  This is because symbol ‘NA’ is used here to indicate
     <non available> data, and the two means are nonsense.  A possible
     solution would be to take out from the matrix those rows with ‘NA’
     symbols, although this deserves some loss of information.

          (%i1) load ("descriptive")$
          (%i2) s3 : read_matrix (file_search ("biomed.data"))$
          (%i3) g(v):= v[4] # NA and v[6] # NA $
          (%i4) mean (subsample (s3, g, 3, 4, 5, 6));
          (%o4) [79.4923076923077, 86.2032967032967, 16.93186813186813,
                                                                      2514
                                                                      ----]
                                                                       13

 -- Function: transform_sample (<matrix>, <varlist>, <exprlist>)

     Transforms the sample <matrix>, where each column is called
     according to <varlist>, following expressions in <exprlist>.

     Examples:

     The second argument assigns names to the three columns.  With these
     names, a list of expressions define the transformation of the
     sample.

          (%i1) load ("descriptive")$
          (%i2) data: matrix([3,2,7],[3,7,2],[8,2,4],[5,2,4]) $
          (%i3) transform_sample(data, [a,b,c], [c, a*b, log(a)]);
                                         [ 7  6   log(3) ]
                                         [               ]
                                         [ 2  21  log(3) ]
          (%o3)                          [               ]
                                         [ 4  16  log(8) ]
                                         [               ]
                                         [ 4  10  log(5) ]

     Add a constant column and remove the third variable.

          (%i1) load ("descriptive")$
          (%i2) data: matrix([3,2,7],[3,7,2],[8,2,4],[5,2,4]) $
          (%i3) transform_sample(data, [a,b,c], [makelist(1,k,length(data)),a,b]);
                                            [ 1  3  2 ]
                                            [         ]
                                            [ 1  3  7 ]
          (%o3)                             [         ]
                                            [ 1  8  2 ]
                                            [         ]
                                            [ 1  5  2 ]


File: maxima.info,  Node: Functions and Variables for descriptive statistics,  Next: Functions and Variables for statistical graphs,  Prev: Functions and Variables for data manipulation,  Up: Package descriptive

51.3 Functions and Variables for descriptive statistics
=======================================================

 -- Function: mean
          mean (<x>)
          mean (<x>, <w>)

     Returns the sample mean.  <x> must be a list or matrix.

     When <x> is a list, ‘mean’ returns the sample mean of <x>.

     When <x> is a matrix, ‘mean’ returns a list comprising the sample
     mean of each column.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <x[i]> is given equal weight, or a list of
     the same length as <x>, in which case the weight for <x[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     The unweighted sample mean is defined as

                               n
                              ====
                       _   1  \
                       x = -   >    x
                           n  /      i
                              ====
                              i = 1

     The weighted sample mean is defined as

                               n
                              ====
                       _   1  \
                       x = -   >    w  x
                           Z  /      i  i
                              ====
                              i = 1

     where <Z> is the sum of the weights,

                             n
                            ====
                            \
                       Z =   >    w
                            /      i
                            ====
                            i = 1

     Examples:

     Sample mean of a list.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) mean (s1);
                                         471
          (%o3)                          ---
                                         100

     Sample mean of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) mean (s2);
          (%o3) [9.9485, 10.160700000000004, 10.868499999999997,
                                    15.716600000000001, 14.844100000000001]

     Weighted sample mean of a list.

          (%i1) load ("descriptive")$
          (%i2) mean ([a, b, c, d], [1, 2, 3, 4]);
                                 4 d + 3 c + 2 b + a
          (%o2)                  -------------------
                                         10

     Weighted sample mean of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) mm: matrix ([p, q, r], [s, t, u]);
                                     [ p  q  r ]
          (%o2)                      [         ]
                                     [ s  t  u ]
          (%i3) mean (mm, [vv, ww]);
                        s ww + p vv  t ww + q vv  u ww + r vv
          (%o3)        [-----------, -----------, -----------]
                          ww + vv      ww + vv      ww + vv

 -- Function: var
          var (<x>)
          var (<x>, <w>)

     Returns the sample variance.  <x> must be a list or matrix.

     When <x> is a list, ‘var’ returns the sample variance of <x>.

     When <x> is a matrix, ‘var’ returns a list comprising the sample
     variance of each column.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <x[i]> is given equal weight, or a list of
     the same length as <x>, in which case the weight for <x[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     The unweighted sample variance is defined as

                              n
                            ====
                     2   1  \          _ 2
                    s  = -   >    (x - x)
                         n  /       i
                            ====
                            i = 1

     The weighted sample variance is defined as

                              n
                            ====
                     2   1  \             _ 2
                    s  = -   >    w  (x - x)
                         Z  /      i   i
                            ====
                            i = 1

     where <Z> is the sum of the weights,

                             n
                            ====
                            \
                       Z =   >    w
                            /      i
                            ====
                            i = 1

     Example:

     Sample variance of a list.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) var (s1), numer;
          (%o3)                   8.425899999999999

     Sample variance of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) var (s2);
          (%o3) [17.22190675000001, 14.987736510000005,
                 15.475728749999998, 32.17651044000001, 24.423076190000007]

     Weighted sample variance of a list.

          (%i1) load ("descriptive")$
          (%i2) var ([a - b, a, a + b], [3, 5, 7]);
                                            2
                                       134 b
          (%o2)                        ------
                                        225

     Weighted sample variance of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) mm: matrix ([a - b, c - d], [a, c], [a + b, c + d]);
                                  [ a - b  c - d ]
                                  [              ]
          (%o2)                   [   a      c   ]
                                  [              ]
                                  [ b + a  d + c ]
          (%i3) var (mm, [3, 5, 7]);
                                        2       2
                                   134 b   134 d
          (%o3)                   [------, ------]
                                    225     225

     See also function ‘var1’.

 -- Function: var1
          var1 (<list>)
          var1 (<matrix>)

     This is the sample variance, defined as
                               n
                             ====
                         1   \          _ 2
                        ---   >    (x - x)
                        n-1  /       i
                             ====
                             i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) var1 (s1), numer;
          (%o3)                    8.5110101010101
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) var1 (s2);
          (%o5) [17.395865404040414, 15.139127787878794,
                 15.632049242424243, 32.50152569696971, 24.669773929292937]

     See also function ‘var’.

 -- Function: std
          std (<x>)
          std (<x>, <w>)

     Returns the sample standard deviation.  <x> must be a list or
     matrix.

     When <x> is a list, ‘std’ returns the sample standard deviation of
     <x>, which is defined as the square root of the sample variance, as
     computed by ‘var’.

     When <x> is a matrix, ‘std’ returns a list comprising the sample
     standard deviation of each column.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <x[i]> is given equal weight, or a list of
     the same length as <x>, in which case the weight for <x[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     Example:

     Sample standard deviation of a list.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) std (s1), numer;
          (%o3)                  2.9027400848164135

     Sample standard deviation of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) std (s2);
          (%o3) [4.149928523480858, 3.8713998127292415,
                  3.9339202775348663, 5.672434260526957, 4.941970881136392]

     See also functions ‘var’ and ‘std1’.

 -- Function: std1
          std1 (<list>)
          std1 (<matrix>)

     This is the square root of the function ‘var1’, the variance with
     denominator n-1.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) std1 (s1), numer;
          (%o3)                   2.917363553109228
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) std1 (s2);
          (%o5) [4.170835096721089, 3.8909032097803196,
                  3.9537386411375555, 5.701010936401517, 4.966867617451963]

     See also functions ‘var1’ and ‘std’.

 -- Function: noncentral_moment
          noncentral_moment (<x>, <k>)
          noncentral_moment (<x>, <k>, <w>)

     Returns the noncentral moment of order <k>.  <x> must be a list or
     matrix.

     When <x> is a list, ‘noncentral_moment’ returns the noncentral
     moment of order <k> of <x>.

     When <x> is a matrix, ‘noncentral_moment’ returns a list comprising
     the noncentral moment of order <k> of each column.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <x[i]> is given equal weight, or a list of
     the same length as <x>, in which case the weight for <x[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     The unweighted noncentral moment of order <k> is defined as

                               n
                              ====
                           1  \      k
                           -   >    x
                           n  /      i
                              ====
                              i = 1

     The weighted noncentral moment of order <k> is defined as

                               n
                              ====
                           1  \         k
                           -   >    w  x
                           Z  /      i  i
                              ====
                              i = 1

     where <Z> is the sum of the weights,

                             n
                            ====
                            \
                       Z =   >    w
                            /      i
                            ====
                            i = 1

     Examples:

     First noncentral moment of a list.  The first noncentral moment is
     equal to the sample mean.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) noncentral_moment (s1, 1), numer;
          (%o3)                         4.71
          (%i4) mean (s1), numer;
          (%o4)                         4.71

     Fifth noncentral moment of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) noncentral_moment (s2, 5);
          (%o3) [319793.87247615046, 320532.19238924625,
                 391249.56213815557, 2502278.205988911, 1691881.7977422548]

     See also function ‘central_moment’.

 -- Function: central_moment
          central_moment (<x>, <k>)
          central_moment (<x>, <k>, <w>)

     Returns the central moment of order <k>.  <x> must be a list or
     matrix.

     When <x> is a list, ‘central_moment’ returns the central moment of
     order <k> of <x>.

     When <x> is a matrix, ‘central_moment’ returns a list comprising
     the central moment of order <k> of each column.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <x[i]> is given equal weight, or a list of
     the same length as <x>, in which case the weight for <x[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     The unweighted central moment of order <k> is defined as

                            n
                           ====
                        1  \          _ k
                        -   >    (x - x)
                        n  /       i
                           ====
                           i = 1

     The weighted central moment of order <k> is defined as

                            n
                           ====
                        1  \             _ k
                        -   >    w  (x - x)
                        Z  /      i   i
                           ====
                           i = 1

     where <Z> is the sum of the weights,

                             n
                            ====
                            \
                       Z =   >    w
                            /      i
                            ====
                            i = 1

     Examples:

     Second central moment of a list.  The second central moment is
     equal to the sample variance.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) central_moment (s1, 2), numer;
          (%o3)                   8.425899999999999
          (%i4) var (s1), numer;
          (%o4)                   8.425899999999999

     Third central moment of each column of a matrix.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) central_moment (s1, 2), numer; /* the variance */
          (%o3)                   8.425899999999999
          (%i5) s2 : read_matrix (file_search ("wind.data"))$
          (%i6) central_moment (s2, 3);
          (%o6) [11.29584771375004, 16.97988248298583, 5.626661952750102,
                                       37.5986572057918, 25.85981904394192]

     See also functions ‘central_moment’ and ‘mean’.

 -- Function: cv
          cv (<list>)
          cv (<matrix>)

     Returns the variation coefficient, defined as the sample standard
     deviation ‘std’ divided by the ‘mean’.

     Examples:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) cv (s1), numer;
          (%o3)                  0.6162930116383044
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) cv (s2);
          (%o5) [0.4171411291632767, 0.38101703748061055,
                0.3619561372346568, 0.3609199356430116, 0.3329249251309538]

     See also functions ‘std’ and ‘mean’.

 -- Function: smin
          smin (<list>)
          smin (<matrix>)

     This is the minimum value of the sample <list>.  When the argument
     is a matrix, ‘smin’ returns a list containing the minimum values of
     the columns, which are associated to statistical variables.

     Examples:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) smin (s1);
          (%o3)                           0
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) smin (s2);
          (%o5)             [0.58, 0.5, 2.67, 5.25, 5.17]

     See also function ‘smax’.

 -- Function: smax
          smax (<list>)
          smax (<matrix>)

     This is the maximum value of the sample <list>.  When the argument
     is a matrix, ‘smax’ returns a list containing the maximum values of
     the columns, which are associated to statistical variables.

     Examples:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) smax (s1);
          (%o3)                           9
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) smax (s2);
          (%o5)          [20.25, 21.46, 20.04, 29.63, 27.63]

     See also function ‘smin’.

 -- Function: range
          range (<list>)
          range (<matrix>)

     The range is the difference between the extreme values.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) range (s1);
          (%o3)                           9
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) range (s2);
          (%o5)   [19.67, 20.96, 17.369999999999997, 24.38, 22.46]

 -- Function: quantile
          quantile (<list>, <p>)
          quantile (<matrix>, <p>)

     This is the <p>-quantile, with <p> a number in [0, 1], of the
     sample <list>.  Although there are several definitions for the
     sample quantile (Hyndman, R. J., Fan, Y. (1996) <Sample quantiles
     in statistical packages>.  American Statistician, 50, 361-365), the
     one based on linear interpolation is implemented in package *note
     Package descriptive::

     Examples:

     Input is a list.  First and third quartiles are computed.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) [quantile (s1, 1/4), quantile (s1, 3/4)], numer;
          (%o3)                      [2.0, 7.25]

     Input is a matrix.  First quartile is computed for each column.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) quantile (s2, 1/4);
          (%o3)    [7.2575, 7.477500000000001, 7.82, 11.28, 11.48]

 -- Function: median
          median (<list>)
          median (<matrix>)

     Once the sample is ordered, if the sample size is odd the median is
     the central value, otherwise it is the mean of the two central
     values.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) median (s1);
                                          9
          (%o3)                           -
                                          2
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) median (s2);
          (%o5)   [10.059999999999999, 9.855, 10.73, 15.48, 14.105]

     The median is the 1/2-quantile.

     See also function ‘quantile’.

 -- Function: qrange
          qrange (<x>)

     Returns the interquartile range, defined as the difference between
     the third and first quartiles: ‘quantile(<x>, 3/4) - quantile(<x>,
     1/4)’

     <x> must be a list or matrix.  When <x> is a matrix, ‘qrange’
     returns the interquartile range for each column.

     Examples:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) qrange (s1);
                                         21
          (%o3)                          --
                                         4
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) qrange (s2);
          (%o5) [5.385, 5.572499999999998, 6.022500000000001,
                                      8.729999999999999, 6.649999999999999]

     See also function ‘quantile’.

 -- Function: mean_deviation
          mean_deviation (<list>)
          mean_deviation (<matrix>)

     The mean deviation, defined as
                               n
                             ====
                         1   \          _
                         -    >    |x - x|
                         n   /       i
                             ====
                             i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) mean_deviation (s1);
                                         51
          (%o3)                          --
                                         20
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) mean_deviation (s2);
          (%o5) [3.2879599999999987, 3.075342, 3.2390700000000003,
                                      4.715664000000001, 4.028546000000002]

     See also function ‘mean’.

 -- Function: median_deviation
          median_deviation (<list>)
          median_deviation (<matrix>)

     The median deviation, defined as
                           n
                         ====
                     1   \
                     -    >    |x - med|
                     n   /       i
                         ====
                         i = 1
     where ‘med’ is the median of <list>.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) median_deviation (s1);
                                          5
          (%o3)                           -
                                          2
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) median_deviation (s2);
          (%o5) [2.75, 2.7550000000000003, 3.08, 4.315, 3.3099999999999996]

     See also function ‘mean’.

 -- Function: harmonic_mean
          harmonic_mean (<list>)
          harmonic_mean (<matrix>)

     The harmonic mean, defined as
                            n
                         --------
                          n
                         ====
                         \     1
                          >    --
                         /     x
                         ====   i
                         i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) y : [5, 7, 2, 5, 9, 5, 6, 4, 9, 2, 4, 2, 5]$
          (%i3) harmonic_mean (y), numer;
          (%o3)                  3.9018580276322052
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) harmonic_mean (s2);
          (%o5) [6.948015590052786, 7.391967752360356, 9.055658197151745,
                                     13.441990281936924, 13.01439145898509]

     See also functions ‘mean’ and ‘geometric_mean’.

 -- Function: geometric_mean
          geometric_mean (<list>)
          geometric_mean (<matrix>)

     The geometric mean, defined as
                           /  n      \ 1/n
                           | /===\   |
                           |  ! !    |
                           |  ! !  x |
                           |  ! !   i|
                           | i = 1   |
                           \         /

     Example:

          (%i1) load ("descriptive")$
          (%i2) y : [5, 7, 2, 5, 9, 5, 6, 4, 9, 2, 4, 2, 5]$
          (%i3) geometric_mean (y), numer;
          (%o3)                   4.454845412337012
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) geometric_mean (s2);
          (%o5) [8.82476274347979, 9.22652604739361, 10.044267571488904,
                                     14.612741263490207, 13.96184163444275]

     See also functions ‘mean’ and ‘harmonic_mean’.

 -- Function: kurtosis
          kurtosis (<list>)
          kurtosis (<matrix>)

     The kurtosis coefficient, defined as
                              n
                            ====
                      1     \          _ 4
                     ----    >    (x - x)  - 3
                        4   /       i
                     n s    ====
                            i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) kurtosis (s1), numer;
          (%o3)                  - 1.273247946514421
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) kurtosis (s2);
          (%o5) [- 0.2715445622195385, 0.119998784429451,
          - 0.42752334904828615, - 0.6405361979019522,
          - 0.4952382132352935]

     See also functions ‘mean’, ‘var’ and ‘skewness’.

 -- Function: skewness
          skewness (<list>)
          skewness (<matrix>)

     The skewness coefficient, defined as
                              n
                            ====
                      1     \          _ 3
                     ----    >    (x - x)
                        3   /       i
                     n s    ====
                            i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) skewness (s1), numer;
          (%o3)                 0.009196180476450424
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) skewness (s2);
          (%o5) [0.1580509020000978, 0.2926379232061854,
             0.09242174416107717, 0.20599843481486865, 0.21425202488908313]

     See also functions ‘mean’,, ‘var’ and ‘kurtosis’.

 -- Function: pearson_skewness
          pearson_skewness (<list>)
          pearson_skewness (<matrix>)

     Pearson's skewness coefficient, defined as
                          _
                       3 (x - med)
                       -----------
                            s
     where <med> is the median of <list>.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) pearson_skewness (s1), numer;
          (%o3)                  0.21594840290938955
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) pearson_skewness (s2);
          (%o5) [- 0.08019976629211892, 0.2357036272952649,
             0.10509040624912039, 0.12450423405923679, 0.44641817958045193]

     See also functions ‘mean’, ‘var’ and ‘median’.

 -- Function: quartile_skewness
          quartile_skewness (<list>)
          quartile_skewness (<matrix>)

     The quartile skewness coefficient, defined as
                         c    - 2 c    + c
                          3/4      1/2    1/4
                         --------------------
                             c    - c
                              3/4    1/4
     where c_p is the <p>-quantile of sample <list>.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) quartile_skewness (s1), numer;
          (%o3)                 0.047619047619047616
          (%i4) s2 : read_matrix (file_search ("wind.data"))$
          (%i5) quartile_skewness (s2);
          (%o5) [- 0.040854224698235304, 0.14670255720053824,
             0.033623910336239196, 0.03780068728522298, 0.2105263157894735]

     See also function ‘quantile’.

 -- Function: km
          km (<list>, <option> ...)
          km (<matrix>, <option> ...)

     Kaplan Meier estimator of the survival, or reliability, function
     S(x)=1-F(x).

     Data can be introduced as a list of pairs, or as a two column
     matrix.  The first component is the observed time, and the second
     component a censoring index (1 = non censored, 0 = right censored).

     The optional argument is the name of the variable in the returned
     expression, which is <x> by default.

     Examples:

     Sample as a list of pairs.

          (%i1) load ("descriptive")$
          (%i2) S: km([[2,1], [3,1], [5,0], [8,1]]);
                                 charfun((3 <= x) and (x < 8))
          (%o2) charfun(x < 0) + -----------------------------
                                               2
             3 charfun((2 <= x) and (x < 3))
           + -------------------------------
                            4
           + charfun((0 <= x) and (x < 2))
          (%i3) load ("draw")$
          (%i4) draw2d(
            line_width = 3, grid = true,
            explicit(S, x, -0.1, 10))$

     Estimate survival probabilities.

          (%i1) load ("descriptive")$
          (%i2) S(t):= ''(km([[2,1], [3,1], [5,0], [8,1]], t)) $
          (%i3) S(6);
                                          1
          (%o3)                           -
                                          2

 -- Function: cdf_empirical
          cdf_empirical (<list>, <option> ...)
          cdf_empirical (<matrix>, <option> ...)

     Empirical distribution function F(x).

     Data can be introduced as a list of numbers, or as an one column
     matrix.

     The optional argument is the name of the variable in the returned
     expression, which is <x> by default.

     Example:

     Empirical distribution function.

          (%i1) load ("descriptive")$
          (%i2) F(x):= ''(cdf_empirical([1,3,3,5,7,7,7,8,9]));
          (%o2) F(x) := (charfun(x >= 9) + charfun(x >= 8)
           + 3 charfun(x >= 7) + charfun(x >= 5) + 2 charfun(x >= 3)
           + charfun(x >= 1))/9
          (%i3) F(6);
                                          4
          (%o3)                           -
                                          9
          (%i4) load("draw")$
          (%i5) draw2d(
             line_width = 3,
             grid       = true,
             explicit(F(z), z, -2, 12)) $

 -- Function: cov
          cov (<X>)
          cov (<X>, <w>)

     Returns the sample covariance matrix.  <X> must be a matrix.

     The sample covariance matrix has the same number of rows and
     columns, both equal to the number of columns of <X>; each diagonal
     element <X[i, i]> is equal to the sample variance of the <i>'th
     column, and each off-diagonal element <X[i, j]> is equal to the
     sample covariance of the <i>'th and <j>'th columns.

     <w> is an optional per-datum weight.  <w> must either be 1, in
     which case every datum <X[i]> is given equal weight, or a list of
     the same length as <X>, in which case the weight for <X[i]> is
     given by <w[i]>.  The elements of <w> must be nonnegative and not
     all zero; it is not required that they sum to 1.

     The unweighted sample covariance is defined as

                        n
                       ====
                    1  \           _        _
                S = -   >    (X  - X) (X  - X)'
                    n  /       j        j
                       ====
                       j = 1

     where <X[j]> is the <j>'th row of the sample matrix.

     The weighted sample covariance is defined as

                        n
                       ====
                    1  \           _        _
                S = -   >    w  (X  - X) (X  - X)'
                    Z  /      j   j        j
                       ====
                       j = 1

     where <Z> is the sum of the weights,

                             n
                            ====
                            \
                       Z =   >    w
                            /      i
                            ====
                            i = 1

     Example:

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) fpprintprec : 7$
          (%i4) cov (s2);
                [ 17.22191  13.61811  14.37217  19.39624  15.42162 ]
                [                                                  ]
                [ 13.61811  14.98774  13.30448  15.15834  14.9711  ]
                [                                                  ]
          (%o4) [ 14.37217  13.30448  15.47573  17.32544  16.18171 ]
                [                                                  ]
                [ 19.39624  15.15834  17.32544  32.17651  20.44685 ]
                [                                                  ]
                [ 15.42162  14.9711   16.18171  20.44685  24.42308 ]

     See also function ‘cov1’.

 -- Function: cov1 (<matrix>)

     The covariance matrix of the multivariate sample, defined as
                        n
                       ====
                   1   \           _        _
             S  = ---   >    (X  - X) (X  - X)'
              1   n-1  /       j        j
                       ====
                       j = 1
     where X_j is the j-th row of the sample matrix.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) fpprintprec : 7$
          (%i4) cov1 (s2);
                [ 17.39587  13.75567  14.51734  19.59216  15.5774  ]
                [                                                  ]
                [ 13.75567  15.13913  13.43887  15.31145  15.12232 ]
                [                                                  ]
          (%o4) [ 14.51734  13.43887  15.63205  17.50044  16.34516 ]
                [                                                  ]
                [ 19.59216  15.31145  17.50044  32.50153  20.65338 ]
                [                                                  ]
                [ 15.5774   15.12232  16.34516  20.65338  24.66977 ]

     See also function ‘cov’.

 -- Function: global_variances
          global_variances (<matrix>)
          global_variances (<matrix>, <options> ...)

     Function ‘global_variances’ returns a list of global variance
     measures:

        • <total variance>: ‘trace(S_1)’,
        • <mean variance>: ‘trace(S_1)/p’,
        • <generalized variance>: ‘determinant(S_1)’,
        • <generalized standard deviation>: ‘sqrt(determinant(S_1))’,
        • <effective variance> ‘determinant(S_1)^(1/p)’, (defined in:
          Peña, D. (2002) <Análisis de datos multivariantes>;
          McGraw-Hill, Madrid.)
        • <effective standard deviation>: ‘determinant(S_1)^(1/(2*p))’.
     where <p> is the dimension of the multivariate random variable and
     S_1 the covariance matrix returned by ‘cov1’.

     Option:

        • ‘'data’, default ‘'true’, indicates whether the input matrix
          contains the sample data, in which case the covariance matrix
          ‘cov1’ must be calculated, or not, and then the covariance
          matrix (symmetric) must be given, instead of the data.

     Examples:

     Calculate the ‘global_variances’ from sample data.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) global_variances (s2);
          (%o3) [105.33834206060595, 21.06766841212119, 12874.34690469686,
                 113.46517926085015, 6.636590811800794, 2.5761581496097623]

     Calculate the ‘global_variances’ from the covariance matrix.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) s : cov1 (s2)$
          (%i4) global_variances (s, data=false);
          (%o4) [105.33834206060595, 21.06766841212119, 12874.34690469686,
                 113.46517926085015, 6.636590811800794, 2.5761581496097623]

     See also ‘cov’ and ‘cov1’.

 -- Function: cor
          cor (<matrix>)
          cor (<matrix>, <logical_value>)

     The correlation matrix of the multivariate sample.

     Option:

        • ‘'data’, default ‘'true’, indicates whether the input matrix
          contains the sample data, in which case the covariance matrix
          ‘cov1’ must be calculated, or not, and then the covariance
          matrix (symmetric) must be given, instead of the data.

     Examples:

          (%i1) load ("descriptive")$
          (%i2) fpprintprec : 7 $
          (%i3) s2 : read_matrix (file_search ("wind.data"))$
          (%i4) cor (s2);
                [    1.0     0.8476339  0.8803515  0.8239624  0.7519506 ]
                [                                                       ]
                [ 0.8476339     1.0     0.8735834  0.6902622  0.782502  ]
                [                                                       ]
          (%o4) [ 0.8803515  0.8735834     1.0     0.7764065  0.8323358 ]
                [                                                       ]
                [ 0.8239624  0.6902622  0.7764065     1.0     0.7293848 ]
                [                                                       ]
                [ 0.7519506  0.782502   0.8323358  0.7293848     1.0    ]

     Calculate the correlation matrix from the covariance matrix.

          (%i1) load ("descriptive")$
          (%i2) fpprintprec : 7 $
          (%i3) s2 : read_matrix (file_search ("wind.data"))$
          (%i4) s : cov1 (s2)$
          (%i5) cor (s, data=false); /* this is faster */
                [    1.0     0.8476339  0.8803515  0.8239624  0.7519506 ]
                [                                                       ]
                [ 0.8476339     1.0     0.8735834  0.6902622  0.782502  ]
                [                                                       ]
          (%o5) [ 0.8803515  0.8735834     1.0     0.7764065  0.8323358 ]
                [                                                       ]
                [ 0.8239624  0.6902622  0.7764065     1.0     0.7293848 ]
                [                                                       ]
                [ 0.7519506  0.782502   0.8323358  0.7293848     1.0    ]

     See also ‘cov’ and ‘cov1’.

 -- Function: list_correlations
          list_correlations (<matrix>)
          list_correlations (<matrix>, <options> ...)

     Function ‘list_correlations’ returns a list of correlation
     measures:

        • <precision matrix>: the inverse of the covariance matrix S_1,
                      -1     ij
                     S   = (s  )
                      1         i,j = 1,2,...,p

        • <multiple correlation vector>: (R_1^2, R_2^2, ..., R_p^2),
          with
                      2          1
                     R  = 1 - -------
                      i        ii
                              s   s
                                   ii
          being an indicator of the goodness of fit of the linear
          multivariate regression model on X_i when the rest of
          variables are used as regressors.

        • <partial correlation matrix>: with element (i, j) being
                                        ij
                                       s
                     r        = - ------------
                      ij.rest     / ii  jj\ 1/2
                                  |s   s  |
                                  \       /

     Option:

        • ‘'data’, default ‘'true’, indicates whether the input matrix
          contains the sample data, in which case the covariance matrix
          ‘cov1’ must be calculated, or not, and then the covariance
          matrix (symmetric) must be given, instead of the data.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) z : list_correlations (s2)$
          (%i4) fpprintprec : 5$
          (%i5) precision_matrix: z[1];
          (%o5)
              [  0.38486   - 0.13856   - 0.15626   - 0.10239    0.031179  ]
              [                                                           ]
              [ - 0.13856   0.34107    - 0.15233    0.038447   - 0.052842 ]
              [                                                           ]
              [ - 0.15626  - 0.15233    0.47296    - 0.024816  - 0.10054  ]
              [                                                           ]
              [ - 0.10239   0.038447   - 0.024816   0.10937    - 0.034033 ]
              [                                                           ]
              [ 0.031179   - 0.052842  - 0.10054   - 0.034033   0.14834   ]
          (%i6) multiple_correlation_vector: z[2];
          (%o6)     [0.85063, 0.80634, 0.86474, 0.71867, 0.72675]
          (%i7) partial_correlation_matrix: z[3];
                [   - 1.0     0.38244   0.36627   0.49908   - 0.13049 ]
                [                                                     ]
                [  0.38244     - 1.0    0.37927  - 0.19907   0.23492  ]
                [                                                     ]
          (%o7) [  0.36627    0.37927    - 1.0    0.10911    0.37956  ]
                [                                                     ]
                [  0.49908   - 0.19907  0.10911    - 1.0     0.26719  ]
                [                                                     ]
                [ - 0.13049   0.23492   0.37956   0.26719     - 1.0   ]

     See also ‘cov’ and ‘cov1’.

 -- Function: principal_components
          principal_components (<matrix>)
          principal_components (<matrix>, <options> ...)

     Calculates the principal components of a multivariate sample.
     Principal components are used in multivariate statistical analysis
     to reduce the dimensionality of the sample.

     Option:

        • ‘'data’, default ‘'true’, indicates whether the input matrix
          contains the sample data, in which case the covariance matrix
          ‘cov1’ must be calculated, or not, and then the covariance
          matrix (symmetric) must be given, instead of the data.

     The output of function ‘principal_components’ is a list with the
     following results:

        • variances of the principal components,
        • percentage of total variance explained by each principal
          component,
        • rotation matrix.

     Examples:

     In this sample, the first component explains 83.13 per cent of
     total variance.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) fpprintprec:4 $
          (%i4) res: principal_components(s2);
          0 errors, 0 warnings
          (%o4) [[87.57, 8.753, 5.515, 1.889, 1.613],
          [83.13, 8.31, 5.235, 1.793, 1.531],
          [ .4149  .03379   - .4757  - 0.581   - .5126 ]
          [                                            ]
          [ 0.369  - .3657  - .4298   .7237    - .1469 ]
          [                                            ]
          [ .3959  - .2178  - .2181  - .2749    .8201  ]]
          [                                            ]
          [ .5548   .7744    .1857    .2319    .06498  ]
          [                                            ]
          [ .4765  - .4669   0.712   - .09605  - .1969 ]
          (%i5) /* accumulated percentages  */
              block([ap: copy(res[2])],
                for k:2 thru length(ap) do ap[k]: ap[k]+ap[k-1],
                ap);
          (%o5)                 [83.13, 91.44, 96.68, 98.47, 100.0]
          (%i6) /* sample dimension */
                p: length(first(res));
          (%o6)                                  5
          (%i7) /* plot percentages to select number of
                   principal components for further work */
               draw2d(
                  fill_density = 0.2,
                  apply(bars, makelist([k, res[2][k], 1/2], k, p)),
                  points_joined = true,
                  point_type    = filled_circle,
                  point_size    = 3,
                  points(makelist([k, res[2][k]], k, p)),
                  xlabel = "Variances",
                  ylabel = "Percentages",
                  xtics  = setify(makelist([concat("PC",k),k], k, p))) $

     In case the covariance matrix is known, it can be passed to the
     function, but option ‘data=false’ must be used.

          (%i1) load ("descriptive")$
          (%i2) S: matrix([1,-2,0],[-2,5,0],[0,0,2]);
                                          [  1   - 2  0 ]
                                          [             ]
          (%o2)                           [ - 2   5   0 ]
                                          [             ]
                                          [  0    0   2 ]
          (%i3) fpprintprec:4 $
          (%i4) /* the argument is a covariance matrix */
                res: principal_components(S, data=false);
          0 errors, 0 warnings
                                                            [ - .3827  0.0  .9239 ]
                                                            [                     ]
          (%o4) [[5.828, 2.0, .1716], [72.86, 25.0, 2.145], [  .9239   0.0  .3827 ]]
                                                            [                     ]
                                                            [   0.0    1.0   0.0  ]
          (%i5) /* transformation to get the principal components
                   from original records */
                matrix([a1,b2,c3],[a2,b2,c2]).last(res);
                       [ .9239 b2 - .3827 a1  1.0 c3  .3827 b2 + .9239 a1 ]
          (%o5)        [                                                  ]
                       [ .9239 b2 - .3827 a2  1.0 c2  .3827 b2 + .9239 a2 ]


File: maxima.info,  Node: Functions and Variables for statistical graphs,  Prev: Functions and Variables for descriptive statistics,  Up: Package descriptive

51.4 Functions and Variables for statistical graphs
===================================================

 -- Function: barsplot (<data1>, <data2>, ..., <option_1>, <option_2>,
          ...)

     Plots bars diagrams for discrete statistical variables, both for
     one or multiple samples.

     <data> can be a list of outcomes representing one sample, or a
     matrix of <m> rows and <n> columns, representing <n> samples of
     size <m> each.

     Available options are:

        • <box_width> (default, ‘3/4’): relative width of rectangles.
          This value must be in the range ‘[0,1]’.

        • <grouping> (default, ‘clustered’): indicates how multiple
          samples are shown.  Valid values are: ‘clustered’ and
          ‘stacked’.

        • <groups_gap> (default, ‘1’): a positive integer number
          representing the gap between two consecutive groups of bars.

        • <bars_colors> (default, ‘[]’): a list of colors for multiple
          samples.  When there are more samples than specified colors,
          the extra necessary colors are chosen at random.  See ‘color’
          to learn more about them.

        • <frequency> (default, ‘absolute’): indicates the scale of the
          ordinates.  Possible values are: ‘absolute’, ‘relative’, and
          ‘percent’.

        • <ordering> (default, ‘orderlessp’): possible values are
          ‘orderlessp’ or ‘ordergreatp’, indicating how statistical
          outcomes should be ordered on the <x>-axis.

        • <sample_keys> (default, ‘[]’): a list with the strings to be
          used in the legend.  When the list length is other than 0 or
          the number of samples, an error message is returned.

        • <start_at> (default, ‘0’): indicates where the plot begins to
          be plotted on the x axis.

        • All global ‘draw’ options, except ‘xtics’, which is internally
          assigned by ‘barsplot’.  If you want to set your own values
          for this option or want to build complex scenes, make use of
          ‘barsplot_description’.  See example below.

        • The following local *note Package draw:: options: ‘key’,
          ‘color_draw’, ‘fill_color’, ‘fill_density’ and ‘line_width’.
          See also ‘barsplot’.

     There is also a function ‘wxbarsplot’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.  ‘barsplot’ in a
     multiplot context.

     Examples:

     Univariate sample in matrix form.  Absolute frequencies.

          (%i1) load ("descriptive")$
          (%i2) m : read_matrix (file_search ("biomed.data"))$
          (%i3) barsplot(
            col(m,2),
            title        = "Ages",
            xlabel       = "years",
            box_width    = 1/2,
            fill_density = 3/4)$

     Two samples of different sizes, with relative frequencies and user
     declared colors.

          (%i1) load ("descriptive")$
          (%i2) l1:makelist(random(10),k,1,50)$
          (%i3) l2:makelist(random(10),k,1,100)$
          (%i4) barsplot(
             l1,l2,
             box_width = 1,
             fill_density = 1,
             bars_colors = [black, grey],
             frequency = relative,
             sample_keys = ["A", "B"])$

     Four non numeric samples of equal size.

          (%i1) load ("descriptive")$
          (%i2) barsplot(
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            title      = "Asking for something to four groups",
            ylabel     = "# of individuals",
            groups_gap = 3,
            fill_density = 0.5,
            ordering = ordergreatp)$

     Stacked bars.

          (%i1) load ("descriptive")$
          (%i2) barsplot(
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            makelist([Yes, No, Maybe][random(3)+1],k,1,50),
            title      = "Asking for something to four groups",
            ylabel     = "# of individuals",
            grouping   = stacked,
            fill_density = 0.5,
            ordering = ordergreatp)$

     For bars diagrams related options, see ‘barsplot’ of package *note
     Package draw:: See also functions ‘histogram’ and ‘piechart’.

 -- Function: barsplot_description (...)

     Function ‘barsplot_description’ creates a graphic object suitable
     for creating complex scenes, together with other graphic objects.

     Example: ‘barsplot’ in a multiplot context.

          (%i1) load ("descriptive")$
          (%i2) l1:makelist(random(10),k,1,50)$
          (%i3) l2:makelist(random(10),k,1,100)$
          (%i4) bp1 :
                  barsplot_description(
                   l1,
                   box_width = 1,
                   fill_density = 0.5,
                   bars_colors = [blue],
                   frequency = relative)$
          (%i5) bp2 :
                  barsplot_description(
                   l2,
                   box_width = 1,
                   fill_density = 0.5,
                   bars_colors = [red],
                   frequency = relative)$
          (%i6) draw(gr2d(bp1), gr2d(bp2))$

 -- Function: boxplot (<data>)
          boxplot (<data>, <option_1>, <option_2>, ...)

     This function plots box-and-whisker diagrams.  Argument <data> can
     be a list, which is not of great interest, since these diagrams are
     mainly used for comparing different samples, or a matrix, so it is
     possible to compare two or more components of a multivariate
     statistical variable.  But it is also allowed <data> to be a list
     of samples with possible different sample sizes, in fact this is
     the only function in package ‘descriptive’ that admits this type of
     data structure.

     The box is plotted from the first quartile to the third, with an
     horizontal segment situated at the second quartile or median.  By
     default, lower and upper whiskers are plotted at the minimum and
     maximum values, respectively.  Option <range> can be used to
     indicate that values greater than
     ‘quantile(x,3/4)+range*(quantile(x,3/4)-quantile(x,1/4))’ or less
     than ‘quantile(x,1/4)-range*(quantile(x,3/4)-quantile(x,1/4))’ must
     be considered as outliers, in which case they are plotted as
     isolated points, and the whiskers are located at the extremes of
     the rest of the sample.

     Available options are:

        • <box_width> (default, ‘3/4’): relative width of boxes.  This
          value must be in the range ‘[0,1]’.

        • <box_orientation> (default, ‘vertical’): possible values:
          ‘vertical’ and ‘horizontal’.

        • <range> (default, ‘inf’): positive coefficient of the
          interquartilic range to set outliers boundaries.

        • <outliers_size> (default, ‘1’): circle size for isolated
          outliers.

        • All ‘draw’ options, except ‘points_joined’, ‘point_size’,
          ‘point_type’, ‘xtics’, ‘ytics’, ‘xrange’, and ‘yrange’, which
          are internally assigned by ‘boxplot’.  If you want to set your
          own values for this options or want to build complex scenes,
          make use of ‘boxplot_description’.

        • The following local ‘draw’ options: ‘key’, ‘color’, and
          ‘line_width’.

     There is also a function ‘wxboxplot’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.

     Examples:

     Box-and-whisker diagram from a multivariate sample.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix(file_search("wind.data"))$
          (%i3) boxplot(s2,
            box_width  = 0.2,
            title      = "Windspeed in knots",
            xlabel     = "Stations",
            color      = red,
            line_width = 2)$

     Box-and-whisker diagram from three samples of different sizes.

          (%i1) load ("descriptive")$
          (%i2) A :
           [[6, 4, 6, 2, 4, 8, 6, 4, 6, 4, 3, 2],
            [8, 10, 7, 9, 12, 8, 10],
            [16, 13, 17, 12, 11, 18, 13, 18, 14, 12]]$
          (%i3) boxplot (A, box_orientation = horizontal)$

     Option <range> can be used to handle outliers.

          (%i1)  load ("descriptive")$
           B: [[7, 15, 5, 8, 6, 5, 7, 3, 1],
               [10, 8, 12, 8, 11, 9, 20],
               [23, 17, 19, 7, 22, 19]] $
           boxplot (B, range=1)$
           boxplot (B, range=1.5, box_orientation = horizontal)$
           draw2d(
              boxplot_description(
                 B,
                 range            = 1.5,
                 line_width       = 3,
                 outliers_size    = 2,
                 color            = red,
                 background_color = light_gray),
              xtics = {["Low",1],["Medium",2],["High",3]}) $

 -- Function: boxplot_description (...)

     Function ‘boxplot_description’ creates a graphic object suitable
     for creating complex scenes, together with other graphic objects.

 -- Function: histogram
          histogram (<list>)
          histogram (<list>, <option_1>, <option_2>, ...)
          histogram (<one_column_matrix>)
          histogram (<one_column_matrix>, <option_1>, <option_2>, ...)
          histogram (<one_row_matrix>)
          histogram (<one_row_matrix>, <option_1>, <option_2>, ...)

     Constructs and displays a histogram from a data sample.  Data must
     be stored as a list of numbers, or a matrix of one row or one
     column.

     Optional arguments:

        • ‘nclasses’ (default, 10): the number of classes (also called
          bins) in the histogram, or a list of two numbers (the least
          and greatest values included in the histogram), or a list of
          three numbers (the least and greatest values included in the
          histogram, and the number of classes), or a set containing the
          endpoints of the class intervals, or a symbol specifying the
          name of one of three algorithms to automatically determine the
          number of classes: ‘fd’ (Ref.  [1]), ‘scott’ (Ref.  [2]), or
          ‘sturges’ (Ref.  [3]).

          A class interval excludes its left endpoint and includes its
          right endpoint, except for the first interval, which includes
          both the left and right endpoints.  It is assumed that class
          intervals are contiguous.  That is, the right endpoint of one
          interval is equal to the left endpoint of the next.

        • ‘frequency’ (default, ‘absolute’): indicates the scale of the
          vertical axis.  Possible values are: ‘absolute’ (heights of
          bars add up to number of data), ‘relative’ (heights of bars
          add up to 1), ‘percent’ (heights of bars add up to 100), and
          ‘density’ (total area of histogram is 1).

        • ‘htics’ (default, ‘auto’): format of tic marks on the
          horizontal axis.  Possible values are: ‘auto’ (tics are placed
          automatically), ‘endpoints’ (tics are placed at the divisions
          between classes), ‘intervals’ (classes are labeled with the
          corresponding intervals), or a list of labels, one for each
          class.

        • All global ‘draw’ options, except ‘xrange’, ‘yrange’, and
          ‘xtics’, which are internally assigned by ‘histogram’.  If you
          want to set your own values for these options, make use of
          ‘histogram_description’.

        • The following local *note Package draw:: options: ‘key’,
          ‘fill_color’, ‘fill_density’, and ‘line_width’.  Note that the
          outlines of bars, as well as the interior of bars when
          ‘fill_density’ is nonzero, are drawn with ‘fill_color’, not
          ‘color’.

     ‘histogram’ honors the global option ‘histogram_skyline’.  When
     ‘histogram_skyline’ is ‘true’, ‘histogram’ and
     ‘histogram_description’ construct "skyline" plots, which shows the
     outline of the histogram bars, instead of drawing all the vertical
     segments.  Otherwise (the default), histograms are displayed with
     bars showing vertical segments.

     There is also a function ‘wxhistogram’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.

     See also ‘continuous_freq’, which, like ‘histogram’, counts data in
     intervals, but returns the counts instead of displaying a graphic
     representation.

     See also ‘barsplot’.

     Examples:

     A simple histogram with eight classes:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) histogram (
               s1,
               nclasses     = 8,
               title        = "pi digits",
               xlabel       = "digits",
               ylabel       = "Absolute frequency",
               fill_color   = grey,
               fill_density = 0.6)$

     Setting the limits of the histogram to -2 and 12, with 3 classes.
     Also, we introduce predefined tics:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) histogram (
               s1,
               nclasses     = [-2,12,3],
               htics        = ["A", "B", "C"],
               terminal     = png,
               fill_color   = "#23afa0",
               fill_density = 0.6)$

     Bounds for varying class widths.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) histogram (s1, nclasses = {0,3,6,7,11})$

     Freedman-Diaconis formula for the number of classes.

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) histogram(s1, nclasses=fd) $

     References:

     [1] Freedman, D., and Diaconis, P. (1981) On the histogram as a
     density estimator: L_2 theory.  Zeitschrift für
     Wahrscheinlichkeitstheorie und verwandte Gebiete 57, 453-476.

     [2] Scott, D. W. (1979) On optimal and data-based histograms.
     Biometrika 66, 605-610.

     [3] Sturges, H. A. (1926) The choice of a class interval.  Journal
     of the American Statistical Association 21, 65-66.

 -- Function: histogram_description (...)

     Creates a graphic object which represents a histogram.  Such an
     object is suitable for creating complex scenes together with other
     graphic objects, to be displayed by ‘draw2d’.

     ‘histogram_description’ takes the same arguments as the stand-alone
     function ‘histogram’.  See ‘histogram’ for more information.

     Example:

     We make use of ‘histogram_description’ for setting ‘xrange’ and
     adding an explicit curve into the scene:

          (%i1) load ("descriptive")$
          (%i2) ( load("distrib"),
                  m: 14, s: 2,
                  s2: random_normal(m, s, 1000) ) $
          (%i3) draw2d(
                  grid   = true,
                  xrange = [5, 25],
                  histogram_description(
                    s2,
                    nclasses     = 9,
                    frequency    = density,
                    fill_density = 0.5),
                  explicit(pdf_normal(x,m,s), x, m - 3*s, m + 3* s))$

 -- Option variable: histogram_skyline
     Default value: ‘false’

     When ‘histogram_skyline’ is ‘true’, ‘histogram’ and
     ‘histogram_description’ construct "skyline" plots, which shows the
     outline of the histogram bars, instead of drawing all the vertical
     segments.

     The outline is drawn with the current ‘fill_color’ (not the current
     ‘color’).  The interior of the histogram is filled with
     ‘fill_color’, but only if ‘fill_density’ is nonzero.

     Otherwise, histograms are displayed with bars showing vertical
     segments.

     Examples:

     Construct a skyline histogram, and an ordinary histogram for
     comparison, on the same plot.

          (%i1) load ("descriptive") $
          (%i2) L: read_list (file_search ("pidigits.data")) $
          (%i3) histogram_skyline: true $
          (%i4) skyline_hist: histogram_description (L) $
          (%i5) histogram_skyline: false $
          (%i6) ordinary_hist: histogram_description (L) $
          (%i7) draw (gr2d (skyline_hist), gr2d (ordinary_hist)) $

     Continuing the preceding example.  Set display options for
     ‘fill_color’ and ‘fill_density’.

          (%i8) histogram_skyline: true $
          (%i9) skyline_hist: histogram_description (L, fill_color = blue, fill_density = 0.2) $
          (%i10) histogram_skyline: false $
          (%i11) ordinary_hist: histogram_description (L, fill_color = blue, fill_density = 0.2) $
          (%i12) draw (gr2d (skyline_hist), gr2d (ordinary_hist)) $

 -- Function: piechart
          piechart (<list>)
          piechart (<list>, <option_1>, <option_2>, ...)
          piechart (<one_column_matrix>)
          piechart (<one_column_matrix>, <option_1>, <option_2>, ...)
          piechart (<one_row_matrix>)
          piechart (<one_row_matrix>, <option_1>, <option_2>, ...)

     Similar to ‘barsplot’, but plots sectors instead of rectangles.

     Available options are:

        • <sector_colors> (default, ‘[]’): a list of colors for sectors.
          When there are more sectors than specified colors, the extra
          necessary colors are chosen at random.  See ‘color’ to learn
          more about them.

        • <pie_center> (default, ‘[0,0]’): diagram's center.

        • <pie_radius> (default, ‘1’): diagram's radius.

        • All global ‘draw’ options, except ‘key’, which is internally
          assigned by ‘piechart’.  If you want to set your own values
          for this option or want to build complex scenes, make use of
          ‘piechart_description’.

        • The following local ‘draw’ options: ‘key’, ‘color’,
          ‘fill_density’ and ‘line_width’.  See also ‘ellipse’

     There is also a function ‘wxpiechart’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.

     Example:

          (%i1) load ("descriptive")$
          (%i2) s1 : read_list (file_search ("pidigits.data"))$
          (%i3) piechart(
            s1,
            xrange = [-1.1, 1.3],
            yrange = [-1.1, 1.1],
            title  = "Digit frequencies in pi")$

     See also function ‘barsplot’.

 -- Function: piechart_description (...)

     Function ‘piechart_description’ creates a graphic object suitable
     for creating complex scenes, together with other graphic objects.

 -- Function: scatterplot
          scatterplot (<list>)
          scatterplot (<list>, <option_1>, <option_2>, ...)
          scatterplot (<matrix>)
          scatterplot (<matrix>, <option_1>, <option_2>, ...)

     Plots scatter diagrams both for univariate (<list>) and
     multivariate (<matrix>) samples.

     Available options are the same admitted by ‘histogram’.

     There is also a function ‘wxscatterplot’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.

     Examples:

     Univariate scatter diagram from a simulated Gaussian sample.

          (%i1) load ("descriptive")$
          (%i2) load ("distrib")$
          (%i3) scatterplot(
            random_normal(0,1,200),
            xaxis      = true,
            point_size = 2,
            dimensions = [600,150])$

     Two dimensional scatter plot.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) scatterplot(
           submatrix(s2, 1,2,3),
           title      = "Data from stations #4 and #5",
           point_type = diamant,
           point_size = 2,
           color      = blue)$

     Three dimensional scatter plot.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) scatterplot(submatrix (s2, 1,2), nclasses=4)$

     Five dimensional scatter plot, with five classes histograms.

          (%i1) load ("descriptive")$
          (%i2) s2 : read_matrix (file_search ("wind.data"))$
          (%i3) scatterplot(
            s2,
            nclasses     = 5,
            frequency    = relative,
            fill_color   = blue,
            fill_density = 0.3,
            xtics        = 5)$

     For plotting isolated or line-joined points in two and three
     dimensions, see ‘points’.  See also ‘histogram’.

 -- Function: scatterplot_description (...)

     Function ‘scatterplot_description’ creates a graphic object
     suitable for creating complex scenes, together with other graphic
     objects.

 -- Function: starplot (<data1>, <data2>, ..., <option_1>, <option_2>,
          ...)

     Plots star diagrams for discrete statistical variables, both for
     one or multiple samples.

     <data> can be a list of outcomes representing one sample, or a
     matrix of <m> rows and <n> columns, representing <n> samples of
     size <m> each.

     Available options are:

        • <stars_colors> (default, ‘[]’): a list of colors for multiple
          samples.  When there are more samples than specified colors,
          the extra necessary colors are chosen at random.  See ‘color’
          to learn more about them.

        • <frequency> (default, ‘absolute’): indicates the scale of the
          radii.  Possible values are: ‘absolute’ and ‘relative’.

        • <ordering> (default, ‘orderlessp’): possible values are
          ‘orderlessp’ or ‘ordergreatp’, indicating how statistical
          outcomes should be ordered.

        • <sample_keys> (default, ‘[]’): a list with the strings to be
          used in the legend.  When the list length is other than 0 or
          the number of samples, an error message is returned.

        • <star_center> (default, ‘[0,0]’): diagram's center.

        • <star_radius> (default, ‘1’): diagram's radius.

        • All global ‘draw’ options, except ‘points_joined’,
          ‘point_type’, and ‘key’, which are internally assigned by
          ‘starplot’.  If you want to set your own values for this
          options or want to build complex scenes, make use of
          ‘starplot_description’.

        • The following local ‘draw’ option: ‘line_width’.

     There is also a function ‘wxstarplot’ for creating embedded
     histograms in interfaces wxMaxima and iMaxima.

     Example:

     Plot based on absolute frequencies.  Location and radius defined by
     the user.

          (%i1) load ("descriptive")$
          (%i2) l1: makelist(random(10),k,1,50)$
          (%i3) l2: makelist(random(10),k,1,200)$
          (%i4) starplot(
                  l1, l2,
                  stars_colors = [blue,red],
                  sample_keys = ["1st sample", "2nd sample"],
                  star_center = [1,2],
                  star_radius = 4,
                  proportional_axes = xy,
                  line_width = 2 ) $

 -- Function: starplot_description (...)

     Function ‘starplot_description’ creates a graphic object suitable
     for creating complex scenes, together with other graphic objects.

 -- Function: stemplot
          stemplot (<data>)
          stemplot (<data>, <option>)

     Plots stem and leaf diagrams.

     The only available option is:

        • <leaf_unit> (default, ‘1’): indicates the unit of the leaves;
          must be a power of 10.

     Example:

          (%i1) load ("descriptive")$
          (%i2) load("distrib")$
          (%i3) stemplot(
                  random_normal(15, 6, 100),
                  leaf_unit = 0.1);
          -5|4
           0|37
           1|7
           3|6
           4|4
           5|4
           6|57
           7|0149
           8|3
           9|1334588
          10|07888
          11|01144467789
          12|12566889
          13|24778
          14|047
          15|223458
          16|4
          17|11557
          18|000247
          19|4467799
          20|00
          21|1
          22|2335
          23|01457
          24|12356
          25|455
          27|79
          key: 6|3 =  6.3
          (%o3)                  done


File: maxima.info,  Node: Package diag,  Next: Package distrib,  Prev: Package descriptive,  Up: Top

52 Package diag
***************

* Menu:

* Functions and Variables for diag::


File: maxima.info,  Node: Functions and Variables for diag,  Prev: Package diag,  Up: Package diag

52.1 Functions and Variables for diag
=====================================

 -- Function: diag (<lm>)
     Constructs a matrix that is the block sum of the elements of <lm>.
     The elements of <lm> are assumed to be matrices; if an element is
     scalar, it treated as a 1 by 1 matrix.

     The resulting matrix will be square if each of the elements of <lm>
     is square.

     Example:
          (%i1) load("diag")$

          (%i2) a1:matrix([1,2,3],[0,4,5],[0,0,6])$

          (%i3) a2:matrix([1,1],[1,0])$

          (%i4) diag([a1,x,a2]);
                             [ 1  2  3  0  0  0 ]
                             [                  ]
                             [ 0  4  5  0  0  0 ]
                             [                  ]
                             [ 0  0  6  0  0  0 ]
          (%o4)              [                  ]
                             [ 0  0  0  x  0  0 ]
                             [                  ]
                             [ 0  0  0  0  1  1 ]
                             [                  ]
                             [ 0  0  0  0  1  0 ]
          (%i5) diag ([matrix([1,2]), 3]);
                                  [ 1  2  0 ]
          (%o5)                   [         ]
                                  [ 0  0  3 ]

     To use this function write first ‘load("diag")’.

 -- Function: JF (<lambda>,<n>)
     Returns the Jordan cell of order <n> with eigenvalue <lambda>.

     Example:
          (%i1) load("diag")$

          (%i2) JF(2,5);
                              [ 2  1  0  0  0 ]
                              [               ]
                              [ 0  2  1  0  0 ]
                              [               ]
          (%o2)               [ 0  0  2  1  0 ]
                              [               ]
                              [ 0  0  0  2  1 ]
                              [               ]
                              [ 0  0  0  0  2 ]
          (%i3) JF(3,2);
                                   [ 3  1 ]
          (%o3)                    [      ]
                                   [ 0  3 ]

     To use this function write first ‘load("diag")’.

 -- Function: jordan (<mat>)
     Returns the Jordan form of matrix <mat>, encoded as a list in a
     particular format.  To get the corresponding matrix, call the
     function ‘dispJordan’ using the output of ‘jordan’ as the argument.

     The elements of the returned list are themselves lists.  The first
     element of each is an eigenvalue of <mat>.  The remaining elements
     are positive integers which are the lengths of the Jordan blocks
     for this eigenvalue.  These integers are listed in decreasing
     order.  Eigenvalues are not repeated.

     The functions ‘dispJordan’, ‘minimalPoly’ and ‘ModeMatrix’ expect
     the output of a call to ‘jordan’ as an argument.  If you construct
     this argument by hand, rather than by calling ‘jordan’, you must
     ensure that each eigenvalue only appears once and that the block
     sizes are listed in decreasing order, otherwise the functions might
     give incorrect answers.

     Example:
          (%i1) load("diag")$
          (%i2) A: matrix([2,0,0,0,0,0,0,0],
                          [1,2,0,0,0,0,0,0],
                          [-4,1,2,0,0,0,0,0],
                          [2,0,0,2,0,0,0,0],
                          [-7,2,0,0,2,0,0,0],
                          [9,0,-2,0,1,2,0,0],
                          [-34,7,1,-2,-1,1,2,0],
                          [145,-17,-16,3,9,-2,0,3])$
          (%i3) jordan (A);
          (%o3)                [[2, 3, 3, 1], [3, 1]]
          (%i4) dispJordan (%);
                             [ 2  1  0  0  0  0  0  0 ]
                             [                        ]
                             [ 0  2  1  0  0  0  0  0 ]
                             [                        ]
                             [ 0  0  2  0  0  0  0  0 ]
                             [                        ]
                             [ 0  0  0  2  1  0  0  0 ]
          (%o4)              [                        ]
                             [ 0  0  0  0  2  1  0  0 ]
                             [                        ]
                             [ 0  0  0  0  0  2  0  0 ]
                             [                        ]
                             [ 0  0  0  0  0  0  2  0 ]
                             [                        ]
                             [ 0  0  0  0  0  0  0  3 ]

     To use this function write first ‘load("diag")’.  See also
     ‘dispJordan’ and ‘minimalPoly’.

 -- Function: dispJordan (<l>)
     Returns a matrix in Jordan canonical form (JCF) corresponding to
     the list of eigenvalues and multiplicities given by <l>.  This list
     should be in the format given by the ‘jordan’ function.  See
     ‘jordan’ for details of this format.

     Example:
          (%i1) load("diag")$

          (%i2) b1:matrix([0,0,1,1,1],
                          [0,0,0,1,1],
                          [0,0,0,0,1],
                          [0,0,0,0,0],
                          [0,0,0,0,0])$

          (%i3) jordan(b1);
          (%o3)                  [[0, 3, 2]]
          (%i4) dispJordan(%);
                              [ 0  1  0  0  0 ]
                              [               ]
                              [ 0  0  1  0  0 ]
                              [               ]
          (%o4)               [ 0  0  0  0  0 ]
                              [               ]
                              [ 0  0  0  0  1 ]
                              [               ]
                              [ 0  0  0  0  0 ]

     To use this function write first ‘load("diag")’.  See also ‘jordan’
     and ‘minimalPoly’.

 -- Function: minimalPoly (<l>)
     Returns the minimal polynomial of the matrix whose Jordan form is
     described by the list <l>.  This list should be in the format given
     by the ‘jordan’ function.  See ‘jordan’ for details of this format.

     Example:
          (%i1) load("diag")$

          (%i2) a:matrix([2,1,2,0],
                         [-2,2,1,2],
                         [-2,-1,-1,1],
                         [3,1,2,-1])$

          (%i3) jordan(a);
          (%o3)               [[- 1, 1], [1, 3]]
          (%i4) minimalPoly(%);
                                      3
          (%o4)                (x - 1)  (x + 1)

     To use this function write first ‘load("diag")’.  See also ‘jordan’
     and ‘dispJordan’.

 -- Function: ModeMatrix (<A>, [<jordan_info>])
     Returns an invertible matrix <M> such that (M^^-1).A.M is the
     Jordan form of <A>.

     To calculate this, Maxima must find the Jordan form of <A>, which
     might be quite computationally expensive.  If that has already been
     calculated by a previous call to ‘jordan’, pass it as a second
     argument, <jordan_info>.  See ‘jordan’ for details of the required
     format.

     Example:
          (%i1) load("diag")$
          (%i2) A: matrix([2,1,2,0], [-2,2,1,2], [-2,-1,-1,1], [3,1,2,-1])$
          (%i3) M: ModeMatrix (A);
                                [  1    - 1   1   1 ]
                                [                   ]
                                [   1               ]
                                [ - -   - 1   0   0 ]
                                [   9               ]
                                [                   ]
          (%o3)                 [   13              ]
                                [ - --   1   - 1  0 ]
                                [   9               ]
                                [                   ]
                                [  17               ]
                                [  --   - 1   1   1 ]
                                [  9                ]
          (%i4) is ((M^^-1) . A . M = dispJordan (jordan (A)));
          (%o4)                         true

     Note that, in this example, the Jordan form of ‘A’ is computed
     twice.  To avoid this, we could have stored the output of
     ‘jordan(A)’ in a variable and passed that to both ‘ModeMatrix’ and
     ‘dispJordan’.

     To use this function write first ‘load("diag")’.  See also ‘jordan’
     and ‘dispJordan’.

 -- Function: mat_function (<f>,<A>)
     Returns f(A), where <f> is an analytic function and <A> a matrix.
     This computation is based on the Taylor expansion of <f>.  It is
     not efficient for numerical evaluation, but can give symbolic
     answers for small matrices.

     Example 1:

     The exponential of a matrix.  We only give the first row of the
     answer, since the output is rather large.
          (%i1) load("diag")$
          (%i2) A: matrix ([0,1,0], [0,0,1], [-1,-3,-3])$
          (%i3) ratsimp (mat_function (exp, t*A)[1]);
                     2              - t                   2   - t
                   (t  + 2 t + 2) %e       2        - t  t  %e
          (%o3)   [--------------------, (t  + t) %e   , --------]
                            2                               2

     Example 2:

     Comparison with the Taylor series for the exponential and also
     comparing ‘exp(%i*A)’ with sine and cosine.
          (%i1) load("diag")$
          (%i2) A: matrix ([0,1,1,1],
                           [0,0,0,1],
                           [0,0,0,1],
                           [0,0,0,0])$
          (%i3) ratsimp (mat_function (exp, t*A));
                                 [           2     ]
                                 [ 1  t  t  t  + t ]
                                 [                 ]
          (%o3)                  [ 0  1  0    t    ]
                                 [                 ]
                                 [ 0  0  1    t    ]
                                 [                 ]
                                 [ 0  0  0    1    ]
          (%i4) minimalPoly (jordan (A));
                                          3
          (%o4)                          x
          (%i5) ratsimp (ident(4) + t*A + 1/2*(t^2)*A^^2);
                                 [           2     ]
                                 [ 1  t  t  t  + t ]
                                 [                 ]
          (%o5)                  [ 0  1  0    t    ]
                                 [                 ]
                                 [ 0  0  1    t    ]
                                 [                 ]
                                 [ 0  0  0    1    ]
          (%i6) ratsimp (mat_function (exp, %i*t*A));
                            [                        2 ]
                            [ 1  %i t  %i t  %i t - t  ]
                            [                          ]
          (%o6)             [ 0   1     0      %i t    ]
                            [                          ]
                            [ 0   0     1      %i t    ]
                            [                          ]
                            [ 0   0     0        1     ]
          (%i7) ratsimp (mat_function (cos, t*A) + %i*mat_function (sin, t*A));
                            [                        2 ]
                            [ 1  %i t  %i t  %i t - t  ]
                            [                          ]
          (%o7)             [ 0   1     0      %i t    ]
                            [                          ]
                            [ 0   0     1      %i t    ]
                            [                          ]
                            [ 0   0     0        1     ]

     Example 3:

     Power operations.
          (%i1) load("diag")$
          (%i2) A: matrix([1,2,0], [0,1,0], [1,0,1])$
          (%i3) integer_pow(x) := block ([k], declare (k, integer), x^k)$
          (%i4) mat_function (integer_pow, A);
                                 [ 1     2 k     0 ]
                                 [                 ]
          (%o4)                  [ 0      1      0 ]
                                 [                 ]
                                 [ k  (k - 1) k  1 ]
          (%i5) A^^20;
                                   [ 1   40   0 ]
                                   [            ]
          (%o5)                    [ 0    1   0 ]
                                   [            ]
                                   [ 20  380  1 ]

     To use this function write first ‘load("diag")’.


File: maxima.info,  Node: Package distrib,  Next: Package draw,  Prev: Package diag,  Up: Top

53 Package distrib
******************

* Menu:

* Introduction to distrib::
* Functions and Variables for continuous distributions::
* Functions and Variables for discrete distributions::


File: maxima.info,  Node: Introduction to distrib,  Next: Functions and Variables for continuous distributions,  Up: Package distrib

53.1 Introduction to distrib
============================

Package ‘distrib’ contains a set of functions for making probability
computations on both discrete and continuous univariate models.

   What follows is a short reminder of basic probabilistic related
definitions.

   Let f(x) be the <density function> of an absolute continuous random
variable X. The <distribution function> is defined as

                            x
                           /
                           [
                    F(x) = I     f(u) du
                           ]
                           /
                            minf

   which equals the probability Pr(X <= x) .

   The <mean> value is a localization parameter and is defined as

                          inf
                         /
                         [
                E[X]  =  I   x f(x) dx
                         ]
                         /
                          minf

   The <variance> is a measure of variation,

                      inf
                     /
                     [                    2
              V[X] = I     f(x) (x - E[X])  dx
                     ]
                     /
                      minf

   which is a positive real number.  The square root of the variance is
the <standard deviation>, D[X]=sqrt(V[X]) , and it is another measure of
variation.

   The <skewness coefficient> is a measure of non-symmetry,

                      inf
                     /
                 1   [                    3
       SK[X] = ----- I     f(x) (x - E[X])  dx
                   3 ]
               D[X]  /
                      minf

   And the <kurtosis coefficient> measures the peakedness of the
distribution,

                      inf
                     /
                 1   [                    4
       KU[X] = ----- I     f(x) (x - E[X])  dx - 3
                   4 ]
               D[X]  /
                      minf

   If X is gaussian, KU[X]=0.  In fact, both skewness and kurtosis are
shape parameters used to measure the non-gaussianity of a distribution.

   If the random variable X is discrete, the density, or <probability>,
function f(x) takes positive values within certain countable set of
numbers x_i, and zero elsewhere.  In this case, the distribution
function is

                            ====
                            \
                     F(x) =  >    f(x )
                            /        i
                            ====
                           x <= x
                            i

   The mean, variance, standard deviation, skewness coefficient and
kurtosis coefficient take the form

               ====
               \
        E[X] =  >  x  f(x ) ,
               /    i    i
               ====
                x
                 i

                ====
                \                     2
        V[X] =   >    f(x ) (x - E[X])  ,
                /        i    i
                ====
                 x
                  i

               D[X] = sqrt(V[X]),

                          ====
                   1      \                     3
       SK[X] =  -------    >    f(x ) (x - E[X])
                D[X]^3    /        i    i
                          ====
                           x
                            i

                          ====
                   1      \                     4
       KU[X] =  -------    >    f(x ) (x - E[X])   - 3 ,
                D[X]^4    /        i    i
                          ====
                           x
                            i

   respectively.

   There is a naming convention in package ‘distrib’.  Every function
name has two parts, the first one makes reference to the function or
parameter we want to calculate,
     Functions:
        Density function            (pdf_*)
        Distribution function       (cdf_*)
        Quantile                    (quantile_*)
        Mean                        (mean_*)
        Variance                    (var_*)
        Standard deviation          (std_*)
        Skewness coefficient        (skewness_*)
        Kurtosis coefficient        (kurtosis_*)
        Random variate              (random_*)

   The second part is an explicit reference to the probabilistic model,
     Continuous distributions:
        Normal              (*normal)
        Student             (*student_t)
        Chi^2               (*chi2)
        Noncentral Chi^2    (*noncentral_chi2)
        F                   (*f)
        Exponential         (*exp)
        Lognormal           (*lognormal)
        Gamma               (*gamma)
        Beta                (*beta)
        Continuous uniform  (*continuous_uniform)
        Logistic            (*logistic)
        Pareto              (*pareto)
        Weibull             (*weibull)
        Rayleigh            (*rayleigh)
        Laplace             (*laplace)
        Cauchy              (*cauchy)
        Gumbel              (*gumbel)

     Discrete distributions:
        Binomial             (*binomial)
        Poisson              (*poisson)
        Bernoulli            (*bernoulli)
        Geometric            (*geometric)
        Discrete uniform     (*discrete_uniform)
        hypergeometric       (*hypergeometric)
        Negative binomial    (*negative_binomial)
        Finite discrete      (*general_finite_discrete)

   For example, ‘pdf_student_t(x,n)’ is the density function of the
Student distribution with <n> degrees of freedom, ‘std_pareto(a,b)’ is
the standard deviation of the Pareto distribution with parameters <a>
and <b> and ‘kurtosis_poisson(m)’ is the kurtosis coefficient of the
Poisson distribution with mean <m>.

   In order to make use of package ‘distrib’ you need first to load it
by typing
     (%i1) load("distrib")$

   For comments, bugs or suggestions, please contact the author at
<'riotorto AT yahoo DOT com'>.


File: maxima.info,  Node: Functions and Variables for continuous distributions,  Next: Functions and Variables for discrete distributions,  Prev: Introduction to distrib,  Up: Package distrib

53.2 Functions and Variables for continuous distributions
=========================================================

Maxima knows the following kinds of continuous distributions.

* Menu:

* Normal Random Variable::
* Student's t Random Variable::
* Noncentral Student's t Random Variable::
* Chi-squared Random Variable::
* Noncentral Chi-squared Random Variable::
* F Random Variable::
* Exponential Random Variable::
* Lognormal Random Variable::
* Gamma Random Variable::
* Beta Random Variable::
* Continuous Uniform Random Variable::
* Logistic Random Variable::
* Pareto Random Variable::
* Weibull Random Variable::
* Rayleigh Random Variable::
* Laplace Random Variable::
* Cauchy Random Variable::
* Gumbel Random Variable::


File: maxima.info,  Node: Normal Random Variable,  Next: Student's t Random Variable,  Prev: Functions and Variables for continuous distributions,  Up: Functions and Variables for continuous distributions

53.2.1 Normal Random Variable
-----------------------------

Normal random variables (also called Gaussian) is denoted by Normal(m,
s) where m is the mean and s > 0 is the standard deviation.

 -- Function: pdf_normal (<x>,<m>,<s>)
     Returns the value at <x> of the density function of a Normal(m, s)
     random variable, with s>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                                           2
                                    (x - m)
                                  - --------
                                         2
                                      2 s
                                %e
                f(x, m, s) = -------------------
                             sqrt(2) sqrt(%pi) s

 -- Function: cdf_normal (<x>,<m>,<s>)
     Returns the value at <x> of the distribution function of a
     Normal(m, s) random variable, with s>0.  This function is defined
     in terms of Maxima's built-in error function ‘erf’.

     The cdf can be written analytically:

                                  x - m
                            erf(---------)
                                sqrt(2) s    1
               F(x, m, s) = -------------- + -
                                  2          2

          (%i1) load ("distrib")$
          (%i2) cdf_normal(x,m,s);
                                       x - m
                                 erf(---------)
                                     sqrt(2) s    1
          (%o2)                  -------------- + -
                                       2          2

     See also ‘erf’.

 -- Function: quantile_normal (<q>,<m>,<s>)
     Returns the <q>-quantile of a Normal(m, s) random variable, with
     s>0; in other words, this is the inverse of ‘cdf_normal’.  Argument
     <q> must be an element of [0,1].  To make use of this function,
     write first ‘load("distrib")’.

          (%i1) load ("distrib")$
          (%i2) quantile_normal(95/100,0,1);
                                                   9
          (%o2)                sqrt(2) inverse_erf(--)
                                                   10
          (%i3) float(%);
          (%o3)                   1.644853626951472

 -- Function: mean_normal (<m>,<s>)
     Returns the mean of a Normal(m, s) random variable, with s>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                       E[X] = m

 -- Function: var_normal (<m>,<s>)
     Returns the variance of a Normal(m, s) random variable, with s>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                               2
                                       V[X] = s

 -- Function: std_normal (<m>,<s>)
     Returns the standard deviation of a Normal(m, s) random variable,
     with s>0, namely <s>.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                       D[X] = s

 -- Function: skewness_normal (<m>,<s>)
     Returns the skewness coefficient of a Normal(m, s) random variable,
     with s>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                       SK[X] = 0

 -- Function: kurtosis_normal (<m>,<s>)
     Returns the kurtosis coefficient of a Normal(m, s) random variable,
     with s>0, which is always equal to 0.  To make use of this
     function, write first ‘load("distrib")’.

     The kurtosis coefficient is

                                       SK[X] = 0

 -- Function: random_normal (<m>,<s>)
          random_normal (<m>,<s>,<n>)

     Returns a Normal(m, s) random variate, with s>0.  Calling
     ‘random_normal’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     This is an implementation of the Box-Mueller algorithm, as
     described in Knuth, D.E. (1981) <Seminumerical Algorithms.  The Art
     of Computer Programming.> Addison-Wesley.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Student's t Random Variable,  Next: Noncentral Student's t Random Variable,  Prev: Normal Random Variable,  Up: Functions and Variables for continuous distributions

53.2.2 Student's t Random Variable
----------------------------------

Student's t random variable is denoted by t(n) where n is the degrees of
freedom with n > 0.  If Z is a Normal(0, 1) variable and V is an
independent chi^2 random variable with n degress of freedom, then

   Z/sqrt(V/n)

   has a Student's t-distribution with n degrees of freedom.

 -- Function: pdf_student_t (<x>,<n>)
     Returns the value at <x> of the density function of a Student
     random variable t(n), with n>0 degrees of freedom.  To make use of
     this function, write first ‘load("distrib")’.

     The pdf is

                                               (- n) - 1
                                         2     ---------
                                n + 1   x          2
                          gamma(-----) (-- + 1)
                                  2     n
                f(x, n) = ------------------------------
                                            n
                            sqrt(%pi) gamma(-) sqrt(n)
                                            2
     (sqrt(n)*beta(1/2,n/2))^(-1) (1+x^2/n)^(-(n+1)/2)

 -- Function: cdf_student_t (<x>,<n>)
     Returns the value at <x> of the distribution function of a Student
     random variable t(n), with n>0 degrees of freedom.

     The cdf is

                   [ 1-1/2*I_t(n/2, 1/2)  x >= 0
          F(x,n) = [
                   [ 1/2*I_t(n/2, 1/2)    x < 0

     where t = n/(n+x^2) and I_t(a,b) is the *note
     beta_incomplete_regularized:: function.

          (%i1) load ("distrib")$
          (%i2) cdf_student_t(1/2, 7/3);
                                                      7  1  28
                          beta_incomplete_regularized(-, -, --)
                                                      6  2  31
          (%o2)       1 - -------------------------------------
                                            2
          (%i3) float(%);
          (%o3)                  0.6698450596140415

 -- Function: quantile_student_t (<q>,<n>)
     Returns the <q>-quantile of a Student random variable t(n), with
     n>0; in other words, this is the inverse of ‘cdf_student_t’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_student_t (<n>)
     Returns the mean of a Student random variable t(n), with n>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                       E[X] = 0

 -- Function: var_student_t (<n>)
     Returns the variance of a Student random variable t(n), with n>2.

     The variance is

                                              n
                                     V[X] = -----
                                            n - 2

          (%i1) load ("distrib")$
          (%i2) var_student_t(n);
                                          n
          (%o2)                         -----
                                        n - 2

 -- Function: std_student_t (<n>)
     Returns the standard deviation of a Student random variable t(n),
     with n>2.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                               n
                                 D[X] = sqrt(-----)
                                             n - 2

 -- Function: skewness_student_t (<n>)
     Returns the skewness coefficient of a Student random variable t(n),
     with n>3, which is always equal to 0.  To make use of this
     function, write first ‘load("distrib")’.

     The skewness coefficient is

                                       SK[X] = 0

 -- Function: kurtosis_student_t (<n>)
     Returns the kurtosis coefficient of a Student random variable t(n),
     with n>4.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                              6
                                    KU[X] = -----
                                            n - 4

 -- Function: random_student_t (<n>)
          random_student_t (<n>,<m>)

     Returns a Student random variate t(n), with n>0.  Calling
     ‘random_student_t’ with a second argument <m>, a random sample of
     size <m> will be simulated.

     The implemented algorithm is based on the fact that if Z is a
     normal random variable Normal(0, 1) and S^2 is a chi squared random
     variable with n degrees of freedom, Chi^2() , then

                                     Z
                           X = -------------
                               /   2  \ 1/2
                               |  S   |
                               | ---  |
                               \  n   /

     is a Student random variable with n degrees of freedom, t(n).

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Noncentral Student's t Random Variable,  Next: Chi-squared Random Variable,  Prev: Student's t Random Variable,  Up: Functions and Variables for continuous distributions

53.2.3 Noncentral Student's t Random Variable
---------------------------------------------

Let ncp be the non-centrality parameter, n be the degrees of freedom for
the non-central Student's t random variable.

   Then let X be a Normal(n, ncp) and S^2 be an independent chi squared
random variable with n degrees of freedom, the random variable U =
X/sqrt(S^2/n)

   has a non-central Student's t distribution with non-centrality
parameter ncp.

 -- Function: pdf_noncentral_student_t (<x>,<n>,<ncp>)
     Returns the value at <x> of the density function of a noncentral
     Student random variable nc_t(n, ncp) , with n>0 degrees of freedom
     and noncentrality parameter ncp.  To make use of this function,
     write first ‘load("distrib")’.

     The pdf is

                                     2
                                   mu          (- n) - 1
                                 - ---         ---------
                                    2    2         2
                               %e      (x  + 1)          (B(x, n, mu) + An(x, n, mu))
          f(x;n,mu) =          -------------------------------------------------
                                                   1  n
                                              beta(-, -) sqrt(n)
                                                   2  2


     where

                                                  2  2
                                 n + 1    1     mu  x
           A(x, n, mu) = %f    ([-----], [-], ----------)
                           1, 1    2      2       2
                                              2 (x  + n)

                                                             2  2
                                            n        3     mu  x           n
                         sqrt(2) mu %f    ([- + 1], [-], ----------) gamma(- + 1) x
                                      1, 1  2        2       2             2
                                                         2 (x  + n)
           B(x, n, mu) = ----------------------------------------------------------
                                               n + 1        2
                                         gamma(-----) sqrt(x  + n)
                                                 2

     and mu is the non-centrality parameter ncp.

     Sometimes an extra work is necessary to get the final result.

          (%i1) load ("distrib")$
          (%i2) expand(pdf_noncentral_student_t(3,5,0.1));
          rat: replaced 0.01889822365046136 by 15934951/843198350 = 0.01889822365046136

          rat: replaced -8.734356480209641 by -294697965/33740089 = -8.734356480209641

          rat: replaced 4.136255165816327 by 51033443/12338079 = 4.136255165816332

          rat: replaced 1.08061432164203 by 56754827/52520891 = 1.08061432164203

          rat: replaced 0.0565127306411839 by 5608717/99246965 = 0.05651273064118384

          rat: replaced -300.8069396896258 by -79782423/265228 = -300.8069396896256

          rat: replaced 160.6269176184973 by 178374907/1110492 = 160.626917618497
                                     7/2                         7/2
                0.04296414417400905 5      1.323650307289301e-6 5
          (%o2) ------------------------ + -------------------------
                   3/2   5/2                       sqrt(%pi)
                  2    14    sqrt(%pi)
                                                                        7/2
                                                   1.94793720435093e-4 5
                                                 + ------------------------
                                                             %pi
          (%i3) float(%);
          (%o3)                  0.02080593159405671

 -- Function: cdf_noncentral_student_t (<x>,<n>,<ncp>)
     Returns the value at <x> of the distribution function of a
     noncentral Student random variable nc_t(n, ncp) , with n>0 degrees
     of freedom and noncentrality parameter ncp.  This function has no
     closed form and it is numerically computed.

          (%i1) load ("distrib")$
          (%i2) cdf_noncentral_student_t(-2,5,-5);
          (%o2)                   0.995203009331975

 -- Function: quantile_noncentral_student_t (<q>,<n>,<ncp>)
     Returns the <q>-quantile of a noncentral Student random variable
     nc_t(n, ncp) , with n>0 degrees of freedom and noncentrality
     parameter ncp; in other words, this is the inverse of
     ‘cdf_noncentral_student_t’.  Argument <q> must be an element of
     [0,1].  To make use of this function, write first
     ‘load("distrib")’.

 -- Function: mean_noncentral_student_t (<n>,<ncp>)
     Returns the mean of a noncentral Student random variable nc_t(n,
     ncp) , with n>1 degrees of freedom and noncentrality parameter ncp.
     To make use of this function, write first ‘load("distrib")’.

     The mean is

                             n - 1
                    mu gamma(-----) sqrt(n)
                               2
          E[X] =    -----------------------
                                     n
                       sqrt(2) gamma(-)
                                     2

     where mu is the noncentrality parameter ncp.

          (%i1) load ("distrib")$
          (%i2) mean_noncentral_student_t(df,k);
                                    df - 1
                              gamma(------) sqrt(df) k
                                      2
          (%o2)               ------------------------
                                               df
                                 sqrt(2) gamma(--)
                                               2

 -- Function: var_noncentral_student_t (<n>,<ncp>)
     Returns the variance of a noncentral Student random variable
     nc_t(n, ncp) , with n>2 degrees of freedom and noncentrality
     parameter ncp.  To make use of this function, write first
     ‘load("distrib")’.

     The variance is

                                       2 n - 1       2
                         2        gamma (-----) n ncp
                   n (ncp  + 1)            2
          V[X] =   ------------ - --------------------
                      n - 2                  2 n
                                      2 gamma (-)
                                               2

     where mu is the noncentrality parameter ncp.

 -- Function: std_noncentral_student_t (<n>,<ncp>)
     Returns the standard deviation of a noncentral Student random
     variable nc_t(n, ncp) , with n>2 degrees of freedom and
     noncentrality parameter ncp.  To make use of this function, write
     first ‘load("distrib")’.

     The standard deviation is

                                       2 n - 1       2
                              2        gamma (-----) n ncp
                        n (ncp  + 1)            2
          D[X] =   sqrt(------------ - --------------------)
                           n - 2                  2 n
                                           2 gamma (-)
                                                    2

 -- Function: skewness_noncentral_student_t (<n>,<ncp>)
     Returns the skewness coefficient of a noncentral Student random
     variable nc_t(n, ncp) , with n>3 degrees of freedom and
     noncentrality parameter ncp.  To make use of this function, write
     first ‘load("distrib")’.

     If U is a non-central Student's t random variable with n degrees of
     freedom and a noncentrality parameter mu , the skewness is

          SK[U] =
                                               2
                    n - 1           n (2 n + mu  - 3)
          (mu gamma(-----) sqrt(n) (-----------------
                      2              (n - 3) (n - 2)
                                2      2 n - 1
                   2          mu  gamma (-----) n
                (mu  + 1) n                2
           - 2 (----------- - -------------------)))
                   n - 2                 2 n
                                  2 gamma (-)
                                           2
                                              2      2 n - 1
                                 2          mu  gamma (-----) n
                          n   (mu  + 1) n                2      3/2
          /(sqrt(2) gamma(-) (----------- - -------------------)   )
                          2      n - 2                 2 n
                                                2 gamma (-)
                                                         2

 -- Function: kurtosis_noncentral_student_t (<n>,<ncp>)
     Returns the kurtosis coefficient of a noncentral Student random
     variable nc_t(n, ncp) , with n>4 degrees of freedom and
     noncentrality parameter ncp.  To make use of this function, write
     first ‘load("distrib")’.

     If U is a non-central Student's t random variable with n degrees of
     freedom and a noncentrality parameter mu , the kurtosis is

          KU[U] =
              4       2       2
           (mu  + 6 mu  + 3) n       2      2 n - 1
          (-------------------- - (mu  gamma (-----) n
             (n - 4) (n - 2)                    2
                                                               2      2 n - 1
                               2                  2          mu  gamma (-----) n
            n (3 (3 n - 5) + mu  (n + 1))      (mu  + 1) n                2
           (----------------------------- - 3 (----------- - -------------------)))
                   (n - 3) (n - 2)                n - 2                 2 n
                                                                 2 gamma (-)
                                                                          2
                                           2      2 n - 1
                              2          mu  gamma (-----) n
                   2 n     (mu  + 1) n                2      2
          /(2 gamma (-)))/(----------- - -------------------)  - 3
                     2        n - 2                 2 n
                                             2 gamma (-)
                                                      2

 -- Function: random_noncentral_student_t (<n>,<ncp>)
          random_noncentral_student_t (<n>,<ncp>,<m>)

     Returns a noncentral Student random variate nc_t(n, ncp) , with
     n>0.  Calling ‘random_noncentral_student_t’ with a third argument
     <m>, a random sample of size <m> will be simulated.

     The implemented algorithm is based on the fact that if <X> is a
     normal random variable Normal(ncp, 1) and S^2 is a chi square
     random variable with <n> degrees of freedom, Chi^2() , then

                                     X
                           U = -------------
                               /   2  \ 1/2
                               |  S   |
                               | ---  |
                               \  n   /

     is a noncentral Student random variable with n degrees of freedom
     and noncentrality parameter ncp, nc_t(n, ncp) .

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Chi-squared Random Variable,  Next: Noncentral Chi-squared Random Variable,  Prev: Noncentral Student's t Random Variable,  Up: Functions and Variables for continuous distributions

53.2.4 Chi-squared Random Variable
----------------------------------

Let X_1, X_2, ..., X_k be independent and identically distributed
Normal(0, 1) variables.  Then X^2 = sum(X_i^2, i, 1, n)

   is said to follow a chi-square distribution with n degrees of
freedom.

 -- Function: pdf_chi2 (<x>,<n>)
     Returns the value at <x> of the density function of a Chi-square
     random variable Chi^2() , with n>0.  The Chi^2() random variable is
     equivalent to the Gamma(n/2,2) .

     The pdf is

                       [  n/2 - 1   - x/2
                       [ x        %e      unit_step(x)
                       [ -----------------------------     for x >= 0
                       [               n   n/2
             f(x, n) = [         gamma(-) 2
                       [               2
                       [
                       [ 0                                 otherwise

          (%i1) load ("distrib")$
          (%i2) pdf_chi2(x,n);
                             n/2 - 1   - x/2
                            x        %e      unit_step(x)
          (%o2)             -----------------------------
                                          n   n/2
                                    gamma(-) 2
                                          2

 -- Function: cdf_chi2 (<x>,<n>)
     Returns the value at x of the distribution function of a Chi-square
     random variable Chi^2() , with n>0.

     The cdf is

                    [        n  x
                    [ (1 - Q(-, -))     for x >= 0
                    [        2  2
          F(x, n) = [
                    [ 0                 otherwise

     where Q(a,z) is the *note gamma_incomplete_regularized:: function.

          (%i1) load ("distrib")$
          (%i2) cdf_chi2(3,4);
                                                           3
          (%o2)        1 - gamma_incomplete_regularized(2, -)
                                                           2
          (%i3) float(%);
          (%o3)                  0.4421745996289252

 -- Function: quantile_chi2 (<q>,<n>)
     Returns the <q>-quantile of a Chi-square random variable Chi^2() ,
     with n>0; in other words, this is the inverse of ‘cdf_chi2’.
     Argument <q> must be an element of [0,1].

     This function has no closed form and it is numerically computed.

          (%i1) load ("distrib")$
          (%i2) quantile_chi2(0.99,9);
          (%o2)                   21.66599433346194

 -- Function: mean_chi2 (<n>)
     Returns the mean of a Chi-square random variable Chi^2() , with
     n>0.

     The Chi^2() random variable is equivalent to the Gamma(n/2,2) .

     The mean is

                                      E[X] = n

          (%i1) load ("distrib")$
          (%i2) mean_chi2(n);
          (%o2)                           n

 -- Function: var_chi2 (<n>)
     Returns the variance of a Chi-square random variable Chi^2() , with
     n>0.

     The Chi^2() random variable is equivalent to the Gamma(n/2,2) .

     The variance is

                                     V[X] = 2 n

          (%i1) load ("distrib")$
          (%i2) var_chi2(n);
          (%o2)                          2 n

 -- Function: std_chi2 (<n>)
     Returns the standard deviation of a Chi-square random variable
     Chi^2() , with n>0.

     The Chi^2() random variable is equivalent to the Gamma(n/2,2) .

     The standard deviation is

                               D[X] = sqrt(2) sqrt(n)

          (%i1) load ("distrib")$
          (%i2) std_chi2(n);
          (%o2)                    sqrt(2) sqrt(n)

 -- Function: skewness_chi2 (<n>)
     Returns the skewness coefficient of a Chi-square random variable
     Chi^2() , with n>0.

     The Chi^2() random variable is equivalent to the Gamma(n/2,2) .

     The skewness coefficient is

                                             3/2
                                            2
                                   SK[X] = -------
                                           sqrt(n)

          (%i1) load ("distrib")$
          (%i2) skewness_chi2(n);
                                         3/2
                                        2
          (%o2)                        -------
                                       sqrt(n)

 -- Function: kurtosis_chi2 (<n>)
     Returns the kurtosis coefficient of a Chi-square random variable
     Chi^2() , with n>0.

     The Chi^2() random variable is equivalent to the Gamma(n/2,2) .

     The kurtosis coefficient is

                                             12
                                     KU[X] = --
                                             n

          (%i1) load ("distrib")$
          (%i2) kurtosis_chi2(n);
                                         12
          (%o2)                          --
                                         n

 -- Function: random_chi2 (<n>)
          random_chi2 (<n>,<m>)

     Returns a Chi-square random variate Chi^2() , with n>0.  Calling
     ‘random_chi2’ with a second argument <m>, a random sample of size
     <m> will be simulated.

     The simulation is based on the Ahrens-Cheng algorithm.  See
     ‘random_gamma’ for details.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Noncentral Chi-squared Random Variable,  Next: F Random Variable,  Prev: Chi-squared Random Variable,  Up: Functions and Variables for continuous distributions

53.2.5 Noncentral Chi-squared Random Variable
---------------------------------------------

Let X[1], X[2], ..., X[n] be n independent normally distributed random
variables with means mu[k] and unit variances.  Then the random variable

   sum(X[k]^2, k, 1, n)

   has a noncentral chi-squared distribution.  The number of degrees of
freedom is n, and the noncentrality parameter is defined by

   sum(mu[k]^2, k, 1, n)

 -- Function: pdf_noncentral_chi2 (<x>,<n>,<ncp>)
     Returns the value at x of the density function of a noncentral
     Chi-square random variable m4_noncentral_chi2(n,ncp), with n>0 and
     noncentrality parameter ncp >= 0 .  To make use of this function,
     write first ‘load("distrib")’.

     For x < 0, the pdf is 0, and for x >= 0 the pdf is

           f(x, n, ncp) =
                                                                 (- x) - ncp
                                                                 -----------
                            n                     x  n/4 - 1/2        2
                   bessel_i(- - 1, sqrt(ncp x)) (---)          %e            unit_step(x)
                            2                    ncp
                   ----------------------------------------------------------------------
                                                     2

 -- Function: cdf_noncentral_chi2 (<x>,<n>,<ncp>)
     Returns the value at <x> of the distribution function of a
     noncentral Chi-square random variable m4_noncentral_chi2(n,ncp),
     with n>0 and noncentrality parameter ncp >= 0 .  To make use of
     this function, write first ‘load("distrib")’.

 -- Function: quantile_noncentral_chi2 (<q>,<n>,<ncp>)
     Returns the <q>-quantile of a noncentral Chi-square random variable
     m4_noncentral_chi2(n,ncp), with n>0 and noncentrality parameter ncp
     >= 0 ; in other words, this is the inverse of
     ‘cdf_noncentral_chi2’.  Argument <q> must be an element of [0,1].

     This function has no closed form and it is numerically computed.

 -- Function: mean_noncentral_chi2 (<n>,<ncp>)
     Returns the mean of a noncentral Chi-square random variable
     m4_noncentral_chi2(n,ncp), with n>0 and noncentrality parameter ncp
     >= 0 .

     The mean is

                                   E[X] = ncp + n

 -- Function: var_noncentral_chi2 (<n>,<ncp>)
     Returns the variance of a noncentral Chi-square random variable
     m4_noncentral_chi2(n,ncp), with n>0 and noncentrality parameter ncp
     >= 0 .

     The variance is

                                V[X] = 2 (2 ncp + n)

 -- Function: std_noncentral_chi2 (<n>,<ncp>)
     Returns the standard deviation of a noncentral Chi-square random
     variable m4_noncentral_chi2(n,ncp), with n>0 and noncentrality
     parameter ncp >= 0 .

     The standard deviation is

                           D[X] = sqrt(2) sqrt(2 ncp + n)

 -- Function: skewness_noncentral_chi2 (<n>,<ncp>)
     Returns the skewness coefficient of a noncentral Chi-square random
     variable m4_noncentral_chi2(n,ncp), with n>0 and noncentrality
     parameter ncp >= 0 .

     The skewness coefficient is

                    3/2
                   2    (n + 3 mu)
           SK[X] = ---------------
                              3/2
                    (n + 2 mu)


 -- Function: kurtosis_noncentral_chi2 (<n>,<ncp>)
     Returns the kurtosis coefficient of a noncentral Chi-square random
     variable m4_noncentral_chi2(n,ncp), with n>0 and noncentrality
     parameter ncp >= 0 .

     The kurtosis coefficient is

                     12 (n + 4 mu)
             KU[X] = -------------
                                2
                      (n + 2 mu)

 -- Function: random_noncentral_chi2 (<n>,<ncp>)
          random_noncentral_chi2 (<n>,<ncp>,<m>)

     Returns a noncentral Chi-square random variate
     m4_noncentral_chi2(n,ncp), with n>0 and noncentrality parameter ncp
     >= 0 .  Calling ‘random_noncentral_chi2’ with a third argument <m>,
     a random sample of size <m> will be simulated.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: F Random Variable,  Next: Exponential Random Variable,  Prev: Noncentral Chi-squared Random Variable,  Up: Functions and Variables for continuous distributions

53.2.6 F Random Variable
------------------------

Let S_1 and S_2 be independent random variables with a chi-squared
distribution with degrees of freedom n and m, respectively.  Then F =
(S_1/n)/(S_2/m) has an F distribution with n and m degrees of freedom.

 -- Function: pdf_f (<x>,<m>,<n>)
     Returns the value at <x> of the density function of a F random
     variable F(m,n), with m,n>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

           f(x, m, n) =
                                                                   (- n) - m
                                                                   ---------
                              n n/2       n + m   n/2 - 1  n x         2
                             (-)    gamma(-----) x        (--- + 1)          unit_step(x)
                              m             2               m
                             ------------------------------------------------------------
                                                        m        n
                                                  gamma(-) gamma(-)
                                                        2        2


 -- Function: cdf_f (<x>,<m>,<n>)
     Returns the value at <x> of the distribution function of a F random
     variable F(m,n), with m,n>0.

     The cdf is

                                                         n  m     n
           F(x, m, n) = (1 - beta_incomplete_regularized(-, -, -------))
                                                         2  2  m x + n
                                                                       unit_step(x)

          (%i1) load ("distrib")$
          (%i2) cdf_f(2,3,9/4);
                                                      9  3  3
          (%o2)       1 - beta_incomplete_regularized(-, -, --)
                                                      8  2  11
          (%i3) float(%);
          (%o3)                  0.6675672817900802

 -- Function: quantile_f (<q>,<m>,<n>)
     Returns the <q>-quantile of a F random variable F(m,n), with m,n>0;
     in other words, this is the inverse of ‘cdf_f’.  Argument <q> must
     be an element of [0,1].

          (%i1) load ("distrib")$
          (%i2) quantile_f(2/5,sqrt(3),5);
          (%o2)                  0.5189478385736904

 -- Function: mean_f (<m>,<n>)
     Returns the mean of a F random variable F(m,n), with m>0, n>2.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                             n
                                    E[X] = -----
                                           n - 2

 -- Function: var_f (<m>,<n>)
     Returns the variance of a F random variable F(m,n), with m>0, n>4.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                         2
                      2 n  (n + m - 2)
              V[X] = ------------------
                                      2
                     m (n - 4) (n - 2)

 -- Function: std_f (<m>,<n>)
     Returns the standard deviation of a F random variable F(m,n), with
     m>0, n>4.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                  n         n + m - 2
            D[X] = sqrt(2) sqrt(-----) sqrt(---------)
                                n - 2       m (n - 4)

 -- Function: skewness_f (<m>,<n>)
     Returns the skewness coefficient of a F random variable F(m,n),
     with m>0, n>6.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                    3/2
                   2    sqrt(n - 4) (n + 2 m - 2)
           SK[X] = ------------------------------
                    (n - 6) sqrt(m (n + m - 2))


 -- Function: kurtosis_f (<m>,<n>)
     Returns the kurtosis coefficient of a F random variable F(m,n),
     with m>0, n>8.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                                                  2
                    12 (m (n + m - 2) (5 n - 22) + (n - 4) (n - 2) )
            KU[X] = ------------------------------------------------
                             m (n - 8) (n - 6) (n + m - 2)

 -- Function: random_f (<m>,<n>)
          random_f (<m>,<n>,<k>)

     Returns a F random variate F(m,n), with m,n>0.  Calling ‘random_f’
     with a third argument <k>, a random sample of size <k> will be
     simulated.

     The simulation algorithm is based on the fact that if <X> is a
     Chi^2(m) random variable and Y is a Chi^2() random variable, then

                                  n X
                              F = ---
                                  m Y

     is a F random variable with <m> and <n> degrees of freedom, F(m,n).

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Exponential Random Variable,  Next: Lognormal Random Variable,  Prev: F Random Variable,  Up: Functions and Variables for continuous distributions

53.2.7 Exponential Random Variable
----------------------------------

The _exponential distribution_ is the probablity distribution of the
time between events in a process where the events occur continuously and
independently at a constant average rate.

 -- Function: pdf_exp (<x>,<m>)
     Returns the value at <x> of the density function of an
     Exponential(m) random variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The pdf is

                    [ m*exp(-m*x) for x >= 0
          f(x, m) = [
                    [ 0           otherwise

          (%i1) load ("distrib")$
          (%i2) pdf_exp(x,m);
                                   - m x
          (%o2)                m %e      unit_step(x)

 -- Function: cdf_exp (<x>,<m>)
     Returns the value at <x> of the distribution function of an
     Exponential(m) random variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The cdf is

                   [ 1 - exp(-m*x)  for x >= 0
          F(x,n) = [
                   [ 0              otherwise

          (%i1) load ("distrib")$
          (%i2) cdf_exp(x,m);
                                    - m x
          (%o2)              (1 - %e     ) unit_step(x)

 -- Function: quantile_exp (<q>,<m>)
     Returns the <q>-quantile of an Exponential(m) random variable, with
     m>0; in other words, this is the inverse of ‘cdf_exp’.  Argument
     <q> must be an element of [0,1].

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

          (%i1) load ("distrib")$
          (%i2) quantile_exp(0.56,5);
          (%o2)                  0.1641961104139661
          (%i3) quantile_exp(0.56,m);
                                 0.8209805520698303
          (%o3)                  ------------------
                                         m

 -- Function: mean_exp (<m>)
     Returns the mean of an Exponential(m) random variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The mean is

                                             1
                                      E[X] = -
                                             m

          (%i1) load ("distrib")$
          (%i2) mean_exp(m);
                                          1
          (%o2)                           -
                                          m

 -- Function: var_exp (<m>)
     Returns the variance of an Exponential(m) random variable, with
     m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The variance is

                                             1
                                        VX = --
                                              2
                                             m

          (%i1) load ("distrib")$
          (%i2) var_exp(m);
                                         1
          (%o2)                          --
                                          2
                                         m

 -- Function: std_exp (<m>)
     Returns the standard deviation of an Exponential(m) random
     variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The standard deviation is

                                             1
                                      D[X] = -
                                             m

          (%i1) load ("distrib")$
          (%i2) std_exp(m);
                                          1
          (%o2)                           -
                                          m

 -- Function: skewness_exp (<m>)
     Returns the skewness coefficient of an Exponential(m) random
     variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The skewness coefficient is

                                      SK[X] = 2

          (%i1) load ("distrib")$
          (%i2) skewness_exp(m);
          (%o2)                           2

 -- Function: kurtosis_exp (<m>)
     Returns the kurtosis coefficient of an Exponential(m) random
     variable, with m>0.

     The Exponential(m) random variable is equivalent to the
     Weibull(1,1/m) .

     The kurtosis coefficient is

                                      KU[X] = 6

          (%i1) load ("distrib")$
          (%i2) kurtosis_exp(m);
          (%o2)                           6

 -- Function: random_exp (<m>)
          random_exp (<m>,<k>)

     Returns an Exponential(m) random variate, with m>0.  Calling
     ‘random_exp’ with a second argument <k>, a random sample of size
     <k> will be simulated.

     The simulation algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Lognormal Random Variable,  Next: Gamma Random Variable,  Prev: Exponential Random Variable,  Up: Functions and Variables for continuous distributions

53.2.8 Lognormal Random Variable
--------------------------------

The _lognormal_ distribution is distribution for a random variable whose
logarithm is normally distributed.

 -- Function: pdf_lognormal (<x>,<m>,<s>)
     Returns the value at <x> of the density function of a
     Lognormal(m,s) random variable, with s>0.  To make use of this
     function, write first ‘load("distrib")’.

     The pdf is

                             [                   2
                             [       (log(x) - m)
                             [     - -------------
                             [              2
                             [           2 s
                             [   %e
                f(x, m, s) = [ ---------------------      for x >= 0
                             [ sqrt(2) sqrt(%pi) s x
                             [
                             [ 0                          for x < 0

 -- Function: cdf_lognormal (<x>,<m>,<s>)
     Returns the value at <x> of the distribution function of a
     Lognormal(m,s) random variable, with s>0.  This function is defined
     in terms of Maxima's built-in error function ‘erf’.

     The cdf is

                                                   log(x) - m
                                               erf(----------)
                                                   sqrt(2) s     1
                    F(x, m, s) = unit_step(x) (--------------- + -)
                                                      2          2

          (%i1) load ("distrib")$
          (%i2) cdf_lognormal(x,m,s);
                                           log(x) - m
                                       erf(----------)
                                           sqrt(2) s     1
          (%o2)          unit_step(x) (--------------- + -)
                                              2          2

     See also ‘erf’.

 -- Function: quantile_lognormal (<q>,<m>,<s>)
     Returns the <q>-quantile of a Lognormal(m,s) random variable, with
     s>0; in other words, this is the inverse of ‘cdf_lognormal’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

          (%i1) load ("distrib")$
          (%i2) quantile_lognormal(95/100,0,1);
                               sqrt(2) inverse_erf(9/10)
          (%o2)              %e
          (%i3) float(%);
          (%o3)                   5.180251602233015

 -- Function: mean_lognormal (<m>,<s>)
     Returns the mean of a Lognormal(m,s) random variable, with s>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                             2
                                            s
                                            -- + m
                                            2
                                   E[X] = %e

 -- Function: var_lognormal (<m>,<s>)
     Returns the variance of a Lognormal(m,s) random variable, with s>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                       2         2
                                      s         s  + 2 m
                            V[X] = (%e   - 1) %e


 -- Function: std_lognormal (<m>,<s>)
     Returns the standard deviation of a Lognormal(m,s) random variable,
     with s>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                                   2
                                                  s  + 2 m
                                         2        --------
                                        s            2
                          D[X] = sqrt(%e   - 1) %e


 -- Function: skewness_lognormal (<m>,<s>)
     Returns the skewness coefficient of a Lognormal(m,s) random
     variable, with s>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                          2          2
                                         s          s
                          SK[X] = sqrt(%e   - 1) (%e   + 2)

 -- Function: kurtosis_lognormal (<m>,<s>)
     Returns the kurtosis coefficient of a Lognormal(m,s) random
     variable, with s>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                   2          2          2
                                4 s        3 s        2 s
                      KU[X] = %e     + 2 %e     + 3 %e     - 3


 -- Function: random_lognormal (<m>,<s>)
          random_lognormal (<m>,<s>,<n>)

     Returns a Lognormal(m,s) random variate, with s>0.  Calling
     ‘random_lognormal’ with a third argument <n>, a random sample of
     size <n> will be simulated.

     Log-normal variates are simulated by means of random normal
     variates.  See ‘random_normal’ for details.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Gamma Random Variable,  Next: Beta Random Variable,  Prev: Lognormal Random Variable,  Up: Functions and Variables for continuous distributions

53.2.9 Gamma Random Variable
----------------------------

The _gamma distribution_ is a two-parameter family of probability
distributions.  Maxima uses the parameterization using the shape and
scale for the first and second parameters of the distribution.

 -- Function: pdf_gamma (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Gamma(a,b)
     random variable, with a,b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The shape parameter is a, and the scale parameter is b.

     The pdf is

                              a - 1   - x/b
                             x      %e      unit_step(x)
                f(x, a, b) = ---------------------------
                                               a
                                     gamma(a) b

 -- Function: cdf_gamma (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Gamma(a,b) random variable, with a,b>0.

     The cdf is

                       [ 1 - Q(a,x/b) for x>= 0
          F(x, a, b) = [
                       [ 0            for x < 0

     where Q(a,z) is the *note gamma_incomplete_regularized:: function.
          (%i1) load ("distrib")$
          (%i2) cdf_gamma(3,5,21);
                                                           1
          (%o2)        1 - gamma_incomplete_regularized(5, -)
                                                           7
          (%i3) float(%);
          (%o3)                 4.402663157376807e-7

 -- Function: quantile_gamma (<q>,<a>,<b>)
     Returns the <q>-quantile of a Gamma(a,b) random variable, with
     a,b>0; in other words, this is the inverse of ‘cdf_gamma’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_gamma (<a>,<b>)
     Returns the mean of a Gamma(a,b) random variable, with a,b>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                     E[X] = a b

 -- Function: var_gamma (<a>,<b>)
     Returns the variance of a Gamma(a,b) random variable, with a,b>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                               2
                                     V[X] = a b

 -- Function: std_gamma (<a>,<b>)
     Returns the standard deviation of a Gamma(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                 D[X] = sqrt(a) b

 -- Function: skewness_gamma (<a>,<b>)
     Returns the skewness coefficient of a Gamma(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                               2
                                    SK[X] = -------
                                            sqrt(a)

 -- Function: kurtosis_gamma (<a>,<b>)
     Returns the kurtosis coefficient of a Gamma(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                               6
                                       KU[X] = -
                                               a


 -- Function: random_gamma (<a>,<b>)
          random_gamma (<a>,<b>,<n>)

     Returns a Gamma(a,b) random variate, with a,b>0.  Calling
     ‘random_gamma’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is a combination of two procedures,
     depending on the value of parameter <a>:

     For a >= 1 , Cheng, R.C.H. and Feast, G.M. (1979).  <Some simple
     gamma variate generators>.  Appl.  Stat., 28, 3, 290-295.

     For 0 < a < 1 , Ahrens, J.H. and Dieter, U. (1974).  <Computer
     methods for sampling from gamma, , poisson and binomial
     distributions>.  Computing, 12, 223-246.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Beta Random Variable,  Next: Continuous Uniform Random Variable,  Prev: Gamma Random Variable,  Up: Functions and Variables for continuous distributions

53.2.10 Beta Random Variable
----------------------------

The _beta_ distribution is a family of distributions defined over [0,1]
parameterized by two positive shape parameters a, and b.

 -- Function: pdf_beta (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Beta(a,b)
     random variable, with a,b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                        [        b - 1  a - 1
                        [ (1 - x)      x
           f(x, a, b) = [ -------------------   for 0 <= x <= 1
                        [     beta(a, b)
                        [
                        [ 0                     otherwise

 -- Function: cdf_beta (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Beta(a,b) random variable, with a,b>0.

     The cdf is

                       [ 0                                     for x < 0
                       [
          F(x, a, b) = [ beta_incomplete_regularized(a, b, x)  for 0 <= x <= 1
                       [
                       [ 1                                     for x > 1

          (%i1) load ("distrib")$
          (%i2) cdf_beta(1/3,15,2);
                                         11
          (%o2)                       --------
                                      14348907
          (%i3) float(%);
          (%o3)                 7.666089131388195e-7

 -- Function: quantile_beta (<q>,<a>,<b>)
     Returns the <q>-quantile of a Beta(a,b) random variable, with
     a,b>0; in other words, this is the inverse of ‘cdf_beta’.  Argument
     <q> must be an element of [0,1].  To make use of this function,
     write first ‘load("distrib")’.

 -- Function: mean_beta (<a>,<b>)
     Returns the mean of a Beta(a,b) random variable, with a,b>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                              a
                                     E[X] = -----
                                            b + a

 -- Function: var_beta (<a>,<b>)
     Returns the variance of a Beta(a,b) random variable, with a,b>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                             a b
              V[X] = --------------------
                            2
                     (b + a)  (b + a + 1)

 -- Function: std_beta (<a>,<b>)
     Returns the standard deviation of a Beta(a,b) random variable, with
     a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                             a b
                     sqrt(---------)
                          b + a + 1
              D[X] = ---------------
                       abs(b + a)

 -- Function: skewness_beta (<a>,<b>)
     Returns the skewness coefficient of a Beta(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                     2 (b - a) sqrt(b + a + 1)
             SK[X] = -------------------------
                       sqrt(a b) (b + a + 2)

 -- Function: kurtosis_beta (<a>,<b>)
     Returns the kurtosis coefficient of a Beta(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                            2
                    3 (b + a + 1) (2 (b + a)  + a b (b + a - 6))
            KU[X] = -------------------------------------------- - 3
                            a b (b + a + 2) (b + a + 3)

 -- Function: random_beta (<a>,<b>)
          random_beta (<a>,<b>,<n>)

     Returns a Beta(a,b) random variate, with a,b>0.  Calling
     ‘random_beta’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is defined in Cheng, R.C.H. (1978).
     <Generating Beta Variates with Nonintegral Shape Parameters>.
     Communications of the ACM, 21:317-322

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Continuous Uniform Random Variable,  Next: Logistic Random Variable,  Prev: Beta Random Variable,  Up: Functions and Variables for continuous distributions

53.2.11 Continuous Uniform Random Variable
------------------------------------------

The _continuous uniform_ distribution is constant over the interval
[a,b] and is zero elsewhere.

 -- Function: pdf_continuous_uniform (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a
     ContinuousUniform(a,b) random variable, with a < b .  To make use
     of this function, write first ‘load("distrib")’.

     The pdf

                       [ 1/(b-a) for 0 <= x <= 1
          f(x, a, b) = [
                       [ 0       otherwise

     and is 0 otherwise.

 -- Function: cdf_continuous_uniform (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     ContinuousUniform(a,b) random variable, with a < b .  To make use
     of this function, write first ‘load("distrib")’.

     The cdf is

                     [ 0              for x < a
          F(x,a,b) = [ (x-a)/(b-a)    for a <= x <= b
                     [ 1              for x > b

 -- Function: quantile_continuous_uniform (<q>,<a>,<b>)
     Returns the <q>-quantile of a ContinuousUniform(a,b) random
     variable, with a < b ; in other words, this is the inverse of
     ‘cdf_continuous_uniform’.  Argument <q> must be an element of
     [0,1].  To make use of this function, write first
     ‘load("distrib")’.

 -- Function: mean_continuous_uniform (<a>,<b>)
     Returns the mean of a ContinuousUniform(a,b) random variable, with
     a < b .  To make use of this function, write first
     ‘load("distrib")’.

     The mean is

                                            b + a
                                     E[X] = -----
                                              2


 -- Function: var_continuous_uniform (<a>,<b>)
     Returns the variance of a ContinuousUniform(a,b) random variable,
     with a < b .  To make use of this function, write first
     ‘load("distrib")’.

     The variance is

                                                  2
                                           (b - a)
                                    V[X] = --------
                                              12

 -- Function: std_continuous_uniform (<a>,<b>)
     Returns the standard deviation of a ContinuousUniform(a,b) random
     variable, with a < b .  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                          abs(b - a)
                                   D[X] = ----------
                                          2 sqrt(3)


 -- Function: skewness_continuous_uniform (<a>,<b>)
     Returns the skewness coefficient of a ContinuousUniform(a,b) random
     variable, with a < b .  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                      SK[X] = 0

 -- Function: kurtosis_continuous_uniform (<a>,<b>)
     Returns the kurtosis coefficient of a ContinuousUniform(a,b) random
     variable, with a < b .  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

     6 KU[X] = - - 5

 -- Function: random_continuous_uniform (<a>,<b>)
          random_continuous_uniform (<a>,<b>,<n>)

     Returns a ContinuousUniform(a,b) random variate, with a < b .
     Calling ‘random_continuous_uniform’ with a third argument <n>, a
     random sample of size <n> will be simulated.

     This is a direct application of the ‘random’ built-in Maxima
     function.

     See also ‘random’.  To make use of this function, write first
     ‘load("distrib")’.


File: maxima.info,  Node: Logistic Random Variable,  Next: Pareto Random Variable,  Prev: Continuous Uniform Random Variable,  Up: Functions and Variables for continuous distributions

53.2.12 Logistic Random Variable
--------------------------------

The _logistic_ distribution is a continuous distribution where it's
cumulative distribution function is the logistic function.

 -- Function: pdf_logistic (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a
     <Logistice(a,b) random variable , with b>0.  To make use of this
     function, write first ‘load("distrib")’.

     a is the location parameter and b is the scale parameter.

     The pdf is

                                                a - x
                                                -----
                                                  b
                                              %e
                             f(x, a, b) = ----------------
                                               a - x
                                               -----
                                                 b       2
                                          b (%e      + 1)

 -- Function: cdf_logistic (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     <Logistice(a,b) random variable , with b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                                                 1
                               F(x, a, b) = -----------
                                              a - x
                                              -----
                                                b
                                            %e      + 1

 -- Function: quantile_logistic (<q>,<a>,<b>)
     Returns the <q>-quantile of a <Logistice(a,b) random variable ,
     with b>0; in other words, this is the inverse of ‘cdf_logistic’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_logistic (<a>,<b>)
     Returns the mean of a <Logistice(a,b) random variable , with b>0.
     To make use of this function, write first ‘load("distrib")’.

     The mean is

                                      E[X] = a

 -- Function: var_logistic (<a>,<b>)
     Returns the variance of a <Logistice(a,b) random variable , with
     b>0.  To make use of this function, write first ‘load("distrib")’.

     The variance is

                                             2  2
                                          %pi  b
                                   V[X] = -------
                                             3


 -- Function: std_logistic (<a>,<b>)
     Returns the standard deviation of a <Logistice(a,b) random variable
     , with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                         %pi abs(b)
                                  D[X] = ----------
                                          sqrt(3)

 -- Function: skewness_logistic (<a>,<b>)
     Returns the skewness coefficient of a <Logistice(a,b) random
     variable , with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                      SK[X] = 0

 -- Function: kurtosis_logistic (<a>,<b>)
     Returns the kurtosis coefficient of a <Logistice(a,b) random
     variable , with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                              6
                                      KU[X] = -
                                              5

 -- Function: random_logistic (<a>,<b>)
          random_logistic (<a>,<b>,<n>)

     Returns a <Logistice(a,b) random variate, with b>0.  Calling
     ‘random_logistic’ with a third argument <n>, a random sample of
     size <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Pareto Random Variable,  Next: Weibull Random Variable,  Prev: Logistic Random Variable,  Up: Functions and Variables for continuous distributions

53.2.13 Pareto Random Variable
------------------------------

 -- Function: pdf_pareto (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Pareto(a,b)
     random variable, with a,b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                       [ a*b^a/x^(a+1)   for x >= b
          f(x, a, b) = [
                       [ 0               for x < b

 -- Function: cdf_pareto (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Pareto(a,b) random variable, with a,b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                       [ 1 - (b/x)^a     for x >= 0
          F(x, a, b) = [
                       [ 0               for x < 0

 -- Function: quantile_pareto (<q>,<a>,<b>)
     Returns the <q>-quantile of a Pareto(a,b) random variable, with
     a,b>0; in other words, this is the inverse of ‘cdf_pareto’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_pareto (<a>,<b>)
     Returns the mean of a Pareto(a,b) random variable, with a>1,b>0.
     To make use of this function, write first ‘load("distrib")’.

     The mean is E[X] = a*b/(a-1)

 -- Function: var_pareto (<a>,<b>)
     Returns the variance of a Pareto(a,b) random variable, with
     a>2,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The variance is

                                        2
                                     a b
                        V[X] = ----------------
                                              2
                               (a - 2) (a - 1)

 -- Function: std_pareto (<a>,<b>)
     Returns the standard deviation of a Pareto(a,b) random variable,
     with a>2,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                        a
                                 sqrt(-----) b
                                      a - 2
                          D[X] = -------------
                                     a - 1

 -- Function: skewness_pareto (<a>,<b>)
     Returns the skewness coefficient of a Pareto(a,b) random variable,
     with a>3,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                               2 sqrt(a - 2) (a + 1)
                       SK[X] = ---------------------
                                  (a - 3) sqrt(a)

 -- Function: kurtosis_pareto (<a>,<b>)
     Returns the kurtosis coefficient of a Pareto(a,b) random variable,
     with a>4,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                  3    2
                              6 (a  + a  - 6 a - 2)
                      KU[X] = --------------------- - 3
                                    2
                                a (a  - 7 a + 12)

 -- Function: random_pareto (<a>,<b>)
          random_pareto (<a>,<b>,<n>)

     Returns a Pareto(a,b) random variate, with a>0,b>0.  Calling
     ‘random_pareto’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Weibull Random Variable,  Next: Rayleigh Random Variable,  Prev: Pareto Random Variable,  Up: Functions and Variables for continuous distributions

53.2.14 Weibull Random Variable
-------------------------------

 -- Function: pdf_weibull (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Weibull(a,b)
     random variable, with a,b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                       [                       a
                       [      x a - 1   - (x/b)
                       [   a (-)      %e         unit_step(x)
                       [      b
                       [   ----------------------------------   for x >= 0
                       [                   b
          f(x, a, b) = [
                       [ 0                                      for x < 0

 -- Function: cdf_weibull (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Weibull(a,b) random variable, with a,b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                       [ 1 - exp(-(x/b)^a)      for x >= 0
          F(x, a, b) = [
                       [ 0                      for x < 0

 -- Function: quantile_weibull (<q>,<a>,<b>)
     Returns the <q>-quantile of a Weibull(a,b) random variable, with
     a,b>0; in other words, this is the inverse of ‘cdf_weibull’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_weibull (<a>,<b>)
     Returns the mean of a Weibull(a,b) random variable, with a,b>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                             1
                                E[X] = gamma(- + 1) b
                                             a

 -- Function: var_weibull (<a>,<b>)
     Returns the variance of a Weibull(a,b) random variable, with a,b>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                   2             2 1        2
                     V[X] = (gamma(- + 1) - gamma (- + 1)) b
                                   a               a

 -- Function: std_weibull (<a>,<b>)
     Returns the standard deviation of a Weibull(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The variance is

                                       2             2 1
                     D[X] = sqrt(gamma(- + 1) - gamma (- + 1)) b
                                       a               a

 -- Function: skewness_weibull (<a>,<b>)
     Returns the skewness coefficient of a Weibull(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                        3                1            2               3 1
                  gamma(- + 1) - 3 gamma(- + 1) gamma(- + 1) + 2 gamma (- + 1)
                        a                a            a                 a
          SK[X] = ------------------------------------------------------------
                                      2             2 1      3/2
                               (gamma(- + 1) - gamma (- + 1))
                                      a               a

 -- Function: kurtosis_weibull (<a>,<b>)
     Returns the kurtosis coefficient of a Weibull(a,b) random variable,
     with a,b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                          4                1            3
           KU[X] = (gamma(- + 1) - 4 gamma(- + 1) gamma(- + 1)
                          a                a            a
                    2 1            2               4 1
           + 6 gamma (- + 1) gamma(- + 1) - 3 gamma (- + 1))
                      a            a                 a
                  2             2 1      2
          /(gamma(- + 1) - gamma (- + 1))  - 3
                  a               a

 -- Function: random_weibull (<a>,<b>)
          random_weibull (<a>,<b>,<n>)

     Returns a Weibull(a,b) random variate, with a,b>0.  Calling
     ‘random_weibull’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Rayleigh Random Variable,  Next: Laplace Random Variable,  Prev: Weibull Random Variable,  Up: Functions and Variables for continuous distributions

53.2.15 Rayleigh Random Variable
--------------------------------

The _Rayleigh_ distribution coincides with the chi-squared distribution
with two degrees of freedom.

 -- Function: pdf_rayleigh (<x>,<b>)
     Returns the value at <x> of the density function of a Rayleigh(b)
     random variable, with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The pdf is

                    [ 2*b^2*x*exp(-b^2*x^2)    for x>= 0
          f(x, b) = [
                    [ 0                        otherwise

          (%i1) load ("distrib")$
          (%i2) pdf_rayleigh(x,b);
                                        2  2
                               2     - b  x
          (%o2)             2 b  x %e        unit_step(x)

 -- Function: cdf_rayleigh (<x>,<b>)
     Returns the value at <x> of the distribution function of a
     Rayleigh(b) random variable, with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The cdf is

                    [ 1 - exp(-b^2*x^2)    for x >= 0
          F(x, b) = [
                    [ 0                    for x < 0

          (%i1) load ("distrib")$
          (%i2) cdf_rayleigh(x,b);
                                      2  2
                                   - b  x
          (%o2)             (1 - %e       ) unit_step(x)

 -- Function: quantile_rayleigh (<q>,<b>)
     Returns the <q>-quantile of a Rayleigh(b) random variable, with
     b>0; in other words, this is the inverse of ‘cdf_rayleigh’.
     Argument <q> must be an element of [0,1].

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

          (%i1) load ("distrib")$
          (%i2) quantile_rayleigh(0.99,b);
                                  2.145966026289347
          (%o2)                   -----------------
                                          b

 -- Function: mean_rayleigh (<b>)
     Returns the mean of a Rayleigh(b) random variable, with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The mean is

                                         sqrt(%pi)
                                  E[X] = ---------
                                            2 b

          (%i1) load ("distrib")$
          (%i2) mean_rayleigh(b);
                                      sqrt(%pi)
          (%o2)                       ---------
                                         2 b

 -- Function: var_rayleigh (<b>)
     Returns the variance of a Rayleigh(b) random variable, with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The variance is

                                              %pi
                                          1 - ---
                                               4
                                   V[X] = -------
                                             2
                                            b

          (%i1) load ("distrib")$
          (%i2) var_rayleigh(b);
                                           %pi
                                       1 - ---
                                            4
          (%o2)                        -------
                                          2
                                         b

 -- Function: std_rayleigh (<b>)
     Returns the standard deviation of a Rayleigh(b) random variable,
     with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The standard deviation is

                                               %pi
                                      sqrt(1 - ---)
                                                4
                               D[X] = -------------
                                            b

          (%i1) load ("distrib")$
          (%i2) std_rayleigh(b);
                                             %pi
                                    sqrt(1 - ---)
                                              4
          (%o2)                     -------------
                                          b

 -- Function: skewness_rayleigh (<b>)
     Returns the skewness coefficient of a Rayleigh(b) random variable,
     with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The skewness coefficient is

                                      3/2
                                   %pi      3 sqrt(%pi)
                                   ------ - -----------
                                     4           4
                           SK[X] = --------------------
                                            %pi 3/2
                                       (1 - ---)
                                             4

          (%i1) load ("distrib")$
          (%i2) skewness_rayleigh(b);
                                   3/2
                                %pi      3 sqrt(%pi)
                                ------ - -----------
                                  4           4
          (%o2)                 --------------------
                                         %pi 3/2
                                    (1 - ---)
                                          4

 -- Function: kurtosis_rayleigh (<b>)
     Returns the kurtosis coefficient of a Rayleigh(b) random variable,
     with b>0.

     The Rayleigh(b) random variable is equivalent to the Weibull(2,1/b)
     .

     The kurtosis coefficient is

                                               2
                                          3 %pi
                                      2 - ------
                                            16
                              KU[X] = ---------- - 3
                                           %pi 2
                                      (1 - ---)
                                            4

          (%i1) load ("distrib")$
          (%i2) kurtosis_rayleigh(b);
                                            2
                                       3 %pi
                                   2 - ------
                                         16
          (%o2)                    ---------- - 3
                                        %pi 2
                                   (1 - ---)
                                         4

 -- Function: random_rayleigh (<b>)
          random_rayleigh (<b>,<n>)

     Returns a Rayleigh(b) random variate, with b>0.  Calling
     ‘random_rayleigh’ with a second argument <n>, a random sample of
     size <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Laplace Random Variable,  Next: Cauchy Random Variable,  Prev: Rayleigh Random Variable,  Up: Functions and Variables for continuous distributions

53.2.16 Laplace Random Variable
-------------------------------

The _Laplace_ distribution is a continuous probability distribution that
is sometimes called the double exponential distribution because it can
be thought of as two exponential distributions spliced back to back.

 -- Function: pdf_laplace (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Laplace(a,b)
     random variable, with b>0.  To make use of this function, write
     first ‘load("distrib")’.

     Here, a is the location parameter (or mean), and b is the scale
     parameter, related to the variance.

     The pdf is

                                     abs(x - a)
                                   - ----------
                                         b
                                 %e
                    f(x, a, b) = --------------
                                      2 b
     1/(2*b)*exp(-abs(x-a)/b)

 -- Function: cdf_laplace (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Laplace(a,b) random variable, with b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                       [ 1/2*exp((x-a)/b)     for x < a
          F(x, a, b) = [
                       [ 1-1/2*exp((x-a)/b)   for x >= a

 -- Function: quantile_laplace (<q>,<a>,<b>)
     Returns the <q>-quantile of a Laplace(a,b) random variable, with
     b>0; in other words, this is the inverse of ‘cdf_laplace’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_laplace (<a>,<b>)
     Returns the mean of a Laplace(a,b) random variable, with b>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                      E[X] = a

 -- Function: var_laplace (<a>,<b>)
     Returns the variance of a Laplace(a,b) random variable, with b>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                               2
                                     V[X] = 2 b

 -- Function: std_laplace (<a>,<b>)
     Returns the standard deviation of a Laplace(a,b) random variable,
     with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                  D[X] = sqrt(2) b

 -- Function: skewness_laplace (<a>,<b>)
     Returns the skewness coefficient of a Laplace(a,b) random variable,
     with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                      SK[X] = 0

 -- Function: kurtosis_laplace (<a>,<b>)
     Returns the kurtosis coefficient of a Laplace(a,b) random variable,
     with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                      KU[X] = 3

 -- Function: random_laplace (<a>,<b>)
          random_laplace (<a>,<b>,<n>)

     Returns a Laplace(a,b) random variate, with b>0.  Calling
     ‘random_laplace’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Cauchy Random Variable,  Next: Gumbel Random Variable,  Prev: Laplace Random Variable,  Up: Functions and Variables for continuous distributions

53.2.17 Cauchy Random Variable
------------------------------

The _Cauchy_ distribution (also known as the Lorentz distribution) is
the distribution of of the ratio of two independent normally distributed
random variables with mean zero.

   Note that the mean, variance, standard deviation, skewness
coefficient, and kurtosis coefficient are all undefined for the Cauchy
distribution.  The integrals do not converge in this case.

 -- Function: pdf_cauchy (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Cauchy(a,b)
     random variable, with b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                                      b
                f(x, a, b) = -------------------
                                         2    2
                             %pi ((x - a)  + b )

 -- Function: cdf_cauchy (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Cauchy(a,b) random variable, with b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                                               x - a
                                          atan(-----)
                                                 b      1
                             F(x, a, b) = ----------- + -
                                              %pi       2

 -- Function: quantile_cauchy (<q>,<a>,<b>)
     Returns the <q>-quantile of a Cauchy(a,b) random variable, with
     b>0; in other words, this is the inverse of ‘cdf_cauchy’.  Argument
     <q> must be an element of [0,1].  To make use of this function,
     write first ‘load("distrib")’.

 -- Function: random_cauchy (<a>,<b>)
          random_cauchy (<a>,<b>,<n>)

     Returns a Cauchy(a,b) random variate, with b>0.  Calling
     ‘random_cauchy’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Gumbel Random Variable,  Prev: Cauchy Random Variable,  Up: Functions and Variables for continuous distributions

53.2.18 Gumbel Random Variable
------------------------------

 -- Function: pdf_gumbel (<x>,<a>,<b>)
     Returns the value at <x> of the density function of a Gumbel(a,b)
     random variable, with b>0.  To make use of this function, write
     first ‘load("distrib")’.

     The pdf is

                                       a - x
                                       -----
                             a - x       b
                             ----- - %e
                               b
                           %e
              f(x, a, b) = -----------------
                                   b

 -- Function: cdf_gumbel (<x>,<a>,<b>)
     Returns the value at <x> of the distribution function of a
     Gumbel(a,b) random variable, with b>0.  To make use of this
     function, write first ‘load("distrib")’.

     The cdf is

                                 a - x
                                 -----
                                   b
                             - %e
              F(x, a, b) = %e

 -- Function: quantile_gumbel (<q>,<a>,<b>)
     Returns the <q>-quantile of a Gumbel(a,b) random variable, with
     b>0; in other words, this is the inverse of ‘cdf_gumbel’.  Argument
     <q> must be an element of [0,1].  To make use of this function,
     write first ‘load("distrib")’.

 -- Function: mean_gumbel (<a>,<b>)
     Returns the mean of a Gumbel(a,b) random variable, with b>0.

     The mean is

                                 E[X] = %gamma b + a

          (%i1) load ("distrib")$
          (%i2) mean_gumbel(a,b);
          (%o2)                     %gamma b + a
     where symbol ‘%gamma’ stands for the Euler-Mascheroni constant.
     See also ‘%gamma’.

 -- Function: var_gumbel (<a>,<b>)
     Returns the variance of a Gumbel(a,b) random variable, with b>0.
     To make use of this function, write first ‘load("distrib")’.

     The variance is

                                             2  2
                                          %pi  b
                                   V[X] = -------
                                             6

 -- Function: std_gumbel (<a>,<b>)
     Returns the standard deviation of a Gumbel(a,b) random variable,
     with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                           %pi b
                                   D[X] = -------
                                          sqrt(6)

 -- Function: skewness_gumbel (<a>,<b>)
     Returns the skewness coefficient of a Gumbel(a,b) random variable,
     with b>0.

     The skewness coefficient is

                                          3/2
                                       2 6    zeta(3)
                               SK[X] = --------------
                                               3
                                            %pi

          (%i1) load ("distrib")$
          (%i2) skewness_gumbel(a,b);
                                      3/2
                                   2 6    zeta(3)
          (%o2)                    --------------
                                           3
                                        %pi
     where ‘zeta’ stands for the Riemann's zeta function.

 -- Function: kurtosis_gumbel (<a>,<b>)
     Returns the kurtosis coefficient of a Gumbel(a,b) random variable,
     with b>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                             12
                                     KU[X] = --
                                             5

 -- Function: random_gumbel (<a>,<b>)
          random_gumbel (<a>,<b>,<n>)

     Returns a Gumbel(a,b) random variate, with b>0.  Calling
     ‘random_gumbel’ with a third argument <n>, a random sample of size
     <n> will be simulated.

     The implemented algorithm is based on the general inverse method.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Functions and Variables for discrete distributions,  Prev: Functions and Variables for continuous distributions,  Up: Package distrib

53.3 Functions and Variables for discrete distributions
=======================================================

Maxima knows the following kinds of discrete distributions

* Menu:

* General Finite Discrete Random Variable::
* Binomial Random Variable::
* Poisson Random Variable::
* Bernoulli Random Variable::
* Geometric Random Variable::
* Discrete Uniform Random Variable::
* Hypergeometric Random Variable::
* Negative Binomial Random Variable::


File: maxima.info,  Node: General Finite Discrete Random Variable,  Next: Binomial Random Variable,  Prev: Functions and Variables for discrete distributions,  Up: Functions and Variables for discrete distributions

53.3.1 General Finite Discrete Random Variable
----------------------------------------------

 -- Function: pdf_general_finite_discrete (<x>,<v>)
     Returns the value at <x> of the probability function of a general
     finite discrete random variable, with vector probabilities v, such
     that ‘Pr(X=i) = v_i’.  Vector v can be a list of nonnegative
     expressions, whose components will be normalized to get a vector of
     probabilities.  To make use of this function, write first
     ‘load("distrib")’.

          (%i1) load ("distrib")$
          (%i2) pdf_general_finite_discrete(2, [1/7, 4/7, 2/7]);
                                          4
          (%o2)                           -
                                          7
          (%i3) pdf_general_finite_discrete(2, [1, 4, 2]);
                                          4
          (%o3)                           -
                                          7

 -- Function: cdf_general_finite_discrete (<x>,<v>)
     Returns the value at <x> of the distribution function of a general
     finite discrete random variable, with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

          (%i1) load ("distrib")$
          (%i2) cdf_general_finite_discrete(2, [1/7, 4/7, 2/7]);
                                          5
          (%o2)                           -
                                          7
          (%i3) cdf_general_finite_discrete(2, [1, 4, 2]);
                                          5
          (%o3)                           -
                                          7
          (%i4) cdf_general_finite_discrete(2+1/2, [1, 4, 2]);
                                          5
          (%o4)                           -
                                          7

 -- Function: quantile_general_finite_discrete (<q>,<v>)
     Returns the <q>-quantile of a general finite discrete random
     variable, with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: mean_general_finite_discrete (<v>)
     Returns the mean of a general finite discrete random variable, with
     vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: var_general_finite_discrete (<v>)
     Returns the variance of a general finite discrete random variable,
     with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: std_general_finite_discrete (<v>)
     Returns the standard deviation of a general finite discrete random
     variable, with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: skewness_general_finite_discrete (<v>)
     Returns the skewness coefficient of a general finite discrete
     random variable, with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: kurtosis_general_finite_discrete (<v>)
     Returns the kurtosis coefficient of a general finite discrete
     random variable, with vector probabilities v.

     See ‘pdf_general_finite_discrete’ for more details.

 -- Function: random_general_finite_discrete (<v>)
          random_general_finite_discrete (<v>,<m>)

     Returns a general finite discrete random variate, with vector
     probabilities v.  Calling ‘random_general_finite_discrete’ with a
     second argument <m>, a random sample of size <m> will be simulated.

     See ‘pdf_general_finite_discrete’ for more details.

          (%i1) load ("distrib")$
          (%i2) random_general_finite_discrete([1,3,1,5]);
          (%o2)                           4
          (%i3) random_general_finite_discrete([1,3,1,5], 10);
          (%o3)            [3, 4, 3, 4, 4, 4, 4, 2, 4, 4]


File: maxima.info,  Node: Binomial Random Variable,  Next: Poisson Random Variable,  Prev: General Finite Discrete Random Variable,  Up: Functions and Variables for discrete distributions

53.3.2 Binomial Random Variable
-------------------------------

The _binomial distribution_ with parameters n and p is a discrete
probability distribution.  It consists of n independent experiments
where each experiment consists of a Boolean-valued outcome where a
success occurs with a probablity p.

   For example, a biased coin that comes up heads with probablity p is
tossed n times.  Then the probability of exactly k heads in n tosses is
given by the binomial distribution.

 -- Function: pdf_binomial (<x>,<n>,<p>)
     Returns the value at <x> of the probability function of a
     Binomial(n,p) random variable, with 0 \leq p \leq 1 and n a
     positive integer.  To make use of this function, write first
     ‘load("distrib")’.

     The pdf is

                                                         n - x  x
                      f(x, n, p) = binomial(n, x) (1 - p)      p

 -- Function: cdf_binomial (<x>,<n>,<p>)
     Returns the value at <x> of the distribution function of a
     Binomial(n,p) random variable, with 0 \leq p \leq 1 and n a
     positive integer.

     The cdf is

          F(x, n, p) = beta_incomplete_regularized(n - floor(x), floor(x) + 1,
                                                                            1 - p)

          (%i1) load ("distrib")$
          (%i2) cdf_binomial(5,7,1/6);
                                        7775
          (%o2)                         ----
                                        7776
          (%i3) float(%);
          (%o3)                  0.9998713991769548

 -- Function: quantile_binomial (<q>,<n>,<p>)
     Returns the <q>-quantile of a Binomial(n,p) random variable, with 0
     \leq p \leq 1 and n a positive integer; in other words, this is the
     inverse of ‘cdf_binomial’.  Argument <q> must be an element of
     [0,1].  To make use of this function, write first
     ‘load("distrib")’.

 -- Function: mean_binomial (<n>,<p>)
     Returns the mean of a Binomial(n,p) random variable, with 0 \leq p
     \leq 1 and n a positive integer.  To make use of this function,
     write first ‘load("distrib")’.

     The mean is

                                      E[X] = n p

 -- Function: var_binomial (<n>,<p>)
     Returns the variance of a Binomial(n,p) random variable, with 0
     \leq p \leq 1 and n a positive integer.  To make use of this
     function, write first ‘load("distrib")’.

     The variance is

                                 V[X] = n (1 - p) p

 -- Function: std_binomial (<n>,<p>)
     Returns the standard deviation of a Binomial(n,p) random variable,
     with 0 \leq p \leq 1 and n a positive integer.  To make use of this
     function, write first ‘load("distrib")’.

     The standard deviation is

                              D[X] = sqrt(n (1 - p) p)

 -- Function: skewness_binomial (<n>,<p>)
     Returns the skewness coefficient of a Binomial(n,p) random
     variable, with 0 \leq p \leq 1 and n a positive integer.  To make
     use of this function, write first ‘load("distrib")’.

     The skewness coefficient is

                                           1 - 2 p
                              SK[X] = -----------------
                                      sqrt(n (1 - p) p)

 -- Function: kurtosis_binomial (<n>,<p>)
     Returns the kurtosis coefficient of a Binomial(n,p) random
     variable, with 0 \leq p \leq 1 and n a positive integer.  To make
     use of this function, write first ‘load("distrib")’.

     The kurtosis coefficient is

                                       1 - 6 (1 - p) p
                               KU[X] = ---------------
                                         n (1 - p) p

 -- Function: random_binomial (<n>,<p>)
          random_binomial (<n>,<p>,<m>)

     Returns a Binomial(n,p) random variate, with 0 \leq p \leq 1 and n
     a positive integer.  Calling ‘random_binomial’ with a third
     argument <m>, a random sample of size <m> will be simulated.

     The implemented algorithm is based on the one described in
     Kachitvichyanukul, V. and Schmeiser, B.W. (1988) <Binomial Random
     Variate Generation>.  Communications of the ACM, 31, Feb., 216.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Poisson Random Variable,  Next: Bernoulli Random Variable,  Prev: Binomial Random Variable,  Up: Functions and Variables for discrete distributions

53.3.3 Poisson Random Variable
------------------------------

The _Poisson distribution_ is a discrete probability distribution.  It
is the probability that a given number of events occur in a fixed
interval when the events occur independently of the time of the last
event, and the events occur with a known constant rate.

 -- Function: pdf_poisson (<x>,<m>)
     Returns the value at <x> of the probability function of a
     Poisson(m) random variable, with m>0.  To make use of this
     function, write first ‘load("distrib")’.

     The pdf is

                                             x   - m
                                            m  %e
                                  f(x, m) = --------
                                               x!

 -- Function: cdf_poisson (<x>,<m>)
     Returns the value at <x> of the distribution function of a
     Poisson(m) random variable, with m>0.

     The cdf is

                F(x, m) = gamma_incomplete_regularized(floor(x) + 1, m)

          (%i1) load ("distrib")$
          (%i2) cdf_poisson(3,5);
          (%o2)          gamma_incomplete_regularized(4, 5)
          (%i3) float(%);
          (%o3)                  0.2650259152973619

 -- Function: quantile_poisson (<q>,<m>)
     Returns the <q>-quantile of a Poisson(m) random variable, with m>0;
     in other words, this is the inverse of ‘cdf_poisson’.  Argument <q>
     must be an element of [0,1].  To make use of this function, write
     first ‘load("distrib")’.

 -- Function: mean_poisson (<m>)
     Returns the mean of a Poisson(m) random variable, with m>0.  To
     make use of this function, write first ‘load("distrib")’.

     The mean is

                                      E[X] = m

 -- Function: var_poisson (<m>)
     Returns the variance of a Poisson(m) random variable, with m>0.  To
     make use of this function, write first ‘load("distrib")’.

     The variance is

                                      V[X] = m

 -- Function: std_poisson (<m>)
     Returns the standard deviation of a Poisson(m) random variable,
     with m>0.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                   D[X] = sqrt(m)

 -- Function: skewness_poisson (<m>)
     Returns the skewness coefficient of a Poisson(m) random variable,
     with m>0.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness is

                                              1
                                   SK[X] = -------
                                           sqrt(m)

 -- Function: kurtosis_poisson (<m>)
     Returns the kurtosis coefficient of a Poisson random variable
     Poi(m), with m>0.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                              1
                                      KU[X] = -
                                              m

 -- Function: random_poisson (<m>)
          random_poisson (<m>,<n>)

     Returns a Poisson(m) random variate, with m>0.  Calling
     ‘random_poisson’ with a second argument <n>, a random sample of
     size <n> will be simulated.

     The implemented algorithm is the one described in Ahrens, J.H. and
     Dieter, U. (1982) <Computer Generation of Poisson Deviates From
     Modified Normal Distributions>.  ACM Trans.  Math.  Software, 8, 2,
     June,163-179.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Bernoulli Random Variable,  Next: Geometric Random Variable,  Prev: Poisson Random Variable,  Up: Functions and Variables for discrete distributions

53.3.4 Bernoulli Random Variable
--------------------------------

The _Bernoulli distribution_ is a discrete probability distribution
which takes on two values, 0 and 1.  The value 1 occurs with probability
p, and 0 occurs with probabilty 1-p.

   It is equivalent to the Binomial(1,p) distribution (*note Binomial
Random Variable::)

 -- Function: pdf_bernoulli (<x>,<p>)
     Returns the value at <x> of the probability function of a
     Bernoulli(p) random variable, with 0 \leq p \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The mean is

                                                 1 - x  x
                                f(x, p) = (1 - p)      p

          (%i1) load ("distrib")$
          (%i2) pdf_bernoulli(1,p);
          (%o2)                           p

 -- Function: cdf_bernoulli (<x>,<p>)
     Returns the value at <x> of the distribution function of a
     Bernoulli(p) random variable, with 0 \leq p \leq 1.  To make use of
     this function, write first ‘load("distrib")’.

     The cdf is

           F(x, n, p) = beta_incomplete_regularized(n - floor(x), floor(x) + 1,
                                                                              1 - p)

 -- Function: quantile_bernoulli (<q>,<p>)
     Returns the <q>-quantile of a Bernoulli(p) random variable, with 0
     \leq p \leq 1; in other words, this is the inverse of
     ‘cdf_bernoulli’.  Argument <q> must be an element of [0,1].  To
     make use of this function, write first ‘load("distrib")’.

 -- Function: mean_bernoulli (<p>)
     Returns the mean of a Bernoulli(p) random variable, with 0 \leq p
     \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The mean is

                                      E[X] = p

          (%i1) load ("distrib")$
          (%i2) mean_bernoulli(p);
          (%o2)                           p

 -- Function: var_bernoulli (<p>)
     Returns the variance of a Bernoulli(p) random variable, with 0 \leq
     p \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The variance is

                                  V[X] = (1 - p) p

          (%i1) load ("distrib")$
          (%i2) var_bernoulli(p);
          (%o2)                       (1 - p) p

 -- Function: std_bernoulli (<p>)
     Returns the standard deviation of a Bernoulli(p) random variable,
     with 0 \leq p \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The standard deviation is

                               D[X] = sqrt((1 - p) p)

          (%i1) load ("distrib")$
          (%i2) std_bernoulli(p);
          (%o2)                    sqrt((1 - p) p)

 -- Function: skewness_bernoulli (<p>)
     Returns the skewness coefficient of a Bernoulli(p) random variable,
     with 0 \leq p \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The skewness coefficient is

                                           1 - 2 p
                               SK[X] = ---------------
                                       sqrt((1 - p) p)

          (%i1) load ("distrib")$
          (%i2) skewness_bernoulli(p);
                                       1 - 2 p
          (%o2)                    ---------------
                                   sqrt((1 - p) p)

 -- Function: kurtosis_bernoulli (<p>)
     Returns the kurtosis coefficient of a Bernoulli(p) random variable,
     with 0 \leq p \leq 1.

     The Bernoulli(p) random variable is equivalent to the Binomial(1,p)
     .

     The kurtosis coefficient is

                                       1 - 6 (1 - p) p
                               KU[X] = ---------------
                                          (1 - p) p

          (%i1) load ("distrib")$
          (%i2) kurtosis_bernoulli(p);
                                   1 - 6 (1 - p) p
          (%o2)                    ---------------
                                      (1 - p) p

 -- Function: random_bernoulli (<p>)
          random_bernoulli (<p>,<n>)

     Returns a Bernoulli(p) random variate, with 0 \leq p \leq 1.
     Calling ‘random_bernoulli’ with a second argument <n>, a random
     sample of size <n> will be simulated.

     This is a direct application of the ‘random’ built-in Maxima
     function.

     See also ‘random’.  To make use of this function, write first
     ‘load("distrib")’.


File: maxima.info,  Node: Geometric Random Variable,  Next: Discrete Uniform Random Variable,  Prev: Bernoulli Random Variable,  Up: Functions and Variables for discrete distributions

53.3.5 Geometric Random Variable
--------------------------------

The _Geometric distibution_ is a discrete probability distribution.  It
is the distribution of the number Bernoulli trials that fail before the
first success.

   Consider flipping a biased coin where heads occurs with probablity p.
Then the probability of k-1 tails in a row followed by heads is given by
the Geometric(p) distribution.

 -- Function: pdf_geometric (<x>,<p>)
     Returns the value at <x> of the probability function of a
     Geometric(p) random variable, with 0 < p \leq 1

     The pdf is

                                                  x
                                 f(x, p) = (1 - p)  p

     This is interpreted as the probability of x failures before the
     first success.

     ‘load("distrib")’ loads this function.

 -- Function: cdf_geometric (<x>,<p>)
     Returns the value at <x> of the distribution function of a
     Geometric(p) random variable, with 0 < p \leq 1

     The cdf is

                                                floor(x) + 1
                           F(x, p) = 1 - (1 - p)

     ‘load("distrib")’ loads this function.

 -- Function: quantile_geometric (<q>,<p>)
     Returns the <q>-quantile of a Geometric(p) random variable, with 0
     < p <= 1 ; in other words, this is the inverse of ‘cdf_geometric’.
     Argument <q> must be an element of [0,1].

     The probability from which the quantile is derived is defined as p
     (1 - p)^x.  This is interpreted as the probability of x failures
     before the first success.

     ‘load("distrib")’ loads this function.

 -- Function: mean_geometric (<p>)
     Returns the mean of a Geometric(p) random variable, with 0 < p \leq
     1.

     The mean is

                                           1
                                    E[X] = - - 1
                                           p

     The probability from which the mean is derived is defined as p (1 -
     p)^x.  This is interpreted as the probability of x failures before
     the first success.

     ‘load("distrib")’ loads this function.

 -- Function: var_geometric (<p>)
     Returns the variance of a Geometric(p) random variable, with 0 < p
     \leq 1.

     The variance is

                                           1 - p
                                    V[X] = -----
                                             2
                                            p

     ‘load("distrib")’ loads this function.

 -- Function: std_geometric (<p>)
     Returns the standard deviation of a Geometric(p) random variable,
     with 0 < p \leq 1.

                                        sqrt(1 - p)
                                 D[X] = -----------
                                             p

     ‘load("distrib")’ loads this function.

 -- Function: skewness_geometric (<p>)
     Returns the skewness coefficient of a Geometric(p) random variable,
     with 0 < p \leq 1.

     The skewness coefficient is

                                            2 - p
                                 SK[X] = -----------
                                         sqrt(1 - p)

     ‘load("distrib")’ loads this function.

 -- Function: kurtosis_geometric (<p>)
     Returns the kurtosis coefficient of a geometric random variable
     Geometric(p) , with 0 < p \leq 1.

     The kurtosis coefficient is

                                         2
                                        p  - 6 p + 6
                                KU[X] = ------------
                                           1 - p

     ‘load("distrib")’ loads this function.

 -- Function: random_geometric (<p>)
          random_geometric (<p>,<n>)

     ‘random_geometric(<p>)’ returns one random sample from a
     Geometric(p) distribution, with 0 < p <= 1 .

     ‘random_geometric(<p>, <n>)’ returns a list of <n> random samples.

     The algorithm is based on simulation of Bernoulli trials.

     The probability from which the random sample is derived is defined
     as p (1 - p)^x.  This is interpreted as the probability of x
     failures before the first success.

     ‘load("distrib")’ loads this function.


File: maxima.info,  Node: Discrete Uniform Random Variable,  Next: Hypergeometric Random Variable,  Prev: Geometric Random Variable,  Up: Functions and Variables for discrete distributions

53.3.6 Discrete Uniform Random Variable
---------------------------------------

The _Discrete uniform distribution_ is a discrete probablity
distribution where a finite number of values are equally likely to
occur.  The values are 1,2,3,...,n.

   For example throwing a fair die of 6 sides numbered 1 through 6
follows a DiscreteUniform(1/6) distribution.

 -- Function: pdf_discrete_uniform (<x>,<n>)
     Returns the value at <x> of the probability function of a
     DiscreteUniform(n) random variable, with n a strictly positive
     integer.  To make use of this function, write first
     ‘load("distrib")’.

     The pdf is

                                                 1
                                       f(x, n) = -
                                                 n

 -- Function: cdf_discrete_uniform (<x>,<n>)
     Returns the value at <x> of the distribution function of a
     DiscreteUniform(n) random variable, with n a strictly positive
     integer.  To make use of this function, write first
     ‘load("distrib")’.

     The cdf is

                                            floor(x)
                                  F(x, n) = --------
                                               n

 -- Function: quantile_discrete_uniform (<q>,<n>)
     Returns the <q>-quantile of a DiscreteUniform(n) random variable,
     with n a strictly positive integer; in other words, this is the
     inverse of ‘cdf_discrete_uniform’.  Argument <q> must be an element
     of [0,1].  To make use of this function, write first
     ‘load("distrib")’.

 -- Function: mean_discrete_uniform (<n>)
     Returns the mean of a DiscreteUniform(n) random variable, with n a
     strictly positive integer.  To make use of this function, write
     first ‘load("distrib")’.

     The mean is

                                           n + 1
                                    E[X] = -----
                                             2

 -- Function: var_discrete_uniform (<n>)
     Returns the variance of a DiscreteUniform(n) random variable, with
     n a strictly positive integer.  To make use of this function, write
     first ‘load("distrib")’.

     The variance is

                                            2
                                           n  - 1
                                    V[X] = ------
                                             12

 -- Function: std_discrete_uniform (<n>)
     Returns the standard deviation of a DiscreteUniform(n) random
     variable, with n a strictly positive integer.  To make use of this
     function, write first ‘load("distrib")’.

     The standard deviation is

                                              2
                                        sqrt(n  - 1)
                                 D[X] = ------------
                                         2 sqrt(3)

 -- Function: skewness_discrete_uniform (<n>)
     Returns the skewness coefficient of a DiscreteUniform(n) random
     variable, with n a strictly positive integer.  To make use of this
     function, write first ‘load("distrib")’.

     The skewness coefficient is

                                      SK[X] = 0

 -- Function: kurtosis_discrete_uniform (<n>)
     Returns the kurtosis coefficient of a DiscreteUniform(n) random
     variable, with n a strictly positive integer.  To make use of this
     function, write first ‘load("distrib")’.

     The kurtosis coefficient is

                                              2
                                          6 (n  + 1)
                             KU[X] = - -----------------
                                       5 (n - 1) (n + 1)


 -- Function: random_discrete_uniform (<n>)
          random_discrete_uniform (<n>,<m>)

     Returns a DiscreteUniform(n) random variate, with n a strictly
     positive integer.  Calling ‘random_discrete_uniform’ with a second
     argument <m>, a random sample of size <m> will be simulated.

     This is a direct application of the ‘random’ built-in Maxima
     function.

     See also ‘random’.  To make use of this function, write first
     ‘load("distrib")’.


File: maxima.info,  Node: Hypergeometric Random Variable,  Next: Negative Binomial Random Variable,  Prev: Discrete Uniform Random Variable,  Up: Functions and Variables for discrete distributions

53.3.7 Hypergeometric Random Variable
-------------------------------------

The _hypergeometric distribution_ is a discrete probability
distribution.

   Let n_1 be the number of objects of a class A and n_2 be the number
of objects of class B. We take out n objects, _without_ replacment.
Then the hypergeometric distribution is the probability that exactly k
objects are from class A. Of course n \leq n_1 + n_2.

 -- Function: pdf_hypergeometric (<x>,<n_1>,<n_2>,<n>)
     Returns the value at <x> of the probability function of a
     Hypergeometric(n1,n2,n)

     random variable, with n_1, n_2 and n non negative integers and
     n\leq n_1+n_2.  Being n_1 the number of objects of class A, n_2 the
     number of objects of class B, and n the size of the sample without
     replacement, this function returns the probability of event
     "exactly <x> objects are of class A".

     To make use of this function, write first ‘load("distrib")’.

     The pdf is

                                     binomial(n_1, x) binomial(n_2, n - x)
                 f(x, n_1, n_2, n) = -----------------------------------
                                            binomial(n_2 + n_1, n)

 -- Function: cdf_hypergeometric (<x>,<n_1>,<n_2>,<n>)
     Returns the value at <x> of the distribution function of a
     Hypergeometric(n1,n2,n)

     random variable, with n_1, n_2 and n non negative integers and
     n\leq n_1+n_2.  See ‘pdf_hypergeometric’ for a more complete
     description.

     To make use of this function, write first ‘load("distrib")’.

     The cdf is

                                floor(x)
                                ====
                                \
                                 >       binomial(n_1, k) binomial(n_2, n - k)
                                /
                                ====
                                k = 0
            F(x, n_1, n_2, n) = --------------------------------------------
                                            binomial(n_2 + n_1, n)

 -- Function: quantile_hypergeometric (<q>,<n1>,<n2>,<n>)
     Returns the <q>-quantile of a Hypergeometric(n1,n2,n) random
     variable, with <n1>, <n2> and <n> non negative integers and n\leq
     n1+n2; in other words, this is the inverse of ‘cdf_hypergeometric’.
     Argument <q> must be an element of [0,1].  To make use of this
     function, write first ‘load("distrib")’.

 -- Function: mean_hypergeometric (<n_1>,<n_2>,<n>)
     Returns the mean of a discrete uniform random variable
     Hypergeometric(n_1,n_2,n) , with n_1, n_2 and n non negative
     integers and n\leq n_1+n_2.  To make use of this function, write
     first ‘load("distrib")’.

     The mean is

                                           n n_1
                                   E[X] = -------
                                          n_2 + n_1


 -- Function: var_hypergeometric (<n1>,<n2>,<n>)
     Returns the variance of a hypergeometric random variable
     Hypergeometric(n_1,n_2,n) , with n_1, n_2 and n non negative
     integers and n <= n_1 + n_2 .  To make use of this function, write
     first ‘load("distrib")’.

     The variance is

                                  n n_1 n_2 (n_2 + n_1 - n)
                          V[X] = ----------------------------
                                                            2
                                 (n_2 + n_1 - 1) (n_2 + n_1)

 -- Function: std_hypergeometric (<n_1>,<n_2>,<n>)
     Returns the standard deviation of a Hypergeometric(n_1,n_2,n)
     random variable, with n_1, n_2 and n non negative integers and
     n\leq n_1+n_2.  To make use of this function, write first
     ‘load("distrib")’.

     The standard deviation is

                                    n n_1 n_2 (n_2 + n_1 - n)
                               sqrt(-------------------------)
                                          n_2 + n_1 - 1
                        D[X] = -------------------------------
                                          n_2 + n_1

 -- Function: skewness_hypergeometric (<n_1>,<n_2>,<n>)
     Returns the skewness coefficient of a Hypergeometric(n1,n2,n)
     random variable, with n_1, n_2 and n non negative integers and
     n\leq n1+n2.  To make use of this function, write first
     ‘load("distrib")’.

     The skewness coefficient is

                                                           n_2 + n_1 - 1
                  (n_2 - n_1) (n_2 + n_1 - 2 n) sqrt(-------------------------)
                                                     n n_1 n_2 (n_2 + n_1 - n)
          SK[X] = -------------------------------------------------------------
                                          n_2 + n_1 - 2


 -- Function: kurtosis_hypergeometric (<n_1>,<n_2>,<n>)
     Returns the kurtosis coefficient of a Hypergeometric(n_1,n_2,n)
     random variable, with n_1, n_2 and n non negative integers and
     n\leq n1+n2.  To make use of this function, write first
     ‘load("distrib")’.

     The kurtosis coefficient is

                                              2
          KU[X] = ((n_2 + n_1 - 1) (n_2 + n_1)
                                          2                          2
            3 n_1 n_2 ((n - 2) (n_2 + n_1)  + 6 n (n_2 + n_1 - n) - n  (n_2 + n_1))
           (-----------------------------------------------------------------------
                                                    2
                                         (n_2 + n_1)
           - 6 n (n_2 + n_1 - n) + (n_2 + n_1) (n_2 + n_1 + 1)))
          /(n n_1 n_2 (n_2 + n_1 - 3) (n_2 + n_1 - 2) (n_2 + n_1 - n)) - 3

 -- Function: random_hypergeometric (<n1>,<n2>,<n>)
          random_hypergeometric (<n1>,<n2>,<n>,<m>)

     Returns a Hypergeometric(n1,n2,n) random variate, with <n1>, <n2>
     and <n> non negative integers and n <= n_1 + n_2 .  Calling
     ‘random_hypergeometric’ with a fourth argument <m>, a random sample
     of size <m> will be simulated.

     Algorithm described in Kachitvichyanukul, V., Schmeiser, B.W.
     (1985) <Computer generation of hypergeometric random variates.>
     Journal of Statistical Computation and Simulation 22, 127-145.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Negative Binomial Random Variable,  Prev: Hypergeometric Random Variable,  Up: Functions and Variables for discrete distributions

53.3.8 Negative Binomial Random Variable
----------------------------------------

The _negative binomial distribution_ is a discrete probability
distribution.  Suppose we have a sequence of Bernoulli trials where each
trial has two outcomes called "success" and "failure" where "success"
occurs with probablity p and "failure" with probability 1-p.  We observe
the sequence until a predefined number r of sucesses have occurred.
Then the number of failures seen will have a NegativeBinomial(r,p)
distribution.

 -- Function: pdf_negative_binomial (<x>,<n>,<p>)
     Returns the value at <x> of the probability function of a
     NegativeBinomial(n,p) random variable, with 0 < p \leq 1 and n a
     positive number.  To make use of this function, write first
     ‘load("distrib")’.

     The pdf is

                                             x  n
                                      (1 - p)  p  gamma(x + n)
                         f(x, n, p) = ------------------------
                                            gamma(n) x!

 -- Function: cdf_negative_binomial (<x>,<n>,<p>)
     Returns the value at <x> of the distribution function of a
     NegativeBinomial(n,p) random variable, with 0 < p \leq 1 and n a
     positive number.

     The cdf is

             F(x, n, p) = beta_incomplete_regularized(n, floor(x) + 1, p)

          (%i1) load ("distrib")$
          (%i2) cdf_negative_binomial(3,4,1/8);
                                        3271
          (%o2)                        ------
                                       524288

 -- Function: quantile_negative_binomial (<q>,<n>,<p>)
     Returns the <q>-quantile of a NegativeBinomial(n,p) random
     variable, with 0 < p \leq 1 and n a positive number; in other
     words, this is the inverse of ‘cdf_negative_binomial’.  Argument
     <q> must be an element of [0,1].  To make use of this function,
     write first ‘load("distrib")’.

 -- Function: mean_negative_binomial (<n>,<p>)
     Returns the mean of a NegativeBinomial(n,p) random variable, with 0
     < p \leq 1 and n a positive number.  To make use of this function,
     write first ‘load("distrib")’.

     The mean is

                                         n (1 - p)
                                  E[X] = ---------
                                             p

 -- Function: var_negative_binomial (<n>,<p>)
     Returns the variance of a NegativeBinomial(n,p) random variable,
     with 0 < p \leq 1 and n a positive number.  To make use of this
     function, write first ‘load("distrib")’.

     The variance is

                                         n (1 - p)
                                  V[X] = ---------
                                             2
                                            p

 -- Function: std_negative_binomial (<n>,<p>)
     Returns the standard deviation of a NegativeBinomial(n,p) random
     variable, with 0 < p \leq 1 and n a positive number.  To make use
     of this function, write first ‘load("distrib")’.

     The standard deviation is

                                      sqrt(n (1 - p))
                               D[X] = ---------------
                                             p

 -- Function: skewness_negative_binomial (<n>,<p>)
     Returns the skewness coefficient of a NegativeBinomial(n,p) random
     variable, with 0 < p \leq 1 and n a positive number.  To make use
     of this function, write first ‘load("distrib")’.

     The skewness coefficient is

                                            2 - p
                               SK[X] = ---------------
                                       sqrt(n (1 - p))

 -- Function: kurtosis_negative_binomial (<n>,<p>)
     Returns the kurtosis coefficient of a NegativeBinomial(n,p) random
     variable, with 0 < p \leq 1 and n a positive number.  To make use
     of this function, write first ‘load("distrib")’.

     The kurtosis coefficient is

                                         2
                                        p  - 6 p + 6
                                KU[X] = ------------
                                         n (1 - p)

 -- Function: random_negative_binomial (<n>,<p>)
          random_negative_binomial (<n>,<p>,<m>)

     Returns a NegativeBinomial(n,p) random variate, with 0 < p \leq 1
     and n a positive number.  Calling ‘random_negative_binomial’ with a
     third argument <m>, a random sample of size <m> will be simulated.

     Algorithm described in Devroye, L. (1986) <Non-Uniform Random
     Variate Generation>.  Springer Verlag, p.  480.

     To make use of this function, write first ‘load("distrib")’.


File: maxima.info,  Node: Package draw,  Next: Package drawdf,  Prev: Package distrib,  Up: Top

54 Package draw
***************

* Menu:

* Introduction to draw::
* Functions and Variables for draw::
* Functions and Variables for pictures::
* Functions and Variables for worldmap::


File: maxima.info,  Node: Introduction to draw,  Next: Functions and Variables for draw,  Prev: Package draw,  Up: Package draw

54.1 Introduction to draw
=========================

‘draw’ is a Maxima-Gnuplot and a Maxima-VTK interface.

   There are three main functions to be used at Maxima level:
   • ‘draw2d’, draws a single 2D scene.
   • ‘draw3d’, draws a single 3D scene.
   • ‘draw’, can be filled with multiple ‘gr2d’ and ‘gr3d’ commands that
     each creates a draw scene all sharing the same window.
   Each scene can contain any number of objects and ‘key=value’ pairs
with options for the scene or the following objects.

   A selection of useful objects a scene can be made up from are:
   • ‘explicit’ plots a function.
   • ‘implicit’ plots all points an equation is true at.
   • ‘points’ plots points that are connected by lines if the option
     ‘points_joined’ was set to ‘true’ in a previous line of the current
     scene.
   • ‘parametric’ allows to specify separate expressions that calculate
     the x, y (and in 3d plots also for the z) variable.

   A short description of all draw commands and options including
example plots (in the html and pdf version of this manual) can be found
in the section *Note Functions and Variables for draw::.  An online
version of the html manual can be found at
<https://maxima.sourceforge.io/docs/manual/maxima_singlepage.html#draw>.
More elaborated examples of this package can be found at the following
locations:

   <http://riotorto.users.sourceforge.net/Maxima/gnuplot/>
<http://riotorto.users.sourceforge.net/Maxima/vtk/>

   Example:

     (%i1) draw2d(
               title="Two simple plots",
               xlabel="x",ylabel="y",grid=true,

               color=red,key="A sinus",
               explicit(sin(x),x,1,10),
               color=blue,line_type=dots,key="A cosinus",
               explicit(cos(x),x,1,10)
     )$
   (Figure draw_intro)

   You need Gnuplot 4.2 or newer to run draw; If you are using wxMaxima
as a front end ‘wxdraw’, ‘wxdraw2d’ and ‘wxdraw3d’ are drop-in
replacements for draw that do the same as ‘draw’, ‘draw2d’ and ‘draw3d’
but embed the resulting plot in the worksheet.

   If you want to use VTK with draw, you need VTK with the Python
interface installed (the *note Package dynamics:: uses VTK with the TCL
interface!)  and set the variable:

   ‘draw_renderer: 'vtk $’

