R E D U C E U S E R ' S M A N U A L Version 3.3 Anthony C. Hearn The Rand Corporation Santa Monica, CA 90406-2138 July 1987 Rand Publication CP78 (Rev. 7/87) Copyright (c) 1987 The Rand Corporation. All rights reserved. Registered system holders may reproduce all or any part of this publication for internal purposes, provided that the source of the material is clearly acknowledged, and the copyright notice is retained. ABSTRACT This document provides the user with a description of the algebraic programming system REDUCE. The capabilities of this system include: 1) expansion and ordering of polynomials and rational functions, 2) substitutions and pattern matching in a wide variety of forms, 3) automatic and user controlled simplification of expressions, 4) calculations with symbolic matrices, 5) arbitrary precision integer and real arithmetic, 6) facilities for defining new functions and extending program syntax, 7) analytic differentiation and integration, 8) factorization of polynomials, 9) Dirac matrix calculations of interest to high energy physicists. ACKNOWLEDGMENT The production of this version of the manual has been the result of the contributions of a large number of individuals who have taken the time and effort to suggest improvements to previous versions, and to draft new sections. Particular thanks are due to Gerry Rayna, who provided a draft rewrite of most of the first half of the manual. Other people who have made significant contributions have included John Fitch, Martin Griss, Jed Marti, Don Morrison, Arthur Norman and Larry Seward. TABLE OF CONTENTS 1. Introductory information about REDUCE. . . . . . . . . . . . . . .1-1 2. Structure of programs. . . . . . . . . . . . . . . . . . . . . . .2-1 2.1 The REDUCE standard character set . . . . . . . . . . . .2-1 2.2 Numbers . . . . . . . . . . . . . . . . . . . . . . . . .2-1 2.3 Identifiers . . . . . . . . . . . . . . . . . . . . . . .2-2 2.3.1 Restrictions. . . . . . . . . . . . . . . . . . . . . .2-3 2.4 Variables . . . . . . . . . . . . . . . . . . . . . . . .2-3 2.4.1 Reserved variables. . . . . . . . . . . . . . . . . . .2-3 2.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . .2-4 2.6 Comments. . . . . . . . . . . . . . . . . . . . . . . . .2-4 2.7 Operators . . . . . . . . . . . . . . . . . . . . . . . .2-4 2.7.1 Built-in infix operators. . . . . . . . . . . . . . . .2-5 3. Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . .3-1 3.1 Scalar expressions. . . . . . . . . . . . . . . . . . . .3-1 3.2 Integer expressions . . . . . . . . . . . . . . . . . . .3-2 3.3 Boolean expressions . . . . . . . . . . . . . . . . . . .3-2 3.4 Equations . . . . . . . . . . . . . . . . . . . . . . . .3-3 3.5 Proper statements as expressions. . . . . . . . . . . . .3-4 4. Lists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1 Operations on lists . . . . . . . . . . . . . . . . . . .4-1 4.1.1 First . . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1.2 Second. . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1.3 Third . . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1.4 Rest. . . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1.5 . (Cons) operator . . . . . . . . . . . . . . . . . . .4-2 4.1.6 Append. . . . . . . . . . . . . . . . . . . . . . . . .4-2 4.1.7 Reverse . . . . . . . . . . . . . . . . . . . . . . . .4-2 5. Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 5.1 Assignment statements . . . . . . . . . . . . . . . . . .5-1 5.1.1 SET statement . . . . . . . . . . . . . . . . . . . . .5-2 5.2 Group statements. . . . . . . . . . . . . . . . . . . . .5-2 5.3 Conditional statements. . . . . . . . . . . . . . . . . .5-3 5.4 FOR statements. . . . . . . . . . . . . . . . . . . . . .5-4 5.5 WHILE...DO. . . . . . . . . . . . . . . . . . . . . . . .5-5 5.6 REPEAT...UNTIL. . . . . . . . . . . . . . . . . . . . . .5-6 5.7 Compound statements . . . . . . . . . . . . . . . . . . .5-7 5.7.1 Compound statements with GO TO. . . . . . . . . . . . .5-8 5.7.2 Labels and GO TO statements . . . . . . . . . . . . . .5-9 5.7.3 RETURN statements . . . . . . . . . . . . . . . . . . .5-9 6. Commands and declarations. . . . . . . . . . . . . . . . . . . . .6-1 6.1 Array declarations. . . . . . . . . . . . . . . . . . . .6-1 6.2 Mode handling declarations. . . . . . . . . . . . . . . .6-2 6.3 END identifier. . . . . . . . . . . . . . . . . . . . . .6-2 6.4 BYE command . . . . . . . . . . . . . . . . . . . . . . .6-3 6.5 QUIT command. . . . . . . . . . . . . . . . . . . . . . .6-3 6.6 SHOWTIME command. . . . . . . . . . . . . . . . . . . . .6-3 6.7 DEFINE command. . . . . . . . . . . . . . . . . . . . . .6-3 ii 7. Built-in prefix operators. . . . . . . . . . . . . . . . . . . . .7-1 7.1 Numerical functions . . . . . . . . . . . . . . . . . . .7-1 7.2 Mathematical functions. . . . . . . . . . . . . . . . . .7-1 7.3 DF operator . . . . . . . . . . . . . . . . . . . . . . .7-3 7.3.1 Adding differentiation rules. . . . . . . . . . . . . .7-3 7.4 INT operator. . . . . . . . . . . . . . . . . . . . . . .7-4 7.4.1 Options . . . . . . . . . . . . . . . . . . . . . . . .7-5 7.4.2 Advanced use. . . . . . . . . . . . . . . . . . . . . .7-5 7.4.3 References. . . . . . . . . . . . . . . . . . . . . . .7-5 7.5 Length operator . . . . . . . . . . . . . . . . . . . . .7-6 7.6 MKID operator . . . . . . . . . . . . . . . . . . . . . .7-6 7.7 SOLVE operator. . . . . . . . . . . . . . . . . . . . . .7-6 7.7.1 Options . . . . . . . . . . . . . . . . . . . . . . . .7-7 7.8 Linear operators. . . . . . . . . . . . . . . . . . . . .7-8 7.9 Non-commuting operators . . . . . . . . . . . . . . . . .7-9 7.10 Symmetric and antisymmetric operators. . . . . . . . . .7-9 7.11 Declaring new prefix operators . . . . . . . . . . . . 7-10 7.12 Declaring new infix operators. . . . . . . . . . . . . 7-11 7.13 Creating and removing variable dependency. . . . . . . 7-11 8. Display and structuring of expressions . . . . . . . . . . . . . .8-1 8.1 Kernels . . . . . . . . . . . . . . . . . . . . . . . . .8-1 8.2 The expression workspace. . . . . . . . . . . . . . . . .8-2 8.3 Output of expressions . . . . . . . . . . . . . . . . . .8-3 8.3.1 LINELENGTH operator . . . . . . . . . . . . . . . . . .8-3 8.3.2 Output declarations . . . . . . . . . . . . . . . . . .8-3 8.3.2.1 ORDER declaration . . . . . . . . . . . . . . . . . .8-4 8.3.2.2 FACTOR declaration. . . . . . . . . . . . . . . . . .8-4 8.3.3 Output control switches . . . . . . . . . . . . . . . .8-5 8.3.3.1 ALLFAC switch . . . . . . . . . . . . . . . . . . . .8-5 8.3.3.2 DIV switch. . . . . . . . . . . . . . . . . . . . . .8-5 8.3.3.3 LIST switch . . . . . . . . . . . . . . . . . . . . .8-5 8.3.3.4 RAT switch. . . . . . . . . . . . . . . . . . . . . .8-6 8.3.3.5 RATPRI switch . . . . . . . . . . . . . . . . . . . .8-6 8.3.3.6 REVPRI switch . . . . . . . . . . . . . . . . . . . .8-7 8.3.4 WRITE command . . . . . . . . . . . . . . . . . . . . .8-7 8.3.5 Suppression of zeros. . . . . . . . . . . . . . . . . .8-9 8.3.6 FORTRAN style output of expressions . . . . . . . . . .8-9 8.3.6.1 FORTRAN output options. . . . . . . . . . . . . . . 8-11 8.3.7 Saving expressions for later use as input . . . . . . 8-11 8.3.8 Displaying expression structure . . . . . . . . . . . 8-12 8.4 Changing the internal order of variables. . . . . . . . 8-13 8.5 Obtaining parts of algebraic expressions. . . . . . . . 8-13 8.5.1 COEFF operator. . . . . . . . . . . . . . . . . . . . 8-13 8.5.2 COEFFN operator . . . . . . . . . . . . . . . . . . . 8-14 8.5.3 PART operator . . . . . . . . . . . . . . . . . . . . 8-14 8.5.4 Changing parts of expressions . . . . . . . . . . . . 8-15 9. Operations on polynomials and rationals. . . . . . . . . . . . . .9-1 9.1 Controlling the expansion of expressions. . . . . . . . .9-1 9.2 Factorization of polynomials. . . . . . . . . . . . . . .9-2 9.3 Cancellation of common factors. . . . . . . . . . . . . .9-4 9.3.1 Determining the GCD of two polynomials. . . . . . . . .9-5 iii 9.4 Working with least common multiples . . . . . . . . . . .9-5 9.5 Controlling use of common denominators. . . . . . . . . .9-5 9.6 REMAINDER operator. . . . . . . . . . . . . . . . . . . .9-6 9.7 RESULTANT operator. . . . . . . . . . . . . . . . . . . .9-6 9.8 Obtaining parts of polynomials and rational functions . .9-6 9.8.1 DEG operator. . . . . . . . . . . . . . . . . . . . . .9-7 9.8.2 DEN operator. . . . . . . . . . . . . . . . . . . . . .9-7 9.8.3 LCOF operator . . . . . . . . . . . . . . . . . . . . .9-7 9.8.4 LTERM operator. . . . . . . . . . . . . . . . . . . . .9-8 9.8.5 MAINVAR operator. . . . . . . . . . . . . . . . . . . .9-8 9.8.6 NUM operator. . . . . . . . . . . . . . . . . . . . . .9-8 9.8.7 REDUCT operator . . . . . . . . . . . . . . . . . . . .9-8 9.9 Polynomial coefficient arithmetic . . . . . . . . . . . .9-9 9.9.1 Rational coefficients in polynomials. . . . . . . . . .9-9 9.9.2 Real coefficients in polynomials. . . . . . . . . . . .9-9 9.9.3 Arbitrary precision real coefficients . . . . . . . . 9-10 9.9.4 Modular number coefficients in polynomials. . . . . . 9-10 9.9.5 Complex number coefficients in polynomials. . . . . . 9-10 10. Substitution commands . . . . . . . . . . . . . . . . . . . . . 10-1 10.1 SUB operator . . . . . . . . . . . . . . . . . . . . . 10-1 10.2 WHERE operator . . . . . . . . . . . . . . . . . . . . 10-1 10.3 LET rules. . . . . . . . . . . . . . . . . . . . . . . 10-2 10.3.1 FOR ALL...LET. . . . . . . . . . . . . . . . . . . . 10-4 10.3.2 FOR ALL...SUCH THAT...LET. . . . . . . . . . . . . . 10-5 10.3.3 Removing assignments and substitution rules. . . . . 10-5 10.3.4 Overlapping LET Rules. . . . . . . . . . . . . . . . 10-6 10.3.5 Substitutions for general expressions. . . . . . . . 10-6 10.4 Asymptotic commands. . . . . . . . . . . . . . . . . . 10-9 11. File handling commands. . . . . . . . . . . . . . . . . . . . . 11-1 11.1 IN command . . . . . . . . . . . . . . . . . . . . . . 11-1 11.2 OUT command. . . . . . . . . . . . . . . . . . . . . . 11-1 11.3 SHUT command . . . . . . . . . . . . . . . . . . . . . 11-2 12. Commands for interactive use of REDUCE. . . . . . . . . . . . . 12-1 12.1 Referencing previous results . . . . . . . . . . . . . 12-1 12.2 Interactive editing. . . . . . . . . . . . . . . . . . 12-2 12.3 Interactive file control . . . . . . . . . . . . . . . 12-3 13. Matrix calculations . . . . . . . . . . . . . . . . . . . . . . 13-1 13.1 MAT operator . . . . . . . . . . . . . . . . . . . . . 13-1 13.2 Matrix variables . . . . . . . . . . . . . . . . . . . 13-1 13.3 Matrix expressions . . . . . . . . . . . . . . . . . . 13-2 13.4 Operators with matrix arguments. . . . . . . . . . . . 13-2 13.4.1 DET operator . . . . . . . . . . . . . . . . . . . . 13-3 13.4.2 TP operator. . . . . . . . . . . . . . . . . . . . . 13-3 13.4.3 TRACE operator . . . . . . . . . . . . . . . . . . . 13-3 13.5 Matrix assignments . . . . . . . . . . . . . . . . . . 13-3 13.6 Evaluating matrix elements . . . . . . . . . . . . . . 13-4 iv 14. Procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 14.1 Procedure heading. . . . . . . . . . . . . . . . . . . 14-1 14.2 Procedure body . . . . . . . . . . . . . . . . . . . . 14-2 14.3 Using LET inside procedures. . . . . . . . . . . . . . 14-4 14.4 Let Rules as procedures. . . . . . . . . . . . . . . . 14-4 15. User contributed packages . . . . . . . . . . . . . . . . . . . 15-1 15.1 ALGINT: indefinite integration of square roots . . . . 15-1 15.2 ANUM: an algebraic number package. . . . . . . . . . . 15-1 15.3 EXCALC: a differential geometry package. . . . . . . . 15-1 15.4 GENTRAN: a code generation package . . . . . . . . . . 15-2 15.5 GROEBNER: Groebner Basis computation . . . . . . . . . 15-2 15.6 SPDE: a package for finding symmetry groups of PDE's . 15-2 16. Symbolic mode . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 16.1 Symbolic infix operators . . . . . . . . . . . . . . . 16-2 16.2 Symbolic expressions . . . . . . . . . . . . . . . . . 16-2 16.3 Quoted expressions . . . . . . . . . . . . . . . . . . 16-3 16.4 LAMBDA expressions . . . . . . . . . . . . . . . . . . 16-3 16.5 Symbolic assignment statements . . . . . . . . . . . . 16-4 16.6 FOR EACH statement . . . . . . . . . . . . . . . . . . 16-4 16.7 Symbolic procedures. . . . . . . . . . . . . . . . . . 16-4 16.8 Standard LISP equivalent of REDUCE input . . . . . . . 16-5 16.9 Communicating with algebraic mode. . . . . . . . . . . 16-5 16.9.1 Passing algebraic mode values to symbolic mode . . . 16-6 16.9.2 Passing Symbolic mode values back to algebraic mode. 16-8 16.9.3 Complete example . . . . . . . . . . . . . . . . . . 16-9 16.9.4 Defining procedures which communicate between modes. 16-9 16.10 References. . . . . . . . . . . . . . . . . . . . . .16-10 17. Calculations in high energy physics . . . . . . . . . . . . . . 17-1 17.1 Notation . . . . . . . . . . . . . . . . . . . . . . . 17-1 17.2 Operators used in high energy physics calculations . . 17-1 17.2.1 . (Cons) operator. . . . . . . . . . . . . . . . . . 17-1 17.2.2 G operator for gamma matrices. . . . . . . . . . . . 17-2 17.2.3 EPS operator . . . . . . . . . . . . . . . . . . . . 17-3 17.3 Vector variables . . . . . . . . . . . . . . . . . . . 17-3 17.4 Additional expression types. . . . . . . . . . . . . . 17-3 17.4.1 Vector expressions . . . . . . . . . . . . . . . . . 17-3 17.4.2 Dirac expressions. . . . . . . . . . . . . . . . . . 17-4 17.5 Trace calculations . . . . . . . . . . . . . . . . . . 17-4 17.6 Mass declarations. . . . . . . . . . . . . . . . . . . 17-5 17.7 Example. . . . . . . . . . . . . . . . . . . . . . . . 17-5 17.8 Extensions to more than four dimensions. . . . . . . . 17-6 18. REDUCE and RLISP utilities. . . . . . . . . . . . . . . . . . . 18-1 18.1 The Standard LISP compiler . . . . . . . . . . . . . . 18-1 18.2 Fast loading code generation program . . . . . . . . . 18-1 18.3 The Standard LISP cross reference program. . . . . . . 18-2 18.3.1 Restrictions:. . . . . . . . . . . . . . . . . . . . 18-3 18.3.2 Usage: . . . . . . . . . . . . . . . . . . . . . . . 18-3 18.3.3 Options: . . . . . . . . . . . . . . . . . . . . . . 18-3 18.4 Prettyprinting REDUCE expressions. . . . . . . . . . . 18-4 v 18.5 Prettyprinting Standard LISP S-expressions . . . . . . 18-4 A. Reserved identifiers . . . . . . . . . . . . . . . . . . . . . . .A-1 B. Operators normally available in REDUCE . . . . . . . . . . . . . .B-1 C. Commands and declarations. . . . . . . . . . . . . . . . . . . . .C-1 D. Mode switches in REDUCE. . . . . . . . . . . . . . . . . . . . . .D-1 E. Diagnostic and error messages in REDUCE. . . . . . . . . . . . . .E-1 F. Variables in REDUCE. . . . . . . . . . . . . . . . . . . . . . . .F-1 G. Keyword index. . . . . . . . . . . . . . . . . . . . . . . . . . .G-1 1-1 1. INTRODUCTORY INFORMATION ABOUT REDUCE ←←←←←←←←←←←← ←←←←←←←←←←← ←←←←← ←←←←←← REDUCE is a system for carrying out algebraic operations accurately, no matter how complicated the expressions become. It can manipulate polynomials in a variety of forms, both expanding and factoring them, and extract various parts of them as required. REDUCE can also do differentiation and integration, but we shall only show trivial examples of this in this introduction. Other topics which are not considered include the use of arrays, the definition of procedures and operators, the specific routines for high energy physics calculations, the use of files to eliminate repetitious typing and for saving results, and the editing of the input text. Also not considered in any detail in this introduction are the many options that are available for varying computational procedures, output forms, number systems used, and so on. REDUCE is designed to be an interactive system, so that the user can input an algebraic expression and see its value before moving on to the next calculation. Not all computer systems support interactive use, so REDUCE can also be used in batch mode by inputting a sequence of calculations and getting results without the necessity of interaction during the calculations. In this introduction, we shall limit ourselves to the interactive use of REDUCE, since this illustrates most completely the capabilities of the system. When REDUCE is called, it begins by printing a banner message like: REDUCE 3.3, 15-Jul-87 ... where the version number and the system release date will change from time to time. It then prompts the user for input by: 1: You can now type a REDUCE statement, terminated by a semicolon to indicate the end of the expression, for example: (x+y+z)**2; This expression would normally be followed by another character (a Return on an ASCII keyboard) to "wake up" the system, which would then input the expression, evaluate it, and return the result: 2 2 2 X + 2*X*Y + 2*X*Z + Y + 2*Y*Z + Z Let us review this simple example to learn a little more about the way that REDUCE works. First, we note that REDUCE deals with variables, and constants like other computer languages, but that in evaluating the former, a variable can stand for itself. Expression evaluation normally follows 1-2 the rules of high school algebra, so the only surprise in the above example might be that the expression was expanded. REDUCE normally expands expressions where possible, collecting like terms and ordering the variables in a specific manner. However, expansion, ordering of variables, format of output and so on is under control of the user, and various declarations are available to manipulate these. Another characteristic of the above example is the use of lower case on input and upper case on output. In fact, input may be in either mode, but lower case is converted to upper case by the system. Finally, the numerical prompt can be used to reference the result in a later computation. As a further illustration of the system features, the user should try: for i:= 1:50 product i; The result in this case is the value of 50!, 30414093201713378043612608166064768844377641568960512000000000000 Since we want exact results in algebraic calculations, it is essential that integer arithmetic be performed to arbitrary precision, as in the above example. Furthermore, the FOR statement in the above is illustrative of a whole range of combining forms which REDUCE supports for the convenience of the user. Among the many options in REDUCE is the use of other number systems, such as multiple precision floating point with any specified number of digits -- of use if roundoff in, say, the 100th digit is all that can be tolerated. In many cases, it is necessary to use the results of one calculation in succeeding calculations. One way to do this is via an assignment for a variable, such as u := (x+y+z)**2; If we now use u in later calculations, the value of the right-hand side of the above will be used. The results of a given calculation are also saved in the variable WS (for WorkSpace), so this can be used in the next calculation for further processing. For example, the expression df(ws,x); following the previous evaluation will calculate the derivative of (x+y+z)**2 with respect to x. Alternatively, 1-3 int(ws,y); would calculate the integral of the same expression with respect to y. REDUCE is also capable of handling symbolic matrices. For example, matrix m(2,2); declares m to be a two by two matrix, and m := mat((a,b),(c,d)); gives its elements values. Expressions which include m and make algebraic sense may now be evaluated, such as 1/m to give the inverse, 2*m - u*m**2 to give us another matrix and det(m) to give us the determinant of m. REDUCE has a wide range of substitution capabilities. The system knows about elementary functions, but does not automatically invoke many of their well-known properties. For example, products of trigonometrical functions are not converted automatically into multiple angle expressions, but if the user wants this, he can say: for all x,y let cos(x)*cos(y) = (cos(x+y)+cos(x-y))/2, cos(x)*sin(y) = (sin(x+y)-sin(x-y))/2, sin(x)*sin(y) = (cos(x-y)-cos(x+y))/2; An expression such as sin(a+b)*cos(a-b) would now convert into the equivalent expression (SIN(2*A) + SIN(2*B))/2. Another very commonly used capability of the system, and an illustration of one of the many output modes of Reduce, is the ability to output results in a FORTRAN compatible form. Such results can then be used in a FORTRAN based numerical calculation. This is particularly useful as a way of generating algebraic formulas to be used as the basis of extensive numerical calculations. For example, the statements on fort; df(log(x)*(sin(x)+cos(x))/sqrt(x),x,2); will result in the output ANS=(-4.*LOG(X)*COS(X)*X**2-4.*LOG(X)*COS(X)*X+3.*LOG(X)* . COS(X)-4.*LOG(X)*SIN(X)*X**2+4.*LOG(X)*SIN(X)*X+3.*LOG(X) . *SIN(X)+8.*COS(X)*X-8.*COS(X)-8.*SIN(X)*X-8.*SIN(X))/(4.* . SQRT(X)*X**2) These algebraic manipulations illustrate the algebraic mode of REDUCE. REDUCE is based on Standard LISP. A symbolic mode is also available for 1-4 executing LISP statements. These statements follow the syntax of LISP, e.g. symbolic car '(a); Communication between the two modes is possible. With this simple introduction, you are now in a position to study the material in the full REDUCE manual in order to learn just how extensive the range of facilities really is. If further tutorial material is desired, the seven REDUCE Interactive Lessons by David R. Stoutemyer are recommended. These are normally available online at most installations. 2-1 2. STRUCTURE OF PROGRAMS ←←←←←←←←← ←← ←←←←←←←← A REDUCE program consists of a set of functional commands which are evaluated sequentially by the computer. These commands are built up from declarations, statements and expressions. Such entities are composed of sequences of numbers, variables, operators, strings, reserved words and delimiters (such as commas and parentheses), which in turn are sequences of basic characters. 2.1 The Reduce Standard Character Set ←←← ←←←←←← ←←←←←←←← ←←←←←←←←← ←←← The basic characters which are used to build REDUCE symbols are the following: i) The 26 upper case letters A through Z ii) The 10 decimal digits 0 through 9 iii) The special characters ! " " $ % ' ( ) * + , - . / : ; < > = { } Programs composed from this standard set of characters will run in any available REDUCE system. Most implementations permit lower case on input. With the exception of strings and characters preceded by an exclamation mark (q.v.), such lower case characters will be converted internally into upper case. If you do not wish this conversion to occur, the command OFF RAISE; achieves this. However, now case IS distinguished internally, so that df is not the same as DF (the derivative operator). Several implementations also allow some special characters to represent operators in the system. The operating instructions for a particular implementation should be consulted on these points. For generality, we shall limit ourselves to the standard character set in this exposition. 2.2 Numbers ←←←←←←← There are several different types of numbers available in REDUCE. Integers consist of a signed or unsigned sequence of decimal digits written without a decimal point. e.g. -2, 5396, +32 In principle, there is no practical limit on the number of digits permitted as exact arithmetic is used in most implementations. (You should however check the specific instructions for your particular system implementation to make sure that this is true.) For example, if you ask for the value of 2**2000 (2 to the 2000th power) you get it displayed as a number of 603 decimal digits, taking up nine lines of output on an interactive display. It should be borne in mind of course that computations with such long numbers can be quite slow. Numbers that aren't integers are usually represented as the quotient of two integers, in lowest terms: that is, as rational numbers. 2-2 In most versions of REDUCE it is also possible (but not always desirable!) to ask REDUCE to work with floating point approximations to numbers, either single precision or -- in some versions -- multiple precision with any specified number of digits. Such numbers are called REAL. They can be input in two ways: i) as a signed or unsigned sequence of decimal digits with an embedded or trailing decimal point. Up to 8 such digits are allowed in most implementations, although this can vary. Again, you should check the specific instructions for a given implementation for the maximum size permitted. ii) as in i) followed by a decimal exponent which is written as the letter E followed by a signed or unsigned integer. e.g. 32. +32.0 0.32E2 and 320.E-1 are all representations of 32. CAUTION: The unsigned part of any number may NOT begin with a decimal point, as this causes confusion with the CONS (.) operator in symbolic mode (q.v.), i.e. NOT ALLOWED: .5 -.23 +.12; use: 0.5 -0.23 +0.12 instead. 2.3 Identifiers ←←←←←←←←←←← Identifiers in REDUCE consist of one or more alphanumeric characters (i.e. upper case alphabetic letters or decimal digits) the first of which must be alphabetic. The maximum number of characters allowed is implementation dependent, although twenty-four is permitted in most implementations: e.g. A AZ P1 Q23P AVERYLONGVARIABLE A sequence of alphanumeric characters in which the first is a digit is interpreted as a product. For example, 2AB3C is interpreted as 2*AB3C. There is one exception to this: If the first letter after a digit is E, the system will try to interpret that part of the sequence as a real number, which may fail in some cases. For example, 2E12 is the real number 2.0*10**12, 2E3C is 2000.0*C, and 2EBC gives an error. Special characters, such as -, *, and blank, may be used in identifiers too, even as the first character, but each must be preceded by an exclamation mark in input: e.g. LIGHT!-YEARS D!*!*N GOOD! MORNING !$SIGN !5GOLDRINGS CAUTION: Many system identifiers have such special characters in their names (especially * and =). If the user accidentally picks the name of one of them for his own purposes it may have catastrophic consequences for his REDUCE run. Identifiers are used as variables, labels and to name arrays, operators and procedures. 2-3 2.3.1 Restrictions ←←←←←←←←←←←← The reserved words listed in another section may not be used as identifiers. No spaces may appear within an identifier, and an identifier may not extend over a line of text. (Hyphenation of an identifier, by using a reserved character as a hyphen before an end-of-line character is possible in some versions of REDUCE). 2.4 Variables ←←←←←←←←← Every variable is named by an identifier, and is given a specific type. The type is of no concern to the ordinary user. Most variables are allowed to have the default type, called SCALAR. These can receive, as values, the representation of any ordinary algebraic expression. In the absence of such a value, they stand for themselves. 2.4.1 Reserved Variables ←←←←←←←← ←←←←←←←←← Several variables in REDUCE have particular properties which should not be changed by the user. These variables are as follows: E Intended to represent the base of the natural logarithms. LOG(E), if it occurs in an expression, is automatically replaced by 1. If NUMVAL (q.v.) is on in an appropriate real arithmetic mode, E is replaced by the value of E to the current degree of floating point precision. I Intended to represent the square root of -1. I**2 is replaced by -1, and appropriately for higher powers of I. (This applies only to the symbol I used on the top level, not as a formal parameter in a procedure, a local variable, nor in the context FOR I:= ... .) NIL In REDUCE (algebraic mode only) taken as a synonym for zero. Therefore NIL can not be used as a variable. PI Intended to represent the circular constant. With NUMVAL on in an appropriate real arithmetic mode, it is replaced by the value of PI to the current degree of floating point precision. T Can not be used as a formal parameter or local variable in procedures, since conflict arises with the symbolic mode meaning of T as "true". Use of these reserved variables inappropriately will lead to an error. 2-4 There are also internal variables used by REDUCE that have similar restrictions. These usually have an asterisk in their names, so it is unlikely a casual user would use one. An example of such a variable is K!* used in the asymptotic command package. Certain words are reserved in REDUCE. They may only be used in the manner intended. A list of these is given in the section "Reserved Identifiers". There are, of course, an impossibly large number of such names to keep in mind. The reader may therefore want to make himself a copy of the list, deleting the names he doesn't think he is likely to use by mistake. 2.5 Strings ←←←←←←← Strings are used only in WRITE statements (q.v.). A string consists of any number of characters enclosed in double quotes. e.g. "A String". Lower case characters within a string are not converted to upper case. The string "" represents the empty string. It is not possible to include a double quote itself in a string. 2.6 Comments ←←←←←←←← Text can be included in program listings for the convenience of human readers, in such a way that REDUCE pays no attention to it. There are two ways to do this: 1) Everything from the word COMMENT to the next statement terminator (q.v.), normally ; or $, is ignored. Such comments can be placed anywhere a blank could properly appear. (Note that END and >> are NOT treated as COMMENT delimiters!) 2) Everything from the symbol % to the end of the line on which it appears is ignored. Such comments can be placed as the last part of any line. Statement terminators have no special meaning in such comments. Remember to put a semicolon before the % if the earlier part of the line is intended to be so terminated. Remember also to begin each line of a multi-line "%" comment with a % sign. 2.7 Operators ←←←←←←←←← Operators in REDUCE are specified by name and type. There are two types, infix and prefix. Operators can be purely abstract, just symbols with no properties; they can have values assigned (using := or simple LET declarations) for specific arguments; they can have properties declared for some collection of arguments (using more general LET declarations); or they can be fully defined (usually by a procedure declaration). 2-5 Infix operators occur between their arguments. e.g. A + B - C (spaces optional) X<Y AND Y>Z (spaces required where shown) Spaces can be freely inserted between operators and variables or operators and operators. They are required only where operator names are spelled out with letters (such as the AND in the example) and must be unambiguously separated from another such or from a variable (like Y). Wherever one space can be used, so can any larger number. Prefix operators occur to the left of their arguments, which are written as a list enclosed in parentheses and separated by commas, as with normal mathematical functions. e.g. COS(U) DF(X**2,X) Q(V+W) Unmatched parentheses, incorrect groupings of infix operators and the like, naturally lead to syntax errors. The parentheses can be omitted (replaced by a space following the operator name) if the operator is unary and the argument is a single symbol or begins with a prefix operator name: COS Y means COS(Y) COS (-Y) -- parentheses necessary LOG COS Y means LOG(COS(Y)) LOG COS (A+B) means LOG(COS(A+B)) but COS A*B means (COS A)*B COS -Y is erroneous (treated as a variable "COS" minus the variable Y) A unary prefix operator has a precedence higher than any infix operator. In other words, REDUCE will always interpret COS Y + 3 as (COS Y) + 3 rather than as COS(Y + 3). Infix operators may also be used in a prefix format on input, e.g., +(A,B,C). On output, however, such expressions will always be printed in infix form (i.e., A + B + C for this example). A number of prefix operators are built into the system with predefined properties. Users may also add new operators and define their rules for simplification. The built in operators are described in another section. 2.7.1 Built-In Infix Operators ←←←←←←←← ←←←←← ←←←←←←←←← The following infix operators are built into the system. They are all defined internally as procedures. 2-6 <infix operator>::= WHERE|:=|OR|AND|NOT|MEMBER|MEMQ|=|NEQ|EQ|>=| >|<=|<|+|-|*|/|**|. These operators may be further divided into the following subclasses: <assignment operator> ::= := <logical operator> ::= OR|AND|NOT|MEMBER|MEMQ <relational operator> ::= =|NEQ|EQ|>=|>|<=|< <substitution operator> ::= WHERE <arithmetic operator> ::= +|-|*|/|** <construction operator> ::= . MEMBER, MEMQ, and EQ are not used in the algebraic mode of REDUCE. They are explained in the section on symbolic mode (q.v.). WHERE is described in the section on substitutions. For compatibility with the intermediate language used by REDUCE, each special character infix operator has an alternative alphanumeric identifier associated with it. These identifiers may be used interchangeably with the corresponding special character names on input. This correspondence is as follows: := SETQ (the assignment operator) = EQUAL >= GEQ > GREATERP <= LEQ < LESSP + PLUS - DIFFERENCE (if unary, MINUS) * TIMES / QUOTIENT (if unary, RECIP) ** EXPT (raising to a power) . CONS Note: NEQ is used to mean NOT EQUAL. There is no special symbol provided for it. The above operators are binary, except NOT which is unary and + and * which are n-ary (i.e., taking an arbitrary number of arguments). In addition, - and / may be used as unary operators, e.g., /2 means the same as 1/2. Any other operator is parsed as a binary operator using a left association rule. Thus A/B/C is interpreted as (A/B)/C. There are two exceptions to this rule: := and . are right associative. Example: A:=B:=C is interpreted as A:=(B:=C). Unlike ALGOL and PASCAL, ** is left associative. The operators <, <=, >, >= can only be used for making comparisons between numbers. No meaning is currently assigned to this kind of comparison between general expressions. Parentheses may be used to specify the order of combination. If parentheses are omitted then this order is by the ordering of the precedence list defined by the right-hand side of the BNF definition of 2-7 <infix operator> above, from lowest to highest. In other words, := has the lowest precedence, and . (the dot operator) the highest. 3-1 3. EXPRESSIONS ←←←←←←←←←←← REDUCE expressions may be of several types and consist of sequences of numbers, variables, operators, left and right parentheses and commas. The most common types are as follows: 3.1 Scalar Expressions ←←←←←← ←←←←←←←←←←← Using the arithmetic operations + - * / ** (power) and parentheses, scalar expressions are composed from numbers, ordinary "scalar" variables (identifiers), array names with subscripts, operator or procedure names with arguments, statement expressions. Examples: X X**3 - 2*Y/(2*Z**2 - DF(X,Z)) (P**2 + M**2)**(1/2)*LOG (Y/M) A(5) + B(I,Q) In most systems, the carat symbol (↑) may be used as an alternative to ** for forming powers. The particular system instructions should be consulted to determine if this is not supported. Statement expressions (q.v.), usually in parentheses, can also form part of a scalar expression, as in the example W + (C:=X+Y) + Z . When the algebraic value of an expression is needed, REDUCE determines it, starting with the algebraic values of the parts, roughly as follows: Variables and operator symbols with an argument list have the algebraic values they were last assigned, or if never assigned stand for themselves. However, array elements have the algebraic values they were last assigned, or, if never assigned, are taken to be 0. Procedures are evaluated with the values of their actual parameters. In evaluating expressions, the standard rules of algebra are applied. Unfortunately, this algebraic evaluation of an expression is not as unambiguous as is numerical evaluation. This process is generally referred to as 'simplification' in the sense that the evaluation usually but not always produces a simplified form for the expression. There are many options available to the user for carrying out such simplification. If the user doesn't specify any method, the default method 3-2 is used. The default evaluation of an expression involves expansion of the expression and collection of like terms, ordering of the terms, evaluation of derivatives and other functions and substitution for any expressions which have values assigned or declared (see assignments and LET statements). In many cases, this is all that the user needs. The declarations by which the user can exercise some control over the way in which the evaluation is performed are explained in other sections. For example, if a real (floating point) number is encountered during evaluation, the system will normally convert it into a ratio of two integers, and print a message informing the user of the conversion. If the user wants to use real arithmetic, he can affect this by the command ON FLOAT;. Other modes for coefficient arithmetic are described elsewhere. If an illegal action occurs during evaluation (such as division by zero) or functions are called with the wrong number of arguments, and so on, an appropriate error message is generated. A list of such error messages is given in an appendix. 3.2 Integer Expressions ←←←←←←← ←←←←←←←←←←← These are expressions which, because of the values of the constants and variables in them, evaluate to whole numbers. Examples: 2, 37 * 999, (X + 3)**2 - X**2 - 6*X are obviously integer expressions. J + K - 2 * J**2 is an integer expression when J and K have values that are integers, or if not integers are such that "the variables and fractions cancel out", as in K - 7/3 - J + 2/3 + 2*J**2. 3.3 Boolean Expressions ←←←←←←← ←←←←←←←←←←← A boolean expression returns a truth value. In the algebraic mode of REDUCE, boolean expressions have the syntactical form: <expression> <relational operator> <expression> or <boolean function> (<arguments>) or <boolean expression> <logical operator> <boolean expression>. In addition to the logical and relational operators defined earlier as infix operators, the following boolean functions are also defined: 3-3 EVENP(U) determines if the number U is even or not. FIXP(U) determines if the expression U is integer or not. FREEOF(U,V) determines if the expression U does not contain the kernel (q.v.) V anywhere in its structure. NUMBERP(U) determines if U is a number or not. ORDP(U,V) determines if U is ordered ahead of V by some canonical ordering (based on the expression structure and an internal ordering of identifiers). In the algebraic mode of REDUCE the result, True or False, of such an expression cannot be assigned to a variable. Boolean expressions can only appear directly within IF, FOR, WHILE, and UNTIL statements, as described in other sections. Examples: J<1 X>0 OR X=-2 NUMBERP X FIXP X AND EVENP X NUMBERP X AND X NEQ 0 When two or more boolean expressions are combined with AND, they are evaluated one by one until a False expression is found. The rest are not evaluated. Thus NUMBERP X AND NUMBERP Y AND X>Y does not attempt to make the X>Y comparison unless X and Y are both verified to be numbers. Similarly, evaluation of a sequence of boolean expressions connected by OR stops as soon as a True expression is found. NB: It is not possible to define in algebraic mode a procedure (q.v.) which returns a boolean value; symbolic mode (q.v.) must be used instead. An algebraic mode procedure can however be written to return say 1 or 0 as its value, which can then be tested for in a boolean expression. Finally, if an algebraic (non-boolean) expression is used in a place where a boolean expression is expected, then True is assumed (i.e., no error occurs) as in IF (X := A+B) THEN Y := C+D. 3.4 Equations ←←←←←←←←← Equations are a particular type of expression with the syntax <expression> = <expression>. In addition to their role as boolean expressions, they can also be used as 3-4 arguments to several operators (e.g., SOLVE (q.v.)), and can be returned as values. To facilitate the handling of equations, two selectors, LHS and RHS, which return the left- and right-hand sides of a equation respectively, are provided. For example, LHS(A+B=C) ==> A+B and RHS(A+B=C) ==> C. 3.5 Proper Statements As Expressions ←←←←←← ←←←←←←←←←← ←← ←←←←←←←←←←← Several kinds of proper statements (q.v.) deliver an algebraic or numeric result of some kind, which can in turn be used as an expression or part of an expression. For example, an assignment statement itself has a value, namely the value assigned. So 2 * (X := A+B) is equal to 2*(A+B), as well as having the "side-effect" of assigning the value A+B to X. In context, Y := 2 * (X := A+B); sets X to A+B and Y to 2*(A+B). The sections on the various proper statement types indicate which of these statements are also useful as expressions. 4-1 4. LISTS ←←←←← A list is an object consisting of a sequence of other objects (including lists themselves), separated by commas and surrounded by braces. Examples of lists are: {A,B,C} {1,A-B,C=D} {{A},{{B,C},D},E}. 4.1 Operations On Lists ←←←←←←←←←← ←← ←←←←← Several operators in the system return their results as lists, and a user can create new lists using braces and commas. To facilitate the use of such lists, a number of operators are also available for manipulating them. PART(<list>,n) for example will return the nth element of a list. LENGTH will return the length of a list. Several operators are also defined uniquely for lists. For those familiar with them, these operators in fact mirror the operations defined for LISP lists. These operators are as follows: 4.1.1 First ←←←←← This operator returns the first member of a list. An error occurs if the argument is not a list, or the list is empty. 4.1.2 Second ←←←←←← SECOND returns the second member of a list. An error occurs if the argument is not a list or has no second element. 4.1.3 Third ←←←←← This operator returns the third member of a list. An error occurs if the argument is not a list or has no third element. 4.1.4 Rest ←←←← REST returns its argument with the first element removed. An error occurs if the argument is not a list, or is empty. 4-2 4.1.5 . (Cons) Operator ← ←←←←←← ←←←←←←←← This operator adds ("conses") an expression to the front of a list. For example: A . {B,C} ==> {A,B,C}. 4.1.6 Append ←←←←←← This operator appends its first argument to its second to form a new list. Examples: APPEND({A,B},{C,D}) ==> {A,B,C,D} APPEND({{A,B}},{C,D}) ==> {{A,B},C,D}. 4.1.7 Reverse ←←←←←←← The operator REVERSE returns its argument with the elements in the reverse order. It only applies to the top level list, not any lower level lists that may occur. Examples are: REVERSE({A,B,C}) ==> {C,B,A} REVERSE({{A,B,C},D}) ==> {D,{A,B,C}}. 5-1 5. STATEMENTS ←←←←←←←←←← A statement is any combination of reserved words and expressions, and has the syntax <statement> ::= <expression>|<proper statement> A REDUCE program consists of a series of commands which are statements followed by a terminator: <terminator> ::= ;|$ The division of the program into lines is arbitrary. Several statements can be on one line, or one statement can be freely broken onto several lines. If the program is run interactively, statements ending with ; or $ are not processed until an end-of-line character is encountered. This character can vary from system to system, but is normally the RETURN key on an ASCII terminal. Specific systems may also use additional keys as statement terminators. If a statement is a proper statement, the appropriate action takes place. Depending on the nature of the proper statement some result or response may or may not be printed out, and the response may or may not depend on the terminator used. If a statement is an expression, it is evaluated. If the terminator is a semicolon, the result is printed. If the terminator is a dollar sign, the result is not printed. Because it is not usually possible to know in advance how large an expression will be, no explicit format statements are offered to the user. However, a variety of output declarations are available so that the output can be produced in different forms. These output declarations are explained elsewhere. The following sub-sections describe the proper statements types in REDUCE. 5.1 Assignment Statements ←←←←←←←←←← ←←←←←←←←←← These statements have the syntax <assignment statement> ::= <expression> := <expression> The <expression> on the left side is normally the name of a variable, an operator symbol with its list of arguments filled in, or an array name with the proper number of integer subscript values within the array bounds. For example: A1 := B+C H(L,M) := X-2*Y (where H is an operator) K(3,5) := X-2*Y (where K is a 2-dim. array) 5-2 More general assignments such as A+B := C are also allowed. The effect of these is explained in the section "Substitutions for General Expressions". An assignment statement causes the expression on the right side to be evaluated, and the resulting value is assigned to the variable or array position or operator "position" indicated on the left. If a semicolon is used as the terminator when an assignment is issued as a command (i.e. not as a part of a group statement or procedure or other similar construct), the left-hand side symbol of the assignment statement is printed out, followed by a ":=" , followed by the value of the expression on the right. It is also possible to write a multiple assignment statement: <expression> := <expression> := ... := <expression> := <expression> In this form, each <expression> but the last is set to the value of the last <expression>. If a semicolon is used as a terminator, each expression except the last is printed followed by a ":=" ending with the value of the last expression. 5.1.1 Set Statement ←←← ←←←←←←←←← In some cases, it is desirable to perform an assignment in which BOTH the left- and right-hand sides of an assignment are evaluated. In this case, the SET statement can be used with the syntax: SET(<expression>,<expression>); For example, the statements A := B+C; SET(A-C,X); will set the value of A-C, namely B, to X. 5.2 Group Statements ←←←←← ←←←←←←←←←← The group statement is a construct used where REDUCE expects a single statement, but a series of actions needs to be performed. It is formed by enclosing one or more statements (of any kind) between the symbols << and >>, separated by semicolons or dollar signs -- it doesn't matter which. The statements are executed one after another. Examples will be given in the sections on IF and other types of statements in which the << ... >> construct is useful. If the last statement in the enclosed group has a value, then that is also the value of the group statement. Care must be taken not to have a semicolon or dollar sign after the last grouped statement, if the value of 5-3 the group is relevant: such an extra terminator causes the group to have the value NIL or zero. 5.3 Conditional Statements ←←←←←←←←←←← ←←←←←←←←←← The conditional statement has the following syntax: <conditional statement> ::= IF <boolean expression> THEN <statement> [ELSE <statement>] The boolean expression is evaluated. If the result is True, the first <statement> is executed. If it is False, the second is. In either case the statement after the entire conditional statement is executed next. Examples: IF X=5 THEN A:=B+C ELSE D:=E+F IF X=5 AND NUMBERP Y THEN <<FF:=Q1; A:=B+C>> ELSE <<FF:=Q2; D:=E+F>> Note the use of the group statement. Conditional statements associate to the right; i.e., IF <a> THEN <b> ELSE IF <c> THEN <d> ELSE <e> is equivalent to: IF <a> THEN <b> ELSE (IF <c> THEN <d> ELSE <e>) In addition, the construction IF <a> THEN IF <b> THEN <c> ELSE <d> parses as IF <a> THEN (IF <b> THEN <c> ELSE <d>). If it is the value of the conditional statement which is of primary interest, it is often called a conditional expression instead. Its value is the value of whichever statement was executed. (If the executed statement has no value, the conditional expression has no value or the value 0, depending on how it is used.) Examples: A:=IF X<5 THEN 123 ELSE 456; B:=U + V**(IF NUMBERP Z THEN 10*Z ELSE 1) + W; 5-4 If the value is of no concern, the ELSE clause may be omitted if no action is required in the "False" case. IF X=5 THEN A:=B+C; Note: If by mistake a scalar or numeric expression is used in place of the boolean expression -- for example, a variable is written there -- the True alternative is always followed. 5.4 For Statements ←←← ←←←←←←←←←← The FOR statement is used to define a variety of program loops. Its general syntax is as follows: {STEP <number> UNTIL} {<var> := <number> { } <number> } FOR { { : } } <action> <exprn> { } { EACH <var> IN <list> } where <action> ::= DO|PRODUCT|SUM|COLLECT|JOIN. The assignment form of the FOR statement defines an iteration over the indicated numerical range. If expressions that do not evaluate to numbers are used in the designated places, an error will result. The FOR EACH form of the FOR statement is designed to iterate down a list. Again, an error will occur if a list is not used. The action DO means that <exprn> is simply evaluated and no value kept; the statement returning 0 in this case (or no value at the top level). COLLECT means that the results of evaluating <exprn> each time are linked together to make a list, and JOIN means that the values of <exprn> are themselves lists that are joined to make one list (similar to CONC in LISP). Finally, PRODUCT and SUM form the respective combined value out of the values of <exprn>. In all cases, <exprn> is evaluated algebraically within the scope of the current value of <var>. If <action> is DO, then nothing else happens. In other cases, <action> is a binary operator that causes a result to be built up and returned by FOR. In those cases, the loop is initialized to a default value (zero for SUM, 1 for PRODUCT, and an empty list for the other actions). The test for the end condition is made before any action is taken. If the variable is out of range in the assignment case, or the <list> is empty in the FOR EACH case, <exprn> is not evaluated at all, unlike FORTRAN which executes each DO loop at least once. Examples: 1) If A, B have been declared to be arrays, the following stores 5**2 through 10**2 in A(5) through A(10), and at the same time stores the cubes in the B array: 5-5 FOR I := 5 STEP 1 UNTIL 10 DO <<A(I):=I**2; B(I):=I**3>> 2) As a convenience, the common construction STEP 1 UNTIL may be abbreviated to a colon. Thus, instead of the above we could write: FOR I := 5:10 DO <<A(I):=I**2; B(I):=I**3>> 3) The following sets C to the sum of the squares of 1,3,5,7,9; and D to the expression X * (X+1) * (X+2) * (X+3) * (X+4): C := FOR J:=1 STEP 2 UNTIL 9 SUM J**2; D := FOR K:=0 STEP 1 UNTIL 4 PRODUCT (X+K); 4) The following forms a list of the squares of the elements of the list {A,B,C}: FOR EACH X IN {A,B,C} COLLECT X**2; 5) The following forms a list of the listed squares of the elements of the list {A,B,C} (i.e., {{A**2},{B**2}<{C**2}}): FOR EACH X IN {A,B,C} COLLECT {X**2}; 6) The following also forms a list of the squares of the elements of the list {A,B,C}, since the JOIN operation joins the individual lists into one list: FOR EACH X IN {A,B,C} JOIN {X**2}; The control variable used in the FOR statement is actually a new variable, not related to the variable of the same name outside the FOR statement. In other words, executing a statement FOR I:= ... doesn't change the system's assumption that I**2 = -1. Furthermore, in algebraic mode, the value of the control variable is substituted in <exprn> only if it occurs explicitly in that expression. It will not replace a variable of the same name in the value of that expression. For example: B := A; FOR A := 1:2 DO WRITE B; prints A twice, not 1 followed by 2. 5.5 While...Do ←←←←←←←←←← The FOR ... DO feature allows easy coding of a repeated operation in which the number of repetitions is known in advance. If the criterion for repetition is more complicated, WHILE ... DO can often be used. Its syntax is: 5-6 WHILE <boolean expression> DO <statement> The WHILE ... DO controls the single statement following DO. If several statements are to be repeated, as is almost always the case, they must be grouped using the << ... >> or BEGIN ... END as in the example below. The WHILE condition is tested each time BEFORE the action following the DO is attempted. If the condition is false to begin with, the action is not performed at all. Make sure that what is to be tested has an appropriate value initially. Example: Suppose we want to add up a series of terms, generated one by one, until we reach a term which is less than 1/1000 in value. For our simple example, let us suppose the first term equals 1 and each term is obtained from the one before by taking one third of it and adding one third its square. We would write: EX:=0; TERM:=1; WHILE NUM(TERM - 1/1000) >= 0 DO <<EX := EX+TERM; TERM:=(TERM + TERM**2)/3>>; EX; As long as TERM is greater than or equal ( >= ) to 1/1000 it will be added to EX and the next TERM calculated. As soon as TERM becomes less than 1/1000 the WHILE test fails and the TERM will not be added. 5.6 Repeat...Until ←←←←←←←←←←←←←← REPEAT ... UNTIL is very similar in purpose to WHILE ... DO. Its syntax is: REPEAT <statement> UNTIL <boolean expression> (PASCAL users note: Only a single statement -- usually a group statement -- is allowed between the REPEAT and the UNTIL.) There are two essential differences: 1) The test is performed after the controlled statement (or group of statements) is executed, so the controlled statement is always executed at least once. 2) The test is a test for when to stop rather than when to continue, so its "polarity" is the opposite of that in WHILE ... DO. Example: We rewrite the example from the WHILE ... DO section: 5-7 EX:=0; TERM:=1; REPEAT <<EX := EX+TERM; TERM := (TERM + TERM**2)/3>> UNTIL NUM(TERM - 1/1000) < 0; EX; The answer here will not be exactly the same as before, because the first term which is less than 1/1000 WILL be added to EX this time. 5.7 Compound Statements ←←←←←←←← ←←←←←←←←←← Often the desired process can best (or only) be described as a series of steps to be carried out one after the other. In many cases, this can be achieved by use of the group statement (q.v.). However, each step often provides some intermediate result, until at the end we have the final result wanted. Alternatively, iterations on the steps are needed that are not possible with constructs such as WHILE or REPEAT statements (q.v.). In such cases the steps of the process must be enclosed between the words BEGIN and END forming what is technically called a block or compound statement. Such a compound statement can in fact be used wherever a group statement appears. The converse is not true: BEGIN ... END can be used in ways that << ... >> can not. If intermediate results must be formed, local variables must be provided in which to store them. "Local" means that their values are deleted as soon as the block's operations are complete, and there is no conflict with variables outside the block that happen to have the same name. Local variables are created by a SCALAR declaration immediately after the BEGIN: SCALAR A,B,C,Z; If more convenient, several SCALAR declarations can be given one after another: SCALAR A,B,C; SCALAR Z; In place of SCALAR one can also use the declarations INTEGER or REAL. In the present version of REDUCE variables declared INTEGER are expected to have only integer values, and are initialized to 0. REAL variables on the other hand are currently treated as algebraic mode SCALARs. CAUTION: INTEGER, REAL and SCALAR declarations can only be given immediately after a BEGIN. An error will result if they are used after other statements in a block (including ARRAY and OPERATOR declarations, which are global in scope), or outside the top-most block (e.g., at the top level). All variables declared SCALAR are automatically initialized to zero in algebraic mode (NIL in symbolic mode). Any symbols not declared as local variables in a block refer to the variables of the same name in the current calling environment. In particular, if they are not so declared at a higher level (e.g., in a surrounding block or as parameters in a calling procedure, their values can 5-8 be permanently changed. Following the SCALAR declaration(s), if any, write the statements to be executed, one after the other, separated by delimiters (e.g., ; or $) (it doesn't matter which). The last statement in the body, just before END, need not have a terminator (since the BEGIN ... END are in a sense brackets confining the block statements). The last statement must also be the command RETURN followed by the variable or expression whose value is to be the value returned by the procedure. If the RETURN is omitted (or nothing is written after the word RETURN) the value returned by the procedure will be zero (or NIL in symbolic mode). Remember to put a terminator after the END. Example: Given a previously assigned integer value for N, the following block will compute the Legendre polynomial of degree N in the variable X: BEGIN SCALAR SEED,DERIV,TOP,FACT; SEED:=1/(Y**2 - 2*X*Y +1)**(1/2); DERIV:=DF(SEED,Y,N); TOP:=SUB(Y=0,DERIV); FACT:=FOR I:=1:N PRODUCT I; RETURN TOP/FACT END; 5.7.1 Compound Statements With Go To ←←←←←←←← ←←←←←←←←←← ←←←← ←← ←← It is possible to have more complicated structures inside the BEGIN ... END brackets than indicated in the previous example. That the individual lines of the program need not be assignment statements, but could be almost any other kind of statement or command, needs no explanation. For example, conditional statements, and WHILE and REPEAT constructions, have an obvious role in defining more intricate blocks. If these structured constructs don't suffice, it is possible to use labels and GO TOs within a compound statement, and also to use RETURN in places within the block other than just before the END. The following subsections discuss these matters in detail. For many readers the following example, presenting one possible definition of a process to calculate the factorial of N for preassigned N (there are far simpler ones!) will suffice: Example: BEGIN SCALAR M; M:=1; L: IF N=0 THEN RETURN M; M:=M*N; N:=N-1; 5-9 GO TO L END; 5.7.2 Labels And Go To Statements ←←←←←← ←←← ←← ←← ←←←←←←←←←← Within a BEGIN ... END compound statement it is possible to label statements, and transfer to them out of sequence using GO TO statements. Only statements on the top level inside compound statements can be labeled, not ones inside subsidiary constructions like << ... >>, IF ... THEN ..., WHILE ... DO ... , etc. Labels and GO TO statements have the syntax: <go to statement> ::= GO TO <label> | GOTO <label> <label> ::= <identifier> <labeled statement> ::= <label>:<statement> Note that statement names cannot be used as labels. While GO TO is an unconditional transfer, it is frequently used in conditional statements such as IF X>5 THEN GO TO ABCD; giving the effect of a conditional transfer. 5.7.3 Return Statements ←←←←←← ←←←←←←←←←← The value corresponding to a BEGIN ... END compound statement, such as a procedure body, is normally 0 (NIL in symbolic mode). By executing a RETURN statement in the compound statement a different value can be returned. After a RETURN statement is executed no further statements within the compound statement are. Examples: RETURN X+Y; RETURN M; RETURN; Note that parentheses are not required around the X+Y, although they are permitted. The last example is equivalent to RETURN 0; . Since RETURN actually moves up only one block level, in a sense the casual user is not expected to understand, we tabulate some cautions concerning its use. RETURN can be used on the top level inside the compound statement, i.e. as one of the statements bracketed together by the BEGIN ... END. RETURN can be used within a top level << ... >> construction within the compound statement. 5-10 RETURN can be used within an IF ... THEN ... ELSE ... on the top level within the compound statement. NOTE: At present, there is no construct provided to permit early termination of a FOR, WHILE, or REPEAT statement. In particular, the use of RETURN in such cases results in a syntax error. For example, BEGIN SCALAR Y; Y := FOR I:=0:99 DO IF A(I)=X THEN RETURN B(I); ... will lead to an error. 6-1 6. COMMANDS AND DECLARATIONS ←←←←←←←← ←←← ←←←←←←←←←←←← A command is an order to the system to do something. Some commands cause visible results (such as calling for input or output); others, usually called declarations, set options, define properties of variables, or define procedures. Commands are formally defined as a statement followed by a terminator <command> ::= <statement> <terminator> <terminator> ::= ;|$ Some REDUCE commands and declarations are described in the following sub-sections. 6.1 Array Declarations ←←←←← ←←←←←←←←←←←← Array declarations in REDUCE are similar to FORTRAN dimension statements. e.g. ARRAY A(10),B(2,3,4); Array indices each range from 0 to the value declared. An element of an array is referred to in standard FORTRAN notation, e.g. A(2). We can also use an expression for defining an array bound, provided the value of the expression is a positive integer. For example, if X has the value 10 and Y the value 7 then ARRAY C(5*X+Y) is the same as ARRAY C(57). If an array is referenced by an index outside its range, an error occurs. If the array is to be one-dimensional, and the bound a number or a variable (not a more general expression) the parentheses may be omitted: ARRAY A 10, C 57; The operator LENGTH (q.v.) applied to an array name returns a list of its dimensions. All array elements are initialized to 0 at declaration time. In other words, an array element has an "instant evaluation" property and cannot stand for itself. If this is required, then an operator (q.v.) should be used instead. Array declarations can appear anywhere in a program. Once a symbol is declared to name an array, it can not also be used as a variable, or to name an operator or a procedure. It can however be re-declared to be an array, and its size may be changed at that time. An array name can also continue to be used as a parameter in a procedure, or a local variable in a compound statement, although this use is not recommended, since it can lead to user confusion over the type of the variable. 6-2 Arrays once declared are global in scope, and so can then be referenced anywhere in the program. In other words, unlike arrays in most other languages, a declaration within a block (or a procedure) does not limit the scope of the array to that block, nor does the array go away on exiting the block (use CLEAR instead for this purpose). 6.2 Mode Handling Declarations ←←←← ←←←←←←←← ←←←←←←←←←←←← The ON and OFF declarations are available to the user for controlling various system options. Each option is represented by a "switch" name. ON and OFF take a list of switch names as argument and turn them on and off respectively. e.g. ON TIME; causes the system to print a message after each command giving the elapsed cpu time since the last command, or since TIME was last turned off, or the session began. Another useful switch with interactive use is DEMO, which causes the system to pause after each command in a file until a Return is typed on the terminal. This enables a user to set up a demonstration file and step through it command by command. As with most declarations, arguments to ON and OFF may be strung together separated by commas. For example, OFF TIME,DEMO; will turn off both the time messages and the demonstration switch. We note here that while most ON and OFF commands are obeyed almost instantaneously, some trigger time-consuming actions such as reading in necessary modules from secondary storage. A diagnostic message is printed if ON or OFF are used with a switch that is not known to the system. For example, if you misspell "demo" and type ON DEMQ; you will get the message ***** DEMQ not defined as switch. 6.3 End Identifier ←←← ←←←←←←←←←← The identifier END has three separate uses. 1) Its use in a BEGIN ... END bracket has been discussed in connection with compound statements (q.v.). 2) Files to be read using IN should end with an extra END; command. The reason for this is explained in the section on the IN command (q.v.). This 6-3 use of END does not allow an immediately preceding END (such as the END of a procedure definition), so we advise using ;END; there. 3) A command END; entered at the top level transfers control to the LISP system which is the host of the REDUCE system. All files opened by IN or OUT statements are closed in the process. END; does not stop REDUCE. Those familiar with LISP can experiment with typing identifiers and (<function name><argument list>) lists to see the value returned by LISP. (No terminators, other than RETURN, should be used.) The data structures created during the REDUCE run are accessible. You remain in this LISP mode until you explicitly re-enter REDUCE by saying (BEGIN) at the LISP top level. In most systems, a LISP error also returns you to REDUCE (exceptions are noted in the operating instructions for your particular REDUCE implementation). In either case, you will return to REDUCE in the same mode, algebraic or symbolic, that you were in before the END;. If you are in LISP mode by mistake -- which is usually the case, the result of typing more ENDs than BEGINs -- type (BEGIN) in parentheses and hit RETURN. 6.4 Bye Command ←←← ←←←←←←← The command BYE; stops the execution of REDUCE, closes all open output files, and returns you to the computer system monitor program. Where the implementation permits it, your REDUCE session is destroyed. If you wish to return later to that session, use QUIT; instead. 6.5 Quit Command ←←←← ←←←←←←← The command QUIT; stops the execution of REDUCE and returns you to the computer system monitor program. Where the implementation permits it, your REDUCE session is retained so that you can use it again later. If you do not wish to reenter the REDUCE session, use BYE; instead. 6.6 Showtime Command ←←←←←←←← ←←←←←←← SHOWTIME; prints the elapsed time since the last call of this command or, on its first call, since the current REDUCE session began. The time is normally given in milliseconds and gives the time as measured by a system clock. The operations covered by this measure are system dependent. 6.7 Define Command ←←←←←← ←←←←←←← The command DEFINE allows a user to supply a new name for any identifier or replace it by any well-formed expression. Its argument is a list of expressions of the form <identifier> = <number>|<identifier>|<operator>| <reserved word>|<expression> 6-4 Example: DEFINE BE==,X=Y+Z; means that 'BE' will be interpreted as an equal sign, and 'X' as the expression Y+Z from then on. This renaming is done at parse time, and therefore takes precedence over any other replacement declared for the same identifier. It stays in effect until the end of the REDUCE run. The identifiers ALGEBRAIC and SYMBOLIC have properties which prevent DEFINE from being used on them. To define ALG to be a synonym for ALGEBRAIC, the more complicated construction PUT('ALG,'NEWNAM,'ALGEBRAIC); must be used. 7-1 7. BUILT-IN PREFIX OPERATORS ←←←←←←←← ←←←←←← ←←←←←←←←← In the following subsections are descriptions of the most useful prefix operators built into REDUCE that are not defined in other sections (such as substitution operators). Some are fully defined internally as procedures; others are more nearly abstract operators, with only some of their properties known to the system. In many cases, an operator is described by a prototypical header line as follows. Each formal parameter is given a name and followed by its allowed type. The names of classes referred to in the definition are printed in lower case, and parameter names in upper case. If a parameter type is not commonly used, it may be a specific set enclosed in brackets {...}. Operators which accept formal parameter lists of arbitrary length have the parameter and type class enclosed in square brackets indicating that zero or more occurrences of that argument are permitted. Optional parameters and their type classes are enclosed in angle brackets. 7.1 Numerical Functions ←←←←←←←←← ←←←←←←←←← REDUCE knows that the following represent functions that can take an arbitrary number of numerical expressions as their arguments: MAX MIN. For example, MAX(2,-3,4,5) ==> 5 MIN(2,-2) ==> -2. MAX or MIN of an empty list returns 0. In addition, the function ABS will return the absolute value of its single numerical argument. An error occurs if a non-numeric argument is supplied to any of these functions. 7.2 Mathematical Functions ←←←←←←←←←←←← ←←←←←←←←← REDUCE knows that the following represent mathematical functions that can take arbitrary scalar expressions as their single argument: SIN COS TAN COT ASIN ACOS ATAN SQRT EXP LOG SINH COSH TANH ASINH ACOSH ATANH ERF DILOG EXPINT. It only knows the most elementary identities and properties of these functions, however (except in ON NUMVAL mode (q.v.)). For example: 7-2 COS (-X) = COS (X) SIN (-X) = - SIN (X) COS (n*PI) = (-1)**n SIN (n*PI) = 0 LOG (E) = 1 E**(I*PI/2) = I LOG (1) = 0 E**(I*PI) = -1 LOG (E**X) = X E**(3*I*PI/2) = -I With the default system switch settings, the argument of a square root is first simplified, and any divisors of the expression that are perfect squares taken outside the square root argument. The remaining expression is left under the square root. However, if the switch REDUCED is on, multiplicative factors in the argument of the square root are also separated, becoming individual square roots. Thus with REDUCED off, the expression SQRT(-8*A**2*B) would become 2*A*SQRT(-2*B) , whereas with REDUCED on, it would become 2*A*I*SQRT(2)*SQRT(B) . The switch REDUCED also applies to other rational powers in addition to square roots. Note that such simplifications can cause trouble if A is eventually given a value which is a negative number. If it is important that the positive property of the square root always be preserved, the switch PRECISE can be set on. This causes any non-numerical factors taken out of surds to be represented by their absolute value form. With both REDUCED and PRECISE on then, the above example would become 2*I*ABS(A)*SQRT(2)*SQRT(B) . The square root function can be input using the name SQRT, or the power operation **(1/2). On output, unsimplified square roots are represented by the operator SQRT rather than a fractional power. The derivatives of these functions are also known to the system. The user can add further rules for the reduction of expressions involving these operators by using the LET command (q.v.). The statement that REDUCE knows very little about these functions applies only in the mathematically exact OFF NUMVAL mode. If NUMVAL is set on, and the polynomial coefficient arithmetic has been set to an appropriate real mode, any of the functions SIN COS TAN ASIN ACOS ATAN SQRT EXP LOG which is given a numeric argument has its value calculated to the current 7-3 degree of floating point precision. In addition, real (non-integer valued) powers of numbers will also be evaluated. In all systems, BIGFLOAT mode will cause such evaluations. A number of systems (e.g., those based on Portable Standard LISP) will also permit such evaluations in single precision floating point mode (activated by ON FLOAT). 7.3 Df Operator ←← ←←←←←←←← The operator DF is used to represent partial differentiation with respect to one or more variables. It is used with the syntax: DF(EXPRN:algebraic,[VAR:kernel<,NUM:integer>]):algebraic. The first argument is the expression to be differentiated. The remaining arguments specify the differentiation variables and the number of times they are applied. The number NUM may be omitted if it is 1. e.g. DF(Y,X) = dY/dX 2 2 DF(Y,X,2) = d Y/dX 5 2 2 DF(Y,X1,2,X2,X3,2)= d Y/dX1 dX2 dX3 The evaluation of DF(Y,X) proceeds as follows: first, the values of Y and X are found. Let us assume that X has no assigned value, so its value is X. Each term or other part of the value of Y which contains the variable X is differentiated by the standard rules. If Z is another variable, not X itself, then its derivative with respect to X is taken to be 0, unless Z has previously been declared to DEPEND (q.v.) on X, in which case the derivative is reported as the symbol DF(Z,X). 7.3.1 Adding Differentiation Rules ←←←←←← ←←←←←←←←←←←←←←← ←←←←← The LET statement (q.v.) can be used for the introduction of rules for differentiation of user-defined operators. Its general form is FOR ALL <var1>,...,<varn> LET DF(<operator><varlist>,<vari>)=<expression> where <varlist> ::= (<var1>,...,<varn>), and <var1>,...,<varn> are the dummy variable arguments of <operator>. An analogous form applies to infix operators. Examples: FOR ALL X LET DF(TAN X,X)= SEC(X)**2; (This is how the tan differentiation rule appears in the REDUCE source.) 7-4 FOR ALL X,Y LET DF(F(X,Y),X)=2*F(X,Y), DF(F(X,Y),Y)=X*F(X,Y); Notice that all dummy arguments of the relevant operator must be declared arbitrary by the FOR ALL command, and that rules may be supplied for operators with any number of arguments. If no differentiation rule appears for any argument in an operator, the differentiation routines will return as result an expression in terms of DF. For example, if the rule for the differentiation with respect to the second argument of F is not supplied, the evaluation of DF(F(X,Z),Z) would leave this expression unchanged. (No DEPEND declaration (q.v.) is needed here, since F(X,Z) obviously "depends on" Z. Once such a rule has been defined for a given operator, any future differentiation rules for that operator must be defined with the same number of arguments for that operator, otherwise and error message "Incompatible DF rule argument length for <operator>" is printed. 7.4 Int Operator ←←← ←←←←←←←← INT is an operator in REDUCE for analytic integration using a combination of the Risch-Norman algorithm and pattern matching. It is used with the syntax: INT(EXPRN:algebraic,VAR:kernel):algebraic. It will return correctly the indefinite integral for expressions comprising polynomials, log functions, exponential functions and tan and atan. The arbitrary constant is not represented. If the integral cannot be done in closed terms, it returns a formal integral for the answer in one of two ways: 1) It returns the input, INT( ... , ... ) unchanged. 2) It returns an expression involving INT's of some other functions (sometimes more complicated than the original one, unfortunately). Rational functions can be integrated when the denominator is factorizable by the program. In addition it will attempt to integrate expressions involving error functions, dilogarithms and other trigonometric expressions. In these cases it might not always succeed in finding the solution, even if one exists. Examples: INT(LOG(X),X) ==> X*(LOG(X) - 1), INT(E**X,X) ==> E**X. The program checks that the variable supplied is a variable and gives an error if it is not. 7-5 7.4.1 Options ←←←←←←← The switch TRINT when on will trace the operation of the algorithm. It produces a great deal of output in a somewhat illegible form, and is not of much interest to the general user. It is normally off. If the switch FAILHARD is on the algorithm will terminate with an error if the integral cannot be done in closed terms, rather than return a formal integration form. FAILHARD is normally off. The switch NOLNR suppresses the use of the linear properties of integration in cases when the integral cannot be found in closed terms. 7.4.2 Advanced Use ←←←←←←←← ←←← If a function appears in the integrand which is not one of the functions EXP, ERF, TAN, ATAN, LOG, DILOG then the algorithm will make an attempt to integrate the argument if it can, differentiate it and reach a known function. However the answer cannot be guaranteed in this case. If a function is known to be algebraically independent of this set it can be flagged transcendental by FLAG('(TRILOG),'TRANSCENDENTAL); in which case this function will be added to the permitted field descriptors for an genuine decision procedure. If this is done the user is responsible for the mathematical correctness of his actions. The standard version does not deal with algebraic extensions. Thus integration of expressions involving square roots and other like things can lead to trouble. A contributed package that supports integration of functions involving square roots is available, however. This is distributed with most versions of REDUCE. 7.4.3 References ←←←←←←←←←← A. C. Norman & P. M. A. Moore, "Implementing the New Risch Algorithm", Proc. 4th International Symposium on Advanced Comp. Methods in Theor. Phys., CNRS, Marseilles, 1977. S. J. Harrington, "A New Symbolic Integration System in Reduce", Comp. Journ. 22 (1979) 2. A. C. Norman & J. H. Davenport, "Symbolic Integration - The Dust Settles?", Proc. EUROSAM 79, Lecture Notes in Computer Science 72, Springer-Verlag, Berlin Heidelberg New York (1979) 398-407. Comments and complaints should be sent to; Professor John P. Fitch, or Dr. Arthur C. Norman Dept of Computing Studies, Computer Laboratory, 7-6 Bath University, University of Cambridge Bath, BA2 6AY Cambridge, CB2 3QG, England England. 7.5 Length Operator ←←←←←← ←←←←←←←← LENGTH is a generic operator for finding the length of various objects in the system. The meaning depends on the type of the object. In particular, the length of an algebraic expression is the number of additive top-level terms its expanded representation. Examples: LENGTH (A+B) ==> 2 LENGTH (2) ==> 1. Other objects that support a length operator include arrays, lists and matrices. The explicit meaning in these cases is included in the description of these objects. 7.6 Mkid Operator ←←←← ←←←←←←←← In many applications, it is useful to create a set of identifiers for naming objects in a consistent manner. In most cases, it is sufficient to create such names from two components. The operator MKID is provided for this purpose. Its syntax is: MKID(U:id,V:id|non-negative integer):id E.g., mkid(A,3) ==> A3. mkid(APPLE,S) ==> APPLES mkid(A+B,2) gives an error. 7.7 Solve Operator ←←←←← ←←←←←←←← SOLVE is an operator for solving one or more simultaneous algebraic equations. It is used with the syntax: SOLVE(EXPRN:algebraic[,VAR:kernel|,VARLIST:list of kernels]):integer. EXPRN is of the form <expression> or {<expression1>,<expression2>, ...}. Each expression is an algebraic equation, or is the difference of the two sides of the equation. The second argument is either a kernel or a list of kernels representing the unknowns in the system. This argument may be omitted if the number of distinct top-level kernels equals the number of unknowns, in which case these kernels are presumed to be the unknowns. Simultaneous equations must currently be linear in the kernels in terms of which the solutions are sought. 7-7 For example: SOLVE(LOG(SIN(X+3))**5 = 8,X); or SOLVE(A*LOG(SIN(X+3))**5 - B, SIN(X+3)); or SOLVE({A*X+Y=3,Y=-2},{X,Y}); 7.7.1 Options ←←←←←←← If SOLVESINGULAR is on, degenerate systems such as x+y=0,2x+2y=0 will be solved by introducing appropriate arbitrary constants. SOLVE returns a list of solutions. If there is one unknown, each solution is an equation for the unknown. If a complete solution was found, the unknown will appear by itself on the left-hand side of the equation. On the other hand, if the solve package could not find a solution, the "solution" will be an equation for the unknown. If there are several unknowns, each solution will be a list of equations for the unknowns. For example, SOLVE(X**2=1,X); ==> {X=-1,X=1} SOLVE(X**7-X**6+X**2=1,X) ==> {X**6+X+1=0,X=1} SOLVE({X+3Y=7,Y-X=1},{X,Y}) ==> {{X=1,Y=2}}. Solution multiplicities are stored in the global variable MULTIPLICITIES!* rather than the solution list. The value of this variable is a list of the multiplicities of the solutions for the last call of SOLVE. For example, SOLVE(X**2=2X-1,X); MULTIPLICITIES!*; gives the results {X=1} {2}. For one equation, SOLVE recursively uses square-free factorization together with the known inverses of LOG, SIN, COS, **, ACOS, ASIN, and linear, quadratic, cubic, quartic, or binomial factors. For simultaneous linear equations, the built-in matrix equation solvers are used, SOLVE merely providing a convenient form of input for small or sparse systems. The consistent singular equation 0=0 or equations involving functions with multiple inverses may introduce unique new indeterminant kernels ARBCOMPLEX(j), ARBREAL(j), or ARBINT(j), (j=1,2,...), representing arbitrary complex, real or integer numbers respectively. To automatically select the principal branches, do OFF ALLBRANCH. To suppress solutions of consistent singular equations do OFF SOLVESINGULAR. To incorporate additional inverse functions do, for example: 7-8 PUT('SINH,'INVERSE,'ASINH); PUT('ASINH,'INVERSE,'SINH); together with any desired simplification rules such as FOR ALL X LET SINH(ASINH(X))=X, ASINH(SINH(X))=X; For completeness, functions with non-unique inverses should be treated as **, SIN, and COS are in the SOLVE module source. Arguments of ASIN and ACOS are not checked to insure that the absolute value of the real part does not exceed 1; and arguments of LOG are not checked to insure that the absolute value of the imaginary part does not exceed PI; but checks (perhaps involving user response for non-numerical arguments) could be introduced using LET statements for these operators. Users should also note that even though the solve package can find exact solutions for cubics and quartics, the results in most cases are so intractable that it is better to look for another method of solution. 7.8 Linear Operators ←←←←←← ←←←←←←←←← An operator can be declared to be linear in its first argument over powers of its second argument. If an operator F is so declared, F of any sum is broken up into sums of F's, and any factors which are not powers of the variable are taken outside. This means that F must have (at least) two arguments. In addition, the second argument must be an identifier (or more generally a kernel), not an expression. Example: If F were declared linear, then F(A*X**5 + B*X + C,X) ==> A*F(X**5,X) + B*F(X,X) + C*F(1,X). More precisely, not only will the variable and its powers remain within the scope of the F operator, but so will any variable and its powers which had been declared to DEPEND (q.v.) on the prescribed variable; and so would any expression which contains that variable or a dependent variable on any level : e.g. COS(SIN(X)). To declare operators F and G to be linear operators, use: LINEAR F,G; The analysis is done of the first argument with respect to the second; any other arguments are ignored. It uses the following rules of evaluation: F(0) => 0 F(-Y,X) => -F(Y,X) F(Y+Z,X) => F(Y,X)+F(Z,X) 7-9 F(Y*Z,X) => Z*F(Y,X) if Z does not depend on X. F(Y/Z,X) => F(Y,X)/Z if Z does not depend on X. To summarize, Y "depends" on the indeterminate X in the above if either of the following hold: 1) Y is an expression which contains X at any level as a variable, e.g.: COS(SIN(X)) 2) Any variable in the expression Y has been declared dependent on X by use of the declaration DEPEND (q.v.). The use of such linear operators can be seen in the paper Fox, J.A. and A. C. Hearn, "Analytic Computation of Some Integrals in Fourth Order Quantum Electrodynamics" Journ. Comp. Phys. 14 (1974) 301-317, which contains a complete listing of a program for definite integration of some expressions which arise in fourth order quantum electrodynamics. 7.9 Non-Commuting Operators ←←←←←←←←←←←←← ←←←←←←←←← An operator can be declared to be non-commutative under multiplication by the declaration NONCOM. Example: If the declaration NONCOM U,V; is given, then the expressions U(X)*U(Y)-U(Y)*U(X) and U(X)*V(Y)-V(Y)*U(X) will remain unchanged on simplification, and in particular will not simplify to zero. Note that it is the operator (U and V in the above example) and not the variable that has the non-commutative property. The LET statement may be used to introduce rules of evaluation for such operators. In particular, the boolean operator ORDP is useful for introducing an ordering on such expressions. Example: The rule FOR ALL X,Y SUCH THAT X NEQ Y AND ORDP(X,Y) LET U(X)*U(Y)= U(Y)*U(X)+COMM(X,Y); would introduce the commutator of U(X) and U(Y) for all X and Y. Note that since ORDP(X,X) is True, the equality check is necessary in the degenerate case to avoid a circular loop in the rule. 7.10 Symmetric And Antisymmetric Operators ←←←←←←←←← ←←← ←←←←←←←←←←←←← ←←←←←←←←← An operator can be declared to be symmetric with respect to its arguments by the declaration SYMMETRIC. For example SYMMETRIC U,V; means that any expression involving the top level operators U or V will 7-10 have its arguments reordered to conform to the internal order used by REDUCE. The user can change this order for kernels by the command KORDER (q.v.). For example, U(X,V(1,2)) would become U(V(2,1),X), since numbers are ordered in decreasing order, and expressions are ordered in decreasing order of complexity. An operator can similarly be declared antisymmetric by the declaration ANTISYMMETRIC. For example, ANTISYMMETRIC L,M; means that any expression involving the top level operators L or M will have its arguments reordered to conform to the internal order of the system, and the sign of the expression changed if there are an odd number of argument interchanges necessary to bring about the new order. For example, L(X,M(1,2)) would become -L(-M(2,1),X) since one interchange occurs with each operator. An expression like L(X,X) would also be replaced by 0. 7.11 Declaring New Prefix Operators ←←←←←←←←← ←←← ←←←←←← ←←←←←←←←← The user may add new prefix operators to the system by the using the declaration OPERATOR. e.g. OPERATOR H,G1,ARCTAN; adds the prefix operators H, G1 and ARCTAN to the system. This allows symbols like H(W), H(X,Y,Z), G1(P+Q), ARCTAN(U/V) to be used in expressions, but no meaning or properties of the operator are implied. The same operator symbol can be used equally well as a 1-, 2-, 3-, etc.-place operator. To give a meaning to an operator symbol, or express some of its properties, LET statements can be used, or the operator can be given a definition as a procedure (q.v.). If the user forgets to declare an identifier as an operator, the system will prompt the user to do so in interactive mode, or do it automatically in non-interactive mode. A diagnostic message will also be printed if an identifier is declared operator more than once. Operators once declared are global in scope, and so can then be referenced anywhere in the program. In other words, a declaration within a block (or a procedure) does not limit the scope of the operator to that block, nor does the operator go away on exiting the block (use CLEAR instead for this purpose). 7-11 7.12 Declaring New Infix Operators ←←←←←←←←← ←←← ←←←←← ←←←←←←←←← Users can add new infix operators by using the declarations INFIX and PRECEDENCE. e.g. INFIX MM; PRECEDENCE MM,-; The declaration INFIX MM would allow one to use the symbol MM as an infix operator: A MM B instead of MM(A,B). The declaration PRECEDENCE MM,- says that MM should be inserted into the infix operator precedence list (q.v.) just AFTER the - operator. This gives it higher precedence than - and lower precedence than * . Thus A - B MM C - D means A - (B MM C) - D, while A * B MM C * D means (A * B) MM (C * D). Both infix and prefix operators have no transformation properties unless LET statements or procedure declarations are used to assign a meaning. We should note here that infix operators so defined are always binary: A MM B MM C means (A MM B) MM C. 7.13 Creating And Removing Variable Dependency ←←←←←←←← ←←← ←←←←←←←← ←←←←←←←← ←←←←←←←←←← There are several facilities in REDUCE, such as the differentiation operator and the linear operator facility, which can utilize knowledge of the dependency between various variables, or kernels (q.v.). Such dependency may be expressed by the command DEPEND. DEPEND takes an arbitrary number of arguments and sets up a dependency of the first argument on the remaining arguments. e.g.: DEPEND X, Y, Z; says that X is dependent on both Y and Z. DEPEND Z,COS(X),Y; says that Z is dependent on COS(X) and Y. Dependencies introduced by DEPEND can be removed by the command NODEPEND. The arguments of this are the same as for DEPEND. e.g., given the above dependencies, NODEPEND Z,COS(X); 7-12 says that Z is no longer dependent on COS(X), although it remains dependent on Y. 8-1 8. DISPLAY AND STRUCTURING OF EXPRESSIONS ←←←←←←← ←←← ←←←←←←←←←←← ←← ←←←←←←←←←←← In this section, we consider a variety of commands and operators which permit the user to obtain various parts of algebraic expressions and also display their structure in a variety of forms. Also presented are some additional concepts in the REDUCE design that help the user gain a better understanding of the structure of the system. 8.1 Kernels ←←←←←←← REDUCE is designed so that each operator in the system has an evaluation (or simplification) function associated with it which transforms the expression into an internal canonical form. This form, which bears little resemblance to the original expression, is described in detail in Hearn, A. C., "REDUCE 2, A System and Language for Algebraic Manipulation," Proc. of Second Symposium on Symbolic and Algebraic Manipulation, ACM, New York (1971) 128-133. The evaluation function may transform its arguments in one of two alternative ways. First, it may convert the expression into other operators in the system, leaving no functions of the original operator for further manipulation. This is in a sense true of the evaluation functions associated with the operators +, * and / , for example, because the canonical form does not include these operators explicitly. It is also true of an operator such as the determinant operator DET (q.v.) because the relevant evaluation function calculates the appropriate determinant, and the operator DET no longer appears. On the other hand, the evaluation process may leave some residual functions of the relevant operator. For example, with the operator COS, a residual expression like COS(X) may remain after evaluation unless a rule for the reduction of cosines into exponentials, for example, were introduced. These residual functions of an operator are termed kernels and are stored uniquely like variables. Subsequently, the kernel is carried through the calculation as a variable unless transformations are introduced for the operator at a later stage. In those cases where the evaluation process leaves an operator expression with non-trivial arguments, the form of the argument can vary depending on the state of the system at the point of evaluation. Such arguments are normally produced in expanded form with no terms factored or grouped in any way. For example, the expression COS(2*X+2*Y) will normally be returned in the same form. If the argument 2*X+2*Y were evaluated at the top level, however, it would be printed as 2*(X+Y). If it is desirable to have the arguments themselves in a similar form, the switch INTSTR (for "internal structure"), if on, will cause this to happen. In cases where the arguments of the kernel operators may be reordered, the system puts them in a canonical order, based on an internal intrinsic ordering of the variables. However, some commands allow arguments in the form of kernels, and the user has no way of telling what internal order the system will assign to these arguments. To resolve this difficulty, we introduce the notion of a kernel form as an expression which transforms to 8-2 a kernel on evaluation. Examples of kernel forms are: A COS (X*Y) LOG (SIN (X)) whereas A*B (A+B)**4 are not. We see that kernel forms can usually be used as generalized variables, and most algebraic properties associated with variables may also be associated with kernels. 8.2 The Expression Workspace ←←← ←←←←←←←←←← ←←←←←←←←← Several mechanisms are available for saving and retrieving previously evaluated expressions. The simplest of these refers to the last algebraic expression simplified. When an assignment of an algebraic expression is made, or an expression is evaluated at the top level, (i.e., not inside a compound statement or procedure) the results of the evaluation are automatically saved in a variable WS which we shall refer to as the workspace. (More precisely, the expression is assigned to the variable WS which is then available for further manipulation.) Example: If we evaluate the expression (X+Y)**2 at the top level and next wish to differentiate it with respect to Y, we can simply say DF(WS,Y); to get the desired answer. If the user wishes to assign the workspace to a variable or expression for later use, the SAVEAS statement can be used. It has the syntax SAVEAS <expression> For example, after the differentiation in the last example, the workspace holds the expression 2*X+2*Y. If we wish to assign this to the variable Z we can now say SAVEAS Z; If the user wishes to save the expression in a form that allows him to use some of its variables as arbitrary parameters, the FOR ALL (q.v.) command 8-3 can be used. Example: FOR ALL X SAVEAS H(X); with the above expression would mean that H(Z) evaluates to 2*Y+2*Z. A further method for referencing more than the last expression is described in the section on interactive use of REDUCE. 8.3 Output Of Expressions ←←←←←← ←← ←←←←←←←←←←← A considerable degree of flexibility is available in REDUCE in the printing of expressions generated during calculations. No explicit format statements are supplied, as these prove to be of little use in algebraic calculations, where the size of output or its composition is not generally known in advance. Instead, REDUCE provides a series of mode options to the user which should enable him to produce his output in a comprehensible and possibly pleasing form. The most extreme option offered is to suppress the output entirely from any top level evaluation. This is accomplished by turning off the switch OUTPUT which is normally on. It is useful for limiting output when loading large files or producing "clean" output from the prettyprint programs (q.v.). In most circumstances, however, we wish to view the output, so we need to know how to format it appropriately. As we mentioned earlier, an algebraic expression is normally printed in an expanded form, filling the whole output line with terms. Certain output declarations, however, can be used to affect this format. To begin with, we look at an operator for changing the length of the output line. 8.3.1 Linelength Operator ←←←←←←←←←← ←←←←←←←← This operator is used with the syntax LINELENGTH(NUM:integer):integer, and sets the output line length to the integer NUM. It returns the previous output line length (so that it can be stored for later resetting of the output line if needed). 8.3.2 Output Declarations ←←←←←← ←←←←←←←←←←←← We now describe a number of switches and declarations which are available for controlling output formats. It should be noted, however, that the transformation of large expressions to produce these varied output formats can take a lot of computing time and space. If a user wishes to speed up the printing of his output in such cases, he can turn off the switch PRI. 8-4 If this is done, then output is produced in one fixed format, which basically reflects the internal form of the expression, and none of the options below apply. PRI is normally on. With PRI on, the output declarations and switches available are as follows: 8.3.2.1 Order Declaration ←←←←← ←←←←←←←←←←← The declaration ORDER may be used to order variables on output. The syntax is: ORDER V1,...VN; where the Vi are kernels (q.v.). Thus, ORDER X,Y,Z; orders X ahead of Y, Y ahead of Z and all three ahead of other variables not given an order. ORDER NIL; resets the output order to the system default. The order of variables may be changed by further calls of ORDER, but then the reordered variables would have an order lower than those in earlier ORDER calls. Thus, ORDER X,Y,Z; ORDER Y,X; would order Z ahead of Y and X. The default ordering is implementation dependent, but is usually alphabetic. 8.3.2.2 Factor Declaration ←←←←←← ←←←←←←←←←←← This declaration takes a list of identifiers or kernels (q.v.) as argument. FACTOR is not a factoring command (use FACTORIZE or the FACTOR switch (q.v.) for this purpose); rather it is a separation command. All terms involving fixed powers of the declared expressions are printed as a product of the fixed powers and a sum of the rest of the terms. All expressions involving a given prefix operator may also be factored by putting the operator name in the list of factored identifiers. e.g. FACTOR X,COS,SIN(X); causes all powers of X and SIN(X) and all functions of COS to be factored. The declaration REMFAC V1,...,Vn; removes the factoring flag from the expressions V1 through Vn. 8-5 8.3.3 Output Control Switches ←←←←←← ←←←←←←← ←←←←←←←← In addition to these declarations, the form of the output can be modified by switching various output control switches using the declarations ON and OFF. We shall illustrate the use of these switches by an example, namely the printing of the expression X**2*(Y**2+2*Y)+X*(Y**2+Z)/(2*A) . The relevant switches are as follows: 8.3.3.1 Allfac Switch ←←←←←← ←←←←←← This switch will cause the system to search the whole expression, or any sub-expression enclosed in parentheses, for simple multiplicative factors and print them outside the parentheses. Thus our expression with ALLFAC off will print as 2 2 2 2 (2*X *Y *A + 4*X *Y*A + X*Y + X*Z)/(2*A) and with ALLFAC on as 2 2 X*(2*X*Y *A + 4*X*Y*A + Y + Z)/(2*A) . ALLFAC is normally on, and is on in the following examples, except where otherwise stated. 8.3.3.2 Div Switch ←←← ←←←←←← This switch makes the system search the denominator of an expression for simple factors which it divides into the numerator, so that rational fractions and negative powers appear in the output. With DIV on, our expression would print as 2 2 (-1) (-1) X*(X*Y + 2*X*Y + 1/2*Y *A + 1/2*A *Z) . DIV is normally off. 8.3.3.3 List Switch ←←←← ←←←←←← This switch causes the system to print each term in any sum on a separate line. With LIST on, our expression prints as 2 X*(2*X*Y *A 8-6 + 4*X*Y*A 2 + Y + Z)/(2*A) . LIST is normally off. 8.3.3.4 Rat Switch ←←← ←←←←←← This switch is only useful with expressions in which variables are factored with FACTOR. With this mode, the overall denominator of the expression is printed with each factored sub-expression. We assume a prior declaration FACTOR X; in the following output. We first print the expression with RAT off: 2 2 (2*X *Y*A*(Y + 2) + X*(Y + Z))/(2*A) . With RAT on the output becomes: 2 2 X *Y*(Y + 2) + X*(Y + Z)/(2*A) . RAT is normally off. Next, if we leave X factored, and turn on both DIV and RAT, the result becomes 2 (-1) 2 X *Y*(Y + 2) + 1/2*X*A *(Y + Z) . Finally, with X factored, RAT on and ALLFAC off we retrieve the original structure 2 2 2 X *(Y + 2*Y) + X*(Y + Z)/(2*A) . 8.3.3.5 Ratpri Switch ←←←←←← ←←←←←← If the numerator and denominator of an expression can each be printed in one line, the output routines will print them in a two dimensional notation, with numerator and denominator on separate lines and a line of dashes in between. For example, (A+B)/2 will print as A + B ----- . 2 Turning this switch off causes such expressions to be output in a linear form. 8-7 8.3.3.6 Revpri Switch ←←←←←← ←←←←←← The normal ordering of terms in output is from highest to lowest power. In some situations (e.g., when a power series is output), the opposite ordering is more convenient. The switch REVPRI if on causes such a reverse ordering of terms. For example, the expression y*(x+1)**2+(y+3)↑2 will normally print as 2 2 X *Y + 2*X*Y + Y + 7*Y + 9 whereas with REVPRI on, it will print as 2 2 9 + 7*Y + Y + 2*X*Y + X *Y. 8.3.4 Write Command ←←←←← ←←←←←←← In simple cases no explicit output command is necessary in REDUCE, since the value of any expression is automatically printed if a semicolon is used as a delimiter. There are, however, several situations in which such a command is useful. In a FOR, WHILE, or REPEAT statement it may be desired to output something each time the statement within the loop construct is repeated. It may be desired for a procedure to output intermediate results or other information while it is running. It may be desired to have results labeled in special ways, especially if the output is directed to a file or device other than the terminal. The WRITE command consists of the word WRITE followed by one or more items separated by commas, and followed by a terminator. There are three kinds of items which can be used: 1) Expressions (including variables and constants). The expression is evaluated, and the result is printed out. 2) Assignments. The expression on the right side of the := operator is evaluated, and is assigned to the variable on the left; then the symbol on the left is printed, followed by a ":=", followed by the value of the expression on the right -- almost exactly the way an assignment followed by a semicolon prints out normally. (The difference is that if the WRITE is in a FOR statement and the left-hand side of the assignment is an array position or something similar containing the variable of the FOR iteration, then the value of that variable is inserted in the printout.) 3) Arbitrary strings of characters, preceded and followed by double-quote marks (e.g., "string"). The items specified by a single WRITE statement print side by side on one 8-8 line. (The line is broken automatically if it is too long.) Strings print exactly as quoted. The print line is closed at the end of a WRITE command evaluation. Therefore the command WRITE ""; (specifying nothing to be printed except the empty string) causes a line to be skipped. Examples: (1) If A is X+5, B is itself, C is 123, M is an array, and Q=3, then WRITE M(Q):=A," ",B/C," THANK YOU" will set M(3) to X+5 and prints M(Q) := X + 5 B/123 THANK YOU . The only reason there are blanks between the 5 and B, and the 3 and T, are the blanks in the quoted strings. (2) To print a table of the squares of the integers from 1 to 20: FOR I:=1:20 DO WRITE I," ",I**2; (3) To print a table of the squares of the integers from 1 to 20, and at the same time store them in positions 1 to 20 of an array A: FOR I:=1:20 DO <<A(I):=I**2; WRITE I," ",A(I)>>; This will give us two columns of numbers. If we had used FOR I:=1:20 DO WRITE I," ",A(I):=I**2; we would also get "A(i) := " repeated on each line. (4) The following more complete example calculates the famous f and g series, first reported in Sconzo, P., LeSchack, A. R., and Tobey, R., "Symbolic Computation of f and g Series by Computer", Astronomical Journal 70 (May 1965). X1:= -SIG*(MU+2*EPS)$ X2:= EPS-2*SIG**2$ X3:= -3*MU*SIG$ F:= 1$ G:= 0$ FOR I:= 1 STEP 1 UNTIL 10 DO BEGIN F1:= -MU*G + X1*DF(F,EPS) + X2*DF(F,SIG) + X3*DF(F,MU); WRITE "F(",I,") := ",F1; G1:= F + X1*DF(G,EPS) + X2*DF(G,SIG) + X3*DF(G,MU); WRITE "G(",I,") := ",G1; F:=F1$ G:=G1$ END; 8-9 A portion of the output, to illustrate the printout from the WRITE command, is as follows: ... <prior output> ... 2 F(4) := MU*(3*EPS - 15*SIG + MU) G(4) := 6*SIG*MU 2 F(5) := 15*SIG*MU*( - 3*EPS + 7*SIG - MU) 2 G(5) := MU*(9*EPS - 45*SIG + MU) ... <more output> ... 8.3.5 Suppression Of Zeros ←←←←←←←←←←← ←← ←←←←← It is sometimes annoying to have zero assignments (i.e. assignments of the form <expression> := 0) printed, especially in printing large arrays with many zero elements. The output from such assignments can be suppressed by turning on the switch NERO. 8.3.6 Fortran Style Output Of Expressions ←←←←←←← ←←←←← ←←←←←← ←← ←←←←←←←←←←← It is naturally possible to evaluate expressions numerically in REDUCE by giving all variables and sub-expressions numerical values. However, as we pointed out elsewhere the user must declare real arithmetical operation by turning on the switches FLOAT or BIGFLOAT. However, it should be remembered that arithmetic in REDUCE is not particularly fast, since results are interpreted rather than evaluated in a compiled form. The user with a large amount of numerical computation after all necessary algebraic manipulations have been performed is therefore well advised to perform these calculations in a FORTRAN or similar system. For this purpose, REDUCE offers facilities for users to produce FORTRAN compatible files for numerical processing. First, when the switch FORT is on, the system will print expressions in a FORTRAN notation. Expressions begin in column 7. If an expression extends over one line, a continuation mark (.) followed by a blank appears on subsequent cards. After a certain number of lines have been produced (according to the value of the variable *CARDNO (q.v.)), a new expression is started. If the expression printed arises from an assignment to a variable, the variable is printed as the name of the expression. Otherwise the expression is given the default name ANS. An error occurs if identifiers or numbers are outside the bounds permitted by FORTRAN. A second option is to use the WRITE command to produce other programs. 8-10 Example: The following REDUCE statements ON FORT; OUT FORFIL; WRITE "C THIS IS A FORTRAN PROGRAM"; WRITE " 1 FORMAT(E13.5)"; WRITE " U=1.23"; WRITE " V=2.17"; WRITE " W=5.2"; X:=(U+V+W)**11; WRITE "C OF COURSE IT WAS FOOLISH TO EXPAND THIS EXPRESSION"; WRITE " PRINT 1,X"; WRITE " END"; SHUT FORFIL; OFF FORT; will generate a file FORFIL which contains: C THIS IS A FORTRAN PROGRAM 1 FORMAT(E13.5) U=1.23 V=2.17 W=5.2 ANS1=1320.*U**3*V*W**7+165.*U**3*W**8+55.*U**2*V**9+495.*U . **2*V**8*W+1980.*U**2*V**7*W**2+4620.*U**2*V**6*W**3+ . 6930.*U**2*V**5*W**4+6930.*U**2*V**4*W**5+4620.*U**2*V**3* . W**6+1980.*U**2*V**2*W**7+495.*U**2*V*W**8+55.*U**2*W**9+ . 11.*U*V**10+110.*U*V**9*W+495.*U*V**8*W**2+1320.*U*V**7*W . **3+2310.*U*V**6*W**4+2772.*U*V**5*W**5+2310.*U*V**4*W**6 . +1320.*U*V**3*W**7+495.*U*V**2*W**8+110.*U*V*W**9+11.*U*W . **10+V**11+11.*V**10*W+55.*V**9*W**2+165.*V**8*W**3+330.* . V**7*W**4+462.*V**6*W**5+462.*V**5*W**6+330.*V**4*W**7+ . 165.*V**3*W**8+55.*V**2*W**9+11.*V*W**10+W**11 X=U**11+11.*U**10*V+11.*U**10*W+55.*U**9*V**2+110.*U**9*V* . W+55.*U**9*W**2+165.*U**8*V**3+495.*U**8*V**2*W+495.*U**8 . *V*W**2+165.*U**8*W**3+330.*U**7*V**4+1320.*U**7*V**3*W+ . 1980.*U**7*V**2*W**2+1320.*U**7*V*W**3+330.*U**7*W**4+462. . *U**6*V**5+2310.*U**6*V**4*W+4620.*U**6*V**3*W**2+4620.*U . **6*V**2*W**3+2310.*U**6*V*W**4+462.*U**6*W**5+462.*U**5* . V**6+2772.*U**5*V**5*W+6930.*U**5*V**4*W**2+9240.*U**5*V . **3*W**3+6930.*U**5*V**2*W**4+2772.*U**5*V*W**5+462.*U**5 . *W**6+330.*U**4*V**7+2310.*U**4*V**6*W+6930.*U**4*V**5*W . **2+11550.*U**4*V**4*W**3+11550.*U**4*V**3*W**4+6930.*U** . 4*V**2*W**5+2310.*U**4*V*W**6+330.*U**4*W**7+165.*U**3*V . **8+1320.*U**3*V**7*W+4620.*U**3*V**6*W**2+9240.*U**3*V** . 5*W**3+11550.*U**3*V**4*W**4+9240.*U**3*V**3*W**5+4620.*U . **3*V**2*W**6+ANS1 C OF COURSE IT WAS FOOLISH TO EXPAND THIS EXPRESSION PRINT 1,X END 8-11 8.3.6.1 Fortran Output Options ←←←←←←← ←←←←←← ←←←←←←← There are a number of methods available to change the default format of the FORTRAN output. The breakup of the expression into subparts is such that the number of continuation lines produced is less than a given number. This number can be modified by the assignment CARDNO!* := <number>; where <number> is the TOTAL number of cards allowed in a statement. CARDNO!* is initially set to 20. The width of the output expression is also adjustable by the assignment FORTWIDTH!* := <integer>; which sets the total width of a given line to <integer>. The initial FORTRAN output width is 70. REDUCE automatically inserts a decimal point after each isolated integer coefficient in a FORTRAN expression (so that, for example, 4 becomes 4.). To prevent this, set the PERIOD mode switch to OFF. Finally, the default name ANS assigned to an unnamed expression and its subparts can be changed by the operator VARNAME. This takes a single identifier as argument, which then replaces ANS as the expression name. The value of VARNAME is its argument. 8.3.7 Saving Expressions For Later Use As Input ←←←←←← ←←←←←←←←←←← ←←← ←←←←← ←←← ←← ←←←←← It is often useful to save an expression on an external file for use later as input in further calculations. The commands for opening and closing output files are explained elsewhere. However, we see in the examples on output of expressions that the standard 'natural' method of printing expressions in not compatible with the input syntax. So to print the expression in an input compatible form we must inhibit this natural style by turning off the switch NAT. If this is done, a dollar sign will also be printed at the end of the expression. Example: The following sequence of commands OFF NAT; OUT OUT; X := (Y+Z)**2; WRITE "END"; SHUT OUT; ON NAT; will generate a file OUT which contains X := Y**2 + 2*Y*Z + Z**2$ END$ 8-12 8.3.8 Displaying Expression Structure ←←←←←←←←←← ←←←←←←←←←← ←←←←←←←←← In those cases where the final result has a complicated form, it is often convenient to display the skeletal structure of the answer. The operator STRUCTR, which takes a single expression as argument, will do this for you. Its syntax is: STRUCTR(EXPRN:algebraic[,ID1:identifier[,ID2:identifier]]); The structure is printed effectively as a tree, in which the subparts are laid out with auxiliary names. If the optional ID is absent, the auxiliary names are prefixed by the root ANS. This root may be changed by the operator VARNAME (q.v.). If the optional ID1 is present, and is an array name, the subparts are named as elements of that array, otherwise ID1 is used as the root prefix. The EXPRN can be either a scalar or a matrix expression. Use of any other will result in an error. Example: Let us suppose that the workspace contains ((A+B)**2+C)**3+D. Then the input STRUCTR WS; will (with EXP off) result in the output: ANS3 WHERE 3 ANS3 := ANS2 + D 2 ANS2 := ANS1 + C ANS1 := A + B The workspace remains unchanged after this operation, since STRUCTR returns no value (if STRUCTR is used as a sub-expression, its value is taken to be 0). In addition, the sub-expressions are normally only displayed and not stored. If you wish to store the sub-expressions with their displayed names, the switch SAVESTRUCTR should be turned on. Alternatively the PART operator (q.v.) can be used to retrieve the required parts of the expression. For example, to get the term corresponding to ANS2 in the above, one could say: PART(WS,1,1); If FORT is on, then the results are printed in the reverse order; the algorithm in fact guaranteeing that no sub-expression will be referenced before it is defined. The second optional argument ID2 may also be used in this case to name the actual expression (or expressions in the case of a matrix argument). 8-13 Example: Let us suppose that M, a 2 by 1 matrix, contains the elements ((A+B)**2+C)**3+D and (A+B)*(C+D) respectively, and that V has been declared to be an array. With EXP off and FORT on, the statement STRUCTR(2*M,V,K); will result in the output V(1)=A+B V(2)=V(1)**2+C V(3)=V(2)**3+D V(4)=C+D K(1,1)=2.*V(3) K(2,1)=2.*V(1)*V(4). 8.4 Changing The Internal Order Of Variables ←←←←←←←← ←←← ←←←←←←←← ←←←←← ←← ←←←←←←←←← The internal ordering of variables (more specifically kernels) can have significant effect on the space and time associated with a calculation. In its default state, REDUCE uses a specific order for this which may vary between sessions. However, it is possible for the user to change this internal order by means of the declaration KORDER. The syntax for this is: KORDER V1,...,Vn; where the Vi are kernels. With this declaration, the Vi are ordered internally ahead of any other kernels in the system. V1 has the highest order, V2 the next highest, and so on. A further call of KORDER replaces a previous one. KORDER NIL; resets the internal order to the system default. Unlike the ORDER declaration (q.v.), which has a purely cosmetic effect on the way results are printed, the use of KORDER can have significant on computation time. In critical cases then, the user can experiment with the ordering of the variables used to determine the optimum set for a given problem. 8.5 Obtaining Parts Of Algebraic Expressions ←←←←←←←←← ←←←←← ←← ←←←←←←←←← ←←←←←←←←←←← There are many occasions where it is desirable to obtain a specific part of an expression, or even change such a part to another expression. A number of operators are available in REDUCE for this purpose, and will be described in this section. In addition, operators for obtaining specific parts of polynomials and rational functions (such as a denominator) are described in another section. 8.5.1 Coeff Operator ←←←←← ←←←←←←←← Syntax: COEFF(EXPRN:polynomial,VAR:kernel). COEFF is an operator which partitions EXPRN into its various coefficients with respect to VAR and returns them as a list, with the coefficient 8-14 independent of VAR first. Under normal circumstances, an error results if EXPRN is not a polynomial in VAR, although the coefficients themselves can be rational as long as they do not depend on VAR. However, if the switch RATARG is on, denominators are not checked for dependence on VAR, and are taken to be part of the coefficients. Example: COEFF((Y**2+Z)**3/Z,Y); returns the result 2 {Z ,0,3*Z,0,3,0,1/Z}. whereas COEFF((Y**2+Z)**3/Z,Y); gives an error if RATARG is off, and the result 3 2 {Z /Y,0,3*Z /Y,0,3*Z/Y,0,1/Y} if RATARG is on. The length of the result of COEFF is the highest power of VAR encountered plus 1. In the above examples it is 7. In addition, the variables HIPOW!* and LOWPOW!* are set to the highest and lowest non-zero power found in EXPRN during the evaluation. If EXPRN is zero, then HIPOW!* and LOWPOW!* are both set to zero. 8.5.2 Coeffn Operator ←←←←←← ←←←←←←←← The Coeffn operator is designed to give the user a particular coefficient of a variable in a polynomial, as opposed to Coeff which returns all coefficients. Coeffn is used with the syntax COEFFN(EXPRN:polynomial,VAR:kernel,N:integer). It returns the Nth coefficient of VAR in the polynomial EXPRN. 8.5.3 Part Operator ←←←← ←←←←←←←← Syntax: PART(EXPRN:algebraic[,INTEXP:integer]). This operator works on the form of the expression as printed OR AS IT WOULD HAVE BEEN PRINTED AT THAT POINT IN THE CALCULATION bearing in mind all the relevant switch settings at that point. The reader therefore needs some 8-15 familiarity with the way that expressions are represented in prefix form in REDUCE to use these operators effectively. Furthermore, it is assumed that PRI is ON at that point in the calculation. The reason for this is that with PRI off, an expression is printed by walking the tree representing the expression internally. To save space, it is never actually transformed into the equivalent prefix expression as occurs when PRI is on. However, the operations on polynomials described elsewhere can be equally well used in this case to obtain the relevant parts. The evaluation proceeds recursively down the integer expression list. In other words, PART(<expression>,<integer1>,<integer2>) ==> PART(PART(<expression>,<integer1>),<integer2>) and so on, and PART(<expression>) ==> <expression>. INTEXP can be any expression that evaluates to an integer. If the integer is positive, then that term of the expression is found. If the integer is 0, the operator is returned. Finally, if the integer is negative, the counting is from the tail of the expression rather than the head. For example, if the expression A+B is printed as A+B (i.e., the ordering of the variables is alphabetical), then PART(A+B,2) ==> B PART(A+B,-1) ==> B and PART(A+B,0) ==> PLUS. An operator ARGLENGTH is available to determine the number of arguments of the top level operator in an expression. If the expression does not contain a top level operator, then -1 is returned. For example, ARGLENGTH(A+B+C) ==> 3 ARGLENGTH(F()) ==> 0 ARGLENGTH(A) ==> -1. 8.5.4 Changing Parts Of Expressions ←←←←←←←← ←←←←← ←← ←←←←←←←←←←← PART may also be used to change a given part of an expression. In this case, the PART construct appears on the left-hand side of an assignment statement, and the expression to replace the given part on the right-hand side. For example, with the normal settings of REDUCE's switches: PART(A+B,2) := C; ==> A+C PART(A+B,0) := -; ==> A-B. 9-1 9. OPERATIONS ON POLYNOMIALS AND RATIONALS ←←←←←←←←←← ←← ←←←←←←←←←←← ←←← ←←←←←←←←← Many operations in computer algebra are concerned with polynomials and rational functions. In this section, we review some of the switches and operators available for this purpose. These are in addition to those that work on general expressions (such as DF and INT) described elsewhere. In the case of operators, the arguments are first simplified before the operations are applied. In addition, they operate only on arguments of prescribed types, and produce a type mismatch error if given arguments which cannot be interpreted in the required mode with the current switch settings. For example, if an argument is required to be a kernel and A/2 is used (with no other rules for A), an error A/2 invalid as kernel will result. With the exception of those that select various parts of a polynomial or rational function, these operations have potentially significant effects on the space and time associated with a given calculation. The user should therefore experiment with their use in a given calculation in order to determine the optimum set for a given problem. One such operation provided by the system is an operator TERMS that returns the number of top level terms in the numerator of its argument. For example, TERMS ((A+B+C)**3/(C+D)); has the value 10. To get the number of terms in the denominator, one would first select the denominator by the operator DEN (q.v.) and then call terms, as in TERMS DEN ((A+B+C)**3/(C+D)); Other operations currently supported, the relevant switches and operators, and the required argument and value modes of the latter, follow. 9.1 Controlling The Expansion Of Expressions ←←←←←←←←←←← ←←← ←←←←←←←←← ←← ←←←←←←←←←←← The switch EXP controls the expansion of expressions. If it is off, no expansion of powers or products of expressions occurs. Users should note however that in this case results come out in a normal but not necessarily canonical form. This means that zero expressions simplify to zero, but that two equivalent expressions need not necessarily simplify to the same form. Example: With EXP on, the two expressions (A+B)*(A+2*B) and A**2+3*A*B+2*B**2 will both simplify to the latter form. With EXP off, they would remain unchanged, unless the complete factoring (ALLFAC) option were in force. 9-2 EXP is normally on. Several operators that expect a polynomial as an argument behave differently when EXP is off, since there is often only one term at the top level. For example, with EXP off TERMS ((A+B+C)**3/(C+D)); returns the value 1. 9.2 Factorization Of Polynomials ←←←←←←←←←←←←← ←← ←←←←←←←←←←← REDUCE is capable of factorizing univariate and multivariate polynomials that have integer coefficients, finding all factors that also have integer coefficients. The package for doing this was written by Dr. Arthur C. Norman and Ms. P. Mary Ann Moore at The University of Cambridge. It is described in P. M. A. Moore and A. C. Norman, "Implementing a Polynomial Factorization and GCD Package", Proc. SYMSAC '81, ACM (New York) (1981), 109-116. The easiest way to use this facility is to turn on the switch FACTOR, which causes all expressions to be output in a factored form. For example, with FACTOR on, the expression A**2-B**2 is returned as (A+B)*(A-B). It is also possible to factorize a given expression explicitly. The operator FACTORIZE that invokes this facility is used with the syntax FACTORIZE(EXPRN:polynomial[,INTEXP:prime integer]):list, the optional argument of which will be described later. Thus to find and display all factors of the cyclotomic polynomial x**105-1, one could write: FACTORIZE(X**105-1); In the above example, there is no overall numerical factor in the result, so the results will consist only of polynomials in x. The number of such polynomials can be found by using the operator LENGTH (q.v.). If there is a numerical factor, as in factorizing (12*x**2-12), that factor will appear as the first member of the result. It will however not be factored further. Prime factors of such numbers can be found using the switch IFACTOR. For example, on ifactor; factorize(12x**2-12); would result in the output {2,2,3,X-1,X+1}. Note that the IFACTOR switch only affects the result of FACTORIZE. It has no effect if the FACTOR switch is also on. 9-3 The order in which the factors occur in the result (with the exception of a possible overall numerical coefficient which comes first) is system dependent and should not be relied on. Similarly it should be noted that any pair of individual factors can be negated without altering their product, and that REDUCE may sometimes do that. The factorizer works by first reducing multivariate problems to univariate ones and then solving the univariate ones modulo small primes. It normally selects both evaluation points and primes using a random number generator that should lead to different detailed behavior each time any particular problem is tackled. If, for some reason, it is known that a certain (probably univariate) factorization can be performed effectively with a known prime, P say, this value of P can be handed to FACTORIZE as a second argument. An error will occur if a non-prime is provided to FACTORIZE in this manner. It is also an error to specify a prime that divides the discriminant of the polynomial being factored, but users should note that this condition is not checked by the program. Factorization can be performed over a number of polynomial coefficient domains in addition to integers. The particular description of the relevant domain should be consulted to see if factorization is supported. For example, the following statements will factorize x**4+1 modulo 7: SETMOD 7; ON MODULAR; FACTORIZE(X**4+1); The factorization module is provided with a trace facility that may be useful as a way of monitoring progress on large problems, and of satisfying curiosity about the internal workings of the package. The most simple use of this is enabled by issuing the REDUCE command ON TRFAC; Following this, all calls to the factorizer will generate informative messages reporting on such things as the reduction of multivariate to univariate cases, the choice of a prime and the reconstruction of full factors from their images. Further levels of detail in the trace are intended mainly for system tuners and for the investigation of suspected bugs. For example, TRALLFAC gives tracing information at all levels of detail. The switch that can be set by "ON TIMINGS;" makes it possible for one who is familiar with the algorithms used to determine what part of the factorization code is consuming the most resources. "ON OVERVIEW;" reduces the amount of detail presented in other forms of trace. Other forms of trace output are enabled by directives of the form SYMBOLIC SET!-TRACE!-FACTOR(number,filename); where useful numbers are 1,2,3 and 100,101,... . This facility is intended to make it possible to discover in fairly great detail what just some small part of the code has been doing - the numbers refer mainly to depths of recursion when the factorizer calls itself, and to the split between its work forming and factorizing images and reconstructing full factors from 9-4 these. If NIL is used in place of a filename the trace output requested is directed to the standard output stream. After use of this trace facility the generated trace files should be closed by calling SYMBOLIC CLOSE!-TRACE!-FILES(); CAUTION: The code for performing multivariate factorization is very large, and therefore takes considerable time to load. As a result, there is some delay when the factorizer is first used while the code is being loaded. In addition, using the factorizer with MCD off will result in an error. 9.3 Cancellation Of Common Factors ←←←←←←←←←←←← ←← ←←←←←← ←←←←←←← Facilities are available in REDUCE for cancelling common factors in the numerators and denominators of expressions, at the option of the user. The system will perform this greatest common divisor computation if the switch GCD is on. (GCD is normally off.) A check is automatically made, however, for common variable and numerical products in the numerators and denominators of expressions, and the appropriate cancellations made. When GCD is on, and EXP is off, a check is made for square free factors in an expression. This includes separating out and independently checking the content of a given polynomial where appropriate. (For an explanation of these terms, see Anthony C. Hearn, "Non-Modular Computation of Polynomial GCDS Using Trial Division", Proc. EUROSAM 79, published as Lecture Notes on Comp. Science, Springer-Verlag, Berlin, No 72 (1979) 227-239.) Example: With EXP off and GCD on, the polynomial A*C+A*D+B*C+B*D would be returned as (A+B)*(C+D). Under normal circumstances, gcd's are computed using an algorithm described in the above paper. It is also possible in REDUCE to compute gcd's using an alternative algorithm, called the ezgcd algorithm, that uses modular arithmetic. The switch EZGCD, if on in addition to GCD, makes this happen. In non-trivial cases, the ezgcd algorithm is almost always better than the basic algorithm, often by orders of magnitude. We therefore STRONGLY advise users to use the EZGCD switch where they have the facilities available for supporting the package. For a description of the ezgcd algorithm, see J. Moses and D.Y.Y. Yun, "The EZ GCD Algorithm", Proc. ACM 1973, ACM, New York (1973) 159-166. CAUTION: The code for the ezgcd package is quite large. Consequently, there is usually a delay when it is first used while that module is loaded. Note also that this package shares code with the factorizer, so a certain amount of trace information can be produced using the factorizer trace switches. 9-5 An implementation of the heuristic gcd algorithm, first introduced by B.W. Char, K.O.Geddes and G.H. Gonnet, as described in J.H. Davenport and J. Padget, "HEUGCD: How Elementary Upperbounds Generate Cheaper Data", Proc. of EUROCAL '85, Vol 2, 18-28, published as Lecture Notes on Comp. Science, No. 204, Springer-Verlag, Berlin, 1985, is also available on an experimental basis. To use this algorithm, the switch HEUGCD should be on in addition to GCD. Note that if both EZGCD and HEUGCD are on, the former takes precedence. 9.3.1 Determining The Gcd Of Two Polynomials ←←←←←←←←←←← ←←← ←←← ←← ←←← ←←←←←←←←←←← This operator, used with the syntax GCD(EXPRN1:polynomial,EXPRN2:polynomial):polynomial, returns the greatest common divisor of the two polynomials EXPRN1 and EXPRN2. Examples: GCD(X**2+2*X+1,X**2+3*X+2) ==> X+1 GCD(2*X**2-2*Y**2,4*X+4*Y) ==> 2*X+2*Y GCD(X**2+Y**2,X-Y) ==> 1. 9.4 Working With Least Common Multiples ←←←←←←← ←←←← ←←←←← ←←←←←← ←←←←←←←←← Greatest common divisor calculations can often become expensive if extensive work with large rational expressions is required. However, in many cases, the only significant cancellations arise from the fact that there are often common factors in the various denominators which are combined when two rationals are added. Since these denominators tend to be smaller and more regular in structure than the numerators, considerable savings in both time and space can occur if a full gcd check is made when the denominators are combined and only a partial check when numerators are constructed. In other words, the true least common multiple of the denominators is computed at each step. The switch LCM is available for this purpose, and is normally on. 9.5 Controlling Use Of Common Denominators ←←←←←←←←←←← ←←← ←← ←←←←←← ←←←←←←←←←←←← When two rational functions are added, REDUCE normally produces an expression over a common denominator. However, if the user does not want denominators combined, he can turn off the switch MCD which controls this process. The latter switch is particularly useful if no greatest common divisor calculations are desired, or excessive differentiation of rational functions is required. CAUTION: With MCD off, results are not guaranteed to come out in either normal or canonical form. In other words, an expression equivalent to zero may in fact not be simplified to zero. This option is therefore most 9-6 useful for avoiding expression swell during intermediate parts of a calculation. MCD is normally on. 9.6 Remainder Operator ←←←←←←←←← ←←←←←←←← Syntax: REMAINDER(EXPRN1:polynomial,EXPRN2:polynomial):polynomial. Returns the remainder when EXPRN1 is divided by EXPRN2. This is the true remainder based on the internal ordering of the variables, and not the pseudo-remainder. Examples: REMAINDER((X+Y)*(X+2*Y),X+3*Y) ==> 2*Y**2 REMAINDER(2*X+Y,2) ==> Y. 9.7 Resultant Operator ←←←←←←←←← ←←←←←←←← This is used with the syntax RESULTANT(EXPRN1:polynomial,EXPRN2:polynomial,VAR:kernel):polynomial. It computes the resultant of the two given polynomials with respect to the given variable. The result can be identified as the determinant of a Sylvester matrix, but can often also be thought of informally as the result obtained when the given variable is eliminated between the two input polynomials. If the two input polynomials have a non-trivial gcd their resultant vanishes. The sign conventions used by the resultant function follow those in R. Loos, "Computing in Algebraic Extensions" in "Computer Algebra - Symbolic and Algebraic Computation", Second Ed., Edited by B. Buchberger, G.E. Collins and R. Loos, Springer-Verlag, 1983, namely deg(p)*deg(q) resultant(p(x),q(x),x) = (-1) *resultant(q,p,x) deg(p) resultant(a,p(x),x) = a (a free of the variable x) resultant(a,b,x) = 1 (a,b free of the variable x) 9.8 Obtaining Parts Of Polynomials And Rational Functions ←←←←←←←←← ←←←←← ←← ←←←←←←←←←←← ←←← ←←←←←←←← ←←←←←←←←← These operators select various parts of a polynomial or rational function structure. Except for the cost of rearrangement of the structure, these operations take very little time to perform. 9-7 9.8.1 Deg Operator ←←← ←←←←←←←← This operator is used with the syntax DEG(EXPRN:polynomial,VAR:kernel):integer. It returns the leading degree of the polynomial EXPRN in the variable VAR. If VAR does not occur as a variable in EXPRN, 0 is returned. Examples: DEG((A+B)*(C+2*D)**2,A) ==> 1 DEG((A+B)*(C+2*D)**2,D) ==> 2 DEG((A+B)*(C+2*D)**2,E) ==> 0. 9.8.2 Den Operator ←←← ←←←←←←←← This is used with the syntax: DEN(EXPRN:rational):polynomial. It returns the denominator of the rational expression EXPRN. If EXPRN is a polynomial, 1 is returned. Examples: DEN(X/Y**2) ==> Y**2 DEN(100/6) ==> 3 [since 100/6 is first simplified to 50/3] DEN(A/4+B/6) ==> 12 DEN(A+B) ==> 1 9.8.3 Lcof Operator ←←←← ←←←←←←←← LCOF is used with the syntax LCOF(EXPRN:polynomial,VAR:kernel):polynomial. It returns the leading coefficient of the polynomial EXPRN in the variable VAR. If VAR does not occur as a variable in EXPRN, EXPRN is returned unchanged. Examples: LCOF((A+B)*(C+2*D)**2,A) ==> C**2+4*C*D+4*D**2 LCOF((A+B)*(C+2*D)**2,D) ==> 4*(A+B) LCOF((A+B)*(C+2*D),E) ==> A*C+2*A*D+B*C+2*B*D. 9-8 9.8.4 Lterm Operator ←←←←← ←←←←←←←← Syntax: LTERM(EXPRN:polynomial,VAR:kernel):polynomial. LTERM returns the leading term of EXPRN with respect to VAR. If EXPRN does not depend on VAR, 0 is returned. Examples: LTERM((A+B)*(C+2*D)**2,A) ==> A*(C**2+4*C*D+4*D**2) LTERM((A+B)*(C+2*D)**2,D) ==> 4*D**2*(A+B) LTERM((A+B)*(C+2*D)**2,E) ==> 0. 9.8.5 Mainvar Operator ←←←←←←← ←←←←←←←← Syntax: MAINVAR(EXPRN:polynomial):expression. Returns the main variable (based on the internal polynomial representation) of EXPRN. If EXPRN is a domain element, 0 is returned. Examples: MAINVAR((A+B)*(C+2*D)**2) ==> A (normally) MAINVAR(2) ==> 0 9.8.6 Num Operator ←←← ←←←←←←←← Syntax: NUM(EXPRN:rational):polynomial. Returns the numerator of the rational expression EXPRN. If EXPRN is a polynomial, that polynomial is returned. Examples: NUM(X/Y**2) ==> X NUM(100/6) ==> 50 NUM(A/4+B/6) ==> 3*A+2*B NUM(A+B) ==> A+B 9.8.7 Reduct Operator ←←←←←← ←←←←←←←← Syntax: REDUCT(EXPRN:polynomial,VAR:kernel):polynomial. Returns the reductum of EXPRN with respect to VAR (i.e., the part of EXPRN left after the leading term is removed). If EXPRN does not depend on the variable VAR, 0 is returned. Examples: 9-9 REDUCT((A+B)*(C+2*D)**2,A) ==> B*(C**2+4*C*D+4*D**2) REDUCT((A+B)*(C+2*D)**2,D) ==> C*(A*C+4*A*D+B*C+4*B*D) REDUCT((A+B)*(C+2*D)**2,E) ==> 0. 9.9 Polynomial Coefficient Arithmetic ←←←←←←←←←← ←←←←←←←←←←← ←←←←←←←←←← REDUCE allows for a variety of numerical domains for the numerical coefficients of polynomials used in calculations. The default mode is integer arithmetic, although the possibility of using real coefficients has been discussed elsewhere. Rational coefficients have also been available by using integer coefficients in both the numerator and denominator of an expression, using the ON DIV option (q.v.) to print the coefficients as rationals. However, REDUCE includes several other coefficient options in its basic version which we shall describe in this section. All such coefficient modes are actually supported in a table-driven manner so that it is straightforward to extend the range of possibilities. A description of how to do this is given in R.J. Bradford, A.C. Hearn, J.A. Padget and E. Schruefer, "Enlarging the REDUCE Domain of Computation," Proc. of SYMSAC '86, ACM, New York (1986), 100-106. 9.9.1 Rational Coefficients In Polynomials ←←←←←←←← ←←←←←←←←←←←← ←← ←←←←←←←←←←← Instead of treating rational numbers as the numerator and denominator of a rational expression, it is also possible to use them as polynomial coefficients directly. This is accomplished by turning on the switch RATIONAL. Example: With RATIONAL off, the input expression A/2 would be converted into a rational expression, whose numerator was A and denominator 2. With RATIONAL on, the same input would become a rational expression with numerator 1/2*A and denominator 1. Thus the latter can be used in operations that require polynomial input whereas the former could not. 9.9.2 Real Coefficients In Polynomials ←←←← ←←←←←←←←←←←← ←← ←←←←←←←←←←← The switch FLOAT permits the use of fixed-sized real coefficients in polynomial expressions. The actual precision of these coefficients is system dependent. In this mode, denominators are automatically made monic, and an appropriate adjustment made to the numerator. If a single precision real coefficient is found to be equal to an integer within the precision of the system comparison operation, then it is normally replaced by the equivalent integer. If a user does not want this conversion to occur, the switch CONVERT should be turned off. CONVERT is normally on. However, even with CONVERT off, a real coefficient equal to zero is replaced by 0. Furthermore, the conversion of a denominator to monic form implies that a leading real coefficient of 1.0 in a denominator is replaced by 1. Example: With FLOAT on, the input expression A/2 would be converted into a rational expression whose numerator is 0.5*A and denominator 1. 9-10 9.9.3 Arbitrary Precision Real Coefficients ←←←←←←←←← ←←←←←←←←← ←←←← ←←←←←←←←←←←← REDUCE includes a module for those calculations that require greater real number precision than the FLOAT mode supports. To use this mode, the command ON BIGFLOAT; is used. The default precision in this case is ten decimal digits. This precision can however be changed by the operator PRECISION. For example, PRECISION 50; sets the precision to fifty decimal digits. NOTE: At present, it is not possible to input a real number with more digits than those of a single precision real number in the given implementation. This deficiency will be corrected in future versions. Further information on this module may be found in T. Sasaki, "Manual for Arbitrary Precision Real Arithmetic System in REDUCE", Department of Computer Science, University of Utah, Technical Note No. TR-8 (1979). 9.9.4 Modular Number Coefficients In Polynomials ←←←←←←← ←←←←←← ←←←←←←←←←←←← ←← ←←←←←←←←←←← REDUCE includes facilities for manipulating polynomials whose coefficients are computed modulo a given base. To use this option, two commands must be used; SETMOD <integer>, to set the prime modulus, and ON MODULAR to cause the actual modular calculations to occur. For example, with SETMOD 3; and ON MODULAR, the polynomial (A+2*B)**3 would become A**3 + 2*B**3. The argument of SETMOD is evaluated algebraically, except that non-modular (integer) arithmetic is used. Thus the sequence SETMOD 3; ON MODULAR; SETMOD 7; will correctly set the modulus to 7. Users should note that the modular calculations are on the polynomial coefficients only. It is not currently possible to reduce the exponents since no check for a prime modulus is made (which would allow x**(p-1) to be reduced to 1 mod p). Note also that any division by a number not co-prime with the modulus will result in the error "Invalid modular division". 9.9.5 Complex Number Coefficients In Polynomials ←←←←←←← ←←←←←← ←←←←←←←←←←←← ←← ←←←←←←←←←←← Although REDUCE routinely treats the square of the variable I as equivalent to -1, this is not sufficient to reduce expressions involving I to lowest terms, or to factor such expressions over the complex numbers. For example, in the default case, FACTORIZE(A**2+1) gives the result 9-11 {A**2+1} and (A**2+B**2)/(A+I*B) is not reduced further. However, if the switch COMPLEX is turned on, full complex arithmetic is then carried out. In other words, the above factorization will give the result {A-I,A+I} and the quotient will be reduced to A-I*B. The switch COMPLEX may be combined with FLOAT or BIGFLOAT to give complex floats and complex bigfloats respectively, and the appropriate arithmetic is performed in each case. If the switch RATIONALIZE is on, then complex conjugation is used to remove complex numbers from denominators of expressions. This operation will also work on denominators involving the variable I even if COMPLEX is off. 10-1 10. SUBSTITUTION COMMANDS ←←←←←←←←←←←← ←←←←←←←← An important class of commands in REDUCE is that which defines substitutions for variables and expressions to be made during the evaluation of expressions. Such substitutions use the prefix operator SUB, the infix operator WHERE, and various forms of the command LET. 10.1 Sub Operator ←←← ←←←←←←←← Syntax: SUB([VAR:kernel = EXPRN:algebraic,]EXPRN1:algebraic):algebraic. The SUB operator gives the algebraic result of replacing every occurrence of the variable VAR in the expression EXPRN1 by the expression EXPRN. Specifically, EXPRN1 is first evaluated using all available rules. Next the substitutions are made, and finally the substituted expression is reevaluated. When more than one variable occurs in the substitution list, the substitution is performed by recursively walking down the tree representing EXPRN1, and replacing every VAR found by the appropriate EXPRN. The EXPRN are not themselves searched for any occurrences of the various VARs. The trivial case SUB(EXPRN1) returns the algebraic value of EXPRN1. Example: SUB(X=A+Y,Y=Y+1,X**2+Y**2) ==> (A+Y)**2+(Y+1)**2 (normally multiplied out). Note that the assignments X:=A+Y, etc, do not take place. At the present time, EXPRN1 must be a scalar expression. It cannot be a matrix expression, for example. This restriction will be removed some time in the future. 10.2 Where Operator ←←←←← ←←←←←←←← In defining expressions, it is often useful to name common sub-expressions locally within the scope of that expression. The infix operator WHERE may be used for this purpose. It syntax is: EXPRN WHERE VAR:identifier=EXPRN1[,VAR2=EXPRN2,...,VARN=EXPRNN] For example, X**2 + 2X + 3 WHERE X=Y would evaluate to Y**2 + 2*Y +3, if Y had no previous value. If more than one substitution equation occurs in a WHERE expression, the substitutions occur in parallel. In other words, the substitution is 10-2 performed by recursively walking down the tree representing EXPRN, and replacing every VARi found by the appropriate EXPRNi. The EXPRNi are not themselves searched for any occurrences of the various VARs. For example X**2+Y**3 WHERE X=Y,Y=X would evaluate to X**3 + Y**2. Although WHERE has a precedence less than any other infix operator, it still binds higher than keywords such as ELSE, THEN, DO, REPEAT and so on. Thus the expression IF A=2 THEN 3 ELSE A+2 WHERE A=3 will parse as IF A=2 THEN 3 ELSE (A+2 WHERE A=3). Unlike SUB, WHERE may be used to introduce auxiliary variables in symbolic mode expressions (q.v.). 10.3 Let Rules ←←← ←←←←← Unlike substitutions introduced via SUB or WHERE, LET rules are global in scope and stay in effect until replaced or CLEARed. The simplest use of the LET statement is in the form LET <substitution list> where <substitution list> is a list of rules separated by commas, each of the form: <variable> = <expression> or <prefix operator> (<argument>,...,<argument>) = <expression> or <argument> <infix operator>,..., <argument> = <expression> e.g. LET X = Y**2, H(U,V) = U - V, COS(PI/3) = 1/2, A*B = C, L+M = N, W**3 = 2*Z - 3, Z**10 = 0 (These could have been entered as seven separate LET statements.) After such LET rules have been input, X will always be evaluated as the square of Y, and so on. This is so even if at the time the LET rule was input, the variable Y had a value other than Y. (In contrast, the 10-3 assignment X:=Y**2 will set X equal to the square of the current value of Y, which could be quite different.) The rule LET A*B=C means that whenever A and B are both factors in an expression their product will be replaced by C. For example, A**5 * B**7 * W would be replaced by C**5 * B**2 * W. The rule of L+M will not only replace all occurrences of L+M by N, but will also normally replace L by N-M, but not M by N-L. A more complete description of this case is given in the section on substitutions for general expressions. The rule pertaining to W**3 will apply to any power of W greater than or equal to the third. Note especially the last example, LET Z**10=0. This declaration means, in effect: ignore the tenth or any higher power of Z. Such declarations, when appropriate, often speed up a computation to a considerable degree. (q.v. Asymptotic Commands for more details.) Any new operators occurring in such LET rules will be automatically declared OPERATOR by the system, if the rules are being read from a file. If they are being entered interactively, the system will ask DECLARE ... OPERATOR? . Answer Y or N and hit RETURN. In each of these examples, substitutions are only made for the explicit expressions given; i.e., none of the variables may be considered arbitrary in any sense. For example, the command LET H(U,V) = U - V; will cause H(U,V) to evaluate to U - V, but will not affect H(U,Z) or H with any arguments other than precisely the symbols U,V. These simple LET rules are on the same logical level as assignments made with the := operator. An assignment X := P+Q cancels a rule LET X = Y**2 made earlier, and vice versa. CAUTION: A recursive rule such as LET X = X + 1; is erroneous, since any subsequent evaluation of X will lead to a non- terminating chain of substitutions (and finally a stack overflow error): X ==> X + 1 ==> (X + 1) + 1 ==> ((X + 1) + 1) + 1 ==> ... Similarly, coupled substitutions such as LET L = M + N, N = L + R; will lead to the same error. 10-4 Array and matrix elements can appear on the left-hand side of a LET statement. However, because of their "instant evaluation" property, it is the value of the element that is substituted for, rather than the element itself. E.g., ARRAY A(5); A(2) := B; LET A(2) = C; results in B being substituted by C; the assignment for A(2) does not change. Finally, if an error occurs in any equation in a LET statement (including generalized statements involving FOR ALL and SUCH THAT), the remaining rules are not evaluated. 10.3.1 For All...Let ←←← ←←←←←←←←← If a substitution for all possible values of a given argument of an operator is required, the declaration FOR ALL (or FORALL) may be used. The syntax of such a command is FOR ALL <variable>,...,<variable> <LET statement> <terminator> e.g. FOR ALL X,Y LET H(X,Y) = X-Y; FOR ALL X LET K(X,Y) = X**Y; The first of these declarations would cause H(A,B) to be evaluated as A-B, H(U+V,U+W) to be V-W, etc. If the operator symbol H is used with more or fewer argument places, not two, the LET would have no effect, and no error would result. The second declaration would cause K(A,Y) to be evaluated as A**Y, but would have no effect on K(A,Z) since the rule didn't say FOR ALL Y ... . Where we used X and Y in the examples, any variables could have been used. This use of a variable doesn't affect the value it may have outside the LET statement. However, you should remember what variables you actually used. If you want to delete the rule subsequently, you must use the same variables in the CLEAR command (q.v.). It is possible to use more complicated expressions as a template for a LET statement, as explained in the section on substitutions for general expressions. In nearly all cases, the rule will be accepted, and a consistent application made by the system. However, if there is a sole constant or a sole free variable on the left-hand side of a rule (e.g., LET 2=3 or FOR ALL X LET X=2), then the system is unable to handle the rule, and the error message SUBSTITUTION FOR ... NOT ALLOWED will be issued. Any variable listed in the FOR ALL part will have its 10-5 symbol preceded by an equal sign: X in the above example will appear as =X. An error will also occur if a variable in the FOR ALL part is not properly matched on both sides of the LET equation. 10.3.2 For All...Such That...Let ←←← ←←←←←←←←←← ←←←←←←←←←← If a substitution is desired for more than a single value of a variable in an operator or other expression, but not all values, a conditional form of the FOR ALL ... LET declaration can be used. Example: FOR ALL X SUCH THAT NUMBERP X AND X<0 LET H(X)=0; will cause H(-5) to be evaluated as 0, but H of a positive integer, or of an argument which is not an integer at all, would not be affected. Any boolean expression can follow the SUCH THAT keywords. 10.3.3 Removing Assignments And Substitution Rules ←←←←←←←← ←←←←←←←←←←← ←←← ←←←←←←←←←←←← ←←←←← The user may remove all assignments and substitution rules from any expression by the command CLEAR, in the form CLEAR <expression>,...,<expression><terminator> e.g. CLEAR X, H(X,Y); Because of their "instant evaluation" property, array and matrix elements cannot be cleared with CLEAR. For example, if A is an array, you must say A(3) := 0; rather than CLEAR A(3); to "clear" element A(3). On the other hand, a whole array (or matrix) A can be cleared by the command CLEAR A; . This means much more than resetting to 0 all the elements of A. The fact that A is an array, and what its dimensions are, are forgotten, so A can be redefined as another type of object -- say, operator. The more general types of LET declarations can also be deleted by using CLEAR. Simply repeat the LET rule to be deleted, using CLEAR in place of LET, and omitting the equal sign and right-hand part. The same dummy variables must be used in the FOR ALL part, and the boolean expression in the SUCH THAT part must be written the same way. (The placing of blanks doesn't have to be identical.) 10-6 Example: The LET rule FOR ALL X SUCH THAT NUMBERP X AND X<0 LET H(X)=0; can be erased by the command FOR ALL X SUCH THAT NUMBERP X AND X<0 CLEAR H(X); 10.3.4 Overlapping Let Rules ←←←←←←←←←←← ←←← ←←←←← CLEAR is not the only way to delete a LET rule. A new LET rule identical to the first, but with a different expression after the equal sign, replaces the first. Replacements are also made in other cases where the existing rule would be in conflict with the new rule. For example, a rule for x**4 would replace a rule for x**5. The user should however be cautioned against having several LET rules in effect which relate to the same expression. No guarantee can be given as to which rules will be applied by REDUCE or in what order. It is best to CLEAR an old rule before entering a new related LET rule. 10.3.5 Substitutions For General Expressions ←←←←←←←←←←←←← ←←← ←←←←←←← ←←←←←←←←←←← The examples of substitutions discussed in other sections have involved very simple rules. However, the substitution mechanism used in REDUCE is very general, and can handle arbitrarily complicated rules without difficulty. The general substitution mechanism used in REDUCE is discussed in Hearn, A. C., "REDUCE, A User-Oriented Interactive System for Algebraic Simplification," Interactive Systems for Experimental Applied Mathematics, (edited by M. Klerer and J. Reinfelds), Academic Press, New York (1968), 79-90, and Hearn. A. C., "The Problem of Substitution," Proc. 1968 Summer Institute on Symbolic Mathematical Computation, IBM Programming Laboratory Report FSC 69-0312 (1969). For the reasons given in these references, REDUCE does not attempt to implement a general pattern matching algorithm. However, the present system uses far more sophisticated techniques than those discussed in the above papers. It is now possible for the rules appearing in arguments of LET to have the form <substitution expression> = <expression> where any rule to which a sensible meaning can be assigned is permitted. However, this meaning can vary according to the form of <substitution expression>. The semantic rules associated with the application of the substitution are completely consistent, but somewhat complicated by the pragmatic need to perform such substitutions as efficiently as possible. The following rules explain how the majority of the cases are handled. 10-7 To begin with, the <substitution expression> is first partly simplified by collecting like terms and putting identifiers (and kernels) in the system order. However, no substitutions are performed on any part of the expression with the exception of expressions with the "instant evaluation" property, such as array and matrix elements, whose actual values are used. It should also be noted that the system order used is not changeable by the user, even with the KORDER command. Specific cases are then handled as follows: (1) If the resulting simplified rule has a left-hand side which is an identifier, an expression with a top-level algebraic operator or a power, then the rule is added without further change to the appropriate table. (2) If the operator * appears at the top level of the simplified left-hand side, then any constant arguments in that expression are moved to the right-hand side of the rule. The remaining left-hand side is then added to the appropriate table. For example, LET 2*X*Y=3 becomes LET X*Y=3/2, so that X*Y is added to the product substitution table, and when this rule is applied, the expression X*Y becomes 3/2, but X or Y by themselves are not replaced. (3) If the operators +, - or / appear at the top level of the simplified left-hand side, all but the first term is moved to the right-hand side of the rule. Thus the rules LET L+M=N, X/2=Y, A-B=C become LET L=N-M, X=2*Y, A=C+B. One problem that can occur in this case is that if a quantified expression is moved to the right-hand side, a given free variable might no longer appear on the left-hand side, resulting in an error because of the unmatched free variable. E.g., FOR ALL X,Y LET F(X)+F(Y)=X*Y would become FOR ALL X,Y LET F(X)=X*Y-F(Y), which no longer has X on both sides. The fact that array and matrix elements are evaluated in the left-hand side of rules can lead to confusion at times. Consider for example the 10-8 statements ARRAY A(5); LET X+A(2)=3; LET A(3)=4; The left-hand side of the first rule will become X, and the second 0. Thus the first rule will be instantiated as a substitution for X, and the second will result in an error. The order in which a set of rules is applied is not easily understandable without a detailed knowledge of the system simplification protocol. It is also possible for this order to change from release to release, as improved substitution techniques are implemented. Users should therefore assume that the order of application of rules is arbitrary, and program accordingly. After a substitution has been made, the expression being evaluated is reexamined in case a new allowed substitution has been generated. This process is continued until no more substitutions can be made. However, this is sometimes undesirable. For example, if one wishes to integrate a polynomial with respect to X by a rule of the form FOR ALL N LET X**N = X**(N+1)/(N+1); one only wants the substitution to be made once. (Otherwise X**2 would become X**3/3 which would then become X**4/12 and so on). This resubstitution for a given rule can be inhibited by turning off the switch RESUBS (which is normally on). RESUBS may also inhibit subsequent applications of other rules, but because of the complexity of the substitution mechanisms, it it still possible that several different rules will be applied even with RESUBS on. As mentioned elsewhere, when a substitution expression appears in a product, the substitution is made if that expression divides the product. For example, the rule LET A**2*C = 3*Z; would cause A**2*C*X to be replaced by 3*Z*X and A**2*C**2 by 3*Z*C. If the substitution is desired only when the substitution expression appears in a product with the explicit powers supplied in the rule, the command MATCH should be used instead. For example, MATCH A**2*C = 3*Z; would cause A**2*C*X to be replaced by 3*Z*X, but A**2*C**2 would not be replaced. MATCH can also be used with the FOR ALL constructions described above. To remove substitution rules of the type discussed in this section, the CLEAR command can be used, combined, if necessary, with the same FOR ALL clause with which the rule was defined, for example: 10-9 FOR ALL X CLEAR LOG(E**X),E**LOG(X),COS(W*T+THETA(X)); Note, however, that the arbitrary variable names in this case MUST be the same as those used in defining the substitution. 10.4 Asymptotic Commands ←←←←←←←←←← ←←←←←←←← In expansions of polynomials involving variables which are known to be small, it is often desirable to throw away all powers of these variables beyond a certain point to avoid unnecessary computation. The command LET may be used to do this. For example, if only powers of X up to X**7 are needed, the command LET X**8 = 0; will cause the system to delete all powers of X higher than 7. CAUTION: This particular simplification works differently from most substitution mechanisms in REDUCE in that it is applied during polynomial manipulation rather than to the whole evaluated expression. Thus, with the above rule in effect, x**10/x**5 would give the result zero, since the numerator would simplify to zero. Similarly x**20/x**10 would give a ZERO DENOMINATOR error message, since both numerator and denominator would first simplify to zero. The method just described is not adequate when expressions involve several variables having different degrees of smallness. In this case, it is necessary to supply an asymptotic weight to each variable and count up the total weight of each product in an expanded expression before deciding whether to keep the term or not. There are two associated commands in the system to permit this type of asymptotic constraint. The command WEIGHT takes a list of equations of the form <kernel form> = <number>, where <number> must be a positive integer (not just evaluate to a positive integer). This command assigns the weight <number> to the relevant kernel form. A check is then made in all algebraic evaluations to see if the total weight of the term is greater than the weight level assigned to the calculation. If it is, the term is deleted. To compute the total weight of a product, the individual weights of each kernel form are multiplied by their corresponding powers and then added. The weight level of the system is initially set to 2. The user may change this setting by the command WTLEVEL <number>; which sets <number> as the new weight level of the system. Again, <number> must be a positive integer. 11-1 11. FILE HANDLING COMMANDS ←←←← ←←←←←←←← ←←←←←←←← In many applications, it is desirable to load previously prepared REDUCE files into the system, or to write output on other files. REDUCE offers four commands for this purpose, namely, IN, OUT, SHUT and LOAD. The first three operators are described here; LOAD is discussed in another section. 11.1 In Command ←← ←←←←←←← This command takes a list of file names as argument and directs the system to input each file (which should contain REDUCE statements and commands) into the system. File names can either be an identifier or a string. The explicit format of these will be system dependent and, in many cases, site dependent. The explicit instructions for the implementation being used should therefore be consulted for further details. e.g. IN F1,"GGG.RR.S"; will first load file F1, then GGG.RR.S. When a semicolon is used as the terminator of the IN statement, the statements in the file are echoed on the terminal or written on the current output file. If $ or ESCAPE is used as the terminator, the input is not shown. Echoing of all or part of the input file can be prevented, even if a semicolon was used, by placing an OFF ECHO; command in the input file. Files to be read using IN should end with ;END;. (Note the two semicolons!) First of all, this is protection against obscure difficulties the user will have if there are, by mistake, more BEGINs than ENDs on the file. Secondly, it triggers some file control book-keeping which may improve system efficiency. If END is omitted, an error message "End-of-file read" will occur. 11.2 Out Command ←←← ←←←←←←← This command takes a single file name as argument, and directs output to that file from then on, until another OUT changes the output file, or SHUT closes it. Output can go to only one file at a time, although many can be open. If the file has previously been used for output during the current job, and not SHUT, the new output is appended to the end of the file. Any existing file is erased before its first use for output in a job, or if had been SHUT before the new OUT. To output on the terminal without closing the output file, the reserved file name T (for terminal) may be used. e.g. OUT OFILE; will direct output to the file OFILE and OUT T; will direct output to the user's terminal. The output sent to the file will be in the same form that it would have on the terminal. In particular X**2 would appear on two lines, an X on the 11-2 lower line and a 2 on the line above. If the purpose of the output file is to save results to be read in later, this is not an appropriate form. We first must turn off the NAT switch which specifies that output should be in standard mathematical notation. Example: To create a file ABCD from which it will be possible to read -- using IN -- the value of the expression XYZ: OFF ECHO$ % needed if your input is from a file. OFF NAT$ % output in IN-readable form. Each expression % printed will end with a $ . OUT ABCD$ % output to new file LINELENGTH 72$ % needed in those systems with fixed input line length. XYZ:=XYZ; % will output "XYZ := " followed by the value % of XYZ WRITE ";END"$ % standard for ending files for IN SHUT ABCD$ % save ABCD, return to terminal output ON NAT$ % restore usual output form 11.3 Shut Command ←←←← ←←←←←←← This command takes a list of names of files which have been previously opened via an "OUT" statement and closes them. Most systems require this action by the user before he ends the REDUCE job (if not sooner), otherwise the output may be lost. If a file is shut and a further OUT command issued for the same file, the file is erased before the new output is written. If it is the current output file which is shut, output will switch to the terminal. Attempts to shut files that have not been opened by "OUT", or an input file will lead to errors. 12-1 12. COMMANDS FOR INTERACTIVE USE OF REDUCE ←←←←←←←← ←←← ←←←←←←←←←←← ←←← ←← ←←←←←← REDUCE is designed as an interactive system, but naturally it can also operate in a batch processing or background mode by taking its input command by command from the relevant input stream. There is a basic difference, however, between interactive and batch use of the system. In the former case, whenever the system discovers an ambiguity at some point in a calculation, such as a forgotten type assignment for instance, it asks the user for the correct interpretation. In batch operation, it is not practical to terminate the calculation at such points and require resubmission of the job, so the system makes the most obvious guess of the user's intentions and continues the calculation. There is also a difference in the handling of errors. In the former case, the computation can continue since the user has the opportunity to correct the mistake. In batch mode, the error may lead to consequent erroneous (and possibly time consuming) computations. So in the default case, no further evaluation occurs, although the remainder of the input is checked for syntax errors. A message "Continuing with parsing only" informs the user that this is happening. On the other hand, the switch ERRCONT, if on, will cause the system to continue evaluating expressions after such errors occur. When a syntactical error occurs, the place where the system detected the error is marked with three dollar signs ($$$). In interactive mode, the user can then use ED to correct the error, or retype the command. When a non-syntactical error occurs in interactive mode, the command being evaluated at the time the last error occurred is saved, and may later be reevaluated by the command RETRY. 12.1 Referencing Previous Results ←←←←←←←←←←← ←←←←←←←← ←←←←←←← It is often useful to be able to reference results of previous computations during a REDUCE session. For this purpose, REDUCE maintains a history of all interactive inputs and the results of all interactive computations during a given session. These results are referenced by the command number that REDUCE prints automatically in interactive mode. To use an input expression in a new computation, one writes INPUT(n), where n is the command number. To use an output expression, one writes WS(n). WS references the previous command. E.g., if command number 1 was int(x-1,x); and the result of command number 7 was X-1, then 2*input(1)-ws(7)**2; would give the result -1, whereas 2*ws(1)-ws(7)**2; would yield the same result, but WITHOUT a recomputation of the integral. The operator DISPLAY is available to display previous inputs. If its 12-2 argument is a positive integer, n say, then the previous n inputs are displayed. If its argument is ALL (or in fact any non-numerical expression), then all previous inputs are displayed. 12.2 Interactive Editing ←←←←←←←←←←← ←←←←←←← It is possible when working interactively to edit any REDUCE input that comes from the user's terminal, and also some user-defined procedure definitions. At the top level, one can access any previous command string by the command ED(n), where n is the desired command number as prompted by the system in interactive mode. ED; (i.e. no argument) accesses the previous command. After ED has been called, you can now edit the displayed string using a string editor with the following commands: B move pointer to beginning C<character> replace next character by <character> D delete next character E end editing and reread text F<character> move pointer to next occurrence of <character> I<string><escape> insert <string> in front of pointer K<character> delete all chars until <character> P print string from current pointer Q give up with error exit S<string><escape> search for first occurrence of <string> positioning pointer just before it <space> or X move pointer right one char. The above table can be displayed online by typing a question mark followed by a carriage return to the editor. The editor prompts with an angle bracket. Commands can be combined on a single line, and all command sequences must be followed by a carriage return to become effective. Thus, to change the command X := A+1; to X := A+2;, and cause it to be executed, the following edit command sequence could be used: F1C2E<return>. The interactive editor may also be used to edit a user-defined procedure that has not been compiled (q.v.). To do this, one says: EDITDEF <id>; where <id> is the name of the procedure. The procedure definition will then be displayed in editing mode, and may then be edited and redefined on exiting from the editor. 12-3 12.3 Interactive File Control ←←←←←←←←←←← ←←←← ←←←←←←← If input is coming from an external file, the system treats it as a batch processed calculation. If the user desires interactive response in this case, he can include the command ON INT; in the file. Likewise, he can issue the command OFF INT; in the main program if he does not desire continual questioning from the system. Regardless of the setting of INT, input commands from a file are not kept in the system, and so can not be edited using ED. However, many implementations of REDUCE provide a link to an external system editor that can be used for such editing. The specific instructions for the particular implementation should be consulted for information on this. Two commands are available in REDUCE for interactive use of files. PAUSE; may be inserted at any point in an input file. When this command is encountered on input, the system prints the message CONT? on the user's terminal and halts. If the user responds Y (for yes), the calculation continues from that point in the file. If the user responds N (for no), control is returned to the terminal, and the user can input further statements and commands. Later on he can use the command CONT; to transfer control back to the point in the file following the last PAUSE encountered. A top-level PAUSE; from the user's terminal has no effect. 13-1 13. MATRIX CALCULATIONS ←←←←←← ←←←←←←←←←←←← A very powerful feature of the REDUCE system is the ease with which matrix calculations can be performed. To extend our syntax to this class of calculations we need to add another prefix operator, MAT, and a further variable and expression type as follows: 13.1 Mat Operator ←←← ←←←←←←←← This prefix operator is used to represent n x m matrices. MAT has n arguments interpreted as rows of the matrix, each of which is a list of m expressions representing elements in that row. For example, the matrix (A B C) ( ) (D E F) would be written as MAT ((A,B,C),(D,E,F)). Note that the single column matrix (X) (Y) becomes MAT((X),(Y)). The inside parentheses are required to distinguish it from the single row matrix (X Y) which would be written as MAT((X,Y)). 13.2 Matrix Variables ←←←←←← ←←←←←←←←← An identifier may be declared a matrix variable by the declaration MATRIX. The size of the matrix may be declared explicitly in the matrix declaration, or by default in assigning such a variable to a matrix expression. e.g. MATRIX X(2,1),Y(3,4),Z; declares X to be a 2 x 1 (column) matrix, Y to be a 3 x 4 matrix and Z a matrix whose size is declared later by default. Matrix declarations can appear anywhere in a program. Once a symbol is declared to name a matrix, it can not also be used to name an array, operator or a procedure, or used as an ordinary variable. It can however be re-declared to be a matrix, and its size may be changed at that time. Matrices once declared are global in scope, and so can then be referenced anywhere in the program. In other words, a declaration within a block (or a procedure) does not limit the scope of the matrix to that block, nor does 13-2 the matrix go away on exiting the block (use CLEAR instead for this purpose). An element of a matrix is referred to in the expected manner; thus X(1,1) gives the first element of the matrix X defined above. References to elements of a matrix whose size has not yet been declared leads to an error. All elements of a matrix whose size is declared are initialized to 0. As a result, a matrix element has an "instant evaluation" property and cannot stand for itself. If this is required, then an operator (q.v.) should be used to name the matrix elements as in: MATRIX M; OPERATOR X; M := MAT((X(1,1),X(1,2)); 13.3 Matrix Expressions ←←←←←← ←←←←←←←←←←← These follow the normal rules of matrix algebra as defined by the following syntax: <matrix expression> ::= MAT<matrix description>|<matrix variable>| <scalar expression>*<matrix expression>| <matrix expression>*<matrix expression> <matrix expression>+<matrix expression>| <matrix expression>**<integer>| <matrix expression>/<matrix expression> Sums and products of matrix expressions must be of compatible size otherwise an error will result during their evaluation. Similarly, only square matrices may be raised to a power. A negative power is computed as the inverse of the matrix raised to the corresponding positive power. A/B is interpreted as A*B**(-1). Examples: Assuming X and Y have been declared as matrices, the following are matrix expressions Y Y**2*X-3*Y**(-2)*X Y+ MAT((1,A),(B,C))/2 The computation of the quotient of two matrices normally uses a two-step elimination method due to Bareiss. An alternative method using Cramer's method is also available. This is often more efficient than the Bareiss method, although we have no solid statistics on this yet. To use Cramer's method instead, the switch CRAMER should be turned on. 13.4 Operators With Matrix Arguments ←←←←←←←←← ←←←← ←←←←←← ←←←←←←←←← The operator LENGTH (q.v.) applied to a matrix returns a list of the number of rows and columns in the matrix. Three additional operators are useful in matrix calculations, namely DET, TP and TRACE defined as follows 13-3 13.4.1 Det Operator ←←← ←←←←←←←← Syntax: DET(EXPRN:matrix←expression):algebraic. The operator DET is used to represent the determinant of a square matrix expression. e.g. DET(Y**2) is a scalar expression whose value is the determinant of the square of the matrix Y, and DET MAT((A,B,C),(D,E,F),(G,H,J)); is a scalar expression whose value is the determinant of the matrix ( A B C ) ( ) ( D E F ) ( ) ( G H J ). 13.4.2 Tp Operator ←← ←←←←←←←← Syntax: TP(EXPRN:matrix←expression):matrix. This operator takes a single matrix argument and returns its transpose. 13.4.3 Trace Operator ←←←←← ←←←←←←←← Syntax: TRACE(EXPRN:matrix←expression):algebraic. The operator TRACE is used to represent the trace of a square matrix. 13.5 Matrix Assignments ←←←←←← ←←←←←←←←←←← Matrix expressions may appear in the right-hand side of assignment statements. If the left-hand side of the assignment, which must be a variable, has not already been declared a matrix, it is declared by default to the size of the right-hand side. The variable is then set to the value of the right-hand side. Such an assignment may be used very conveniently to find the solution of a set of linear equations. For example, to find the solution of the following set of equations A11*X(1) + A12*X(2) = Y1 A21*X(1) + A22*X(2) = Y2 we simply write 13-4 X := 1/MAT((A11,A12),(A21,A22))*MAT((Y1),(Y2)); 13.6 Evaluating Matrix Elements ←←←←←←←←←← ←←←←←← ←←←←←←←← Once an element of a matrix has been assigned, it may be referred to in standard array element notation. Thus Y(2,1) refers to the element in the second row and first column of the matrix Y. 14-1 14. PROCEDURES ←←←←←←←←←← It is often useful to name a statement for repeated use in calculations with varying parameters, or to define a complete evaluation procedure for an operator. REDUCE offers a procedural declaration for this purpose. Its general syntax is: [<procedural type>] PROCEDURE <name>[<varlist>];<statement>; and <varlist> ::= (<variable>,...,<variable>) This will be explained more fully in the following sections. In the algebraic mode of REDUCE the <procedure type> can be omitted, since the default is ALGEBRAIC. Procedures of type INTEGER or REAL may also be used. In the former case, the system checks to ensure that the input parameters and value of the procedure are integers. At present, such checking is not done for a real procedure, although this will change in the future when a more complete type checking mechanism is installed. Users should therefore only use these types when appropriate. An empty variable list may also be omitted. All procedures are automatically declared to be operators on definition. In order to allow users relatively easy access to the whole REDUCE source program, system procedures are not protected against user redefinition. If a procedure is redefined, a message *** <procedure name> REDEFINED is printed. If this occurs, and the user is not redefining his own procedure, he is well advised to rename it, and possibly start over (because he has ALREADY redefined some internal procedure whose correct functioning may be required for his job!) All required procedures should be defined at the top level, since they have global scope throughout a program. In particular, an attempt to define a procedure within a procedure will cause an error to occur. 14.1 Procedure Heading ←←←←←←←←← ←←←←←←← Each procedure has a heading consisting of the word PROCEDURE (optionally preceded by the word ALGEBRAIC), followed by the name of the procedure to be defined, and followed by its formal parameters -- the symbols which will be used in the body of the definition to illustrate what is to be done. There are three cases: 1) No parameters. Simply follow the procedure name with a terminator (semicolon or dollar sign or ESCAPE). PROCEDURE ABC; 14-2 When such a procedure is used in an expression or command, ABC(), with empty parentheses, must be written. 2) One parameter. Enclose it in parentheses OR just leave at least one space, then follow with a terminator. PROCEDURE ABC(X); or PROCEDURE ABC X; 3) More than one parameter. Enclose them in parentheses, separated by commas, then follow with a terminator. PROCEDURE ABC(X,Y,Z); Referring to the last example, if later in some expression being evaluated the symbols ABC(U,P*Q,123) appear, the operations of the procedure body will be carried out as if X had the same value as U does, Y the same value as P*Q does, and Z the value 123. The values of X, Y, Z, after the procedure body operations are completed are unchanged. So, normally, are the values of U, P, Q, and (of course) 123. (This is technically referred to as call by value.) The reader will have noted the word "normally" a few lines earlier. The call by value protections can be bypassed if necessary, as described elsewhere. 14.2 Procedure Body ←←←←←←←←← ←←←← Following the delimiter which ends the procedure heading must be a SINGLE statement defining the action to be performed or the value to be delivered. A terminator must follow the statement. If it is a semicolon, the name of the procedure just defined is printed. It is not printed if dollar sign or ESCAPE is used. If the result wanted is given by a formula of some kind, the body is just that formula, using the variables in the procedure heading. Simple Example: If F(X) is to mean (X+5)*(X+6)/(X+7), the entire procedure definition could read PROCEDURE F X; (X+5)*(X+6)/(X+7); Then F(10) would evaluate to 240/17, F(A-6) to A*(A-1)/(A+1), and so on. More Complicated Example: Suppose we need a function P(N,X) which, for any positive integer N, is the Legendre polynomial of order N. We can define this operator using the textbook formula defining these functions: 14-3 n | 1 d 1 | p (x) = --- --- ---------------| n n! n 2 1/2| dy (y -2*x*y+1) | y=0 Put into words, the Legendre polynomial P(N,X) is the result of substituting Y=0 in the Nth partial derivative with respect to Y of a certain fraction involving X and Y, then dividing that by N factorial. This verbal formula can easily be written in REDUCE: PROCEDURE P(N,X); SUB(Y=0,DF(1/(Y**2-2*X*Y+1)**(1/2),Y,N)) /(FOR I:=1:N PRODUCT I); Having input this definition, the expression evaluation 2*P(2,W); would result in the output 2 3*W - 1 . If the desired process is best described as a series of steps, then a group or compound statement can be used. Example: The above Legendre polynomial example can be rewritten as a series of steps instead of a single formula as follows: PROCEDURE P(N,X); BEGIN SCALAR SEED,DERIV,TOP,FACT; SEED:=1/(Y**2 - 2*X*Y +1)**(1/2); DERIV:=DF(SEED,Y,N); TOP:=SUB(Y=0,DERIV); FACT:=FOR I:=1:N PRODUCT I; RETURN TOP/FACT END; Procedures may also be defined recursively. In other words, the procedure body can include references to the procedure name itself, or to other procedures which themselves reference the given procedure. As an example, we can define the Legendre polynomial through its standard recurrence relation: PROCEDURE P(N,X); IF N<0 THEN REDERR "Invalid argument to P(N,X)" ELSE IF N=0 THEN 1 ELSE IF N=1 THEN X ELSE ((2*N-1)*X*P(N-1,X)-(N-1)*P(N-2,X))/N; 14-4 The operator REDERR in the above example provides for a simple error exit from an algebraic procedure (and also a block). It takes a string as argument. It should be noted however that all the above definitions of P(N,X) are quite inefficient if extensive use is to be made of such polynomials, since each call effectively recomputes all lower order polynomials. It would be better to store these expressions in an array, and then use say the recurrence relation to compute only those polynomials that have not already been derived. We leave it as an exercise for the reader to write such a definition. 14.3 Using Let Inside Procedures ←←←←← ←←← ←←←←←← ←←←←←←←←←← By using LET instead of an assignment in the procedure body it is possible to bypass the call-by-value protection. If X is a formal parameter or local variable of the procedure (i.e. is in the heading or in a SCALAR declaration), and LET is used instead of := to make an assignment to X, e.g. LET X = 123; then it is the variable which is the value of X that is changed. This effect also occurs with local variables defined in a block. If the value of X is not a variable, but a more general expression, then it is that expression that is used on the left-hand side of the LET statement. For example, if X has the value P*Q, it is as if LET P*Q = 123 has been executed. 14.4 Let Rules As Procedures ←←← ←←←←← ←← ←←←←←←←←←← The LET statement offers an alternative syntax and semantics for procedure definition. In place of PROCEDURE ABC (X,Y,Z); <procedure body>; one can write FOR ALL X,Y,Z LET ABC(X,Y,Z) = <procedure body>; There are several differences to note. If the procedure body contains an assignment to one of the formal parameters, e.g. X:=123; in the PROCEDURE case it is a variable holding a copy of the first actual 14-5 argument which is changed. The actual argument is not changed. In the LET case, the actual argument is changed. Thus, if ABC is defined using LET, and ABC(U,V,W) is evaluated, the value of U changes to 123. That is, the LET form of definition allows the user to bypass the protections which are enforced by the call by value conventions of standard PROCEDURE definitions. Example: We take our earlier FACTORIAL procedure and write it as a LET statement. FOR ALL N LET FACTORIAL N = BEGIN SCALAR M,S; M:=1; S:=N; L1: IF S=0 THEN RETURN M; M:=M*S; S:=S-1; GO TO L1 END; The reader will notice that we introduced a new local variable, S, and set it equal to N. The original form of the procedure contained the statement N:=N-1;. If the user asked for the value of FACTORIAL (5) then N would correspond to -- not just have the value of -- 5, and REDUCE would object to trying to execute the statement 5:=5-1. If PQR is a procedure with no parameters, PROCEDURE PQR; <procedure body>; it can be written as a LET statement quite simply: LET PQR = <procedure body>; To call "procedure" PQR if defined in the latter form, the empty parentheses would not be used: use PQR not PQR() where a call on the procedure is needed. The two notations for a procedure with no arguments can be combined. PQR can be defined in the standard PROCEDURE form. Then a LET statement LET PQR = PQR(); would allow a user to use PQR instead of PQR() in calling the procedure. A feature available with LET-defined procedures and not with procedures defined in the standard way is the possibility of defining partial functions. FOR ALL X SUCH THAT NUMBERP X LET UVW(X) = <procedure body); 14-6 Now UVW of an integer would be calculated as prescribed by the procedure body, while UVW of a general argument, such as Z or P+Q (assuming these evaluate to themselves) would simply stay UVW(Z) or UVW(P+Q) as the case may be. 15-1 15. USER CONTRIBUTED PACKAGES ←←←← ←←←←←←←←←←← ←←←←←←←← The complete REDUCE system includes a library of packages that have been contributed by users. These packages are unsupported, but are provided with the REDUCE distribution as a service to the user community. All questions regarding these packages should therefore be directed to their individual authors, who are solely responsible for their maintenance and development. In order to emphasize the unsupported nature of these packages, they must be specifically loaded before they can be used. The relevant command is LOAD "<package name>"; although this syntax may vary from implementation to implementation. The user notes for the specific version you are using should therefore be consulted for details on how to do this. Each package comes with its own documentation and test file, which is included, along with the source of the package, in the REDUCE system distribution. These items should be studied for details on the use of any particular package. We also list below the packages available in the current release of REDUCE, together with a paragraph describing their capabilities. 15.1 Algint: Indefinite Integration Of Square Roots ←←←←←←← ←←←←←←←←←← ←←←←←←←←←←← ←← ←←←←←← ←←←←← This package, which is an extension of the basic integration package distributed with REDUCE, will analytically integrate a wide range of expressions involving square roots, but not if the square roots involve not-sqrt functions such as sin, log, etc. Author: James H. Davenport. 15.2 Anum: An Algebraic Number Package ←←←←← ←← ←←←←←←←←← ←←←←←← ←←←←←←← This package provides facilities for handling algebraic numbers as polynomial coefficients in REDUCE calculations. It includes facilities for introducing indeterminates to represent algebraic numbers, for calculating splitting fields, and for factoring and finding greatest common divisors in such domains. Author: Eberhard Schruefer. 15.3 Excalc: A Differential Geometry Package ←←←←←←← ← ←←←←←←←←←←←← ←←←←←←←← ←←←←←←← EXCALC is designed for easy use by all who are familiar with the calculus of Modern Differential Geometry. The program is currently able to handle scalar-valued exterior forms, vectors and operations between them, as well 15-2 as non-scalar valued forms (indexed forms). It is thus an ideal tool for studying differential equations, doing calculations in general relativity and field theories, or doing simple things such as calculating the Laplacian of a tensor field for an arbitrary given frame. Author: Eberhard Schruefer. 15.4 Gentran: A Code Generation Package ←←←←←←←← ← ←←←← ←←←←←←←←←← ←←←←←←← GENTRAN is an automatic code GENerator and TRANslator. It constructs complete numerical programs based on sets of algorithmic specifications and symbolic expressions. Formatted FORTRAN, RATFOR or C code can be generated through a series of interactive commands or under the control of a template processing routine. Large expressions can be automatically segmented into subexpressions of manageable size, and a special file-handling mechanism maintains stacks of open I/O channels to allow output to be sent to any number of files simultaneously and to facilitate recursive invocation of the whole code generation process. Author: Barbara L. Gates. 15.5 Groebner: Groebner Basis Computation ←←←←←←←←← ←←←←←←←← ←←←←← ←←←←←←←←←←← GROEBNER is a package for the computation of Groebner Bases using the Buchberger algorithm. It can be used over a variety of different coefficient domains, and for different variable and term orderings. Authors: Ruediger Gebauer, Anthony C. Hearn and M. Moeller. 15.6 Spde: A Package For Finding Symmetry Groups Of Pde'S ←←←←← ← ←←←←←←← ←←← ←←←←←←← ←←←←←←←← ←←←←←← ←← ←←←←← The package SPDE provides a set of functions which may be used to determine the symmetry group of Lie- or point-symmetries of a given system of partial differential equations. In many cases the determining system is solved completely automatically. In other cases the user has to provide additional input information for the solution algorithm to terminate. Author: Fritz Schwarz. 16-1 16. SYMBOLIC MODE ←←←←←←←← ←←←← At the system level, REDUCE is based on a version of the programming language LISP known as Standard LISP which is described in J. Marti, Hearn, A. C., Griss, M. L. and Griss, C., "Standard LISP Report" SIGPLAN Notices, ACM, New York, 14, No 10 (1979) 48-68. We shall assume in this section that the reader is familiar with the material in that paper. This also assumes implicitly that the reader has a reasonable knowledge about LISP in general, say at the level of the LISP 1.5 Programmer's Manual (McCarthy, J., Abrahams, P. W., Edwards, D. J., Hart, T. P. and Levin, M. I., "LISP 1.5 Programmer's Manual", M.I.T. Press, 1965) or any of the books mentioned at the end of this section. Persons unfamiliar with this material will have some difficulty understanding this section. Although REDUCE is designed primarily for algebraic calculations, its source language is general enough to allow for a full range of LISP-like symbolic calculations. To achieve this generality, however, it is necessary to provide the user with two modes of evaluation, namely an algebraic mode and a symbolic mode. To enter symbolic mode, the user types SYMBOLIC; (or LISP;) and to return to algebraic mode he types ALGEBRAIC;. Evaluations proceed differently in each mode so the user is advised to check what mode he is in if a puzzling error arises. He can find his mode by typing !*MODE; The current mode will then be printed as ALGEBRAIC or SYMBOLIC. Expression evaluation may proceed in either mode at any level of a calculation, provided the results are passed from mode to mode in a compatible manner. One simply prefixes the relevant expression by the appropriate mode. If the mode name prefixes an expression at the top level, it will then be handled as if the global system mode had been changed for the scope of that particular calculation. For example, if the current mode is ALGEBRAIC, then the commands SYMBOLIC CAR '(A); X+Y; will cause the first expression to be evaluated and printed in symbolic mode and the second in algebraic mode. Only the second evaluation will thus affect the expression workspace. On the other hand, the statement X + SYMBOLIC CAR '(12); will result in the algebraic value X+12. The use of SYMBOLIC (and equivalently ALGEBRAIC) in this manner is the same as any operator. That means that parentheses could be omitted in the above examples since the meaning is obvious. In other cases, parentheses must be used, as in 16-2 SYMBOLIC(X := 'A); Omitting the parentheses, as in SYMBOLIC X := A; would be wrong, since it would parse as SYMBOLIC(X) := A; For convenience, it is assumed that any operator whose FIRST argument is quoted is being evaluated in symbolic mode, regardless of the mode in effect at that time. Thus, the first example above could be equally well written: CAR '(A); Except where explicit limitations have been made, most REDUCE algebraic constructions carry over into symbolic mode. However, there are some differences. First, expression evaluation now becomes LISP evaluation. Secondly, assignment statements are handled differently, as we discuss shortly. Thirdly, local variables and array elements are initialized to NIL rather than 0. (In fact, any variables not explicitly declared INTEGER are also initialized to NIL in algebraic mode, but the algebraic evaluator recognizes NIL as 0.) Finally, function definitions follow the conventions of Standard LISP. To begin with, we mention a few extensions to our basic syntax which are designed primarily if not exclusively for symbolic mode. 16.1 Symbolic Infix Operators ←←←←←←←← ←←←←← ←←←←←←←←← There are four binary infix operators in REDUCE intended for use in symbolic mode, namely . (CONS), EQ, MEMBER and MEMQ. The precedence of these operators was given in another section. 16.2 Symbolic Expressions ←←←←←←←← ←←←←←←←←←←← These consist of scalar variables and operators and follow the normal rules of the LISP meta language. Examples: X CAR U . REVERSE V SIMP (U+V**2) 16-3 16.3 Quoted Expressions ←←←←←← ←←←←←←←←←←← Because symbolic evaluation requires that each variable or expression has a value, it is necessary to add to REDUCE the concept of a quoted expression by analogy with the LISP QUOTE function. This is provided by the single quote mark '. e.g. 'A represents the LISP S-expression (QUOTE A) '(A B C) represents the LISP S-expression (QUOTE (A B C)) Note, however, that strings are constants and therefore evaluate to themselves in symbolic mode. Thus, to print the string "A String", one would write PRIN2 "A String"; Within a quoted expression, identifier syntax rules are those of REDUCE. Thus ( A !. B) is the list consisting of the three elements A, . and B, whereas (A . B) is the dotted pair of A and B. 16.4 Lambda Expressions ←←←←←← ←←←←←←←←←←← LAMBDA expressions provide the means for constructing LISP LAMBDA expressions in symbolic mode. They may not be used in algebraic mode. Syntax: <LAMBDA expression> ::= LAMBDA <varlist><terminator><statement> where <varlist> ::= (<variable>,...,<variable>) e.g. LAMBDA (X,Y); CAR X . CDR Y is equivalent to the LISP LAMBDA expression (LAMBDA (X Y) (CONS (CAR X) (CDR Y))) The parentheses may be omitted in specifying the variable list if desired. LAMBDA expressions may be used in symbolic mode in place of prefix operators, or as an argument of the reserved word FUNCTION. In those cases where a LAMBDA expression is used to introduce local variables to avoid recomputation, a WHERE statement can also be used. For example, the expression (LAMBDA (X,Y); LIST(CAR X,CDR X,CAR Y,CDR Y)) (REVERSE U,REVERSE V) can also be written LIST(CAR X,CDR X,CAR Y,CDR Y) WHERE X=REVERSE U,Y=REVERSE V . 16-4 16.5 Symbolic Assignment Statements ←←←←←←←← ←←←←←←←←←← ←←←←←←←←←← In symbolic mode, if the left side of an assignment statement is a variable, a SETQ of the right-hand side to that variable occurs. If the left-hand side is an expression, it must be of the form of an array element, otherwise an error will result. e.g. X:=Y translates into (SETQ X Y) whereas A(3) := 3 will be valid if A has been previously declared a single dimensioned array of at least four elements. 16.6 For Each Statement ←←← ←←←← ←←←←←←←←← The FOR EACH form of the FOR statement, designed for iteration down a list, is more general in symbolic mode. Its syntax is: FOR EACH ID:identifier {IN|ON} LST:list {DO|COLLECT|JOIN|PRODUCT|SUM} EXPRN:S-expr As in algebraic mode, if the keyword IN is used, iteration is on each element of the list. With ON, iteration is on the whole list remaining at each point in the iteration. As a result, we have the following equivalence between each form of FOR EACH and the various mapping functions in LISP: | DO COLLECT JOIN ----|-------------------------- IN | MAPC MAPCAR MAPCAN ON | MAP MAPLIST MAPCON Example: To list each element of the list (A B C): FOR EACH X IN '(A B C) COLLECT LIST X; 16.7 Symbolic Procedures ←←←←←←←← ←←←←←←←←←← All the functions described in the Standard LISP Report are available to users in symbolic mode. Additional functions may also be defined as symbolic procedures. For example, to define the LISP function ASSOC, the following could be used: SYMBOLIC PROCEDURE ASSOC(U,V); IF NULL V THEN NIL 16-5 ELSE IF U = CAAR V THEN CAR V ELSE ASSOC(U, CDR V); If the default mode were symbolic, then SYMBOLIC could be omitted in the above definition. MACROs and FEXPRs may be defined by prefixing the keyword PROCEDURE by the word MACRO or FEXPR. (In fact, ordinary functions may be defined with the keyword EXPR prefixing PROCEDURE as was used in the Standard LISP Report.) e.g. we could define a MACRO CONSCONS by SYMBOLIC MACRO PROCEDURE CONSCONS L; EXPAND(CDR L, 'CONS); 16.8 Standard Lisp Equivalent Of Reduce Input ←←←←←←←← ←←←← ←←←←←←←←←← ←← ←←←←←← ←←←←← A user can obtain the Standard LISP equivalent of his REDUCE input by turning on the switch DEFN (for definition). The system then prints the LISP translation of his input but does not evaluate it. Normal operation is resumed when DEFN is turned off. 16.9 Communicating With Algebraic Mode ←←←←←←←←←←←←← ←←←← ←←←←←←←←← ←←←← One of the principal motivations for a user of the algebraic facilities of REDUCE to learn about symbolic mode is that it gives one access to a wider range of techniques than is possible in algebraic mode alone. For example, if a user wishes to use parts of the system defined in the basic system source code, or refine their algebraic code definitions to make them more efficient, then it is necessary to understand the source language in fairly complete detail. Moreover, it is also necessary to know a little more about the way REDUCE operates internally. Basically, REDUCE considers expressions in two forms; prefix form, which follow the normal LISP rules of function composition, and so called canonical form, which uses a different syntax. Once these details are understood, the most critical problem faced by a user is how to make expressions and procedures communicate between symbolic and algebraic mode. The purpose of this section is to teach a user the basic principles for this. If one wants to evaluate an expression in algebraic mode, and then use that expression in symbolic mode calculations, or vice versa, the easiest way to do this is to assign a variable to that expression whose value is easily obtainable in both modes. To facilitate this, a declaration SHARE is available. SHARE takes a list of identifiers as argument, and marks these variables as having recognizable values in both modes. The declaration may be used in either mode. E.g., SHARE X,Y; 16-6 says that X and Y will receive values to be used in both modes. If a SHARE declaration is made for a variable with a previously assigned algebraic value, that value is also made available in symbolic mode. 16.9.1 Passing Algebraic Mode Values To Symbolic Mode ←←←←←←← ←←←←←←←←← ←←←← ←←←←←← ←← ←←←←←←←← ←←←← If one wishes to work with parts of an algebraic mode expression in symbolic mode, one simply makes an assignment of a shared variable to the relevant expression in algebraic mode. For example, if one wishes to work with (A+B)**2, one would say, in algebraic mode: X := (A+B)**2; assuming that X was declared shared as above. If we now change to symbolic mode and say X; its value will be printed as a prefix form with the syntax: (*SQ <standard quotient> T) This particular format reflects the fact that the algebraic mode processor currently likes to transfer prefix forms from command to command, but doesn't like to reconvert standard forms (which represent polynomials) and standard quotients back to a true LISP prefix form for the expression (which would result in excessive computation). So *SQ is used to tell the algebraic processor that it is dealing with a prefix form which is really a standard quotient and the second argument (T or NIL) tells it whether it needs further processing (essentially, an 'already simplified' flag). So to get the true standard quotient form in symbolic mode, one needs CADR of the variable. E.g., Z := CADR X; would store in Z the standard quotient form for (A+B)**2. Once you have this expression, you can now manipulate it as you wish. To facilitate this, a standard set of selectors and constructors are available for getting at parts of the form. Those presently defined are as follows: REDUCE Selectors DENR denominator of standard quotient LC leading coefficient of polynomial LDEG leading degree of polynomial LPOW leading power of polynomial 16-7 LT leading term of polynomial MVAR main variable of polynomial NUMR numerator (of standard quotient) PDEG degree of a power RED reductum of polynomial TC coefficient of a term TDEG degree of a term TPOW power of a term REDUCE Constructors .+ add a term to a polynomial ./ divide (two polynomials to get quotient) .* multiply a power by a coefficient to produce a term .** raise a variable to a power For example, to find the numerator of the standard quotient above, one could say: NUMR Z; or to find the leading term of the numerator: LT NUMR Z; Conversion between various data structures is facilitated by the use of a set of functions defined for this purpose. Those currently implemented include: !*A2F convert an algebraic expression to a standard form. If result is rational, an error results. !*A2K converts an algebraic expression to a kernel. If this is not possible, an error results. !*F2A converts a standard form to an algebraic expression !*F2Q convert a standard form to a standard quotient !*K2F convert a kernel to a standard form !*K2Q convert a kernel to a standard quotient 16-8 !*P2F convert a standard power to a standard form !*P2Q convert a standard power to a standard quotient !*Q2F convert a standard quotient to a standard form. If the quotient denominator is not 1, an error results !*Q2K convert a standard quotient to a kernel. If this is not possible, an error results. !*T2F convert a standard term to a standard form !*T2Q convert a standard term to a standard quotient 16.9.2 Passing Symbolic Mode Values Back To Algebraic Mode ←←←←←←← ←←←←←←←← ←←←← ←←←←←← ←←←← ←← ←←←←←←←←← ←←←← In order to pass the value of a shared variable from symbolic mode to algebraic mode, the only thing to do is make sure that the value in symbolic mode is a prefix expression. E.g., one uses (EXPT (PLUS A B) 2) for (A+B)**2, or the format (*SQ <standard quotient> T) as described above. However, if you have been working with parts of a standard form they will probably not be in this form. In that case, you can do the following: 1) If it is a standard quotient, call PREPSQ on it. This takes a standard quotient as argument, and returns a prefix expression. Alternatively, you can call MK!*SQ on it, which returns a prefix form like (*SQ <standard quotient> T) and avoids translation of the expression into a true prefix form. 2) If it is a standard form, call PREPF on it. This takes a standard form as argument, and returns the equivalent prefix expression. Alternatively, you can convert it to a standard quotient and then call MK!*SQ. 3) If it is a part of a standard form, you must usually first build up a standard form out of it, and then go to step 2. The conversion functions described earlier may be used for this purpose. For example, a) If Z is an expression which is a term, !*T2F Z is a standard form. b) If Z is a standard power, !*P2F Z is a standard form. c) If Z is a variable, you can pass it direct to algebraic mode. For example, to pass the leading term of (A+B)**2 back to algebraic mode, one could say: Y:= MK!*SQ !*T2Q LT NUMR Z; where Y has been declared shared as above. If you now go back to algebraic mode, you can work with Y in the usual way. 16-9 16.9.3 Complete Example ←←←←←←←← ←←←←←←← The following is the complete code for doing the above steps. The end result will be that the square of the leading term of (A+B)**2 is calculated. SHARE X,Y; %declare X and Y as shared variables; X := (A+B)**2; %store (A+B)**2 in X; SYMBOLIC; %transfer to symbolic mode; Z := CADR X; %store true standard quotient in Z; LT NUMR Z; %print the leading term of the numerator of Z; Y := MK!*SQ !*T2Q NUMR Z; %store a valid prefix form of this leading term in Y; ALGEBRAIC; %return to algebraic mode; Y**2; %evaluate the square of the leading term of (A+B)**2; 16.9.4 Defining Procedures Which Communicate Between Modes ←←←←←←←← ←←←←←←←←←← ←←←←← ←←←←←←←←←←← ←←←←←←← ←←←←← If one wishes to define a procedure in symbolic mode for use as an operator in algebraic mode, it is necessary to declare this fact to the system by using the declaration OPERATOR in SYMBOLIC MODE. Thus SYMBOLIC OPERATOR LEADTERM; would declare the procedure LEADTERM as an algebraic operator. This declaration MUST be made in symbolic mode as the effect in algebraic mode is different. The value of such a procedure must be a prefix form. The algebraic processor will pass arguments to such procedures in prefix form. Therefore if you want to work with the arguments as standard quotients you must first convert them to that form by using the function SIMP!*. This function takes a prefix form as argument and returns the evaluated standard quotient. For example, if you want to define a procedure LEADTERM which gives the leading term of an algebraic expression, one could do this as follows: SYMBOLIC OPERATOR LEADTERM; %declare LEADTERM as a symbolic %mode procedure to be used in %algebraic mode; SYMBOLIC PROCEDURE LEADTERM U; %define LEADTERM; MK!*SQ !*T2Q LT NUMR SIMP!* U; Note that this operator has a different effect than the operator LTERM (q.v.). In the latter case, the calculation is done with respect to the second argument of the operator. In the example here, we simply extract the leading term with respect to the system's choice of main variable. Finally, if you wish to use the algebraic evaluator on an argument in a symbolic mode definition, the function REVAL can be used. The one argument 16-10 of REVAL must be the prefix form of an expression. REVAL returns the evaluated expression as a true LISP prefix form. 16.10 References ←←←←←←←←←← There are a number of useful books which can give you further information about LISP. Here is a selection: Allen, J. R., "The Anatomy of LISP", McGraw Hill, New York, 1978. McCarthy J., P. W. Abrahams, J. Edwards, T. P. Hart and M. I. Levin, "LISP 1.5 Programmer's Manual", M.I.T. Press, 1965. Weissman, C., "LISP 1.5 Primer", Dickenson, 1967. Winston, P. H. and Horn, B. K. P., "LISP", Addison-Wesley, 1981. 17-1 17. CALCULATIONS IN HIGH ENERGY PHYSICS ←←←←←←←←←←←← ←← ←←←← ←←←←←← ←←←←←←← A set of REDUCE commands is provided for users interested in symbolic calculations in high energy physics. Several extensions to our basic syntax are necessary, however, to allow for the different data structures encountered. 17.1 Notation ←←←←←←←← In order to allow for the printing of this text on printers with limited character sets, we represent Greek characters in this section by their (upper case) English names. 17.2 Operators Used In High Energy Physics Calculations ←←←←←←←←← ←←←← ←← ←←←← ←←←←←← ←←←←←←← ←←←←←←←←←←←← We begin by introducing three new operators required in these calculations. 17.2.1 . (Cons) Operator ← ←←←←←← ←←←←←←←← Syntax: (EXPRN1:vector←expression) . (EXPRN2:vector←expression):algebraic. The binary . operator, which is normally used to denote the addition of an element to the front of a list, can also be used in algebraic mode to denote the scalar product of two Lorentz four-vectors. For this to happen, the second argument must be recognizable as a vector expression (q.v.) at the time of evaluation. With this meaning, this operator is often referred to as the "dot" operator. In the present system, the index handling routines all assume that Lorentz four-vectors are used, but these routines could be rewritten to handle other cases. Components of vectors can be represented by including representations of unit vectors in the system. Thus if EO represents the unit vector (1,0,0,0), (P.EO) represents the zeroth component of the four-vector P. Our metric and notation follows Bjorken and Drell "Relativistic Quantum Mechanics" (McGraw-Hill, New York, 1965). Similarly, an arbitrary component P may be represented by (P.U). If contraction over components of vectors is required, then the declaration INDEX must be used. Thus INDEX U; declares U as an index, and the simplification of (P.U) * (Q.U) would result in (P.Q) . 17-2 The metric tensor g(u,v) may be represented by (U.V). If contraction over u and v is required, then U and V should be declared as indices. Errors occur if indices are not properly matched in expressions. If a user later wishes to remove the index property from specific vectors, he can do it with the declaration REMIND. Thus REMIND V1...VN; removes the index flags from the variables V1 through Vn. However, these variables remain vectors in the system. 17.2.2 G Operator For Gamma Matrices ← ←←←←←←←← ←←← ←←←←← ←←←←←←←← Syntax: G(ID:identifier[,EXPRN:vector←expression]) :gamma←matrix←expression. G is an n-ary operator used to denote a product of gamma matrices contracted with Lorentz four-vectors. Gamma matrices are associated with fermion lines in a Feynman diagram. If more than one such line occurs, then a different set of gamma matrices (operating in independent spin spaces) is required to represent each line. To facilitate this, the first argument of G is a line identification identifier (not a number) used to distinguish different lines. Thus G(L1,P) * G(L2,Q) denotes the product of P associated with a fermion line identified as L1, and Q associated with another line identified as L2 and where P and Q are Lorentz four-vectors. A product of gamma matrices associated with the same line may be written in a contracted form. Thus G(L1,P1,P2,...,P3) = G(L1,P1)*G(L1,P2)*,...,*G(L1,P3) . The vector A is reserved in arguments of G to denote the special gamma matrix GAMMA5. Thus G(L,A) = GAMMA5 associated with line L. G(L,P,A) = GAMMA.P*GAMMA5 associated with line L. GAMMA (associated with line L) may be written as G(L,U), with U flagged U as an index if contraction over U is required. The notation of Bjorken and Drell is assumed in all operations involving gamma matrices. 17-3 17.2.3 Eps Operator ←←← ←←←←←←←← Syntax: EPS(EXPRN1:vector←expression,...,EXPRN4:vector←exp) :vector←exp. The operator EPS has four arguments, and is used only to denote the completely antisymmetric tensor of order 4 and its contraction with Lorentz four-vectors. Thus EPS = ( +1 if I,J,K,L is an even permutation of 0,1,2,3 IJKL ( -1 if an odd permutation ( 0 otherwise A contraction of the form EPS p q may be written as EPS(I,J,P,Q), IJuv u v with I and J flagged as indices, and so on. 17.3 Vector Variables ←←←←←← ←←←←←←←←← Apart from the line identification identifier in the G operator, all other arguments of the operators in this section are vectors. Variables used as such must be declared so by the type declaration VECTOR. e.g. VECTOR P1,P2; declares P1 and P2 to be vectors. Variables declared as indices or given a mass (q.v.) are automatically declared vector by these declarations. 17.4 Additional Expression Types ←←←←←←←←←← ←←←←←←←←←← ←←←←← Two additional expression types are necessary for high energy calculations, namely 17.4.1 Vector Expressions ←←←←←← ←←←←←←←←←←← These follow the normal rules of vector combination. Thus the product of a scalar or numerical expression and a vector expression is a vector, as are the sum and difference of vector expressions. If these rules are not followed, error messages are printed. Furthermore, if the system finds an undeclared variable where it expects a vector variable, it will ask the user in interactive mode whether to make that variable a vector or not. In batch mode, the declaration will be made automatically and the user informed of this by a message. Examples: 17-4 Assuming P and Q have been declared vectors, the following are vector expressions P P-2*Q/3 2*X*Y*P - P.Q*Q/(3*Q.Q) whereas P*Q and P/Q are not. 17.4.2 Dirac Expressions ←←←←← ←←←←←←←←←←← These denote those expressions which involve gamma matrices. A gamma matrix is implicitly a 4 x 4 matrix, and so the product, sum and difference of such expressions, or the product of a scalar and Dirac expression is again a Dirac expression. There are no Dirac variables in the system, so whenever a scalar variable appears in a Dirac expression without an associated gamma matrix expression, an implicit unit 4 x 4 matrix is assumed. e.g. G(L,P) + M denotes G(L,P) + M*<unit 4 x 4 matrix> . Multiplication of Dirac expressions, as for matrix expressions, is of course non-commutative. 17.5 Trace Calculations ←←←←← ←←←←←←←←←←←← When a Dirac expression is evaluated, the system computes one quarter of the trace of each gamma matrix product in the expansion of the expression. One quarter of each trace is taken in order to avoid confusion between the trace of the scalar M, say, and M representing M * <unit 4 x 4 matrix>. Contraction over indices occurring in such expressions is also performed. If an unmatched index is found in such an expression, an error occurs. The algorithms used for trace calculations are the best available at the time this system was produced. For example, in addition to the algorithm developed by Chisholm for contracting indices in products of traces, REDUCE uses the elegant algorithm of Kahane for contracting indices in gamma matrix products. These algorithms are described in Chisholm, J. S. R., Il Nuovo Cimento X, 30, 426 (1963) and Kahane, J., Journal Math. Phys. 9, 1732 (1968). It is possible to prevent the trace calculation over any line identifier by the declaration NOSPUR. E.g. NOSPUR L1,L2; will mean that no traces are taken of gamma matrix terms involving the line numbers L1 and L2. However, in some calculations involving more than one line, a catastrophic error "This NOSPUR option not implemented" can occur (for the reason stated!) If you encounter this error, please let us know! 17-5 A trace of a gamma matrix expression involving a line identifier which has been declared NOSPUR may be later taken by making the declaration SPUR. 17.6 Mass Declarations ←←←← ←←←←←←←←←←←← It is often necessary to put a particle 'on the mass shell' in a calculation. This can, of course, be accomplished with a LET command such as LET P.P= M**2; but an alternative method is provided by two commands MASS and MSHELL. MASS takes a list of equations of the form: <vector variable> = <scalar variable> e.g. MASS P1=M, Q1=MU; The only effect of this command is to associate the relevant scalar variable as a mass with the corresponding vector. If we now say MSHELL <vector variable>,...,<vector variable>; and a mass has been associated with these arguments, a substitution of the form <vector variable>.<vector variable> = <mass>**2 is set up. An error results if the variable has no preassigned mass. 17.7 Example ←←←←←←← We give here as an example of a simple calculation in high energy physics the computation of the Compton scattering cross-section as given in Bjorken and Drell Eqs. (7.72) through (7.74). We wish to compute 2 2 PF+m E'EKI EE'KF PI+m KIEE' KFE'E ALPHA /2 (k'/k) trace ((----)(----- + ------)(----)(----- + ------)). 2m 2k.PI 2k'.PI 2m 2k.PI 2k'.PI where ki and kf are the four-momenta of incoming and outgoing photons (with polarization vectors e and e' and laboratory energies k and k' respectively) and pi,pf are incident and final electron four-momenta. Upper case momenta in the above formula are used to indicate contractions of the momenta with gamma matrices. For example, PF = GAMMA . pf. Omitting the factor ALPHA**2/(2*m**2)*(k'/k)**2 we need to find E'EKI EE'KF KIEE' KFE'E 17-6 1/4 trace ((PF+m)(----- + ------)(PI+m)(----- + ------)) 2k.pi 2k'.pi 2k.pi 2k'.pi A straightforward REDUCE program for this, with appropriate substitutions (but using P1 instead of PI to avoid confusion with the reversed variable PI) would be: ON DIV; % THIS GIVES US OUTPUT IN SAME FORM AS BJORKEN AND DRELL; MASS KI= 0, KF= 0, P1= M, PF= M; VECTOR E,EP; % IF E IS USED AS A VECTOR, IT LOSES ITS SCALAR IDENTITY AS THE BASE OF NATURAL LOGARITHMS; MSHELL KI,KF,P1,PF; LET P1.E= 0, P1.EP= 0, P1.PF= M**2+KI.KF, P1.KI= M*K,P1.KF= M*KP, PF.E= -KF.E, PF.EP= KI.EP, PF.KI= M*KP, PF.KF= M*K, KI.E= 0, KI.KF= M*(K-KP), KF.EP= 0, E.E= -1, EP.EP=-1; FOR ALL P LET GP(P)= G(L,P)+M; COMMENT THIS IS JUST TO SAVE US A LOT OF WRITING; GP(PF)*(G(L,EP,E,KI)/(2*KI.P1) + G(L,E,EP,KF)/(2*KF.P1)) * GP(P1)*(G(L,KI,E,EP)/(2*KI.P1) + G(L,KF,EP,E)/(2*KF.P1))$ WRITE "THE COMPTON CROSS-SECTION IS ",WS; This program will print the following result (-1) (-1) 2 THE COMPTON CXN IS 1/2*K*KP + 1/2*K *KP + 2*E.EP - 1 17.8 Extensions To More Than Four Dimensions ←←←←←←←←←← ←← ←←←← ←←←← ←←←← ←←←←←←←←←← In our discussion so far, we have assumed that we are working in the normal four dimensions of QED calculations. However, in most cases, the programs will also work in an arbitrary number of dimensions. The command VECDIM <expression>; sets the appropriate dimension. The dimension can be symbolic as well as numeric. Users should note however, that the EPS operator and the gamma 5 symbol (A) are not properly defined in other than four dimensions and will lead to an error if used. 18-1 18. REDUCE AND RLISP UTILITIES ←←←←←← ←←← ←←←←← ←←←←←←←←← REDUCE and its associated support language system RLISP include a number of utilities which have proved useful for program development over the years. The following are supported in most of the implementations of REDUCE currently available. 18.1 The Standard Lisp Compiler ←←← ←←←←←←←← ←←←← ←←←←←←←← Many versions of REDUCE include a Standard LISP compiler that is automatically loaded on demand. You should check your system specific user guide to make sure you have such a compiler. To make the compiler active, the switch COMP should be turned on. Any further definitions input after this will be compiled automatically. Furthermore, if the switch PWRDS is on (the default), a statistics message of the form <function-name> COMPILED, <words> WORDS, <words> LEFT is printed. The first number is the number of words of binary program space the compiled function took, and the second number the number of words left unused in binary program space. Other switches of interest which may be used with the compiler are as follows: PLAP If ON, causes the printing of the portable macros produced by the compiler. PGWD If ON, causes the printing of the actual assembly language instructions generated from the macros. A complete description of the compiler may be found in M. L. Griss and A. C. Hearn, "A Portable LISP Compiler", SOFTWARE - Practice and Experience 11 (1981) 541-605. 18.2 Fast Loading Code Generation Program ←←←← ←←←←←←← ←←←← ←←←←←←←←←← ←←←←←←← In most versions of REDUCE, it is possible to take any set of LISP, RLISP or REDUCE commands and build a fast loading version of them. In RLISP or REDUCE, one does the following: FASLOUT <filename>; <commands or IN statements> FASLEND; To load such a file, one uses the command LOAD, e.g. LOAD FOO; or LOAD FOO,BAH; Fast-loading files produced by this process may have an implementation dependent extension added by this process. For example, on the DEC-10 an extension FAP is added, and on the VAX, b (for binary). Such extensions are 18-2 required by the LOAD program; if they are missing, an error occurs. In doing this build, as with the production of a Standard LISP form of such statements, it is important to remember that some of the commands must be instantiated during the building process. For example, macros must be expanded, and some property list operations must happen. To facilitate this, the EVAL and IGNORE flags (q.v.) may be used. Note also that there can be no LOAD command within the input statements. To avoid excessive printout, input statements should be followed by a $ instead of the semicolon. With LOAD however, the input doesn't print out regardless of which terminator is used with the command. If you subsequently change the source files used in producing a fast loading file, don't forget to repeat the above process in order to update the fast loading file correspondingly. Remember also that the text which is read in during the creation of the fast load file, in the compiling process described above, is NOT stored in your REDUCE environment, but only translated and output. If you want to use the file just created, you must then use LOAD to load the output of the fast-loading file generation program. 18.3 The Standard Lisp Cross Reference Program ←←← ←←←←←←←← ←←←← ←←←←← ←←←←←←←←← ←←←←←←← CREF is a Standard LISP program for processing a set of Standard LISP function definitions to produce: 1) A "summary" showing: i. A list of files processed. ii. A list of "entry points" (functions which are not called or are only called by themselves). iii. A list of undefined functions (functions called but not defined in this set of functions). iv. A list of variables that were used non-locally but not declared GLOBAL or FLUID before their use. v. A list of variables that were declared GLOBAL but not used as FLUIDs, i.e., bound in a function. vi. A list of FLUID variables that were not bound in a function so that one might consider declaring them GLOBALs. vii. A list of all GLOBAL variables present. viii. A list of all FLUID variables present. ix. A list of all functions present. 2) A "global variable usage" table, showing for each non-local variable: i. Functions in which it is used as a declared FLUID or GLOBAL. ii. Functions in which it is used but not declared. iii. Functions in which it is bound. iv. Functions in which it is changed by SETQ. 3) A "function usage" table showing for each function: 18-3 i. Where it is defined. ii. Functions which call this function. iii. Functions called by it. iv. Non-local variables used. The program will also check that functions are called with the correct number of arguments, and print a diagnostic message otherwise. The output is alphabetized on the first seven characters of each function name. 18.3.1 Restrictions: ←←←←←←←←←←←←← Algebraic procedures in REDUCE are treated as if they were symbolic, so that algebraic constructs will actually appear as calls to symbolic functions, such as AEVAL. 18.3.2 Usage: ←←←←←← To invoke the cross reference program, the switch CREF is used. ON CREF causes the cref program to load and the cross-referencing process to begin. After all the required definitions are loaded, OFF CREF will cause the cross-reference listing to be produced. For example, if you wish to cross-reference all functions in the file TST.RED, and produce the cross-reference listing in the file TST.CRF, the following sequence can be used: OUT TST.CRF; ON CREF; IN TST.RED$ OFF CREF; END; To process more than one file, more IN statements may be added before the call of OFF CREF, or the IN statement changed to include a list of files. 18.3.3 Options: ←←←←←←←← Functions with the flag NOLIST will not be examined or output. Initially, all Standard LISP functions are so flagged. (In fact, they are kept on a list NOLIST!*, so if you wish to see references to ALL functions, then CREF should be first loaded with the command LOAD CREF, and this variable then set to NIL). It should also be remembered that any macros with the property list flag EXPAND, or, if the switch FORCE is on, without the property list flag NOEXPAND, will be expanded before the definition is seen by the cross- reference program, so this flag can also be used to select those macros you require expanded and those you do not. 18-4 18.4 Prettyprinting Reduce Expressions ←←←←←←←←←←←←←← ←←←←←← ←←←←←←←←←←← REDUCE includes a module for printing REDUCE syntax in a standard format. This module is activated by the switch PRET, which is normally off. Since the system converts algebraic input into an equivalent symbolic form, the printing program tries to interpret this as an algebraic expression before printing it. In most cases, this can be done successfully. However, there will be occasional instances where results are printed in symbolic mode form that bears little resemblance to the original input, even though it is formally equivalent. If you want to prettyprint a whole file, say OFF OUTPUT,MSG; and (hopefully) only clean output will result. Unlike DEFN (q.v.), input is also evaluated with PRET on. 18.5 Prettyprinting Standard Lisp S-Expressions ←←←←←←←←←←←←←← ←←←←←←←← ←←←← ←←←←←←←←←←←←← Standard LISP includes a module for printing S-expressions in a standard format. The Standard LISP function for this purpose is PRETTYPRINT which takes a LISP expression and prints the formatted equivalent. Users can also have their REDUCE input printed in this form by use of the switch DEFN. This is in fact a convenient way to convert REDUCE (or RLISP) syntax into LISP. OFF MSG; will prevent warning messages from being printed. NOTE: When DEFN is on, input is not evaluated. A-1 A. RESERVED IDENTIFIERS ←←←←←←←← ←←←←←←←←←←← We list here all identifiers that are normally reserved in REDUCE including names of commands and operators initially in the system. Excluded are words that are reserved in specific implementations of the system. Commands ALGEBRAIC ANTISYMMETRIC ARRAY BYE CLEAR COMMENT CONT DEFINE DEPEND DISPLAY EDITDEF ED END FACTOR FOR FORALL FOREACH GO GOTO IF IN INDEX INFIX INTEGER KORDER LET LINEAR LISP MASS MATCH MATRIX MSHELL NODEPEND NONCOM NOSPUR OFF ON OPERATOR ORDER OUT PAUSE PRECEDENCE PROCEDURE QUIT REAL REMFAC REMIND RETRY RETURN SAVEAS SCALAR SETMOD SHARE SHOWTIME SHUT SPUR SYMBOLIC SYMMETRIC VECDIM VECTOR WEIGHT WRITE WTLEVEL (Page 6-1) Infix Operators := = >= > <= < + * / ** . WHERE SETQ OR AND NOT MEMBER MEMQ EQUAL NEQ EQ GEQ GREATERP LEQ LESSP PLUS DIFFERENCE MINUS TIMES QUOTIENT EXPT CONS (Page 2-5) Mathematical Operators ACOS ACOSH ASIN ASINH ATAN ATANH COS COSH COT DILOG ERF EXP EXPINT LOG SIN SINH SQRT TAN TANH (Page 7-1) Prefix Operators ABS ARGLENGTH COEFF DEG DEN DET DF EPS FACTORIZE GCD G INT LCOF LINELENGTH LTERM MAINVAR MAT MAX MIN NUM PART PFACTORIZE PRECISION REDERR REDUCT REMAINDER RESULTANT SOLVE STRUCTR SUB TP TRACE VARNAME (Page 7-1) Reserved Variables E I K!* NIL PI T (Page 2-3) Reserved Words Not Included Above BEGIN DO EXPR FASLOUT FEXPR FLAGOP INPUT LAMBDA LISP LOAD MACRO PRODUCT REPEAT SMACRO SUM WHILE WS (Page 2-4) B-1 B. OPERATORS NORMALLY AVAILABLE IN REDUCE ←←←←←←←←← ←←←←←←←← ←←←←←←←←← ←← ←←←←←← This section describes all the operators that are normally available in REDUCE. Excluded from this list are the infix operators listed under "Reserved Identifiers" and the mathematical operators (SIN, COS, etc.) also listed there. Notation: Each operator is provided with a prototypical header line. Each formal parameter is given a name and followed by its allowed type. The names of classes referred to in the definition are printed in lower case, and parameter names in upper case. If a parameter type is not commonly used, it may be a specific set enclosed in brackets {...}. Operators which accept formal parameter lists of arbitrary length have the parameter and type class enclosed in square brackets indicating that zero or more occurrences of that argument are permitted. Optional parameters and their type classes are enclosed in angle brackets. ABS(EXPRN:numeric):numeric Returns the absolute value of EXPRN (Page 7-1) APPEND(L1:list,L2:list):list Appends the list L1 to the list L2 (Page 4-2) ARGLENGTH(EXPRN:algebraic) Returns the number of arguments of the top level operator in EXPRN (Page 8-15) COEFFN(EXPRN:polynomial,VAR:kernel,N:integer) Returns the Nth coefficient of VAR in EXPRN (Page 8-14) COEFF(EXPRN:rational,VAR:kernel) Returns a list of the coefficients of EXPRN with respect to VAR, ordered from zeroth to the highest powered term. (Page 8-13) DEG(EXPRN:polynomial,VAR:kernel):integer Returns the leading degree of the polynomial EXPRN in the variable VAR (Page 9-7) DEN(EXPRN:rational):polynomial Returns the denominator of the rational expression EXPRN (Page 9-7) DET(EXPRN:matrix←expression):algebraic Returns the determinant of the matrix EXPRN (Page 13-3) DF(EXPRN:algebraic,[VAR:kernel<,NUM:integer>]):algebraic Returns the derivative of EXPRN wrt VAR, repeated NUM times (Page 7-3) B-2 EPS(EXPRN1:vector←expression,...,EXPRN4:vector←exp):vector←exp Represents the antisymmetric tensor of order 4 in high energy physics calculations (Page 17-3) FACTORIZE(EXPRN:polynomial[,INTEXP:prime integer]):list Factorizes polynomial EXPRN, returning factors as a list of expressions, and using optional prime INTEXP for internal computation (Page 9-2) First(L:list) Returns the first element of a list (Page 4-1) GCD(EXPRN1:polynomial,EXPRN2:polynomial):polynomial Returns the greatest common divisor of the two polynomials EXPRN1 and EXPRN2 (Page 9-5) G(ID:identifier[,EXPRN:vector←expression]):gamma←matrix←expression Represents a Dirac gamma matrix expression in high energy physics calculations (Page 17-2) INT(EXPRN:algebraic,VAR:kernel):algebraic Returns the integral of EXPRN with respect to VAR (Page 7-4) LCOF(EXPRN:polynomial,VAR:kernel):polynomial Returns the leading coefficient of the polynomial EXPRN in the variable VAR (Page 9-7) LENGTH(EXPRN:algebraic) Returns the length of the object EXPRN (Page 7-6) LHS(EXPRN:equation):any Returns the left-hand side of the equation EXPRN (Page 3-4) LINELENGTH(NUM:integer):integer Sets the output line length to NUM and returns previous line length (Page 8-3) LTERM(EXPRN:polynomial,VAR:kernel):polynomial Returns the leading term of EXPRN with respect to VAR (Page 9-8) MAINVAR(EXPRN:polynomial):expression Returns the main variable of EXPRN (Page 9-8) MAT Used to represent matrices (Page 13-1) MAX([EXPRN:numeric]):numeric Returns the maximum of the given EXPRNs (Page 7-1) MIN([EXPRN:numeric]):numeric Returns the minimum of the given EXPRNs (Page 7-1) MKID(U:id,V:id|non-negative integer):id Creates an identifier UN from id U and integer N B-3 (Page 7-6) NUM(EXPRN:rational):polynomial Returns the numerator of the rational expression EXPRN (Page 9-8) PART(EXPRN:algebraic[,INTEXP:integer]) Returns the appropriate part of EXPRN as defined by INTEXP (Page 8-14) PRECISION(EXPRN:integer):integer; Sets the real number precision to <integer> decimal digits when arbitrary precision real arithmetic (BIGFLOAT) is used (Page 9-10) REDERR(STRING:string) Provides an error exit from a block or procedure (Page 14-3) REDUCT(EXPRN:polynomial,VAR:kernel):polynomial Returns the reductum of EXPRN with respect to VAR (Page 9-8) REMAINDER(EXPRN1:polynomial,EXPRN2:polynomial):polynomial Returns the remainder when EXPRN1 is divided by EXPRN2 (Page 9-6) REST(L:list):list Returns the list L with the first element removed (Page 4-1) RESULTANT(EXPRN1:polynomial,EXPRN2:polynomial,VAR:kernel):polynomial Returns the resultant of EXPRN1 and EXPRN2 with respect to the variable VAR (Page 9-6) REVERSE(L:list):list Returns the list L with elements in reverse order (Page 4-2) RHS(EXPRN:equation):any Returns the right-hand side of the equation EXPRN (Page 3-4) SOLVE(EXPRN:algebraic[,VAR:kernel|,VARLIST:list of kernels]):integer Solves a set of equations in terms of the kernel VAR, or a list of kernels (Page 7-6) STRUCTR(EXPRN:algebraic[,ID1:identifier[,ID2:identifier]]) Displays the structure of EXPRN (Page 8-12) SUB([VAR1:kernel = EXPRN1:algebraic],EXPRN:algebraic):algebraic Replaces every occurrence of VAR1 in EXPRN by EXPRN1 (Page 10-1) Second(L:list) Returns the second element of a list (Page 4-1) B-4 TP(EXPRN:matrix←expression):matrix Returns the transpose of the matrix EXPRN (Page 13-3) TRACE(EXPRN:matrix←expression):algebraic Returns the trace of the matrix EXPRN (Page 13-3) Third(L:list) Returns the second element of a list (Page 4-1) VARNAME(ID:identifier) Sets the expression naming variable to ID (Page 8-11) (EXPRN:algebraic) . (L:list) Adds EXPRN to the front of the list L (Page 4-2) C-1 C. COMMANDS AND DECLARATIONS ←←←←←←←← ←←← ←←←←←←←←←←←← This index summarizes the commands and declarations normally available in REDUCE. Notation: E, E1,...,En denote expressions ID, ID1,...IDn denote identifiers V, V1,...,Vn denote variables (or more generally kernels) ALGEBRAIC E; If E is empty, the system mode is set to algebraic. Otherwise, E is evaluated in algebraic mode and the system mode is not changed (Page 16-1) ANTISYMMETRIC ID1,...,IDn; Declares operators ID1 through IDn to be anti- symmetric in their arguments (Page 7-10) ARRAY V1<size>,...,Vn<size> Declares V1 through Vn as array names. <size> describes the maximum size of the array (Page 6-1) BYE; Stops the execution of REDUCE and returns you to the system monitor. The REDUCE job is destroyed (Page 6-3) CLEAR E1,...En; Removes any substitutions declared for E1 through En from system (Page 10-5) COMMENT <any>; Used for including comments in text. <any> is any sequence of characters not including a terminator (Page 2-4) CONT; An interactive command which causes the system to continue the calculation from the point in the input file where the last PAUSE was encountered (Page 12-3) DEFINE E1,...,En; Allows for the replacement of the left-hand side of the equations E1 through En by the corresponding right-hand side (Page 6-3) DEPEND V1,...,Vn; Sets up a dependency of variable V1 on kernels V2 through Vn (Page 7-11) DISPLAY E; Causes previous inputs to be displayed. If E is a non-negative integer, then that many expressions will be displayed (Page 12-1) EDITDEF <name> Causes the uncompiled procedure <name> to be displayed in interactive editing mode (Page 12-2) C-2 ED <null or number> Invokes an interactive string editor for previous command or command <number> (Page 12-2) END; Used to terminate a program block, end a file, or transfer control to LISP (Page 6-2) FACTOR E1,...En; Declares expressions as factors in output (Page 8-4) FOR Command used to define a variety of program loops (Page 5-4) FORALL V1,...,Vn <command> Declares variables V1 through Vn as arbitrary in the substitution rule given by <command> (Page 10-4) GO (TO) V; Performs an unconditional transfer to label V Can only be used in compound statements (Page 5-9) IF Used to define conditional statements (Page 5-3) INDEX V1,...,Vn; Declares high energy vectors V1 through Vn as indices (Page 17-1) INFIX ID1,...,IDn; Declares ID1 through IDn to be infix operators (Page 7-11) INTEGER V1,...,Vn; Declares V1 through Vn as local integer variables in a block statement (Page 5-7) IN V1,...,Vn; Inputs the external REDUCE files V1 through Vn (Page 11-1) KORDER V1,...,Vn; Declares an internal ordering for variables V1 through Vn (Page 8-13) LET E1,...,En; Declares substitutions for the left-hand sides of expressions E1 through En. In addition, LET can be used to input differentiation rules (Page 10-2) LINEAR V1,...,Vn; Declares operators V1 through Vn to be linear in in their arguments (Page 7-8) LISP E; A synonym for SYMBOLIC E; (Page 16-1) MASS V1=M1,...,VN=MN; Assigns a mass Mi to each vector Vi in high energy physics calculations (Page 17-5) MATCH E1,..., En; Declares substitutions for the left-hand sides of E1 through En when matching of explicit powers is required (Page 10-8) MATRIX E1,...,En; Declares matrix variables to the system. The Ei may be matrix variable names, or include C-3 details of the size of the matrix (Page 13-1) MSHELL V1,...,Vn; Puts each Vi "on the mass shell" in high energy physics calculations (Page 17-5) NODEPEND V1,...,Vn; Removes dependency of variable V1 on V2 through Vn (Page 7-11) NONCOM ID1,...,IDn; Declares operators ID1 through IDn to be non- commutative under multiplication (Page 7-9) NOSPUR ID1,...,IDn; Declares that line identification symbols ID1 through IDn do not have traces taken over them in high energy physics calculations (Page 17-4) OFF V1,...,Vn; Turns off the switches V1 through Vn (Page 6-2) ON V1,...,Vn; Turns on the switches V1 through Vn (Page 6-2) OPERATOR V1,...,Vn; Declares identifiers V1 through Vn as algebraic operators (Page 7-10) ORDER V1,...,Vn; Declares an ordering for variables V1 through Vn on output (Page 8-4) OUT V; Declares V as an output file (Page 11-1) PAUSE; An interactive command for use in an input file. When it is evaluated, control is transferred to the user's terminal (Page 12-3) PRECEDENCE ID1,ID2; Give infix operator ID1 a precedence higher than ID2 (Page 7-11) PROCEDURE Names a statement for repeated use in calculations. Type specification of procedure precedes the command name (Page 14-1) QUIT; Stops the execution of REDUCE and returns you to the system monitor. The REDUCE job is retained (Page 6-3) REAL V1,...,Vn; Declares V1 through Vn as local real variables in a block statement (Page 5-7) REMFAC E1,...,En; Removes expressions as factors in output (Page 8-4) REMIND V1,...,Vn; Declares that V1 through Vn are no longer high energy physics indices (Page 17-2) RETRY; Evaluates the command in which the last error occurred (Page 12-1) C-4 RETURN E; Causes a transfer out of a compound statement to the next highest program level. Value of E is returned from compound statement. E may be empty (Page 5-9) SAVEAS E; Assigns E to the current expression in the workspace (Page 8-2) SCALAR V1,...,Vn; Declares V1 through Vn as local scalar variables in a block statement (Page 5-7) SETMOD E; Sets the modular base to E (used with the switch MODULAR) (Page 9-10) SHARE V1,...,Vn; Permits variables V1 through Vn to be accessed in both symbolic and algebraic modes (Page 16-5) SHOWTIME; Prints the elapsed time since the last call of this command or the beginning of the session (Page 6-3) SHUT V1,...,Vn; Closes the output files V1 through Vn (Page 11-2) SPUR ID1,...,IDn; Declares that line identification symbols ID1 through IDn now have traces taken over them in high energy physics calculations (Page 17-5) SYMBOLIC E; If E is empty, the system evaluation mode is set to symbolic. Otherwise, E is evaluated in symbolic mode and the system mode not changed (Page 16-1) SYMMETRIC ID1,...,IDn; Declares operators ID1 through IDn to be symmetric in their arguments (Page 7-9) VECDIM E; Sets the dimension of the vector and Dirac matrix algebra to the expression E in high energy physics calculations (Page 17-6) VECTOR V1,...,Vn; Declares V1 through Vn to be high energy physics vectors (Page 17-3) WEIGHT E1,...En; Assigns an asymptotic weight to the left-hand sides of E1 through En (Page 10-9) WRITE E1,...,En; Causes the values of E1 through En to be written on the current output channel (Page 8-7) WTLEVEL E; Sets the asymptotic weight level of the system to E (Page 10-9) D-1 D. MODE SWITCHES IN REDUCE ←←←← ←←←←←←←← ←← ←←←←←← This section lists the switches that may appear as arguments of ON and OFF. The action of the switch when it is ON is described here, unless stated otherwise. Unless otherwise indicated the default value of the switch is OFF. ALLBRANCH Used by the SOLVE module to select all or only principal branches of solutions. Default ON (Page 7-7) ALLFAC Causes the system to factor out common products on output of expressions. Default ON (Page 8-5) BIGFLOAT Provides for the use of arbitrary precision real coefficients in polynomials (Page 9-10) COMP If ON, causes succeeding function definitions to be compiled (Page 18-1) COMPLEX Permits full complex arithmetic to be performed on polynomial coefficients (Page 9-11) CONVERT Causes a real coefficient equal to an integer within the system precision to be replaced by that integer. Default ON (Page 9-9) CRAMER If on, causes Cramer's method to be used for matrix quotients (Page 13-2) CREF If ON, causes a cross-reference analysis of subse- quent inputs to occur. The actual table is printed following a later OFF CREF (Page 18-3) DEFN Causes the system to output the LISP equivalent of REDUCE input without evaluation (Page 16-5) DEMO Causes the system to pause after each command in a file until a Return is typed on the terminal (Page 6-2) DIV Causes the system to divide out simple factors on output, so that negative powers or rational fractions can be produced (Page 8-5) ECHO Causes echoing of input (Page 11-1) ERRCONT Causes the system to continue evaluation of expressions in non-iteractive mode (Page 12-1) EXP Causes expressions to be expanded during their evaluation. Default ON (Page 9-1) D-2 EZGCD Causes the system to cancel greatest common divisors using the ezgcd algorithm. GCD must also be on for this to happen (Page 9-4) FACTOR If on, causes the system to factor expressions into factors with integer coefficients (Page 9-2) FAILHARD If on, causes integration algorithm to terminate with an error if integral not possible in closed terms (Page 7-5) FLOAT Allows for the use of floating point numbers during evaluation (Page 3-2) FORT Declares output in a FORTRAN notation (Page 8-9) GCD Causes the system to cancel greatest common divisors in rational expressions (Page 9-4) HEUGCD Causes the system to cancel greatest common divisors using the heuristic gcd algorithm. GCD must also be on for this to happen (Page 9-5) IFACTOR If on, causes factorization of the numerical coefficient in the output from FACTORIZE (Page 9-2) INT Specifies an interactive mode of operation. Default is system dependent (Page 12-3) INTSTR If on, causes operator arguments to be produced in a more structured form (Page 8-1) LCM When on, uses least common multiple of denominators when combining rational expressions (Page 9-5) LIST Causes output to be listed one term to each line (Page 8-5) MCD Causes denominators to be combined when expressions are added. Default ON (Page 9-5) MODULAR Provides for the use of modular integer coefficients. Base used is set by SETMOD (Page 9-10) MSG When off, suppresses the printing of warning messages. Error messages are still printed. Default ON (Page 18-4) NAT Specifies 'natural' style of output. Default ON (Page 8-11) NERO Inhibits printing of zero assignments (Page 8-9) D-3 NOLNR Suppresses the use of the linear properties in the integration algorithm (Page 7-5) NUMVAL Provides for the numerical evaluation of expressions in an appropriate real mode (Page 7-2) OUTPUT If OFF, suppresses printing the value of any top level expression. Default ON (Page 8-3) OVERVIEW Reduces the level of detail in trace of factorization algorithm (Page 9-3) PERIOD Causes a period to be printed after each integer coefficient in FORTRAN output. Default ON (Page 8-11) PGWD Causes the printing of the assembly language instructions generated from the macros (Page 18-1) PLAP Causes the printing of the portable macros produced by the compiler (Page 18-1) PRECISE Causes the system to return the absolute value form of any product terms taken out of rational powers (Page 7-2) PRET Causes input commands to be printed in REDUCE syntax in a standard format (Page 18-4) PRI Specifies formatted printing for output. Default ON (Page 8-3) PWRDS Causes a statistics message to be printed after a function is compiled. Default ON (Page 18-1) RAISE Causes input lower case characters to be converted into upper case. Characters in strings and those preceded by ! are excluded. Default ON (Page 2-1) RAT Output switch used in conjunction with FACTOR. Causes the overall denominator in an expression to be printed with each factored sub-expression (Page 8-6) RATARG If on, allows variable dependent denominators in COEFF expressions (Page 8-14) RATIONAL Provides for the use of rational number coefficients in polynomials (Page 9-9) RATIONALIZE If on, denominators of expressions are adjusted to remove complex numbers and surds (Page 9-11) D-4 RATPRI If on (the default), causes rational expressions to print in a two dimensional notation where possible (Page 8-6) REDUCED Causes the system to factor out product terms in an expression with rational powers (Page 7-2) RESUBS When RESUBS is off, the system does not re-examine an expression for further substitutions after one has been made. Default ON (Page 10-8) REVPRI If on, causes terms to be output in reverse order (Page 8-7) SAVESTRUCTR Stores the sub-expressions in a STRUCTR output with their assigned names (Page 8-12) SOLVESINGULAR Used by the SOLVE module to solve degenerate systems by introducing arbitrary constants. Default ON (Page 7-7) TIME Causes the system to print a message after each command giving the elapsed cpu time since the last command, or since TIME was last turned OFF or the session began (Page 6-2) TIMINGS Provides timing information on the factorization algorithm (Page 9-3) TRALLFAC Gives all levels of tracing information for the factorization algorithm (Page 9-3) TRFAC Traces the operation of the factorization algorithm (Page 9-3) TRINT Traces the operation of the integration algorithm (Page 7-5) E-1 E. DIAGNOSTIC AND ERROR MESSAGES IN REDUCE ←←←←←←←←←← ←←← ←←←←← ←←←←←←←← ←← ←←←←←← Diagnostic messages in the REDUCE system are of two types; error messages and warning messages. The former usually cause the termination of the current calculation whereas the latter warn the user of an ambiguity encountered or some action taken which may indicate an error. If the system is in an interactive state, it can ask the user when it encounters an ambiguity for the correct interpretation. Otherwise it will make the most plausible guess, print a message informing the user of the choice made, and continue. If an error is found during the parsing of the input, the current phrase is reprinted with the place marked where the error was encountered. In interactive systems, the expression can then be edited with the command ED. A list of the current diagnostic messages is given below. Those that indicate a warning (as opposed to an error) are so marked. Notation: E, E1,...,En denote expressions ID, ID1...,IDn denote identifiers A represents only gamma5 in vector expressions An attempt to use A as other than gamma5 in a high energy physics expression has been found (Page 17-2) CATASTROPHIC ERROR This error should not occur normally. If it does, please send a copy of the relevant input and output to the author (Page 3-2) Cannot shut current input file ID An attempt has been made to shut the current input file (Page 11-2) Continuing with parsing only An error has been found in a session being run in batch mode, so no further computation is done (Page 12-1) Domain mode ID1 changed to ID2 An automatic change of domain mode has occurred. This is usually the result of a user's change in a switch value. WARNING (Page 9-9) Domain mode error: <reason> A check of the tables that control polynomial coeff- icient arithmetic has revealed an error. This should only occur if a user has introduced a new coeff- icient mode (Page 9-9) End-of-file read [in file ID] There was a missing END in a file, or an end-of-file E-2 character had been typed on a terminal (Page 11-1) E invalid [in ID statement] The expression E is not permitted at this point in the (optionally) named statement (Page 5-1) E invalid as ID The expression E has been used in a context where ID was required (Page 9-1) Gamma5 not allowed unless vecdim is 4 Gamma5 has been used in a computation involving a vector dimension other than 4 (Page 17-6) ID invalid outside block An INTEGER, REAL or SCALAR declaration has been used outside a block. Such declarations should be deleted (Page 5-7) ID is a reserved identifier The reserved variable ID has not been used correctly (Page 2-3) ID not found ID was expected but could not be found (Page 7-11) ID not open An attempt has been made to shut a file that has not been opened for output (Page 11-2) ID redefined ID has been defined of a particular type more than once. WARNING (Page 7-10) ID too long for FORTRAN An identifier exceeds the size allowed for FORTRAN identifiers (Page 8-9) ID1 ID2 not set An object of type ID1 and name ID2 whose size is not yet known has been referenced (Page 13-2) ID1 declared ID2 ID1 has been declared of type ID2. Posed as a question in interactive mode. WARNING (Page 7-10) Improper delimiter An unexpected delimiter has been found at or near the marked position (Page 2-5) Incompatible DF rule argument length for ID A differentiation rule for the operator ID has been defined with a different number of operator arguments than a previous rule (Page 7-4) Index out of range A reference has been made to an array element or other structure outside the defined index range (Page 6-1) Invalid S-expression An ill-formed S-expression has been found on input at or near the marked point (Page 16-3) E-3 Invalid modular division A modular division in which the argument is not co-prime with the modulus has occurred (Page 9-10) MACRO ID used as function A MACRO has been used as a functional argument (Page 16-5) Matrix mismatch Two matrix expressions are not correctly matched for addition or multiplication (Page 13-2) Missing ID A symbol of type ID (e.g., matrix or vector) was expected and not found (Page 17-3) Missing arguments for G operator A line symbol is missing in a gamma matrix expression (Page 17-2) Missing operator An operator was expected at or near the marked position (Page 2-5) Non square matrix An invalid operation on a non square matrix has been requested (e.g., a trace) (Page 13-2) No file open CONT has been improperly called with no files open (Page 12-3) Redundant operator An unexpected operator was found at or near the marked position (Page 2-5) Redundant vector A redundant vector has been found in a vector expression (Page 17-3) Singular matrix A request has been made to invert a singular matrix (Page 13-2) Substitution for <expression> not allowed Indicates that <expression> is an invalid form in a LET or CLEAR statement (Page 10-4) Syntax error: <reason> A syntax error has been encountered in the input for the reason given (Page 2-5) Too few right parentheses Input syntax error (Page 2-5) Too many right parentheses Input syntax error (Page 2-5) Unmatched free variables <list> The variables in <list> have not been properly matched in a LET statement (Page 10-5) E-4 Unmatched index <list> Unmatched indices have been encountered during the evaluation of a gamma matrix expression (Page 17-4) V has no mass A variable encountered in an MSHELL declaration has no mass assigned to it (Page 17-5) Wrong number of arguments to ID ID has been called with the wrong number of arguments (Page 3-2) Zero denominator REDUCE cannot handle a zero denominator (Page 3-2) 0**0 formed REDUCE cannot handle 0**0 (Page 3-2) 0/0 formed REDUCE cannot handle 0/0 (Page 3-2) <id> not defined as switch ON or OFF have been called on an unknown switch (Page 6-2) <number1> represented by <number2> Real <number1> has been converted to rational <number2>. WARNING (Page 3-2) F-1 F. VARIABLES IN REDUCE ←←←←←←←←← ←← ←←←←←← The following variables are defined in the basic REDUCE system. Variables prefixed or suffixed with an asterisk are changeable, either by the user or the system as appropriate. In particular, the mode switches (q.v.) are based on a corresponding variable prefixed by an asterisk that is either true or false depending on whether the switch is on or off. E.g., the switch COMP corresponds to the internal variable !*COMP. Such switch variables are not listed in this section. A Reserved only in arguments of the G operator in the high energy physics package to denote gamma5. May be used freely elsewhere (Page 17-2) CARDNO!* Value is the total number of lines produced in a given FORTRAN output expression (Page 8-11) FORTWIDTH!* Value is the current line width for FORTRAN output (Page 8-11) HIPOW!* Set by COEFF to highest power encountered (Page 8-14) LOWPOW!* Set by COEFF to lowest power encountered (Page 8-14) !*MODE Value is the current top level mode of the system. May be accessed in either algebraic or symbolic mode (Page 16-1) G-1 G. KEYWORD INDEX ←←←←←←← ←←←←← ALGINT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-1 ANUM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-1 Abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-1 Algebraic←mode. . . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 Allfac. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-5 Antisymmetric . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-9 Append. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-2 Arbitrary←precision←real. . . . . . . . . . . . . . . . . . . . . . 9-10 Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1 Assignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-4 Asymptotic. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 Begin...end . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Bigfloat. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11 Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Body. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-2 Bye . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-3 Call←by←value . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-4 Canonical←form. . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 Cardno!*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-9 Character←set . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 Clear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-5 Coeff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-13 G-2 Coefficient . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-9 Coeffn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-14 Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1 Command←table . . . . . . . . . . . . . . . . . . . . . . . . . . . .C-1 Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 Comp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-10 Compound←statement. . . . . . . . . . . . . . . . . . . . . . . . . .5-2 . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Conditional←statement . . . . . . . . . . . . . . . . . . . . . . . .5-3 Cons. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-1 Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-6 Cont. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 Cref. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-2 Cross←reference . . . . . . . . . . . . . . . . . . . . . . . . . . 18-2 Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1 Define. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-3 Defn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-5 Deg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Degree. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Den . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Denominator . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Depend. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-11 Det . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3 Df. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-3 Differentiation . . . . . . . . . . . . . . . . . . . . . . . . . . .7-3 G-3 Dirac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Dirac←trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-1 Div . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-5 Do. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-5 Dollar←sign . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 Dot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-1 EXCALC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-1 Echo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 Ed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-2 Editdef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-2 End . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 Eps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-3 Equation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .E-1 Error←table . . . . . . . . . . . . . . . . . . . . . . . . . . . . .E-1 Evenp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Exclamation←point . . . . . . . . . . . . . . . . . . . . . . . . . .2-2 Exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-1 Expression. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 Factor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-4 Factorization . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-2 Factorize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-2 Fap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Fasl. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 G-4 Faslout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Fast←loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 File←handling . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 First . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Fixp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 For←all . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-5 For←each. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-4 Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-9 Freeof. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 GENTRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2 GROEBNER. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2 Gamma←matrix. . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 Gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-5 General←substitution. . . . . . . . . . . . . . . . . . . . . . . . 10-6 Go. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-9 Goto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-9 Groebner←Basis. . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2 Group←statement . . . . . . . . . . . . . . . . . . . . . . . . . . .5-2 G-5 HIPOW!* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-14 High←energy←physics . . . . . . . . . . . . . . . . . . . . . . . . 17-1 History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-1 Identifier. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-2 If. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-3 In. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-1 Infix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-5 Infix←operator. . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-1 Instant←evaluation. . . . . . . . . . . . . . . . . . . . . . . . . .6-1 . . . . . . . . . . . . . . . . . . . . . . . . . 10-4 . . . . . . . . . . . . . . . . . . . . . . . . . 10-7 . . . . . . . . . . . . . . . . . . . . . . . . . 13-2 Int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-4 Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-4 Interactive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-1 I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 Kernel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 Keyword←index . . . . . . . . . . . . . . . . . . . . . . . . . . . .G-1 Korder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-13 LISP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 LOWPOW!*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-14 Label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-9 G-6 Lambda. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-3 Lcm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-5 Lcof. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Leading←coefficient . . . . . . . . . . . . . . . . . . . . . . . . .9-7 Leading←term. . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Length. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-2 Let . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-4 Lhs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 Line←length . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-3 Linear. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-8 Linear←operator . . . . . . . . . . . . . . . . . . . . . . . . . . .7-8 List. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-5 List←operations . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Load. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Loop. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 Lterm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Main←variable . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Mainvar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Mass. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-5 Mat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-1 Match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-6 Mathematical←functions. . . . . . . . . . . . . . . . . . . . . . . .7-1 Matrix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-1 G-7 Max . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-1 Mcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-5 Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .E-1 Min . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-1 Mkid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-6 Mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 Mode←communication. . . . . . . . . . . . . . . . . . . . . . . . . 16-5 Modular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-10 Mshell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-5 Multiple←assignment←statement . . . . . . . . . . . . . . . . . . . .5-2 Nero. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-9 New←Infix←Operator. . . . . . . . . . . . . . . . . . . . . . . . . 7-11 New←Prefix←Operator . . . . . . . . . . . . . . . . . . . . . . . . 7-10 Nodepend. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-11 Noncom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-9 Noncommuting←operator . . . . . . . . . . . . . . . . . . . . . . . .7-9 Nospur. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Num . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Number. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 Numberp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 Numerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Numerical←function. . . . . . . . . . . . . . . . . . . . . . . . . .7-1 Numval. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-2 Off . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 On. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 Operator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 G-8 Operator←table. . . . . . . . . . . . . . . . . . . . . . . . . . . .B-1 Order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-4 Ordp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-9 Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 Output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-1 Output←declaration. . . . . . . . . . . . . . . . . . . . . . . . . .8-3 Part. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-14 Pause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3 Polynomial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-1 Precedence. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-11 Precedence←list . . . . . . . . . . . . . . . . . . . . . . . . . . .2-6 Precision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-10 Prefix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-1 Prefix←operator . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 Pret. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-4 Prettyprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-4 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-9 Procedure←heading . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 Product . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 Proper←statement. . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 Qcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-6 G-9 Quit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-3 Quote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-3 RLISP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 Rat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-6 Rational←coefficient. . . . . . . . . . . . . . . . . . . . . . . . .9-9 Rational←function . . . . . . . . . . . . . . . . . . . . . . . . . .9-1 Ratpri. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-6 Real. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Real←coefficient. . . . . . . . . . . . . . . . . . . . . . . . . . .9-9 Rederr. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3 Reduced . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-2 Reduct. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Reductum. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-8 Remainder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-6 Remfac. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-4 Rename. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-3 Repea1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-6 Reserved. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .A-1 Reserved←variable . . . . . . . . . . . . . . . . . . . . . . . . . .2-3 Rest. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Resultant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-6 Return. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-9 Reverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-2 Revpri. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-7 Rhs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 SPDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-2 G-10 Save. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-11 Scalar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-7 Second. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Selector. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-6 Semicolon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 Series. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-2 Share . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-5 Showtime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-3 Shut. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-2 Side←effect . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-4 Simplification. . . . . . . . . . . . . . . . . . . . . . . . . . . .3-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 Solve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-6 Spur. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Standard←form . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-6 Standard←quotient . . . . . . . . . . . . . . . . . . . . . . . . . 16-6 Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 String. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 Structr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-12 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-12 Structuring . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 Sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1 Subroutine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-1 Substitution. . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1 Such←that . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-5 G-11 Sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-4 Switch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 Switch←table. . . . . . . . . . . . . . . . . . . . . . . . . . . . .D-1 Symbolic←assignment . . . . . . . . . . . . . . . . . . . . . . . . 16-4 Symbolic←mode . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-1 Symmetric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-9 Terminator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1 Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-1 Third . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 Time. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-2 Tp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3 Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3 Truncation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 Until . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-6 User←packages . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-1 Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-1 Variable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-3 Variable←table. . . . . . . . . . . . . . . . . . . . . . . . . . . .F-1 Varname . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-12 Vector. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-3 WS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-1 Weight. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 Where . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-3 While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-5 Workspace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-2 G-12 Write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-7 Wtlevel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-9 % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-2