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;