.<<< to run this off, do deqn newmacs primer1.n | ditroff -me -Pip {or equivalent} .Lc MACSYMA\ Primer\ for\ UNIX 1 .(l C adapted and edited by Richard J. Fateman \fIUniversity of California Berkeley \fP from material by Joel Moses \fI Massachusetts Institute of Technology\fP .pp .sh 2 Introduction .pp .EQ delim @@ .EN .Ma (pronounced ``maxima''\**) .(f \** (The acronym stands for Project MAC's SYmbolic MAnipulation System. ``MAC'' itself is an acronym, usually cited as meaning Man and Computer or Machine Aided Cognition. The Laboratory for Computer Science at the Massachusetts Institute of Technology was known as Project MAC during the initial development of MACSYMA.) .)f is a large computer program designed for the manipulation of algebraic expressions. You can use .Ma for manipulation of algebraic expressions involving constants, variables, and functions. It can differentiate, integrate, take limits, solve equations, factor polynomials, expand functions in power series, and perform many other operations. You can use a programming language to extend .Ma 's capabilities to new domains. .pp A few of the system's most-used capabilities are described in this primer. A more complete discussion of these features and others for more specialized interests may be found in the .Ma Reference Manual. Additionally, information about each command is available through an on-line documentation retrieval command, \f(CWdescribe.\fP To see a blurb on, for example, \f(CWexpand,\fP type \f(CWdescribe(expand);\fP to the system. For some commands, an \f(CWexample\fP is also available, and can be viewed by typing, for instance, \f(CWexample(expand);\fP .sh 2 Starting\ Up .pp On most UNIX systems, the system may be loaded by typing \f(CWvaxima\fP to the shell prompt. It may be necessary to type \f(CW/usr/mac/vaxima\fP or some similar pathname on your system. Your computer system manager should know where the program is installed. If you expect to be using vaxima frequently, you should include in your .login script, a line setting the system variable VAXIMA to the home directory for vaxima documentation and programs. For example, .br \f(CW setenv VAXIMA /usr/mac \fP .pp If you are just starting to use .Ma now, you could just type this in now. (This assume you are using the usual ``C-shell'' command-line interpreter.) A few seconds after typing \f(CWvaxima\fP, the system will return with a heading and prompt resembling the text below. .eB \f(CW % vaxima .. set tabs in case they appear in fixed width displays below .ta .ta 41p +41p +41p +41p +41p +41p +41p +41p +41p +41p vaxima 2.04 Sun Jul 12 23:25:20 1982 (c1) \fP .eE The number 2.04 is a version identification number which will change from time to time, as will the day and date of the system construction. The label (c1) is a name being assigned automatically to your first command. (c labels are used for user-input commands, d-labels for .Ma output expressions.) .sh 2 Typing\ Expressions .pp Suppose you wanted to work with the expression @(x + 1) sup 3@. You could type it in by using Fortran-style syntax as follows: .eB \f(CW (c1) (x+1)**3; \fP .eE The ``;'' and the (invisible) ``carriage return'' terminates your command, and prompts .Ma to evaluate your expression, simplify it, and display the result. The character ``$'' may also be used to end a command line, in which case the result will be computed but not displayed. .pp In this case of command c1 above, the evaluation and simplification processes leave the expression unchanged, and .Ma responds with the display below. .eB \f(CW 3 (d1) (x + 1) (c2) \fP .eE .pp Note that the expression is normally printed in a two-dimensional format with raised superscripts. This usually makes the expression easier to understand than a linear format, although as you will see in later displays, it sometimes requires some effort. There is a more readable (but slower) typesetting display facility which requires more a elaborate computer terminal than the usual character-display type. .pp The result is assigned a label \f(CWd1\fP which may be used in subsequent commands. An important observation: the system is assigning values to the names \f(CWc1\fP, \f(CWd1\fP, etc. You should avoid using these same names for other purposes in your computations. .pp If you choose to leave .Ma at this point, or any time a \f(CWc-line\fP prompt appears, type \f(CW quit();\fP. If you wish to stop in the midst of a computation and quit in a less orderly fashion, type -z (that's one character), to get back to the UNIX shell, and \f(CW kill % \fP. .pp After the display, .Ma prompts you with the next line label, \f(CWc2\fP. .sh 2 Your\ Next\ Command .pp One of the many commands available in .Ma is the \f(CWexpand\fP command, which converts an expression to an mathematically equivalent one, but with certain changes in the form. Most commands have the form of a ``function'' being applied to some arguments. In this case, the expression labelled \f(CWd1\fP above is the single argument to \f(CWexpand\fP. .eB \f(CW (c2) expand(d1); 3 2 (d2) x + 3 x + 3 x + 1 \fP .eE .sh 2 Typing\ Errors .pp Before getting too involved, you should realize that if you make a mistake in typing, you can delete erroneous characters by using your standard UNIX erase, kill, word-kill, etc. characters. (Typically these are backspace, control-U, control-W, respectively) If you wish to delete all lines of a multi-line command, typing ?? will give you a freshly re-typed line label. .pp If you make a mistake but type the semi-colon and return before you notice, the system will provide a message: .eB \f(CW (c2) expand((d1); expand (( d1) ***$*** syntax error please rephrase or edit. (c2) \fP .eE If you are a novice at using the computer, you should probably retype the expression. Editing involves the use of one of the system text editors, and is described in the manual. .sh 2 More\ Commands .pp Let us consider a few additional commands and facilities. To differentiate an expression, use the \f(CWdiff\fP command. \f(CWDiff(expr,var)\fP differentiates an expression with respect to the variable \f(CWvar\fP. .eB \f(CW (c3) sin(x)*cos(x); (d3) cos(x) sin(x) (c4) diff(%,x); 2 2 (d4) cos (x) - sin (x) \fP .eE .pp Note the use of the symbol \f(CW%\fP in line \f(CWc4\fP. This symbol is a shorthand for the previous expression computed, which in this case is \f(CWd3.\fP .pp To differentiate an expression twice, use \f(CWdiff(expr,var,2)\fP. .eB \f(CW (c5) diff(d3,x,2); (d5) - 4 cos(x) sin(x) \fP .eE The concept of differentiation is actually a good deal more general than is illustrated by this example. Application of the chain rule is generally supported, and a large repertoire of built-in functions and operations are provided. .sh 2 Substitution .pp There are a number of ways of producing a new expression from an old one by substitution. For example, to substitute @x sup 2 @ for every occurrence of @z@ in the expression @ z e sup z @ you could type .eB \f(CW (c6) z*%e**z; z (d6) z %e (c7) d6,z=x**2; 2 2 x (d7) x %e \fP .eE In .Ma , the base of the natural logarithms is written \f(CW%e\fP, to distinguish it from a simple variable named \f(CWe\fP. @ sqrt -1 @ is written as \f(CW%i\fP and @pi @ is written \f(CW%pi.\fP .pp An alternative syntax for exactly the same command as that on line \f(CWc7\fP is to explicitly invoke the \f(CWev\fP command (for evaluation in a context where @ z = x sup 2 @ ). .Eb \f(CW (c8) ev(d6,z=x**2); 2 2 x (d8) x %e \fP .eE .pp The \f(CWev\fP command has more elaborate options and uses. \f(CWEv\fP ``evaluates'' the first expression (leftmost argument) in an environment specified by the additional expressions which are either equations as shown above, or built-in ``switches'' which control .Ma . .pp An equivalent command in this particular case, is \f(CWsubstitute\fP, which is limited to the simpler semantics we use. You can abbreviate the command as \f(CWsubst\fP: .eB \f(CW (c9) subst(x**2,z,d6); 2 2 x (d9) x %e \fP .eE Note the order of arguments to \f(CWsubstitute\fP: substitute \f(CWa\fP for \f(CWb\fP in \f(CWc\fP is written \f(CWsubst(a,b,c);\fP. .sh 2 Assignments .pp Although some very sophisticated linguistic facilities are available in .Ma , we will describe only a few of the basic features in this chapter. Assignment is very familiar to programmers, and associates a ``value'' with a name. .pp To assign a value to a variable, used a colon (:) as follows: .eB \f(CW (c10) a:%; 2 2 x (d10) x %e (c11) a+1; 2 2 x (d11) x %e + 1 \fP .eE .pp Many users are surprised when such values are used when they themselves have forgotten the existence of such assignments and reuse the same name as an ``indeterminate''. To ``unassign'' a value from \f(CWa\fP, say: .eB \f(CW (c12) kill(a); (d12) done \fP .eE Now if you ask for the value of \f(CWa\fP, you get: .eB \f(CW (c13) a; (d13) a \fP .eE .sh 2 Defining\ Functions .pp The process of function definition is similar to assignment, but associates ``parameters'' or ``arguments'' with the name, and associates a computation with the use of the name: the value which is produced is basically the result of substituting values with names in the associated expression. For example, to define a function @f ( z )@ which will be, essentially, a short-hand for @sin sup 2 z + 1 @ you use ``:='' as follows: .eB \f(CW (c14) f(z) := sin(z)**2+1; 2 (d14) f(z) := sin (z) + 1 (c15) f(x+1); 2 (d15) sin (x + 1) + 1 \fP .eE It is possible to define functions which use any of the built-in .Ma commands, or use user-defined functions. Although we have illustrated only a few simple built-in commands, .Ma provides you with a complete programming language. This may not be a comfort to you if you are totally unfamiliar with programming, but if you want to use .Ma for elaborate processing of mathematical equations or data, you may have to learn some of this. If you have some familiarity with some conventional programming languages, you may be pleasantly surprised by the additional generality afforded by ``symbolic'' computation. Further on in this primer we give some examples of the language of .Ma . .pp If you type a command such as \f(CWg(z)\fP, where \f(CWg\f(CW is otherwise undefined, .Ma will treat it as an ``unknown'' function, similar to an indeterminate. .sh 2 Equations,\ Parts,\ and\ Solve .pp Sometimes it is convenient to compute with equations in .Ma . An equation is not the same as an assignment, a function definition, or a test for equality. Some programming languages overuse the symbol ``='' for some of these, but .Ma does not. In .Ma , an equation is just an expression containing two subexpressions separated by an ``=''. Certain simplification and evaluation operations are defined to work in (usually) conventional ways on equations, as illustrated below. Line \f(CWc16\fP shows how to type in an equation. .eB \f(CW (c16) x**2+2*x=y**2; 2 2 (d16) x + 2 x = y (c17) d16+1; 2 2 (d17) x + 2 x + 1 = y + 1 \fP .eE The left-hand-side of an equation can be selected with the \f(CWlhs\fP command, or by the more general \f(CWpart\fP command which can be used to pick apart expressions such as sums, products, etc. .eB \f(CW (c18) lhs(%); 2 (d18) x + 2 x + 1 (c19) part(d17,2); 2 (d19) y + 1 (c20) part(%,1); 2 (d20) y \fP .eE To save typing, the same result as \f(CWd20\fP could have been obtained from \f(CWpart(part(d17,2),1)\fP or even more simply, \f(CWpart(d17,2,1)\fP. .pp Equations are used by some commands, and are, for example, used by the \f(CWsolve\fP command. They are returned in a \f(CWlist\fP, that is, a sequence separated by commas and enclosed in square brackets: .eB \f(CW (c21) x**2-1; 2 (d21) x - 1 (c22) solve(%,x); (d22) [x = - 1, x = 1] \fP .eE Notice the way the list of the two solutions is displayed. We can substitute the first of the two answers in \f(CWd21\fP, and evaluate: .eB \f(CW (c23) d21,part(%,1); (d23) 0 \fP .eE .sh 2 Sums,\ Programs,\ Ev\ revisited .pp The sum of the first five positive integers, squared, can be computed by: .eB \f(CW (c24) sum(i**2,i,1,5); (d24) 55 \fP .eE Another way of providing a similar result by writing a small program, is to use a \f(CWfor\fP statement. .eB \f(CW (c25) for i:1 step 1 thru 5 do s:s+i**2 ; (d25) done \fP .eE The result is stored as the value of the variable \f(CWs\fP. If \f(CWs\fP had been 0 previously, the current value of \f(CWs\fP would be 55. Actually, .eB \f(CW (c26) s; (d26) s + 55 \fP .eE This reflects the fact that the value of \f(CWs\fP initially was just \f(CWs\fP. We can, of course, substitute 0 for the original value: .eB \f(CW (c27) %,s=0; (d27) 55 \fP .eE Note that this substitution does not affect the value of \f(CWs\fP. It just sets \f(CWd27\fP to 55. A more mysterious case is to see what happens if we type .eB \f(CW (c28) ev(s+55); (d28) s + 165 \fP .eE [explanation: if we had typed merely s+55, it would evaluate to (s+55)+55, or s+110. But \f(CWev\fP evaluates ``once more'' to get (s+55)+110. \f(CWEv\fP is a puzzle and an addiction.] .pp In spite of the previous example, summations are not \f(CWreally\fP the same as the programming languages' ``for loops''. Sometimes summations are merely placeholders for computations which for one reason or another cannot be done. This is an example: .eB \f(CW (c29) 'sum(g(i),i,0,n); n ==== \e (d29) > g(i) / ==== i = 0 \fP .eE There are three reasons for this summation to be returned ``unsummed''. We have not provided a ``function definition'' for \f(CWg\fP; the variable \f(CWn\fP is not some fixed integer value; and finally the ``quote'' symbol or apostrophe (') to the left of the \f(CWsum\fP on line \f(CWc29\fP inhibits evaluation. The effect of the quote is, in most circumstances the prevention of evaluation. Sometimes .Ma can deduce the value of a summation in closed form even though it cannot be evaluated, because of built-in simplification capabilities. Some summations can, for example, be solved by a fairly general procedure analogous to symbolic integration. .pp In .Ma a distinction is sometimes drawn between ``noun'' and ``verb'' forms of commands. Most functions are ``verbs'' in that they will be evaluated ``away'' in an effort to eliminate them from expressions. To prevent such evaluation, the ``quote'' illustrated above can generally be used. Some functions are nouns or verbs depending upon context such as the nature of their arguments. The trigonometric functions are this way, being nouns if they are given integer arguments, but verbs if they are given floating-point arguments, or \f(CWev\fP'd with the \f(CWnumer\fP option set: .eB \f(CW (c30) sin(1); (d30) sin(1) (c31) sin(1),numer; (d31) 0.8414709848078965 \fP .eE Floating-point numbers are carried to double precision. There is also an implementation of higher (arbitrarily higher!) precision ``bigfloats'' available and described in the manual. .sh 2 More\ Expansion .pp Let us return to our very first example of a command, and provide some more details and techniques for expansion, or application of the distributive law of multiplication. In some computations where an indeterminate represents a quantity of small magnitude, you might wish to automatically drop higher-degree terms from an expansion. In some cases you might wish to drop terms in several variables, e.g. all terms in @q@ with exponent greater than 7, and terms in @p@ with exponent greater than 4, or terms of @p sup n @ and @q sup m @ combined so that their ``weight'' @2 n + m@ exceeds 7. This sequence of commands does that: .eB \f(CW (c32) ratwtlvl:7$ (c33) ratweight(q,1,p,2); (d33) [q, 1, p, 2] (c34) ratexpand((p+q+1)^8); 7 6 5 5 4 4 2 3 3 (d34) 8 q + 28 q + 168 p q + 56 q + 280 p q + 70 q + 560 p q + 280 p q 3 2 2 2 2 3 2 + 56 q + 420 p q + 168 p q + 28 q + 280 p q + 168 p q + 56 p q + 8 q 3 2 + 56 p + 28 p + 8 p + 1 \fP .eE The ``rats'' appearing in the command names here are an indication that the commands use something called ``canonical RATional expression form'', an efficient form used for dealing with polynomials and ratios of polynomials. We have also used ``^'' instead of ``**'' (the two notations are interchangeable in .Ma .) We will return to representation issue shortly. .sh 2 Integration .pp One of .Ma 's flashiest features is its ability to compute symbolic indefinite integrals: .eB \f(CW (c35) x/(x^3+1); x (d35) ------ 3 x + 1 (c36) integrate(%,x); 2 x - 1 2 atan(-------) log(x - x + 1) sqrt(3) log(x + 1) (d36) --------------- + ------------- - ---------- 6 sqrt(3) 3 \fP .eE To check the solution, we can differentiate. .eB \f(CW (c37) diff(%,x); 2 2 x - 1 1 (d37) ------------------ + -------------- - --------- 2 2 3 (x + 1) (2 x - 1) 6 (x - x + 1) 3 (---------- + 1) 3 \fP .eE A more satisfactory form would result if the terms were expanded and the sum put over a common denominator. By converting this result to a canonical rational form (the same form used for the previous RAT commands) the expression is simplified. The \f(CWratsimp\fP command does this: .eB \f(CW (c38) ratsimp(%); x (d38) ------ 3 x + 1 \fP .eE .sh 2 Representation\ and\ Simplification .pp The multiplicity of representations illustrated by lines d38 and d37 constitute an important feature of .Ma . It is not always so clear which command will produce the most appealing form of an expression. \f(CWRatsimp\fP, which did such a fine job above, would produce a huge expression if applied to @ (x + 5) sup 100 @, since it multiplies through all those terms. .pp The correct choice of representation is often the key to solving challenging problems. .pp The \f(CWfactor\fP command is another way of changing representation, illustrated below. .eB \f(CW (c39) factor(x^12+1); 4 8 4 (d39) (x + 1) (x - x + 1) \fP .eE .pp \f(CWFactor\fP finds exact integral factors, not approximate zeros, and is thus qualitatively different from numerical root-finders. It is generally much slower than numerical routines, but gives a different type of answer, as illustrated above. If your system has a numerical program library for zero finding, it can probably be connected to .Ma . For example, on VAX systems licensed to use the IMSL library, a routine called \f(CWzrpoly\fP is available, which finds approximate zeros for real polynomials. .pp \f(CWFactor\fP and \f(CWintegrate\fP are probably two of the more surprising commands in .Ma because most people who understand the problems involved are not familiar with general algorithms for solving them. There \f(CWare\fP general algorithms for these problems, although the algorithm for integration sometimes indicates that the answer does not exist in terms of elementary functions. When a general solution to a problem is not available, or even when it is known but inefficient, it is sometimes possible to simulate a good solution method by ``pattern recognition'': that is, by recognizing those cases that can be solved, and providing the answers, without dealing with the complete problem. Many user programs, and a few built-in .Ma facilities use this approach. .pp \f(CWFactor\fP, and indeed many of the commands illustrated above, are used internally by .Ma for its own more complicated algorithms. For example, \f(CWsolve\fP uses \f(CWfactor\fP and other routines on polynomial problems. .sh 2 Limitations .pp You should realize that an algebraic manipulation system like .Ma cannot solve all symbolic problems. .ip There are times when \f(CWsolve\fP or \f(CWintegrate\fP or other commands will determine that there are no closed-form solutions to the problem posed (in which case they will generally inform you of the situation). .ip There are other instances in which the solution method may be known in principal, but because the calculations are so onerous, the computer seems unlikely to finish in a reasonable time. Algebraic computations are often subject to ``intermediate expression swell'' where (even though the final answer may be small -- perhaps 0), the route to the answer is difficult. .ip Occasionally you may run out of memory space. A clever computer system administrator change the program and operating system parameters to your benefit, but it is more likely that you could try to rearrange your computations. .pp Just because it is possible to type a command in a syntactically satisfactory manner does not mean that the required computation is easy or even feasible. Once a computation has started, you may have second thoughts about allowing it to finish. Hence you might be concerned with the information in the next section: .sh 2 Stopping .pp You may, from time to time, get your system running on a fool's errand. How do you bring it to its senses? .pp There are several related notions of running uncontrollably. If the output is streaming past you at too high a speed to read, (this is unlikely to happen on a slow printing terminal, but might happen on a display terminal) you can make the system pause by typing -S (that's done by holding the control key down and typing S. We usually write this as ^S), which is the default ``X-off'' character. Normally, no output gets lost, but transmission is temporarily halted. You can resume the display by typing -Q (or ``X-on''). .pp Sometimes you want to halt computation, not just printing. You have an interrupt character, usually or ^C, which you have chosen as your standard in your UNIX operating system shell. If you wish to halt a computation, you can type this interrupt character one, two, or three times. .LP The first character will cause an interrupt at the next available clean place in your computation. (Technically, this would be at the interface between some compiled and some interpreted code). If the interrupt does not happen promptly enough for you, you may type the interrupt character a second time. (Technically speaking, this will snap ``transfer links'' which are used when compiled code calls compiled code, and then cause an interrupt at the next such function-call.) It is possible to be caught in a very tight loop in which there are no function calls, in which case the third typing of the interrupt character will stop the computation \f(CWcold\fP. Even using this drastic interrupt, you will generally be able to avail yourself of any of several alternatives. .lp When the system stops, it will type .eB \f(CW Interrupt (type h for help): \fP .eE .lp You can then type one of several atoms: .ip q Just quit out of the interrupt and continue the computation (after displaying the time if \f(CW showtime \fP was set to \f(CWtrue \fP or \f(CW all.\fP); .ip r Reset the computation to the top-level of .Ma , .ip exit Exit from .Ma , .ip l Enter a LISP break, (something a LISP expert might want to do: LISP, an acronym for LISt Processing Language, is the computer language in which .Ma is implemented.), .ip m Enter a .Ma -break. This gives you a kind of .Ma -subprocess within your running program, which you can use to inquire about variables, resetting things, etc. You exit by typing \f(CWexit;\fP which returns you to your previous computation. .ip h Type a menu of options. Basically what you see above. .pp It is also possible to quit temporarily out of your job by typing ^Z. See your UNIX manual for details on job control, background jobs, and similar issues. Some people, in desperation, hang up their telephone. This might work, assuming you are connected to the computer that way. Turning the power off on a hard-wired terminal usually does not work. .sh 2 Out\ of\ Core? .pp In the 4BSD UNIX system, the message 'killed' or 'out of core' immediately after the starting of a vaxima means that there is currently insufficient free space on the swapping device to run .Ma . This can happen with any job, but is perhaps more likely to happen with .Ma because of its size. This situation is system-load dependent and swap-space dependent: when the load decreases, try again. .sh 2 Quitting .pp If you wish to exit from .Ma , in an orderly fashion, removing the quiescent job, returning control to the shell (or whatever invoked .Ma ), you can do this by typing the command \f(CWexit();\fP .sh 2 Storage\ Allocation\ and\ Timing .pp If you run .Ma for long enough, and especially if you set up a long computation, you will see strange messages like the two below: .eB \f(CW [*list:634{22%}; fixnum:43{2%}; ut:0%] [*list:634{23%}; fixnum:43{2%}; ut:69%] \fP .eE This is caused by a phenomenon known as a ``garbage collection'' (really) which is part of the underlying LISP language system. This is an activity started up when the computation needs more free storage. The system then stops doing ``useful'' work, and identifies objects in memory which are no longer needed. This takes a few seconds of computer time (maybe 2), which under heavy load may take a half-minute of real time. .pp A message occurs after each garbage collection. You cannot really stop the garbage collector, but you can stop the message from printing out by setting \f(CWgcprint : false \fP. You may think you don't want to see this information, but it is actually reassuring to know that your program \f(CWis\fP running sometimes, even though it is printing nothing but ``gc'' messages. .pp Programs which may have run out of storage on other version of .Ma may run successfully on the VAX. However, the address space available to a user is in practice restricted by operating system constraints, some of which have been incorporated as parameters in the LISP system. An error message which declares ``Attempt to allocate beyond static structures'' indicates that you will have to have a reconfigured LISP system to grow larger. You should save your computation and ask your system administration or manager to make a larger LISP system and .Ma . This takes about 3 or 4 minutes of computation, but requires familiarity with the instructions for generating a system. Since the current allocation is really fairly large, you should also take this opportunity to see if you really want to continue with the computation. Large jobs in most time-sharing systems, tend to be more burdensome than small ones, even those running for longer periods of time. .pp It is possible to fiddle with various allocations to attempt to decrease the number of garbage collections in a system which you suspect will require large amounts of a particular kind of space. The command \f(CWalloc(,)\fP allocates some number of pages. Spacetypes include \f(CWlist, bignum, fixnum, flonum, array \fP and a few others. Most .Ma computations use .i list cells predominantly. See the Franz LISP manual for more details. .pp The message ``[fasl hole filled up]'' which you may provoke by using the \f(CWfasl\fP or \f(CWload\fP program, is merely informative, and is not an indication of trouble. .pp If the .Ma variable \f(CW gcprint \fP is set to a non-false value then after each garbage collection a summary of current memory allocation will be printed out in this form: [*list:634{87%}; fixnum:23{27%}; ut:87%]. The meaning of this is that after garbage collection and subsequent allocation of new data space, there are 634 (512 byte) pages of list data and 23 pages of fixnum data. 87% of the list space is used and 27% of the fixnum space is used. The * before list indicates that it was list space which ran out and caused the garbage collection. The ut indicates the percentage of time utilized in non-garbage collection mode. The first time the message is printed, this item will be 0% because various counters must be initialized. The allocation of storage is automatic; you will never be asked to make a decision about which data space to allocate, although a low utilization measure is an indication that automatic allocation is not working appropriately for your problem, and various parameters can be fiddled with via \f(CWalloc\fP. .pp You can also get brief information about the time taken by each command by setting \f(CW showtime : all\fP. The ``garbage collection'' or ``gc'' time is indicated separately, because it happens asynchronously and it seems unfair to penalize a particular (perhaps millisecond) operation for the fact that it was the unlucky one to trigger a ``gc''. .ce \f(CWIntermission. Take a break.\fP .pp In the next two sections of the primer we introduce a number of facilities in .Ma useful in dealing with trigonometric functions. A section on rule-directed transformations follows, since our favorite examples are trigonometry simplifications. .sh 2 Operations\ with\ Trigonometric\ Forms .pp Consider the expression @ cos sup 2 x - sin sup 2 x @. .eB \f(CW (c40) cos(x)^2-sin(x)^2; 2 2 (d40) cos (x) - sin (x) \fP .eE .pp To evaluate the last expression at a point, say @pi / 3 @, you can use the \f(CWev\fP command: .eB \f(CW (c41)ev(%,x=%pi/3) 1 (d41) - - 2 \fP .eE .pp The value of @1 / 2 @ was obtained not by computing @ pi / 3 @ numerically and approximating the value of @sin@ at that point, but by a routine which provides simplification of special values of trigonometric functions at points @ n pi / m @, where @m@ = 1,2,3,4,6 and @n@ is an integer. To obtain a real approximation, we could use \f(CWnumer, \fP as illustrated previously. .pp Of course .Ma is able to differentiate expressions involving trigonometric functions, also as illustrated previously. .eB \f(CW (c42) diff(d40,x); (d42) - 4 cos(x) sin(x) \fP .eE and knows how to integrate them. .eB \f(CW (c43) integrate(d40,x); sin(2 x) sin(2 x) -------- + x x - -------- 2 2 (d43) ------------ - ------------ 2 2 \fP .eE This result is less than satisfactory. See what we can do: .eB \f(CW (c44) expand(%); sin(2 x) (d44) -------- 2 \fP .eE .sh 2 Trigonometric\ Re-representations\ and\ Identities .pp There are a number of identity transformations specifically oriented to trigonometric forms. Whether these produce simpler or more complex expressions depends on the expressions they are used upon, and sometimes is a matter of opinion. .Ma can convert trigonometric functions with argument @nx@, @n@ an integer, to trigonometric functions in @x@. You use \f(CWtrigexpand\fP for this transformation: .eB \f(CW (c45) trigexpand(%); (d45) cos(x) sin(x) \fP .eE .pp Another operation named \f(CWtrigreduce\fP performs a related, almost ``inverse'' transformation, that of converting products of powers of trigonometric functions to functions with multiple angles. .eB \f(CW (c46) trigreduce(%); sin(2 x) (d46) -------- 2 \fP .eE .pp Sometimes you wish to convert all trigonometric functions to exponentials with complex arguments. With the flag \f(CWexponentialize\fP set to \f(CWtrue \fP you can perform this transformation: .eB \f(CW (c47) exponentialize:true$ (c48) sin(x); %i x - %i x %i (%e - %e ) (d48) - ---------------------- 2 \fP .eE .pp In order to convert back to trigonometric functions you can use \f(CW realpart.\fP First we must turn off the exponentialize flag. .eB \f(CW (c49) exponentialize:false$ (c50) realpart(d48); (d50) sin(x) \fP .eE .pp Exponentials with complex arguments of the form @n i pi / m , ~~~m = 1,2,3,4,6@, @n@ an integer, will be transformed to algebraic numbers if the flag\f(CW %emode\fP is set to \f(CWtrue.\fP .eB \f(CW (c51) %emode:true$ (c52) d50,x=%pi; (d52) 0 \fP .eE .pp Before continuing, let's reset that flag. .eB \f(CW (c53) %emode:false$ \fP .eE .pp A very powerful technique for approximation of analytic functions is the use of truncated Taylor series (more generally, Laurent series). .Ma provides a command for the computation of these approximations, as illustrated below: .eB \f(CW (c54) taylor(sin(x)/x,x,0,4); 2 4 x x (d54)/t/ 1 - -- + --- + . . . 6 120 \fP .eE This is a Taylor series in @x@ about @x=0@ up to the 4th power. Observe that the display has some unusual features: the terms are ordered in reverse of the conventional (non-series) display, there is a \f(CW/t/ \fP mark near the label, and the ellipsis (. . .) is printed to the right to indicate truncation of other terms. Taylor series are a separate representation of expressions in .Ma . Recall that we have encountered the ``rational'' representation used internally by commands like \f(CWratsimp, factor,\fP and sometimes in \f(CWintegrate. \fP This form can also be directly provided in answers from some commands. All along we have been seeing a ``usual'' or ``general'' representation in our interactions. Thus we have already seen evidence of three representations. Many of .Ma 's most powerful commands for simplification are essentially switching between representations. There are a few more representations in the system directly accessible by the user such as ``Poisson'' series, used in celestial mechanics; there are a number of additional alternative representations used, but away from the user's sight. .sh 2 Rules .pp It is handy to have a facility for applying identities or side relations. The prototypical one is @ sin sup 2 x ~+~ cos sup 2 x ~ -> ~ 1 @ . There are a number of ways of achieving the effect of such a rule. The simplest is substitution. Let us recall expression d40. .eB \f(CW (c55) d40; 2 2 (d55) cos (x) - sin (x) (c56) %,sin(x)^2=1-cos(x)^2; 2 (d56) 2 cos (x) - 1 \fP .eE The same effect could have been achieved by using \f(CWsubstitute(1-cos(x)^2,sin(x)^2,%).\fP .pp To continue with the same prototypical rule, often one wishes to recognize that @sin sup 4 x @ can be transformed using the same rule. For this one needs the added power of \f(CWratsubst.\fP .eB \f(CW (c57) ratsubst(1-cos(x)^2,sin(x)^2,sin(x)^4); 4 2 (d57) cos (x) - 2 cos (x) + 1 \fP .eE .pp In general \f(CWratsubst\fP will perform a \f(CWratsimp\fP (and thus an expansion) as well as apply the substitution. .pp When performing calculations repeatedly, you may wish to apply a substitution rule whenever possible. You can have an ``automatic'' facility, although not the full power of a \f(CWratsubst\fP command by using a \f(CWtellsimp\fP rule. .eB \f(CW (c58) tellsimp(sin(x)^2,1-cos(x)^2)$ (c59) (sin(x)+1)^2; 2 (d59) (sin(x) + 1) (c60) expand(%); 2 (d60) 2 sin(x) - cos (x) + 2 (c61) sin(x)^2; 2 (c61) 1 - cos (x) \fP .eE .pp You can ``tell the simplifier'' a more general rule which will convert @ sin sup 2 a @ to @ 1 - cos sup 2 a @ for any @a@ using a declaration: .eB \f(CW (c62) matchdeclare(a,true)$ (c63) tellsimp(sin(a)^2,1-cos(a)^2)$ (c64) sin(y)^2; 2 (d64) 1 - cos (y) \fP .eE .pp You should understand that the existence of such rules generally slows down the simplification of expressions with the same ``main operator'' as the \f(CWtellsimp\fP rules. In this case the main operator is ``^''. .pp Another rule-defining mechanism, \f(CWlet\fP has much of the power of a \f(CWratsubst,\fP although it will be applied only when using \f(CWletsimp.\fP First let us remove the \f(CWtellsimp\fP rule. .eB \f(CW (c65) kill(rules)$ (c66) let(sin(a)^2,1-cos(a)^2); 2 2 (d66) (sin (a) --> 1 - cos (a)) \fP .eE .pp Note that @a@ is still declared \f(CWtrue\fP for matching purposes. To effect a transformation using the \f(CWlet\fP rules, whatever their number, you use the \f(CWletsimp\fP command. .eB \f(CW (c67) sin(x)^4; 4 (d67) sin (x) (c68) letsimp(%); 4 2 (d68) cos (x) - 2 cos (x) + 1 \fP .eE .pp We have not exhausted .Ma facilities for dealing with trigonometric functions, or for that matter, its facilities for defining and applying rules. .pp Poisson series, mentioned earlier, deals with a special class of trigonometric expressions frequently used in celestial mechanics have a special representation. A program called \f(CWtrigsimp\fP may provide appropriate simplifications in a goal-driven fashion (to make the smallest expression). Other ways of defining rules and ``advising'' the simplifier are described in the .Ma manual. .Lc Introduction\ to\ MACSYMA\'s\ Programming\ Language 2 .sh 2 Introduction 2 1 .pp This second chapter of the primer on .Ma is intended for readers who are familiar with the basic ideas of algebraic manipulation from chapter 1, who know at least one programming language, and who wish to use .Ma for more ambitious tasks than can be handled in a few sequential commands. If you are familiar with Pascal or Algol 60, you will probably find this adequate as a programming background. Familiarity with Fortran or Basic is less useful. .pp .Ma 's user-programming language\** .(f \** The system-programming language used for implementing .Ma , namely LISP, is quite different. If you wish to see how .Ma was constructed, you need to know LISP to understand the source code. .)f is designed to allow you to define program modules or ``functions'' for algebraic manipulation. Each module uses zero or more arguments, and returns an algebraic expression. Since numbers are special cases of algebraic expressions, .Ma 's user-language can be used as a numeric language too. Because the language is implemented as an interpreter it is usually more general than compiler-based languages, and also tends to be rather slow in tight inner loops of simple operations, by comparison. It has novel linguistic features, some of which are illustrated below. .sh 2 Some\ Examples .pp \f(CWf1\fP and \f(CWf2\fP defined below, are versions of the ``factorial'' function. Observe the punctuation carefully. Assignment is ``:'', function definition is ``:='', statements are separated from one another by ``,'' [not .i terminated by commas]. The label ``loop'' is set off by a comma as though it were a statement too. We have added indentation to make the programs conform to what you might expect, but extra spaces and tabs are optional. There is a conditional execution statement (the \f(CWif\fP) which has an optional \f(CWelse\fP clause. .eB \f(CW (c1) f1(x):=if x<1 then 1 else x*f1(x-1)$ (c2) f1(5); (d2) 120 (c3) f2(x) := block ([temp], temp:1, while n > 1 do ( temp:n*temp, n:n-1), /*end while*/ temp)$ (c4) f2(5); (d4) 120 \fP .eE Observe the simplicity of using .Ma compared to, say, Pascal. There is no need to write a ``driver'' or main program with input or output commands. The input is provide through function application on an argument, and the output is the displayed value. .pp Every command or function in .Ma has a value, and may, in addition, have some side-effects, such as the setting of variables, or the printing of messages. .pp The \f(CWblock\fP construction illustrated above is analogous to a procedure declaration. The first part of it is a list of local variables, and following that, expressions which are evaluated in order. Certain expressions or commands make sense only within a block, not at .Ma 's command level: these are labels, \f(CWreturn\fPs and \f(CWgo\fPs. The semantics of each of these commands conforms to the usual intuitive meaning. If the last statement in a \f(CWblock\fP does not cause a transfer of control, and ``execution falls through the bottom'', the value returned from the \f(CW block\fP is the value of the last expression evaluated. .sh 2 Unconventional\ Conditionals .pp The next example shows a function with a side-effect, but the major point is to illustrate some subtleties which you may not have thought about in conditional statements (\f(CWif-then-else\fP). .pp If you were asked, ``Is A greater than B'', it would seem you could respond either ``yes'' or ``no''. In your conventional programming language, certainly, that would be a reasonable assumption. But really, wouldn't it be appropriate in some circumstances for you to answer, ``How should I know?''? .pp That option is preserved in .Ma . If the flag \f(CWprederror\fP is set to \f(CWtrue\fP, the default, and if .Ma is unable to evaluate a predicate, it signals an error, and unless directed otherwise, returns control to the top-level .Ma command monitor. However, if the \f(CWprederror\fP flag is \f(CWfalse\fP, execution continues to the next statement, ignoring both \f(CWthen\fP and \f(CW else\fP clauses! .pp This is illustrated below: .eB \f(CW (c5) test(x,y):=block([], if x > y then print(x, '' is greater than '', y) else print(x, '' is not greater than'', y), return(alldone))$ (c6) test(4,3); 4 is greater than 3 (d6) alldone (c7) test(3,4); 3 is not greater than 4 (d7) alldone (c8) test(y^2+1,-y); 2 MACSYMA was unable to evaluate the predicate: y + 1 > - y (c9) prederror:false$ (c10) test(y^2+1,-y); (d10) alldone \fP .eE Note that no message was printed for line \f(CWd10,\fP but the return value, ``alldone'' was displayed. .sh 2 Assumptions .pp What do YOU think? Is @y sup 2 + 1 ~>~ - y@? For this question to make sense, both sides of the inequality must be in the same ordered domain. We do not know, offhand, whether @y@ can assume values which are matrices, complex numbers, sets, or even programs! .pp If @y@ were known to be real, or more specifically, positive real, a program could try some deduction. .Ma has some features of this nature, as illustrated below. .eB \f(CW (c11) assume(y>0); (d11) [y > 0] (c12) test(y^2+1,-y); 2 y + 1 is greater than - y (d12) alldone \fP .eE If we wish .Ma to forget that assumption, .eB \f(CW (c13) forget(y>0); (d13) [y > 0] .eE .sh 2 Arbitrary\ Numbers\ of\ Parameters .pp Ambitious packages of programs have been written by many .Ma users. Sometimes the requirement that a command has a fixed number of arguments causes discomfort.\** .(f \** The language Pascal does not allow you to define a function \f(CWf\fP which can be used with a variable number of actual parameters, although the Pascal design includes built-in procedures with variable numbers of arguments (\f(CWwrite\fP for example). .)f It is possible to write a .Ma program which counts the number of arguments it is given, sets default values for others, and does any number of clever things. A simple example is shown below. Note the way the ``left-hand-side'' of the ``:='' is set up. .eB \f(CW (c14) prog3([l]) := block( [], print (''l is bound to'', l, '' and l[1] is '',l[1]), return(length(l)))$ (c15) prog3(a,b,c,d); l is bound to [a, b, c, d] and l[1] is a (d15) 4 (c16) prog3(a,b); l is bound to [a, b] and l[1] is a (d16) 2 \fP .eE .sh 2 Arrays .pp Arrays are a useful data structure, and are provided in most programming languages. .Ma provides arrays, but does not require that they be declared, or that they have numeric (integer) index-sets. Rather than writing a program to fill up an array and then iterating through all elements, sometimes it is easier to describe a program to generate elements as they are called for. Such array-associated functions are often quite convenient. The usual way you set them up is to provide specific values for certain index values, and then let others be assigned as needed. Note carefully the use of ``:='' and ``:''. .eB \f(CW (c17) a[4]:4*u; (d17) 4 u (c18) a[22/7]:%pi; (d18) %pi (c19) a[x]:mystery; (d19) mystery (c20) a[h]:=cos(h); (d20) a := cos(h) h (c21) a[3]; (d21) cos(3) (c22) a[x+1]; (d22) cos(x + 1) \fP .eE You might wonder what the value of @a@ is, after all this. Most disappointing: .eB \f(CW (c23) a; (d23) a \fP .eE The information that you are after is available this way: .eB \f(CW (c24) arrayinfo(a); 22 (d24) [hashed, 1, [3], [--], [4], [x], [x + 1]] 7 \fP .eE The list of information supplied indicates several aspects of the array. It is ``hashed'': uses the data-structure of a hash-table for storage (this is a common encoding trick discussed in data structure texts). The number of subscripts is 1. The specific indexes for which it has recorded values are listed. The array-associated function defined on line \f(CWc20\fP can be displayed by \f(CWdispfun\fP. .sh 2 Iteration .pp ``For'' loops provide the major iteration facility in .Ma . Three examples which illustrate variants of this are the factorial functions below: .eB \f(CW (c25) f3(n) := block([temp], temp:1, for i:1 thru n do temp : temp*i, return(temp))$ (c26) f4(n) := block([temp], temp:1, for i:n step -1 thru 1 do temp : temp*i, return(temp))$ (c27) f5(n) := block([temp], temp:1, for i:n unless i <= 1 do (temp : temp*i , i:i-2), return(temp))$ \fP .eE Decrementing @i@ by 2 in the previous program was needed because the default step size of 1 is added to @i@ each time through. \f(CWF5\fP is certainly a perverse program. Incidentally, \f(CWreturn\fPs from within a \f(CWfor\fP exit from the loop, and not from the enclosing \f(CWblock.\fP It is important to note that one can group a collection of statement to be ``done'' together with parentheses, as illustrated in \f(CWf5.\fP .sh 2 Serious\ Business .pp Most serious users of .Ma find that they are repeatedly using the same programs, and need to save them for another day. Some users also find they rarely get the programs or the data quite right the first time, and would rather type these things in to a text editor, and have .Ma gobble the text up from a file rather than the keyboard. Publication quality programs require comments and other features you are unlikely to want to type into .Ma interactively. .pp Some people perfect a function or get an algebraic expression correct by typing definitions and commands into a file, say, \f(CWnewstuff\fP, using an editor such as \f(CWed, ex, vi, \fP or \f(CWemacs\fP and then within .Ma type \f(CWbatch(newstuff);\fP. If your file-name has funny characters like periods or slashes, you must use quotes. For example, \f(CWbatch("/usr/mac/demo.begin")\fP. .pp .Ma then reads the statements the file, assigning labels etc., and if there are syntax or other errors, prompts for help from the keyboard. If you want it to continue on to the next line after an error, type \f(CWbatcon(true);\fP . .pp Reading very large text files of programs and data can be slow using \f(CWbatch\fP, and if you are not changing the text, you might prefer saving your environment in another way. You can use \f(CWsave(savedstuff,all);\fP to save every named or labelled object in a .Ma system, on the file \f(CWsavedstuff\fP in your working directory. (You had better have write-permission or you'll get an error message.) Another time you can start up from where you left off by typing \f(CWloadfile(savedstuff);\fP into a fresh .Ma . You can load several saved files into a single system. Naturally if the files contain items with identical names, there is a potential for conflict. These will be resolved in favor of the last item read in. .pp If you want to save only some material you have produced, say only the functions defined and the values of variables x, y, and z, you can type \f(CWsave(savfunxyz,functions,x,y,z);\fP .pp A neat way to save a useful section of your environment is to (carefully) use \f(CWkill\fP to remove useless items first, and then save \f(CWall\fP that is left. Doing \f(CWkill(labels,...)\fP after first making sure that any useful result also has a name other than a c or d-label is sometimes a good start. You generally should not save every computation, since disk space is not infinite. .sh 2 Hardcopy .pp If you print out the files produced by \f(CWsave\fP to show to your colleagues who are as yet unconvinced of the merits of .Ma , you will be disappointed. While such files are ``ASCII'' character text, they do not make easy reading for persons uninitiated in various arcane matters. .pp What you might want to do, then, is store human-readable versions of your output on a file. This is especially useful if you have a display terminal, or a slow hardcopy printer. .Ma provides a way of opening a file for echoing both input and output of the system. The command \f(CWwritefile(fn);\fP where fn is a filename, starts the echoing, and \f(CWclosefile();\fP stops the echoing. If you want the output to be human-readable after being run through a typesetting program (eqn + troff in UNIX), you can experiment with the output produced by setting \f(CWtypeset : true \fP. (Suggestion: \f(CWgcprint : false\fP is a good idea.) .sh 2 Return\ to\ Arrays\ and\ Functions .pp .Ma provides a fascinating trick: arrays of functions. Imagine an array, each of whose elements is a function. For example, Legendre polynomials have an index, and an argument. Thus we can refer to @ P sub 4 ( z sup 2 )@. Just as arrays can have an associated function, function-arrays can have such an associated function. .pp Because we like to show off occasionally, and typesetting can be done by the VAX .Ma system, we illustrate this feature here. This was produced by saving output in a file and running it through ``troff'' ( \fIT\dE\uX\fP may be an alternative at some time). (c28) p[n](x):=ratsimp(1/(2^n*n!)*diff((x^2-1)^n,x,n)); .EQ I (d28) p sub n [ x ] ~:=~ "ratsimp" ( 1 over { 2 sup n \^ n ! } \^ { d sup n } over { d x sup n } ( x sup 2 ^-^ 1 ) sup n ) .EN (c29) p[4]; .EQ I (d29) lambda ( [ x ] , { "35" \^ x sup 4 ^-^ "30" \^ x sup 2 ^+^ 3 } over 8 ) .EN (c30) p[4](y+1); .EQ I (d30) { "35" \^ ( y ^+^ 1 ) sup 4 ^-^ "30" \^ ( y ^+^ 1 ) sup 2 ^+^ 3 } over 8 .EN .EQ .EN The ``lambda'' (@lambda@) notation for a raw function of one variable appears on line c29. This notation comes from the ``@lambda@-calculus'' used to describe the programming language LISP, and illustrates the fact that .Ma can talk about such structures. You can generally ignore this fact, however. .sh 2 More\ Useful\ Examples .pp As has been indicated earlier, procedures in .Ma can be used for almost any classical programming purposes (e.g. numerical techniques, combinatorial search). We have already indicated some differences from a purely numerical language, such as FORTRAN. We have seen that in .Ma there are no required type declarations, and floating-point numbers, while ``contagious'' in the sense that mixed-mode (floating-point + integer) is converted to floating-point, do not necessarily arise from certain calculations. For example, \f(CWsin(3)\fP normally results in \f(CWsin(3)\fP in .Ma , rather than its floating-point equivalent. \f(CWsin(3.0)\fP will, however, return a floating-point number. The numerical subroutine below, a Newton's method zero-finder sets the flag \f(CWnumer\fP to \f(CWtrue\fP to force .Ma to convert most expressions free of indeterminates to numbers. .pp This program uses Newton's method to find a zero of the expression \f(CWexp\fP which depends on the variable \f(CWvar.\fP The iteration starts with \f(CWvar=x0\fP and terminates when the expression, evaluated at the trial-point, has absolute value less than \f(CWeps.\fP The derivative of \f(CWexp\fP is computed algebraically, and its value is computed at various points as the search is being conducted: .eB \f(CW .lg 0 (c1) newton(exp,var,x0,eps):= /* 1 */ block([xn,s,numer], /* 2 */ numer:true, /* 3 */ s:diff(exp,var), /* 4 */ xn:x0, /* 5 */ while abs(subst(xn,var,exp))> eps do xn:xn-subst(xn,var,exp)/subst(xn,var,s), return(xn) ) /* 8 */$ .lg \fP .eE This procedure for Newton's method uses an explicit expression for the first argument \f(CWexp\fP (e.g. \f(CWsin(x)*erf(2*x)-%e^x\fP ). It is not a function name, e.g. \f(CWf\fP as we used before. The use of such an expression is straightforward and probably the best way for a beginner. The resulting program is somewhat verbose, because, as illustrated in lines 6 and 7 above, it is necessary to substitute values for variables in the expression and its derivative, \f(CWs,\fP to get numbers. Note the setting of \f(CWnumer\fP on line 3 to assure that the \f(CWif\fP statement on line 6 would get numerical values for its test. The rest of the procedure is the classical Newton iteration. The advantage of this procedure over a purely numerical one is that it takes advantage of the ability to compute the derivative of \f(CWexp\fP algebraically and automatically, once, before evaluating it at any point. .pp Another item to observe here is the use of comments in the text of programs which are \f(CWbatch\fPed in to the system. \f(CW /* This is a comment */ .\fP .pp There are often many different ways of expressing the same computation, and some of them may be substantially more convenient or efficient than others. While it may not make much of a difference in efficiency in this case, the following revision of the \f(CWnewton\fP procedure illustrates some techniques you may find useful in .Ma . .eB \f(CW .lg 0 (c2) newton(exp,var,x0,eps):= /* 1 */ block([ xn:x0, s:diff(exp,var), numer:true], /* 2 */ define(f(var), exp), /* 3 */ define(fprime(var),s), /* 4 */ loop, if abs(f(xn)) < eps then return(xn), /* 5 */ xn: xn - f(xn)/fprime(xn), /* 6 */ go (loop) ) /* 7 */ $ \fP .lg .eE Observe the list of local names at the beginning of the \f(CWblock,\fP which are initialized at the same time they are declared on line 2. Lines 3 and 4 are interesting because they define two new functions, \f(CWf\fP and \f(CWfprime\fP each to have as their bodies, the values of \f(CWexp\fP and \f(CWs\fP. The Newton iteration is more easily observed in functional rather than ``substitution'' notation. An even smaller version of \f(CWnewton\fP could be defined by using a single function for \f(CWexp/diff(exp,var)\fP. .pp Let us try this last function: .eB \f(CW (c3) h:expand((x-1)*(x-3)*(x-5)); 3 2 (d3) x - 9 x + 23 x - 15 (c4) newton(h,x,3.5,1.0e-10); (d4) 2.999999999994027 \fP .eE You might wonder how many iterations that took. One way is to use the very convenient debugging feature provided by .Ma which allows you to watch the assignment of values to variables. You set the variable \f(CWsetcheck\fP to a list of the variables you wish to watch. (or \f(CWall\fP to watch all the variables.) .eB \f(CW (c5) setcheck:[xn]$ (c6) newton(h,x,3.5,1.0e-10); xn set to 3.5 xn set to 2.923076923076923 xn set to 3.000228597554006 [*flonum:20{5%}; list:634{17%}; fixnum:43{2%}; ut:0%] xn set to 2.999999999994027 (d6) 2.999999999994027 \fP .eE (That message ``[*flonum: ...]'' is a message from the garbage collector, mentioned in the first section of the primer. ) .pp That tells us that only three iterations were needed in this case. .pp We claimed that two functions were defined in running this program. To display a function using the same syntax that you would use to type it in, you use the \f(CWgrind\fP\** command. .(f \** When computers were slow and programs were large, reformatting programs took a long time. The name of a program at MIT to ``grind out'' LISP function definitions was \f(CWgrindef\fP. The name was carried over to .Ma . Now, most LISP systems call this reformatting ``prettyprinting''. .)f .eB \f(CW (c7) grind(fprime); fprime(x):=3*x^2-18*x+23$ (d7) done \fP .eE .sh 2 Part\ Hacking .pp An important tool for applications programs in .Ma the ability to extract and test parts of expressions. These are used for the definition or extension of algorithms which do various conditional manipulation of formulas. For example, you can write a symbolic differentiation algorithm for expressions by applying the rules below: .EQ I (1) d over dx~ x ~=~ 1 ~~~~~~~d over dx~ y ~=~ 0 ~~(y != x) .EN .EQ I (2) d over dx~ ( u + v) ~=~ d over dx~ u ~+~ d over dx~ v .EN .EQ I (3) d over dx~ ( u cdot v) ~=~ v d over dx~ u ~+~ u d over dx~ v .EN .pp The technique we shall consider for implementing a version of the differentiation program is to take the expression apart using the \f(CWpart\fP command, and use the rules above to guide the manipulation. .pp First, we check to see if the expression is an atom (e.g. number, variable). Thus we begin our differentiation program as follows: .eB \f(CW .lg 0 newdiff(expr,var):= if atom(expr)=true then (if expr=var then 1 else 0) \fP .eE This fragment implements both parts of rule 1. If the \f(CWif\fP statement falls through to the \f(CWelse \fP clause, then we have a composite expression. We then check what its leading operator is by selecting its zeroth ``part'' via \f(CWpart(expr,0).\fP Based on its value we apply the appropriate rule. .eB \f(CW else if part(expr,0)=''+'' then newdiff(part(expr,1),var) + newdiff(part(expr,2),var) else if part(expr,0)=''*'' then part(expr,2)*newdiff(part(expr,1),var) + part(expr,1)*newdiff(part(expr,2),var) else 'newdiff(expr,var)$ .lg \fP .eE Note the last clause which returns a 'newdiff form, that is, quoted, as a result when the program doesn't know how to handle the leading operator. With some thought, you should now be able to extend newdiff to accommodate expressions including \f(CWsin\fP and \f(CWcos\fP as well as sums and products with more than two terms. (The .Ma language does not at the moment have a \f(CWcase\fP statement, which would make this particular program look better.) .sh 2 User\ Representation\ of\ Data .pp There is no ``record'' or ``structure'' data-type ``constructor'' in .Ma , but there is a way of doing something similar. If you have used a language like Pascal which has such a feature, you may appreciate its usefulness. Modern dialects of LISP use such structures, but when .Ma was first designed and initially implemented (in 1967), this was not in widespread use. It also influenced the user-level programming language. .pp It is natural to have to deal with collections of information in writing programs. For example, you might wish to provide as input or output data, a pair of expressions representing a lower and an upper bound on a formula. One way of handling this is by making up a new ``function'' name, say \f(CWbounds\fP and using it as though it were a record designator or constructor, but never associating it with an algorithm. Thus \f(CWbounds(1,x)\fP could be an expression representing the ordered pair <1,\f(CWx\fP>. Another example would be the use of \f(CWinteger_vector(1,3,5,7)\fP to designate a sequence (presumably of arbitrary length, in general), of integers. There is a built-in form in .Ma , namely a ``list'', which can be used to deal with such collections. It is part of the LISP heritage indicated earlier that there was initially only one type of structure: lists of any length or element type in .Ma . A list, when printed, looks like square-brackets enclosing a sequence of items. Thus you could express the bounds above as [\f(CW1,x\fP]. However, if you used lists for all collections, you would not know, on the face of it, whether [1,2] was an instance of \f(CWbounds\fP or \f(CWinteger_vector.\fP .Ma allows you to designate functions you intend to treat as lists, although you can use a different ``header'' like \f(CWbounds\fP with each different type. .Ma makes available certain built-in functions which can then be used on such list-like constructions such as \f(CWinteger_vector\fP. These are declared by, for example, \f(CWdeclare(integer_vector,list).\fP The built-in operations include \f(CWcons, append, member, endcons, map, rest.\fP \f(CWlist2:cons(element,list1)\fP returns a (new) \f(CWlist2\fP which has the given element inserted at the beginning of \f(CWlist1; \fP \f(CWList1 \fP and \f(CWlist2 \fP have a common ``shared'' tail. \f(CWlist3:append(list1,list2)\fP returns a (new) \f(CWlist3\fP which is a combination of the two lists, sharing a common tail with list2. \f(CWMember(element,list)\fP returns true or false depending on a test for membership. \f(CWEndcons(element,list)\fP returns an (unshared) list where the given element has been attached to the end of given list \f(CWMap(fn,list)\fP returns a new list where each element has had the function fn applied to it in turn. \f(CWRest(list,n) \fP returns the part of the list beginning n items from the front. These functions are parts of the fundamental repertoire of the programming language LISP. .pp The use of list-like objects should be considered whenever you are dealing with a collection of elements: a set of coordinates, a series of coefficients, a system of equations, a set of solutions, etc. .pp Independent of the ``whole list'' operations above, .Ma has some selection and alteration operations which are available on the same collections of data by the use of a numeric index. If you wish to use these indexing facilities, as we will illustrate for the notion of \f(CWcomplex\fP below, you \f(CWdeclare(complex,list).\fP Then, if you define a complex number by \f(CWx:complex(3,4)\fP meaning that \f(CWx\fP has real part 3, and imaginary part 4, the notation \f(CWx[1]:10;\fP is supported, and changes the value of \f(CWx\fP to \f(CWcomplex(10,4).\fP The declaration explains to the .Ma system that the data structure for \f(CWcomplex\fP will be implemented (in effect) as a list of items, and should be decomposable using the semantics of the .Ma list-handling commands. In fact, both selection and alteration is supported, and if you set the notation up by \f(CW(real:1,imag:2)$\fP you can use the following command: \f(CWx[imag]:-x[imag]\fP to change \f(CWx\fP to its complex conjugate. .pp An important caution must be observed. When .Ma deals with compound structures, they are usually not recopied, and if there are two names for the same object and the object is changed, then both names refer to the changed object. If \f(CWx\fP and \f(CWy\fP refer to the same \f(CWcomplex\fP number, then changes to \f(CWx[real]\fP are also made to the corresponding component of \f(CWy\fP. If these items are to be kept separate, \f(CWx:copylist(y);\fP will give \f(CWx\fP a different representation, but whose value is the same as \f(CWy\fP's. You can then change their components separately. .pp .Ma 's built-in lists mentioned earlier, which use square-brackets, can be altered and selected by indexing. .pp There are two other compound structures in .Ma which we mention here, which may be useful for collections of data: arrays and matrices. The matrix form is useful for two-dimensional rectangular tables of data. The matrix data format is supported by a number of special commands oriented toward the conventional interpretation of matrices in mathematics: inverses, determinants, etc. Matrices can be used for other kinds of data, but you should be cautious about using them in a manner that is too far distant from the conventional: arithmetic operations in .Ma , in particular, have already been defined. .pp Arrays are unusual in their flexibility in .Ma . They are usually treated as global tables, although they can be declared to be .i local to a function; they cannot be passed around as parameters as is the case with matrices. The names of arrays may be passed from program to program, but the data itself is not recopied, nor is it convenient to even make a copy of the data into another array. ``Hashed'' arrays are particularly ingenious, and have been illustrated earlier. Functions can be associated with arrays to provide new values for entries as they are required. .pp At this point you should be able to make use of the .Ma manual to learn more details for representation of new data types as you develop your application. .sh 1 More\ learning .pp The true programming buff may also be interested in the macro-expansion capabilities of .Ma and its extensible syntax. At this point we would discourage the use of these facilities by novices, but encourage their use by persons willing to experiment in providing the most versatile user-oriented packages within the .Ma framework. .pp There is a ``compilation'' facility which allows users to translate .Ma code into potentially faster running code. Since most of the time in most programs is used by calls to LISP programs, this is usually ineffective. In general, this should be avoided by novices and most experienced users, since time spent on this is more wisely spent on mathematical restructuring of the solution method, or (in the case of primarily numerical computation), using a numerical library routine written in a suitable language. .sh 1 Maxims\ for\ the\ MACSYMA\ User .pp Some beginning users of algebraic manipulation systems find that their previous experiences with traditional programming systems do not translate easily into algebraic programming; others find .Ma descriptions inadequate because the emphasis is on the mixture of mathematical notations and algorithms, and not on ``efficient'' use of machine or human resources (no one likes to wait longer than necessary for an answer!). While we cannot provide a complete education in efficient and effective programming, we have collected a few ``maxims'' in an attempt to help you with some of these ``start-up'' problems. .pp \fIAlgebraic manipulation is a new and different computational approach for which prior experience with computational methods may be misleading. You should attempt to learn the ways in which algebraic manipulation differs from other approaches.\fP .pp For example, consider the problem of inverting an @n times n@ matrix. In numerical analysis we learn that the problem requires on the order of @n sup 3@ operations. Theoreticians will point out that for @n@ sufficiently large, one can reduce the number of multiplications below @ n sup 3@ to @n sup 2.8@. This analysis is unfortunately not relevant in dealing with matrices with symbolic entries. Consider the number of terms in the determinant of the general @n times n@ matrix whose elements are the symbols @ a sub i,j @. When the inverse is written out in a fully expanded form, just the determinant (a necessary part of representing the inverse) has @n !@ terms. It is impossible to compute this determinant in less than ``time proportional to @n !@'' In fact, for large @n@, it is just not feasible to compute this form explicitly on existing computers. The combinatorial or exponential character that some algebraic manipulation problems have when they are approached with an inefficient algorithm, makes for a vastly different game from, say, numerical computation, where the size of objects is generally known at the onset of the calculation, and does not increase. .pp \fINeedlessly generalizing a problem usually results in unnecessary expense\fP. .pp For example, if you wish to obtain determinants for a collection of matrices whose general pattern of entries is represented by parametric formulas, you might consider obtaining the determinant of the general matrix and substituting various values for the parameters into the result. This may work for matrices of low order, but is probably a poor plan for dealing with the exponential growth inherent in computing symbolic determinants. It would probably be better to substitute the parameters first, since this would drastically reduce the cost of the determinant calculation. .pp Sometimes, when humans are dealing with formulas, it is preferable to use an indeterminate, say @G@ in a formula which is really known to be, say, 3/5. On the other hand, it is likely (although not certain!) that the calculation using 3/5 will take less time than the calculation with @G@. Since the cost inherent in some computations is usually a function of the number of variables in the expression, \fIit pays to reduce the number of variables in a problem as much as possible.\fR .PP \fIYou should be aware of the types of calculations which in the general case have exponential growth \fR (e.g. many matrix calculations with symbolic entries, repeated differentiation of products or quotients, solution of systems of polynomial equations). .pp \fIYour should anticipate a certain amount of trial-and-error in calculations.\fR Just as in other problem-solving activities, often the first technique that comes to mind is not the best. While it occasionally happens that brute force carries the day, cleverness in computing can be as important as cleverness in hand calculations. It is natural, during hand calculations, to apply critical simplificiations or substitutions in computations. These simplifications include collecting terms selectively or striking out terms which do not ultimately contribute to the final answer because of physical interpretations. Computer algorithms which do not incorporate these same tricks may bog down surprisingly soon. Thinking about these shortcuts may be important. In fact, it is one of the more rewarding aspects of computer algebra systems that they give the problem solver an opportunity to organize, encapsulate and distribute a particularly clever piece of mathematical manipulation. .pp \fITry to reduce your problem so that it can be performed in a simpler domain.\fR For example, if your problem appears to involve trigonometric functions, logs, exponentials, etc. see if you can reduce it to a rational function (ratio of polynomials) problem. If it appears to be a rational function, see if you can, by substitutions, make it into a polynomial problem, or a truncated power-series problem. If it appears to be a problem involving rational numbers, consider the use of floating-point numbers as an alternative, if the growth in the size of numbers presents difficulties. .pp There are other special forms that are especially efficient. In a number of areas of investigation \fIit pays to convert all expressions to the internal rational form (using \fRrat\fI) or into Poisson-series form (using \fRintopois\fI) to avoid the overhead the the general representation.\fR The price you may pay here is thtat the structure of the formulas may be significantly different from those you began with: The canonical transformations used by these representations drastically re-order, expand, and modify the original expressions. .pp \fISometimes someone else has already started on your problem.\fR You should look through the ``share'' directory programs available to see if there are contributed packages that might be of use either as subroutines or as models for programming. You should also consider writing programs that you develop in solving your problems in a form suitable for sharing with others. .pp \fIPattern matching allows you to ``tune'' the system simplifier to your .pplication, and develop rule-replacement programs.\fR Learning to use the pattern-matching facilities effectively is a nontrivial task. Nevertheless if you have a fairly complex problem involvilng the recognition and application of identities, you should consider making an effort to use these facilities. In recent years, advocates of ``rule-based expert systems'' have claimed that this type of formalism can or should be used to incorporate varied types of knowledge. Algebraic manipulation programs have depended on pattern matching since at least 1961, for some of their power. .pp Finally, we would like to point out that algebraic manipulation systems, in spite of their pitfalls, can be of major assistance in solving difficult problems. If you are willing to invest some time in learning, there may be enormous benefits in using such a system. We think it is unfortunate that some users reserve .Ma for difficult problems. Those of us who have grown up with .Ma near at hand find it of great use in routine computations as well. .pp We have enjoyed constructing .Ma , and we hope that you will enjoy using it. We hope you will consider contributing to program libraries at your local installation and at other sites. .pp Naturally, any comments or additions to this primer are welcome. .nf Richard Fateman University of California, Berkeley (Last revision 12/85)