Origin for each line in Lesson_4.red from check-in f2c04ccdad:

f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:                   REDUCE INTERACTIVE LESSON NUMBER 4
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:                          David R. Stoutemyer
f2c04ccdad 2021-03-03 trnsz@pobox.c:                          University of Hawaii
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT This is lesson 4 of 7 REDUCE lessons.  As before, please
f2c04ccdad 2021-03-03 trnsz@pobox.c: refrain from using variables beginning with the letters F through H
f2c04ccdad 2021-03-03 trnsz@pobox.c: during the lesson.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: In theory, assignments and LET statements are sufficient to accomplish
f2c04ccdad 2021-03-03 trnsz@pobox.c: anything that any other practical computing mechanism is capable of
f2c04ccdad 2021-03-03 trnsz@pobox.c: doing.  However, it is more convenient for some purposes to use
f2c04ccdad 2021-03-03 trnsz@pobox.c: function procedures which can employ branch selection and iteration as
f2c04ccdad 2021-03-03 trnsz@pobox.c: do most traditional programming languages.  As a trivial example, if
f2c04ccdad 2021-03-03 trnsz@pobox.c: we invariably wanted to replace cotangents with the corresponding
f2c04ccdad 2021-03-03 trnsz@pobox.c: tangents, we could input:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: algebraic procedure cotan(x); 1/tan(x);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT As an example of the use of this function, we have;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: cotan(log(f));
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Note:
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    1.  The procedure definition automatically declares the procedure
f2c04ccdad 2021-03-03 trnsz@pobox.c:        name as an operator.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    2.  A procedure can be executed any time after its definition,
f2c04ccdad 2021-03-03 trnsz@pobox.c:        until it is cleared.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    3.  Any parameters are dummy variables that are distinct from any
f2c04ccdad 2021-03-03 trnsz@pobox.c:        other variables with the same name outside the procedure
f2c04ccdad 2021-03-03 trnsz@pobox.c:        definition, and the corresponding arguments can be arbitrary
f2c04ccdad 2021-03-03 trnsz@pobox.c:        expressions.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    4.  The value returned by a procedure is the value of the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        expression following the procedure statement.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    5.  The function COT is already defined in REDUCE and should not be
f2c04ccdad 2021-03-03 trnsz@pobox.c:        redefined.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: We can replace this definition with a different one:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: algebraic procedure cotan(y); cos(y)/sin(y);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: g1 := cotan(log(f));
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT In place of the word ALGEBRAIC, we can optionally use the word
f2c04ccdad 2021-03-03 trnsz@pobox.c: INTEGER when a function always returns an integer value, or we can
f2c04ccdad 2021-03-03 trnsz@pobox.c: optionally use the word REAL when a function always returns a
f2c04ccdad 2021-03-03 trnsz@pobox.c: floating-point value.  (ALGEBRAIC can also be omitted, since it is the
f2c04ccdad 2021-03-03 trnsz@pobox.c: default procedure type.)
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Try writing a procedure definition for the sine in terms of the
f2c04ccdad 2021-03-03 trnsz@pobox.c: cosine, then type G1.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Here is a more complicated function which introduces the
f2c04ccdad 2021-03-03 trnsz@pobox.c: notion of a conditional expression:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: algebraic procedure sumcheck(aj, j, m, n, s);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    COMMENT J is an indeterminate and the other parameters are
f2c04ccdad 2021-03-03 trnsz@pobox.c:       expressions.  This function returns the global variable named
f2c04ccdad 2021-03-03 trnsz@pobox.c:       PROVED if the function can inductively verify that S equals the
f2c04ccdad 2021-03-03 trnsz@pobox.c:       sum of AJ for J going from M through N, returning the global
f2c04ccdad 2021-03-03 trnsz@pobox.c:       variable named UNPROVED otherwise.  For the best chance of
f2c04ccdad 2021-03-03 trnsz@pobox.c:       proving a correct sum, the function should be executed under the
f2c04ccdad 2021-03-03 trnsz@pobox.c:       influence of ON EXP, ON MCD, and any other user-supplied
f2c04ccdad 2021-03-03 trnsz@pobox.c:       simplification rules relevant to the expression classes of AJ
f2c04ccdad 2021-03-03 trnsz@pobox.c:       and S;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if sub(j=m,aj) - sub(n=m,s) neq 0 or
f2c04ccdad 2021-03-03 trnsz@pobox.c:       s + sub(j=n+1,aj) - sub(n=n+1,s) neq 0 then unproved
f2c04ccdad 2021-03-03 trnsz@pobox.c:     else proved;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: on exp, mcd;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: clear x, j, n;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: sumcheck(j, j, 1, n, n*(n+1)/2);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: sumcheck(x^j, j, 0, n, (x^(n+1)-1)/(x-1));
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Within procedures of this sort a global variable is any
f2c04ccdad 2021-03-03 trnsz@pobox.c: variable which is not one of the parameters, and a global variable has
f2c04ccdad 2021-03-03 trnsz@pobox.c: the value, if any, which is current for that name at the point from
f2c04ccdad 2021-03-03 trnsz@pobox.c: where the procedure is used.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Conditional expressions have the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    IF condition THEN expression1 ELSE expression2.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: There are generally several equivalent ways of writing a conditional
f2c04ccdad 2021-03-03 trnsz@pobox.c: expression.  For example, the body of the above procedure could have
f2c04ccdad 2021-03-03 trnsz@pobox.c: been written
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    IF SUB(J=M,AJ) - SUB(N=M,S) = 0 AND
f2c04ccdad 2021-03-03 trnsz@pobox.c:       S + SUB(J=N+1,AJ) - SUB(N=N+1,S) = 0 THEN PROVED
f2c04ccdad 2021-03-03 trnsz@pobox.c:     ELSE UNPROVED.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Note how we compare a difference with 0, rather than comparing two
f2c04ccdad 2021-03-03 trnsz@pobox.c: nonzero expressions, for reasons explained in lesson 3.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: As an exercise, write a procedure analogous to SUMCHECK for proving
f2c04ccdad 2021-03-03 trnsz@pobox.c: closed-form product formulas, then test it on the valid formula that
f2c04ccdad 2021-03-03 trnsz@pobox.c: COS(N*X) equals the product of COS(J*X)/COS(J*X-X) for J ranging from
f2c04ccdad 2021-03-03 trnsz@pobox.c: 1 through N.  You do not need to include prefatory comments describing
f2c04ccdad 2021-03-03 trnsz@pobox.c: parameters and the returned value until you learn how to use a text
f2c04ccdad 2021-03-03 trnsz@pobox.c: editor.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Most REDUCE statements are also expressions because they have
f2c04ccdad 2021-03-03 trnsz@pobox.c: a value.  The value is usually 0 if nothing else makes sense, but I
f2c04ccdad 2021-03-03 trnsz@pobox.c: will mention the value only if it is useful.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: The value of an assignment statement is the assigned value.  Thus a
f2c04ccdad 2021-03-03 trnsz@pobox.c: multiple assignment, performed right to left, can be achieved by a
f2c04ccdad 2021-03-03 trnsz@pobox.c: sequence of the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:     variable1 := variable2 := ... := variableN := expression.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Moreover, assignments can be inserted within ordinary expressions such
f2c04ccdad 2021-03-03 trnsz@pobox.c: as X*(Y:=5).  Such assignments must usually be parenthesized because
f2c04ccdad 2021-03-03 trnsz@pobox.c: of the low precedence of the assignment operator, and excessive use of
f2c04ccdad 2021-03-03 trnsz@pobox.c: this construct tends to make programs confusing.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT REDUCE treats as a single expression any sequence of
f2c04ccdad 2021-03-03 trnsz@pobox.c: statements preceded by the pair of adjacent characters << and followed
f2c04ccdad 2021-03-03 trnsz@pobox.c: by the pair >>.  The value of such a group expression is the value of
f2c04ccdad 2021-03-03 trnsz@pobox.c: the last statement in the group.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Group expressions facilitate the implementation of tasks that are most
f2c04ccdad 2021-03-03 trnsz@pobox.c: easily stated as a sequence of operations.  However, such sequences
f2c04ccdad 2021-03-03 trnsz@pobox.c: often utilize temporary variables to count, hold intermediate results,
f2c04ccdad 2021-03-03 trnsz@pobox.c: etc., and it is hazardous to use global variables for that purpose.
f2c04ccdad 2021-03-03 trnsz@pobox.c: If a top-level REDUCE statement or another function directly or
f2c04ccdad 2021-03-03 trnsz@pobox.c: indirectly uses that variable name, then its value or its virgin
f2c04ccdad 2021-03-03 trnsz@pobox.c: indeterminate status there might be damaged by our use as a temporary
f2c04ccdad 2021-03-03 trnsz@pobox.c: variable.  In large programs or programs which rely on the work of
f2c04ccdad 2021-03-03 trnsz@pobox.c: others, such interference has a non-negligible probability, even if
f2c04ccdad 2021-03-03 trnsz@pobox.c: all programmers agree to the convention that all such temporary
f2c04ccdad 2021-03-03 trnsz@pobox.c: variables should begin with the function name as a prefix and all
f2c04ccdad 2021-03-03 trnsz@pobox.c: programmers attempt to comply with the convention.  For this reason,
f2c04ccdad 2021-03-03 trnsz@pobox.c: REDUCE provides another expression-valued sequence called a
f2c04ccdad 2021-03-03 trnsz@pobox.c: BEGIN-block, which permits the declaration of local variables that are
f2c04ccdad 2021-03-03 trnsz@pobox.c: distinct from any other variables outside the block having the same
f2c04ccdad 2021-03-03 trnsz@pobox.c: name.  Another advantage of using local variables for temporary
f2c04ccdad 2021-03-03 trnsz@pobox.c: variables is that the perhaps large amount of storage occupied by
f2c04ccdad 2021-03-03 trnsz@pobox.c: their values can be reclaimed after leaving their block.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT A BEGIN-block consists of the word BEGIN, followed by optional
f2c04ccdad 2021-03-03 trnsz@pobox.c: declarations, followed by a sequence of statements, followed by the
f2c04ccdad 2021-03-03 trnsz@pobox.c: word END.  Within BEGIN-blocks, it is often convenient to return
f2c04ccdad 2021-03-03 trnsz@pobox.c: control and possibly a value from someplace other than the end of the
f2c04ccdad 2021-03-03 trnsz@pobox.c: block.  Control and a value may be returned via a RETURN-statement of
f2c04ccdad 2021-03-03 trnsz@pobox.c: the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:           RETURN expression
f2c04ccdad 2021-03-03 trnsz@pobox.c: or
f2c04ccdad 2021-03-03 trnsz@pobox.c:           RETURN,
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: 0 being returned in the latter case.  A BEGIN-block does not return
f2c04ccdad 2021-03-03 trnsz@pobox.c: the value of the last statement.  If a value is to be returned then
f2c04ccdad 2021-03-03 trnsz@pobox.c: RETURN must be used.  These features and others are illustrated by the
f2c04ccdad 2021-03-03 trnsz@pobox.c: following function:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: algebraic procedure limit(ex, indet, pnt);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    begin COMMENT This function uses up through 4 iterations of L'Hospital's
f2c04ccdad 2021-03-03 trnsz@pobox.c:       rule to attempt determination of the limit of expression EX as
f2c04ccdad 2021-03-03 trnsz@pobox.c:       indeterminate INDET approaches expression PNT.  This function is
f2c04ccdad 2021-03-03 trnsz@pobox.c:       intended for the case where SUB(INDET=PNT, EX) yields 0/0,
f2c04ccdad 2021-03-03 trnsz@pobox.c:       provoking a zero-divide message.  This function returns the
f2c04ccdad 2021-03-03 trnsz@pobox.c:       global variable named UNDEFINED when the limit is 0 dividing an
f2c04ccdad 2021-03-03 trnsz@pobox.c:       expression which did not simplify to 0, and this function
f2c04ccdad 2021-03-03 trnsz@pobox.c:       returns the global variable named UNKNOWN when it cannot
f2c04ccdad 2021-03-03 trnsz@pobox.c:       determine the limit.  Otherwise this function returns an
f2c04ccdad 2021-03-03 trnsz@pobox.c:       expression which is the limit.  For best results, this function
f2c04ccdad 2021-03-03 trnsz@pobox.c:       should be executed under the influence of ON EXP, ON MCD, and
f2c04ccdad 2021-03-03 trnsz@pobox.c:       any user-supplied simplification rules appropriate to the
f2c04ccdad 2021-03-03 trnsz@pobox.c:       expression classes of EX and PNT;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    integer iteration;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    scalar n, d, nlim, dlim;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    iteration := 0;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    n := num(ex);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    d := den(ex);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    nlim := sub(indet=pnt, n);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    dlim := sub(indet=pnt, d);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    while nlim=0 and dlim=0 and iteration<5 do <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       n := df(n, indet);
f2c04ccdad 2021-03-03 trnsz@pobox.c:       d := df(d, indet);
f2c04ccdad 2021-03-03 trnsz@pobox.c:       nlim := sub(indet=pnt, n);
f2c04ccdad 2021-03-03 trnsz@pobox.c:       dlim := sub(indet=pnt, d);
f2c04ccdad 2021-03-03 trnsz@pobox.c:       iteration := iteration + 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    return (if nlim=0 then
f2c04ccdad 2021-03-03 trnsz@pobox.c:               if dlim=0 then unknown
f2c04ccdad 2021-03-03 trnsz@pobox.c:               else 0
f2c04ccdad 2021-03-03 trnsz@pobox.c:            else if dlim=0 then undefined
f2c04ccdad 2021-03-03 trnsz@pobox.c:            else nlim/dlim)
f2c04ccdad 2021-03-03 trnsz@pobox.c:    end;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: % Examples follow...
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: g1 := (e^x-1)/x;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: % Evaluation at 0 causes a zero denominator error at top level but
f2c04ccdad 2021-03-03 trnsz@pobox.c: % continue anyway.
f2c04ccdad 2021-03-03 trnsz@pobox.c: sub(x=0, g1);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: limit(g1, x, 0);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: g1:= ((1-x)/log(x))^2;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: % Evaluation at 1 causes a zero denominator error at top level but
f2c04ccdad 2021-03-03 trnsz@pobox.c: % continue anyway.
f2c04ccdad 2021-03-03 trnsz@pobox.c: sub(x=1, g1);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: limit(g1, x, 1);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT  Note:
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    1.  The idea behind L'Hospital's rule is that as long as the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        numerator and denominator are both zero at the limit point, we
f2c04ccdad 2021-03-03 trnsz@pobox.c:        can replace them by their derivatives without altering the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        limit of the quotient.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    2.  Assignments within groups and BEGIN-blocks do not automatically
f2c04ccdad 2021-03-03 trnsz@pobox.c:        cause output.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    3.  Local variables are declared INTEGER, REAL, or SCALAR, the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        latter corresponding to the same most general class denoted by
f2c04ccdad 2021-03-03 trnsz@pobox.c:        ALGEBRAIC in a procedure statement.  All local variables are
f2c04ccdad 2021-03-03 trnsz@pobox.c:        initialized to zero, so they cannot serve as indeterminates.
f2c04ccdad 2021-03-03 trnsz@pobox.c:        Moreover, if we attempted to overcome this by clearing them, we
f2c04ccdad 2021-03-03 trnsz@pobox.c:        would clear all variables with their names.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    4.  We do not declare the attributes of parameters.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    5.  The NUM and DEN functions respectively extract the numerator
f2c04ccdad 2021-03-03 trnsz@pobox.c:        and denominator of their arguments.  (With OFF MCD, the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        denominator of 1+1/X would be 1.)
f2c04ccdad 2021-03-03 trnsz@pobox.c:    6.  The WHILE-loop has the general form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:           WHILE condition DO statement.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:        REDUCE also has a "GO TO" statement, and using commas rather
f2c04ccdad 2021-03-03 trnsz@pobox.c:        than semicolons to prevent termination of this comment, the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        above general form of a WHILE-loop is equivalent to
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:           BEGIN  GO TO TEST,
f2c04ccdad 2021-03-03 trnsz@pobox.c:        LOOP: statement,
f2c04ccdad 2021-03-03 trnsz@pobox.c:        TEST: IF condition THEN GO TO LOOP,
f2c04ccdad 2021-03-03 trnsz@pobox.c:           RETURN 0
f2c04ccdad 2021-03-03 trnsz@pobox.c:           END.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:        A GOTO statement is permitted only within a block, and the GOTO
f2c04ccdad 2021-03-03 trnsz@pobox.c:        statement cannot refer to a label outside the same block or to
f2c04ccdad 2021-03-03 trnsz@pobox.c:        a label inside a block that the GOTO statement is not also
f2c04ccdad 2021-03-03 trnsz@pobox.c:        within.  Actually, 99.99% of REDUCE BEGIN-blocks are less
f2c04ccdad 2021-03-03 trnsz@pobox.c:        confusing if written entirely without GOTOs, and I mention them
f2c04ccdad 2021-03-03 trnsz@pobox.c:        primarily to explain WHILE-loops in terms of a more primitive
f2c04ccdad 2021-03-03 trnsz@pobox.c:        notion.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT
f2c04ccdad 2021-03-03 trnsz@pobox.c:    7.  The LIMIT function provides a good illustration of nested
f2c04ccdad 2021-03-03 trnsz@pobox.c:        conditional expressions.  Proceeding sequentially through such
f2c04ccdad 2021-03-03 trnsz@pobox.c:        nests, each ELSE clause is matched with the nearest preceding
f2c04ccdad 2021-03-03 trnsz@pobox.c:        unmatched THEN clause in the group or block.  In order to help
f2c04ccdad 2021-03-03 trnsz@pobox.c:        reveal their structure, I have consistently indented nested
f2c04ccdad 2021-03-03 trnsz@pobox.c:        conditional statements, continuations of multi-line statements
f2c04ccdad 2021-03-03 trnsz@pobox.c:        and loop-bodies according to one of the many staunchly defended
f2c04ccdad 2021-03-03 trnsz@pobox.c:        indentation styles.  (If you have an instructor, I also urge
f2c04ccdad 2021-03-03 trnsz@pobox.c:        you to humor him by adopting his style for the duration of the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        course.)
f2c04ccdad 2021-03-03 trnsz@pobox.c:    8.  C and Java programmers take note: "IF ... THEN ... ELSE ..." is
f2c04ccdad 2021-03-03 trnsz@pobox.c:        regarded as one expression, and semicolons are used to separate
f2c04ccdad 2021-03-03 trnsz@pobox.c:        rather than terminate statements.  Moreover, BEGIN and END are
f2c04ccdad 2021-03-03 trnsz@pobox.c:        brackets rather than statements, so a semicolon is never needed
f2c04ccdad 2021-03-03 trnsz@pobox.c:        immediately after BEGIN, and a semicolon is necessary
f2c04ccdad 2021-03-03 trnsz@pobox.c:        immediately preceding END only if the END is intended as a
f2c04ccdad 2021-03-03 trnsz@pobox.c:        labeled destination for a GOTO.  Within conditional
f2c04ccdad 2021-03-03 trnsz@pobox.c:        expressions, an inappropriate semicolon after an END, a >>, or
f2c04ccdad 2021-03-03 trnsz@pobox.c:        an ELSE-clause is likely to be one of your most prevalent
f2c04ccdad 2021-03-03 trnsz@pobox.c:        mistakes.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT The next exercise is based on the above LIMIT function:
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: For the sum of positive expressions AJ for J ranging from some finite
f2c04ccdad 2021-03-03 trnsz@pobox.c: initial value to infinity, the infinite series converges if the limit
f2c04ccdad 2021-03-03 trnsz@pobox.c: of the ratio SUB(J=J+1,AJ)/AJ is less than 1 as J approaches infinity.
f2c04ccdad 2021-03-03 trnsz@pobox.c: The series diverges if this limit exceeds 1, and the test is
f2c04ccdad 2021-03-03 trnsz@pobox.c: inconclusive if the limit is 1.  To convert the problem to the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: required by the above LIMIT program, we can replace J by 1/!*FOO in
f2c04ccdad 2021-03-03 trnsz@pobox.c: the ratio, then take the limit as the indeterminate !*FOO approaches
f2c04ccdad 2021-03-03 trnsz@pobox.c: zero.  (Since an indeterminate is necessary here, I picked the weird
f2c04ccdad 2021-03-03 trnsz@pobox.c: name !*FOO to make the chance of conflict negligible.)
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: After writing such a function to perform the ratio test, test it on
f2c04ccdad 2021-03-03 trnsz@pobox.c: the examples AJ=J/2^J, AJ=1/J^2, AJ=2^J/J^10, and AJ=1/J.  (The first
f2c04ccdad 2021-03-03 trnsz@pobox.c: two converge and the second two diverge.);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Groups or blocks can be used wherever any arbitrary expression
f2c04ccdad 2021-03-03 trnsz@pobox.c: is allowed, including the right-hand side of a LET rule.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: The need for loops with an integer index variable running from a given
f2c04ccdad 2021-03-03 trnsz@pobox.c: initial value through a given final value by a given increment is so
f2c04ccdad 2021-03-03 trnsz@pobox.c: prevalent that REDUCE offers a convenient special way of accomplishing
f2c04ccdad 2021-03-03 trnsz@pobox.c: it via a FOR-loop, which has the general form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    FOR index := initial STEP increment UNTIL final DO statement.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Except for the use of commas as statement separators, this construct
f2c04ccdad 2021-03-03 trnsz@pobox.c: is equivalent to
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    BEGIN INTEGER index,
f2c04ccdad 2021-03-03 trnsz@pobox.c:    index := initial,
f2c04ccdad 2021-03-03 trnsz@pobox.c:    IF increment>0 THEN WHILE index <= final DO <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       statement,
f2c04ccdad 2021-03-03 trnsz@pobox.c:       index := index + increment >>
f2c04ccdad 2021-03-03 trnsz@pobox.c:    ELSE WHILE index >= final DO <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       statement,
f2c04ccdad 2021-03-03 trnsz@pobox.c:       index := index + increment >>,
f2c04ccdad 2021-03-03 trnsz@pobox.c:    RETURN 0
f2c04ccdad 2021-03-03 trnsz@pobox.c:    END;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Note:
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    1.  The index variable is automatically declared local to the FOR-
f2c04ccdad 2021-03-03 trnsz@pobox.c:        loop.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    2.  "initial", "increment", and "final" must have integer values.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    3.  FORTRAN programmers take note: the body of the loop is not
f2c04ccdad 2021-03-03 trnsz@pobox.c:        automatically executed at least once.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    4.  An abbreviation for "STEP 1 UNTIL" is ":".
f2c04ccdad 2021-03-03 trnsz@pobox.c:    5.  Since the WHILE-loop and the FOR-loop have implied BEGIN-
f2c04ccdad 2021-03-03 trnsz@pobox.c:        blocks, a RETURN statement within their bodies cannot transfer
f2c04ccdad 2021-03-03 trnsz@pobox.c:        control further than the point following the loops.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Another frequent need is to produce output from within a group or
f2c04ccdad 2021-03-03 trnsz@pobox.c: block, because such output is not automatically produced.  This can be
f2c04ccdad 2021-03-03 trnsz@pobox.c: done using the WRITE-statement, which has the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    WRITE expression1, expression2, ..., expressionN.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Beginning a new line with expression1, the expressions are printed
f2c04ccdad 2021-03-03 trnsz@pobox.c: immediately adjacent to each other, split over line boundaries if
f2c04ccdad 2021-03-03 trnsz@pobox.c: necessary.  The value of the WRITE-statement is the value of its last
f2c04ccdad 2021-03-03 trnsz@pobox.c: expression, and any of the expressions can be a character-string of
f2c04ccdad 2021-03-03 trnsz@pobox.c: the form "character1 character2 ... characterM".
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Inserting the word "WRITE" on a separate line before an assignment is
f2c04ccdad 2021-03-03 trnsz@pobox.c: convenient for debugging, because the word is then easily deleted
f2c04ccdad 2021-03-03 trnsz@pobox.c: afterward.  These features and others are illustrated by the following
f2c04ccdad 2021-03-03 trnsz@pobox.c: equation solver:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: operator solvefor, soln;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for all x, lhs, rhs let solvefor(x, lhs, rhs) = solvefor(x, lhs-rhs);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT LHS and RHS are expressions such that P=NUM(LHS-RHS) is a
f2c04ccdad 2021-03-03 trnsz@pobox.c: polynomial of degree at most 2 in the indeterminate or functional form
f2c04ccdad 2021-03-03 trnsz@pobox.c: X.  Otherwise an error message is printed.  As a convenience, RHS can
f2c04ccdad 2021-03-03 trnsz@pobox.c: be omitted if it is 0.  If P is quadratic in X, the two values of X
f2c04ccdad 2021-03-03 trnsz@pobox.c: which satisfy P=0 are stored as the values of the functional forms
f2c04ccdad 2021-03-03 trnsz@pobox.c: SOLN(1) and SOLN(2).  If P is a first-degree polynomial in X, SOLN(1)
f2c04ccdad 2021-03-03 trnsz@pobox.c: is set to the one solution.  If P simplifies to 0, SOLN(1) is set to
f2c04ccdad 2021-03-03 trnsz@pobox.c: the identifier ARBITRARY.  If P is an expression which does not
f2c04ccdad 2021-03-03 trnsz@pobox.c: simplify to zero but does not contain X, SOLN(1) is set to the
f2c04ccdad 2021-03-03 trnsz@pobox.c: identifier NONE.  In all other cases, SOLN(1) is set to the identifier
f2c04ccdad 2021-03-03 trnsz@pobox.c: UNKNOWN.  The function then returns the number of SOLN forms which
f2c04ccdad 2021-03-03 trnsz@pobox.c: were set.  This function prints a well deserved warning message if the
f2c04ccdad 2021-03-03 trnsz@pobox.c: denominator of LHS-RHS contains X.  If LHS-RHS is not polynomial in X,
f2c04ccdad 2021-03-03 trnsz@pobox.c: it is wise to execute this function under the influence of ON GCD.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for all x, lhsmrhs let solvefor(x, lhsmrhs) =
f2c04ccdad 2021-03-03 trnsz@pobox.c:    begin integer hipow;  scalar temp, cflist, cf0, cf1, cf2;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if lhsmrhs = 0 then <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       soln(1) := arbitrary;
f2c04ccdad 2021-03-03 trnsz@pobox.c:       return 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    cflist :=  coeff(lhsmrhs, x);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    hipow := hipow!*;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if hipow = 0 then <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       soln(1) := none;
f2c04ccdad 2021-03-03 trnsz@pobox.c:       return 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if hipow > 2 then <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       soln(1) := unknown;
f2c04ccdad 2021-03-03 trnsz@pobox.c:       return 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if hipow = 1 then <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       soln(1) := first(cflist)/second(cflist);
f2c04ccdad 2021-03-03 trnsz@pobox.c:       if df(sub(x=!*foo, soln(1)), !*foo) neq 0 then
f2c04ccdad 2021-03-03 trnsz@pobox.c:          soln(1) := unknown;
f2c04ccdad 2021-03-03 trnsz@pobox.c:       return 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    cf0 := first(cflist)/third(cflist);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    cf1 := -second(cflist)/third(cflist)/2;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    if df(sub(x=!*foo, cf0), !*foo) neq 0
f2c04ccdad 2021-03-03 trnsz@pobox.c:          or df(sub(x=!*foo, cf1), !*foo) neq 0  then <<
f2c04ccdad 2021-03-03 trnsz@pobox.c:       soln(1) := unknown;
f2c04ccdad 2021-03-03 trnsz@pobox.c:       return 1 >>;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    temp := (cf1^2 - cf0)^(1/2);
f2c04ccdad 2021-03-03 trnsz@pobox.c:    soln(1) := cf1 + temp;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    soln(2) := cf1 - temp;
f2c04ccdad 2021-03-03 trnsz@pobox.c:    return 2
f2c04ccdad 2021-03-03 trnsz@pobox.c:    end;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT And some examples:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(x, a*x^2, -b*x-c) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(log(x), 5*log(x)-7) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(x, x, x) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:= 1:solvefor(x, 5) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(x, x^3+x+1) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(x, x*e^x, 1) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: g1 := x/(e^x-1);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: % Results in 'invalid as polynomial' error, continue anyway:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: for k:=1:solvefor(x, g1) do write soln(k) := soln(k);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: sub(x=soln(1), g1);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: limit(g1, x, soln(1));
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT Here we have used LET rules to permit the user the convenience
f2c04ccdad 2021-03-03 trnsz@pobox.c: of omitting default arguments.  (Function definitions have to have a
f2c04ccdad 2021-03-03 trnsz@pobox.c: fixed number of parameters.)
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: Array elements are designated by the same syntax as matrix elements,
f2c04ccdad 2021-03-03 trnsz@pobox.c: namely as functional forms having integer arguments.  Here are some
f2c04ccdad 2021-03-03 trnsz@pobox.c: desiderata that may help you decide which of these alternatives is
f2c04ccdad 2021-03-03 trnsz@pobox.c: most appropriate for a particular application:
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    1.  The lower bound of each array subscript is 0 vs. 1 for
f2c04ccdad 2021-03-03 trnsz@pobox.c:        matrices vs. unrestricted for functional forms.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    2.  The upper bound of each array subscript must have a specific
f2c04ccdad 2021-03-03 trnsz@pobox.c:        integer value at the time the array is declared, as must the
f2c04ccdad 2021-03-03 trnsz@pobox.c:        upper bounds of matrix subscripts when a matrix is first
f2c04ccdad 2021-03-03 trnsz@pobox.c:        referred to, on the left side of a matrix assignment.  In
f2c04ccdad 2021-03-03 trnsz@pobox.c:        contrast, functional forms never require a commitment to a
f2c04ccdad 2021-03-03 trnsz@pobox.c:        specific upper bound.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    3.  An array can have any fixed number of subscripts, a matrix must
f2c04ccdad 2021-03-03 trnsz@pobox.c:        have exactly 2, and a functional form can have a varying
f2c04ccdad 2021-03-03 trnsz@pobox.c:        arbitrary number.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    4.  Matrix operations, such as transpose and inverse, are built-in
f2c04ccdad 2021-03-03 trnsz@pobox.c:        only for matrices.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    5.  For most implementations, access to array elements requires
f2c04ccdad 2021-03-03 trnsz@pobox.c:        time approximately proportional to the number of subscripts,
f2c04ccdad 2021-03-03 trnsz@pobox.c:        whereas access to matrix elements takes time approximately
f2c04ccdad 2021-03-03 trnsz@pobox.c:        proportional to the sum of the two subscript values, whereas
f2c04ccdad 2021-03-03 trnsz@pobox.c:        access to functional forms takes average time approximately
f2c04ccdad 2021-03-03 trnsz@pobox.c:        proportional to the number of bound functional forms having
f2c04ccdad 2021-03-03 trnsz@pobox.c:        that name.
f2c04ccdad 2021-03-03 trnsz@pobox.c:    6.  Only functional forms permit the effect of a subscripted
f2c04ccdad 2021-03-03 trnsz@pobox.c:        indeterminate such as having an answer be "A(M,N) + B(3,4)".
f2c04ccdad 2021-03-03 trnsz@pobox.c:    7.  Only functional forms can be used alone in the LHS of LET
f2c04ccdad 2021-03-03 trnsz@pobox.c:        substitutions.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT
f2c04ccdad 2021-03-03 trnsz@pobox.c:    8.  All arrays, matrices, and operators are global regardless of
f2c04ccdad 2021-03-03 trnsz@pobox.c:        where they are declared, so declaring them within a BEGIN-block
f2c04ccdad 2021-03-03 trnsz@pobox.c:        does not afford the protection and automatic storage recovery
f2c04ccdad 2021-03-03 trnsz@pobox.c:        of local variables.  Moreover, clearing them within a
f2c04ccdad 2021-03-03 trnsz@pobox.c:        BEGIN-block will clear them globally, and normal functions
f2c04ccdad 2021-03-03 trnsz@pobox.c:        cannot return an array or a matrix value.  Furthermore, REDUCE
f2c04ccdad 2021-03-03 trnsz@pobox.c:        parameters are referenced by value, which means that an
f2c04ccdad 2021-03-03 trnsz@pobox.c:        assignment to a parameter has no effect on the corresponding
f2c04ccdad 2021-03-03 trnsz@pobox.c:        argument.  Thus, matrix or array results cannot be transmitted
f2c04ccdad 2021-03-03 trnsz@pobox.c:        back to an argument either.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    9.  It is often advantageous to use two or more of these
f2c04ccdad 2021-03-03 trnsz@pobox.c:        alternatives to represent a set of quantities at different
f2c04ccdad 2021-03-03 trnsz@pobox.c:        times in the same program.  For example, to get the general
f2c04ccdad 2021-03-03 trnsz@pobox.c:        form of the inverse of a 3-by-3 matrix, we could write
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:           MATRIX AA(3,3),
f2c04ccdad 2021-03-03 trnsz@pobox.c:           OPERATOR A,
f2c04ccdad 2021-03-03 trnsz@pobox.c:           FOR J:=1:3 DO
f2c04ccdad 2021-03-03 trnsz@pobox.c:              FOR K:=1:3 DO AA(J,K) := A(J,K),
f2c04ccdad 2021-03-03 trnsz@pobox.c:           AA^-1.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:        As another example, we might use an array to receive some
f2c04ccdad 2021-03-03 trnsz@pobox.c:        polynomial coefficients, then transfer the values to a matrix
f2c04ccdad 2021-03-03 trnsz@pobox.c:        for inversion.;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT The COEFF function is the remaining new feature in our
f2c04ccdad 2021-03-03 trnsz@pobox.c: SOLVEFOR example.  The first argument is a polynomial expression in
f2c04ccdad 2021-03-03 trnsz@pobox.c: the indeterminate or functional form which is the second argument.
f2c04ccdad 2021-03-03 trnsz@pobox.c: The polynomial coefficients of the integer powers of the indeterminate
f2c04ccdad 2021-03-03 trnsz@pobox.c: are returned as a LIST, with the independent coefficient first.  The
f2c04ccdad 2021-03-03 trnsz@pobox.c: highest and lowest non-zero powers are placed in the variables HIPOW!*
f2c04ccdad 2021-03-03 trnsz@pobox.c: and LOWPOW!* respectively.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: A LIST is a kind of data structure, just as matrices and arrays are.
f2c04ccdad 2021-03-03 trnsz@pobox.c: It is represented as a comma-separated sequence of elements enclosed
f2c04ccdad 2021-03-03 trnsz@pobox.c: in braces.  The elements can be accessed with the functions FIRST,
f2c04ccdad 2021-03-03 trnsz@pobox.c: SECOND, THIRD, PART(i) which returns the i-th element, and REST, which
f2c04ccdad 2021-03-03 trnsz@pobox.c: returns a list of all but the first element.  For example:;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: clear x;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: coeff(x^5+2, x);
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: lowpow!*;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: hipow!*;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: pause;
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: COMMENT COEFF does not check to make sure that the coefficients do not
f2c04ccdad 2021-03-03 trnsz@pobox.c: contain its second argument within a functional form, so that is the
f2c04ccdad 2021-03-03 trnsz@pobox.c: reason we differentiated.  The reason we first substituted the
f2c04ccdad 2021-03-03 trnsz@pobox.c: indeterminate !*FOO for the second argument is that differentiation
f2c04ccdad 2021-03-03 trnsz@pobox.c: does not work with respect to a functional form.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: The last exercise is to rewrite the last rule so that we can solve
f2c04ccdad 2021-03-03 trnsz@pobox.c: equations which simplify to the form
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    a*x^(m+2*l) + b*x^(m+l) + c*x^m = 0,  where m >= 0 and l >= 1.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: The solutions are
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    0,  with multiplicity m,
f2c04ccdad 2021-03-03 trnsz@pobox.c:    x1*E^(2*j*I*pi/l),
f2c04ccdad 2021-03-03 trnsz@pobox.c:    x2*E^(2*j*I*pi/l),  with j = 0, 1, ..., l-1,
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: where x1 and x2 are the solutions to the quadratic equation
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c:    a*x^2 + b*x + c = 0.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: As a convenience to the user, you might also wish to have a global
f2c04ccdad 2021-03-03 trnsz@pobox.c: switch named SOLVEPRINT, such that when it is nonzero, the solutions
f2c04ccdad 2021-03-03 trnsz@pobox.c: are automatically printed.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: This is the end of lesson 4.  When you are ready to run lesson 5,
f2c04ccdad 2021-03-03 trnsz@pobox.c: start a new REDUCE session.
f2c04ccdad 2021-03-03 trnsz@pobox.c: 
f2c04ccdad 2021-03-03 trnsz@pobox.c: ;end;

iCAS Bundled REDUCE Scripts
Homepage | GitHub Mirror | SourceHut Mirror | NotABug Mirror | Chisel Mirror | Chisel RSS ]