Origin for each line in Lesson_7.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 7
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 7 of 7 REDUCE lessons.  Sometimes it is desired
5f892713c3 2021-03-03 trnsz@pobox.c: to have a certain facility available to algebraic mode, no such
5f892713c3 2021-03-03 trnsz@pobox.c: facility is described in the REDUCE User's Manual, and there is no
5f892713c3 2021-03-03 trnsz@pobox.c: easy way to implement the facility directly in algebraic mode.  The
5f892713c3 2021-03-03 trnsz@pobox.c: possibilities are:
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  The facility exists for algebraic mode, but is undocumented.
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  The facility exists, but is available only in symbolic mode.
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  The facility is not built-in for either mode.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Perusal of the REDUCE source code (see
5f892713c3 2021-03-03 trnsz@pobox.c: https://sourceforge.net/p/reduce-algebra/code/HEAD/tree/trunk/packages/
5f892713c3 2021-03-03 trnsz@pobox.c: -- alg contains the core algebra facilities), together with
5f892713c3 2021-03-03 trnsz@pobox.c: experimentation can reveal which of these alternatives is true.  (Even
5f892713c3 2021-03-03 trnsz@pobox.c: in case 3, an inquiry via the REDUCE Project Forum or Mailing List --
5f892713c3 2021-03-03 trnsz@pobox.c: see https://sourceforge.net/projects/reduce-algebra/support -- may
5f892713c3 2021-03-03 trnsz@pobox.c: reveal that someone else has already implemented the supplementary
5f892713c3 2021-03-03 trnsz@pobox.c: facility and can provide the code.);
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 type of statement is available to both modes if its leading
5f892713c3 2021-03-03 trnsz@pobox.c: keyword appears in either of the equivalent statements
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       PUT (..., 'STAT, ...)
5f892713c3 2021-03-03 trnsz@pobox.c: or
5f892713c3 2021-03-03 trnsz@pobox.c:       DEFLIST('(...), 'STAT).
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: A symbolic-mode global variable is available to algebraic mode and
5f892713c3 2021-03-03 trnsz@pobox.c: vice-versa if the name of the variable appears in either of the
5f892713c3 2021-03-03 trnsz@pobox.c: equivalent statements
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       SHARE ...,
5f892713c3 2021-03-03 trnsz@pobox.c: or
5f892713c3 2021-03-03 trnsz@pobox.c:       FLAG('(...), 'SHARE).
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: A function defined in symbolic mode is directly available to algebraic
5f892713c3 2021-03-03 trnsz@pobox.c: mode if the function name appears in one of the statements
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       SYMBOLIC OPERATOR ...,
5f892713c3 2021-03-03 trnsz@pobox.c:       PUT(..., 'SIMPFN, ...),
5f892713c3 2021-03-03 trnsz@pobox.c:       DEFLIST('(...), 'SIMPFN),
5f892713c3 2021-03-03 trnsz@pobox.c:       FLAG('(...), 'OPFN).
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: In addition, if you want a function to be used as a predicate in IF or
5f892713c3 2021-03-03 trnsz@pobox.c: WHILE statements, it should be flagged BOOLEAN, as in
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       FLAG('(...), 'BOOLEAN);
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 Other functions which are used but not defined in RLISP are
5f892713c3 2021-03-03 trnsz@pobox.c: the built-in LISP functions.  See a description of the underlying LISP
5f892713c3 2021-03-03 trnsz@pobox.c: system (normally either PSL or CSL) for documentation on these
5f892713c3 2021-03-03 trnsz@pobox.c: functions.  All Standard Lisp functions should be available.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Particularly notable built-in features available only to symbolic mode
5f892713c3 2021-03-03 trnsz@pobox.c: include
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  A function named SPACES, which outputs the number of blanks
5f892713c3 2021-03-03 trnsz@pobox.c:        indicated by its integer argument.
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  A function named REDERR, which provokes an error interrupt
5f892713c3 2021-03-03 trnsz@pobox.c:        after outputting its arguments.
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  A predicate named KERNP, which returns NIL if its argument
5f892713c3 2021-03-03 trnsz@pobox.c:        is not an indeterminate or a functional form.
5f892713c3 2021-03-03 trnsz@pobox.c:    4.  A function named MATHPRINT, which outputs its argument in
5f892713c3 2021-03-03 trnsz@pobox.c:        natural mathematical notation, beginning on a new line.
5f892713c3 2021-03-03 trnsz@pobox.c:    5.  A function named MAPRIN, which is like MATHPRINT, but does not
5f892713c3 2021-03-03 trnsz@pobox.c:        automatically start or end a new line.
5f892713c3 2021-03-03 trnsz@pobox.c:    6.  A function named TERPRI!*, which ends the current output-line.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Thus, for example, all that we have to do to make the predicate KERNP
5f892713c3 2021-03-03 trnsz@pobox.c: and the function SPACES available to algebraic mode is to type
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       FLAG('(KERNP), 'BOOLEAN),
5f892713c3 2021-03-03 trnsz@pobox.c:       SYMBOLIC OPERATOR SPACES.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: When such simple remedies are unavailable, we can introduce our own
5f892713c3 2021-03-03 trnsz@pobox.c: statements or write our own SYMBOLIC-mode variables and procedures,
5f892713c3 2021-03-03 trnsz@pobox.c: then use these techniques to make them available to algebraic mode.
5f892713c3 2021-03-03 trnsz@pobox.c: In order to do so, it is usually necessary to understand how REDUCE
5f892713c3 2021-03-03 trnsz@pobox.c: represents and simplifies algebraic expressions.;
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 One of the REDUCE representations is called Cambridge Prefix.
5f892713c3 2021-03-03 trnsz@pobox.c: An expression is either an atom or a list consisting of a literal
5f892713c3 2021-03-03 trnsz@pobox.c: atom, denoting a function or operator name, followed by arguments
5f892713c3 2021-03-03 trnsz@pobox.c: which are Cambridge Prefix expressions.  The most common unary
5f892713c3 2021-03-03 trnsz@pobox.c: operator names are MINUS, LOG, SIN, and COS.  The most common binary
5f892713c3 2021-03-03 trnsz@pobox.c: operator names are DIFFERENCE, QUOTIENT, and EXPT.  The most common
5f892713c3 2021-03-03 trnsz@pobox.c: nary operator names are PLUS and TIMES.  Thus, for example, the
5f892713c3 2021-03-03 trnsz@pobox.c: expression
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       3*x^2*y + x^(1/2) + e^(-x)
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: could be represented as
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: '(PLUS (TIMES 3 (EXPT X 2) Y) (EXPT X (QUOTIENT 1 2)) (EXPT E (MINUS X))
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: The parser produces an unsimplified Cambridge Prefix version of
5f892713c3 2021-03-03 trnsz@pobox.c: algebraic-mode expressions typed by the user, then the simplifier
5f892713c3 2021-03-03 trnsz@pobox.c: returns a simplified prefix version.  When a symbolic procedure that
5f892713c3 2021-03-03 trnsz@pobox.c: has been declared a symbolic operator is invoked from algebraic mode,
5f892713c3 2021-03-03 trnsz@pobox.c: the procedure is given simplified Cambridge Prefix versions of the
5f892713c3 2021-03-03 trnsz@pobox.c: arguments.  To illustrate these ideas, here is an infix function named
5f892713c3 2021-03-03 trnsz@pobox.c: ISFREEOF, which determines whether its left argument is free of the
5f892713c3 2021-03-03 trnsz@pobox.c: indeterminate, function name, or literal sub-expression which is the
5f892713c3 2021-03-03 trnsz@pobox.c: right argument.  ISFREEOF is similar to the REDUCE FREEOF function but
5f892713c3 2021-03-03 trnsz@pobox.c: less general.;
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: flag('(isfreeof), 'boolean);
5f892713c3 2021-03-03 trnsz@pobox.c: infix isfreeof;
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure campre1 isfreeof campre2;
5f892713c3 2021-03-03 trnsz@pobox.c:    if campre1=campre2 then nil
5f892713c3 2021-03-03 trnsz@pobox.c:    else if atom campre1 then t
5f892713c3 2021-03-03 trnsz@pobox.c:    else (car campre1 isfreeof campre2)
5f892713c3 2021-03-03 trnsz@pobox.c:       and (cdr campre1 isfreeof campre2);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: algebraic if log(5+x+cos(y)) isfreeof sin(z-7)
5f892713c3 2021-03-03 trnsz@pobox.c:    then write "WORKS ONE WAY";
5f892713c3 2021-03-03 trnsz@pobox.c: algebraic if not(log(5+x+cos(y)) isfreeof cos(y))
5f892713c3 2021-03-03 trnsz@pobox.c:    then write "WORKS OTHER WAY TOO";
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT Conceivably we might wish to distinguish when CAMPRE2 is a
5f892713c3 2021-03-03 trnsz@pobox.c: literal atom occurring as a function name from the case when CAMPRE2
5f892713c3 2021-03-03 trnsz@pobox.c: is a literal atom and occurs as an indeterminate.  Accordingly, see if
5f892713c3 2021-03-03 trnsz@pobox.c: you can write two such more specialized infix predicates named
5f892713c3 2021-03-03 trnsz@pobox.c: ISFREEOFINDET and ISFREEOFFUNCTION.;
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 When writing a symbolic-mode function, it is often desired to
5f892713c3 2021-03-03 trnsz@pobox.c: invoke the algebraic simplifier from within the function.  This can be
5f892713c3 2021-03-03 trnsz@pobox.c: done by using the function named REVAL, which returns a simplified
5f892713c3 2021-03-03 trnsz@pobox.c: Cambridge Prefix version of its prefix argument.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Usually, REDUCE uses and produces a different representation, which I
5f892713c3 2021-03-03 trnsz@pobox.c: call REDUCE prefix.  The symbolic function AEVAL returns a simplified
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE-prefix version of its prefix argument.  Both REVAL and AEVAL
5f892713c3 2021-03-03 trnsz@pobox.c: can take either type of prefix argument.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: A REDUCE-prefix expression is an integer, a floating-point number, an
5f892713c3 2021-03-03 trnsz@pobox.c: indeterminate, or an expression of the form
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       ('!*SQ standardquotient . !*SQVAR!*).
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: !*SQVAR!* is a global variable which is set to T when the REDUCE-
5f892713c3 2021-03-03 trnsz@pobox.c: prefix expression is originally formed.  The value of !*SQVAR!* is
5f892713c3 2021-03-03 trnsz@pobox.c: reset to NIL if subsequent LET, MATCH, or computational ON statements
5f892713c3 2021-03-03 trnsz@pobox.c: could change the environment is such a way that the expression might
5f892713c3 2021-03-03 trnsz@pobox.c: require resimplification next time it 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 Standard quotients are neither Cambridge nor REDUCE prefix, so
5f892713c3 2021-03-03 trnsz@pobox.c: the purpose of the atom '!*SQ is to make the value of all algebraic-
5f892713c3 2021-03-03 trnsz@pobox.c: mode variables always be some type of prefix form at the top level.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: A standard quotient is a unit-normal dotted pair of 2 standard forms,
5f892713c3 2021-03-03 trnsz@pobox.c: and a standard form is the REDUCE representation for a polynomial.
5f892713c3 2021-03-03 trnsz@pobox.c: Unit-normal means that the leading coefficient of the denominator is
5f892713c3 2021-03-03 trnsz@pobox.c: positive.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE has a built-in symbolic function SIMP!*, which returns the
5f892713c3 2021-03-03 trnsz@pobox.c: simplified standard quotient representation of its argument, which can
5f892713c3 2021-03-03 trnsz@pobox.c: be either Cambridge or REDUCE prefix.  REDUCE also has symbolic
5f892713c3 2021-03-03 trnsz@pobox.c: functions named NEGSQ, INVSQ, ADDSQ, MULTSQ, DIVSQ, DIFFSQ, and
5f892713c3 2021-03-03 trnsz@pobox.c: CANONSQ which respectively negate, reciprocate, add, multiply, divide,
5f892713c3 2021-03-03 trnsz@pobox.c: differentiate, and unit-normalize standard quotients.  There is also a
5f892713c3 2021-03-03 trnsz@pobox.c: function named ABSQ, which negates a standard quotient if the leading
5f892713c3 2021-03-03 trnsz@pobox.c: coefficient of its numerator is negative, and there is a function
5f892713c3 2021-03-03 trnsz@pobox.c: named EXPTSQ which raises a standard quotient to an integer power.
5f892713c3 2021-03-03 trnsz@pobox.c: Finally, there is a function named MK!*SQ, which returns a REDUCE
5f892713c3 2021-03-03 trnsz@pobox.c: prefix version of its standard-quotient argument, and there is also a
5f892713c3 2021-03-03 trnsz@pobox.c: function named PREPSQ which returns a Cambridge prefix version of its
5f892713c3 2021-03-03 trnsz@pobox.c: standard-quotient argument.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: If there is a sequence of operations, rather than converting from
5f892713c3 2021-03-03 trnsz@pobox.c: prefix to standard quotient and back at each step, it is usually more
5f892713c3 2021-03-03 trnsz@pobox.c: efficient to do the operations on standard quotients, then use MK!*SQ
5f892713c3 2021-03-03 trnsz@pobox.c: to make the final result be REDUCE prefix.  Also it is often more
5f892713c3 2021-03-03 trnsz@pobox.c: efficient to work with polynomials rather than rational functions
5f892713c3 2021-03-03 trnsz@pobox.c: during the intermediate steps.;
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 coefficient domain of polynomials is floating-point
5f892713c3 2021-03-03 trnsz@pobox.c: numbers, integers, integers modulo an arbitrary integer modulus, or
5f892713c3 2021-03-03 trnsz@pobox.c: rational numbers.  However, zero is represented as NIL.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: The polynomial variables are called kernels, which can be
5f892713c3 2021-03-03 trnsz@pobox.c: indeterminates or uniquely-stored fully simplified Cambridge-prefix
5f892713c3 2021-03-03 trnsz@pobox.c: functional forms.  The latter alternative permits the representation
5f892713c3 2021-03-03 trnsz@pobox.c: of expressions which could not otherwise be represented as the ratio
5f892713c3 2021-03-03 trnsz@pobox.c: of two expanded polynomials, such as
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    1.  sub-expressions of the form LOG(...) or SIN(...),
5f892713c3 2021-03-03 trnsz@pobox.c:    2.  sub-expressions of the form indeterminate^noninteger,
5f892713c3 2021-03-03 trnsz@pobox.c:    3.  unexpanded polynomials, each polynomial factor being
5f892713c3 2021-03-03 trnsz@pobox.c:        represented as a functional form,
5f892713c3 2021-03-03 trnsz@pobox.c:    4.  rational expressions not placed over a common denominator,
5f892713c3 2021-03-03 trnsz@pobox.c:        each quotient sub-expression being represented as a functional
5f892713c3 2021-03-03 trnsz@pobox.c:        form.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: A polynomial is represented as a list of its nonzero terms in
5f892713c3 2021-03-03 trnsz@pobox.c: decreasing order of the degree of the leading "variable".  Each term
5f892713c3 2021-03-03 trnsz@pobox.c: is represented as a standard power dotted with its coefficient, which
5f892713c3 2021-03-03 trnsz@pobox.c: is a standard form in the remaining variables.  A standard power is
5f892713c3 2021-03-03 trnsz@pobox.c: represented as a variable dotted with a positive integer degree.;
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 Letting ::= denote "is defined as" and letting | denote "or",
5f892713c3 2021-03-03 trnsz@pobox.c: we can summarize the REDUCE data representations as follows:
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    reduceprefix ::= ('!*SQ standardquotient . !*SQVAR!*)
5f892713c3 2021-03-03 trnsz@pobox.c:    standardquotient ::= NUMR(standardquotient) ./
5f892713c3 2021-03-03 trnsz@pobox.c:                                DENR(standardquotient)
5f892713c3 2021-03-03 trnsz@pobox.c:    NUMR(standardquotient) ::= standardform
5f892713c3 2021-03-03 trnsz@pobox.c:    DENR(standardquotient) ::= unitnormalstandardform
5f892713c3 2021-03-03 trnsz@pobox.c:    domainelement ::= NIL | nonzerointeger | nonzerofloat |
5f892713c3 2021-03-03 trnsz@pobox.c:                      nonzerointeger . positiveinteger
5f892713c3 2021-03-03 trnsz@pobox.c:    standardform ::= domainelement |
5f892713c3 2021-03-03 trnsz@pobox.c:                     LT(standardform) .+ RED(standardform)
5f892713c3 2021-03-03 trnsz@pobox.c:    RED(standardform) ::= standardform
5f892713c3 2021-03-03 trnsz@pobox.c:    LT(standardform) := LPOW(standardform) .* LC(standardform)
5f892713c3 2021-03-03 trnsz@pobox.c:    LPOW(standardform) := MVAR(standardform) .^ LDEG(standardform)
5f892713c3 2021-03-03 trnsz@pobox.c:    LC(standardform) ::= standardform
5f892713c3 2021-03-03 trnsz@pobox.c:    MVAR(standardform) ::= kernel
5f892713c3 2021-03-03 trnsz@pobox.c:    kernel ::= indeterminate | functionalform
5f892713c3 2021-03-03 trnsz@pobox.c:    functionalform ::= (functionname Cambridgeprefix1 Cambridgeprefix2
5f892713c3 2021-03-03 trnsz@pobox.c:                        ...)
5f892713c3 2021-03-03 trnsz@pobox.c:    Cambridgeprefix ::= integer | float | indeterminate |
5f892713c3 2021-03-03 trnsz@pobox.c:                           functionalform
5f892713c3 2021-03-03 trnsz@pobox.c:    LC(unitnormalstandardform) ::= positivedomainelement |
5f892713c3 2021-03-03 trnsz@pobox.c:                                  unitnormalstandardform
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: I have taken this opportunity to also introduce the major REDUCE
5f892713c3 2021-03-03 trnsz@pobox.c: selector macros named NUMR, DENR, LT, RED, LPOW, LC, MVAR, and LDEG,
5f892713c3 2021-03-03 trnsz@pobox.c: together with the major constructor macros named ./, .+, .*, and .^ .
5f892713c3 2021-03-03 trnsz@pobox.c: The latter are just mnemonic aliases for ".".  A comparison of my
5f892713c3 2021-03-03 trnsz@pobox.c: verbal and more formal definitions also reveals that the selectors are
5f892713c3 2021-03-03 trnsz@pobox.c: respectively just aliases for CAR, CDR, CAR, CDR, CAAR, CDAR, CAAAR,
5f892713c3 2021-03-03 trnsz@pobox.c: and CDAAR.  Since these selectors and constructors are macros rather
5f892713c3 2021-03-03 trnsz@pobox.c: than functions, they afford a more readable and modifiable programming
5f892713c3 2021-03-03 trnsz@pobox.c: style at no cost in ultimate efficiency.  Thus you are encouraged to
5f892713c3 2021-03-03 trnsz@pobox.c: use them and to invent your own when convenient.  As an example of how
5f892713c3 2021-03-03 trnsz@pobox.c: this can be done, here is the macro definition for extracting the main
5f892713c3 2021-03-03 trnsz@pobox.c: variable of a standard term:;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: %   symbolic smacro procedure tvar trm; caar trm;
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 It turns out that there are already built-in selectors named
5f892713c3 2021-03-03 trnsz@pobox.c: TC, TPOW, and TDEG, which respectively extract the coefficient,
5f892713c3 2021-03-03 trnsz@pobox.c: leading power, and leading degree of a standard term.  There are also
5f892713c3 2021-03-03 trnsz@pobox.c: built-in constructors named !*P2F, !*K2F, !*K2Q, and !*T2Q, which
5f892713c3 2021-03-03 trnsz@pobox.c: respectively make a power into a standard form, a kernel into a
5f892713c3 2021-03-03 trnsz@pobox.c: standard form, a kernel into a standard quotient, and a term into a
5f892713c3 2021-03-03 trnsz@pobox.c: standard quotient.  See the REDUCE User's Manual for a complete list.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: The unary functions NEGF and ABSF respectively negate, and unit-
5f892713c3 2021-03-03 trnsz@pobox.c: normalize their standard-form arguments.  The binary functions ADDF,
5f892713c3 2021-03-03 trnsz@pobox.c: MULTF, QUOTF, SUBF, EXPTF, and GCDF respectively add, multiply, divide,
5f892713c3 2021-03-03 trnsz@pobox.c: substitute into, raise to a positive integer power, and determine the
5f892713c3 2021-03-03 trnsz@pobox.c: greatest common divisor of standard forms.  See if you can use them to
5f892713c3 2021-03-03 trnsz@pobox.c: define a macro which subtracts standard 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 The best way to become adept at working with standard forms
5f892713c3 2021-03-03 trnsz@pobox.c: and standard quotients is to study the corresponding portions of the
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE source listing.  The listing of ADDF and its subordinates is
5f892713c3 2021-03-03 trnsz@pobox.c: particularly instructive.  As an exercise, see if you can write a
5f892713c3 2021-03-03 trnsz@pobox.c: function named ISFREEOFKERN which determines whether or not its left
5f892713c3 2021-03-03 trnsz@pobox.c: argument is free of the kernel which is the right argument, using
5f892713c3 2021-03-03 trnsz@pobox.c: REDUCE prefix rather than Cambridge prefix for the left argument.;
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 a final example of the interaction between modes, here is a
5f892713c3 2021-03-03 trnsz@pobox.c: function which produces simple character-based plots.  Note that, to
5f892713c3 2021-03-03 trnsz@pobox.c: keep the implementation as simple as possible, values of the
5f892713c3 2021-03-03 trnsz@pobox.c: indeterminate ("x") increase downwards and values of the expression
5f892713c3 2021-03-03 trnsz@pobox.c: plotted ("y") increase to the right.  This is the conventional
5f892713c3 2021-03-03 trnsz@pobox.c: orientation rotated clockwise through 90 degrees!;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: share ncols;
5f892713c3 2021-03-03 trnsz@pobox.c: ncols := 66;
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic operator plot;
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure plot(ex, xinit, dx, ndx, yinit, dy);
5f892713c3 2021-03-03 trnsz@pobox.c:    begin COMMENT This procedure produces a character-plot of univariate
5f892713c3 2021-03-03 trnsz@pobox.c:       expression EX where,
5f892713c3 2021-03-03 trnsz@pobox.c:          XINIT is the initial value of the indeterminate,
5f892713c3 2021-03-03 trnsz@pobox.c:          DX is the increment per line of the indeterminate,
5f892713c3 2021-03-03 trnsz@pobox.c:          NDX is the number of lines plotted,
5f892713c3 2021-03-03 trnsz@pobox.c:          YINIT is the value represented at the left edge,
5f892713c3 2021-03-03 trnsz@pobox.c:          DY is incremental value per column.
5f892713c3 2021-03-03 trnsz@pobox.c:       The shared variable NCOLS, initially 66, is the number of columns
5f892713c3 2021-03-03 trnsz@pobox.c:       used.  Points are plotted using "*", except "<" and ">" are used
5f892713c3 2021-03-03 trnsz@pobox.c:       at the left and right edges to indicate out of bounds points.;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    scalar x, f, y;  integer col, ncolsminus1;
5f892713c3 2021-03-03 trnsz@pobox.c:    ncolsminus1 := ncols - 1;
5f892713c3 2021-03-03 trnsz@pobox.c:    write "Starting the plot of ",ex;
5f892713c3 2021-03-03 trnsz@pobox.c:    x := listofvars ex;          % find indeterminates;
5f892713c3 2021-03-03 trnsz@pobox.c:    if length x > 1 then rederr
5f892713c3 2021-03-03 trnsz@pobox.c:      "ERROR: PLOT expression can have at most 1 indeterminate";
5f892713c3 2021-03-03 trnsz@pobox.c:    if null x then <<
5f892713c3 2021-03-03 trnsz@pobox.c:       write "ERROR: no indeterminates in ", ex;
5f892713c3 2021-03-03 trnsz@pobox.c:       rederr "" >>
5f892713c3 2021-03-03 trnsz@pobox.c:    else x := car x;
5f892713c3 2021-03-03 trnsz@pobox.c:    write " in variable ", x;  terpri();
5f892713c3 2021-03-03 trnsz@pobox.c:    COMMENT Convert args from algebraic to symbolic values;
5f892713c3 2021-03-03 trnsz@pobox.c:    xinit := revalx xinit;
5f892713c3 2021-03-03 trnsz@pobox.c:    dx := revalx dx;
5f892713c3 2021-03-03 trnsz@pobox.c:    yinit := revalx yinit;
5f892713c3 2021-03-03 trnsz@pobox.c:    dy := revalx dy;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:    for j:= 0:ndx do <<
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       % generate expression with current value substituted for x
5f892713c3 2021-03-03 trnsz@pobox.c:       f := subst(xinit + j*dx, x, ex);
5f892713c3 2021-03-03 trnsz@pobox.c:       y := eval(f);                      % eval expression
5f892713c3 2021-03-03 trnsz@pobox.c:       col := rnd((y - yinit)/dy);        % scale and round for cols
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c:       if col<0 then write "<"
5f892713c3 2021-03-03 trnsz@pobox.c:       else if col > ncolsminus1 then << spaces(ncolsminus1);
5f892713c3 2021-03-03 trnsz@pobox.c:          prin2 ">";
5f892713c3 2021-03-03 trnsz@pobox.c:          terpri() >>
5f892713c3 2021-03-03 trnsz@pobox.c:       else << spaces(col);
5f892713c3 2021-03-03 trnsz@pobox.c:          prin2 "*";
5f892713c3 2021-03-03 trnsz@pobox.c:          terpri() >>
5f892713c3 2021-03-03 trnsz@pobox.c:       >> ;
5f892713c3 2021-03-03 trnsz@pobox.c:    if null y then rederr
5f892713c3 2021-03-03 trnsz@pobox.c:      "ERROR: UNABLE TO PERFORM FLOATING-POINT EVALUATION OF 1ST ARG"
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: symbolic procedure listofvars campre;
5f892713c3 2021-03-03 trnsz@pobox.c:    if null campre or numberp campre then nil
5f892713c3 2021-03-03 trnsz@pobox.c:    else if atom campre then list campre
5f892713c3 2021-03-03 trnsz@pobox.c:    else varsinargs cdr campre;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure varsinargs listofcampre;
5f892713c3 2021-03-03 trnsz@pobox.c:    if null listofcampre then nil
5f892713c3 2021-03-03 trnsz@pobox.c:    else union(listofvars car listofcampre, varsinargs cdr listofcampre);
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure rnd x;
5f892713c3 2021-03-03 trnsz@pobox.c:    begin scalar ans;
5f892713c3 2021-03-03 trnsz@pobox.c:    ans := revalx x;
5f892713c3 2021-03-03 trnsz@pobox.c:    if not numberp x then redderr "RND GIVEN NON-NUMERIC ARGUMENT";
5f892713c3 2021-03-03 trnsz@pobox.c:    if ans >=0 then ans := fix(ans+00.5)
5f892713c3 2021-03-03 trnsz@pobox.c:    else ans:= fix(ans-0.5);
5f892713c3 2021-03-03 trnsz@pobox.c:    return ans
5f892713c3 2021-03-03 trnsz@pobox.c:    end;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure revalx u;
5f892713c3 2021-03-03 trnsz@pobox.c:    % MAKE SURE WE GET TRUE FLOATS IN SYMBOLIC MODE.
5f892713c3 2021-03-03 trnsz@pobox.c:    if eqcar(u,'!:rd!:) then rdprepx u else u;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: symbolic procedure rdprepx u;
5f892713c3 2021-03-03 trnsz@pobox.c:    if floatp cdr u then cdr u else bf2flr u;
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: on rounded;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: plot(y^2,     0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: plot((a+1)^2, 0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: b := a*2;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: plot(a*b,     0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 trnsz@pobox.c: pause;
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: COMMENT We leave it as an exercise to write a more elaborate plot
5f892713c3 2021-03-03 trnsz@pobox.c: procedure which offers amenities such as automatic scaling, numbered
5f892713c3 2021-03-03 trnsz@pobox.c: ordinates, etc.
5f892713c3 2021-03-03 trnsz@pobox.c: 
5f892713c3 2021-03-03 trnsz@pobox.c: Good luck with these exercises, with REDUCE, with computer algebra and
5f892713c3 2021-03-03 trnsz@pobox.c: with all of your endeavors.
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 ]