5f892713c3 2021-03-03 1: COMMENT
5f892713c3 2021-03-03 2:
5f892713c3 2021-03-03 3: REDUCE INTERACTIVE LESSON NUMBER 7
5f892713c3 2021-03-03 4:
5f892713c3 2021-03-03 5: David R. Stoutemyer
5f892713c3 2021-03-03 6: University of Hawaii
5f892713c3 2021-03-03 7:
5f892713c3 2021-03-03 8:
5f892713c3 2021-03-03 9: COMMENT This is lesson 7 of 7 REDUCE lessons. Sometimes it is desired
5f892713c3 2021-03-03 10: to have a certain facility available to algebraic mode, no such
5f892713c3 2021-03-03 11: facility is described in the REDUCE User's Manual, and there is no
5f892713c3 2021-03-03 12: easy way to implement the facility directly in algebraic mode. The
5f892713c3 2021-03-03 13: possibilities are:
5f892713c3 2021-03-03 14:
5f892713c3 2021-03-03 15: 1. The facility exists for algebraic mode, but is undocumented.
5f892713c3 2021-03-03 16: 2. The facility exists, but is available only in symbolic mode.
5f892713c3 2021-03-03 17: 3. The facility is not built-in for either mode.
5f892713c3 2021-03-03 18:
5f892713c3 2021-03-03 19: Perusal of the REDUCE source code (see
5f892713c3 2021-03-03 20: https://sourceforge.net/p/reduce-algebra/code/HEAD/tree/trunk/packages/
5f892713c3 2021-03-03 21: -- alg contains the core algebra facilities), together with
5f892713c3 2021-03-03 22: experimentation can reveal which of these alternatives is true. (Even
5f892713c3 2021-03-03 23: in case 3, an inquiry via the REDUCE Project Forum or Mailing List --
5f892713c3 2021-03-03 24: see https://sourceforge.net/projects/reduce-algebra/support -- may
5f892713c3 2021-03-03 25: reveal that someone else has already implemented the supplementary
5f892713c3 2021-03-03 26: facility and can provide the code.);
5f892713c3 2021-03-03 27:
5f892713c3 2021-03-03 28: pause;
5f892713c3 2021-03-03 29:
5f892713c3 2021-03-03 30: COMMENT A type of statement is available to both modes if its leading
5f892713c3 2021-03-03 31: keyword appears in either of the equivalent statements
5f892713c3 2021-03-03 32:
5f892713c3 2021-03-03 33: PUT (..., 'STAT, ...)
5f892713c3 2021-03-03 34: or
5f892713c3 2021-03-03 35: DEFLIST('(...), 'STAT).
5f892713c3 2021-03-03 36:
5f892713c3 2021-03-03 37: A symbolic-mode global variable is available to algebraic mode and
5f892713c3 2021-03-03 38: vice-versa if the name of the variable appears in either of the
5f892713c3 2021-03-03 39: equivalent statements
5f892713c3 2021-03-03 40:
5f892713c3 2021-03-03 41: SHARE ...,
5f892713c3 2021-03-03 42: or
5f892713c3 2021-03-03 43: FLAG('(...), 'SHARE).
5f892713c3 2021-03-03 44:
5f892713c3 2021-03-03 45: A function defined in symbolic mode is directly available to algebraic
5f892713c3 2021-03-03 46: mode if the function name appears in one of the statements
5f892713c3 2021-03-03 47:
5f892713c3 2021-03-03 48: SYMBOLIC OPERATOR ...,
5f892713c3 2021-03-03 49: PUT(..., 'SIMPFN, ...),
5f892713c3 2021-03-03 50: DEFLIST('(...), 'SIMPFN),
5f892713c3 2021-03-03 51: FLAG('(...), 'OPFN).
5f892713c3 2021-03-03 52:
5f892713c3 2021-03-03 53: In addition, if you want a function to be used as a predicate in IF or
5f892713c3 2021-03-03 54: WHILE statements, it should be flagged BOOLEAN, as in
5f892713c3 2021-03-03 55:
5f892713c3 2021-03-03 56: FLAG('(...), 'BOOLEAN);
5f892713c3 2021-03-03 57:
5f892713c3 2021-03-03 58: pause;
5f892713c3 2021-03-03 59:
5f892713c3 2021-03-03 60: COMMENT Other functions which are used but not defined in RLISP are
5f892713c3 2021-03-03 61: the built-in LISP functions. See a description of the underlying LISP
5f892713c3 2021-03-03 62: system (normally either PSL or CSL) for documentation on these
5f892713c3 2021-03-03 63: functions. All Standard Lisp functions should be available.
5f892713c3 2021-03-03 64:
5f892713c3 2021-03-03 65: Particularly notable built-in features available only to symbolic mode
5f892713c3 2021-03-03 66: include
5f892713c3 2021-03-03 67:
5f892713c3 2021-03-03 68: 1. A function named SPACES, which outputs the number of blanks
5f892713c3 2021-03-03 69: indicated by its integer argument.
5f892713c3 2021-03-03 70: 2. A function named REDERR, which provokes an error interrupt
5f892713c3 2021-03-03 71: after outputting its arguments.
5f892713c3 2021-03-03 72: 3. A predicate named KERNP, which returns NIL if its argument
5f892713c3 2021-03-03 73: is not an indeterminate or a functional form.
5f892713c3 2021-03-03 74: 4. A function named MATHPRINT, which outputs its argument in
5f892713c3 2021-03-03 75: natural mathematical notation, beginning on a new line.
5f892713c3 2021-03-03 76: 5. A function named MAPRIN, which is like MATHPRINT, but does not
5f892713c3 2021-03-03 77: automatically start or end a new line.
5f892713c3 2021-03-03 78: 6. A function named TERPRI!*, which ends the current output-line.
5f892713c3 2021-03-03 79:
5f892713c3 2021-03-03 80: Thus, for example, all that we have to do to make the predicate KERNP
5f892713c3 2021-03-03 81: and the function SPACES available to algebraic mode is to type
5f892713c3 2021-03-03 82:
5f892713c3 2021-03-03 83: FLAG('(KERNP), 'BOOLEAN),
5f892713c3 2021-03-03 84: SYMBOLIC OPERATOR SPACES.
5f892713c3 2021-03-03 85:
5f892713c3 2021-03-03 86: When such simple remedies are unavailable, we can introduce our own
5f892713c3 2021-03-03 87: statements or write our own SYMBOLIC-mode variables and procedures,
5f892713c3 2021-03-03 88: then use these techniques to make them available to algebraic mode.
5f892713c3 2021-03-03 89: In order to do so, it is usually necessary to understand how REDUCE
5f892713c3 2021-03-03 90: represents and simplifies algebraic expressions.;
5f892713c3 2021-03-03 91:
5f892713c3 2021-03-03 92: pause;
5f892713c3 2021-03-03 93:
5f892713c3 2021-03-03 94: COMMENT One of the REDUCE representations is called Cambridge Prefix.
5f892713c3 2021-03-03 95: An expression is either an atom or a list consisting of a literal
5f892713c3 2021-03-03 96: atom, denoting a function or operator name, followed by arguments
5f892713c3 2021-03-03 97: which are Cambridge Prefix expressions. The most common unary
5f892713c3 2021-03-03 98: operator names are MINUS, LOG, SIN, and COS. The most common binary
5f892713c3 2021-03-03 99: operator names are DIFFERENCE, QUOTIENT, and EXPT. The most common
5f892713c3 2021-03-03 100: nary operator names are PLUS and TIMES. Thus, for example, the
5f892713c3 2021-03-03 101: expression
5f892713c3 2021-03-03 102:
5f892713c3 2021-03-03 103: 3*x^2*y + x^(1/2) + e^(-x)
5f892713c3 2021-03-03 104:
5f892713c3 2021-03-03 105: could be represented as
5f892713c3 2021-03-03 106:
5f892713c3 2021-03-03 107: '(PLUS (TIMES 3 (EXPT X 2) Y) (EXPT X (QUOTIENT 1 2)) (EXPT E (MINUS X))
5f892713c3 2021-03-03 108:
5f892713c3 2021-03-03 109: The parser produces an unsimplified Cambridge Prefix version of
5f892713c3 2021-03-03 110: algebraic-mode expressions typed by the user, then the simplifier
5f892713c3 2021-03-03 111: returns a simplified prefix version. When a symbolic procedure that
5f892713c3 2021-03-03 112: has been declared a symbolic operator is invoked from algebraic mode,
5f892713c3 2021-03-03 113: the procedure is given simplified Cambridge Prefix versions of the
5f892713c3 2021-03-03 114: arguments. To illustrate these ideas, here is an infix function named
5f892713c3 2021-03-03 115: ISFREEOF, which determines whether its left argument is free of the
5f892713c3 2021-03-03 116: indeterminate, function name, or literal sub-expression which is the
5f892713c3 2021-03-03 117: right argument. ISFREEOF is similar to the REDUCE FREEOF function but
5f892713c3 2021-03-03 118: less general.;
5f892713c3 2021-03-03 119:
5f892713c3 2021-03-03 120: pause;
5f892713c3 2021-03-03 121:
5f892713c3 2021-03-03 122: flag('(isfreeof), 'boolean);
5f892713c3 2021-03-03 123: infix isfreeof;
5f892713c3 2021-03-03 124: symbolic procedure campre1 isfreeof campre2;
5f892713c3 2021-03-03 125: if campre1=campre2 then nil
5f892713c3 2021-03-03 126: else if atom campre1 then t
5f892713c3 2021-03-03 127: else (car campre1 isfreeof campre2)
5f892713c3 2021-03-03 128: and (cdr campre1 isfreeof campre2);
5f892713c3 2021-03-03 129:
5f892713c3 2021-03-03 130: algebraic if log(5+x+cos(y)) isfreeof sin(z-7)
5f892713c3 2021-03-03 131: then write "WORKS ONE WAY";
5f892713c3 2021-03-03 132: algebraic if not(log(5+x+cos(y)) isfreeof cos(y))
5f892713c3 2021-03-03 133: then write "WORKS OTHER WAY TOO";
5f892713c3 2021-03-03 134:
5f892713c3 2021-03-03 135: COMMENT Conceivably we might wish to distinguish when CAMPRE2 is a
5f892713c3 2021-03-03 136: literal atom occurring as a function name from the case when CAMPRE2
5f892713c3 2021-03-03 137: is a literal atom and occurs as an indeterminate. Accordingly, see if
5f892713c3 2021-03-03 138: you can write two such more specialized infix predicates named
5f892713c3 2021-03-03 139: ISFREEOFINDET and ISFREEOFFUNCTION.;
5f892713c3 2021-03-03 140:
5f892713c3 2021-03-03 141: pause;
5f892713c3 2021-03-03 142:
5f892713c3 2021-03-03 143: COMMENT When writing a symbolic-mode function, it is often desired to
5f892713c3 2021-03-03 144: invoke the algebraic simplifier from within the function. This can be
5f892713c3 2021-03-03 145: done by using the function named REVAL, which returns a simplified
5f892713c3 2021-03-03 146: Cambridge Prefix version of its prefix argument.
5f892713c3 2021-03-03 147:
5f892713c3 2021-03-03 148: Usually, REDUCE uses and produces a different representation, which I
5f892713c3 2021-03-03 149: call REDUCE prefix. The symbolic function AEVAL returns a simplified
5f892713c3 2021-03-03 150: REDUCE-prefix version of its prefix argument. Both REVAL and AEVAL
5f892713c3 2021-03-03 151: can take either type of prefix argument.
5f892713c3 2021-03-03 152:
5f892713c3 2021-03-03 153: A REDUCE-prefix expression is an integer, a floating-point number, an
5f892713c3 2021-03-03 154: indeterminate, or an expression of the form
5f892713c3 2021-03-03 155:
5f892713c3 2021-03-03 156: ('!*SQ standardquotient . !*SQVAR!*).
5f892713c3 2021-03-03 157:
5f892713c3 2021-03-03 158: !*SQVAR!* is a global variable which is set to T when the REDUCE-
5f892713c3 2021-03-03 159: prefix expression is originally formed. The value of !*SQVAR!* is
5f892713c3 2021-03-03 160: reset to NIL if subsequent LET, MATCH, or computational ON statements
5f892713c3 2021-03-03 161: could change the environment is such a way that the expression might
5f892713c3 2021-03-03 162: require resimplification next time it is used.;
5f892713c3 2021-03-03 163:
5f892713c3 2021-03-03 164: pause;
5f892713c3 2021-03-03 165:
5f892713c3 2021-03-03 166: COMMENT Standard quotients are neither Cambridge nor REDUCE prefix, so
5f892713c3 2021-03-03 167: the purpose of the atom '!*SQ is to make the value of all algebraic-
5f892713c3 2021-03-03 168: mode variables always be some type of prefix form at the top level.
5f892713c3 2021-03-03 169:
5f892713c3 2021-03-03 170: A standard quotient is a unit-normal dotted pair of 2 standard forms,
5f892713c3 2021-03-03 171: and a standard form is the REDUCE representation for a polynomial.
5f892713c3 2021-03-03 172: Unit-normal means that the leading coefficient of the denominator is
5f892713c3 2021-03-03 173: positive.
5f892713c3 2021-03-03 174:
5f892713c3 2021-03-03 175: REDUCE has a built-in symbolic function SIMP!*, which returns the
5f892713c3 2021-03-03 176: simplified standard quotient representation of its argument, which can
5f892713c3 2021-03-03 177: be either Cambridge or REDUCE prefix. REDUCE also has symbolic
5f892713c3 2021-03-03 178: functions named NEGSQ, INVSQ, ADDSQ, MULTSQ, DIVSQ, DIFFSQ, and
5f892713c3 2021-03-03 179: CANONSQ which respectively negate, reciprocate, add, multiply, divide,
5f892713c3 2021-03-03 180: differentiate, and unit-normalize standard quotients. There is also a
5f892713c3 2021-03-03 181: function named ABSQ, which negates a standard quotient if the leading
5f892713c3 2021-03-03 182: coefficient of its numerator is negative, and there is a function
5f892713c3 2021-03-03 183: named EXPTSQ which raises a standard quotient to an integer power.
5f892713c3 2021-03-03 184: Finally, there is a function named MK!*SQ, which returns a REDUCE
5f892713c3 2021-03-03 185: prefix version of its standard-quotient argument, and there is also a
5f892713c3 2021-03-03 186: function named PREPSQ which returns a Cambridge prefix version of its
5f892713c3 2021-03-03 187: standard-quotient argument.
5f892713c3 2021-03-03 188:
5f892713c3 2021-03-03 189: If there is a sequence of operations, rather than converting from
5f892713c3 2021-03-03 190: prefix to standard quotient and back at each step, it is usually more
5f892713c3 2021-03-03 191: efficient to do the operations on standard quotients, then use MK!*SQ
5f892713c3 2021-03-03 192: to make the final result be REDUCE prefix. Also it is often more
5f892713c3 2021-03-03 193: efficient to work with polynomials rather than rational functions
5f892713c3 2021-03-03 194: during the intermediate steps.;
5f892713c3 2021-03-03 195:
5f892713c3 2021-03-03 196: pause;
5f892713c3 2021-03-03 197:
5f892713c3 2021-03-03 198: COMMENT The coefficient domain of polynomials is floating-point
5f892713c3 2021-03-03 199: numbers, integers, integers modulo an arbitrary integer modulus, or
5f892713c3 2021-03-03 200: rational numbers. However, zero is represented as NIL.
5f892713c3 2021-03-03 201:
5f892713c3 2021-03-03 202: The polynomial variables are called kernels, which can be
5f892713c3 2021-03-03 203: indeterminates or uniquely-stored fully simplified Cambridge-prefix
5f892713c3 2021-03-03 204: functional forms. The latter alternative permits the representation
5f892713c3 2021-03-03 205: of expressions which could not otherwise be represented as the ratio
5f892713c3 2021-03-03 206: of two expanded polynomials, such as
5f892713c3 2021-03-03 207:
5f892713c3 2021-03-03 208: 1. sub-expressions of the form LOG(...) or SIN(...),
5f892713c3 2021-03-03 209: 2. sub-expressions of the form indeterminate^noninteger,
5f892713c3 2021-03-03 210: 3. unexpanded polynomials, each polynomial factor being
5f892713c3 2021-03-03 211: represented as a functional form,
5f892713c3 2021-03-03 212: 4. rational expressions not placed over a common denominator,
5f892713c3 2021-03-03 213: each quotient sub-expression being represented as a functional
5f892713c3 2021-03-03 214: form.
5f892713c3 2021-03-03 215:
5f892713c3 2021-03-03 216: A polynomial is represented as a list of its nonzero terms in
5f892713c3 2021-03-03 217: decreasing order of the degree of the leading "variable". Each term
5f892713c3 2021-03-03 218: is represented as a standard power dotted with its coefficient, which
5f892713c3 2021-03-03 219: is a standard form in the remaining variables. A standard power is
5f892713c3 2021-03-03 220: represented as a variable dotted with a positive integer degree.;
5f892713c3 2021-03-03 221:
5f892713c3 2021-03-03 222: pause;
5f892713c3 2021-03-03 223:
5f892713c3 2021-03-03 224: COMMENT Letting ::= denote "is defined as" and letting | denote "or",
5f892713c3 2021-03-03 225: we can summarize the REDUCE data representations as follows:
5f892713c3 2021-03-03 226:
5f892713c3 2021-03-03 227: reduceprefix ::= ('!*SQ standardquotient . !*SQVAR!*)
5f892713c3 2021-03-03 228: standardquotient ::= NUMR(standardquotient) ./
5f892713c3 2021-03-03 229: DENR(standardquotient)
5f892713c3 2021-03-03 230: NUMR(standardquotient) ::= standardform
5f892713c3 2021-03-03 231: DENR(standardquotient) ::= unitnormalstandardform
5f892713c3 2021-03-03 232: domainelement ::= NIL | nonzerointeger | nonzerofloat |
5f892713c3 2021-03-03 233: nonzerointeger . positiveinteger
5f892713c3 2021-03-03 234: standardform ::= domainelement |
5f892713c3 2021-03-03 235: LT(standardform) .+ RED(standardform)
5f892713c3 2021-03-03 236: RED(standardform) ::= standardform
5f892713c3 2021-03-03 237: LT(standardform) := LPOW(standardform) .* LC(standardform)
5f892713c3 2021-03-03 238: LPOW(standardform) := MVAR(standardform) .^ LDEG(standardform)
5f892713c3 2021-03-03 239: LC(standardform) ::= standardform
5f892713c3 2021-03-03 240: MVAR(standardform) ::= kernel
5f892713c3 2021-03-03 241: kernel ::= indeterminate | functionalform
5f892713c3 2021-03-03 242: functionalform ::= (functionname Cambridgeprefix1 Cambridgeprefix2
5f892713c3 2021-03-03 243: ...)
5f892713c3 2021-03-03 244: Cambridgeprefix ::= integer | float | indeterminate |
5f892713c3 2021-03-03 245: functionalform
5f892713c3 2021-03-03 246: LC(unitnormalstandardform) ::= positivedomainelement |
5f892713c3 2021-03-03 247: unitnormalstandardform
5f892713c3 2021-03-03 248:
5f892713c3 2021-03-03 249: I have taken this opportunity to also introduce the major REDUCE
5f892713c3 2021-03-03 250: selector macros named NUMR, DENR, LT, RED, LPOW, LC, MVAR, and LDEG,
5f892713c3 2021-03-03 251: together with the major constructor macros named ./, .+, .*, and .^ .
5f892713c3 2021-03-03 252: The latter are just mnemonic aliases for ".". A comparison of my
5f892713c3 2021-03-03 253: verbal and more formal definitions also reveals that the selectors are
5f892713c3 2021-03-03 254: respectively just aliases for CAR, CDR, CAR, CDR, CAAR, CDAR, CAAAR,
5f892713c3 2021-03-03 255: and CDAAR. Since these selectors and constructors are macros rather
5f892713c3 2021-03-03 256: than functions, they afford a more readable and modifiable programming
5f892713c3 2021-03-03 257: style at no cost in ultimate efficiency. Thus you are encouraged to
5f892713c3 2021-03-03 258: use them and to invent your own when convenient. As an example of how
5f892713c3 2021-03-03 259: this can be done, here is the macro definition for extracting the main
5f892713c3 2021-03-03 260: variable of a standard term:;
5f892713c3 2021-03-03 261:
5f892713c3 2021-03-03 262: % symbolic smacro procedure tvar trm; caar trm;
5f892713c3 2021-03-03 263:
5f892713c3 2021-03-03 264: pause;
5f892713c3 2021-03-03 265:
5f892713c3 2021-03-03 266: COMMENT It turns out that there are already built-in selectors named
5f892713c3 2021-03-03 267: TC, TPOW, and TDEG, which respectively extract the coefficient,
5f892713c3 2021-03-03 268: leading power, and leading degree of a standard term. There are also
5f892713c3 2021-03-03 269: built-in constructors named !*P2F, !*K2F, !*K2Q, and !*T2Q, which
5f892713c3 2021-03-03 270: respectively make a power into a standard form, a kernel into a
5f892713c3 2021-03-03 271: standard form, a kernel into a standard quotient, and a term into a
5f892713c3 2021-03-03 272: standard quotient. See the REDUCE User's Manual for a complete list.
5f892713c3 2021-03-03 273:
5f892713c3 2021-03-03 274: The unary functions NEGF and ABSF respectively negate, and unit-
5f892713c3 2021-03-03 275: normalize their standard-form arguments. The binary functions ADDF,
5f892713c3 2021-03-03 276: MULTF, QUOTF, SUBF, EXPTF, and GCDF respectively add, multiply, divide,
5f892713c3 2021-03-03 277: substitute into, raise to a positive integer power, and determine the
5f892713c3 2021-03-03 278: greatest common divisor of standard forms. See if you can use them to
5f892713c3 2021-03-03 279: define a macro which subtracts standard forms.;
5f892713c3 2021-03-03 280:
5f892713c3 2021-03-03 281: pause;
5f892713c3 2021-03-03 282:
5f892713c3 2021-03-03 283: COMMENT The best way to become adept at working with standard forms
5f892713c3 2021-03-03 284: and standard quotients is to study the corresponding portions of the
5f892713c3 2021-03-03 285: REDUCE source listing. The listing of ADDF and its subordinates is
5f892713c3 2021-03-03 286: particularly instructive. As an exercise, see if you can write a
5f892713c3 2021-03-03 287: function named ISFREEOFKERN which determines whether or not its left
5f892713c3 2021-03-03 288: argument is free of the kernel which is the right argument, using
5f892713c3 2021-03-03 289: REDUCE prefix rather than Cambridge prefix for the left argument.;
5f892713c3 2021-03-03 290:
5f892713c3 2021-03-03 291: pause;
5f892713c3 2021-03-03 292:
5f892713c3 2021-03-03 293: COMMENT As a final example of the interaction between modes, here is a
5f892713c3 2021-03-03 294: function which produces simple character-based plots. Note that, to
5f892713c3 2021-03-03 295: keep the implementation as simple as possible, values of the
5f892713c3 2021-03-03 296: indeterminate ("x") increase downwards and values of the expression
5f892713c3 2021-03-03 297: plotted ("y") increase to the right. This is the conventional
5f892713c3 2021-03-03 298: orientation rotated clockwise through 90 degrees!;
5f892713c3 2021-03-03 299:
5f892713c3 2021-03-03 300: share ncols;
5f892713c3 2021-03-03 301: ncols := 66;
5f892713c3 2021-03-03 302: symbolic operator plot;
5f892713c3 2021-03-03 303: symbolic procedure plot(ex, xinit, dx, ndx, yinit, dy);
5f892713c3 2021-03-03 304: begin COMMENT This procedure produces a character-plot of univariate
5f892713c3 2021-03-03 305: expression EX where,
5f892713c3 2021-03-03 306: XINIT is the initial value of the indeterminate,
5f892713c3 2021-03-03 307: DX is the increment per line of the indeterminate,
5f892713c3 2021-03-03 308: NDX is the number of lines plotted,
5f892713c3 2021-03-03 309: YINIT is the value represented at the left edge,
5f892713c3 2021-03-03 310: DY is incremental value per column.
5f892713c3 2021-03-03 311: The shared variable NCOLS, initially 66, is the number of columns
5f892713c3 2021-03-03 312: used. Points are plotted using "*", except "<" and ">" are used
5f892713c3 2021-03-03 313: at the left and right edges to indicate out of bounds points.;
5f892713c3 2021-03-03 314:
5f892713c3 2021-03-03 315: scalar x, f, y; integer col, ncolsminus1;
5f892713c3 2021-03-03 316: ncolsminus1 := ncols - 1;
5f892713c3 2021-03-03 317: write "Starting the plot of ",ex;
5f892713c3 2021-03-03 318: x := listofvars ex; % find indeterminates;
5f892713c3 2021-03-03 319: if length x > 1 then rederr
5f892713c3 2021-03-03 320: "ERROR: PLOT expression can have at most 1 indeterminate";
5f892713c3 2021-03-03 321: if null x then <<
5f892713c3 2021-03-03 322: write "ERROR: no indeterminates in ", ex;
5f892713c3 2021-03-03 323: rederr "" >>
5f892713c3 2021-03-03 324: else x := car x;
5f892713c3 2021-03-03 325: write " in variable ", x; terpri();
5f892713c3 2021-03-03 326: COMMENT Convert args from algebraic to symbolic values;
5f892713c3 2021-03-03 327: xinit := revalx xinit;
5f892713c3 2021-03-03 328: dx := revalx dx;
5f892713c3 2021-03-03 329: yinit := revalx yinit;
5f892713c3 2021-03-03 330: dy := revalx dy;
5f892713c3 2021-03-03 331:
5f892713c3 2021-03-03 332: for j:= 0:ndx do <<
5f892713c3 2021-03-03 333:
5f892713c3 2021-03-03 334: % generate expression with current value substituted for x
5f892713c3 2021-03-03 335: f := subst(xinit + j*dx, x, ex);
5f892713c3 2021-03-03 336: y := eval(f); % eval expression
5f892713c3 2021-03-03 337: col := rnd((y - yinit)/dy); % scale and round for cols
5f892713c3 2021-03-03 338:
5f892713c3 2021-03-03 339: if col<0 then write "<"
5f892713c3 2021-03-03 340: else if col > ncolsminus1 then << spaces(ncolsminus1);
5f892713c3 2021-03-03 341: prin2 ">";
5f892713c3 2021-03-03 342: terpri() >>
5f892713c3 2021-03-03 343: else << spaces(col);
5f892713c3 2021-03-03 344: prin2 "*";
5f892713c3 2021-03-03 345: terpri() >>
5f892713c3 2021-03-03 346: >> ;
5f892713c3 2021-03-03 347: if null y then rederr
5f892713c3 2021-03-03 348: "ERROR: UNABLE TO PERFORM FLOATING-POINT EVALUATION OF 1ST ARG"
5f892713c3 2021-03-03 349: end;
5f892713c3 2021-03-03 350:
5f892713c3 2021-03-03 351: pause;
5f892713c3 2021-03-03 352:
5f892713c3 2021-03-03 353: symbolic procedure listofvars campre;
5f892713c3 2021-03-03 354: if null campre or numberp campre then nil
5f892713c3 2021-03-03 355: else if atom campre then list campre
5f892713c3 2021-03-03 356: else varsinargs cdr campre;
5f892713c3 2021-03-03 357:
5f892713c3 2021-03-03 358: symbolic procedure varsinargs listofcampre;
5f892713c3 2021-03-03 359: if null listofcampre then nil
5f892713c3 2021-03-03 360: else union(listofvars car listofcampre, varsinargs cdr listofcampre);
5f892713c3 2021-03-03 361:
5f892713c3 2021-03-03 362: symbolic procedure rnd x;
5f892713c3 2021-03-03 363: begin scalar ans;
5f892713c3 2021-03-03 364: ans := revalx x;
5f892713c3 2021-03-03 365: if not numberp x then redderr "RND GIVEN NON-NUMERIC ARGUMENT";
5f892713c3 2021-03-03 366: if ans >=0 then ans := fix(ans+00.5)
5f892713c3 2021-03-03 367: else ans:= fix(ans-0.5);
5f892713c3 2021-03-03 368: return ans
5f892713c3 2021-03-03 369: end;
5f892713c3 2021-03-03 370:
5f892713c3 2021-03-03 371: symbolic procedure revalx u;
5f892713c3 2021-03-03 372: % MAKE SURE WE GET TRUE FLOATS IN SYMBOLIC MODE.
5f892713c3 2021-03-03 373: if eqcar(u,'!:rd!:) then rdprepx u else u;
5f892713c3 2021-03-03 374:
5f892713c3 2021-03-03 375: symbolic procedure rdprepx u;
5f892713c3 2021-03-03 376: if floatp cdr u then cdr u else bf2flr u;
5f892713c3 2021-03-03 377:
5f892713c3 2021-03-03 378: pause;
5f892713c3 2021-03-03 379:
5f892713c3 2021-03-03 380: on rounded;
5f892713c3 2021-03-03 381:
5f892713c3 2021-03-03 382: plot(y^2, 0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 383: pause;
5f892713c3 2021-03-03 384:
5f892713c3 2021-03-03 385: plot((a+1)^2, 0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 386: pause;
5f892713c3 2021-03-03 387:
5f892713c3 2021-03-03 388: b := a*2;
5f892713c3 2021-03-03 389:
5f892713c3 2021-03-03 390: plot(a*b, 0, 0.25, 10, 0, 0.25);
5f892713c3 2021-03-03 391: pause;
5f892713c3 2021-03-03 392:
5f892713c3 2021-03-03 393: COMMENT We leave it as an exercise to write a more elaborate plot
5f892713c3 2021-03-03 394: procedure which offers amenities such as automatic scaling, numbered
5f892713c3 2021-03-03 395: ordinates, etc.
5f892713c3 2021-03-03 396:
5f892713c3 2021-03-03 397: Good luck with these exercises, with REDUCE, with computer algebra and
5f892713c3 2021-03-03 398: with all of your endeavors.
5f892713c3 2021-03-03 399:
5f892713c3 2021-03-03 400: ;end;