This file records the changes I have made to the published program CC-The Calculus Calculator. The new version is called CC4 and should be treated as experimental. Everything about CC is copyrighted by my this year, 1991--the source code, the object code, the help file, even this file. For more information about CC, call or write me: David Meredith Department of Mathematics San Francisco State University 1600 Holloway Ave. San Francisco, CA 94132 415-338-2199 6/6/90 completed altering saving of last graph to list of graphics commands. Also fixed vertical write so correct area blanked before writing, and correct area checked for off/screen. Now last graph takes much less space for EGA,VGA screens. speed is ok. 6/19/90 changed exit key to ^Q, deleted confirmation, but added "do you want to save your work" fixed it so cancels printing of long variable list. 6/22/90 changed display so only first 10 items in list are displayed. Also eliminated hide and show as no longer necessary. When variables printed with F2 only first ten items of list are printed followed by ...more... . To print entire variable, use F8 or PRINTVAR (cf. 9/19/90). 7/7/90 added Xor to list of operators. Works on booleans and integers. Also have broken CC up into a large number of overlays. 8/7/90 have added lots of matrix operations. See below. Also now error in execution of subroutine puts you in subroutine window with bad line highlighted. Three-d graphing commands redone completely. The basic commands are simplified by the assumption of defaults in place of required parameters. NOTE: WHEN OPTIONAL PARAMETERS ARE USED, THE SEMICOLON SEPERATOR MUST ALSO BE USED. Otherwise there is not enough information in the input for CC to parse it. The step parameter is the NUMBER OF STEPS, not the size of a step. Here are the three-d graphing commands with options: Paramg3d(f(s,t),g(s,t),h(s,t),s=a to b [step c]; t = e to f [step g] [; x1 to x2,y1 to y2,z1 to z2]) if the any of the optional x,y,z limits are present, all msut be. Without them, CC uses the min and max of f,g,h respectively as the x,y,z limits. Graph3d(f(x,y),x=a to b [step c];y=e to f [step g][;z1 to z2]); Curve3d(f(t),g(t),h(t),t=a to b [step c] [; x1 to x2,y1 to y2,z1 to z2]) MatrixG(a[,z1,z2]) This is the graph of a matrix. You can optionally specify the vertical limits of the graphing space, otherwise the max and min of the matrix elements are used. One improvement over CC3 is that the two parameters can have a different number of subdivisions. Also curves are drawn directly, not faked. The default step is 15. the total number of points that can be used --(step1+1)(step2+1)--is 1600. Here are sample minimal 3d graphing commands. graph3d(x^2 - y^2, x=-1 to 1, y = -1 to 1) Paramg3d(sin(s)cos(t), sin(s)sin(t),cos(s),s=0 to pi, t=0 to 2pi) Curve3d(cos(t),sin(t),sin(3t),t=0,2pi) MatrixG(a) 8/15/90 Matrix Commands Matrix commands include arithmetic + - * / \ .* ./. . +, -, * are as expected. A/B = A*B^(-1). A\B = A^(-1) * B . A^n is defined for positive and negative integers n if A is square. To get the inverse of a matrix, you can enter A^(-1), but it is easier to enter 1/A . The operators A .* B and A ./ B operate between same size matrices and multiply or divide elementwise. Scalar functions like SIN and EXP work inside matrices unless specified to work on entire matrix. New functions include Rank, RREF, LU (invertible matrices only), QR, Balance (temporary --will be hidden), Det,. To define a matrix, either enter the data surrounded by braces and rows seperated by semicolons: {a,b,c;d,e,f} or use the command MATRIX(a(i,j),i=....j= ...). See below for more on MATRIX. Special matrices can be defined with Diag(x) where x is a list or an n x 1 or 1 x n matrix Eye(n) n x n identity Zero(n,m) Ones(n,m) n x m matrix of zeros or ones. To define a submatrix of a matrix A, use A[i:j, k:l]. The i,j element of a matrix A is A[i,j]. Matrices can be defined with the command MATRIX as follows. If the step is not used, the semicolon can be any seperator and the default step will be 1. Matrix(f(x,y),x=a to b [step c]; y = e to f [step g]) Here the step parameter is the SIZE of the step. 9/1/90 Editing to mark text, move the cursor to the beginning of the text to be marked, then push F3. Move cursor to end, then push either or . moves text to save buffer; does the same but deletes the marked text as well. To mark an entire entry, push Shift-F3, then or . To insert the saved text, move the cursor to the point of insertion and push F4. When new text is saved, the original text is moved to a new buffer. There are ten buffers, which are accessed by F4, Alt-1, Alt-2,..., Alt-9. When new text goes into the F4 buffer, each existing buffer moves up one, and the Alt-9 buffer is discarded. (**********) This material is changed. See 1/31/91 ***Pushing F3 twice inserts a blank line. (**********) This material is changed. See 1/31/91 Lines can be erased without saving with Control-Y. Shift-F4 erases all text buffers--if you need to recover the memory. 9/10/90 Improved the solver routine to take care of functions singular at their roots. Done by replacing f(x) = 0 with f(x)/f'(x) = 0. When this routine entered, the phrase Super Solver appears on the screen. 9/19/90 (revised 11/15/90) Data files To print the last graph, issue the command: PrintGraph To save the last graph for later reloading, use: SaveGraph(filename) The filename must be a string (path allowed) surrounded by single quotes or a variable containing such a string. You could use either: SaveGraph('pix.cc') or pixfile = 'pix.cc' SaveGraph(pixfile) To load a saved graph and display it, use: LoadGraph(filename) This will erase the current Last Graph. To save a list (or single datum or matrix) from a variable to a file, use: SaveVar(variable-name, filename) To load a variable from a file (like the file saved above): LoadVar(variable-name, filename) Note that the entries can be numerical formulas as well as numbers. CC will read and evaluate any legal CC numerical formula (no variables or user- defined functions) found in the file. To print the values of a variable, use: PrintVar(variable-name) When CC saves a variable, it creates an ASCII file beginning with a line containing one of the words LIST VARIABLE MATRIX. If the file starts with VARIABLE, it should have one more line with a value or formula. If the file starts with LIST, it should consist of a series of lines with one number or formula per line. If the file begins with MATRIX, there will be several values or formulas on each line seperated by commas, with the same number on each line. You can create your own files for loading into CC by following these rules. 9/20/90 Added command WAIT(n), which causes computer to pause n seconds. Useful in between GRAPHICS and TEXT to pause a picture. To pause until a key is pressed, use PAUSE. 9/28/90 Changed command BKCOLOR to CURRENTBKCOLOR. This returns current background color. Added two commands BKCOLOR(color number) which sets the background color, and AXISCOLOR(color number), which sets the color of the axes. Presently the color of the crosshairs cannot be changed. These commands should be used in conjunction with AXISON, AXISOFF, KEEPLINE and VARYLINE 10/2/90 Crosshair color now determined by AxisColor Fixed Div and Mod to work with negative integers. 10/11/90 Due to self-imposed limitation on the length of function names, I have had to change some commands. COLOR becomes SETCOLOR SETCOLOR(BLUE) makes the next line or graph blue CURRENTCOLOR becomes COLOR COLOR is a function that returns the color of the next graph BKCOLOR becomes SETBKCOLOR SETBKCOLOR(BLUE) makes the graphics background blue CURRENTBKCOLOR becomes BKCOLOR this is the one that was too long. BKCOLOR is a function that returns the current graphics background color 10/12/90 added bignums--infinite precision integers and fractions. To enter a bignum, precede it with &, eg &123456789. Bignums can be added, subtracted, multiplied and divided with each other and with integers. 10/25/90 A note on differentiation which is not covered in any of my manuals. Certain operators are invisible to differentiation. For example, d/dx(Hex(f(x)) = hex(df/dx). Same for the operators Integer, Bin, Transpose, Fix, Float. 10/30/90 Bignums now work pretty well. You can enter a bignum with or without a decimal: &35.8 = 179/5. Bignums can be added, subtracted, multiplied and divided. You can raise them to integral (but not bignum) powers or take their factorials. Try &3^100 and &100! . Bignums combined with integers result in bignums,but bignums combined with non-integral reals or with complex numbers result in floating point values. When transcendental functions are applied to bignums, like SIN, the bignum is first changed to its floating point equivalent, then the function is computed on the floating point value. Any bignum can be changed to its floating point equivalent with the functin FLOAT(x). If x is not a bignum, it is unchanged. Any real or complex decimal can be changed to a bignum equivalent with the function FIX(x). Be careful with this function. If you want 1/3, enter &1/^&3 (or &1/3 or 1/&3 or 1/fix(3) ), not fix(1/3). Fix(1/3) is a horrible fraction whose denominator is 2^40. CC first changes 1/3 into an approximating floating binary number, then converts this to a fraction. Matrices with ALL bignum or integer entries can be added, multiplied, subtracted and divided with bignum results. Also the functions LU, DET, RANK, and RREF can be applied to bignum matrices with bignum results. Because squareroots are involved, QR and BALANCE always return a floating point result. Lists can also have bignum entries. SUM, PRODUCT, MAX, MIN and AVERAGE return bignum result when applied to a list of bignums and integers, but STANDEV and REGR return floating point results, again because square roots are involved. Here's a special problem: to define the Hilbert matrix, you could say: H(n) = Matrix(&1/(i+j-1), i = 1 to n, j = 1 to n) but this won't work. CC changes this into &1*(i+j-1)^(-1), and the second factor gets evaluated to a real which, when multiplied by &1, yields a floating point real. You must say: H(n) = Matrix(1/fix(i+j-1), i=1 to n, j = 1 to n) Bignums are slow to compute with. On my medium speed AT, it took over one minute to compute det(H(10)) . A NOTE ON LISTS AND MATRICES (********* this paragraph is now superceded. see 1/3/91. The comments are still correct. List operations work on matrices, going across the rows one by one. You can say SUM(A) or MAX(A) or even STANDEV(A) when A is a matrix. You can do regression against two matrices (of the same size) or apply LISTG to a pair of matrices. **********) 11/7/90 added a function SOLVEPOLY with eye to developing eigenvalue routines. The syntax is SOLVEPOLY(x) where x is a list of coefficients for a polynomial with constant coefficient listed first. The function returns a list of roots. It fails on polynomials with coefficients of very different sizes or very small coefficients (work in progress) but works on reasonable polynomials. User beware. Example: x = (1,-3,3,1) SOLVEPOLY(x) // returns (1,1,1) 11/9/90 Still finishing up SOLVEPOLY. I think it will have to fail on the following example, which seems very hard: x^5+1000x^4+x^3+x^2+x+1 = 0 I can solve this by hand--it has one large root near -1000 which can be gotten at with a binary search, and four small complex roots. These are best found by finding their inverses as roots of x^5+x^4+x^3+x^2+1000x+1 = 0 I've also removed one annoyance. Now, if you enter x(y+1) meaning x*(y+1), CC will recognize that x is a variable, not a function and instead of returning an error message will perform the multiplication. If this causes any ambiguities or other problems, please let me know. 11/13/90 Added two functions. LOG10(x) is log base 10. It only works on positive reals. TRACE(x) is the trace function for matrices. I've been experimenting with eigenvalues and SOLVEPOLY. I coded Fadeveev's (sp?) algorithm for the characteristic polynomial in the subroutine window, then used SOLVEPOLY on the result to get the eigenvalues of a matrix. I created the hilbert matrix with bignums (so the characteristic polynomial consisted of bignums too, but of course the solutions returned by SOLVEPOLY were real), found the eigenvalues, and computed the rank of matrix-eigenvalue*I . Up to size 5, the rank was one less than the size. For size 6 and larger, the eigenvalues were not so accurate. The computation for size 6, using bignums, required about 15 minutes. 11/15/90 The commands LOADM SAVEM PRINTM have been eliminated. CC is smart enough to use LOADVAR SAVEVAR PRINTVAR and know when a matrix is involved. See revised comment following 9/19/90. Note that bignums cannot be saved and read back yet. (11/23/90 now they can) 11/23/90 Matrix algorithms are coming along. I've added CHARPOLY(x) which takes a matrix as an argument and returns a list representing a polynomial (constant term first). If x is Hermitian, CHARPOLY is forced to return real coefficients. I've also added EIGENVAL(x), which takes a matrix x as an argument and returns a list of eigenvalues, sorted in order of decreasing magnitude. If x is Hermitian, the eigenvalues are forced to be real. We also have EIG(x), which takes a matrix x as an argument and returns a list of two matrices. If you enter e = EIG(x) then e[1] is a diagonal matrix with the eigenvalues on the diagonal, and e[2] has the corresponding eigenvectors in its columns. If x has repeated eigenvalues, then the eigenvectors for repeated eigenvalues are selected to be orthogonal. If the matrix is deficient (some eigenvalue has an insufficient number of eigenvectors) then the matrix of eigenvectors has columns of zeros replacing the missing eigenvectors. So long as x is not dificient, x = ev[2]*ev[1]/ev[2] . That is, the command EIG diagonalizes x. Bignums can be saved with SAVEVAR and loaded with LOADVAR. I added some display features to EIG, SOLVEPOLY, CHARPOLY, EIGENVAL, SOLVE, IMPLICIT and IN so that the user would have something to watch while these relatively slow commands work. Finally, for today, I changed the commands that set some of CC's parameters. Now we have commands to set the parameters: SetSolveTol(x) SetInTol(x) SetInDepth(x) SetMatrixTol(x) Setting x = 0 in these commands (or using any other illegal value) causes the corresponding parameter to be reset to its default value. No longer need you look up the default values in the manual. The commands: SolveTol InTol InDepth MatrixTol all return the current values of the corresponding parameter. Previously, these commands set the parameters. 11/29/90 Just finished singular values. If A is an n x m matrix of rank r, the command S = SVD(A) returns a list of three matrices: S[1] is n x r with orthonormal rows S[2] is r x r diagonal with the singular values on the diagonal. The singular values are always positive real numbers. S[3] is m x r with orthogonal rows Moreover, A = S[1]*S[2]*S[3]" The command P = PINV(A) returns the pseudo-inverse of A, which is P = S[3]/S[2]*S[1]" Remember, B" is the conjugate transpose (Hermitian) of B. The ratio of the largest and smallest singular values is called the condition number of A, and can be computed directly with the command COND(A). As suggested by Professor Alex Calders of Duffel, Belgium, I've added two new input commands. Previously, when you executed INPUT or INPUTS on a graphics screen, you got a large box which obscured much of the screen. The new commands are INPUT@(x,y,n,a) and INPUTS@(x,y,n,a), where (x,y) is the coordinate of the lower-left corner of the region where you want the user to type the input, n is the number of characters room is made for, and a is the variable which will receive the input. INPUT@ gets numerical input; INPUTS@ gets string input. INPUT@ only works in subroutines when GRAPHICS is active. Note that this new input command does not include provision for a message to the user. This command should be used in conjunction with WRITE@. Use WRITE@ to put instructions on the screen, then create the input box at a convenient point on the screen where the user can type a response. If you try to place the input box too high on the screen,it will be automatically lowered, and if you try to place it to far to the right for the number of characters you wish to accomodate, it will be automatically shifted to the left. Note that the graphics cursor is alive while waiting for a response to INPUT@--the graphics cursor is not active while waiting for a response to INPUT or while a message created by WRITE is on the screen. Here's a simple example: procedure test window(0,3,-1,1) graphics qu(cos(x),x) sk(x,x) solve(cos(b)=b,b=1) Write@(.1,-.6,'Enter x-coordinate where curves intersect') repeat input@(.3,-.8,5,x) ok = x > b-.05 and x < b+.05 if not ok beep end until ok Write@(.1,-.7,x) Write@(.1,-.8,'You got it!!') text end The procedure graphs two curves on the screen and asks the user to input the x-coordinate of their intersection. The request repeats until the user inputs an answer within 0.05 of the correct one. 12/11/90 IMPORTANT NOTE ON CONFIGURATION FILES Altered the configuration (Control-F9) routine to allow you to add page length (in lines), as requested by European correspondent. Also recently fixed some bugs in config routines, so you MUST remake your config files if you are using one. Do this by erasing the configuration file CC.CFG while outside of CC, then creating a new one from within CC by pressing Control-F9. Note: you set the total number of lines on your page; CC will allow for a top and bottom margin. Also added a form-feed or skip-to-top-of-page command to the print (F2) menu. This will be useful for laser-jet users, but beware: CC not only skips to top of page but starts the next page, positioning the print head to write the first character on the next page. Changed the effect of F8. Now you can no longer load a graph through this key, only a file of commands, so you will not be prompted to choose G for graph or C for command file. After pushing F8, you will be asked directly for the name of the command file to load. Graphs must be loaded with the command LOADGRAPH(filename). 12/12/90 Changed the directory command from shift-F1 to shift-F8, since F8 is my file input key. After viewing the directory, you have the opportunity to make that directory your primary directory. Also added Control-F8, which is a simple change directory command. Added commands ROWVECTOR(X) and COLVECTOR(X), which take a list X and turn it into a 1-row or 1-column matrix. If X is not a list, the result is a 1x1 matrix whose sole entry is X. Fixed 3d graphs so that (a) axis labels print horizontally, not paralell to the axes, and (b) if the axis points in the negative direction, a negative sign is added to the axis name. 12/20/90 Merry Christmas. The matrix editor is completed. Now, when you compute a matrix, it will be shown in spreadsheet format. You can cursor around it with the arrow keys, the control-left and right keys, pgup and pgdn, control-home and control-end. The highlighted element is displayed at the bottom of the screen, so even if it isn't completely displayed in the matrix you can see it by highlighting it. If you produce a formula with more than one matrix, each will be shown in turn. For example, if you compute A/B, with B a matrix with symbolic entries, both A and B will be displayed, and the result Matrix(.,.)/Matrix(.,.) shown in the Output Window. You can also edit matrices with the spreadsheet. To create or change a matrix A, execute the command: MEDIT(A) If A is not a matrix, its contents will be lost. You can move around A with the arrow keys, etc, as above, adding or changing elements in the matrix. This command can also be used to view a matrix. If a matrix is displayed as a result, without possibility of editing, the highlighted element is shown in boldface or a different color. In this case you cannot cursor beyond the boundaries of the matrix. If the matrix is displayed as a result of the MEDIT command, the highlighted element is reversed and can be changed. In this case you can cursor beyond the current boundaries of the matrix and make the matrix larger by adding elements. You do not need to fill in all the elements--blank elements will be filled with zeros. Now there are four ways to create a matrix: Surround its elements with braces: {1,2,3;4,5,6} Use a formula: Matrix(1/(i+j-1,i=1,5,j=1,5) Read it from a disk file: LoadVar(A,'filename') Create it with MEDIT: MEdit(A) 1/2/91 Happy New Year. Just added some string operators. Strings are entered by surrounding them with apostrophes: x = 'abcde' . Now they are displayed with apostrophes to distinguish them in the output from undefined variable names. Strings can be used in WRITE and INPUT statements, they can be compared for position in alphabetical order, and now they can be manipulated. To extract the third character from a string, use x[3]. The result is a string of length 1, unless x has fewer than 3 characters. In that case the result is the empty string '', or the string of length 0. To extract the substring consisting of characters 4..7, use x[4:7] or x[4,7]. If x has fewer than 7 characters, then all characters of x, beginning with the 4th, will be returned. If x has fewer than 4 characters, the empty string is returned. Strings can be concatenated with | just like lists. 'abc' | 'de' returns 'abcde' . To determine if one string x is a substring of another string y, use the function POS(x,y). (POS means position.) POS returns 0 if x is not a substring of y, otherwise it returns the position of y corresponding to the starting point of the substring x. POS('abc', '12abcde') returns 3. The length of a string can be determined with the function LENGTH(x). The function UPCASE(x) returns a string y which is the same as x except that all lower case letters a..z are replaced with upper case letters A..Z. If x is a string, then ASC(x) returns a list of integers that are the ASCII codes of the characters of x. If x is a string of length 1, then ASC(x) is an integer, not a list of length 1. Conversely, if x is an integer or a list of integers in the range 32..255, then CHR(x) is a string whose character codes are in x. If x has entries outside the required range, they are ignored. NOTE: strings with characters in the range 129..255 will not print on the graphics screen. Turbo Pascal does not support them in graphics mode. ***now they do see 1/27/91*** 1/3/91 Changed the statistical functions for matrices. Now SUM MAX MIN AVERAGE STANDEV, applied to a matrix, return a row vector containing the appropriate value for each column of the matrix. If matrix has only one column, a scalar rather than a 1 x 1 matrix is returned. REGR(m), for a matrix m, works as follows. Let p be the same as m, but replace the last column by 1's, and let b be the last column of m. Then REGR(m) = pinv(p)*b. Thus REGR is a column vector whose length = the # of columns of m. If m is r x 2, then if we think of the rows of m as points, the elems of regr(m) = (c,d)" and y = cx+d is the regression line through the points. More generally, REGR(m) = (r1,...,rn) where the hyperplane most nearly approximating the rows of m is xn = r1 x1 + r2 x2 + ... + rn-1 x-1 + rn Added a sorting routine for matrices. The function SORT(m,i) sorts the rows of the matrix m on the data in column i and returns a sorted matrix. m is unchanged, unless you use the command m = SORT(m,i) . To sort on two columns, first sort on the secondary key, then on the primary key. 1/4/91 The command SOLVEPOLY (11/7/90 and following) now has a complement: if p is a list representing a polynomial, and x is a value, then EVALPOLY(p,x) returns the the value p(x). EVALPOLY uses Horner's method, so it will be faster on large polynomials than defining a function equal to p and evaluating it: f(t) = SUM(p[i]*x^(i-1), i = 1 to length(p)) f(x) The difference can be seen if you take p = LIST(1,i=1,100) and x = 2. 1/7/91 Finally, there is a ZOOM feature for graphics. To magnify part of a graph (only the part drawn with GRAPH, DOTGRAPH, QUICKG, SKETCH, PARAMG POLARG, DIFFG and INTEG, not LINE, FILL, WRITE, etc.) move the crosshairs to one corner of the region to be magnified. Press control-Z (the crosshairs change to Z) and use the cursor keys to move the Z to the opposite corner of the region to be magnified. Press and your graph will be magnified. If you want to cancel the zoom command, press . To restart the window at the current location of the Z, press Control-Z again. After zooming your window, the window parameters WINDOWLEFT etc. will be changed to reflect the new window. If you zoom on a curve drawn with PARAMG or POLARG, much of the curve may be outside the zoomed window, since you won't have changed the limits of the parameters. Now you can use WINDOW(0,0,0,0) to restore the window limits to their original values, which were WINDOW(-1.4,1.4,-1,1) . *** this is changed see 2/10/91 *** 1/9/91 To complement CHR and ASC, I've added VAL and STR. If s is a string, then VAL(s) returns the numerical value of s. s may be any legal CC formula. Conversely, if x is a value or CC formula, then STR(x) returns a string representing the value of x. Examples: VAL('12') = 12 VAL('Cos(PI)') = -1 STR(3) = '3' STR(Cos(PI)) = '-1' Complex values and bignums can be used with VAL and STR. 1/15/91 Added a new command: FIELD(f(x,y),g(x,y),x,y) draws vector field (f,g) in current window. Example: FIELD(-y,x,x,y) The resulting vectors are not strictly proportional to their true lengths. Although longer vectors appear longer, at least if they are parallel, the proportion between longest and shortest vector has been reduced so that individual vectors aren't reduced to single points. However, if one vector is very long, the others may virtually disappear. This will happen, in particular, if there is a singularity at the origin of the vector field. Then, if you draw one vector very close to the origin, it will dwarf the others. To avoid this, see the next comment. Normally 15 x 15 vectors are drawn. You can change this value by adding a different number of vectors in each direction after the direction parameter: FIELD(-y,x,x,10,y,10) . If your window is symmetric about the origin, you can avoid placing a vector near the origin by choosing an even number of vectors in each direction. Also, to complement Zoom, after zooming you can press Control-U to UnZoom--go back to prior window. *** See 2/8/91 for information on expanded UnZoom. *** 1/27/90 We are at war. I've started compiling with Turbo Pascal 6.0. This gives me new stroked fonts with all the characters with codes 32-255. I've changed from the triplex font to the small font for all writing, including the text which was previously written in the default (bitmapped) font. Internally I'm using sizes 4-10, but externally, you should use size codes 1..7 for Write@, VWrite@, Write@c and VWrite@c. The default size is 2, matching the text used by CC to label the ends of the axes, the coordinates of the crosshairs, and the message at the lower left of the graphics screen. I've also added two commands to complement vector fields: TRAJ(f(x,y),g(x,y), x = a, y = b) draws a trajectory through the vector field (f,g) beginning at (a,b). Normally 50 segments are used to draw the trajectory. You can change this number by adding a value after b. LEVELC(f(x,y)=g(x,y), x = a, y = b) draws the graph of f(x,y) = g(x,y) both ways from the solution point closest to (a,b) . Normally 50 segments are used to draw each half of the solution curve; you can change this value by adding a different number after b. Examples: TRAJ(-y,x,x=.5, y=.5, 100) LEVELC(x^2+y^2 = 1, x=.7, y=.7, 30) *** see 2/9/91 for a step size parameter *** 1/29/91 I seem to have neglected to list a couple of matrix commands. TRANS(a) transpose of a CONJ(a) conjugate of a a" conjugate transpose or Hermitian of a rows(a) number of rows of a cols(a) number of columns of a rank(a) rank of a it may be necessary to jigger matrixtol a bit to get this value to come out right. det(a) determinant of a 1/31/90 A minor fix: previously the INPUT(a,b) command required a specific string in apostrophes at a and a variable name at b. The variable name is still required, but the first entry can be any expression at all: 'input third value' a string x a variable (where previously we executed x = 'input third value' ) Cos(4.5) an expression--the value is displayed Cos(4.5t) an expression with undefined terms It is particularly useful to be able to store the input prompt in a variable and use the variable as the prompt in the input statement. Changed the InsertLine key from F3 F3 to Control-Enter. This is easier and more natural, and you don't have to count the number of times you push F3 to get an even number. This required changing the mnemonic info at the top of the screen. Added protected lines. If you save a file with Alt-F7, then reload it with F8, you won't be able to alter any of the non-blank lines. You can, however, add lines where there are blank lines and open up new lines with Control-Enter. If you save the file with F7 after adding more to it, the added material will not be protected, but the original protected lines stay protected. To protect the entire file, save with Alt-F7. To unprotect a file for editing protected lines, load it with Alt-F8. Protected lines are useful for writing lessons, etc. You can prepare a lesson that the student can't write over, leaving blank space for the student to write in. 2/7/91 Added five operations to the editor: Control-RightArrow and Control-LeftArrow now move by words, stopping at spaces and the characters ( = + - * / \ [ { ^ < > Control-Backspace erases an entire word to the left, stopping at the same set of characters. Control-PgUp and Control-PgDn move the cursor up and down one entry at a time. I tried to add Control-Delete to erase an entire word to the right, but Turbo won't recognize this key when compiled under TPC, although it does recognize it in the IDE. I've written to Borland. Sometime earlier, I added but forgot to note: Control-B -- delete left of cursor to beginning of line Control-T -- delete right of cursor to end of line Controy-Y -- delete entire line 2/8/91 Fixed the data file loading routines LOADVAR. Added the capability of reading text files into lists of strings. To create a textfile for input, begin it with the line TEXT, then put any lines you want. Here's a sample file: TEXT Put any information that you want into these lines. Blank lines can be included. Suppose that these lines were stored in a file called TEXTFILE.CC. The following subroutine would read the file and display it on the graphics screen: Procedure Display // Display contents of TEXTFILE.CC on graphics screen LoadVar(a,'TEXTFILE.CC'); Axisoff Window(0,1,0,1) graphics for i = 1 to 4 do Write@(0.1,1-i/5,a[i],3) end text end // Display UnZoom has been improved. If your window was created by zooming, UnZoom (Control-U) returns you to the previous window. You can zoom, then unzoom through a number of windows. If there is no previous window, then UnZoom quadruples the size of the current window by expanding each of the axes by 2 from the center. 2/9/91 TRAJ and LEVELC have been modified. You can use a second optional parameter after the optional step number (but the second parameter cannot be used without the first). The second parameter, a real between -5 and 5, specifies a "step size" for the trajectory and level curve algorithms. The default is step size 0, and the step sizes are related exponentially to the step size factor. If s0 is the default step size, and if ssf is the step size factor, then the resulting stepsize factor is: ssf/5 10 *s0 Thus the minimum step size is 1/10 of the default, and the maximum is 10 times the default. Here are two examples using the second factor: TRAJ(-y,x,x,y,300,-2) LEVELC(x^3+x=y^2, x=0,y=0, 100, -1) 2/10/91 To restore the original window [-1.4,1.4] x [-1,1] , use the command WINDOW without parameters. The algorithms for TRAJ and LEVELC have been improved. TRAJ now uses a predictor-corrector method to compute each step. It traces a circle through the field (-y,x) pretty accurately. Try TRAJ(-y,x,x=1,y=0,222) in the standard window. LEVELC(f=g,x=a,y=b) now computes a new approximation (x,y) by following a vector perpendicular to grad(f-g), then (this is the improvement) follows the gradient vector back to the level curve. I stopped using the built-in solver, and instead wrote a special Newton's method solver for this last step. Given a point (a,b) and a function h(x,y), to move along the gradient field grad(h) from (a,b) to a solution of h(x,y) = 0, we create a function of one variable k(t) = h(a+r*t,b+s*t) where (r,s) = grad(h)(a,b). Then using Newton's method to solve k(t)=0, we begin with t = 0 and correct to t = -h(a,b)/(rı+sı). We just go one step, construct new values of a = a+r*t, b=b+s*t, new values of r and s, and do it again until the pixel representing (a,b) doesn't change from one step to the next. 2/16/91 New command has been added to display a value on demand. Previously, when you had a list or matrix stored in a variable, the only way to view the object was to execute the variable name, which duplicated the value in the variable in the variable ANS. This cost extra memory if the value was a long list or large matrix and destroyed the current value of ANS. Now you can enter the command: DISPLAY(X) where X is a variable name or any other legal CC expression, and the value of X will be displayed without changing the value of any of CC's variables. The Config (Control-F9) routine has been slightly changed so that pressing at each step leaves the value of the choice unchanged. In fact, all the Y/N questions have been altered. The query now shows Y/n or y/N or y/n. If one of the choices is capitalized, then that it the default choice and can by selected by pressing . The only place where there is not a default choice is when the program ends (^Q). The user must specify whether or not to save the work. Neither alternative is an attractive default--no save default is too dangerous, and save default may confuse beginning users. It's been a busy day. Two cars washed and the oil changed, waste paper recycled, and still time for more innovations. Jim Smith pointed out that the new graphics font, Borland's SmallFont, doesn't transfer very well to WordPerfect. Its strokes are only one pixel wide, and they can get lost when the graph is Grabbed and reduced. To overcome this difficulty, I've added two commands: THICKTEXT THINTEXT After executing THICKTEXT, all graphics text of size larger than the default size (3 or more) will be printed with lines two-pixels wide. Actually the text is printed three times, once, then move up one pixel and print again, then move right one pixel and print again. This only applies to large text, since it doesn't look very good on smaller text. To return to ordinary graphics characters, enter the command THINTEXT. 2/19/91 Sometime back, I forgot to note when, I completely revised the help facilty. There is a new help file twice as big as the one in CC3 and new routines to run it. I just made minor changes in the matrix editor. Now, if you cursor to a position in the matrix where an element is defined and start typing a new element, the old element disappears. Previously, whatever you typed was added to the end of the old element. If you begin by pressing or , you will preserve the old element and edit it. For some time, you have been able to move either way on a row of a matrix you are editing with the key. Also, if a matrix is displayed after creating or DISPLAYing it, you can return to the calculator screen by pressing or . However, if you have called up the matrix with MEDIT, then you must terminate the session with . That is because it is too easy, after entering a formula into the matrix editor, to terminate the formula with . 2/24/91 The last three days were spent in an exhaustive rewrite of the algebraic simplification algorithms. They are now much cleaner and easier to understand, and the bugs which gave rise to the rewrite have been eliminated. One quirk has been introduced. Since CC does not factor, a choice must be made for the order of application of the following two rules: (a+b)c = ac + bc and a^n a^m = a^(n+m). (CC has an algorithm to determine when two expressions are equal, so it can combine their exponents.) The situation arises here. The second rule is now applied first, so that (x+y)*(x+y)^(-1) gets converted to 1 instead of x*(x+y)^(-1) + y(x+y)^(-1). However, this order of application can have strange (but correct) results. If x is undefined and you try PRODUCT(1+N*X,N=1,5), you will find that CC catches the factor (1+3X) and retains it, while the other factors are expanded by the rule of transitivity. Changed the default number of steps in FIELD to 14 from 15, so that there is no vector in the center of the field, which will often be (0,0) and may be a singularity of the field. Including the singularity doesn't cause a crash, but may cause all other vectors to be reduced to points. 2/29/91 Minor changes today. Decided that SAVEVAR should not save bignums, since once saved they could not be read back in if they were very big. They can be saved by F2-7, save all input, subroutines and variables to disk. Changed REGR(m), where m is a matrix. Now REGR(m) returns a column vector which is a least squares solution to the equation Ta = b, where T is the matrix formed by deleting the last column of m and adding a new first column of 1's, and b is the last column of m. Thus, if each row of m is the data x1,x2,...,xn,y, the column vector a gives the best linear fit: a0 + a1x1+...+anxn = y. Previously the constant term was at the end of the linear approximation. 3/14/91 I've altered the input routines considerably, so that lines up to 2048 characters can be entered. You can enter (with spaces, not carriage-returns): x = {1,2,3,4; 5,6,7,8; 9,10,11,12} The tab key moves the cursor to the next line and places it under the first non-blank character, which is a help in creating entries like the one above. You can also enter much longer bignums now. You can also save (with SAVEVAR) and reload (with LOADVAR) large bignums and large matrices. If you look at the file they are saved in, you will see that the file contains lines up to 240 characters in length, and if that isn't enough for one bignum or row of a matrix, a continuation character (#220) is placed at the end of the line and the entry continues on the next line. Now I have to start rewriting the manual. 3/17/91 But not quite yet. Wordwrap has been added. Now you can enter very long comments by starting them with // and just typing. Wordwrap also works in formulas, so your long formulas won't break in the middle of variable names or leave an opening parenthesis on the previous line. Note: if you have an entry like this: lkjlk ljljlk ljjlkj ljlkj ljlkj klX dsfasf dsfsadf afdsa fsafsda and you delete the X or push backspace with the cursor at the beginning of the second line, the first word on the second line will not come up to the first line until there is room for it. I've modified ^B and ^T so they just erase the beginning or end of the line you are on. However, ^Y still erases an entire multi-line entry. You can recover the last ^Y with alt-Y--a primitive UnDo command. I'm considering changing ^Y to just affect one screen line, not an entire entry. 3/19/91 Wordwrap is user-controllable. The command WORDWRAPON turns on wordwrap (the default), and WORDWRAPOFF turns it off. The initial state of wordwrap can be altered in the configuration file. The matrix editor has some unrecorded commands and two new ones. The unrecorded ones are ^End and ^Home, which move you to the beginning or end of matrix. ^RightArrow and ^LeftArrow move one screen at at a time, as does PgUp and PgDn. Home and End move to beginning and end of individual element. The new ones are ^R and ^C. ^R adds a row of zeros above the current row, and ^C adds a column of zeros to the left of the current column. 3/20/91 A slight modification to the routines that add rows and columns. Now, after pressing Control-R or Control-C, CC will ask if you want to add or delete a row. Press I or D to indicate, or to forget the whole thing. 3/27/91 SaveVar, FSaveVar, PrintVar have been changed to Save, FSave, Print. Instead of saving a variable name, you can save any expression, including a variable. This is useful, for now in subroutines you can add a line Print('state 1 reached') and it will print. 4/1/91 Fixed a few small bugs. Now the minimal number of lines per page is 50. 4/9/91 changed LoadVar to Load, to correspond to change to SaveVar. See 3/27/91. Also fixed Save, so it would work.