INDEX

EXPREAD _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

expread()

expreadreads one well-formed expression from the current input buffer and returns its value.

### examples:

    expread(); a+b;

      A + B

FACTORIZE

INDEX

FACTORIZE _ _ _ _ _ _ _ _ _ _ _ _ operator

The factorize operator factors a given expression into a list of {factor,power} pairs.

### syntax:

factorize(<expression>)

<expression> should be a polynomial, otherwise an error will result.

### examples:

    fff := factorize(x^3 - y^3);

             2          2
      		  {{X  + X*Y + Y ,1},{X - Y,1}}

    fac1 := first fff;

                 2          2
      FAC1 := {{X  + X*Y + Y ,1}

    factorize(x^15 - 1);

           8    7    6    5    4
       {{ X  - X  + X  - X  + X  - X + 1,1},
         4    3    2
       {X  + X  + X  + X + 1,1},
         2
       {X  + X + 1,1},
       {X - 1,1}}

    lastone := part(ws,length ws);

      	LASTONE := {X - 1,1}

    setmod 2;

      1

    on modular;

    factorize(x^15 - 1);

         4    3    2
      {{X  + X  + X  + X + 1,1},
         4    3
       {X  + X  + 1,1},
         4
       {X  + X + 1,1},
          2
       { X  + X + 1,1},
       {X + 1,1}}

The factorize command returns the factor,power pairs as a list. You can therefore use the usual list access methods ( first, second, third, rest, length and part) to extract these pairs.

If the <expression> given to factorize is an integer, it will be factored into its prime components. To factor any integer factor of a non-numerical expression, the switch ifactor should be turned on. Its default is off. ifactor has effect only when factoring is explicitly done by factorize, not when factoring is automatically done with the factor switch. If full factorization is not needed the switch limitedfactors allows you to reduce the computing time of calls to factorize.

Factoring can be done in a modular domain by calling factorize when modular is on. You can set the modulus with t he setmod command. The last example above shows factoring modulo 2.

For general comments on factoring, see comments under the switch factor.

HYPOT

INDEX

HYPOT _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

hypot(<expression>,<expression>)

If rounded is on, and the two arguments evaluate to numbers, this operator returns the square root of the sums of the squares of the arguments in a manner that avoids intermediate overflow. In other cases, an expression in the original operator is returned.

### examples:

    hypot(3,4);

      HYPOT(3,4)

    on rounded;

    ws;

      5.0

    hypot(a,b);

      HYPOT(A,B)

IMPART

INDEX

IMPART _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

impart(<expression>) or impart <simple\_expression >

This operator returns the imaginary part of an expression, if that argument has an numerical value. A non-numerical argument is returned as an expression in the operators repart and impart.

### examples:

    impart(1+i);

      1

    impart(a+i*b);

      REPART(B) + IMPART(A)

INT

INDEX

INT _ _ _ _ _ _ _ _ _ _ _ _ operator

The int operator performs analytic integration on a variety of functions.

### syntax:

int(<expression>,<kernel>)

<expression> can be any scalar expression. involving polynomials, log functions, exponential functions, or tangent or arctangent expressions. int attempts expressions involving error functions, dilogarithms and other trigonometric expressions. Integrals involving algebraic extensions (such as square roots) may not succeed. <kernel> must be a REDUCE kernel.

### examples:

    int(x**3 + 3,x);

          3
      X*(X  + 12)
      -----------
           4

    int(sin(x)*exp(2*x),x);

         2*X
        E   *(COS(X) - 2*SIN(X))
      - ------------------------
                   5

    int(1/(x^2-2),x);

      SQRT(2)*(LOG( - SQRT(2) + X) - LOG(SQRT(2) + X))
      ------------------------------------------------
                             4

    int(sin(x)/(4 + cos(x)**2),x);

             COS(X)
        ATAN(------)
               2
      - ------------
             2

    int(1/sqrt(x^2-x),x);

          SQRT(X)*SQRT(X - 1)
      INT(-------------------,X)
                  2
                 X -X

Note that REDUCE couldn't handle the last integral with its defaul t integrator, since the integrand involves a square root. However, the integral can be found using the algint package. Alternatively, you could add a rule using the let statement to evaluate this integral.

The arbitrary constant of integration is not shown. Definite integrals can be found by evaluating the result at the limits of integration (use rounded) and subtracting the lower from the h igher. Evaluation can be easily done by the sub operator.

When int cannot find an integral it returns an expression involving formal int expressions unless the switch failhard has been set. If not all of the expr ession can be integrated, the switch nolnr controls whether a partially integrated result should be returned or not.

INTERPOL

INDEX

INTERPOL _ _ _ _ _ _ _ _ _ _ _ _ operator

interpolgenerates an interpolation polynomial.

### syntax:

interpol(<values>,<variable>,<points>)

<values> and <points> are lists of equal length and <variable> is an algebraic expression (preferably a kernel). The interpolation polynomial is generated in the given variable of degree length(<values>)-1. The unique polynomial f is defined by the property that for corresponding elements v of <values> and p of <points> the relation f(p)=v holds.

### examples:

    f := for i:=1:4 collect(i**3-1);

      F := 0,7,26,63

    p := {1,2,3,4};

      P := 1,2,3,4

    interpol(f,x,p);

       3
      X  - 1

The Aitken-Neville interpolation algorithm is used which guarantee s a stable result even with rounded numbers and an ill-conditioned problem.

LCOF

INDEX

LCOF _ _ _ _ _ _ _ _ _ _ _ _ operator

The lcof operator returns the leading coefficient of a given expression with respect to a given variable.

### syntax:

lcof(<expression>,<kernel>)

<expression> is ordinarily a polynomial. If ratarg is on, a rational expression may also be used, otherwise an error results. <kernel> must be a kernel.

### examples:

    lcof((x+2*y)**5,y);

      32

    lcof((x + y*sin(x))**2 + cos(x)*sin(x)**2,sin(x));

            2
      COS(X)  + Y

    lcof(x**2 + 3*x + 17,y);

       2
      X  + 3*X + 17

If the kernel does not appear in the expression, lcof ret urns the expression.

LENGTH

INDEX

LENGTH _ _ _ _ _ _ _ _ _ _ _ _ operator

The length operator returns the number of items in a list, the number of terms in an expression, or the dimensions of an array or matrix.

### syntax:

length(<expr>) or length <expr>

<expr> can be a list structure, an array, a matrix, or a scalar expression .

### examples:

    alist := {a,b,{ww,xx,yy,zz}};

      ALIST := {A,B,{WW,XX,YY,ZZ}}

    length alist;

      3

    length third alist;

      4

    dlist := {d};

      DLIST := {D}

    length rest dlist;

      0

    matrix mmm(4,5);

    length mmm;

      {4,5}

    array aaa(5,3,2);

    length aaa;

      {6,4,3}

    eex := (x+3)**2/(x-y);

              2
             X  + 6*X + 9
      EEX := ------------
                X - Y

    length eex;

      5

An item in a list that is itself a list only counts as one item. A n error message will be printed if length is called on a matrix which has not had its dimensions set. The length of an array includes the zeroth element of each dimension, showing the full number of elements allocated. (Declaring an array A with n elements allocates A(0),A(1),...,A(n).) The length of an expression is the total number of additive terms appearing in the numerator and denominator of the expression. Note that subtraction of a term is represented internally as addition of a negative term.

LHS

INDEX

LHS _ _ _ _ _ _ _ _ _ _ _ _ operator

The lhs operator returns the left-hand side of an equation, such as those returned in a list by solve.

### syntax:

lhs(<equation>) or lhs <equation>

<equation> must be an equation of the form

left-hand side=right-hand side.

### examples:

    polly := (x+3)*(x^4+2x+1);

                5      4      2
      POLLY := X  + 3*X  + 2*X  + 7*X + 3

    pollyroots := solve(polly,x);

      POLLYROOTS := {X=ROOT F(X3 - X2 + X + 1,X ,
                           O                   )
                     X=-1,
                     X=-3}

    variable := lhs first pollyroots;

      VARIABLE := X

LIMIT

INDEX

LIMIT _ _ _ _ _ _ _ _ _ _ _ _ operator

LIMITS is a fast limit package for REDUCE for functions which are continuous except for computable poles and singularities, based on some earlier work by Ian Cohen and John P. Fitch. The Truncated Power Series package is used for non-critical points, at which the value of the function is the constant term in the expansion around that point. l'Hopital's rule is used in critical cases, with preprocessing of 1-1 forms and reformatting of product forms in order to apply l'Hopital's rule. A limited amount of bounded arithmetic is also employed where applicable.

### syntax:

limit(<expr>,<var>,<limpoint>) or

limit!+(<expr>,<var>,<limpoint>) or

limit!-(<expr>,<var>,<limpoint>)

where <expr> is an expression depending of the variable <var> (a kernel) and <limpoint> is the limit poi nt. If the limit depends upon the direction of approach to the <limpoint>, the operators limit!+ and limit!- may be used.

### examples:

    limit(x*cot(x),x,0);

      0

    limit((2x+5)/(3x-2),x,infinity);

      2
      --
      3

LPOWER

INDEX

LPOWER _ _ _ _ _ _ _ _ _ _ _ _ operator

The lpower operator returns the leading power of an expression with respect to a kernel. 1 is returned if the expression does not depend on the kernel.

### syntax:

lpower(<expression>,<kernel>)

<expression> is ordinarily a polynomial. If ratarg is on, a rational expression may also be used, otherwise an error results. <kernel> must be a kernel.

### examples:

    lpower((x+2*y)**6,y);

       6
      Y

    lpower((x + cos(x))**8 + df(x**2,x),cos(x));

            8
      COS(X)

    lpower(x**3 + 3*x,y);

      1

LTERM

INDEX

LTERM _ _ _ _ _ _ _ _ _ _ _ _ operator

The lterm operator returns the leading term of an expression with respect to a kernel. The expression is returned if it does not depend on the kernel.

### syntax:

lterm(<expression>,<kernel>)

<expression> is ordinarily a polynomial. If ratarg is on, a rational expression may also be used, otherwise an error results. <kernel> must be a kernel.

### examples:

    lterm((x+2*y)**6,y);

          6
      64*Y

    lterm((x + cos(x))**8 + df(x**2,x),cos(x));

            8
      COS(X)

    lterm(x**3 + 3*x,y);

       3
      X  + 3X

MAINVAR

INDEX

MAINVAR _ _ _ _ _ _ _ _ _ _ _ _ operator

The mainvar operator returns the main variable (in the system's internal representation) of its argument.

### syntax:

mainvar(<expression>)

<expression> is usually a polynomial, but may be any valid REDUCE scalar expression. In the case of a rational function, the main variable of the numerator is returned. The main variable returned is a kernel.

### examples:

    test := (a + b + c)**2;

               2                    2            2
      TEST := A  + 2*A*B + 2*A*C + B  + 2*B*C + C

    mainvar(test);

      A

    korder c,b,a;

    mainvar(test);

      C

    mainvar(2*cos(x)**2);

      COS(X)

    mainvar(17);

      0

The main variable is the first variable in the canonical ordering of kernels. Generally, alphabetically ordered functions come first, then alphabetically ordered identifiers (variables). Numbers come last, and as far as mainvar is concerned belong in the family 0. The canonical ordering can be changed by the declaration korder, as shown above.

MAP

INDEX

MAP _ _ _ _ _ _ _ _ _ _ _ _ operator

The map operator applies a uniform evaluation pattern to all members of a composite structure: a matrix, a list or the arguments of an operator expression. The evaluation pattern can be a unary procedure, an operator, or an algebraic expression with one free variable.

### syntax:

map(<function>,<object>)

<object> is a list, a matrix or an operator expression.

<function> is the name of an operator for a single argument: the operator is evaluated once with each element of <object> as its single argument,

or an algebraic expression with exactly one free variable, that is a variable preceded by the tilde symbol: the expression is evaluated for each element of <object> where the element is substituted for the free variable,

or a replacement rule of the form

### syntax:

var=> rep

where <var> is a variable (a <kernel> without subscript) and <rep> is an expression which contains <var>. Here rep is evaluated for each element of <object> where the element is substituted for var. var may be optionally preceded by a tilde.

The rule form for <function> is needed when more than one free variable occurs.

### examples:

    map(abs,{1,-2,a,-a});

      1,2,abs(a),abs(a)

    map(int(~w,x), mat((x^2,x^5),(x^4,x^5)));

              [  3     6 ]
              [ x     x  ]
              [----  ----]
              [ 3     6  ]
              [          ]
              [  5     6 ]
              [ x     x  ]
              [----  ----]
      	[ 5     6  ]

    map(~w*6, x^2/3 = y^3/2 -1);

         2     3
      2*x =3*(y -2)

You can use map in nested expressions. It is not allowed to apply map for a non-composed object, e.g. an identifier or a number.

MKID

INDEX

MKID _ _ _ _ _ _ _ _ _ _ _ _ command

The mkid command constructs an identifier, given a stem and an identifi er or an integer.

### syntax:

mkid(<stem>,<leaf>)

<stem> can be any valid REDUCE identifier that does not include escaped special characters. <leaf> may be an integer, including one given by a local variable in a for loop, or any other legal group of characters.

### examples:

    mkid(x,3);

      X3

    factorize(x^15 - 1);

      {X - 1,
        2
       X  + X + 1,
        4    3    2
       X  + X  + X  + X + 1,
        8    7    5    4    3
       X  - X  + X  - X  + X   - X + 1}

    for i := 1:length ws do write set(mkid(f,i),part(ws,i));

       8    7    5    4    3
      X  - X  + X  - X  + X  - X + 1
       4    3    2
      X  + X  + X  + X + 1
       2
      X  + X + 1
      X - 1

You can use mkid to construct identifiers from inside pro cedures. This allows you to handle an unknown number of factors, or deal with variable amounts of data. It is particularly helpful to attach identifiers to the answers returned by factorize and solve.

NPRIMITIVE

INDEX

NPRIMITIVE _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

nprimitive(<expression>) or nprimitive <simple\_expression>

This operator returns the numerically-primitive part of any scalar expression. In other words, any overall integer factors in the expression are removed.

### examples:

    nprimitive((2x+2y)^2);

       2            2
      X  + 2*X*Y + Y

    nprimitive(3*a*b*c);

      3*A*B*C

NUM

INDEX

NUM _ _ _ _ _ _ _ _ _ _ _ _ operator

The num operator returns the numerator of its argument.

### syntax:

num(<expression>) or num <simple\_expression>

<expression> can be any valid REDUCE scalar expression.

### examples:

    num(100/6);

      50

    num(a/5 + b/6);

      6*A + 5*B

    num(sin(x));

      SIN(X)

numreturns the numerator of the expression after it has b een simplified by REDUCE. As seen in the examples, this includes putting sums of rational expressions over a common denominator, and reducing common factors where possible. If the expression is not a rational expression, it is returned unchanged.

ODESOLVE

INDEX

ODESOLVE _ _ _ _ _ _ _ _ _ _ _ _ operator

The odesolve package is a solver for ordinary differential equations. At the present time it has still limited capabilities:

1. it can handle only a single scalar equation presented as an algebraic expression or equation, and

2. it can solve only first-order equations of simple types, linear equations with constant coefficients and Euler equations.

These solvable types are exactly those for which Lie symmetry techniques give no useful information.

### syntax:

odesolve(<expr>,<var1>,<var2>)

<expr> is a single scalar expression such that <expr>=0 is the ordinary differential equation (ODE for short) to be solved, or is an equivalent equation.

<var1> is the name of the dependent variable, <var2> is the name of the independent variable.

A differential in <expr> is expressed using the df operator. Note that in most cases you must declare explicitly <var1> to depend of <var2> using a depend declaration -- otherwise the derivative might be evaluated to zero on input to odesolve.

The returned value is a list containing the equation giving the general solution of the ODE (for simultaneous equations this will be a list of equations eventually). It will contain occurrences of the operator arbconst for the arbitrary constants in the general solution. The arguments of arbconst should be new. A counter !!arbconst is used to arrange this.

### examples:

    depend y,x;

    % A first-order linear equation, with an initial condition

    ode:=df(y,x) + y * sin x/cos x - 1/cos x$

    odesolve(ode,y,x);

      {y=arbconst(1)*cos(x) + sin(x)}

ONE_OF

INDEX

ONE\_OF _ _ _ _ _ _ _ _ _ _ _ _ type

The operator one_of is used to represent an indefinite choice of one element from a finite set of objects.

### examples:

    x=one_of{1,2,5}

this equation encodes that x can take one of the values 1,2 or 5

REDUCE generates a one_of form in cases when an implicit root_of expression could be converted to an explicit solution set. A one_of form can be converted to a solve solution using expand_cases. See root_of.

PART

INDEX

PART _ _ _ _ _ _ _ _ _ _ _ _ operator

The operator part permits the extraction of various parts or operators of expressions and list s.

### syntax:

part(<expression,integer>{,<integer>}*)

<expression> can be any valid REDUCE expression or a list, integer may be an expression that evaluates to a positive or negative integer or 0. A positive integer <n> picks up the n th term, counting from the first term toward the end. A negative integer n picks up the n th term, counting from the back toward the front. The integer 0 picks up the operator (which is LIST when the expression is a list).

### examples:

    part((x + y)**5,4);

          2  3
      10*X *Y

    part((x + y)**5,4,2);

       2
      X

    part((x + y)**5,4,2,1);

      X

    part((x + y)**5,0);

      PLUS

    part((x + y)**5,-5);

            4
      5*X *Y

    part((x + y)**5,4) := sin(x);

       5      4         3  2                 4    5
      X  + 5*X *Y + 10*X *Y  + SIN(X) + 5*X*Y  + Y

    alist := {x,y,{aa,bb,cc},x**2*sqrt(y)};

                                            2
      			 ALIST := {X,Y,{AA,BB,CC},SQRT(Y)*X }

    part(alist,3,2);

      BB

    part(alist,4,0);

      TIMES

Additional integer arguments after the first one examine the terms recursively, as shown above. In the third line, the fourth term is picked from the original polynomial, 10x^2y^3, then the second term from that, x^2, and finally the first component, x. If an integer's absolute value is too large for the appropriate expression, a message is given.

partworks on the form of the expression as printed, or as it would have been printed at that point of the calculation, bearing in mind the current switch settings. It is important to realize that the switch settings change the operation of part. pri must be on when part is used.

When part is used on a polynomial expression that has minus signs, the + is always returned as the top-level operator. The minus is found as a unary operator attached to the negative term.

partcan also be used to change the relevant part of the expression or list as shown in the sixth example line. The part operator returns the changed expression, though original expression is not changed. You can also use part to change the operator.

PF

INDEX

PF _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

pf(<expression>,<variable>)

pftransforms <expression> into a list of partial fraction s with respect to the main variable, <variable>. pf does a complete partial fraction decomposition, and as the algorithms used are fairly unsophisticated (factorization and the extended Euclidean algorithm), the code may be unacceptably slow in complicated cases.

### examples:

    pf(2/((x+1)^2*(x+2)),x);

          2    -2        2
      	{-----,-----,------------}
        X + 2 X + 1  2
                    X  + 2*X + 1

    off exp;

    pf(2/((x+1)^2*(x+2)),x);

         2    - 2     2
      {-----,-----,--------}
       X + 2 X + 1        2
                   (X + 1)

    for each j in ws sum j;

             2
      ----------------
                    2
      ( + 2)*(X + 1)

If you want the denominators in factored form, turn exp off, as shown in the second example above. As shown in the final example, the for each construct can be used to re combine the terms. Alternatively, one can use the operations on lists to extract any desired term.

PROD

INDEX

PROD _ _ _ _ _ _ _ _ _ _ _ _ operator

The operator prod returns the indefinite or definite product of a given expression.

### syntax:

prod(<expr>,<k>[,<lolim> [,<uplim> ]])

where <expr> is the expression to be multiplied, <k> is the control variable (a kernel), and <lolim> and <uplim> uplim are the optional lower and upper limits. If <uplim> is not supplied the upper limit is taken as <k>. The Gosper algorithm is used. If there is no closed form solution, the operator returns the input unchanged.

### examples:

    prod(k/(k-2),k);

      k*( - k + 1)

REDUCT

INDEX

REDUCT _ _ _ _ _ _ _ _ _ _ _ _ operator

The reduct operator returns the remainder of its expression after the leading term with respect to the kernel in the second argument is removed.

### syntax:

reduct(<expression>,<kernel>)

<expression> is ordinarily a polynomial. If ratarg is on, a rational expression may also be used, otherwise an error results. <kernel> must be a kernel.

### examples:

    reduct((x+y)**3,x);

            2            2
      Y*(3*X  + 3*X*Y + Y )

    reduct(x + sin(x)**3,sin(x));

      X

    reduct(x + sin(x)**3,y);

      0

If the expression does not contain the kernel, reduct ret urns 0.

REPART

INDEX

REPART _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

repart(<expression>) or repart <simple\_expression >

This operator returns the real part of an expression, if that argument has an numerical value. A non-numerical argument is returned as an expression in the operators repart and impart.

### examples:

    repart(1+i);

      1

    repart(a+i*b);

      REPART(A) - IMPART(B)

RESULTANT

INDEX

RESULTANT _ _ _ _ _ _ _ _ _ _ _ _ operator

The resultant operator computes the resultant of two polynomials with respect to a given variable. If the resultant is 0, the polynomials have a root in common.

### syntax:

resultant(<expression>,<expression>,<kernel>)

<expression> must be a polynomial containing <kernel> ; <kernel> must be a kernel.

### examples:

    resultant(x**2 + 2*x + 1,x+1,x);

      0

    resultant(x**2 + 2*x + 1,x-3,x);

      16

    resultant(z**3 + z**2 + 5*z + 5,
              z**4 - 6*z**3 + 16*z**2 - 30*z + 55,
              z);

      0

    resultant(x**3*y + 4*x*y + 10,y**2 + 6*y + 4,y);

       6       5        4        3        2
      Y  + 18*Y  + 120*Y  + 360*Y  + 480*Y  + 288*Y + 64

The resultant is the determinant of the Sylvester matrix, formed f rom the coefficients of the two polynomials in the following way:

Given two polynomials:

        n       n-1
     a x  + a1 x     + ... + an

and

        m       m-1
     b x  + b1 x     + ... + bm

form the (m+n)x(m+n-1) Sylvester matrix by the following means:

       0.......0 a  a1 .......... an
       0....0 a  a1 .......... an  0
           .    .   .   .
       a0 a1 .......... an 0.......0
       0.......0 b  b1 .......... bm
       0....0 b  b1 .......... bm  0
           .    .   .   .
       b  b1 .......... bm 0.......0

If the determinant of this matrix is 0, the two polynomials have a common root. Finding the resultant of large expressions is time-consuming, due to the time needed to find a large determinant.

The sign conventions resultant uses are those given in the article, ``Computing in Algebraic Extensions,'' by R. Loos, appearing in <Computer Algebra--Symbolic and Algebraic Computation>, 2nd ed., edited by B. Buchberger, G.E. Collins and R. Loos, and published by Springer-Verlag, 1983. These are:

      resultant(p(x),q(x),x) = (-1)^{deg p(x)*deg q(x)} * resultant(q(x),p(x),x),
      resultant(a,p(x),x)    = a^{deg p(x)},
      resultant(a,b,x)       = 1

where p(x) and q(x) are polynomials which have x as a variable, an d a and b are free of x.

Error messages are given if resultant is given a non-polynomial expression, or a non-kernel variable.

RHS

INDEX

RHS _ _ _ _ _ _ _ _ _ _ _ _ operator

The rhs operator returns the right-hand side of an equation, such as those returned in a list by solve.

### syntax:

rhs(<equation>) or rhs <equation>

<equation> must be an equation of the form left-hand side = right-hand side.

### examples:

    roots := solve(x**2 + 6*x*y + 5x + 3y**2,x);

                                  2
                         SQRT(24*Y  + 60*Y + 25) + 6*Y + 5
          ROOTS := {X= - ---------------------------------,
                                         2
                                 2
                        SQRT(24*Y  + 60*Y + 25) - 6*Y - 5
                     X= ---------------------------------}
                                        2

    root1 := rhs first roots;

                          2
                 SQRT(24*Y  + 60*Y + 25) + 6*Y + 5
      ROOT1 := - ---------------------------------
                                 2

    root2 := rhs second roots;

                        2
               SQRT(24*Y  + 60*Y + 25) - 6*Y - 5
      ROOT2 := ----------------------------------
                               2

An error message is given if rhs is applied to something other than an equation.

ROOT_OF

INDEX

ROOT\_OF _ _ _ _ _ _ _ _ _ _ _ _ operator

When the operator solve is unable to find an explicit solution or if that solution would be too complicated, the result is presented as formal root expression using the internal operator root_of and a new local variable. An expression with a top level root_of is implicitly a list with an unknown number of elements since we can't always know how many solutions an equation has. If a substitution is made into such an expression, closed form solutions can emerge. If this occurs, the root_of construct is replaced by an operator one_of. At this point it is of course possible to transform the result if the original solve operator expression into a standard solve solution. To effect this, the operator expand_cases can be used.

### examples:

    solve(a*x^7-x^2+1,x);

                     7     2
      {x=root_of(a*x_  - x_  + 1,x_)}

    sub(a=0,ws);

      {x=one_of(1,-1)}

    expand_cases ws;

      x=1,x=-1

The components of root_of and one_of expressions can be processed as usual with operators arglength and part. A higher power of a root_of expression with a polynomial as first argument is simplified by using the polynomial as a side relation.

SELECT

INDEX

SELECT _ _ _ _ _ _ _ _ _ _ _ _ operator

The select operator extracts from a list or from the arguments of an n--ary operator elements corresponding to a boolean predicate. The predicate pattern can be a unary procedure, an operator or an algebraic expression with one free variable.

### syntax:

select(<function>,<object>)

<object> is a list.

<function> is the name of an operator for a single argument: the operator is evaluated once with each element of <object> as its single argument,

or an algebraic expression with exactly one free variable, that is a variable preceded by the tilde symbol: the expression is evaluated for each element of <object> where the element is substituted for the free variable,

or a replacement rule of the form

### syntax:

var=> rep

where <var> is a variable (a <kernel> without subscript) and <rep> is an expression which contains <var>. Here rep is evaluated for each element of <object> where the element is substituted for var. var may be optionally preceded by a tilde.

The rule form for <function> is needed when more than one free variable occurs. The evaluation result of <function> is interpreted as boolean value corresponding to the convention s of REDUCE. The result value is built with the leading operator of the input expression.

### examples:

      select( ~w>0 , {1,-1,2,-3,3})

      {1,2,3}

      q:=(part((x+y)^5,0):=list)

      select(evenp deg(~w,y),q);

        5      3   2       4
      {x  ,10*x  *y  ,5*x*y  }

      select(evenp deg(~w,x),2x^2+3x^3+4x^4);

        2   4
      2x +4x

SHOWRULES

INDEX

SHOWRULES _ _ _ _ _ _ _ _ _ _ _ _ operator

### syntax:

showrules(<expression>) or showrules <simple\_expression>

showrulesreturns in rule -list form any operator rules associated with its argument.

### examples:

    showrules log;

      {LOG(E) => 1,
       LOG(1) => 0,
            ~X
       LOG(E   ) => ~X,
                         1
       DF(LOG(~X),~X) => --}
                         ~X

Such rules can then be manipulated further as with any list. For example rhs first ws; has the value 1.

An operator may have properties that cannot be displayed in such a form, such as the fact it is an odd function, or has a definition defined as a procedure.

SOLVE

INDEX

SOLVE _ _ _ _ _ _ _ _ _ _ _ _ operator

The solve operator solves a single algebraic equation or a system of simultaneous equations.

### syntax:

solve(<expression> [ , <kernel>]) or

solve({<expression>,...} [ ,{ <kernel> ,...}] )

If the number of equations equals the number of distinct kernels, the optional kernel argument(s) may be omitted. <expression> is either a scalar expression or an equation. When more than one expression is given, the list of expressions is surrounded by curly br aces. The optional list of kernels follows, also in curly braces.

### examples:

    sss := solve(x^2 + 7);

      Unknown: X
      SSS := {X= - SQRT(7)*I,
              X=SQRT(7)*I}

    rhs first sss;

      - SQRT(7)*I

    solve(sin(x^2*y),y);

         2*ARBINT(1)*PI
      {Y=---------------
                2
               X
         PI*(2*ARBINT(1) + 1)
       Y=--------------------}
                   2
                  X

    off allbranch;

    solve(sin(x**2*y),y);

      {Y=0}

    solve({3x + 5y = -4,2*x + y = -10},{x,y});

             22   46
      {{X= - --,Y=--}}
             7    7

    solve({x + a*y + z,2x + 5},{x,y});

             5      2*Z - 5
      {{X= - -,Y= - -------}}
             2        2*A

    ab := (x+2)^2*(x^6 + 17x + 1);

             8      7      6       3       2
      AB := X  + 4*X  + 4*X  + 17*X  + 69*X  + 72*X + 4

    www := solve(ab,x);

      {X=ROOT F(X6 + 17*X + 1),X=-2}
             O

    root_multiplicities;

      {1,2}

Results of the solve operator are returned as equation s in a list. You can use the usual list access methods ( first, second, third, rest and part) to extract the desired equation, and then use the operators rhs and lhs to access the right-hand or left-hand exp ression of the equation. When solve is unable to solve an equation, it returns the unsolved part as the argument of root_of, with the variable renamed to avoid confusion, as shown in the last example above.

For one equation, solve uses square-free factorization, roots of unity, and the known inverses of the log, sin, cos, acos, asin, and exponentiation operators. The quadratic, cubic and quartic formulas are used if necessary, but these are applied only when the switch fullroots is set on; otherwise or when no clo sed form is available the result is returned as root_of expression. The switch trigform determines which type of cubic and quartic formula is used. The multiplicity of each solution is given in a list as the system variable root_multiplicities. For systems of simultaneous linear equations, matrix inversion is used. For nonlinear systems, the Groebner basis method is used.

Linear equation system solving is influenced by the switch cramer.

Singular systems can be solved when the switch solvesingular is on, which is the default setting. An empty list is returned the system of equations is inconsistent. For a linear inconsistent system with parameters the variable requirements constraints conditions for the system to become consistent.

For a solvable linear and polynomial system with parameters the variable assumptions contains a list side relations for the parameters: the solution is valid only as long as none of these expressions is zero.

If the switch varopt is on (default), the system rearranges the variable sequence for minimal computation time. Without varopt the user supplied variable sequence is maintained.

If the solution has free variables (dimension of the solution is greater than zero), these are represented by arbcomplex expressions as long as the switch arbvars is on (default). Without arbvars no explicit equations are generated for free variables.

### related:

_ _ _ allbranchswitch

_ _ _ arbvars switch

_ _ _ assumptions variable

_ _ _ fullroots switch

_ _ _ requirements variable

_ _ _ roots operator

_ _ _ root_of operator

_ _ _ trigform switch

_ _ _ varopt switch

SORT

INDEX

SORT _ _ _ _ _ _ _ _ _ _ _ _ operator

The sort operator sorts the elements of a list according to an arbitrary comparison operator.

### syntax:

sort(<lst>,<comp>)

<lst> is a list of algebraic expressions. <comp> is a comparison operator which defines a partial ordering among the members of <lst>. <comp> may be one of the builtin comparison operators like <( lessp), <=( leq) etc., or <comp> may be the name of a comparison procedure. Such a procedure has two arguments, and it returns true if the first argument ranges before the second one, and 0 or nil otherwise. The result of sort is a new list which contains the elements of <lst> in a sequence corresponding to <comp>.

### examples:

     procedure ce(a,b);

       if evenp a and not evenp b then 1 else 0;

    for i:=1:10 collect random(50)$

    sort(ws,>=);

      {41,38,33,30,28,25,20,17,8,5}

    sort(ws,<);

      {5,8,17,20,25,28,30,33,38,41}

    sort(ws,ce);

      {8,20,28,30,38,5,17,25,33,41}

      procedure cd(a,b);

      if deg(a,x)>deg(b,x) then 1 else

      if deg(a,x)<deg(b,x) then 0 else

      if deg(a,y)>deg(b,y) then 1 else 0;

    sort({x^2,y^2,x*y},cd);

        2      2
      {x ,x*y,y }

STRUCTR

INDEX

STRUCTR _ _ _ _ _ _ _ _ _ _ _ _ operator

The structr operator breaks its argument expression into named subexpressions.

### syntax:

structr(<expression> [,<identifier>[,<identifier> ... ]])

<expression> may be any valid REDUCE scalar expression. <identifier> may be any valid REDUCE identifier. The first identifier is the stem for subexpression names, the second is the name to be assigned to the structured expression.

### examples:

    structr(sqrt(x**2 + 2*x) + sin(x**2*z));

      ANS1 + ANS2
          where
                           2
              ANS2 := SIN(X *Z)
                                 1/2
              ANS1 := ((X + 2)*X)

    ans3;

      ANS3

    on fort;

    structr((x+1)**5 + tan(x*y*z),var,aa);

      VAR1=TAN(X*Y*Z)
      AA=VAR1+X**5+5.*X**4+10.*X**3+10.X**2+5.*X+1

The second argument to structr is optional. If it is not given, the default stem ANS is used by REDUCE to construct names for the subexpression. The names are only for display purposes: REDUCE does not store the names and their values unless the switch savestructr is on.

If a third argument is given, the structured expression as a whole is named by this argument, when fort is on. The expression is not stored under this name. You can send these structured Fortran expressions to a file with the out command.

SUB

INDEX

SUB _ _ _ _ _ _ _ _ _ _ _ _ operator

The sub operator substitutes a new expression for a kernel in an expression.

### syntax:

sub(<kernel>=<expression> {,<kernel>=<expression>}*, <expression>) or

sub({<kernel>=<expression>*, <kernel>=expression},<expression>)

<kernel> must be a kernel, <expression> can be any REDUCE scalar expression.

### examples:

    sub(x=3,y=4,(x+y)**3);

      343

    x;

      X

    sub({cos=sin,sin=cos},cos a+sin b)

      COS(B) + SIN(A)

Note in the second example that operators can be replaced using th e sub operator.

SUM

INDEX

SUM _ _ _ _ _ _ _ _ _ _ _ _ operator

The operator sum returns the indefinite or definite summation of a given expression.

### syntax:

sum(<expr>,<k>[,<lolim> [,<uplim> ]])

where <expr> is the expression to be added, <k> is the control variable (a kernel), and <lolim> and <uplim> are the optional lower and upper limits. If <uplim> is not supplied the upper limit is taken as <k>. The Gosper algorithm is used. If there is no closed form solution, the operator returns the input unchanged.

### examples:

    sum(4n**3,n);

       2    2
      n  *(n   + 2*n + 1)

    sum(2a+2k*r,k,0,n-1);

      n*(2*a + n*r - r)

WS

INDEX

WS _ _ _ _ _ _ _ _ _ _ _ _ operator

The ws operator alone returns the last result; ws with a number argument returns the results of the REDUCE statement executed after that numbered prompt.

### syntax:

wsor ws(<number>)

<number> must be an integer between 1 and the current REDUCE prompt number .

### examples:

(In the following examples, unlike most others, the nu mbered prompt is shown.)

    1: df(sin y,y);

      COS(Y)

    2: ws^2;

            2
      COS(Y)

    3: df(ws 1,y);

      -SIN(Y)

wsand ws(<number>) can be used anywher e the expression they stand for can be used. Calling a number for which no result was produced, such as a switch setting, will give an error message.

The current workspace always contains the results of the last REDUCE command that produced an expression, even if several input statements that do not produce expressions have intervened. For example, if you do a differentiation, producing a result expression, then change several switches, the operator ws; returns the results of the differentiation. The current workspace (ws) can also be used inside files, though the numbered workspace contains only the in command that input the file.

There are three history lists kept in your REDUCE session. The first stores raw input, suitable for the statement editor. The second stores parsed input, ready to execute and accessible by input. The third stores results, when they are produced by statements, which are accessible by the ws< n> operator. If your session is very long, storage space begins to fill up with these expressions, so it is a good idea to end the session once in a while, saving needed expressions to files with the saveas and out commands.

An error message is given if a reference number has not yet been used.

Algebraic Operators

INDEX

Algebraic Operators

- APPEND operator

- ARBINT operator

- ARBCOMPLEX operator

- ARGLENGTH operator

- COEFF operator

- COEFFN operator

- CONJ operator

- CONTINUED_FRACTION operator

- DECOMPOSE operator

- DEG operator

- DEN operator

- DF operator

- EXPAND\_CASES operator

- EXPREAD operator

- FACTORIZE operator

- HYPOT operator

- IMPART operator

- INT operator

- INTERPOL operator

- LCOF operator

- LENGTH operator

- LHS operator

- LIMIT operator

- LPOWER operator

- LTERM operator

- MAINVAR operator

- MAP operator

- MKID command

- NPRIMITIVE operator

- NUM operator

- ODESOLVE operator

- ONE\_OF type

- PART operator

- PF operator

- PROD operator

- REDUCT operator

- REPART operator

- RESULTANT operator

- RHS operator

- ROOT\_OF operator

- SELECT operator

- SHOWRULES operator

- SOLVE operator

- SORT operator

- STRUCTR operator

- SUB operator

- SUM operator

- WS operator

  ALGEBRAIC

  INDEX

  ALGEBRAIC _ _ _ _ _ _ _ _ _ _ _ _ command

  The algebraic command changes REDUCE's mode of operation to algebraic. When algebraic is used as an operator (with an argument inside parentheses) that argument is evaluated in algebraic mode, but REDUCE's mode is not changed.

  ### examples:

      algebraic;

      symbolic;

        NIL

      algebraic(x**2);

         2
        X

      x**2;

          ***** The symbol X has no value.

  REDUCE's symbolic mode does not know about most algebraic commands . Error messages in this mode may also depend on the particular Lisp used for the REDUCE implementation.

  ANTISYMMETRIC

  INDEX

  ANTISYMMETRIC _ _ _ _ _ _ _ _ _ _ _ _ declaration

  When an operator is declared antisymmetric, its arguments are reordered to conform to the internal ordering of the system. If an odd number of argument interchanges are required to do this ordering, the sign of the expression is changed.

  ### syntax:

  antisymmetric<identifier>{,<identifier>}*

  <identifier> is an identifier that has been declared as an operator.

  ### examples:

      operator m,n;

      antisymmetric m,n;

      m(x,n(1,2));

        - M( - N(2,1),X)

      operator p;

      antisymmetric p;

      p(a,b,c);

        P(A,B,C)

      p(b,a,c);

        - P(A,B,C)

  If <identifier> has not been declared an operator, the flag antisymmetric is still attached to it. When <identifier> is subsequently used as an operator, the message Declare <identifier > operator? (Y or N) is printed. If the user replies y, the antisymmetric property of the operator is used.

  Note in the first example, identifiers are customarily ordered alphabetically, while numbers are ordered from largest to smallest. The operators may have any desired number of arguments (less than 128).

  ARRAY

  INDEX

  ARRAY _ _ _ _ _ _ _ _ _ _ _ _ declaration

  The array declaration declares a list of identifiers to be of type array, and sets all their entries to 0.

  ### syntax:

  array<identifier>(<dimensions>) {,<identifier>(<dimensions>)}*

  <identifier> may be any valid REDUCE identifier. If the identifier was already an array, a warning message is given that the array has been redefined. <dimensions> are of form <integer>{,<integer>}*.

  ### examples:

      array a(2,5),b(3,3,3),c(200);

      array a(3,5);

        *** ARRAY A REDEFINED

      a(3,4);

        0

      length a;

        {4,6}

  Arrays are always global, even if defined inside a procedure or bl ock statement. Their status as an array remains until the variable is reset by clear. Arrays may not have the same names as operators, procedures or scalar variables.

  Array elements are referred to by the usual notation: a(i,j) returns the jth element of the ith row. The assignment operator := is used to put values into the array. Arrays as a whole cannot be subject to assignment by let or := ; the assignment operator := is only valid for individual elements.

  When you use let on an array element, the contents of that element become the argument to let. Thus, if the element contains a number or some other expression that is not a valid argument for this command, you get an error message. If the element contains an identifier, the identifier has the substitution rule attached to it globally. The same behavior occurs with clear. If the array element contains an identifier or simple_expression, it is cleared. Do <not> use clear to try to set an array element to 0. Because of the side effects of either let or clear, it is unwise to apply either of these to array elements.

  Array indices always start with 0, so that the declaration array a(5) sets aside 6 units of space, indexed from 0 through 5, and initializes them to 0. The length command returns a list of the true num ber of elements in each dimension.

  CLEAR

  INDEX

  CLEAR _ _ _ _ _ _ _ _ _ _ _ _ command

  The clear command is used to remove assignments or remove substitution rules from any expression.

  ### syntax:

  clear<identifier>{,<identifier>}+ or

  <let-type statement> clear <identifier>

  <identifier> can be any scalar, matrix, or array variable or procedure name. <let-type statement> ca n be any general or specific let statement (see below in Comments).

  ### examples:

      array a(2,3);

      a(2,2) := 15;

        A(2,2) := 15

      clear a;

      a(2,2);

        Declare A operator? (Y or N)

      let x = y + z;

      sin(x);

        SIN(Y + Z)

      clear x;

      sin(x);

        SIN(X)

      let x**5 = 7;

      clear x;

      x**5;

        7

      clear x**5;

      x**5;

         5
        X

  Although it is not a good idea, operators of the same name but tak ing different numbers of arguments can be defined. Using a clear statement on any of these operators clears every one with the same name, even if the number of arguments is different.

  The clear command is used to ``forget" matrices, arrays, operators and scalar variables, returning their identifiers to the pristine state to be used for other purposes. When clear is applied to array elements, the contents of the array element becomes the argument for clear. Thus, you get an error message if the element contains a number, or some other expression that is not a legal argument to clear. If the element contains an identifier, it is cleared. When clear is applied to matrix elements, an error message is returned if the element evaluates to a number, otherwise there is no effect. Do not try to use clear to set array or matrix elements to 0. You will not be pleased with the results.

  If you are trying to clear power or product substitution rules made with either let or forall...let, you must reproduce the rule, exactly as you typed it with the same arguments, up to but not including the equal sign, using the word clear instead of the word let. This is shown in the last example. Any other type of let or forall...let substitution can be cleared with just the variable or operator name. match behaves the same as let in this situation. There is a more compli cated example under forall.

  CLEARRULES

  INDEX

  CLEARRULES _ _ _ _ _ _ _ _ _ _ _ _ command

  ### syntax:

  clearrules<list>{,<list>}+

  The operator clearrules is used to remove previously defined rule lists from the system. <list> can be an explicit rule list, or evaluate to a rule list.

  ### examples:

      trig1 := {cos(~x)*cos(~y) => (cos(x+y)+cos(x-y))/2,
                cos(~x)*sin(~y) => (sin(x+y)-sin(x-y))/2,
                sin(~x)*sin(~y) => (cos(x-y)-cos(x+y))/2,
                cos(~x)^2       => (1+cos(2*x))/2,
                sin(~x)^2       => (1-cos(2*x))/2}$

      let trig1;
      cos(a)*cos(b);

        COS(A - B) + COS(A + B)
        -----------------------
                   2

      clearrules trig1;
      cos(a)*cos(b);

        COS(A)*COS(B)

  DEFINE

  INDEX

  DEFINE _ _ _ _ _ _ _ _ _ _ _ _ command

  The command define allows you to supply a new name for an identifier or replace it by any valid REDUCE expression.

  ### syntax:

  define<identifier>=<substitution> {,<identifier>=<substitution>}*

  <identifier> is any valid REDUCE identifier, <substitution> can be a number, an identifier, an operator, a reserved word, or an expression.

  ### examples:

      define is= :=, xx=y+z;

      a is 10;

        A := 10

      xx**2;

         2             2
        Y   + 2*Y*Z + Z

      xx := 10;

        Y + Z := 10

  The renaming is done at the input level, and therefore takes prece dence over any other replacement or substitution declared for the same identifier. It remains in effect until the end of the REDUCE session. Be careful with it, since you cannot easily undo it without ending the session.

  DEPEND

  INDEX

  DEPEND _ _ _ _ _ _ _ _ _ _ _ _ declaration

  dependdeclares that its first argument depends on the rest of its arguments.

  ### syntax:

  depend<kernel>{,<kernel>}+

  <kernel> must be a legal variable name or a prefix operator (see kernel).

  ### examples:

      depend y,x;

      df(y**2,x);

        2*DF(Y,X)*Y

      depend z,cos(x),y;

      df(sin(z),cos(x));

        COS(Z)*DF(Z,COS(X))

      df(z**2,x);

        2*DF(Z,X)*Z

      nodepend z,y;

      df(z**2,x);

        2*DF(Z,X)*Z

      cc := df(y**2,x);

        CC := 2*DF(Y,X)*Y

      y := tan x;

        Y := TAN(X);

      cc;

                        2
        2*TAN(X)*(TAN(X)   + 1)

  Dependencies can be removed by using the declaration nodepend. The differentiation operator uses this information, as shown in the examples above. Linear operators also use knowledge of dependencies (see linear). Note that dependencies can be nested : Having declared y to depend on x, and z to depend on y, we see that the chain rule was applied to the derivative of a function of z with respect to x. If the explicit function of the dependency is later entered into the system, terms with DF(Y,X), for example, are expanded when they are displayed again, as shown in the last example. The boolean operator freeof allows you to check the dependency between two algebraic objects.

  EVEN

  INDEX

  EVEN _ _ _ _ _ _ _ _ _ _ _ _ declaration

  ### syntax:

  even<identifier>{,<identifier>}*

  This declaration is used to declare an operator even in its first argument. Expressions involving an operator declared in this manner are transformed if the first argument contains a minus sign. Any other arguments are not affected.

  ### examples:

              even f;

              f(-a)

        F(A)

              f(-a,-b)

        F(A,-B)

  FACTOR_declaration

  INDEX

  FACTOR _ _ _ _ _ _ _ _ _ _ _ _ declaration

  When a kernel is declared by factor, all terms involving fixed powers of that kernel are printed as a product of the fixed powers and the rest of the terms.

  ### syntax:

  factor<kernel> {,<kernel>}*

  <kernel> must be a kernel or a list of kernels.

  ### examples:

      a := (x + y + z)**2;

              2                    2            2
        A := X  + 2*X*Y + 2*X*Z + Y  + 2*Y*Z + Z

      factor y;

      a;

         2                  2            2
        Y  + 2*Y*(X + Z) + X  + 2*X*Z + Z

      factor sin(x);

      c := df(sin(x)**4*x**2*z,x);

                     4               3         2
        C := 2*SIN(X) *X*Z + 4*SIN(X) *COS(X)*X *Z

      remfac sin(x);

      c;

                3
        2*SIN(X) *X*Z*(2*COS(X)*X + SIN(X))

  Use the factor declaration to display variables of intere st so that you can see their powers more clearly, as shown in the example. Remove this special treatment with the declaration remfac. The factor declaration is only effective when the switch pri is on.

  The factor declaration is not a factoring command; to factor expressions use the factor switch or the factorize command.

  The factor declaration is helpful in such cases as Taylor polynomials where the explicit powers of the variable are expected at the top level, not buried in various factored forms.

  Note that factor does not affect the order of its arguments. You should also use order if this is important.

  FORALL

  INDEX

  FORALL _ _ _ _ _ _ _ _ _ _ _ _ command

  The forall or (preferably) for all command is used as a modifier for let statements, indicating the universal appl icability of the rule, with possible qualifications.

  ### syntax:

  for all<identifier>{,<identifier>}* let <let statement>

  or

  for all<identifier>{,<identifier>}* such that <condition> let <let statement>

  <identifier> may be any valid REDUCE identifier, <let statement> can be an operator, a product or power, or a group or block statement. <condition> must be a logical or comparison operator returning true or false.

  ### examples:

      for all x let f(x) = sin(x**2);

        Declare F operator ? (Y or N)

      y

      f(a);

             2
        SIN(A )

      operator pos;

      for all x such that x>=0 let pos(x) = sqrt(x + 1);

      pos(5);

        SQRT(6)

      pos(-5);

        POS(-5)

      clear pos;

      pos(5);

        Declare POS operator ? (Y or N)

      for all a such that numberp a let x**a = 1;

      x**4;

        1

      clear x**a;

        *** X**A not found

      for all a  clear x**a;

      x**4;

        1

      for all a such that numberp a clear x**a;

      x**4;

         4
        X

  Substitution rules defined by for all or for all...such that commands that involve products or powers are cleared by reproducing the command, with exactly the same variable names used, up to but not including the equal sign, with clear replacing let, as shown in the last example. Other substitutions involving variables or operator names can be cleared with just the name, like any other variable.

  The match command can also be used in product and power substitutions. The syntax of its use and clearing is exactly like let. A match substitution only replaces the term if it is exactly like the pattern, for example match x**5 = 1 replaces only terms of x**5 and not terms of higher powers.

  It is easier to declare your potential operator before defining the for all rule, since the system will ask you to declare it an operator anyway. Names of declared arrays or matrices or scalar variables are invalid as operator names, to avoid ambiguity. Either for all...let statements or procedures are often used to defin e operators. One difference is that procedures implement ``call by value" meaning that assignments involving their formal parameters do not change the calling variables that replace them. If you use assignment statements on the formal parameters in a for all...let statement, the effects are seen in the calling variables. Be careful not to redefine a system operator unless you mean it: the statement for all x let sin(x)=0; has exactly that effect, and the usual definition for sin(x) has been lost for the remainder of the REDUCE session.

  INFIX

  INDEX

  INFIX _ _ _ _ _ _ _ _ _ _ _ _ declaration

  infixdeclares identifiers to be infix operators.

  ### syntax:

  infix<identifier>{,<identifier>}*

  <identifier> can be any valid REDUCE identifier, which has not already been declared an operator, array or matrix, and is not reserved by the system.

  ### examples:

      infix aa;

      for all x,y let aa(x,y) = cos(x)*cos(y) - sin(x)*sin(y);

      x aa y;

        COS(X)*COS(Y) - SIN(X)*SIN(Y)

      pi/3 aa pi/2;

          SQRT(3)
        - -------
             2

      aa(pi,pi);

        1

  A let statement must be used to attach function ality to the operator. Note that the operator is defined in prefix form in the let statement. After its definition, the operator may be used in either prefix or infix mode. The above operator aa finds the cosine of the sum of two angles by the formula

  cos(x+y) = cos(x)*cos(y) - sin(x)*sin(y).

  Precedence may be attached to infix operators with the precedence declaration.

  User-defined infix operators may be used in prefix form. If they are used in infix form, a space must be left on each side of the operator to avoid ambiguity. Infix operators are always binary.

  INTEGER

  INDEX

  INTEGER _ _ _ _ _ _ _ _ _ _ _ _ declaration

  The integer declaration must be made immediately after a begin (or other variable declaration such as real and scalar) and declares local integer variables. They are initialized to 0.

  ### syntax:

  integer<identifier>{,<identifier>}*

  <identifier> may be any valid REDUCE identifier, except t or nil.

  Integer variables remain local, and do not share values with variables of the same name outside the begin...end block. When the block is finished, the variables are removed. You may use the words real or scalar in the place of integer. integer does not indicate typechecking by the current REDUCE; it is only for your own information. Declaration statements must immediately follow the begin, without a semicolon between begin and the first variable declaration.

  Any variables used inside begin...end blocks that were not declared scalar, real or integer are global, and any change made to them inside the block affects their global value. Any array or matrix declared inside a block is always glob al.

  KORDER

  INDEX

  KORDER _ _ _ _ _ _ _ _ _ _ _ _ declaration

  The korder declaration changes the internal canonical ordering of kernels.

  ### syntax:

  korder<kernel>{,<kernel>}*

  <kernel> must be a REDUCE kernel or a list of kernels.

  The declaration korder changes the internal ordering, but not the print ordering, so the effects cannot be seen on output. However, in some calculations, the order of the variables can have significant effects on the time and space demands of a calculation. If you are doing a demanding calculation with several kernels, you can experiment with changing the canonical ordering to improve behavior.

  The first kernel in the argument list is given the highest priority, the second gets the next highest, and so on. Kernels not named in a korder ordering otherwise. A new korder declaration replaces the previous one. To return to canonical ordering, use the command korder nil.

  To change the print ordering, use the declaration order.

  LET

  INDEX

  LET _ _ _ _ _ _ _ _ _ _ _ _ command

  The let command defines general or specific substitution rules.

  ### syntax:

  let<identifier> = <expression>{,<identifier> = <expression>}*

  <identifier> can be any valid REDUCE identifier except an array, and in some cases can be an expression; <expression> can be any valid REDUCE expression.

  ### examples:

      let a = sin(x);

      b := a;

        B := SIN X;

      let c = a;

      exp(a);

         SIN(X)
        E

      a := x**2;

              2
        A := X

      exp(a);

          2
         X
        E

      exp(b);

         SIN(X)
        E

      exp(c);

          2
         X
        E

      let m + n = p;

      (m + n)**5;

         5
        P

      operator h;

      let h(u,v) = u - v;

      h(u,v);

        U - V

      h(x,y);

        H(X,Y)

      array q(10);

      let q(1) = 15;

        ***** Substitution for 0 not allowed

  The let command is also used to activate a rule sets .

  ### syntax:

  let<list>{,<list>}+

  <list> can be an explicit rule list, or evaluate to a rule list.

  ### examples:

      trig1 := {cos(~x)*cos(~y) => (cos(x+y)+cos(x-y))/2,
                cos(~x)*sin(~y) => (sin(x+y)-sin(x-y))/2,
                sin(~x)*sin(~y) => (cos(x-y)-cos(x+y))/2,
                cos(~x)^2       => (1+cos(2*x))/2,
                sin(~x)^2       => (1-cos(2*x))/2}$

      let trig1;
      cos(a)*cos(b);

        COS(A - B) + COS(A + B)
        ------------------------
                   2

  A let command returns no value, though the substitution r ule is entered. Assignment rules made by assign and let rules are at the same level, and cancel each other. There is a difference in their operation, however, as shown in the first example: a let assignment tracks the changes in what it is assigned to, while a := assignment is fixed at the value it originally had.

  The use of expressions as left-hand sides of let statements is a little complicated. The rules of operation are:

  _ _ _ (i) Expressions of the form A*B = C do not change A, B or C, but set A*B to C.

  _ _ _ (ii) Expressions of the form A+B = C substitute C - B for A, but do not change B or C.

  _ _ _ (iii) Expressions of the form A-B = C substitute B + C for A, but do not change B or C.

  _ _ _ (iv) Expressions of the form A/B = C substitute B*C for A, but do not change B or C.

  _ _ _ (v) Expressions of the form A**N = C substitute C for A**N in every expression of a power of A to N or greater. An asymptotic command such as A**N = 0 sets all terms involving A to powers greater than or equal to N to 0. Finite fields may be generated by requiring modular arithmetic (the modular switch) and defining the primitive polynomial via a let statement.

  letsubstitutions involving expressions are cleared by using the clear command with exactly the same expressio n.

  Note when a simple let statement is used to assign functionality to an operator, it is valid only for the exact identifiers used. For the use of the let command to attach more general functionality to an operator, see forall.

  Arrays as a whole cannot be arguments to let statements, but matrices as a whole can be legal arguments, provided both arguments are matrices. However, it is important to note that the two matrices are then linked. Any change to an element of one matrix changes the corresponding value in the other. Unless you want this behavior, you should not use let for matrices. The assignment operator assign can be used for non-tracking assignments, avoiding the side effects. Matrices are redimensioned as needed in let statements.

  When array or matrix elements are used as the left-hand side of let statements, the contents of that element is used as the argument. When the contents is a number or some other expression that is not a valid left-hand side for let, you get an error message. If the contents is an identifier or simple expression, the let rule is globally attached to that identifier, and is in effect not only inside the array or matrix, but everywhere. Because of such unwanted side effects, you should not use let with array or matrix elements. The assignment operator := can be used to put values into array or matrix elements without the side effects.

  Local variables declared inside begin...end blocks cannot be used as the left-hand side of let statements. However, begin...end blocks themselves can be used as the right-hand side of let statements. The construction:

  ### syntax:

  for all<vars> let<operator>(<vars>)=<block>

  is an alternative to the

  ### syntax:

  procedure<name>(<vars>);<block>

  construction. One important difference between the two constructions is that the <vars> as formal parameters to a procedure have their global values protected against change by the procedure, while the <vars> of a let statement are changed globally by its actions.

  Be careful in using a construction such as let x = x + 1 except inside a controlled loop statement. The process of resubstitution continues until a stack overflow message is given.

  The let statement may be used to make global changes to variables from inside procedures. If x is a formal parameter to a procedure, the command let x = ... makes the change to the calling variable. For example, if a procedure was defined by

              procedure f(x,y);
              let x = 15;

  and the procedure was called as

              f(a,b);

  awould have its value changed to 15. Be careful when using let statements inside procedures to avoid unwanted side effects.

  It is also important to be careful when replacing let statements with other let statements. The overlapping of these substitutions can be unpredictable. Ordinarily the latest-entered rule is the first to be applied. Sometimes the previous rule is superseded completely; other times it stays around as a special case. The order of entering a set of related let expressions is very important to their eventual behavior. The best approach is to assume that the rules will be applied in an arbitrary order.