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