Origin for each line in Lesson_3.red from check-in 5f892713c3:

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 3
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:                         Update for REDUCE 3.4
5f892713c3 2021-03-03 trnsz@pobox.c:                             Herbert Melenk
5f892713c3 2021-03-03 trnsz@pobox.c:                       Konrad-Zuse-Zentrum Berlin
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 3 of 7 REDUCE lessons.  Please refrain from
5f892713c3 2021-03-03 trnsz@pobox.c: using variables beginning with the letters F through H during the
5f892713c3 2021-03-03 trnsz@pobox.c: lesson.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Mathematics is replete with many named elementary and not-so-
5f892713c3 2021-03-03 trnsz@pobox.c: elementary functions besides the set built into REDUCE such as SIN,
5f892713c3 2021-03-03 trnsz@pobox.c: COS, and LOG, and it is often convenient to utilize expressions
5f892713c3 2021-03-03 trnsz@pobox.c: containing a functional form such as F(X) to denote an unknown
5f892713c3 2021-03-03 trnsz@pobox.c: function or a class of functions.  Functions are called operators in
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE, and by merely declaring their names as such, we are free to
5f892713c3 2021-03-03 trnsz@pobox.c: use them for functional forms.  For example:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: operator f;
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := f(f(cot(f)), f());
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Note that
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  We can use the same name for both a variable and an operator.
5f892713c3 2021-03-03 trnsz@pobox.c:        (However, this practice often leads to confusion.)
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  We can use the same operator for any number of arguments --
5f892713c3 2021-03-03 trnsz@pobox.c:        including zero arguments such as for F().
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  We can assign values to specific instances of functional
5f892713c3 2021-03-03 trnsz@pobox.c:        forms.;
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 COT is one of the functions already defined in REDUCE together
5f892713c3 2021-03-03 trnsz@pobox.c: with a few of its properties.  However, you can augment or even
5f892713c3 2021-03-03 trnsz@pobox.c: override these definitions depending on the needs of a given problem.
5f892713c3 2021-03-03 trnsz@pobox.c: For example, if you wished to write COT(F) in terms of TAN, you could
5f892713c3 2021-03-03 trnsz@pobox.c: say:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: cot(f) := 1/tan(f);
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := g1 + cot(h+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 Naturally, our assignment for COT(F) did not affect COT(H+1)
5f892713c3 2021-03-03 trnsz@pobox.c: in our example above.  However, we can use a LET rule to make all
5f892713c3 2021-03-03 trnsz@pobox.c: cotangents automatically be replaced by the reciprocal of the
5f892713c3 2021-03-03 trnsz@pobox.c: corresponding tangents:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: let cot(~f) => 1/tan(f);
5f892713c3 2021-03-03 trnsz@pobox.c: g1;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Any variable preceded by a tilde is a dummy variable which is
5f892713c3 2021-03-03 trnsz@pobox.c: distinct from any other previously or subsequently introduced
5f892713c3 2021-03-03 trnsz@pobox.c: indeterminate, variable, or dummy variable having the same name
5f892713c3 2021-03-03 trnsz@pobox.c: outside the rule.  The leftmost occurrence of a dummy variable in a
5f892713c3 2021-03-03 trnsz@pobox.c: rule must be marked with a tilde.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: The arguments to LET are either single rules or lists (explicitly
5f892713c3 2021-03-03 trnsz@pobox.c: enclosed in {..} or as variables with list values).  All elements of a
5f892713c3 2021-03-03 trnsz@pobox.c: list have to be rules (i.e., expressions written in terms of the
5f892713c3 2021-03-03 trnsz@pobox.c: operator "=>") or names of other rule lists.  So we could have written
5f892713c3 2021-03-03 trnsz@pobox.c: the above command either as
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       LET COT(~F) => 1/TAN(F)
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: or as the command sequence
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       RS := {COT(~F) => 1/TAN(F)}
5f892713c3 2021-03-03 trnsz@pobox.c:       LET RS
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: The CLEARRULES command clears one or more rules.  They have to be
5f892713c3 2021-03-03 trnsz@pobox.c: entered in the same form as for LET -- otherwise REDUCE is unable to
5f892713c3 2021-03-03 trnsz@pobox.c: identify them.;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: clearrules cot(~f) => 1/tan(f);
5f892713c3 2021-03-03 trnsz@pobox.c: cot(g+5);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Alternative forms would have been
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:      CLEARRULES {COT(~F) => 1/TAN(F)}
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    or with the above value of RS
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:      CLEARRULES RS
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Note that CLEAR RS would not remove the rule(s) from the system -- it
5f892713c3 2021-03-03 trnsz@pobox.c: would only remove the list value from the variable RS.;
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 arguments of a functional form on the left-hand side of a
5f892713c3 2021-03-03 trnsz@pobox.c: rule can be more complicated than mere indeterminates.  For example,
5f892713c3 2021-03-03 trnsz@pobox.c: we may wish to inform REDUCE how to differentiate expressions
5f892713c3 2021-03-03 trnsz@pobox.c: involving a symbolic function P, whose derivative is expressed in
5f892713c3 2021-03-03 trnsz@pobox.c: terms of another function Q.;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: operator p, q;
5f892713c3 2021-03-03 trnsz@pobox.c: let df(p(~x), x) => q(x)^2;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: df(3*p(f*g), g);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Also, REDUCE obviously knows the chain rule.;
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 As another example, suppose that we wish to employ the
5f892713c3 2021-03-03 trnsz@pobox.c: angle-sum identities for SIN and COS:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: let {sin(~x+~y) => sin(x)*cos(y) + sin(y)*cos(x),
5f892713c3 2021-03-03 trnsz@pobox.c:      cos(~x+~y) => cos(x)*cos(y) - sin(x)*sin(y)};
5f892713c3 2021-03-03 trnsz@pobox.c: cos(5 + f - g);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Note that:
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  LET can have any number of replacement rules written as a list.
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  There was no need for rules with 3 or more addends, because the
5f892713c3 2021-03-03 trnsz@pobox.c:        above rules were automatically employed recursively, with two
5f892713c3 2021-03-03 trnsz@pobox.c:        of the three addends 5, F, and -G grouped together as one of
5f892713c3 2021-03-03 trnsz@pobox.c:        the dummy variables the first time through.
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  Despite the sub-expression F-G in our example, there was no
5f892713c3 2021-03-03 trnsz@pobox.c:        need to make rules for the difference of two angles, because
5f892713c3 2021-03-03 trnsz@pobox.c:        sub-expressions of the form X-Y are treated as X+(-Y).
5f892713c3 2021-03-03 trnsz@pobox.c:    4.  Built-in rules were employed to convert expressions of the form
5f892713c3 2021-03-03 trnsz@pobox.c:        SIN(-X) or COS(-X) to -SIN(X) or COS(X) respectively.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: As an exercise, try to implement rules which transform the logarithms
5f892713c3 2021-03-03 trnsz@pobox.c: of products and quotients respectively to sums and differences of
5f892713c3 2021-03-03 trnsz@pobox.c: logarithms, while converting the logarithm of a power of a quantity to
5f892713c3 2021-03-03 trnsz@pobox.c: the power times the logarithm of the quantity.;
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 Actually, the left-hand side of a rule also can be somewhat
5f892713c3 2021-03-03 trnsz@pobox.c: more general than a functional form.  The left-hand side can be a
5f892713c3 2021-03-03 trnsz@pobox.c: power of an indeterminate or of a functional form, or a product of
5f892713c3 2021-03-03 trnsz@pobox.c: such powers and/or indeterminates or functional forms.  For example,
5f892713c3 2021-03-03 trnsz@pobox.c: we can have the rule
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:        SIN(~X)^2 => 1 - COS(~X)^2
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: or we can have the rule:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: let cos(~x)^2 => 1 - sin(~x)^2;
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := cos(f)^3 + cos(g);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Note that a replacement takes place wherever the left-hand
5f892713c3 2021-03-03 trnsz@pobox.c: side of a rule divides a term.  With a rule replacing SIN(X)^2 and a
5f892713c3 2021-03-03 trnsz@pobox.c: rule replacing COS(X)^2 simultaneously in effect, an expression which
5f892713c3 2021-03-03 trnsz@pobox.c: uses either one will lead to an infinite recursion that eventually
5f892713c3 2021-03-03 trnsz@pobox.c: exhausts the available storage.  (Try it if you wish -- after the
5f892713c3 2021-03-03 trnsz@pobox.c: lesson).  We are also permitted to employ a more symmetric rule using
5f892713c3 2021-03-03 trnsz@pobox.c: a top level "+" provided that no free variables appear in the rule.
5f892713c3 2021-03-03 trnsz@pobox.c: However, a rule such as "SIN(~X)^2 + COS(X)^2 => 1" is not permitted.
5f892713c3 2021-03-03 trnsz@pobox.c: We can get around the restriction against a top-level "+" on the
5f892713c3 2021-03-03 trnsz@pobox.c: left-hand side though, at the minor nuisance of having to employ an
5f892713c3 2021-03-03 trnsz@pobox.c: operator whenever we want the rule applied to an expression:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: clearrules cos(~x)^2 => 1 - sin(~x)^2;
5f892713c3 2021-03-03 trnsz@pobox.c: operator trigsimp;
5f892713c3 2021-03-03 trnsz@pobox.c: trigsimp_rules := {
5f892713c3 2021-03-03 trnsz@pobox.c:    trigsimp(~a*sin(~x)^2 + a*cos(x)^2 + ~c) => a + trigsimp(c),
5f892713c3 2021-03-03 trnsz@pobox.c:    trigsimp(~a*sin(~x)^2 + a*cos(x)^2) => a,
5f892713c3 2021-03-03 trnsz@pobox.c:    trigsimp(sin(~x)^2 + cos(x)^2 + ~c) => 1 + trigsimp(c),
5f892713c3 2021-03-03 trnsz@pobox.c:    trigsimp(sin(~x)^2 + cos(x)^2) => 1,
5f892713c3 2021-03-03 trnsz@pobox.c:    trigsimp(~x) => x }$
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := f*cos(g)^2 + f*sin(g)^2 + g*sin(g)^2 + g*cos(g)^2 + 5;
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := trigsimp(g1) where trigsimp_rules;
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 use another syntactical paradigm: the rule list is
5f892713c3 2021-03-03 trnsz@pobox.c: assigned to a name (here TRIGSIMP_RULES) and it is activated only
5f892713c3 2021-03-03 trnsz@pobox.c: locally for one evaluation, using the WHERE clause.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Why doesn't our rule TRIGSIMP(~X) => X defeat the other more specific
5f892713c3 2021-03-03 trnsz@pobox.c: ones?  The reason is that rules inside a list are applied in the order
5f892713c3 2021-03-03 trnsz@pobox.c: they are written, with the whole process immediately restarted
5f892713c3 2021-03-03 trnsz@pobox.c: whenever any rule succeeds.  Thus the rule TRIGSIMP(X) = X, intended
5f892713c3 2021-03-03 trnsz@pobox.c: to make the operator TRIGSIMP eventually evaporate, is tried only
5f892713c3 2021-03-03 trnsz@pobox.c: after all of the genuine simplification rules have done all they can.
5f892713c3 2021-03-03 trnsz@pobox.c: For such reasons we usually write rules for an operator in an order
5f892713c3 2021-03-03 trnsz@pobox.c: which proceeds from the most specific to the most general cases.
5f892713c3 2021-03-03 trnsz@pobox.c: Experimentation will reveal that TRIGSIMP will not simplify higher
5f892713c3 2021-03-03 trnsz@pobox.c: powers of sine and cosine, such as COS(X)^4 + 2*COS(X)^2*SIN(X)^2 +
5f892713c3 2021-03-03 trnsz@pobox.c: SIN(X)^4, and that TRIGSIMP will not necessarily work when there are
5f892713c3 2021-03-03 trnsz@pobox.c: more than 6 terms.  This latter restriction is not fundamental but is
5f892713c3 2021-03-03 trnsz@pobox.c: a practical one imposed to keep the combinatorial searching associated
5f892713c3 2021-03-03 trnsz@pobox.c: with the current algorithm under reasonable control.  As an exercise,
5f892713c3 2021-03-03 trnsz@pobox.c: see if you can generalize the rules sufficiently so that 5*COS(H)^2 +
5f892713c3 2021-03-03 trnsz@pobox.c: 6*SIN(H)^2 simplifies to 5 + SIN(H)^2 or to 6 - COS(H)^2.;
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 Rules do not need to have free variables.  For example, we
5f892713c3 2021-03-03 trnsz@pobox.c: could introduce the simplification rule to replace all subsequent
5f892713c3 2021-03-03 trnsz@pobox.c: instances of M*C^2 by ENERGY:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: clear m, c, energy;
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := (3*m^2*c^2 + m*c^3 + c^2 + m + m*c + m1*c1^2)
5f892713c3 2021-03-03 trnsz@pobox.c:               where m*c^2 => energy;
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Suppose that instead we wish to replace M by ENERGY/C^2:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: g1 where m => energy/c^2;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT You may wonder how a rule of the trivial form 
5f892713c3 2021-03-03 trnsz@pobox.c: "indeterminate => ..." differs from the corresponding assignment 
5f892713c3 2021-03-03 trnsz@pobox.c: "indeterminate := ...".  The difference is this:
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  The LET rule does not replace any contained bound
5f892713c3 2021-03-03 trnsz@pobox.c:        variables with their values until the rule is actually used for
5f892713c3 2021-03-03 trnsz@pobox.c:        a replacement.
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  The LET rule performs the evaluation of any contained bound
5f892713c3 2021-03-03 trnsz@pobox.c:        variables every time the rule is used.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Thus, the rule "X => X + 1" would cause infinite recursion at the
5f892713c3 2021-03-03 trnsz@pobox.c: first subsequent occurrence of X, as would the pair of rules "{X => Y,
5f892713c3 2021-03-03 trnsz@pobox.c: Y => X}".  (Try it! -- After the lesson.)  To illustrate point 1
5f892713c3 2021-03-03 trnsz@pobox.c: above, compare the following command sequence with the analogous
5f892713c3 2021-03-03 trnsz@pobox.c: earlier one in lesson 2, which used assignments throughout:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: clear e1, f;
5f892713c3 2021-03-03 trnsz@pobox.c: e2 := f;
5f892713c3 2021-03-03 trnsz@pobox.c: let f1 => e1 + e2;
5f892713c3 2021-03-03 trnsz@pobox.c: f1;
5f892713c3 2021-03-03 trnsz@pobox.c: e2 := g;
5f892713c3 2021-03-03 trnsz@pobox.c: f1;
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT For a subsequent example, we need to replace E^(I*X) by
5f892713c3 2021-03-03 trnsz@pobox.c: COS(X)^2 + I*SIN(X)^2 for all X.  See if you can successfully
5f892713c3 2021-03-03 trnsz@pobox.c: introduce this rule.  (Without it, the following code will not work
5f892713c3 2021-03-03 trnsz@pobox.c: correctly!);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: e^i;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT REDUCE does not match I as an instance of the pattern I*X with
5f892713c3 2021-03-03 trnsz@pobox.c: X = 1, so if you neglected to include a rule for this degenerate case,
5f892713c3 2021-03-03 trnsz@pobox.c: do so now.;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: clear x, n, nminusone;
5f892713c3 2021-03-03 trnsz@pobox.c: zero := e^(n*i*x) - e^(nminusone*i*x)*e^(i*x);
5f892713c3 2021-03-03 trnsz@pobox.c: realzero := sub(i=0, zero);
5f892713c3 2021-03-03 trnsz@pobox.c: imagzero := sub(i=0, -i*zero);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Regarding the last two assignments as equations, we can solve
5f892713c3 2021-03-03 trnsz@pobox.c: them to get recurrence relations defining SIN(N*X) and COS(N*X) in
5f892713c3 2021-03-03 trnsz@pobox.c: terms of angles having lower multiplicity.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Can you figure out why I didn't use N-1 rather than NMINUSONE above?
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Can you devise a similar technique to derive the angle-sum identities
5f892713c3 2021-03-03 trnsz@pobox.c: that we previously implemented?;
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 To implement a set of trigonometric multiple-angle expansion
5f892713c3 2021-03-03 trnsz@pobox.c: rules, we need to match the patterns SIN(N*X) and COS(N*X) only when N
5f892713c3 2021-03-03 trnsz@pobox.c: is an integer exceeding 1.  We can implement one of the necessary
5f892713c3 2021-03-03 trnsz@pobox.c: rules as follows:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    cos(~n*~x) => cos(x)*cos((n-1)*x) - sin(x)*sin((n-1)*x)
5f892713c3 2021-03-03 trnsz@pobox.c:              when fixp n and n>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.  In a conditional rule, any dummy variables should appear in the
5f892713c3 2021-03-03 trnsz@pobox.c:        left-hand side of the replacement with a tilde.
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  FIXP, standing for FIX Predicate, is a built-in function which
5f892713c3 2021-03-03 trnsz@pobox.c:        yields true if and only if its argument is an integer.  Other
5f892713c3 2021-03-03 trnsz@pobox.c:        useful predicates are NUMBERP, which is true if its argument
5f892713c3 2021-03-03 trnsz@pobox.c:        represents a numeric value, that is an integer, a rational
5f892713c3 2021-03-03 trnsz@pobox.c:        number or a rounded (floating point) number, and EVENP, which
5f892713c3 2021-03-03 trnsz@pobox.c:        is true if its argument is an integer multiple of 2.
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  Arbitrarily-complicated true-false conditions can be composed
5f892713c3 2021-03-03 trnsz@pobox.c:        using the relational operators =, NEQ, <, >, <=, >=, together
5f892713c3 2021-03-03 trnsz@pobox.c:        with the logical operators "AND", "OR", "NOT".
5f892713c3 2021-03-03 trnsz@pobox.c:    4.  The operators < , >, <=, and >= work only when both sides are
5f892713c3 2021-03-03 trnsz@pobox.c:        numbers.
5f892713c3 2021-03-03 trnsz@pobox.c:    5.  The relational operators have higher precedence than "NOT",
5f892713c3 2021-03-03 trnsz@pobox.c:        which has higher precedence than "AND", which has higher
5f892713c3 2021-03-03 trnsz@pobox.c:        precedence than "OR".
5f892713c3 2021-03-03 trnsz@pobox.c:    6.  In a sequence of expressions joined by "AND" operators, testing
5f892713c3 2021-03-03 trnsz@pobox.c:        is done left to right, and testing is discontinued after the
5f892713c3 2021-03-03 trnsz@pobox.c:        first item which is false.
5f892713c3 2021-03-03 trnsz@pobox.c:    7.  In a sequence of expressions joined by "OR" operators, testing
5f892713c3 2021-03-03 trnsz@pobox.c:        is done left to right, and testing is discontinued after the
5f892713c3 2021-03-03 trnsz@pobox.c:        first item which is true.
5f892713c3 2021-03-03 trnsz@pobox.c:    8.  We didn't actually need the "AND N>1" part in the above rule.
5f892713c3 2021-03-03 trnsz@pobox.c:        Can you guess why?
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Your mission is to complete the set of multiple-angle rules and to
5f892713c3 2021-03-03 trnsz@pobox.c: test them on the example COS(4*X) + COS(X/3) + COS(F*X).;
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 Now suppose that we wish to write a set of rules for doing
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic integration, such that expressions of the form
5f892713c3 2021-03-03 trnsz@pobox.c: INTEGRATE(X^P, X) are replaced by X^(P+1)/(P+1) for arbitrary X and P,
5f892713c3 2021-03-03 trnsz@pobox.c: provided P is independent of X.  This will of course be less complete
5f892713c3 2021-03-03 trnsz@pobox.c: that the analytic integration package available with REDUCE, but for
5f892713c3 2021-03-03 trnsz@pobox.c: specific classes of integrals it is often a reasonable way to do such
5f892713c3 2021-03-03 trnsz@pobox.c: integration.  Noting that DF(P,X) is 0 if P is independent of X, we
5f892713c3 2021-03-03 trnsz@pobox.c: can accomplish this as follows:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: operator integrate;
5f892713c3 2021-03-03 trnsz@pobox.c: let integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0;
5f892713c3 2021-03-03 trnsz@pobox.c: integrate(f^5, f);
5f892713c3 2021-03-03 trnsz@pobox.c: integrate(g^g, g);
5f892713c3 2021-03-03 trnsz@pobox.c: integrate(f^g, f);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := integrate(g*f^5, f) + integrate(f^5+f^g, f);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT The last example indicates that we must incorporate rules
5f892713c3 2021-03-03 trnsz@pobox.c: which distribute integrals over sums and extract factors which are
5f892713c3 2021-03-03 trnsz@pobox.c: independent of the second argument of INTEGRATE.  Can you think of
5f892713c3 2021-03-03 trnsz@pobox.c: rules which accomplish this?  It is a good exercise, but this
5f892713c3 2021-03-03 trnsz@pobox.c: particular pair of properties of INTEGRATE is so prevalent in
5f892713c3 2021-03-03 trnsz@pobox.c: mathematics that operators with these properties are called linear,
5f892713c3 2021-03-03 trnsz@pobox.c: and a corresponding declaration is built into REDUCE:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: linear integrate;
5f892713c3 2021-03-03 trnsz@pobox.c: g1;
5f892713c3 2021-03-03 trnsz@pobox.c: g1 := integrate(f+1, f) + integrate(1/f^5, f);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT We overcame one difficulty and uncovered 3 others.  Clearly
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE does not consider F to match the pattern F^P as F^1, or 1 to
5f892713c3 2021-03-03 trnsz@pobox.c: match the pattern as F^0, or 1/F^5 to match the pattern as F^(-1), but
5f892713c3 2021-03-03 trnsz@pobox.c: we can add additional rules for such cases:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: let {
5f892713c3 2021-03-03 trnsz@pobox.c:    integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
5f892713c3 2021-03-03 trnsz@pobox.c:    integrate(~x, x) => x^2/2,
5f892713c3 2021-03-03 trnsz@pobox.c:    integrate(1, ~x) => x }$
5f892713c3 2021-03-03 trnsz@pobox.c: g1;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT A remaining problem is that INTEGRATE(X^-1, X) will lead to
5f892713c3 2021-03-03 trnsz@pobox.c: X^0/(-1+1), which simplifies to 1/0, which will cause a zero-divide
5f892713c3 2021-03-03 trnsz@pobox.c: error message.  Consequently, we should also include the correct rule
5f892713c3 2021-03-03 trnsz@pobox.c: for this special case:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: let integrate(~x^-1, x) => log(x);
5f892713c3 2021-03-03 trnsz@pobox.c: integrate(1/x, x);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c:  
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT We now collect the integration rules so far into one list
5f892713c3 2021-03-03 trnsz@pobox.c: according to the law that within a rule set a more specific rule
5f892713c3 2021-03-03 trnsz@pobox.c: should precede the more general one:;
5f892713c3 2021-03-03 trnsz@pobox.c:  
5f892713c3 2021-03-03 trnsz@pobox.c: integrate_rules := {
5f892713c3 2021-03-03 trnsz@pobox.c:   integrate(1, ~x) => x,
5f892713c3 2021-03-03 trnsz@pobox.c:   integrate(~x, x) => x^2/2,
5f892713c3 2021-03-03 trnsz@pobox.c:   integrate(~x^-1, x) => log(x),
5f892713c3 2021-03-03 trnsz@pobox.c:   integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
5f892713c3 2021-03-03 trnsz@pobox.c:   integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0 }$
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Note that there are more elegant ways to match special cases
5f892713c3 2021-03-03 trnsz@pobox.c: in which variables have the values 0 or 1 by using "double tilde
5f892713c3 2021-03-03 trnsz@pobox.c: variables" -- see "Advanced use of rule lists" in section 11.3 of the
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE User's Manual.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: This is the end of lesson 3.  We leave it as an intriguing exercise to
5f892713c3 2021-03-03 trnsz@pobox.c: extend this integrator.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: ;end;

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