' JJJJ ?\>',=l>  JJJJ!xHH<>BC=?L,L=LLLW LL* L_ L L L Lc`\_ [ {}~|`{}~|ح! )i ɶLhh捠 W LiHH`,` a $(H (G h$(IL]  8` a ƀ餁L]   思 L  G L G L  L L  L4  :L Lʩ L a y LDFG` )  L 6  H ɓ, h H h %2$($` $L| L  $` "%$L"LX  y $)` I L5H  Ih5`a{)`#`$` I $  o  8` ` & `  慥) 8` I _ 0 膆8` I H h톉ߥ N `  8`  `   ) `  ` NHh  L~ N s w  N 8`` s  w H hi`8`i`HJJh )`N`ɄNHNh` c SCRAMBLED DIRECTORYLe o ɄԝN`8``  iL   iL H  h s O c CANNOT READL H  h s * $ c BAD OR UNFORMATTEDL l !` c WRITE-PROTECTED c DISK; cESC TO ABORT SPACE TO IGNORE, RETURN TO RE-TRY:   L c ` m ) !) `)P)@ xLA `BU,>J>VJ>V`8'x0|&HhHh VY)'&Y)xꪽ)' `Hh`V0^*^*>&` cI꽌ɪVɭ&Y&&Y& 꽌ɪ\8`&&꽌ɪɖ'*&%&,E'зЮ꽌ɪФ`+*xS&x'8*3Ixix&& 8  '  & x)*++`FG8`0($ p,&"  !"#$%&'()*+,-./0123456789:;<=>?80^݌Hh ü ü݌ ռ ռ ռA ļD ļ? ļAEDE?HJ>h Լ ռ ռ ռ`HJ>݌h Hh݌`HIHHHHhHH݌hHhHh݌H6 VDP (ED _ $0x8x D- ڸDD# H8`?E Vk (f???0xE Hh D#-EEE8` D ڸx D - ڸx8`-0ݩ?ʥD EEE`   D#-EEE8` D ڸx D - l `CAT^REN-DELSAV^TYP:RUN LOA׳MOVpGETޱPUTINIFORMONeIN#QPR#W8$6 Y  # 8` p *  p _  `L h& s " c UNABLE TO FORMAT DISK` h 8` )N )i TOO LONG`  pHCOM ܳhH bh  pL p *  _  W ɓ8`` ` b   :D)  *.%  0  ,.8` 08` `  $H    h m mCLES1 ARICLES2 ARI CLES3 ALGCLES4 ALG&CLES5 ALG2PLES1 TRAEPLES2 TRANPLES3 TRA\PLES4 TRAiPLES5 TRAwDISKCOPY COMxDEMO ALLX ح"_" / LI cAPPLE ][ ADIOS-81 Version 01/29/82 ^ l ! 0 W ) W  !  񭰵:Q1J7F)!Le&HH   lK ( :Lk$ ,+L c !hiУ`L W  W ` pH hHH phh 8` pU P Y մIH hBHH hh8Lv p# L h cINSUFFICIENT DISK SPACE` ó챊 ` p/ * * Y _ n拥ɰ cFILE  !"#$%'()*+,-./013456789:;<=>?@ABCDFGHIJKLMOPQRSTUVWXYZ[]^_`abcdefghjklmnopqrstuvyz{|S4 TRAiPLES5 TRAwDISKCOPY COMxDEMO ALLX  &8` )N )i &8`   6,+ 0 s w l l ! 0 cFREE ON : 8 * c K-BYTES8`HNH+, l hAN9m *hH  +8`h`0:)8``  ` L 178`dH W h H W hLMd R R 0LW 8mH Mh`! 0 cERASE ALL FILES ON DRIVE 1 (Y/N):   Y N W ` W 8` h H W hLMd R R 0LW 8mH Mh`! 0 cERASE ALL FIL%File: CLES1.ARI (c) 08/10/80 The Soft Warehouse % LINELENGTH(39)$ NEWLINE: 1$ ECHO: TRUE$ % If this lesson is being displayed too fast, it can be temporarily stopped by typing a CTRL-S (i.e. typing the letter "S" plication crosses distinct from the letter X. To prevent certain ambiguities, multiplication cannot be implied by mere juxtaposition. One of the most frequent mistakes of beginners is to omit asterisks. Later, in order the key marked "<--" cancels the last character typed on the line, and typing a CTRL-X cancels the current line. There is no way to modify a line after striking the RETURN key, but an expression can always be flushed by typing a final tically saved as the value of a variable named "@", which can be used in the next expression. For example: % 3 ;@ ^ @ ;@ ^ @; % As this example illustrates, muMATH can treat very large numbers exactly and quickly. In f0,000,000 feet or 1,486,601,994,240,000,000 inches or 37,843,200,000,000,000 meters or 3,784,320,000,000,000,000 centimeters. Another dramatic comparison with 10^611 is that there are thought to be about 10^72 electrons in the e typing the ESCape key on your console followed by a CTRL-C. In muMATH a "comment" is a percent sign followed by any number of other characters terminated by a matching percent sign. Thus, the text of this explanation is a comion, subtraction or negation, multiplication, division, and raising to a power. For example: % (3*4 - 5) ^ 2 ; % The reason for using ^ and * is that standard terminals do not provide superscripts or centered dots or special multie return. This revises the value of the variable named RDS to the value TRUE. We will explain assignment in more detail later. Don't forget that you can use local editing to correct mistypings on the current line. For example,onal errors in order to become familiar with how they are treated. For example, try 5 7; 5+ /7; 5/0; and 0/0; Have fun!: % RDS: FALSE ; % The value resulting from the last input expression is automain inches or in centimeters without starting all over. (In case you forgot, the speed of light is 186,000 miles/second or 300,000,000 meters/second.) % RDS: FALSE ; % Our answers are about 123,883,499,52 while depressing the CTRL key). Then type it again when you are ready to resume. It is advisable to read sections 4, 5, 6 and 8 of the muMATH Reference Manual before beginning these lessons. This lesson can be aborted at any time by exact rational arithmetic, reducing fractions to lowest terms. In muMATH, arithmetic expressions can be formed in the usual manner, using parentheses together with the operators "+", "-", "*", "/", and "^" respectively for additto give you an opportunity to try some examples, we will "assign" the value FALSE to the variable named RDS. When you are ready to resume the lesson, type the "assignment" RDS: TRUE ; including the semicolon and carriagline containing a "grammatical" or "syntax" error such as "(;". Now we are going to turn control over to you by setting RDS to FALSE. Try some examples of your own similar to the above. Also we suggest that you make a few intentiact, muMATH can accomodate numbers up to about 611 digits. To partially appreciate how large this is, compute the distance in feet or in meters to the star Alpha Centauri, which is 4 light years away, then use "@" to compute the distance ment which has not yet been terminated. Comments do not cause computation; they are merely used to explain programs and examples to human readers. Here is an example of an actual computation% 1/2 + 1/6 ; % Note how muMATH uses ntire universe. (Whoever counted them must be exhausted!) Often one performs an intermediate computation or a trivial assignment for which there is no need to display the result. When this is the case, the display of the resuignment of 3600 to a variable named SECPERHOUR, then use this variable to help compute the number of seconds in 1 day and 1 week: % RDS: FALSE $ % Congratulations on completing CLES1.ARI. To execute the next lesson, merely enter t contrived, we urge you to bring to subsequent lessons appropriate examples from textbooks, tables, articles, or elsewhere. Also, you are encouraged to experiment further with the techniques learned in this lesson: % ECHO: FALSE$ RDS()%File: CLES2.ARI (c) 08/10/80 The Soft Warehouse % LINELENGTH (39)$ NEWLINE: 1$ ECHO: TRUE$ % This file is the second of a sequence of interactive lessons on how to use the muMATH symbolic math system. This lesson presumnge it to any base from two through thirty-six. For example, to see what thirty looks like in base two: % THIRTY: 30 $ RADIX (2) ; THIRTY ; % As you can see, the radix function returns the previous base, which is, of course, displayednt to save values longer than "@" saves them, for use beyond the next input expression. The colon ASSIGNMENT operator provides a means of doing so. The name on the left side of the assignment operator is BOUND or SET to the value of tpper and lower case version of a letter are entirely distinct. Names can be any sequence of alphabetic characters or digits, provided the first character is alphabetic. Thus X, #9, and ABC3 are valid names. Make an assy clear. The use of any computer program tends to become much clearer the second time. In order to experience the decisive learning reinforcement afforded by meaningful personal examples that are not arbitrarilyperand. For example, 3! yields 6, which is 1*2*3. Use this operator to determine the product of the first 100 integers: % RDS: FALSE $ % The number base used for input and output is initially ten, but the RADIX function can be used to chalt can be suppressed by using a dollar sign rather than a semicolon as a terminator. For example, type RDS: TRUE $ and note the difference from when you previously typed RDS:TRUE ; % RDS: FALSE $ % It is often conveniecontributes its value to the expression. For example: % RATE: 55 $ TIME: 2 $ DISTANCE: RATE * TIME ; % Alphabetic characters include the letters A through Z, both upper and lower case, and the character "#". Note that the uhe muMATH command RDS (CLES2, ARI, drive); where drive is the name of the drive on which that lesson is mounted. Alternatively, it may be advisable to repeat this lesson, perhaps another day, if this lesson was not perfectl $ es that the muMATH files through ARITH.MUS have been loaded. For positive integer N, N factorial is the product of the first N integers. The "postfix" factorial operator is "!", which returns the factorial of its ohe expression on its right. This value is saved as the value of the name until the name is bound subsequently to some other value. The name can be used as a variable in subsequent expressions, as we have used "@", in which case the name in the new number base. This inforation helps to get back to a previous base. In base two, eight is written as 1000, so to see what thirty looks like in base eight: % RADIX (1000) ; THIRTY ; % In base eight, sixteen is writte2))^(1/2) - 2^(1/2) - (3/2)^(1/2) can be simplified to 0, provided we make certain reasonable choices of branches for the square roots? In general, simplification of arithmetic expressions containing fractionalmilar people, surface area increases as the 2/3 power of the mass. Veronica wears a 1 square-meter bikini, and she is 50,653 grams, whereas her look-alike mother is 132,651 grams. Use muMATH to determine the area of her mother's simi example: % (-4) ^ (1/2) ; % Decent simplification of expressions containing imaginary numbers, as described in lesson CLES4.ALG, requires that file ALGEBRA.ARI be loaded. Meanwhile if you believe in imf FALSE. For example: % PBRCH: FALSE $ 4 ^ (1/2); % Users having a conservative temperament might prefer to do most of their computation with PBRCH FALSE. This brings us to the end of CLES2.ARI. Though arithmetic, some he base to thirty six? In input expressions, integers beginning with a letter as the most significant digit must begin with a leading zero so as not to be interpreted as a name. For example, in base sixteen, ten is the the desired new base in base two. For example: % RADIX (2) ; RADIX (1010) ; % Now we are guaranteeably in base ten, no matter how badly you got lost. Now consider irrational arithmetic: Did you know that (5 + 2*6^(1/ncreases with the complexity of the input and answer: % RDS: FALSE $ % An input of the form (m/n)^(p/q) is treated in the usual manner as (m^(1/q))^p / (n^(1/q))^p . For example: % (4/9) ^ (3/2) ; % For geometrically si^ (1/3) ; % What if no real branch exits? Then muMATH uses the unbound variable named #I to represent the IMAGINARY number (-1)^(1/2), and expresses the answer in terms of #I, using the branch having smallest positive argument. For ous, so answers thereby obtained should be verified by substitution into the original problem or by physical reasoning. For this reason, there is a CONTROL VARIABLE named PBRCH, initially TRUE, which suppresses Picking a BRanCH in as 20, so to see what thirty looks like in base sixteen: % RADIX (20) ; THIRTY ; % As you can see, the letters A, B, ... are used to represent the digits ten, eleven, ... for bases exceeding ten. Now can you guess why we limit tay have discovered, it is easy to become confused and have a hard time returning to base ten. Two is represented as 2 in any base exceeding 1, so a foolproof way to get from any base to any other is to first get to base two, then express powers is quite difficult, but muMATH makes a valiant attempt. For example: % 4 ^ (1/2) ; 12 ^ (1/2) ; 1000 ^ (1/2) ; % Try simplifying the square roots of increasingly large integers to gain a feel for how the computation time ilar bikini: % RDS: FALSE $ % 4^(1/2) could simplify to either -2 or +2, but muMATH picks the positive real branch if one exists. Otherwise, muMATH picks the negative real branch if one exists, as illustrated by the example: % (-8) aginary numbers and you can't contain your curiosity, why don't you experiment with them to see what muMATH knows about them: % RDS: FALSE $ % As with manual computation, picking a branch of a multiply-branched function is hazard letter-digit A, so to return to base ten: % RADIX (0A) ; % Why don't you now see what ninety- nine raised to the ninety-nine power looks like in base two and in base thirty-six, then return to base ten: % RDS: FALSE $ % As you mof the features illustrated in this lesson may be foreign to you, because sometimes they are taught during algebra rather than before. Thus, if you have any algebra background whatsoever, we urge you to proceed to lessonD VARIABLE is one to which no value has been assigned. Mathematicians call such variables INDETERMINATES. You may have already inadvertently discovered that if you use an unbound variable in an expression, muMATH treats the vy using the single-quote prefix operator, ', which looks like an apostrophe on many terminals. For example: % EG: X + 5; EG: 'EG; EG + 2; % Try assigning the value M*C^2 to E, then change E back to unbound status: few control variables whose values specify whether or not such transformations are performed. For example, the variable controlling expansion of integer powers of sums is called PWREXPD. This variable is conservati control value. Not only would this be rather time consuming, but the ability to form expressions from other expressions constructed under different control settings provides a valuable flexibility for constructing partiallyarn how to program using muSIMP, then proceed to lesson PLES1.ARI. % ECHO: FALSE$ PBRCH: TRUE$ RDS () $ nteractive lessons on how to use muMATH in the calculator mode. This lesson presumes that the muMATH files through ALGEBRA.ARI have been loaded and that the user has studied the arithmetic lessons CLES1.ARI and CLES2.ARI. An UNBOUNMATH automatically simplifies the expressions 0+Y, Y+0, 0*Y, Y*0, 1*Y, Y*1, Y^1, 1^Y, and 2*(X+Y) - 2*X. % RDS: FALSE $ % Sometimes it is desirable to change a bound variable back to unbound status. This can be done b. They may make an expression much larger and less comprehensible. However, they may be necessary in order to permit cancellations which make an expression smaller and more comprehensible. Accordingly, there are a sitive integer powers of sums are expanded, so let's try it: % PWREXPD: 2 $ EG; % Nothing happened! The reason is that muMATH does not automatically reevaluate previously evaluated expressions just because we change a CLES3.ALG even if some of CLES2.ARI was intimidating. Naturally, as implied by its type, file CLES3.ALG requires a muMATH system containing files through ALGEBRA.ARI. If you decide not to proceed to algebra, but want to le%File: CLES3.ALG (c) 09/15/80 The Soft Warehouse % LINELENGTH (39)$ NEWLINE: 1$ ECHO: FALSE$ NUMNUM: DENNUM: 6$ DENDEN: 2$ NUMDEN: PWREXPD: 0$ PBRCH: TRUE$ X: 'X$ ECHO: TRUE$ % This file is the third of a sequence of iariable as a legitimate algebraic unknown. Moreover, muMATH attempts to simplify expressions containing such unbound variables by collecting similar terms and similar factors, etc. For example: % 2*X - X^2/X ; % See if mu % RDS: FALSE $ % You may have noticed that some of the more drastic transformations, such as expanding products or integer powers of sums, are not automatic. The reason is that such transfor- mations are not always advantageousvely initialized to zero, so that integer powers of sums are not expanded. For example: % EG: (X+1)^2 - (X^2-2*X-1) ; % Clearly this is an instance where expansion is desirable. When PWREXPD is a positive integer multiple of 2, then po expanded expressions. On the other hand, it is often desirable to reevaluate expressions under the influence of new control settings, and the built-in EVAL function enables this: % EVAL (EG) ; % Now that PWREXPD is 2 the order of a second, depending on memory size and processor speed; and these slight pauses are sometimes noticable in the middle of a printout or a trivial computation. On a computer with front panel lights, the collections are alss scarce, because relatively more time becomes devoted to increasingly frequent collections. The moral of the story is: don't unnecessarily load too many muMATH files or retain numerous expressions as the values of variamum degree in each unbound variable. In contrast "sparse" polynomials are missing a large percentage of the possible terms less than the maximum degrees. If you are still in an experimental mood, you may wish to try the following ager multiple of 2, then integers in NUMerators are distributed over sums in NUMerators. Similarly when the variable is a positive integer multiple of 3, then monomials in numerators are distributed over sums in numerators, whFor example: % PWREXPD: 3 $ 1 / (X+1)^2 ; % What happens if 1 / ((X+1)^2 - X)^2 is evaluated under the influence of PWREXPD being 3? For a little surprise, try it.% RDS: FALSE $ % Even though (X+1)^2 is WITHIN a n(); % Numbers and nodes which are no longer a part of any value that we can retrieve are automatically recycled intermittently, but the RECLAIM function forces this "garbage collection" process. The collection takes on es of variables, then there will be relatively little unemployed space for our next computation. Not only does this limit the size of the next expression, but computation time also increases dramatically as space becomeit appears that your space or patience is nearly exhausted: EG:(1+X)^2; RECLAIM(); EG:EG^2; RECLAIM(); EG:EG^2; ... % RDS: FALSE $ % These polynomials are called "dense", because there are no missing terms less than the maxie expression size but is sometimes necessary to permit cancellations. For example, this transformation is clearly desirable in the expression: % EG: X^2 - 1 - (X+1)*(X-1) ; % When the control variable named NUMNUM is a positive inte, see how (X+Y)^2 - (X-Y)^2 simplifies: % RDS: FALSE $ % In muMATH, denominators are represented internally as negative powers, and negative integer powers of sums are expanded if PWREXPD is a positive integer multiple of 3. rimarily upon the amount of unemployed space available for storing the data structure used to represent algebraic expressions. We can always determine the total amount of unemployed space expressed in bytes by the command: % RECLAIM o usually recognizable by the change in light patterns. Naturally, if we load an extravagant number of muMATH files into a single muMATH dialogue or if we save a number of relatively large expressions as the valubles. Now, for the experiment: In order to gain an appreciation for how computation time depends on the size of the input expression, answer, and unemployed storage, try timing each computation in the following sequence, until nalogous sequence which produces extremely sparse results: RECLAIM(); (A+B)^2; RECLAIM(); (A+B+C)^2; RECLAIM(); ... % RDS: FALSE $ % Distribution of sums over sums is another transformation which can dramatically increasegative power, it is itself a positive power, so how about trying again with PWREXPD being 2*3: % RDS: FALSE $ % Now, we would like to suggest a little experiment for you: The size limitation on algebraic expressions depends pereas when the variable is a positive integer multiple of 5, then sums in numerators are distributed over sums in numerators. The reason for using the successive primes 2, 3, and 5, is that it provides a convenient er sums. If positive values of NUMNUM cause expansion in numerators, how do we request factoring in numerators? Negative values of NUMNUM cause factoring of numerators. Moreover, the specific negative values cause factoamed DENDEN which controls expansion and factoring among negative powers in a manner entirely analogous to NUMNUM. Use it together with NUMNUM to expand the denominator then semifactor the denominator of the expression X^2/((X-Y be distributed; and a positive multiple of 5 causes sum factors to be distributed. For example: % Y: 'Y $ DENNUM: DENDEN: NUMNUM: 0 $ EG: (5+3*X^2) / (15*X*(4+X)); DENNUM: 2 $ EVAL(EG); DENNUM: 3*DENNUM; EVAL(EG); DENNUM: 5*DENNUcommon integer denominator when DENNUM is a negative integer multiple of 2, expressions are put over a common monomial denominator when DENNUM is a negative integer multiple of 3, and expressions are put over a common sum denomisee), because neither distribution dramatically increases expression size, and because a lack of these distributions often prevents annoyingly obvious cancellations. For instance the expression 2*(X+1) - 2*X will not simplify unlessRDS: FALSE $ % In interpreting these results, it is important to recall that negations are represented internally as a product with the integer coefficient - 1, so NUMNUM must be a positive multiple of 2 to distribute negations ovomputers as well as humans. However, we are working on it for future releases. Meanwhile, try out our semifactoring on the example 3*X*Y^3/7 - 15*X*Y^2/14 + 9*X^4*Y^2/7 % RDS: FALSE $ % As you may have guessed, there is a flag nof various kinds of denominator factors over the terms of corresponding numerator factors: A positive multiple of 2 causes integer denominator factors to be distributed; a positive multiple of 3 causes monomial factors to ttractive form: % RDS: FALSE $ % What about negative values of DENNUM? A little reflection confirms that forming a common denominator reverses the effect of distributing a denominator. Thus, expressions are put over a way to independently control the three types of distribution using one easily remembered control variable name. The initial value of NUMNUM is 6, because numeric and monomial distribution are recoverable (as we shall xample, % EG; NUMNUM: 5 * NUMNUM; EVAL(EG) ; % To witness the great variety of possible expansions, we set % NUMNUM: 0 $ EG: 4 * X^3 * (1+X) * (1-X); % Now, successively EVAL EG with NUMNUM being 2, 3, 5, 6, 10, 15, and 30: % ring of the type which reverses the corresponding expansion. For example: % X: 'X $ Y: 'Y $ NUMNUM: -2 $ EG: 10*X^2*Y + 15*X^3; NUMNUM: 3*NUMNUM; EVAL(EG); % What about negative multiples of 5? Sorry folks, that's hard for c)*(X+Y) + Y^2 + X^2*Y) % RDS: FALSE $ % You may have wondered why we chose the names NUMNUM and DENDEN. The reason is that there is another closely related control variable named DENNUM, which controls the distribution M; EVAL(EG); % Positive setting of DENNUM and NUMNUM are particularly useful for work with truncated series or partial fraction expansions. For example, see if you can put the expression (6 + 6*X + 3*X^2 + X^3)/6 into a more a NUMNUM is a positive multiple of 2. Similarly X+1 - (X+1) will not simplify to 0, since the expression is represented internally as X+1 + -1*(X+1), which requires the -1 to be distributed over the sum. Thus, to return to our enator when DENNUM is a negative integer multiple of 5. For example: % X: 'X $ DENNUM: DENDEN: 0 $ EG: 1 + X/3 + (1+X)/X + (1-X)/(1+X); DENNUM: -2 $ EG: EVAL(EG); DENNUM: 3*DENNUM; EG: EVAL(EG); DENNUM: 5*DENNUM; EG: EVAL(EG); % Try o view some results before doing anything drastic or potentially quite time consuming. PWREXPD: 6; NUMNUM: DENDEN: 30; DENNUM: -30; These settings yield a fully expanded numerator over a fully expanded for cancellation of factors between a numerator and denominator. However, the factoring is done incrementally, term by term, so it may be necessary to first expand over a common denominator so that all cancellable terms haxpansions or partial fractions, because each term is fully expanded over its own denominator. Again, we can't overemphasize the importance of mastering the use of these four control variables. They are your primary tool forvent, it is advisable to initiate a fresh muMATH environment, because our experiments have altered control values and made assignments which could interfere with those lessons in nefarious ways. % ECHO: FALSE$ RDS () $ on of numeric and monomial denominator factors over numerator sums. This tends to give attractive results for polynomials or series with rational-number coefficients, but the relatively costly common-denominator operaffects. Here are the most frequently useful combinations of settings for these three variables: PWREXPD: 0; NUMNUM: DENDEN: DENNUM: 6; These initial values are usually good for general-purpose work, when the user wants t may be irrecoverably lost. PWREXPD: 0; NUMNUM: DENDEN: -6; DENNUM: -30; These settings yield a semifactored numerator over a semi- factored common denominator. This form gives the maximum chanceactoring is done in the denominator where it is usually most important, but there is a maximum opportunity for combination of similar terms in the numerator. PWREXPD:6; NUMNUM: DENDEN: DENNUM: 30; These settings are good for series echoosing, until the usage becomes second nature: % RDS: FALSE $ % Congratulations on completing CLES3.ALG. If the mathematical level was uncomfortably high, proceed to lesson PLES1.ARI. Otherwise proceed to CLES4.ALG. In either e fully simplifying the expression X^4/(X^3+X^2) + 1/(X+1) - 1 by expanding over a common denominator, then factoring: % RDS: FALSE $ % As with NUMNUM and DENDEN, the initial setting of DENNUM is 6, which causes distributi these variables give rather fine control over the form of algebraic expressions. muMATH cannot read the user's mind, so it is important for the user to thoroughly master the use of these variables in order to achieve the desired ecommon denominator. This form gives the maximum chance for combination of similar terms. Moreover, a rational function equivalent to 0 is guaranteed to simplify to 0. However, valuable factoring information ve an opportunity to cancel before attempting factorization. PWREXPD: 2; NUMNUM: 30; DENDEN: -6; DENNUM: -30; These settings are a good compromise between the advantages of expansion and factoring. Semi- f imposing your will on the simplification process, and any lack of understanding of their proper use will ultimately lead to frustration. Accordingly, why don't you try the above and various other combinations on examples of your own tion may be necessary for problems involving ratios of polynomials. You have now been exposed to the four most important algebraic control variables in muMATH. Together with EVAL, the various combinations of settings of %File: CLES4.ALG (c) 10/30/79 The Soft Warehouse % LINELENGTH (39)$ NEWLINE: 1$ ECHO: TRUE$ % This is the fourth of a sequence of muMATH calculator-mode lessons. There are some other algebraic control variabl fact that it so naturally complements NUMNUM, DENDEN, and DENNUM suggests that it must be useful for something! % RDS: FALSE $ % Another control variable named BASEXP controls distribution of a BASe over terms in an EXPonent tion of similar factors having the corresponding types of bases. BASEXP is initially -30. However, distribution (followed perhaps by collection) is sometimes necessary to let some of the terms in an exponent sum combine w when EXPBAS is a positive integer multiple of 2, monomial exponents are distributed over base products when EXPBAS is a positive integer multiple of 3, and exponent sums are distributed over base products when EXPBAS is a poid. Consequently, conservative users may prefer to generally operate with EXPBAS being 2. Moreover, distribution of exponents tends to make expressions more bulky when no cancellations occur. For example % (X * Y * Z) ^ (1 numerators over the terms of denominator sums. NUMDEN is initially 0, but integer numerators are distributed over denominator sums when NUMDEN is a positive integer multiple of 2, monomial numerators are distributich is less drastic than a single common denominator: % NUMDEN: -6 $ Z + 1 / (1/X + 1/Y) / (1+Y) ; % See if you can devise examples exhibiting dramatic simplifications arising from either direction for this novel transformation. Theed over exponent sums when BASEXP is a positive integer multiple of 3, and base sums are distributed over exponent sums when BASEXP is a positive integer multiple of 5. Morever, the corresponding negative values cause collecently negative BASEXP, or vice- versa: % RDS: FALSE $ % Another control variable named EXPBAS controls the distribution of EXPonents over BASes which are PRODUCTS. Integer exponents are distributed over base products permits net simplification: % (X^(1/2) * Y) ^ 2 ; (X*Y)^2 - X^2*Y^2 ; (4*X^2*Y) ^ (1/2) ; % However, the user should beware that as with manual computation, distribution of noninteger exponents is not always vales besides PWREXPD, NUMNUM, DENDEN, and DENNUM; and they are occasionally crucial for achieving a desired effect. One of these, named NUMDEN, provides the logical completion of the latter three, by controlling the distribution of factors inDEN: 30 $ X / (X^3 + X + 1) / (Y + 1) ; EG: (X+Y) / (1+X+Y) / (Y+1) ; % Isn't that intriguing? It yields a sort of "continued-fraction" representation. Now for the reverse direction, which performs a denesting of denominators whwhich is a sum, or controls the reverse process which is collection of similar factors. As might be expected, integer bases are distributed over exponent sums when BASEXP is a positive integer multiple of 2, monomial bases are distributith the base. For example: % EG: 2^(2+X) / 4 ; BASEXP: 2 ; EVAL (EG) ; % See if you can devise an example which requires evaluating an expression first with sufficiently positive BASEXP, then reevaluating with sufficisitive integer multiple of 5. Naturally, the corresponding negative multiples request collection of bases which have similar exponents of the indicated type. The initial value is 30, and here are some examples where distributioned over denominator sums when NUMDEN is a positive integer multiple of 3, and numerator sums are distributed over denominator sums when NUMDEN is a positive integer multiple of 5. For example: % NUMNUM: DENDEN: DENNUM: 0 $ NUM/2) ; % In fact, there are instances where negative settings of EXPBAS are necessary to acheive a desired result. For example: % EG: 2^X * 3^X + (1+X)^(1/2) * (1-X)^(1/2) - (1-X^2)^(1/2) ; EXPBAS: -6 ; NUMNUM: 30 ; EVAL (EG) ; % a control variable named ZEROBAS, initially FALSE, which permits the transformation when nonFALSE. Why then do we automatically simplify X^0 to 1 even though X could perhaps take on the value 0, giving the undefined form 0^0? es 0 from either side of the real axis, 1 is a reasonable interpretation even for 0^0. Nevertheless, there is room for disagreement, and anyone who wishes is free to run with ZEROEXP FALSE. Why don't you try it, using some desired form, try this command. It may reveal some inappropriate settings or remind you of some alternatives you forgot, or reveal the existence of potentially relevant flags of which you were unaware. Often a dialogue proceeds trol variable to its usual value. Consequently, as a convenience, we have provided some functions which, for the most commonly desired sets of "drastic" control values, establishes these values, reevaluates its argument, then allows the contr$ % The variable named PBRCH, already discussed in conjunction with fractional powers of numbers, also controls transformations of the form u^v^w --> u^(v*w). PBRCH is initially TRUE, but when PBRCH is FALSE, the transfoalues of X, so the transformation could lead to invalid results. Of course, sometimes users know that the exponent is positive, or they are willing to assume it is positive and verify the result afterwards. Consequently, there is rd the polynomial X^0 as being formally equivalent to 1. 2. One cannot do effective simplification of rational functions without this widely accepted transformation. 3. Since 1 is the limit of X^0 as X approach we have provided a handy-dandy function named FLAGS which returns the empty name "" after printing a display of all the flags and their values: % FLAGS (); % If you ever get frustrated because you can't get an answer close to the eral control variables, followed by an evaluation then assignments to restore the variables to their usual values. This process can become tedious, and baffling effects can result from inadvertently forgetting to restore a con See if you can devise an example which requires evaluating an expression first with sufficiently positive EXPBAS, then reevaluating with sufficiently negative EXPBAS, or vice- versa, in order to simplify acceptably: % RDS: FALSE See if you can devise such an instance: % RDS: FALSE $ % Now, try the examples 0^X and X^0, to see what happens: % RDS: FALSE $ % The reason that 0^X is not automatically simplified to 0 is that 0^X is undefined for nonpositive vWell, we also have a control variable for that, named ZEROEXP of course, but we initialized it to TRUE because: 1. If we are thinking of polynomials in X rather than any one specific value of X, then we are free to rega rational expression examples, in order to see how you feel about this issue? % RDS: FALSE $ % It is easy to forget the current control-variable settings, and it is even easy to forget the existence of certain control-variables, so best under some control settings which are suitable for the majority of the computations, with an occasional need for an evaluation under different control settings. Each such exception could involve new assignments to sevrmation occurs only for integer w. Otherwise the transformation occurs for any w. The user should be aware that in some circumstances the selected branch is an inappropriate one, so that it may sometimes be necessary to set PBRCH to FALSE. ol variables to revert to their former values before returning the reevaluated argument. One of these functions is called EXPAND, because it requests full expansion with fully distributed denominators, bases, and expone current lesson. % ECHO: FALSE$ RDS () $ denominator of an expression. Accordingly, there are built-in SELECTOR functions named NUM and DEN for this purpose: % DENNUM: 0 $ EG: (1+X) / X ; NUM (EG) ; DEN (EG) ; NUM (1 + EG); DEN (1 + EG); % As the last two examerm, coefficient, base, or exponent. muMATH represents the imaginary number (-1)^(1/2) as #I, and muMATH does appropriate simplification of integer powers of #I. For example: % #I ^ 7 ; EXPAND ((3 + #I) * (1 + 2*#I)) ; EXPANDpower of #I is reduced appropriately. Also, if a control variable called TRGEXPD is a negative multiple of 7, then complex exponentials are converted to trigonometric equivalents. (The opposite transformatienience functions is called EXPD, and it fully expands over a common denominator. Thus the internal control settings are the same as for EXPAND, except that DENNUM: -30. Try EXPD (1/(X+1) + (X+1)^2); % RDS: FALSE $ % Final this is true: % RDS: FALSE $ % This brings us to the end of lesson CLES4.ALG. The next lesson is CLES5.ALG, but as before, it is advisable to start a fresh muMATH to avoid conflicts with bindings established in the%File: CLES5.ALG (c) 10/30/79 The Soft Warehouse % LINELENGTH (39)$ NEWLINE: 1$ ECHO: TRUE$ % It is often desired to extract parts of an expression. Particularly frequent is a need to extract the numerator or tive powers. Try out NUM and DEN on a few examples of your own to gain some experience: % RDS: FALSE $ % The Programming-mode lessons will explain how to completely dismantle an expression to get at any desired part, such as a specific tf the natural logarithms as #E and the ratio of the circumference to the diameter of a circle as #PI. Using these, muMATH performs the simplification #E ^ (n * #I * #PI / 2) --> #I^n, where n is any integer constant, after which the nts. More specifically, it uses the following settings: PWREXPD: 6; NUMDEN: 0; NUMNUM:DENDEN:DENNUM:BASEXP:EXPBAS: 30; To see its effect, try EXPAND (((1+X)/(1-X))^2); % RDS: FALSE $ % Another one of these conv0; PWREXPD: NUMDEN: 0; Since semi-factoring is done termwise, it may be necessary to use EXPD before applying FCTR to an expression, in order to get the desired result. See if you can devise an instance whereples illustrate, NUM and DEN do not force a common denominator or any other transformation before selection, so the denominator is always 1 when the expression is a sum or when the expression is a product having no nega ((X + #I*Y) ^ 3) ; % Try it, you'll like it! % RDS: FALSE $ % The definition of the operator "^" in file ALGEBRA.ARI also implements two higher-level transformations which we mention here only in passing: muMATH represents the base oly, there is a convenience function named FCTR, and it semi- factors over a common denominator. It evaluates its argument under the following control-variable settings: NUMNUM: DENDEN: -6; DENNUM: BASEXP: EXPBAS: -3on for sines and cosines to complex exponentials for TRGEXPD = 7, is implemented by file TRGPOS.ALG.) If your mathematical background includes these facts, you might wish to experience them here. Otherwise you can safely ignorof evaluation: % X: 9 $ EG: EVAL (EG) ; % If these examples are not entirely clear, you had better take the time to experimentally learn the principles by trying some examples of your own: % RDS: FALSE $ % It is often desired to re 'M $ C: 'C $ V: 'V $ EG: M*C^2 + M*V^2/2 $ EVSUB (EG, M, 5); EVSUB (EG, M, M1+M2); M; % Play around with EVSUB for awhile until you are absolutely sure that you understand the difference between substitution and assignment: % RDS:% RDS: FALSE $ % Here is an example where a desired substitution doesn't fully occur:% NUMNUM: 6 $ C: 'C $ S: 'S $ EVSUB (1 - 2*S^2 + S^4, S^2, 1-C^2); % The reason we did not get the desired simplification to C^4 is that if the se is a product, it matches only the same COMPLETE product in the first argument. Again, the remedy is to use an equivalent substitution wherein the second argument is a name. For example: % EVSUB (2*C*S, C, C2/S); % Here is a final. Let's see: % X: 5 $ Y: 'Y $ EG: X + Y ; X: 3 ; EG; EVAL (EG) ; % Apparently the answer is "no", at least if X is bound when the assignment to EG is made. This should not be surprising, because after contributing its value to theign the result to EG, reevaluation of EG after a different assignment to X still has an effect: % X: 7 $ EG: EVAL (EG); % Since this time we did assign the result to EG, further changes to X can have no effect on EG regardless provides a convenient method of accomplishing this effect. EVSUB returns a reevaluated copy of its first argument, wherein every instance of its second argument is replaced by its third argument. For example: % NUMNUM: 6 $ M:ave not endowed EVSUB with any sophistication about finding algebraically IMPLICIT instances of its second argument in its first. See if you can find examples where EVSUB does not do a substitution that you would like it to do: For example: % PWREXPD: 2 $ EVSUB (1 - 2*S^2 + S^4, S, (1-C^2)^(1/2)); % Here is a somewhat different example wherein a desired substitution does not occur: % EVSUB (2*C*S, C*S, C2); % The reason is that if the second argumente this digression: % RDS: FALSE $ % You may have wondered whether or not an assignment to a variable, say X, automatically updates the value of a bound variable, say EG, which was previously assigned an expression containing Xles, previously evaluated expressions are not automatically reevaluated when we bind an unbound varible therein. However, we can always use EVAL to force such a reevaluation: % EVAL (EG) ; % Since we did not assevaluate an expression under the influence of a temporary local assignment to one of the variables therein without disturbing either the existing value of the variable or else its unbound status. The built-in EVSUB function FALSE $ % You may have discovered that EVSUB also permits substitution for arbitrary subexpressions as its second argument. For example: % M: 'M $ C: 'C $ E: 'E $ EVSUB (M*C^2 + 7, M*C^2, E); % To keep the algebra package small, we hcond argument is a power, it matches only the same power in the first argument. We can usually circumvent such problems by instead using an equivalent substitution wherein the second argument is a name rather than a power. expression X + Y, all traces of the name X are absent from this expression. However, suppose that we do a similar calculation wherein X is initially unbound: % X: 'X $ EG: X + Y; X: 3; EG; % As when we change control variab example for which a desired substitution does not occur: % EVSUB (C^2+S^2-1+C+S, C^2+S^2, 1); % Similarly to products, if the second argument is a sum, it matches only the same COMPLETE sum in the first argument. As before, we Math curriculum sequences differ, but probably most users will be most comfortable trying the higher-level packaes in the approximate order EQN, SOLVE, ARRAY, MATRIX, LOG, TRGNEG, TRGPOS, DIF, INT and INTMORE. Since s terms in the expanded form of (X1 + X2 + ... + XM) ^ N grows outrageously with M and N. Consequently, it is important to make every effort to avoid needlessly introducing extra variables for generality's sake. e: a) If K, X, and X0 can be made to occur only as instances of the subexpression K*(X-X0), then consider replacing this subexpression with a variable named perhaps KDX. b) Simila a more systematic technique called DIMENSIONAL ANALYSIS, and an article in the Journal of Computational Physics (June 1977) explains how computer algebra can automate the process. 2. Even when a vari + S^2 - 1, then we can use to our advantage the fact that powers must match exactly for a substitution to take place: % EVSUB (C^2+S^2-1+C+S, C^2, 1-S^2) ; % See now if you can use such techniques to get your examples to ily learned from studying the corresponding DOC files. We suggest that before commencing the Programming-mode lessons, you explore calculator-mode usage of the higher-level packages as far as your math background permits. omputer symbolic math: First, storage and time consumption tends to grow dramatically with the number of variables in the input expressions, even if the ultimate result is fortuitously compact. For example, the number of general techniques for doing this: 1. If members of a set of variables can be made to occur only together as instances of a certain subexpression, consider replacing the subexpression with a single variable. For examplality coefficient, renaming a physically-meaningful subexpression, and grouping quantities into dimensionless quantities. Most engineering and science libraries have books describing could circumvent the difficulty by making an equivalent substitution of (1-C^2) ^ (1/2) for S, or (1-S^2) ^ (1/2) for C, but that would leave an ugly square root in the answer. If our goal is to delete the subexpression C^2t, which is understanding evaluation, substitution, and the ramifications of the various algebraic control variables. You will find that if you know the relevant math, use of the higher-level packages is quite straightforward, easpace becomes increasingly scarce as higher-level packages are loaded, you may have to reread file READ1ST.TXT to learn how to CONDENSE and SAVE if you haven't already. Now for some parting advice about getting the most out of c Mathematical and physical problems are often stated using more variables than are strictly necessary, so it is also important to exploit every opportunity to reduce the number of variables from the original problem. Here are some rly, perhaps a combination such as M*C^2 could be replaced with E, or RHO*V^2/L could be replaced with RE. These are respectively instances of absorbing an offset together with a proportion work: % RDS: FALSE $ % This brings us to the end of the calculator-mode lessons. There are, of course, higher-level math packages in muMATH, but the fact is that from a usage standpoint, we have already covered the hardest parable cannot be eliminated, the complexity of expressions may be reduced if the variable can be made to occur only as instances of a subexpression. For example: a) If only even powers of a variable X ocd numerically. If so, the attempt at an analytic solution at least allows one to proceed with an approximate numerical solution having more confidence that a concise analytical solution has not been overlooked. % ECHO: FALSE$ RD), PRINT (REST (EX1)), #PRINT (RPAR), EX1, ENDFUN $ MOVD (PRINTLINE, #PRINTLINE) $ FUNCTION PRINTLINE (EX1), PRINT (EX1), NEWLINE (), EX1, ENDFUN $ NEWLINE: 1$ ECHO: TRUE $ % This is the first of a sequence of interactive lessons lessons introduce more built-in functions and operators, but more important, the lessons reveal how to supplement the built-in functions and operators with definitions of your own, thus extending muSIMP itself. It is important to programs operate upon. The most primitive UNSTRUCTURED muSIMP data are integers and names, collectively called ATOMS to suggest their indivisibility by ordinary means. Some programs must distinguish these two types of atoms, so thielding mere integer powers of that variable. Some other advice is to avoid fractional powers and denominators as much as possible. They don't simplify well, they consume a lot of space, and they tend to be hard to decipher analytic solution which will at least convey some qualitative information about the solution to the original problem. Sometimes only part of a problem or perhaps even none can be solved symbolically, and the rest must be solve%File: PLES1.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ RFFIRST: 'RFFIRST $ MOVD (PRINT, #PRINT) $ FUNCTION PRINT (EX1), WHEN ATOM (EX1), #PRINT (EX1) EXIT, #PRINT (LPAR), PRINT (FIRST (EX1)), #PRINT (" . "h the lessons. The file TRACE.MUS should be loaded. muSIMP supplies a number of built- in functions and operators. The calculator-mode lessons introduced a few of these, such as RDS, RECLAIM, +, *, etc. These progamming-mode erent from muMATH, because we want to suggest a few of the many other applications for which muSIMP is especially well suited, and because we want these lessons to be comprehensible regardless of math training level. Data is what cur, consider replacing X^2 with a variable named perhaps XSQ. b) If X only occurs as instances of 2^X, 2^(2*X), 2^(3*X),..., consider replacing 2^X with a variable named perhaps TWOTOX, ys one to infer a general solution which can perhaps then be verified by substitution or by induction. Alternatively, perhaps the original problem can be simplified by neglecting some lower-order contributions, in order to get an S () $  about muSIMP programming. It presumes as a minimum that you have read section 8 of the muSIMP/muMATH Reference Manual. Also the first part of CLES1.ARI should be completed since it explains the mechanics of how to interact wit realize that, until the last programming-mode lessons, we will not deal with muMATH. Instead we deal first with muSIMP, the language in which muMATH is written. The illustrative examples for these first few lessons are utterly diff when printed one- dimensionally. Often a change in variable can eliminate a fractional power or a denominator. Sometimes, even when a problem cannot be solved in its full generality, solving a few special cases enableere are two corresponding RECOGNIZER functions: % INTEGER (X76#) ; NAME (X76#) ; EG: -3271 $ INTEGER (EG) ; NAME (EG) ; % Do you suppose that "137", " ", "", and "X + 3", with the quotation marks included, are integers, names, or inv----+-----+----- ! 31 ! ! 7 ! 2 ! !BILBO ---+-----+-----+-----+-----+-----+----- The specific placement of data within memory is managed automatically, so all we are concerned about is the specific name and number values you have seen one bisected box you have seen them all, so to reduce the clutter and thus emphasize the essential features, we henceforth represent such nodes by a mere vertex in our diagrams, giving schematics such as onveniently could use diagrams such as the above. Most of us do not have nice graphics terminals, so we must use another external representation. For this purpose muSIMP uses a representation consisting of the first data item, fo usual operator or functional notation: '(BILBO . 31) Moreover, we must use an ampersand rather than a semicolon as the expression-terminator in order to inform the driver to print the expression as a data stored there is analogous to mail inside the mailbox. As with a row of mailboxes, the contents of computer memory can change over time. There are useful programs which deal only with unstructured data, but the most interestining at location 2, and the node beginning at location 4. Then, begining at location 4, there would be stored the addresses 7 and 2, as illustrated in the following diagram: 1 2 3 4 5 6 7 ---+-----+-----+-----+-concerned about: +----+----+ ! / ! \ ! +-/--+--\-+ / \ BILBO 31 This imagery suggests the word "pointers" for the addresses stored in nodes. If ication. For example, muMATH uses operator and functional notation. Suppose however that we want to specify such aggregates directly in input and output. How can we do it? If we have a nice graphics terminal, then then we cuse of parentheses and periods from how they are otherwise used in muSIMP input, so we must preceed the dotted pair by the single-quote prefix operator to indicate to the parser that we are using dotted-pair notation rather than the alid? Find out for yourself% RDS: FALSE $ % Data can be stored in the computer's memory. The location at which a data item is stored is called its ADDRESS. An address is analogous to a street address on the outside of a mailbox. The "data" consisting of addresses of 2 other data items. For example, suppose that we wish to represent the aggregate consisting of the name BILBO and his age 31. We could store the name BILBO beginning at location 7, the number 31 beginn and the connectivity of the aggregates. Thus, for our purposes it is best to suppress the irrelevant distracting detail associated with the specific addresses. The following diagram is one helpful way to portray only what we are /\ / \ BILBO 31 Although most muSIMP programs use such aggregates internally, many muSIMP programs are designed to read and print data in whatever specialized notation is most suitable for the applllowed by the second data item, separated by a dot and spaces, all enclosed in a pair of matching parentheses. For example: (BILBO . 31) We call this representation of a node a DOTTED PAIR. However, this is a diferent g applications involve aggregates of primitive data elements. One way to make an aggregate of 2 data elements is to use a structural data element called a NODE, which stores the addresses of the 2 data elements. Thus, a node is dotted pair rather than attempt to print it using operator and functional notation. We say "attempt" because not all dotted pairs are appropriate for operator or functional printing, as we will explain in the last lessons. Here then 31) . HOBBIT) & % An alternative structure for this information is the one corresponding to the input '((BILBO . BAGGINS) . (31 . HOBBIT)). On a piece of scratch paper, sketch the corresponding diagram, then hold it close to my face so e whatsoever. In order to do anything interesting with data aggregates, a program must be able to extract their parts. Accordingly, there are a pair of SELECTOR functions named FIRST and REST which respectively return the leftd be used as shorthand for the first of the above two examples and for any analogous example thereafter: % FUNCTION FFFIRST (U), FIRST (FIRST (FIRST (U))) ENDFUN & % If you are not using a hard-copy terminal, jot down this funcFIRST on EG: % RDS: FALSE $ % Our solution is: % FUNCTION RFFIRST (FOO), REST (FIRST (FIRST (FOO))), ENDFUN & RFFIRST (EG) & % The name FOO in the definition is called a PARAMETER, whereas EG where the function is applied is an ee want to represent an aggregate of more than two atomic data elements? For example, what if we want to include BILBO's last name, BAGGINS? Well, we can let one of the pointers of a node point to another node, whose first pointer points / \ /\ 31 / \ BILBO BAGGINS How would you input that? Remember, your input must be terminated by an ampersand. % RDS: FALSE $ % We would input it as: % EG: '(((BILBO . BAGGINS) . n be a dotted pair, they can be used to represent arbitrary "binary tree structures". Moreover, although perhaps unprintable using pure dotted- pair notation, linked networks of binary nodes can be used to represent any data-structur $ % Our answers are: % FIRST (FIRST (FIRST (EG))) & REST (FIRST (FIRST (EG))) & % Deeply nested function invocations become difficult to type and read, so let's define our first muSIMP function named FFFIRST, so that FFFIRST (EG) coul: % FFFIRST (EG) & FFFIRST ('(((BIG . MAC) . CATSUP) . (FRENCH . FRIES))) & % Using the definition of FFFIRST as a model, define a function named RFFIRST which extracts the REST of the FIRST of the FIRST of its argument, then test RFis an example of dotted-pair input and printing: % '(78 . TROMBONES) & % Try a few of your own, and note what happens when you forget the single- quote or use a semicolon rather than an ampersand: % RDS: FALSE $ % What about when w '((BILBO . BAGGINS) . 31) & % Note that we only quote the outermost dotted pair. Now suppose that we want to also include BILBO's species, structured as follows: /\ / \ /\ HOBBIT I can check it. ----- / O^O \ \ \-/ / \---/ % RDS: FALSE $ % My eyes must be getting bad, I couldn't see it. Oh well... Since either element of a dotted pair ca and right pointers in a node. For example: % REST (EG) & FIRST (EG) & FIRST (FIRST (EG)) & REST (FIRST (EG)) & % See if you can extract BILBO and BAGGINS from EG, using nested compositions of FIRST and/or REST: % RDS: FALSEtion definition and all subsequent ones for reference later in the lesson. Despite the word ENDFUN, the fun has just begun: Now that FFFIRST is defined, we can apply it at any subsequent time during the dialogue. For exampleto BILBO and whose other pointer points to BAGGINS. For example: /\ / \ /\ 31 / \ BILBO BAGGINS We can input this as a dotted pair nested within a dotted pair: % xample of an ARGUMENT. We can use any name for a parameter -- even a name which has been bound to a value or even the same name as an argument. The name is merely used as a "dummy variable" to help indicate what to do to an argument wh argument is a node, returning FALSE otherwise: % RDS: FALSE $ % In programming there is rarely, if ever, one unique solution, but ours is: % FUNCTION NODE (U), NOT ATOM (U) ENDFUN & NODE (EG) & NODE (5) & % So much for trivif the argument is an atom, then there is exactly 1 atom in it. So much for trivial cases. We haven't yet solved the whole problem, but it builds our self-confidence to make progress, so that is a good psychological the number of atoms for the left part and the number for the right part, clearly the number for the whole aggregate is merely their sum. But how can we find out the number of atoms in these parts? Why not RECURSIVELY use the vern definition corresponding to the above informal English "algorithm": % FUNCTION #ATOMS (U), WHEN ATOM (U), 1 EXIT, #ATOMS (FIRST(U)) + #ATOMS (REST(U)) ENDFUN & % Here we introduce 2 new concepts: The BODY of a functioer a name or an integer, it is convenient to have a recognizer function for atoms, so that we do not have to test separately for names and atoms when we do not care which type of atom is involved. We could define this recognizer asrning TRUE otherwise. There is also a built-in prefix NOT operator which returns TRUE if its operand is FALSE, returning FALSE otherwise. Knowing this, see if you can define a recognizer named NODE, which returns TRUE if itsuse a tree can be arbitrarily branched. How can we anticipate ahead of time all of these possibilities. Well, let's procrastinate by disposing of the most trivial cases even though we can't yet see the whole solution: Ie where we know we have a node. Perhaps we could somehow subdivide the problem into smaller cases? Let's see ... Nodes have a FIRST part and a REST part, so perhaps that provides the natural subdivision. Hmmm ... If we knewD until sometime after its definition is complete, perhaps it will work. We are working in a highly interactive environment, so the quickest way to resolve questions about muSIMP is to try it and see! Here then is a formal muSIMP functioen the function is subsequently applied. A function definition is like a recipe. It is filed away, without actually being EXECUTED until applied to actual arguments. As another simple example, since an atom is defined as being eith both of its operands are FALSE, returning TRUE otherwise. Try out ATOM on the examples -5, X and EG % RDS: FALSE $ % Analogous to OR, there is a built- in infix AND operator which returns FALSE if either operand is FALSE, retual exercises. Now let's write a function which counts the number of atoms in its argument. We will count each instance of each atom, even if some atoms occur more than once. At first this may seem like a formidable task, becareason for first disposing of the easy cases. Also, with the easy cases out of the way, we can turn our full intellectual powers on the harder cases, unfettered by any distractions to trivial loose ends. We are left with the casy function we are defining to determine these two contributions! It may sound like cheating to refer to the function we are defining from with the definition itself, but remembering that the definition is not actually APPLIE follows: FUNCTION ATOM (U), NAME (U) OR INTEGER (U) ENDFUN & Actually, ATOM is already built- into muSIMP, but the example provides a good opportunity to introduce the built-in infix OR operator, which returns FALSE ifn definition can consist of a sequence of one or more expressions separated by commas. A CONDITIONAL-EXIT is an expression consisting of a sequence of one or more expressions nested between the matching pair of words WHEN and EXIT. When ous how muSIMP and #ATOMS keep track of all of these recursive function invocations. Since the trace package is supposedly loaded, to trace the execution of #ATOMS, we merely issue the command: % TRACE (#ATOMS) & % Now every timere is a function which counts only the number of integers in its argument: % FUNCTION #INTEGERS (U), WHEN INTEGER (U), 1 EXIT, WHEN NAME (U), 0 EXIT, #INTEGERS (FIRST(U)) + #INTEGERS (REST(U)) ENDFUN $ EG & #INTEGERS (EG) ;he HEIGHT of an atom is 1, and the HEIGHT of a node is 1 more than the maximum of the two heights of its FIRST and REST parts. Accordingly, let's first write a function named MAX, which returns the maximum of its two integer arguments. Th Our solution is: % FUNCTION HEIGHT (U), WHEN ATOM (U), 1 EXIT, 1 + MAX (HEIGHT(FIRST(U)), HEIGHT(REST(U))) ENDFUN $ % This brings us to the end of the first programming-mode lessons. It may be a good idea to review this lesson befnal exit, the first expression after the word WHEN is evaluated. If the value is FALSE, then evaluation proceeds to the point immediately following the matching delimiter named EXIT. Otherwise, evaluation proceeds seblems into two parts which are necessarily smaller, hence closer to being atoms. Let's test it, starting with trivial cases first: % #ATOMS (FOO) & #ATOMS (5) & EG & #ATOMS (EG) & % It looks promising, but it is still perhaps mysterirresponding entries and exits to be visually associated. Watch: % #ATOMS (FOO) & EG & #ATOMS (EG) & % Try a few examples of your own, until these new ideas begin to gel: % RDS: FALSE $ UNTRACE (#ATOMS) & #ATOMS (FOO) & % H FALSE $ % Our solution is ... On second thought, we won't give you our solution. Consequently, if you were lazy and didn't try, you had better try now, because the examples will get steadily harder now. % RDS: FALSE $ % Ttions, then test your function to make sure it works correctly: % RDS: FALSE $ % Now, with the help of our friend MAX, see if you can write a function named HEIGHT, which returns the height of its argument: % RDS: FALSE $ % a function definition is APPLIED, the expressions in its body are evaluated sequentially, until perhaps a conditional exit causes an exit from the procedure or until the delimiter named ENDFUN is reached. For a conditio and the value returned by a function is that of the last expression evaluated therein when the function is applied. Thus, #ATOMS immediately returns the value 1 whenever the argument is an atom, and otherwise the function breaks the proe #ATOMS is entered, it prints its name and argument values, whereas every time it is exited, it prints its name followed by an equal sign, followed by the returned value. Moreover, the trace is indented in a manner which allows co % Now, using it as a model, try writing a function named #NAMES, which returns the number of names in its argument. If your first syntactically accepted attempt fails any test, try using TRACE to reveal the reason why: % RDS: ere is a built-in infix integer comparator named ">", so here is a hint: FUNCTION MAX (INT1, INT2), WHEN INT1 > INT2, ... EXIT, ... ENDFUN $ Enter such a definition, with appropriate substitutions for the missing porquentially through the remaining expressions in the conditional exit, if any, exactly as if the body of the conditional exit replaced that of the function. The value of a conditional exit is that of the last expression evaluated therein,ore proceeding to lesson PLES2.TRA. % ECHO: FALSE$ NEWLINE: 0$ MOVD (#PRINT, PRINT)$ MOVD (#PRINTLINE, PRINTLINE)$ RDS ()$  a primitive muSIMP Comparator operator which returns TRUE if its two operands are the same object or equal integers, returning FALSE otherwise: % FIVE: 5 $ 5 EQ FIVE ; % Names are stored uniquely, so two occurences of a name must involve\ / \ / \ ! \ \ ! / \ \ JULY 4 4 Clearly it is desirable to have a more comprehensive equality comparator which also returns TRUE for aggregates which are duplicates in the sense of printing similarly. Let'EST parts are duplicates. Moreover, that can be tested with our beloved recursion, using DUP itself! See if you can write a corresponding function named DUP: % RDS: FALSE $ % There are many possible variants, butto learn that an exercise duplicated an existing facility? It is crucial to understand exactly what the existing facilities do, and the best way to learn that is to understand how they work by creating them independently. EX1)), #PRINT (RPAR), EX1, ENDFUN $ MOVD (PRINTLINE, #PRINTLINE) $ FUNCTION PRINTLINE (EX1), PRINT (EX1), NEWLINE (), EX1, ENDFUN $ NEWLINE: 1$ ECHO: TRUE $ % This is the second of a sequence of muSIMP programming lessons. EQ is What happened? The two aggregates are DUPLICATES, but since they were independently formed they do not start with the same node. In fact, only the name JULY is shared among them, as shown below: second DATE argument /\ / both nodes, which is the nontrivial case. Now, let's employ our "divide-and-conquer" strategem, using FIRST and REST as the partitioning. Two nodes refer to duplicate aggregates if and only if the FIRST parts are duplicates and the Rto see how many different but reasonable ways this function can be written. Actually, there already is a built- in infix operator named "=", which is equivalent to DUP: % DATE: '(JULY . 4) $ DATE = '(JULY . 4) ; % Do you feel DUPed %File: PLES2.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ MOVD (PRINT, #PRINT) $ FUNCTION PRINT (EX1), WHEN ATOM (EX1), #PRINT (EX1) EXIT, #PRINT (LPAR), PRINT (FIRST(EX1)), #PRINT (" . "), PRINT (REST( the same address: % ACTOR: 'BOGART ; ACTOR EQ 'BOGART ; % Here is an example of two different references to the same physical node: % DATE: '(JULY . 4) & FOO: DATE $ FOO EQ DATE ; % However, watch this: % DATE EQ '(JULY . 4) ; %s write such a function, called DUP. Following the general advice given in PLES1, let's first dispose of the trivial cases: If either argument is an atom, then they are duplicates if and only if they are EQ. Otherwise, they are here is one of the most compact: % FUNCTION DUP (U, V), WHEN ATOM (U), U EQ V EXIT, WHEN ATOM (V), FALSE EXIT, WHEN DUP (FIRST(U), FIRST(V)), DUP (REST(U), REST(V)) EXIT, ENDFUN $ % An interesting challenge for your spare time is  Here is a good exercise: See if you can write a comparator function named SAMESHAPE, which returns TRUE if its two arguments are similar in the sense of having nodes and atoms at similar places. For example, SAMES ISOMERS (FIRST(U), FIRST(V)) AND ISOMERS (REST(U), REST(V)) OR ISOMERS (FIRST(U), REST(V)) AND ISOMERS (REST(U), FIRST(V)) ENDFUN $ % Because of all the combinations which might have to be checked, the execution time for thisriables in a dotted pair contribute merely their names rather than their values. For example: % EG: 7 $ '(EG . 3) & % What we want is a function which evaluates its two arguments in the usual way, then returns a node whose twofunction named SKELETON, which constructs a new tree which is structurally similar to its argument but has the name of length zero, "", wherever its argument has an atom. Thus, when printed, the new aggregate will disphen combine them? Yes, as follows: % FUNCTION SKELETON (U), WHEN ATOM (U), "" EXIT, ADJOIN (SKELETON (FIRST(U)), SKELETON (REST(U))) ENDFUN $ SKELETON ('((MOO . GOO) . (GUY . PAN))) & % Easy. Yes? Now it is your turn. Wnamed CONTAINS which returns TRUE if its first argument is a duplicate of its second argument or contains a duplicate of its second argument. For example, ((JULY . 4) . (1931 . FRIDAY)) contains (1931 . FRIDAY). It is at land vice-versa. Write a corresponding comparator function named ISOMERS. (It's similar to DUP, with a twist.) % RDS: FALSE $ % Our answer is: % FUNCTION ISOMERS (U, V), WHEN ATOM (U), U EQ V EXIT, WHEN ATOM (V), FALSE EXIT, have constructed new aggregates. The dot of course results in aggregates, but this occurs as the dot is read. Moreover, since the single quote necessarily preceeding an outermost dotted pair prevents evaluation, bound va ADJOIN within a function definition is dynamic. The node creation is done afresh, with the current values of its arguments every time that part of the function is applied. As an example of the use of ADJOIN, let's write a CASES. So, if the argument is an atom we return what? "". Otherwise we have a node, which is the most general case. However, nodes have a FIRST and a REST, so can we somehow recurse, using SKELETON on these parts, tHAPE ('((KINGS . ROOK) . 5), '((QUEENS . 3) . PAWN)) is TRUE: % RDS: FALSE $ % This is one of those instances where we will not give the answer. Now, using the infix operator named "=", see if you can write a function FUR IRON IRON SULFUR are ISOMERS because they are either the same atom or at every level either the left branches are isomers and the right branches are isomers, or the left branch of one is an isomer of the right branch of the other function can grow quite quickly with depth. Try tracing a few examples of moderate depth: % RDS: FALSE $ % So far our functions have merely dismantled or analyzed aggregates given to them as arguments. None of our examples pointers point to those values. There is such a function, named ADJOIN: % ADJOIN (EG, 3) & % A dotted pair within a function definition is a static entity, frozen at the time the function is defined. In contrast, a reference tolay the skeletal structure of the aggregate without visually- discernable atoms. For example, SKELETON ('((HALLOWEEN . GHOSTS) . WITCHES)) will yield (( . ) . ) OK, let's recite the litany: What comes first? TRIVIAL east as hard as DUP, so take your time and don't give up easily. % RDS: FALSE $ % Here is a harder exercise: The two aggregates /\ /\ / \ / \ CARBON /\ CARBON /\ / \ / \ SULrite a function named TREEREV, which produces a copy of its argument in which every left and right branch are interchanged at every level. For example, TREEREV ('((MOO . GOO) . (GUY . (PAN . CAKE)))) should yield (((CAKE . PAN) . GUY) .r solution. Consequently, if you were lazy and didn't try, you had better try now, because the examples will get steadily harder now. % RDS: FALSE $ % The HEIGHT of an atom is 1, and the HEIGHT of a node is 1 more than the maximumta aggregate as a sequence or LIST of items rather than as a general binary tree. For example, such a sequence is quite natural for the elements of a vector or of a set. We can represent such a sequence in terms of nodes by having an, it looks like a clothes line with the successive data elements suspended from it. +-------+-- - - - ---+----- FALSE ! ! ! item1 item2 itemN This latter diagram more clearly suggests a seitem1 . (item2 . ... (itemN . FALSE) ... )) Conversely, the reader accepts list notation as an alternative input form to dot notation. Naturally, any of the items in a list can themselves be either lists or more geneEV ('(("Isn't" . that) . easy)) & % Here is a somewhat harder exercise: Write a function named SUBST, which returns a copy of its first argument wherein every instance of its second argument is replaced by its third argument. For e (#PRINTLINE, PRINTLINE) $ RDS () $ %File: PLES3.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ NEWLINE: 1$ ECHO: TRUE $ % This is the third in a series of muSIMP programming lessons. Often, it is most natural to represent a da / \ item1 /\ / \ item2 . . /\ / \ itemN FALSE When this diagram is rotated 45 degrees in the counter-clockwise directio is far more readable than dotted pairs. In response to an ampersand terminator, muSIMP prints the above aggregate in the more natural LIST notation: (item1 item2 ... itemN) rather than the equivalent dot notation ( (GOO . MOO)) % RDS: FALSE $ % If you didn't get the following solution, you may groan when you see how easy it is: % FUNCTION TREEREV (U), WHEN ATOM (U), U EXIT, ADJOIN (TREEREV (REST(U)), TREEREV (FIRST(U))) ENDFUN & TREER . BAD))) % RDS: FALSE $ % That's all folks. The next lesson deals with a special form of tree called a list. Many people find lists more to their liking, and perhaps you will too.% ECHO: FALSE $ MOVD (#PRINT, PRINT) $ MOVD of the two heights of its FIRST and REST parts. Accordingly, let's first write a function named MAX, which returns the maximum of its two integer arguments. There is a built-in infix integer comparator named ">", so here is a hint: FUNll of the FIRST cells point to the data elements, using the REST cells to link the sequence together. The last linkage node can have a REST cell which is FALSE to indicate that there are no further linkage nodes: /\ quence or list of items. The simple regularity of the structure permits correspondingly simple function definitions for processing such structures. Moreover, the linear structure suggests an external printed representation which xample, if PHRASE: '(((THIS . (GOSH . DARN)) . CAR) . (IS . ((GOSH . DARN) . BAD))) $ then SUBST (PHRASE, '(GOSH . DARN), '(expletive . deleted)) yields (((THIS . (expletive . deleted)) . CAR) . (IS . ((expletive . deleted)ral dotted pairs. The printer uses list notation as much as possible. Thus, a structure of the form /\ / \ item1 /\ / \ item2 . . /\ e language for efficiency reasons. However, it could be defined using an EQ test as follows: FUNCTION EMPTY (LIS), LIS EQ '(), ENDFUN; Using EMPTY, see if you can define a function named #ITEMS, which returns the number of (t that it returns the number of characters necessary for printing when given an atom. Note that with lists it is typical to recur only on the REST of the list, whereas with general binary trees it is typical to recur on both theorm unions, intersections, etc. First, write a function named ISIN, which returns TRUE if its first argument is in the list which is its second argument, returning FALSE otherwise: % RDS: FALSE $ % Our solution is: % is a hint, in case you gave up: FUNCTION SET (LIS), WHEN ... EXIT, WHEN MEMBER (FIRST(LIS), ... ), FALSE EXIT, SET ( ... ) ENDFUN; %RDS: FALSE $ % In case it isn't clear by now, a rule of this game is that you are free (aniced list notation being output in PLES1 and PLES2. At the beginning of those lessons the function PRINT was redefined so that it printed expression entirely in dot notation. It is important to fully understand the connece when the end of the list has been reached. This TERMINAL CASE is easily achieved by an equality test for the name FALSE. Since the need for this test is so pervasive in muSIMP, the empty list recognizer EMPTY is written in machinNCTION #ITEMS (LIS), WHEN EMPTY (LIS), ... EXIT, 1 + #ITEMS ( ... ) ENDFUN $ % RDS: FALSE $ % Actually, there is already a built- in function called LENGTH, which returns the length of a list. It is somewhat more general in provides a natural representation for a set. For example, (MANGO, (CHOCOLATE . FUDGE), (ALFALFA, SPROUTS)) can represent a set of three foods. Using this representation, let's write functions which test set membership and f contains no duplicates, so we really should have a recognizer function named ISSET, which returns TRUE if its list argument contains no duplicates, returning FALSE otherwise. Try to write such a function: % RDS: FALSE $ % Here / \ itemN atom where "atom" is not the atom FALSE, is printed in a mixed notation as (item1 item2 ... (itemN . atom)) The muSIMP read routines will correctly read such mixed notation. You may wonder why you never nott surprising? Since FALSE is used to signal the end of the list, FALSE and the empty list must be equivalent. % FALSE EQ '() & % Clearly functions which successively process each element of a list must somehow determinop-level) items in its list argument. For example, #ITEMS ('(FROG, (FRUIT . BAT), NEWT)) should yield 3. Here is an incomplete solution. All you have to do is enter it with the portions marked "..." appropriately filled. FU FIRST and the REST. So far, the examples and exercises have been relatively isolated ones. Now we will focus on writing a collection of functions which together provide a significant applications package: A list FUNCTION ISIN (U, LIS), WHEN EMPTY (LIS), FALSE EXIT, WHEN U = FIRST (LIS), EXIT, ISIN (U, REST(LIS)) ENDFUN $ ISIN ('FROG, '(SALAMANDER NEWT TOAD)) ; % Actually, there is already a built- in version of ISIN called MEMBER. A settion between dotted pairs and lists, so take 5 minutes or so to type in some lists, nested lists, nested dotted pairs, and mixtures, noting carefully how they print. % RDS: FALSE $ % Did your examples include: % '() & % Is thad encouraged) to use any functions we have already discussed, whether they are built-in, previous examples, or previous exercises. That is one reason it is adviseable for you to actually do the exercises. Now write a function named SUBSry trees. As an example of this, write a function named MAKESET, which returns a copy of its list argument, except without duplicates if there are any: % RDS: FALSE $ % If you need a hint, here is one, but it is all you wias the set of all elements which are in either (perhaps both) sets. Give it a try: % RDS: FALSE $ % A hint perhaps? Well, the function body can be written in 3 lines, each of which begins just like the corresponding line function for the intersection: % RDS: FALSE $ % So far, our set algebra package has been developed in a so-called BOTTOM-UP manner, with the most primitive functions defined first, and with the more sophisticated functions defined in the two sets. This is in contrast to the ordinary diference of two sets, which is all of the elements that are in the first set but not the second. However, if an ordinary difference function was available, we could write the synt, in case you gave up or had a less compact solution: FUNCTION SUBSET (SET1, SET2), WHEN ... EXIT, WHEN MEMBER (FIRST(SET1), ...), SUBSET( ...) EXIT ENDFUN; %RDS: FALSE $ % Two sets are equal if and only if they contain the sed previously: % FUNCTION EQSET (SET1, SET2), SUBSET (SET1, SET2) AND SUBSET (SET2, SET1) ENDFUN; % Our examples so far have merely analyzed sets. We can use ADJOIN to construct lists, just as we used ADJOIN to construct binacate in the answer, then back to the computer terminal: % RDS: FALSE $ % (It helps to think of nasty test cases BEFORE you start programming). Now for the crowning glory of our set package: The UNION of two sets is defined (SET1), SET2)) ENDFUN $ UNION ('(DOG, CAT, 5, RAT), '(-5, CAT, PIG, DOG))& % The intersection of two sets is the set of all elements which are in both sets. Using our definition of UNION as inspiration, write a corresponding functions remain. As an example of the top-down attitude, let's write a SYMMETRIC DIFFERENCE function for our set-algebra package. The symmetric difference of two sets is the set of all elements which are in exactly one of ET, which returns TRUE if the set which is its first argument is a subset of that which is its second argument. (Remember that every set is a subset of itself and the empty set is a subset of every set.) % RDS: FALSE $ % Here is a hi Do you think that's not much of a hint? Well, the body of the function really can be written with one modest line, so try harder: % RDS: FALSE $ % Remember the rules of the game: You are encouraged to use any function discusll get: FUNCTION MAKESET (LIS) WHEN ..., '() EXIT, WHEN MEMBER ( ... ), ... EXIT, ADJOIN ( ... ) ENDFUN; %RDS: FALSE $ % Let's see if your solution works correctly: % MAKESET ('(FROG, FROG, FROG)) & % If there is a dupli in our hint for MAKESET. % RDS: FALSE $ % Here is our solution: % FUNCTION UNION (SET1, SET2), WHEN EMPTY (SET1), SET2 EXIT, WHEN MEMBER (FIRST(SET1), SET2), UNION (REST(SET1), SET2) EXIT, ADJOIN (FIRST(SET1), UNION (RESTterms of them. The opposite approach is TOP-DOWN, where we define the most comprehensive functions in terms of more primitive ones, then we define those more primitive ones in terms of still more primitive ones, until no undefined same elements. However, the elements need not occur in the same order. Write a corresponding comparator function named EQSET: % RDS: FALSE $ % Ah yes, a hint perhaps?: FUNCTION EQSET (SET1, SET2), ... ENDFUN; % RDS: FALSE $ % mmetric difference as the union of the ordinary difference between set1 and set2, with the ordinary difference between set2 and set1. We have already written UNION, but an ordinary set difference is not yet available. Nevertheless, lethe need to completely reorganize and rewrite all subordinate functions into a more suitable organization. In contrast, the obvious loose ends during a top-down development provide invaluable clues about how to orgaficient merely to append the second ordinary set difference to the first ordinary set difference, or vice- versa. Unfortunately, ADJOIN does not accomplish the desired effect. For example, ADJOIN ('(5, 9), '(3, 7)) yields ENDFUN $ % You may not be getting tired, but my circuits are weary, so let's bring this lesson to a close. % ECHO: FALSE $ RDS () $ $ % Now you try to write ORDDIF. It may help you to know that it can be written very similarly to UNION: % RDS: FALSE $ % Some programmers are initially uncomfortable with the top-down approach because it makes them equential order. With the bottom-up approach, the loose ends are neither written nor referred to until lower- level functions have been written. Unfortunately, as such hidden loose ends are revealed they often make apparent definition of SYMDIF we are taking the union of two DISJOINT sets, because from the definition of ORDDIF it is clear that ORDDIF (SET1, SET2) and ORDDIF (SET2, SET1) cannot have elements in common. Hence it would be more ef is its first argument appended onto the beginning of the list which is its second argument:% RDS: FALSE $ % How about: % FUNCTION APPEND (LIS1, LIS2), WHEN EMPTY (LIS1), LIS2 EXIT, ADJOIN (FIRST(LIS1), APPEND (REST(LIS1), LIS2)) t's bravely proceed to write the symmetric difference in terms of the ordinary difference, then we will worry about how to write the latter: % FUNCTION SYMDIF (SET1, SET2), UNION (ORDDIF (SET1, SET2), ORDDIF (SET2, SET1)) ENDFUN s necessary is that the duty relegated to the auxiliary function be somehow more elementary than the overall duty performed by the function which refers to it. There are necessarily loose ends during the writing of a program in any snize the remaining functions. Moreover, any subsequent changes tend to be easier, because communication between the functions is more localized, more independent, and more hierarchial. For example, we know that in the((5, 9), 3, 7) rather than the desired (5, 9, 3, 7). What we must do is ADJOIN 9 to (3, 7), then adjoin 5 to that result. See if you can generalize this process into a function named APPEND, which returns a list consisting of the list whichnervous to refer to undefined functions: there are obvious loose ends during the writing process. However, it is not necessary to understand how an auxiliary function can be written before daring to refer to it. All that i%File: PLES4.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ NEWLINE: 1$ ECHO: TRUE $ % This is the fourth in a series of muSIMP programming lessons. Often within a function definition it is necessary to DYNAMICAFUNCTION REVLIS (LIS), WHEN ... , FALSE EXIT, APPEND ( ... , LIST (FIRST (LIS))), ENDFUN $ See if you can successfully complete this definition. Naturally, you also have to reenter APPEND if a correct version is not around from thely proportional to n*(n/2), which is proportional to n^2. An technique using COLLECTION VARIABLES permits a list to be reversed in time proportional to n, yielding tremendous time savings for long lists: % FUNCTION REVLIS (alized to FALSE, and they are available for use as LOCAL VARIABLES within the function body. Quite often, as in this example, the initial value of FALSE is exactly what we want, because it also represents the empty list. (When weed, but ignored. Up to this point the lessons have taught the "applicative" style of programming. The emphasis has centered on expression evaluation, functional composition, and recursion. The power and elegance of applicative prator prevents evaluation of the variables. However, the desired effect can be achieved by the statement ADJOIN (FIRSTNAME, ADJOIN (LASTNAME, ADJOIN (MAILADDRESS, '()))). muSIMP provides the function LIST to achieve this effec: FALSE $ % A useful utility to have is a constructor function which reverses a list. Writing such a function can be somewhat tricky. The following skeletal definition uses our friends APPEND and LIST as helper functions: al to the length of its first argument. The REVLIS function outlined above invokes APPEND n times if n is the length of its original argument, and the average length of the argument to APPEND is n/2. Thus, the time is approximatting value is passed back through successive levels as the returned answer. As is illustrated here, we can invoke a function with fewer arguments than there are parameters. When this is done, the extra parameters are initireturns the reversed first argument appended onto the second argument. This "feature" is occasionally quite useful. What if the user supplies more arguments than there are parameters? The extra arguments are evaluatLLY create a list. Suppose we want to make a list of the values of the variables FIRSTNAME, LASTNAME, and MAILADDRESS. It will not do to use the program statement '(FIRSTNAME, LASTNAME, MAILADDRESS), because the quote ope consider the following assignments: % FIRSTNAME: 'JOHN & LASTNAME: 'DOE & MAILADDRESS: 'TIMBUKTU & % Create a list of these variables using the quote operartor and compare it with a list created using the function LIST: % RDSe previous lesson. (Remember to jot down all function definitions if you are not using a hard-copy terminal.) % RDS:FALSE $ % A well-written APPEND necessarily requires execution time which is approximately proportionLIS, ANS), WHEN EMPTY (LIS), ANS EXIT, REVLIS (REST(LIS), ADJOIN (FIRST(LIS), ANS)) ENDFUN $ TRACE (REVLIS) & REVLIS ('(1, 2, 3)) & % A collection variable accumulates the answer during successive recursive invocations. Then, the resul want some other initial value, either the user can supply it, or the function can supply it to an auxiliary function which does the recursion.) Of course, if a user of REVLIS supplies a second argument, then the function t much more compactly and conveniently. Thus, the above list could be created with the following statement: LIST (FIRSTNAME, LASTNAME, MAILADDRESS) Unlike most functions, LIST can have any arbitrary number of arguments. For examplerogramming was the topic of an influential Turing Lecture by J Backus. The lecture was published in the August 1978 issue of the Communications of the ACM. muSIMP also supports the alternative "Von Neumann" style empha of conditional exits anywhere in a loop. Ordinarily there is at least one exit unless the user plans to have the loop repeat indefinitely. Now consider the following sequence: % L1: '(THE ORIGINAL ) $ L2: '(TAIL) $ LIS: 'DOG & ANS: 'CATof the original environment following the return from a called function allows the programmer to change the value of a function's parameters without fear of damaging the values the parameters of the same name have outside the "global" variables. The iterative version of REVLIS using the LOOP construct is slightly faster than the recursive version, but the latter is more compact. When there is such a trade-off between speed and compactness, a good strahaust all available memory before completing its task. This will result in the ALL Spaces Exhausted error trap. The use of iteration in this situation might permit an equivalent computation to proceed to terminat ANS: ADJOIN (FIRST(LIS), ANS), LIS: REST (LIS) ENDLOOP ENDFUN $ % muSIMP has a function named REVERSE which is defined in machine language. Since it is entirely equivalent to REVLIS and much faster, REVERSE should normally be 2. When evaluation reaches an EXIT within the loop, evaluation proceeds to the point immediately following ENDLOOP, and the value of the loop is that of the last expression evaluated therein. There can be any number ss are the corresponding current values for LIS and ANS? See for yourself: % RDS: FALSE $ % The assignments to parameters LIS and ANS in REVLIS has no effect on their values once the function has returned! The restoration more than one piece of information, a list of values can be returned. However, another way is to make assignments within the function body to variables which are not among its parameters. Such variables are called "fluid" ortask. Each time a function is called information must be stored on a STACK so the original environment can be restored when the function returns. Since recursion involves the nesting of function calls, a highly recursive function can exsizing loops, assignments, and other side-effects. To illustrate this style, here is an alternative definition of REVLIS which introduces the LOOP construct: % FUNCTION REVLIS (LIS, ANS), LOOP WHEN EMPTY (LIS), ANS EXIT, the matching delimiter named ENDLOOP. The body of a loop is evaluated similarly to a function body, except: 1. When evaluation reaches the delimiter named ENDLOOP, evaluation proceeds back to the first expression in the loop. & REVLIS (L1, L2) & % The above definition of REVLIS makes assignments to its parameters LIS and ANS. For this example, the final assignments are LIS: '() and ANS: '(ORIGINAL, THE, TAIL). So, what do you guefunction. Thus functions can be thought of as "black boxex" which have no effect other than their returned value. A function's parameters can not be used to pass information back to the calling function. If we wish to return tegy is to program for speed in the crucial most frequently used functions, and program for compactness elsewhere. Another consideration when choosing between iteration and recursion is the amount of storage required to perform a given used in place of REVLIS in application programs written by the user. An iterative loop is an expression consisting of the keyword LOOP, followed by a sequence of one or more expressions separated by commas, followed by ion. For practice with loops, use one to write a nonrecursive recognizer named ISSET, which returns TRUE if its list argument contains no duplicate elements, returning FALSE otherwise. (Compare your definition with the reOP, or ENDFUN delimiter -- whichever is nearest. Thus, BLOCK provides a means for alternative evaluation paths which rejoin within the same function body or loop body, without causing an exit from that body. The first exsing the order of the set elements. Using ADJOIN in a loop generally has this effect, which is why it is so suitable for REVERSE. With sets, incidental list reversal is perhaps acceptable, but for most applications of liepresented as ordered lists. Loops are also less applicable to general tree structures than to lists, but it is often possible to loop on the REST pointer while recursing on the first pointer, or vice-versa, particularly if ADJ does what the infix operator named "=" does: % RDS: FALSE $ % Those of you with previous exposure to only Von Neumann style programming undoubtedly feel more at home now. The reason we postponed revealing these features until now is that w CAT, COW, CAT, RAT)) & % Another good exercise adapted from PLES3 is to use a loop to write a nonrecursive function named SUBSET, which returns TRUE if its first argument is a subset of its second argument, returning FALSE ANS), EXIT, ANS: ADJOIN (FIRST(LIS), ANS) ENDBLOCK, LIS: REST (LIS) ENDLOOP ENDFUN $ MAKESET ('(FROG, FROG, FROG, TERMITE)) & % When evaluation reaches an EXIT, it proceeds to the point following the next ENDBLOCK, ENDLO control mechanism. For example, the CASE- statement and IF-THEN-ELSE construct of some other languages are essentially special cases of a block. You may not have noticed, but the loop version of MAKESET has the effect of reverfurther increasing its greater bulk. Thus, recursion is usually preferable to loops when ADJOIN is involved. For example, recursion is used almost exclusively to implement muMATH, because its symbolic expressions are r U: REST (U) ENDLOOP ENDFUN $ #ATOMS ('((3 . FOO), BAZ)) & % If the answer surprises you, don't forget the FALSE which BAZ is implicitly dotted with. See if you can similarly write a semi-recursive function named DUP which cursive version in lesson PLES3.) % RDS: FALSE $ % Here is our solution: % FUNCTION ISSET (LIS), LOOP WHEN EMPTY (LIS), EXIT, WHEN MEMBER (FIRST(LIS), REST(LIS)), FALSE EXIT, LIS: REST (LIS) ENDLOOP ENDFUN $ ISSET ('(DOG,of the MAKESET function from PLES3 returns a set composed of the unique elements in the list which is its first argument: % FUNCTION MAKESET (LIS, ANS), LOOP WHEN EMPTY (LIS), ANS EXIT, BLOCK WHEN MEMBER (FIRST(LIS), pression in a block must be a conditional-exit (anything else can be moved outside anyway), but since there can be any number of other conditional exits or other expressions within the block, the block provides a very general structuredsts it is not. We could of course use a preliminary or final invocation of REVERSE so that the final list would emerge in the original order, but that would relinquish the speed advantage of the loop approach, while OIN is not involved. For example, compare the following semi-recursive definition of #ATOMS with the fully-recursive one in PLES1: % FUNCTION #ATOMS (U, N), N: 1, LOOP WHEN ATOM (U), N EXIT, N: N + #ATOMS (FIRST(U)), otherwise: % RDS: FALSE $ % A BLOCK is another control construct which is sometimes convenient, particularly in conjuction with the Von Neumann style. As an illustration of its use, the following iterative version e wanted to force the use of applicative programming long enough for you to appreciate it too. Naturally, one should employ whichever style is best suited for each application, so it is worthwhile to become equally conversan n. Now, let's consider the speed of some of the other set functions that we defined: Whether iterative or recursive, MEMBER can require a number of equality comparisons equal to the length of its second argument. Whether defined ent. Data-base applications and others can involve thousands of set operations on sets having thousands of elements, so it is worthwhile to seek methods for which the computation time grows more slowly with set size. In muSIMP, eession called the KEY or INDICATOR, and the rest of each dotted pair is an expression called the associated INFORMATION. For example, in a meteorological data-base application, the name HONOLULU might have the property list PUT returns the value of "information". Using property lists, the basic technique for accomplishing our various operations on two sets of names is: 1. For each name in one of the two sets of names, store TRUE under the key SEEN. E, called REVLIS, required time proportional to n^2, where n is the length of the first argument. We then showed how a collection variable or a loop could yield a much faster technique using time proportional only to on time which grows as the product of the lengths of the two arguments. By similar reasoning, the one- argument functions ISSET and MAKESET are seen to require time proportional to the square of the length of their argumhe above set operations requiring time proportional merely to the length of the one set or to the sum of the lengths of the two sets. A property list is a list of dotted pairs. The first of each dotted pair is an exprng FALSE if no such key occurred on the property list. A command of the form PUT (name, key, information) causes the value of "key" dotted with the value of "information" to be put on the property list of the value of "name".t with both styles. Thus endeth the sermon. % ECHO: FALSE $ RDS () $ %File: PLES5.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ NEWLINE: 1$ ECHO: TRUE $ % This is the fifth in a series of muSIMP programming lessons. In the previous lesson our original version of REVERS iteratively or recursively, SUBSET, EQSET, UNION, and INTERSECTION all require a membership test for each element of one argument in the list which is the other argument. Thus, these definitions can all consume computativery name has an associated PROPERTY LIST which is immediately accessible in an amount of time that is independent of the total number of names in use. Provided the elements of the sets are all names, this permits techniques for t ((RAIN . 2), (HUMIDITY . 40), (TEMPERATURE, 58, 96)) The function used in the form GET (name, key) returns the information which is dotted with the value of "key" on the property list of the value of "name", returni 2. For each name in the other set, check to determine whether or not the name has already been seen, and act accordingly. 3. For each name in the first set, remove the property SEEN so that we won't invalidate subsequentSET1 in the definition of UNIONAUX refers to the argument value associated with that parameter of UNION. This treatment is called "dynamic binding", and a reference such as to SET1 in UNIONAUX is called a "fluid reference". e the concept to issue this advice. Values assigned at the top-level of muSIMP, outside all function definitions, are called GLOBAL values. Examples are the initial values of muSIMP control variables such as RDS and ECHe naturally implemented using the Von Neumann programming style. Try to write such a version of UNION: % RDS: FALSE $ % Now, using either style, write an INTERSECTION function using the property-list technique: %RDS: FALSE $ ormally points to the integer itself. The REST cell is used to determine the sign of the number: if FALSE the integer is non-negative, if TRUE the integer is negative. % FIRST (7) & REST (7) & NINE: 9 $ PUT (NINE, 'TESTING, '(1, 2, 3ue together with the applicative style: % FUNCTION UNION (SET1, SET2), MARK (SET1), UNMARK (SET1, UNIONAUX (SET2)) ENDFUN $ FUNCTION MARK (SET1), WHEN EMPTY (SET1), EXIT, PUT (FIRST(SET1), 'SEEN, TRUE), MARK (REST (SET1)) ENDFUN rior to return from that invocation. If a function refers to a variable which is not among its parameters, then the most recent value of the variable on the stack is used. Thus, when UNIONAUX is invoked from within UNION, maintain, especially if assignments are made to them in functions other than the ones which establish them. Consequently, we recommend generally avoiding fluid variables. The only reason we used one here is to introducrous long lists of parameters in order to pass such environmental control values through a long sequence of function definitions for use deep within. The property-list technique for set operations is one which we think is moratom. For example: % WEATHER: 'FOUL $ PUT ('WEATHER, 'TEMPERATURE, -3) $ PUT ('WEATHER, 'WIND, '((NORTH . WEST), 30)) $ FIRST (WEATHER) & REST ('WEATHER) & % Integer atoms also have FIRST and REST cells. The FIRST cell of an integer n set operations which utilize any of the same elements. A simpler variant of this idea is applicable to the one-argument functions named ISSET and MAKESET. As an example, here is UNION defined using this techniq(FIRST(SET1), 'SEEN, FALSE), UNMARK (REST(SET1), ANS) ENDFUN $ UNION ('(A, B, C, D), '(F, A, E, C)) & % Each time any function is invoked, the outside values of its parameter names, if any, are "stacked" away to be restored later, just p We could have avoided this by making SET1 be an argument and a parameter to UNIONAUX, but that would have made the program slightly slower and more bulky. However, fluid variables make programs much harder to debug andO, or of muMATH control variables such as PBRCH or PWREXPD. Reference to a global value from within a function definition is not quite as confusing as reference to a fluid value, and it is indeed onerous to create nume % Taking the FIRST and/or REST of an atom is generally not necessary, but it does in fact have a well-defined value. The FIRST cell of an atom points to the atom's value, while the REST cell points to the property list associated with the $ FUNCTION UNIONAUX (SET2), WHEN EMPTY (SET2), SET1 EXIT, WHEN GET (FIRST(SET2), 'SEEN), UNIONAUX (REST(SET2)) EXIT, ADJOIN (FIRST(SET2), UNIONAUX(REST(SET2))) ENDFUN $ FUNCTION UNMARK (SET1, ANS), WHEN EMPTY (SET1), ANS EXIT, PUT )) & GET (NINE, 'TESTING) & GET (9, 'TESTING) & % All muSIMP data objects (i.e. nodes, names, and integers) have a FIRST cell and a REST cell which can only point to valid muSIMP data objects. Thus, misuse of these selectors cannot rint and return an error message when given a nonFALSE atom: % FUNCTION EMPTY (LIS), WHEN ATOM (LIS), WHEN LIS EQ FALSE EXIT, PRINT ("*** Warning: EMPTY given nonlist ") EXIT ENDFUN $ EMPTY (5) $ % This is our first exam fewer actual arguments than the function has formal arguments, the remaining formal arguments are assigned the value FALSE. This provides a convenient mechanism for automatically inserting default values for these extra ararameter list of a function definition be an atom or non-list rather than a list. The arguments are passed to the function as a single list of argument values, from which the function can extract the values. For example, it is convenient nguish from the SPREAD brand of peanut butter. Now, suppose that for some reason we already have a list of integers such as % NUMBLIS: '(18, 3, 7, 91, 12, 2) $ % and we want to find their maximum. The expression MAX (NUMBLIS) will noractice to use EMPTY to test for the end condition as a function proceeds down a list. If such a function is inadvertently given a non-list (i.e. a Non-FALSE atom or a structure whose final REST cell points to a Non-FALSE atom), the fund any other functions ordinarily applied to lists use ATOM rather than EMPTY as the termination test. This is slightly faster too, so you may wish to generally avoid EMPTY in favor of ATOM. Alternatively, you can redefine EMPTY to pnated with an ampersand are printed. There is an analogous function named PRTMATH which prints its one argument the same way that expressions terminated with a semicolon are printed. When functions are called with drive indicated by the last operating system prompt given before entering muSIMP). There are instances where it is desirable to permit a function to have an arbitrary number of arguments. This is accomplished by making the formal p (UNTRIED), BIGGEST EXIT, WHEN BIGGEST > FIRST(UNTRIED), MAXAUX (BIGGEST, REST(UNTRIED)) EXIT, MAXAUX (FIRST(UNTRIED), REST(UNTRIED)) ENDFUN $ MAX (7) ; MAX (3, 8, -2) ; % This collection of arguments into a list is called NOSPREAD, to distiaccidently give access to non-data objects such as machine language code, stack, print names, etc. This closed pointer universe guarantees the integrity of muSIMP from possible excursions into the unknown. It is common p the EMPTY test will ultimately cause termination with no ill affects. We prefer to have non-list arguments give more predictable results confined to the argument. Thus, our internal implementations of MEMBER, REVERSE, anple illustrating the fact that conditional exits can be nested arbitrarily deep. The same is true of loops or blocks. This example also illustrates the PRINT function, which prints its one argument the same way that expressions termiguments. When an argument evaluates to FALSE, the function can assign the appropriate default value. For example, if the user omits the drive as the third argument of RDS, that function uses the currently logged in drive (i.e. theto have a function named MAX which returns the largest of one or more argument values. We can implement this as follows: % FUNCTION MAX ARGLIS, MAXAUX (FIRST(ARGLIS), REST(ARGLIS)) ENDFUN $ FUNCTION MAXAUX (BIGGEST, UNTRIED), WHEN EMPTYction will use the FIRST cell of that atom (i.e. its Value cell) as an element of the list and the REST cell of the atom (i.e. its Property List cell) as the REST of the list. Generally the Property List is a well defined list sot work, because MAX is designed for numeric arguments, not for a list of numbers. We could of course extract the elements and feed them individually to MAX, but this is awkward, especially if we are referring to MAX inside a function recompiled back into D-code, a muSIMP program can actuately be made to modify muSIMP functions! In fact, this is exactly what the TRACE and UNTRACE commands do to the traced function. Other examples which could use this feature  ADIOS DISK COPY UTILITY, 05/11/81  TYPE TO ABORT COPY, OTHERWISE ENTER  SOURCE DRIVE NUMBER: Lw  TARGET DRIVE NUMBER: Lx  wx   TYPE TO BEGIN; TO ABORT COPY; OR A TO CHANGE DISK IN DRIVE 1 ` ? 17H h)8H h(`)d`)P)@cbxL5s `RT $I$I$UUU$$A$ value of its second argument. Consequently, we need merely write % APPLY ('MAX, NUMBLIS) & % APPLY works on either SPREAD or NOSPREAD functions. Why don't you try out a few examples: %RDS: FALSE $ % A function written in muSIined function, GETD returns returns FALSE. The following examples show the result of all three types of arguments: % GETD ('UNION) & GETD ('FIRST) & GETD ('FOO) & % Since function definitions can be converted into lists and theed you with sufficient knowledge to be able to use the muSIMP Section of the Reference Manual to achieve any desired muSIMP programming goal. % ECHO: FALSE $ RDS () $ )ԭwx   iL  DISK COPY COMPLETE; MORE (Y/N)? Y N ?L@  L L ? RETURN TO CONTINUE, ESC TO ABORT;    DISK COPY ABORTED; MORE (Y/N)? L@  `  INSERT DISK IN DRIVE 1 `  INSERT n and we do not know ahead of time how many integers are in NUMBLIS. Fortunately there is a convenient function named APPLY, which applies the function whose name is the value of its first argument to the argument list which is the decompile the definition and return it is as a linked list. If GETD is given the name of a primitively defined machine language routine instead, the physical memory address of the routine is returned. Finally, if its argument is not a def include a muSIMP function editor and pretty printer, a cross reference program, and even a compiler all of which could be written in muSIMP. This is the end of programming lesson 5. These lessons should have providDRIVE REQUEST:  L LX ?L IрI(恩Ł襁& INSUFFICIENT GOOD RAM FOR COPY!Lyf kngw =kgi)gff#)׭yfwx   i kngx =kgi)gfyf#MP is stored internally in a very compact form called D-code (see Section 13.9 of the muMATH Reference Manual). In order to retrieve the definition for use as data, the function GETD (GET Definition) of one argument can be used to% File: DEMO.INT (c) 10/07/81 The Soft Warehouse % ECHO: FALSE $ NEWLINE: 1 $ DENNUM: -30$ A: 'A$ B: 'B$ POINT: FALSE$ NUMNUM: LOGEXPD: 30$ DENDEN: 2$ PWREXPD: 6$ TRGEXPD: -15$ MOVD ('NEWLINE, 'CRLF)$ FUNCTION NEWLINE (EX1, EX2), CRLF (OINT: 10$1/3; %*** VARIABLE RADIX BASE ***% % SET FOR HEXADECIMAL ARITHMETIC % RADIX (16);% USE AS A HEX CALCULATOR % 7C80 - 2*12EF + 0A3C;% ASSIGNMENT TO A VARIABLE % EG: 10000;% RETURN TO BASE TEN ARITHMETIC % RADIX (0A);% FIND AUTOMATIC ALGEBRAIC SIMPLIFICATION % % COMBINES SIMILAR TERMS AND FACTORS % 3*X - X;Y^3 * Y^(R+1); % EXPLOITS IDENTITIES AND ZEROS % 0 + X;1 * Y;Z * 0;X^1;Y^0;1^X;% MULTIPLE SIMPLIFICATIONS % 5*X^1*Y + Y^2*-3*X/Y + W^(Z^2 - Z*Z);% POLYNOMIAL MX+5); %*** TRIGONOMETRIC SIMPLIFICATIONS ***% % ELEMENTARY ANGLE VALUES % COS (0);SIN (#PI/2);SIN (37*#PI/3);% EQUIVALENT FUNCTIONS % TAN(X) * COS(X);% MULTIPLE ANGLES EXPANSION % SIN (2*X);COS(3*X);% ANGLE SUMS EXPANSION % COS (X-Y);% COMBNCTION TAYLOR (EXPN, X, A, N, % Locals: % J, C, ANS, NUMNUM, DENNUM), NUMNUM: DENNUM: 30, J: ANS: 0, C: 1, LOOP ANS: ANS + C * EVSUB (EXPN, X, A), WHEN J=N, ANS EXIT, EXPN: DIF (EXPN, X), J: J + 1, C: C * (X-A) / J, emostration file. The length of the momentary pause between problems is controlled by the size of the variable PAUSE. The default value of PAUSE is 5. This demo requires the following muMATH files be loaded: EQN.ALG LOG.ALG TRGNEG.ALG MI;% EXACT, INFINITE PRECISION % 99^99; %*** RATIONAL ARITHMETIC EXAMPLES ***% % REDUCE FRACTIONS TO LOWEST TERMS % 56/77;% FIND COMMON DENOMINATOR % 5/6 - 3/4;% RATIONAL SIMPLIFICATION % 3 * (1/2 + 1/6);% FLOATING POINT NOTATION % PRS OF THE IMAGINARY NUMBER % #I^2;#I^-7;% COMPLEX EXPONENTIALS % #E ^ (#I*#PI); %*** FACTORIALS ***% 5!;50!^2;% BINOMIAL COEFFICIENTS [12:30] % N: 30;M: 12;N! / ((N-M)!*M!); %*** BASIC ALGEBRA EXAMPLES ***% % % LOG (1000, 10);% EXPAND THE LOG OF A PRODUCT % LN (X*Y);% EXPAND THE LOG OF A POWER % LOG (Z^3, 10);% MULTIPLE SIMPLIFICATIONS % LN(X^2*Y) - 2*LN(X);% INTER-BASE SIMPLIFICATIONS % LOG(X,10) * LOG(10,#E);% LOGARITHMIC POWERS % #E ^ LN(2 + 5*X - 4, X);DIF (LN(X)^2, X);DIF (#E^X^2, X);DIF (P*SIN(X) + X^2, X);% FIND INTEGRALS % INT (2*X - 1/X, X);INT (X * #E^X^2 * SIN(#E^X^2), X);INT (LN(LN(X))/X, X); %*** PROGRAMMING IN MUSIMP ***% % TAYLOR SERIES EXPANSION FUNCTION % FUEX1), BLOCK WHEN INTEGER (PAUSE) EXIT, PAUSE: 5 ENDBLOCK, EX2: PAUSE, LOOP WHEN NOT POSITIVE (EX2) EXIT, 1000*1000, EX2: EX2-1 ENDLOOP ENDFUN$ ECHO: TRUE$ % Use CTRL-S to start and stop the scrolling of this d VARIABLE % FOO: (3*8 - 16)^2;% USE OF ASSIGNED VARIABLE % 3*FOO^5;% SAVE INTERMEDIATE RESULTS % SEC#PER#YR: 365*24*3600;IN#PER#MI: 5280*12;% USE OF INTERMEDIATE RESULTS % % TO FIND INCHES TO ALHPA CENTAURI % 4 * 186000 * SEC#PER#YR * IN#PER#EG IN BASE TEN % EG;% BASE TWO ARITHMETIC % RADIX (2);% BINARY ARITHMETIC CALCULATOR % 101101110 * EG;% RETURN TO BASE TEN ARITHMETIC % RADIX (1010); %*** EXPONENTIAL SIMPLIFICATIONS ***% % FRACTIONAL POWERS % 8 ^ (2/3);12 ^ (1/2);% POWEULTIPLICATION % (3*X - 2*Y) * (Y^2 + 4*X);% POLYNOMIAL POWERS % (X+1)^2;(X+5) * (X^2-2*X+3)^2;% CONTENT FACTORIZATION % FCTR (6*X^3*Y + 15*X^2*Y); %*** LOGARITHMIC SIMPLIFICATIONS ***% % NATURAL LOG OF ONE % LN (1);% COMMON LOG OF 100INATION EXPANSIONS % EG: SIN (2*X+Y); %*** REPRESENT EQUATIONS ***% EQN: 2*X+7 == A^2 - X^2/X - 3;% STEP BY STEP SOLUTION FOR X % EQN: EQN + X - 7;EQN: EQN/3; %*** CALCULUS OPERATIONS ***% % FIND DERIVATIVES % DIF (3*X^DIF.ALG INT.DIF % %*** INTEGER ARITHMETIC EXAMPLES ***% % INTEGER ADDITION & SUBTRACTION % 32 + 15 - 24;% MULTIPLICATION & UNARY MINUS % 5 * -12;% USE OF PARENTHESIS % 436 * (123 - 57);% RAISING TO A POWER % 100^3;% ASSIGNMENTS TO A ENDLOOP, ENDFUN ;% TAYLOR SERIES EXPANSION % TAYLOR (#E^X, X, 0, 6);TAYLOR (SIN(X), X, 0, 8);TAYLOR (#E^SIN(X), X, 0, 4); MOVD ('CRLF, 'NEWLINE)$ RDS ()$  about muSIMP programming. It presumes as a minimum that you have read section 8 of the muSIMP/muMATH Reference Manual. Also the first part of CLES1.ARI should be completed since it explains the mechanics of how to interact wit realize that, until the last programming-mode lessons, we will not deal with muMATH. Instead we deal first with muSIMP, the language in which muMATH is written. The illustrative examples for these first few lessons are utterly differe are two corresponding RECOGNIZER functions: % INTEGER (X76#) ; NAME (X76#) ; EG: -3271 $ INTEGER (EG) ; NAME (EG) ; % Do you suppose that "137", " ", "", and "X + 3", with the quotation marks included, are integers, names, or invg applications involve aggregates of primitive data elements. One way to make an aggregate of 2 data elements is to use a structural data element called a NODE, which stores the addresses of the 2 data elements. Thus, a node is    L!˜ȑL! .  3 åL)Dȑ "  ! ʑȱˑL!)6  !.  3  w"  Ðʠ)`8`ȱ L"   "  ^ߐť   L  ), PRINT (REST (EX1)), #PRINT (RPAR), EX1, ENDFUN $ MOVD (PRINTLINE, #PRINTLINE) $ FUNCTION PRINTLINE (EX1), PRINT (EX1), NEWLINE (), EX1, ENDFUN $ NEWLINE: 1$ ECHO: TRUE $ % This is the first of a sequence of interactive lessons lessons introduce more built-in functions and operators, but more important, the lessons reveal how to supplement the built-in functions and operators with definitions of your own, thus extending muSIMP itself. It is important to programs operate upon. The most primitive UNSTRUCTURED muSIMP data are integers and names, collectively called ATOMS to suggest their indivisibility by ordinary means. Some programs must distinguish these two types of atoms, so th data stored there is analogous to mail inside the mailbox. As with a row of mailboxes, the contents of computer memory can change over time. There are useful programs which deal only with unstructured data, but the most interestin 1L s߰ ߰ 7`L ߰ 1G L*U  !   @!    )  !LQ!L L,"ߐȅɅȅʥɅ` .  ȥʥȱ (    3   L " %File: PLES1.TRA (c) 09/24/80 The Soft Warehouse % MATHTRACE: FALSE $ RFFIRST: 'RFFIRST $ MOVD (PRINT, #PRINT) $ FUNCTION PRINT (EX1), WHEN ATOM (EX1), #PRINT (EX1) EXIT, #PRINT (LPAR), PRINT (FIRST (EX1)), #PRINT (" . "h the lessons. The file TRACE.MUS should be loaded. muSIMP supplies a number of built- in functions and operators. The calculator-mode lessons introduced a few of these, such as RDS, RECLAIM, +, *, etc. These progamming-mode erent from muMATH, because we want to suggest a few of the many other applications for which muSIMP is especially well suited, and because we want these lessons to be comprehensible regardless of math training level. Data is what alid? Find out for yourself% RDS: FALSE $ % Data can be stored in the computer's memory. The location at which a data item is stored is called its ADDRESS. An address is analogous to a street address on the outside of a mailbox. The ¥2 .   3  ''   ҠL*#L0* 7 ''   &     0*   LS#LL … åL# - CL* & I  C 6L*L!` &  L4$ L($ &Υ"data" consisting of addresses of 2 other data items. For example, suppose that we wish to represent the aggregate consisting of the name BILBO and his age 31. We could store the name BILBO beginning at location 7, the number 31 beginn /\ / \ BILBO 31 Although most muSIMP programs use such aggregates internally, many muSIMP programs are designed to read and print data in whatever specialized notation is most suitable for the applllowed by the second data item, separated by a dot and spaces, all enclosed in a pair of matching parentheses. For example: (BILBO . 31) We call this representation of a node a DOTTED PAIR. However, this is a diferent dotted pair rather than attempt to print it using operator and functional notation. We say "attempt" because not all dotted pairs are appropriate for operator or functional printing, as we will explain in the last lessons. Here then to BILBO and whose other pointer points to BAGGINS. For example: /\ / \ /\ 31 / \ BILBO BAGGINS We can input this as a dotted pair nested within a dotted pair: % ----+-----+----- ! 31 ! ! 7 ! 2 ! !BILBO ---+-----+-----+-----+-----+-----+----- The specific placement of data within memory is managed automatically, so all we are concerned about is the specific name and number values you have seen one bisected box you have seen them all, so to reduce the clutter and thus emphasize the essential features, we henceforth represent such nodes by a mere vertex in our diagrams, giving schematics such as onveniently could use diagrams such as the above. Most of us do not have nice graphics terminals, so we must use another external representation. For this purpose muSIMP uses a representation consisting of the first data item, fo usual operator or functional notation: '(BILBO . 31) Moreover, we must use an ampersand rather than a semicolon as the expression-terminator in order to inform the driver to print the expression as a e want to represent an aggregate of more than two atomic data elements? For example, what if we want to include BILBO's last name, BAGGINS? Well, we can let one of the pointers of a node point to another node, whose first pointer points ing at location 2, and the node beginning at location 4. Then, begining at location 4, there would be stored the addresses 7 and 2, as illustrated in the following diagram: 1 2 3 4 5 6 7 ---+-----+-----+-----+-concerned about: +----+----+ ! / ! \ ! +-/--+--\-+ / \ BILBO 31 This imagery suggests the word "pointers" for the addresses stored in nodes. If ication. For example, muMATH uses operator and functional notation. Suppose however that we want to specify such aggregates directly in input and output. How can we do it? If we have a nice graphics terminal, then then we cuse of parentheses and periods from how they are otherwise used in muSIMP input, so we must preceed the dotted pair by the single-quote prefix operator to indicate to the parser that we are using dotted-pair notation rather than the is an example of dotted-pair input and printing: % '(78 . TROMBONES) & % Try a few of your own, and note what happens when you forget the single- quote or use a semicolon rather than an ampersand: % RDS: FALSE $ % What about when w and the connectivity of the aggregates. Thus, for our purposes it is best to suppress the irrelevant distracting detail associated with the specific addresses. The following diagram is one helpful way to portray only what we are