home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / MATH / CC4.ZIP / UPDATE.CC < prev   
Text File  |  1991-04-09  |  48KB  |  1,047 lines

  1. This file records the changes I have made to the published program CC-The
  2. Calculus Calculator.  The new version is called CC4 and should be treated as
  3. experimental.  Everything about CC is copyrighted by my this year, 1991--the
  4. source code, the object code, the help file, even this file.  For more
  5. information about CC, call or write me:
  6.  
  7.                 David Meredith
  8.                 Department of Mathematics
  9.                 San Francisco State University
  10.                 1600 Holloway Ave.
  11.                 San Francisco, CA 94132
  12.                 415-338-2199
  13.  
  14.  
  15. 6/6/90
  16.   completed altering saving of last graph to list of graphics commands.
  17.   Also fixed vertical write so correct area blanked before writing, and
  18.     correct area checked for off/screen.
  19.   Now last graph takes much less space for EGA,VGA screens.  speed is ok.
  20.  
  21. 6/19/90
  22.   changed exit key to ^Q, deleted confirmation, but added "do you want to
  23.   save your work"
  24.   fixed it so <ESC> cancels printing of long variable list.
  25.  
  26.  
  27. 6/22/90
  28.   changed display so only first 10 items in list are displayed.  Also
  29.   eliminated hide and show as no longer necessary.  When variables printed
  30.   with F2 only first ten items of list are printed followed by ...more... .
  31.   To print entire variable, use F8 or PRINTVAR (cf. 9/19/90).
  32.  
  33. 7/7/90
  34.   added Xor to list of operators.  Works on booleans and integers.  Also
  35.   have broken CC up into a large number of overlays.
  36.  
  37. 8/7/90
  38.   have added lots of matrix operations.  See below.  Also now error in
  39.   execution of subroutine puts you in subroutine window with bad line
  40.   highlighted.
  41.  
  42.   Three-d graphing commands redone completely.  The basic commands are
  43.   simplified by the assumption of defaults in place of required
  44.   parameters.  NOTE:  WHEN OPTIONAL PARAMETERS ARE USED, THE SEMICOLON
  45.   SEPERATOR MUST ALSO BE USED.  Otherwise there is not enough
  46.   information in the input for CC to parse it.
  47.  
  48.   The step parameter is the NUMBER OF STEPS, not the size of a step.
  49.  
  50.   Here are the three-d graphing commands with options:
  51.  
  52.            Paramg3d(f(s,t),g(s,t),h(s,t),s=a to b [step c]; t = e to f [step g]
  53.                               [; x1 to x2,y1 to y2,z1 to z2])
  54.               if the any of the optional x,y,z limits are present, all
  55.               msut be.  Without them, CC uses the min and max of f,g,h
  56.               respectively as the x,y,z limits.
  57.  
  58.            Graph3d(f(x,y),x=a to b [step c];y=e to f [step g][;z1 to z2]);
  59.  
  60.            Curve3d(f(t),g(t),h(t),t=a to b [step c]
  61.                                                [; x1 to x2,y1 to y2,z1 to z2])
  62.  
  63.            MatrixG(a[,z1,z2])
  64.                  This is the graph of a matrix.  You can optionally
  65.                  specify the vertical limits of the graphing space,
  66.                  otherwise the max and min of the matrix elements are
  67.                  used.
  68.  
  69.   One improvement over CC3 is that the two parameters can have a
  70.   different number of subdivisions.  Also curves are drawn directly, not
  71.   faked.  The default step is 15.  the total number of points that can be used
  72.   --(step1+1)(step2+1)--is 1600.
  73.  
  74.   Here are sample minimal 3d graphing commands.
  75.  
  76.       graph3d(x^2 - y^2, x=-1 to 1, y = -1 to 1)
  77.       Paramg3d(sin(s)cos(t), sin(s)sin(t),cos(s),s=0 to pi, t=0 to 2pi)
  78.       Curve3d(cos(t),sin(t),sin(3t),t=0,2pi)
  79.       MatrixG(a)
  80.  
  81. 8/15/90
  82.  
  83. Matrix Commands
  84.  
  85.   Matrix commands include arithmetic + - * / \ .* ./.   .  +, -, * are as
  86.   expected.  A/B = A*B^(-1).  A\B = A^(-1) * B .  A^n  is defined for positive
  87.   and negative integers n if A is square.  To get the inverse of a matrix,
  88.   you can enter A^(-1), but it is easier to enter 1/A .
  89.  
  90.   The operators  A .* B  and A ./ B
  91.   operate between same size matrices and multiply or divide elementwise.
  92.  
  93.   Scalar functions like SIN and EXP work
  94.   inside matrices unless specified to work on entire matrix.  New functions
  95.   include Rank, RREF, LU (invertible matrices only), QR, Balance (temporary
  96.   --will be hidden), Det,.
  97.  
  98.   To define a matrix, either enter the data surrounded by braces and rows
  99.   seperated by semicolons:
  100.  
  101.                    {a,b,c;d,e,f}
  102.  
  103.   or use the command  MATRIX(a(i,j),i=....j= ...).  See below for more on
  104.   MATRIX.
  105.  
  106.   Special matrices can be defined with
  107.  
  108.          Diag(x)  where x is a list or an n x 1 or 1 x n matrix
  109.          Eye(n)   n x n identity
  110.          Zero(n,m)  Ones(n,m)    n x m matrix of zeros or ones.
  111.  
  112.   To define a submatrix of a matrix A, use A[i:j, k:l].  The i,j element
  113.   of a matrix A is A[i,j].
  114.  
  115.   Matrices can be defined with the command MATRIX as follows.  If the
  116.   step is not used, the semicolon can be any seperator and the default
  117.   step will be 1.
  118.  
  119.            Matrix(f(x,y),x=a to b [step c]; y = e to f [step g])
  120.  
  121.   Here the step parameter is the SIZE of the step.
  122.  
  123.  
  124. 9/1/90
  125. Editing
  126.   to mark text, move the cursor to the beginning of the text to be marked,
  127.   then push F3.  Move cursor to end, then push either <ENTER> or <DEL>.
  128.   <ENTER> moves text to save buffer; <DEL> does the same but deletes the
  129.   marked text as well.
  130.  
  131.   To mark an entire entry, push Shift-F3, then <ENTER> or <DEL>.
  132.  
  133.   To insert the saved text, move the cursor to the point of insertion and
  134.   push F4.
  135.  
  136.   When new text is saved, the original text is moved to a new buffer.
  137.   There are ten buffers, which are accessed by F4, Alt-1, Alt-2,...,
  138.   Alt-9.  When new text goes into the F4 buffer, each existing buffer
  139.   moves up one, and the Alt-9 buffer is discarded.
  140.  
  141.   (**********)  This material is changed.  See 1/31/91
  142.   ***Pushing F3 twice inserts a blank line.
  143.   (**********)  This material is changed.  See 1/31/91
  144.   Lines can be erased without saving with Control-Y.
  145.   Shift-F4 erases all text buffers--if you need to recover the memory.
  146.  
  147. 9/10/90
  148.   Improved the solver routine to take care of functions singular at their
  149.   roots.  Done by replacing f(x) = 0 with f(x)/f'(x) = 0.  When this routine
  150.   entered, the phrase Super Solver appears on the screen.
  151.  
  152. 9/19/90  (revised 11/15/90)
  153. Data files
  154.  
  155.   To print the last graph, issue the command:
  156.  
  157.                            PrintGraph
  158.  
  159.   To save the last graph for later reloading, use:
  160.  
  161.                            SaveGraph(filename)
  162.  
  163.   The filename must be a string (path allowed) surrounded by single quotes
  164.   or a variable containing such a string.  You could use either:
  165.  
  166.                             SaveGraph('pix.cc')
  167.  
  168.   or
  169.  
  170.                             pixfile = 'pix.cc'
  171.                             SaveGraph(pixfile)
  172.  
  173.  
  174.   To load a saved graph and display it, use:
  175.  
  176.                            LoadGraph(filename)
  177.  
  178.   This will erase the current Last Graph.
  179.  
  180.   To save a list (or single datum or matrix) from a variable to a file, use:
  181.  
  182.                            SaveVar(variable-name, filename)
  183.  
  184.   To load a variable from a file (like the file saved above):
  185.  
  186.                            LoadVar(variable-name, filename)
  187.  
  188.   Note that the entries can be numerical formulas as well as numbers.  CC will
  189.   read and evaluate any legal CC numerical formula (no variables or user-
  190.   defined functions) found in the file.
  191.  
  192.   To print the values of a variable, use:
  193.  
  194.                            PrintVar(variable-name)
  195.  
  196.  
  197.   When CC saves a variable, it creates an ASCII file beginning with a line
  198.   containing one of the words LIST VARIABLE MATRIX.  If the file starts with
  199.   VARIABLE, it should have one more line with a value or formula.  If the file
  200.   starts with LIST, it should consist of a series of lines with one number or
  201.   formula per line.  If the file begins with MATRIX, there will be several
  202.   values or formulas on each line seperated by commas, with the same number on
  203.   each line.
  204.  
  205.   You can create your own files for loading into CC by following these rules.
  206.  
  207.  
  208. 9/20/90
  209.   Added command WAIT(n), which causes computer to pause n seconds.  Useful
  210.   in between GRAPHICS and TEXT to pause a picture.  To pause until a key is
  211.   pressed, use PAUSE.
  212.  
  213. 9/28/90
  214.   Changed command BKCOLOR to CURRENTBKCOLOR.  This returns current
  215.   background color.  Added two commands BKCOLOR(color number) which sets
  216.   the background color, and AXISCOLOR(color number), which sets the
  217.   color of the axes.  Presently the color of the crosshairs cannot be
  218.   changed.  These commands should be used in conjunction with AXISON,
  219.   AXISOFF, KEEPLINE and VARYLINE
  220.  
  221. 10/2/90
  222.   Crosshair color now determined by AxisColor
  223.  
  224.   Fixed Div and Mod to work with negative integers.
  225.  
  226. 10/11/90
  227.   Due to self-imposed limitation on the length of function names, I have had to
  228.   change some commands.
  229.  
  230.       COLOR becomes SETCOLOR
  231.                 SETCOLOR(BLUE) makes the next line or graph blue
  232.  
  233.       CURRENTCOLOR becomes COLOR
  234.                 COLOR is a function that returns the color of the next graph
  235.  
  236.       BKCOLOR becomes SETBKCOLOR
  237.                 SETBKCOLOR(BLUE) makes the graphics background blue
  238.  
  239.       CURRENTBKCOLOR becomes BKCOLOR
  240.                 this is the one that was too long.  BKCOLOR is a function that
  241.                 returns the current graphics background color
  242.  
  243.  
  244. 10/12/90
  245.    added bignums--infinite precision integers and fractions.  To enter a
  246.    bignum, precede it with &, eg &123456789.  Bignums can be added,
  247.    subtracted, multiplied and divided with each other and with integers.
  248.                                                                         
  249. 10/25/90
  250.     A note on differentiation which is not covered in any of my manuals.
  251.     Certain operators are invisible to differentiation.  For example,
  252.     d/dx(Hex(f(x)) = hex(df/dx).  Same for the operators Integer, Bin,
  253.     Transpose, Fix, Float.
  254.  
  255. 10/30/90
  256.     Bignums now work pretty well.  You can enter a bignum with or without a
  257.     decimal:  &35.8 = 179/5.  Bignums can be added, subtracted, multiplied and
  258.     divided.  You can raise them to integral (but not bignum) powers or take
  259.     their factorials.  Try &3^100 and &100! .  Bignums combined with integers
  260.     result in bignums,but bignums combined with non-integral reals or with
  261.     complex numbers result in floating point values.
  262.  
  263.     When transcendental functions are applied to bignums, like SIN, the bignum
  264.     is first changed to its floating point equivalent, then the function is
  265.     computed on the floating point value.
  266.  
  267.     Any bignum can be changed to its floating point equivalent with the functin
  268.     FLOAT(x).  If x is not a bignum, it is unchanged.  Any real or complex
  269.     decimal can be changed to a bignum equivalent with the function FIX(x).  Be
  270.     careful with this function.  If you want 1/3, enter &1/^&3 (or &1/3 or
  271.     1/&3 or 1/fix(3) ), not fix(1/3).  Fix(1/3) is a horrible fraction whose
  272.     denominator is 2^40.  CC first changes 1/3 into an approximating floating
  273.     binary number, then converts this to a fraction.
  274.  
  275.     Matrices with ALL bignum or integer entries
  276.     can be added, multiplied, subtracted and divided with bignum results.  Also
  277.     the functions LU, DET, RANK, and RREF can be applied to bignum matrices
  278.     with bignum results.  Because squareroots are involved, QR and BALANCE
  279.     always return a floating point result.
  280.  
  281.     Lists can also have bignum entries.  SUM, PRODUCT, MAX, MIN and AVERAGE
  282.     return bignum result when applied to a list of bignums and integers, but
  283.     STANDEV and REGR return floating point results, again because square roots
  284.     are involved.
  285.  
  286.     Here's a special problem:  to define the Hilbert matrix, you could say:
  287.  
  288.                 H(n) = Matrix(&1/(i+j-1), i = 1 to n, j = 1 to n)
  289.  
  290.     but this won't work.  CC changes this into &1*(i+j-1)^(-1), and the second
  291.     factor gets evaluated to a real which, when multiplied by &1, yields a
  292.     floating point real.  You must say:
  293.  
  294.                 H(n) = Matrix(1/fix(i+j-1), i=1 to n, j = 1 to n)
  295.  
  296.     Bignums are slow to compute with.  On my medium speed AT, it took over one
  297.     minute to compute det(H(10)) .
  298.  
  299. A NOTE ON LISTS AND MATRICES
  300.  
  301.     (********* this paragraph is now superceded.  see 1/3/91.  The comments are
  302.     still correct.
  303.     List operations work on matrices, going across the rows one by one.  You can
  304.     say SUM(A) or MAX(A) or even STANDEV(A) when A is a matrix.  You can do
  305.     regression against two matrices (of the same size) or apply LISTG to a pair
  306.     of matrices.  **********)
  307.  
  308. 11/7/90
  309.     added a function SOLVEPOLY with eye to developing eigenvalue
  310.     routines.  The syntax is SOLVEPOLY(x) where x is a list of
  311.     coefficients for a polynomial with constant coefficient listed
  312.     first.  The function returns a list of roots.  It fails on
  313.     polynomials with coefficients of very different sizes or very small
  314.     coefficients (work in progress) but works on reasonable polynomials.
  315.     User beware.  Example:
  316.  
  317.                         x = (1,-3,3,1)
  318.                         SOLVEPOLY(x)   // returns (1,1,1)
  319.  
  320.  
  321. 11/9/90
  322.     Still finishing up SOLVEPOLY.  I think it will have to fail on the
  323.     following example, which seems very hard:
  324.  
  325.                 x^5+1000x^4+x^3+x^2+x+1 = 0
  326.  
  327.     I can solve this by hand--it has one large root near -1000 which can
  328.     be gotten at with a binary search, and four small complex roots.
  329.     These are best found by finding their inverses as roots of
  330.  
  331.                 x^5+x^4+x^3+x^2+1000x+1 = 0
  332.  
  333.     I've also removed one annoyance.  Now, if you enter x(y+1) meaning
  334.     x*(y+1), CC will recognize that x is a variable, not a function and
  335.     instead of returning an error message will perform the
  336.     multiplication.  If this causes any ambiguities or other problems,
  337.     please let me know.
  338.  
  339. 11/13/90
  340.     Added two functions.  LOG10(x) is log base 10.  It only works on positive
  341.     reals.  TRACE(x) is the trace function for matrices.
  342.  
  343.     I've been experimenting with eigenvalues and SOLVEPOLY.  I coded
  344.     Fadeveev's (sp?) algorithm for the characteristic polynomial in the
  345.     subroutine window, then used SOLVEPOLY on the result to get the eigenvalues
  346.     of a matrix.  I created the hilbert matrix with bignums (so the
  347.     characteristic polynomial consisted of bignums too, but of course the
  348.     solutions returned by SOLVEPOLY were real), found the eigenvalues, and
  349.     computed the rank of matrix-eigenvalue*I .  Up to size 5, the rank was one
  350.     less than the size.  For size 6 and larger, the eigenvalues were not so
  351.     accurate.  The computation for size 6, using bignums, required about 15
  352.     minutes.
  353.  
  354. 11/15/90
  355.     The commands LOADM SAVEM PRINTM have been eliminated.  CC is smart enough
  356.     to use LOADVAR SAVEVAR PRINTVAR and know when a matrix is involved.  See
  357.     revised comment following 9/19/90.
  358.  
  359.     Note that bignums cannot be saved and read back yet.  (11/23/90 now they
  360.     can)
  361.  
  362. 11/23/90
  363.     Matrix algorithms are coming along.  I've added CHARPOLY(x) which takes a
  364.     matrix as an argument and returns a list representing a polynomial
  365.     (constant term first).  If x is Hermitian, CHARPOLY is forced to return
  366.     real coefficients.
  367.  
  368.     I've also added EIGENVAL(x), which takes a matrix x as an argument and
  369.     returns a list of eigenvalues, sorted in order of decreasing magnitude.  If
  370.     x is Hermitian, the eigenvalues are forced to be real.
  371.  
  372.     We also have EIG(x), which takes a matrix x as an argument and returns a
  373.     list of two matrices.  If you enter
  374.  
  375.                 e = EIG(x)
  376.  
  377.     then e[1] is a diagonal matrix with the eigenvalues on the diagonal, and
  378.     e[2] has the corresponding eigenvectors in its columns.  If x has repeated
  379.     eigenvalues, then the eigenvectors for repeated eigenvalues are selected to
  380.     be orthogonal.  If the matrix is deficient (some eigenvalue has an
  381.     insufficient number of eigenvectors) then the matrix of eigenvectors has
  382.     columns of zeros replacing the missing eigenvectors.  So long as x is not
  383.     dificient, x = ev[2]*ev[1]/ev[2] .  That is, the command EIG diagonalizes
  384.     x.
  385.  
  386.     Bignums can be saved with SAVEVAR and loaded with LOADVAR.
  387.  
  388.     I added some display features to EIG, SOLVEPOLY, CHARPOLY, EIGENVAL, SOLVE,
  389.     IMPLICIT and IN so that the user would have something to watch while these
  390.     relatively slow commands work.
  391.  
  392.     Finally, for today, I changed the commands that set some of CC's
  393.     parameters.  Now we have commands to set the parameters:
  394.  
  395.                 SetSolveTol(x)
  396.                 SetInTol(x)
  397.                 SetInDepth(x)
  398.                 SetMatrixTol(x)
  399.  
  400.     Setting x = 0 in these commands (or using any other illegal value) causes
  401.     the corresponding parameter to be reset to its default value.  No longer
  402.     need you look up the default values in the manual.
  403.  
  404.     The commands:
  405.  
  406.                  SolveTol
  407.                  InTol
  408.                  InDepth
  409.                  MatrixTol
  410.  
  411.     all return the current values of the corresponding parameter.  Previously,
  412.     these commands set the parameters.
  413.  
  414. 11/29/90
  415.     Just finished singular values.  If A is an n x m matrix of rank r, the
  416.     command S = SVD(A) returns a list of three matrices:
  417.                         S[1] is n x r with orthonormal rows
  418.                         S[2] is r x r diagonal with the singular values on
  419.                                the diagonal.  The singular values are always
  420.                                positive real numbers.
  421.                         S[3]  is m x r with orthogonal rows
  422.  
  423.        Moreover, A = S[1]*S[2]*S[3]"
  424.  
  425.     The command P = PINV(A) returns the pseudo-inverse of A, which is
  426.                         P = S[3]/S[2]*S[1]"
  427.  
  428.     Remember, B" is the conjugate transpose (Hermitian) of B.
  429.  
  430.     The ratio of the largest and smallest singular values  is called the
  431.     condition number of A, and can be computed directly with the command
  432.     COND(A).
  433.  
  434.  
  435.     As suggested by Professor Alex Calders of Duffel, Belgium, I've added two
  436.     new input commands.  Previously, when you executed INPUT or INPUTS on a
  437.     graphics screen, you got a large box which obscured much of the screen.
  438.     The new commands are INPUT@(x,y,n,a) and INPUTS@(x,y,n,a), where (x,y) is
  439.     the coordinate of the lower-left corner of the region where you want the
  440.     user to type the input, n is the number of characters room is made for, and
  441.     a is the variable which will receive the input.  INPUT@ gets numerical
  442.     input; INPUTS@ gets string input.  INPUT@ only works in subroutines when
  443.     GRAPHICS is active.
  444.  
  445.     Note that this new input command does not include provision for a message
  446.     to the user.  This command should be used in conjunction with WRITE@.  Use
  447.     WRITE@ to put instructions on the screen, then create the input box at a
  448.     convenient point on the screen where the user can type a response.
  449.  
  450.     If you try to place the input box too high on the screen,it will be
  451.     automatically lowered, and if you try to place it to far to the right for
  452.     the number of characters you wish to accomodate, it will be automatically
  453.     shifted to the left.
  454.  
  455.     Note that the graphics cursor is alive while waiting for a response to
  456.     INPUT@--the graphics cursor is not active while waiting for a response to
  457.     INPUT or while a message created by WRITE is on the screen.
  458.  
  459.     Here's a simple example:
  460.  
  461.                  procedure test
  462.                    window(0,3,-1,1)
  463.                    graphics
  464.                    qu(cos(x),x)
  465.                    sk(x,x)
  466.                    solve(cos(b)=b,b=1)
  467.                    Write@(.1,-.6,'Enter x-coordinate where curves intersect')
  468.                    repeat
  469.                        input@(.3,-.8,5,x)
  470.                        ok = x > b-.05 and x < b+.05
  471.                        if not ok
  472.                            beep
  473.                          end
  474.                      until ok
  475.                    Write@(.1,-.7,x)
  476.                    Write@(.1,-.8,'You got it!!')
  477.                    text
  478.                    end
  479.  
  480.  
  481.     The procedure graphs two curves on the screen and asks the user to input
  482.     the x-coordinate of their intersection.  The request repeats until the user
  483.     inputs an answer within 0.05 of the correct one.
  484.  
  485. 12/11/90
  486.  
  487.     IMPORTANT NOTE ON CONFIGURATION FILES
  488.  
  489.     Altered the configuration (Control-F9) routine to allow you to add page
  490.     length (in lines), as requested by European correspondent.  Also recently
  491.     fixed some bugs in config routines, so you MUST remake your config files if
  492.     you are using one.  Do this by erasing the configuration file CC.CFG while
  493.     outside of CC, then creating a new one from within CC by pressing
  494.     Control-F9.
  495.  
  496.     Note:  you set the total number of lines on your page; CC will allow for a
  497.     top and bottom margin.
  498.  
  499.     Also added a form-feed or skip-to-top-of-page command to the print (F2)
  500.     menu.  This will be useful for laser-jet users, but beware:  CC not only
  501.     skips to top of page but starts the next page, positioning the print head
  502.     to write the first character on the next page.
  503.  
  504.     Changed the effect of F8.  Now you can no longer load a graph through this
  505.     key, only a file of commands, so you will not be prompted to choose G for
  506.     graph or C for command file.  After pushing F8, you will be asked directly
  507.     for the name of the command file to load.  Graphs must be loaded with the
  508.     command LOADGRAPH(filename).
  509.  
  510. 12/12/90
  511.     Changed the directory command from shift-F1 to shift-F8, since F8 is my
  512.     file input key.  After viewing the directory, you have the opportunity to
  513.     make that directory your primary directory.  Also added Control-F8, which
  514.     is a simple change directory command.
  515.  
  516.     Added commands ROWVECTOR(X) and COLVECTOR(X), which take a list X and turn
  517.     it into a 1-row or 1-column matrix.  If X is not a list, the result is a
  518.     1x1 matrix whose sole entry is X.
  519.  
  520.     Fixed 3d graphs so that (a) axis labels print horizontally, not paralell to
  521.     the axes, and (b) if the axis points in the negative direction, a negative
  522.     sign is added to the axis name.
  523.  
  524. 12/20/90
  525.     Merry Christmas.  The matrix editor is completed.  Now, when you compute a
  526.     matrix, it will be shown in spreadsheet format.  You can cursor around it
  527.     with the arrow keys, the control-left and right keys, pgup and pgdn,
  528.     control-home and control-end.  The highlighted element is displayed at the
  529.     bottom of the screen, so even if it isn't completely displayed in the
  530.     matrix you can see it by highlighting it.
  531.  
  532.     If you produce a formula with more than one matrix, each will be shown in
  533.     turn.  For example, if you compute A/B, with B a matrix with symbolic
  534.     entries, both A and B will be displayed, and the result
  535.     Matrix(.,.)/Matrix(.,.) shown in the Output Window.
  536.  
  537.     You can also edit matrices with the spreadsheet.  To create or change a
  538.     matrix A, execute the command:
  539.  
  540.                                 MEDIT(A)
  541.  
  542.     If A is not a matrix, its contents will be lost.  You can move around A
  543.     with the arrow keys, etc, as above, adding or changing elements in the
  544.     matrix.
  545.  
  546.     This command can also be used to view a matrix.
  547.  
  548.     If a matrix is displayed as a result, without possibility of editing, the
  549.     highlighted element is shown in boldface or a different color.  In this
  550.     case you cannot cursor beyond the boundaries of the matrix.  If the matrix
  551.     is displayed as a result of the MEDIT command, the highlighted element is
  552.     reversed and can be changed.  In this case you can cursor beyond the
  553.     current boundaries of the matrix and make the matrix larger by adding
  554.     elements.  You do not need to fill in all the elements--blank elements will
  555.     be filled with zeros.
  556.  
  557.     Now there are four ways to create a matrix:
  558.         Surround its elements with braces:  {1,2,3;4,5,6}
  559.         Use a formula:  Matrix(1/(i+j-1,i=1,5,j=1,5)
  560.         Read it from a disk file:  LoadVar(A,'filename')
  561.         Create it with MEDIT:   MEdit(A)
  562.  
  563. 1/2/91
  564.     Happy New Year.  Just added some string operators.  Strings are entered by
  565.     surrounding them with apostrophes:  x = 'abcde'  .   Now they are displayed
  566.     with apostrophes to distinguish them in the output from undefined variable
  567.     names.  Strings can be used in WRITE and INPUT statements, they can be
  568.     compared for position in alphabetical order, and now they can be
  569.     manipulated.
  570.  
  571.     To extract the third character from a string, use x[3].  The result is a
  572.     string of length 1, unless x has fewer than 3 characters.  In that case the
  573.     result is the empty string '', or the string of length 0.  To extract the
  574.     substring consisting of characters 4..7, use x[4:7] or x[4,7].  If x has
  575.     fewer than 7 characters, then all characters of x, beginning with the 4th,
  576.     will be returned. If x has fewer than 4 characters, the empty string is
  577.     returned.
  578.  
  579.     Strings can be concatenated with | just like lists.  'abc' | 'de' returns
  580.     'abcde' .
  581.  
  582.     To determine if one string x is a substring of another string y, use the
  583.     function POS(x,y).  (POS means position.)  POS returns 0 if x is not a
  584.     substring of y, otherwise it returns the position of y corresponding to the
  585.     starting point of the substring x.  POS('abc', '12abcde') returns 3.
  586.  
  587.     The length of a string can be determined with the function LENGTH(x).
  588.  
  589.     The function UPCASE(x) returns a string y which is the same as x except
  590.     that all lower case letters a..z are replaced with upper case letters A..Z.
  591.  
  592.     If x is a string, then ASC(x) returns a list of integers that are the
  593.     ASCII codes of the characters of x.  If x is a string of length 1, then
  594.     ASC(x) is an integer, not a list of length 1.
  595.  
  596.     Conversely, if x is an integer or a list of integers in the range 32..255,
  597.     then CHR(x) is a string whose character codes are in x.  If x has entries
  598.     outside the required range, they are ignored.  NOTE:  strings with
  599.     characters in the range 129..255 will not print on the graphics screen.
  600.     Turbo Pascal does not support them in graphics mode.  ***now they do
  601.     see 1/27/91***
  602.  
  603. 1/3/91
  604.     Changed the statistical functions for matrices.  Now SUM MAX MIN AVERAGE
  605.     STANDEV, applied to a matrix, return a row vector containing the
  606.     appropriate value for each column of the matrix.  If matrix has only one
  607.     column, a scalar rather than a 1 x 1 matrix is returned.
  608.  
  609.     REGR(m), for a matrix m, works as follows.  Let p be the same as m, but
  610.     replace the last column by 1's, and let b be the last column of m.  Then
  611.     REGR(m) = pinv(p)*b.  Thus REGR is a column vector whose length = the # of
  612.     columns of m.  If m is r x 2, then if we think of the rows of m as points,
  613.     the elems of regr(m) = (c,d)" and y = cx+d is the regression line through
  614.     the points.  More generally, REGR(m) = (r1,...,rn) where the hyperplane
  615.     most nearly approximating the rows of m is
  616.  
  617.           xn = r1 x1 + r2 x2 + ... + rn-1 x-1 + rn
  618.  
  619.  
  620.     Added a sorting routine for matrices.  The function SORT(m,i) sorts the
  621.     rows of the matrix m on the data in column i and returns a sorted matrix.
  622.     m is unchanged, unless you use the command  m = SORT(m,i) .
  623.  
  624.     To sort on two columns, first sort on the secondary key, then on the
  625.     primary key.
  626.  
  627. 1/4/91
  628.     The command SOLVEPOLY (11/7/90 and following) now has a complement:  if p
  629.     is a list representing a polynomial, and x is a value, then
  630.  
  631.                              EVALPOLY(p,x)
  632.  
  633.     returns the the value p(x).  EVALPOLY uses Horner's method, so it will be
  634.     faster on large polynomials than defining a function equal to p and
  635.     evaluating it:
  636.  
  637.                    f(t) = SUM(p[i]*x^(i-1), i = 1 to length(p))
  638.                    f(x)
  639.  
  640.      The difference can be seen if you take p = LIST(1,i=1,100) and x = 2.
  641.  
  642. 1/7/91
  643.      Finally, there is a ZOOM feature for graphics.  To magnify part of a graph
  644.      (only the part drawn with GRAPH, DOTGRAPH, QUICKG, SKETCH, PARAMG POLARG,
  645.      DIFFG and INTEG, not LINE, FILL, WRITE, etc.) move the crosshairs to one
  646.      corner of the region to be magnified.  Press control-Z (the crosshairs
  647.      change to Z) and use the cursor keys to move the Z to the opposite corner
  648.      of the region to be magnified.  Press <ENTER> and your graph will be
  649.      magnified.
  650.  
  651.      If you want to cancel the zoom command, press <ESC>.  To restart the
  652.      window at the current location of the Z, press Control-Z again.
  653.  
  654.      After zooming your window, the window parameters WINDOWLEFT etc. will be
  655.      changed to reflect the new window.
  656.  
  657.      If you zoom on a curve drawn with PARAMG or POLARG, much of the curve may
  658.      be outside the zoomed window, since you won't have changed the limits of
  659.      the parameters.
  660.  
  661.      Now you can use  WINDOW(0,0,0,0)  to restore the window limits to their
  662.      original values, which were  WINDOW(-1.4,1.4,-1,1) .  *** this is changed
  663.      see 2/10/91 ***
  664.  
  665. 1/9/91
  666.     To complement CHR and ASC, I've added VAL and STR.  If s is a
  667.     string, then VAL(s) returns the numerical value of s.  s may be any
  668.     legal CC formula.  Conversely, if x is a value or CC formula, then
  669.     STR(x) returns a string representing the value of x.  Examples:
  670.  
  671.                     VAL('12') = 12
  672.                     VAL('Cos(PI)') = -1
  673.                     STR(3) = '3'
  674.                     STR(Cos(PI)) = '-1'
  675.  
  676.     Complex values and bignums can be used with VAL and STR.
  677.  
  678. 1/15/91
  679.     Added a new command:  FIELD(f(x,y),g(x,y),x,y)  draws vector field (f,g) in
  680.     current window.  Example:  FIELD(-y,x,x,y)
  681.  
  682.     The resulting vectors are not strictly proportional to their true lengths.
  683.     Although longer vectors appear longer, at least if they are parallel, the
  684.     proportion between longest and shortest vector has been reduced so that
  685.     individual vectors aren't reduced to single points.  However, if one vector
  686.     is very long, the others may virtually disappear.  This will happen, in
  687.     particular, if there is a singularity at the origin of the vector field.
  688.     Then, if you draw one vector very close to the origin, it will dwarf the
  689.     others.  To avoid this, see the next comment.
  690.  
  691.     Normally 15 x 15 vectors are drawn.  You can change this value by adding a
  692.     different number of vectors in each direction after the direction
  693.     parameter:  FIELD(-y,x,x,10,y,10)  .  If your window is symmetric about the
  694.     origin, you can avoid placing a vector near the origin by choosing an even
  695.     number of vectors in each direction.
  696.  
  697.     Also, to complement Zoom, after zooming you can press Control-U to
  698.     UnZoom--go back to prior window.  *** See 2/8/91 for information on
  699.     expanded UnZoom. ***
  700.  
  701. 1/27/90
  702.     We are at war.
  703.  
  704.     I've started compiling with Turbo Pascal 6.0.  This gives me new stroked
  705.     fonts with all the characters with codes 32-255.  I've changed from the
  706.     triplex font to the small font for all writing, including the text which
  707.     was previously written in the default (bitmapped) font.  Internally I'm
  708.     using sizes 4-10, but externally, you should use size codes 1..7 for
  709.     Write@, VWrite@, Write@c and VWrite@c.  The default size is 2, matching the
  710.     text used by CC to label the ends of the axes, the coordinates of the
  711.     crosshairs, and the message at the lower left of the graphics screen.
  712.  
  713.     I've also added two commands to complement vector fields:
  714.  
  715.                TRAJ(f(x,y),g(x,y), x = a, y = b)
  716.  
  717.     draws a trajectory through the vector field (f,g) beginning at (a,b).
  718.     Normally 50 segments are used to draw the trajectory.  You can change this
  719.     number by adding a value after b.
  720.  
  721.                LEVELC(f(x,y)=g(x,y), x = a, y = b)
  722.  
  723.     draws the graph of f(x,y) = g(x,y) both ways from the solution point
  724.     closest to (a,b) .  Normally 50 segments are used to draw each half of the
  725.     solution curve; you can change this value by adding a different number
  726.     after b.
  727.  
  728.     Examples:
  729.                TRAJ(-y,x,x=.5, y=.5, 100)
  730.                LEVELC(x^2+y^2 = 1, x=.7, y=.7, 30)
  731.  
  732.     *** see 2/9/91 for a step size parameter ***
  733.  
  734. 1/29/91
  735.     I seem to have neglected to list a couple of matrix commands.
  736.  
  737.         TRANS(a)      transpose of a
  738.         CONJ(a)       conjugate of a
  739.         a"            conjugate transpose or Hermitian of a
  740.         rows(a)       number of rows of a
  741.         cols(a)       number of columns of a
  742.         rank(a)       rank of a
  743.                         it may be necessary to jigger matrixtol a bit to get
  744.                         this value to come out right.
  745.         det(a)        determinant of a
  746.  
  747. 1/31/90
  748.     A minor fix:  previously the INPUT(a,b) command required a specific string
  749.     in apostrophes at a and a variable name at b.  The variable name is still
  750.     required, but the first entry can be any expression at all:
  751.  
  752.               'input third value'          a string
  753.               x                            a variable
  754.                                              (where previously we executed
  755.                                              x = 'input third value' )
  756.               Cos(4.5)                     an expression--the value is
  757.                                              displayed
  758.               Cos(4.5t)                    an expression with undefined terms
  759.  
  760.     It is particularly useful to be able to store the input prompt in a
  761.     variable and use the variable as the prompt in the input statement.
  762.  
  763.  
  764.     Changed the InsertLine key from F3 F3 to Control-Enter.  This is easier and
  765.     more natural, and you don't have to count the number of times you push F3
  766.     to get an even number.  This required changing the mnemonic info at the top
  767.     of the screen.
  768.  
  769.  
  770.     Added protected lines.  If you save a file with Alt-F7, then reload it with
  771.     F8, you won't be able to alter any of the non-blank lines.  You can,
  772.     however, add lines where there are blank lines and open up new lines with
  773.     Control-Enter.  If you save the file with F7 after adding more to it, the
  774.     added material will not be protected, but the original protected lines stay
  775.     protected.  To protect the entire file, save with Alt-F7.
  776.  
  777.     To unprotect a file for editing protected lines, load it with Alt-F8.
  778.  
  779.     Protected lines are useful for writing lessons, etc.  You can prepare a
  780.     lesson that the student can't write over, leaving blank space for the
  781.     student to write in.
  782.  
  783. 2/7/91
  784.     Added five operations to the editor:
  785.  
  786.           Control-RightArrow and Control-LeftArrow now move by words, stopping
  787.           at spaces and the characters ( = + - * / \ [ { ^ < >
  788.  
  789.           Control-Backspace erases an entire word to the left, stopping at the
  790.           same set of characters.
  791.  
  792.           Control-PgUp and Control-PgDn move the cursor up and down one entry
  793.           at a time.
  794.  
  795.      I tried to add Control-Delete to erase an entire word to the right, but
  796.      Turbo won't recognize this key when compiled under TPC, although it does
  797.      recognize it in the IDE.  I've written to Borland.
  798.  
  799.      Sometime earlier, I added but forgot to note:
  800.  
  801.            Control-B   -- delete left of cursor to beginning of line
  802.            Control-T   -- delete right of cursor to end of line
  803.            Controy-Y   -- delete entire line
  804.  
  805. 2/8/91
  806.     Fixed the data file loading routines LOADVAR.  Added the capability of
  807.     reading text files into lists of strings.  To create a textfile for input,
  808.     begin it with the line TEXT, then put any lines you want.  Here's a sample
  809.     file:
  810.  
  811.         TEXT
  812.         Put any information that you
  813.         want into these lines.
  814.  
  815.         Blank lines can be included.
  816.  
  817.     Suppose that these lines were stored in a file called TEXTFILE.CC.  The
  818.     following subroutine would read the file and display it on the graphics
  819.     screen:
  820.  
  821.         Procedure Display
  822.           // Display contents of TEXTFILE.CC on graphics screen
  823.           LoadVar(a,'TEXTFILE.CC');
  824.           Axisoff
  825.           Window(0,1,0,1)
  826.           graphics
  827.           for i = 1 to 4 do
  828.               Write@(0.1,1-i/5,a[i],3)
  829.             end
  830.           text
  831.         end  // Display
  832.  
  833.     UnZoom has been improved.  If your window was created by zooming, UnZoom
  834.     (Control-U) returns you to the previous window.  You can zoom, then unzoom
  835.     through a number of windows.  If there is no previous window, then UnZoom
  836.     quadruples the size of the current window by expanding each of the axes by
  837.     2 from the center.
  838.  
  839. 2/9/91
  840.     TRAJ and LEVELC have been modified.  You can use a second optional
  841.     parameter after the optional step number (but the second parameter cannot
  842.     be used without the first).  The second parameter, a real between -5 and 5,
  843.     specifies a "step size" for the trajectory and level curve algorithms.  The
  844.     default is step size 0, and the step sizes are related exponentially to the
  845.     step size factor.  If  s0 is the default step size, and if ssf is the step
  846.     size factor, then the resulting stepsize factor is:
  847.  
  848.                                      ssf/5
  849.                                    10     *s0
  850.  
  851.      Thus the minimum step size is 1/10 of the default, and the maximum is 10
  852.      times the default.  Here are two examples using the second factor:
  853.  
  854.                         TRAJ(-y,x,x,y,300,-2)
  855.                         LEVELC(x^3+x=y^2, x=0,y=0, 100, -1)
  856.  
  857. 2/10/91
  858.      To restore the original window [-1.4,1.4] x [-1,1] , use the command
  859.      WINDOW without parameters.
  860.  
  861.      The algorithms for TRAJ and LEVELC have been improved.  TRAJ now uses a
  862.      predictor-corrector method to compute each step.  It traces a circle
  863.      through the field (-y,x) pretty accurately.  Try TRAJ(-y,x,x=1,y=0,222)
  864.      in the standard window.
  865.  
  866.      LEVELC(f=g,x=a,y=b) now computes a new approximation (x,y) by following a
  867.      vector perpendicular to grad(f-g), then (this is the improvement) follows
  868.      the gradient vector back to the level curve.  I stopped using the built-in
  869.      solver, and instead wrote a special Newton's method solver for this last
  870.      step.  Given a point (a,b) and a function h(x,y), to move along the
  871.      gradient field grad(h) from (a,b) to a solution of h(x,y) = 0, we create a
  872.      function of one variable  k(t) = h(a+r*t,b+s*t) where
  873.      (r,s) = grad(h)(a,b).  Then using Newton's method to solve k(t)=0, we
  874.      begin with t = 0 and correct to t = -h(a,b)/(r²+s²).  We just go one step,
  875.      construct new values of a = a+r*t, b=b+s*t, new values of r and s, and do
  876.      it again until the pixel representing (a,b) doesn't change from one step
  877.      to the next.
  878.  
  879. 2/16/91
  880.      New command has been added to display a value on demand.  Previously, when
  881.      you had a list or matrix stored in a variable, the only way to view the
  882.      object was to execute the variable name, which duplicated the value in the
  883.      variable in the variable ANS.  This cost extra memory if the value was a
  884.      long list or large matrix and destroyed the current value of ANS.  Now you
  885.      can enter the command:
  886.                                 DISPLAY(X)
  887.      where X is a variable name or any other legal CC expression, and the value
  888.      of X will be displayed without changing the value of any of CC's
  889.      variables.
  890.  
  891.      The Config (Control-F9) routine has been slightly changed so that pressing
  892.      <ENTER> at each step leaves the value of the choice unchanged.  In fact,
  893.      all the Y/N questions have been altered.  The query now shows Y/n or y/N
  894.      or y/n.  If one of the choices is capitalized, then that it the default
  895.      choice and can by selected by pressing <ENTER>.  The only place where
  896.      there is not a default choice is when the program ends (^Q).  The user
  897.      must specify whether or not to save the work.  Neither alternative is an
  898.      attractive default--no save default is too dangerous, and save default may
  899.      confuse beginning users.
  900.  
  901.      It's been a busy day.  Two cars washed and the oil changed, waste paper
  902.      recycled, and still time for more innovations.  Jim Smith pointed out that
  903.      the new graphics font, Borland's SmallFont, doesn't transfer very well to
  904.      WordPerfect.  Its strokes are only one pixel wide, and they can get lost
  905.      when the graph is Grabbed and reduced.  To overcome this difficulty, I've
  906.      added two commands:
  907.  
  908.                            THICKTEXT
  909.                            THINTEXT
  910.  
  911.      After executing THICKTEXT, all graphics text of size larger than the
  912.      default size (3 or more) will be printed with lines two-pixels wide.
  913.      Actually the text is printed three times, once, then move up one pixel and
  914.      print again, then move right one pixel and print again.  This only applies
  915.      to large text, since it doesn't look very good on smaller text.  To return
  916.      to ordinary graphics characters, enter the command THINTEXT.
  917.  
  918. 2/19/91
  919.      Sometime back, I forgot to note when, I completely revised the help
  920.      facilty.  There is a new help file twice as big as the one in CC3 and new
  921.      routines to run it.
  922.  
  923.      I just made minor changes in the matrix editor.  Now, if you cursor to a
  924.      position in the matrix where an element is defined and start typing a new
  925.      element, the old element disappears.  Previously, whatever you typed was
  926.      added to the end of the old element.  If you begin by pressing <END> or
  927.      <RIGHTARROW>, you will preserve the old element and edit it.  For some
  928.      time, you have been able to move either way on a row of a matrix you are
  929.      editing with the <TAB> key.
  930.  
  931.      Also, if a matrix is displayed after creating or DISPLAYing it, you can
  932.      return to the calculator screen by pressing <ENTER> or <ESC>.  However, if
  933.      you have called up the matrix with MEDIT, then you must terminate the
  934.      session with <ESC>.  That is because it is too easy, after entering a
  935.      formula into the matrix editor, to terminate the formula with <ENTER>.
  936.  
  937. 2/24/91
  938.      The last three days were spent in an exhaustive rewrite of the algebraic
  939.      simplification algorithms.  They are now much cleaner and easier to
  940.      understand, and the bugs which gave rise to the rewrite have been
  941.      eliminated.  One quirk has been introduced.  Since CC does not factor, a
  942.      choice must be made for the order of application of the following two
  943.      rules:  (a+b)c = ac + bc  and  a^n a^m = a^(n+m).  (CC has an algorithm to
  944.      determine when two expressions are equal, so it can combine their
  945.      exponents.)  The situation arises here.  The second rule is now applied
  946.      first, so that  (x+y)*(x+y)^(-1) gets converted to 1 instead of
  947.      x*(x+y)^(-1) + y(x+y)^(-1).  However, this order of application can have
  948.      strange (but correct) results.  If x is undefined and you try
  949.      PRODUCT(1+N*X,N=1,5), you will find that CC catches the factor (1+3X) and
  950.      retains it, while the other factors are expanded by the rule of
  951.      transitivity.
  952.  
  953.      Changed the default number of steps in FIELD to 14 from 15, so that there
  954.      is no vector in the center of the field, which will often be (0,0) and may
  955.      be a singularity of the field.  Including the singularity doesn't cause a
  956.      crash, but may cause all other vectors to be reduced to points.
  957.  
  958. 2/29/91
  959.      Minor changes today.  Decided that SAVEVAR should not save bignums, since
  960.      once saved they could not be read back in if they were very big.  They can
  961.      be saved by F2-7, save all input, subroutines and variables to disk.
  962.  
  963.      Changed REGR(m), where m is a matrix.  Now REGR(m) returns a column vector
  964.      which is a least squares solution to the equation Ta = b, where  T  is the
  965.      matrix formed by deleting the last column of m and adding a new first
  966.      column of 1's, and b is the last column of m.  Thus, if each row of m is
  967.      the data  x1,x2,...,xn,y, the column vector a gives the best linear fit:
  968.      a0 + a1x1+...+anxn = y.  Previously the constant term was at the end of
  969.      the linear approximation.
  970.  
  971. 3/14/91
  972.      I've altered the input routines considerably, so that lines up to 2048
  973.      characters can be entered.  You can enter (with spaces, not
  974.      carriage-returns):
  975.  
  976.                    x = {1,2,3,4;
  977.                         5,6,7,8;
  978.                         9,10,11,12}
  979.  
  980.      The tab key moves the cursor to the next line and places it under the
  981.      first non-blank character, which is a help in creating entries like the
  982.      one above.
  983.  
  984.      You can also enter much longer bignums now.  You can also save (with
  985.      SAVEVAR) and reload (with LOADVAR) large bignums and large matrices.  If
  986.      you look at the file they are saved in, you will see that the file
  987.      contains lines up to 240 characters in length, and if that isn't enough
  988.      for one bignum or row of a matrix, a continuation character (#220) is
  989.      placed at the end of the line and the entry continues on the next line.
  990.  
  991.      Now I have to start rewriting the manual.
  992.  
  993. 3/17/91
  994.      But not quite yet.  Wordwrap has been added.  Now you can enter very long
  995.      comments by starting them with // and just typing.  Wordwrap also works in
  996.      formulas, so your long formulas won't break in the middle of variable
  997.      names or leave an opening parenthesis on the previous line.
  998.  
  999.      Note:  if you have an entry like this:
  1000.  
  1001.              lkjlk ljljlk ljjlkj ljlkj ljlkj klX
  1002.              dsfasf dsfsadf afdsa fsafsda
  1003.  
  1004.      and you delete the X or push backspace with the cursor at the beginning of
  1005.      the second line, the first word on the second line will not come up to the
  1006.      first line until there is room for it.
  1007.  
  1008.      I've modified ^B and ^T so they just erase the beginning or end of the
  1009.      line you are on.  However, ^Y still erases an entire multi-line entry.
  1010.      You can recover the last ^Y with alt-Y--a primitive UnDo command.  I'm
  1011.      considering changing ^Y to just affect one screen line, not an entire
  1012.      entry.
  1013.  
  1014. 3/19/91
  1015.      Wordwrap is user-controllable.  The command WORDWRAPON turns on wordwrap
  1016.      (the default), and WORDWRAPOFF turns it off.  The initial state of
  1017.      wordwrap can be altered in the configuration file.
  1018.  
  1019.      The matrix editor has some unrecorded commands and two new ones.  The
  1020.      unrecorded ones are ^End and ^Home, which move you to the beginning or end
  1021.      of matrix.  ^RightArrow and ^LeftArrow move one screen at at a time, as
  1022.      does PgUp and PgDn.  Home and End move to beginning and end of individual
  1023.      element.
  1024.  
  1025.      The new ones are ^R and ^C.  ^R adds a row of zeros above the current row,
  1026.      and ^C adds a column of zeros to the left of the current column.
  1027.  
  1028. 3/20/91
  1029.      A slight modification to the routines that add rows and columns.
  1030.      Now, after pressing Control-R or Control-C, CC will ask if you want
  1031.      to add or delete a row.  Press I or D to indicate, or <ESC> to
  1032.      forget the whole thing.
  1033.  
  1034. 3/27/91
  1035.      SaveVar, FSaveVar, PrintVar have been changed to Save, FSave, Print.
  1036.      Instead of saving a variable name, you can save any expression, including
  1037.      a variable.  This is useful, for now in subroutines you can add a line
  1038.                             Print('state 1 reached')
  1039.      and it will print.
  1040.  
  1041. 4/1/91
  1042.      Fixed a few small bugs.  Now the minimal number of lines per page is 50.
  1043.  
  1044.  4/9/91
  1045.      changed LoadVar to Load, to correspond to change to SaveVar.  See 3/27/91.
  1046.      Also fixed Save, so it would work.
  1047.