GENPREC MANUAL TABLE OF CONTENTS Page 2 INTRODUCTION 3 SECTION 1. A FEW WORDS ON THE INTERNAL REPRESENTATION OF MULTIPLE PRECISION NUMBERS 4 SECTION 2.1 NEW VARIABLE TYPES DEFINED IN GENPREC 4 SECTION 2.2 DECLARATION OF USER DEFINED VARIABLES 6 SECTION 3. THE GENPREC PACKAGE AND THE DEPENDENCE TREE 7 SECTION 4. FACILITIES FOR COMPUTING MEMORY REQUIREMENTS 8 SECTION 5.1 DECLARATION OF VARIABLES USED WITHIN GENPREC AND THE SCALARS AND VECTORS OUTPUT BY GENPREC 8 SECTION 5.2 VARIABLE NAMES TO AVOID CONFLICT 9 SECTION 6. THE CONSTANTS PI, e, log base 10(e) AND WHEN IT IS NECESSARY TO CALCULATE THEM 9 SECTION 7. ASSIGNING VALUES TO VARIABLES 13 SECTION 8.1. REDIRECTING OUTPUT TO PRINTER OR DISK FILE. 14 SECTION 8.2. WRITING TO AND READING FROM DISK FILES 16 SECTION 9. EXAMPLES WHICH ILLUSTRATE GENPREC 16 Example 1: The first sample program is to calculate the square root of 2 to 32 significant figures. 17 Example 2: Complex numbers. The square root of 1+i. 18 Example 3: For loops and the multiplication of two matrices. 20 Example 4: Branching. 21 SECTION 10. EXAMPLES PROGRAMS INCLUDED WITH THE GENPREC PACKAGE 23 SECTION 10.1 NOTES ON THE LINEAR TEST SYSTEM: 24 SECTION 11. FUNCTIONS IN GENPREC 24 SECTION 11.1 genprec.h 28 SECTION 11.2 cgenprec.h 33 SECTION 11.3 EXAMPLES OF FUNCTIONS WHICH CAN BE DERIVED FROM IDENTITIES 33 SECTION 11.4 genlin.h 33 SECTION 11.5 cgenlin.h 34 SECTION 11.6 poly.h 35 SECTION 11.7 cpoly.h 36 SECTION 11.8 series.h 37 SECTION 11.9 cseries.h 38 SECTION 11.10 pade.h 38 SECTION 11.11 cpade.h -1- INTRODUCTION GENPREC is a set of C++ subroutines for doing floating point calculations with a large number of significant figures. It has been tested to thousands of significant figures. Each mathematical operation is a subroutine call. For example addition of multiple precision variables "a" and "b" is done via the subroutine: zadd(a,b); as will be explained in more detail later. GENPREC can perform all standard mathematical operations including trigonometric functions, inverse trig functions, logarithmic, exponential, hyperbolic and inverse hyperbolic functions. The constants e, pi, and logbasee(10) are calculated to the desired precision. There is a facility for converting integers or floating point numbers to multiple precision or for rounding multiple precision numbers to floating point for easy data input and output. The code can handle arrays. GENPREC handles complex arithmetic, solves linear equations (real or complex), solves polynomial equations of arbitrary degree (with real or complex coefficients), and includes functions for manipulating power series of any order (real and complex) and functions for calculating the Pade approximant of order (n1/n2) to any power series (real and complex). The code has been optimized for speed and can solve a 50x50 array of 50 linear equations for 50 unknowns to 32 significant figures in about 7 seconds on a 486DX2 50 Mhz machine if complied on an optimizing compiler such as WATCOM C++ ver 9.5. (note that when doing array arithmetic in high precision access to extended memory may be required; WATCOM C++ which includes Rational Systems' DOS extender was chosen for this reason). This speed is roughly comparable to the speed of early versions of Microsoft's Quick Basic (QB87) allowing for the fact that the time to do arithmetic increases as the square of the number of significant figures, and is fast enough for serious scientific and engineering calculations which require more than double precision (more than 15 significant figures). -2- SECTION 1. A FEW WORDS ON THE INTERNAL REPRESENTATION OF MULTIPLE PRECISION NUMBERS In any base, a number can be represented in floating point notation as a * b^p where -1 from C/C++ int precision=8; //(number of significant figures)/4 int zmaxsize=51; //largest real object whether vector or matrix //set zmaxsize=0 if vectors or matrices not used int cmaxsize=25; //largest complex object wheter vector or //matrix //set cmaxsize=0 if complex //vectors or matrices are not used include files " " from Genprec in this order: | genprec.h | ---------------------------------------- | | | | genlin.h poly.h series.h cgenprec.h | | pade.h -------------------------- | | | cgenlin.h cpoly.h cseries.h | cpade.h -6- The tree asserts that if one wishes to include cpade.h one must also include what goes before it on the tree; for example, to include cpade.h: int precision = 8; (number of significant figures/4) int zmaxsize = 0; (size of largest real vector or matrix in the code) int cmaxsize=25; (size of largest complex vector or matrix in code) #include "genprec.h" //top of the tree #include "cgenprec.h" //second level on the tree #include "cgenlin.h" //third level on the tree #include "cpade.h" //lowest level on the tree In the above example, if one wishes to also find the roots of a polynomial with complex coefficients, one must also include cpoly.h. The statement #include "cpoly.h"; can appear anywhere in the list of include statements after #include "cgenprec.h"; The first three items are necessary because the user must specify the desired precision and the maximum size of all of the objects (vectors and matrices) to be found in the code. If only real scalars appear in the code set zmaxsize=0; Set cmaxsize=0 if cgenprec.h is not included. If cgenprec.h is included and only complex scalars appear in the code, set cmaxsize=0. Examples of the use of each include file are in the GENPREC package. SECTION 4. FACILITIES FOR COMPUTING MEMORY REQUIREMENTS One might want to know how much memory is required by a code. A subroutine zmemory(ns,nv,nm,ncs,ncv,ncm) computes this quantity. ns is the number of quantities which you have declared to be realscalar type (nv realvector,nm realmatrix,ncs complexscalar, ncv complex vector, ncm complexmatrix). For example, if you have declared 1 realscalar, 2 realvector, 3 realmatrix, 4 complexscalar, 5 complexvector, and 6 complexmatrix then zmemory(1,2,3,4,5,6) returns the memory required for these variables. Any ordinary C/C++ variables which you have declared are not included in the counting. The memory required is printed on the screen and you are prompted to enter any character if you want to continue. If the memory required is too large and you do not want to continue type a character and control,break (or however you enter a break from the keyboard) and then press enter (this will return you to the DOS prompt). -7- The code itself occupies some memory (usually reported by the compiler but probably not more than 100 kb) and the operating system uses some memory (surely less than 640 kb) so that the size calculated above should not be larger than the users RAM minus (say) 1000 kb. Quite large programs fit into a machine with 8 mb or RAM. SECTION 5.1 DECLARATION OF VARIABLES USED WITHIN GENPREC AND THE SCALARS AND VECTORS OUTPUT BY GENPREC The variables used within GENPREC are all automatically declared for each file (such as genlin.h) included . SECTION 5.2 VARIABLE NAMES TO AVOID CONFLICT Variable names within GENPREC (including integers) all begin with: z genprec.h cz cgenprec.h w genlin.h cw cgenlin.h y poly.h cy cpoly.h p pade.h cp cpade.h s series.h cs cseries.h It is best to avoid using variables that begin with these letters. User variable names may begin with a,b,d-o,q,r,t-v and x plus ca,cb,cd-co,cq,cr,ct-cv and cx. One need not worry too much about this point since if a user defined variable name is the same as one used in genprec the compiler will return an error message in which case he name of the user defined variable will have to be changed. -8- SECTION 6. THE CONSTANTS pi, e, log base 10(e) AND WHEN IT IS NECESSARY TO CALCULATE THEM Pi is involved in all trigonometric calculations and e and log base e (10) are used in all logarithmic and exponential calculations. These must be calculated at the top of main, after genprecdeclarations() using: zsupe(); //e zsuplogsp(); //log base e (10) zsuppi(); //pi The values calculated are longer than necessary and all subsequent calculations of these numbers are done by rounding down to the current precision: zee(); // rounds the output of zsupe to e zlogsp(); // rounds output of zsuplogsp to log base e (10) zpi(); // rounds output of zsuppi() to pi The user might want to calculate these three constants after genprecdeclarations as a matter of course so that they are always present. However, each GENPREC function has a note after its designation in the section of this manual entitled "Functions in GENPREC" saying which of the constants is required. SECTION 7. ASSIGNING VALUES TO VARIABLES Variable names used by GENPREC (such as z,cz, etc.) do not have to be declared explicitly by the user. The variable "z" is where the results of simple conversions from integers or floating point variables appear. For example: zconinttomp(5); converts the integer 5 to multiple precision and stores the result as "z". Similarly, zconftomp(t); converts the double precision variable t (which must have been declared and defined previously) to multiple precision) and stores the results as "z". -9- At the start of a multiple precision calculation variables are normally integers or can be calculated from integers using the functions and constants provided. For example to set the real MP number a to -1/3: zconinttomp(1); // converts 1 to a type realscalar zdivint(z,3); // divide z/3 zchs(z); // you could have just used -1 above zstore(a); Setting a to zero can be done more simple using the function: zzero(a); which will set the multiple precision realscalar a to zero. To set a = 2*pi: //a could be b[i] or c[i][j] zsuppi(); //calculates pi to more digits than required // this only needs to be run once zpi(); //rounds pi to the current precision zmultint(z,2); zstore(a); //a could be b[i] or c[i][j] If all else fails, the manual method for assigning a variable would be (to set a = 0.12345678901): zconinttomp(9010); //z=9010 zdivint(z,10000); //z=0.9010 zstore(a); zconinttomp(5678); zadd(z,a); //z=5678.9010 zdivint(z,10000); //z=.56789010 zstore(a); zconinttomp(1234); zadd(z,a); //z=1234.56789010 zdivint(z,10000); //z=0.123456789010 zstore(a); As a convenience to the user, a subroutine zconinputtomp is included which accomplishes the above. The input is stored as an array zinput (which has been declared for you in GENPREC). The digits to be converted to the internal base 32768 representation are elements of the array and the zeroth element of the array is the power. For example pi to twenty significant figures would be stored and converted to base 32768 as follows: for (i=0;i //include C++ file commands main() {ifstream myfilein; //declares that myfilein is a pointer to an . //input file . myfilein.open("filename.dat", ios::in); //zinput.dat must be for (i=precision;i>=0;i--) myfilein>>z[i]; //in current directory myfilein.close(); zconinputtomp(z); //converts to base 2^15. zstore(a); . If one wants filename.dat to contain than four significant figures per line (say 40), then one writes myfilein.open("filename.dat", ios::in); for (i=precision;i>=0;i=i-10) {myfilein>>z[i]>>z[i-1]>>z[i-2]>>z[z-3]>>z[i-4]>>z[i-5] >>z[i-6]>>z[i-7]>>z[i-8]>>z[i-9];} myfilein.close(); zconinputtomp(z); return 0; } filename.dat has to be made with DOS editor, 40 significant figures per line in the following way. Each line contains 10 groups separated by tabs, and each group contains 4 significant figures. The total number of groups must be exactly=precision+1. The last line may contain less than 10 groups and the last group on the last line is the exponent (power of ten). In a group 0345=345 for instance (that is, leading zeros can be ignored). As an example, the file filename.dat for pi to 21 significant figures when precision=8 is 3141 5926 5358 9793 2384 6000 0 0 1 The zconinputtomp command converts such data to base 32768. Examples of these methods of assigning values to variables are included in genpex.cpp in the GENPREC package. -11- To input complex numbers: coninttomp(1,2); returns the complex number (1+2i) to the variable "cz". The number sqrt(2)-pi*i would be calculated and stored as: cconinttomp(2,0); // 2 csqrtpol(cz); // sqrt(2) cstore(a); //a could be a[i] or a[i][j] cconinttomp(0,-1); // -i zsuppi(); // calculate pi if you haven't already zpi(); // round down cmultcbyr(cz,z); // -pi*i cadd(a,cz); // sqrt(2)-pi*i cstore(a); All of the real GENPREC functions will work with the real or imaginary parts of a complex variable if you refer to these parts as (for example) cz[0] and cz[1] (or whatever you variable name is. So, to store the floating point complex number t1+i*t2 in "a" you could: zconftomp(t1); zstore(a[0]); zconftomp(t2); zstore(a[1]); The zconinputtomp subroutine can be used to input arbitrary values of the real and imaginary parts of a complex variable cz in this manner. // first store desired real part in zinput and then zconinputtomp(zinput); zstore(a[0]); // next store desired imaginary part in zinput and then zconinputtomp(zinput); zstore(a[1]); -12- 8.1. REDIRECTING OUTPUT TO PRINTER OR DISK FILE. The zprint(a); and cprint(a); subroutines print real MP numbers and complex MP numbers to the screen. Complex scalars x+iy are printed with x and y on successive lines. As noted in some of the examples, it is best to space (cout<<'\n';) after printing a complex number. If it is desired, the output of zprint or cprint could be redirected to the printer or a dos file by using the MSDOS redirect commands when running the program: prompt:\program > prn or prompt:\program > filename where program is the name of the executable code returned by the compiler (prompt is the DOS prompt at the directory containing your C++ compiler). Except in cases where one is checking the accuracy of the calculation, one rarely wants to look at more than the first few digits of the result of a calculation - the precision is just used to avoid roundoff errors. in this case the command: zconmptof(a); is used to convert a multiple precision number back to floating point number zf. Once converted, zf can be manipulated as can any floating point number in C++. To convert a complex MP number a to floating point variables "realpart" and "imaginarypart": zconmptof(a[0]); realpart=zf; zconmptof(a[1]); imaginarypart=zf; -13- 8.2. WRITING TO AND READING FROM DISK FILES Read MP numbers can be written to a disk file or read from a disk file using standard C++ file writing and reading commands. An example of one of the many ways of using these commands follows. #include //includes C++ file commands main() {. //declarations followed by the following two declarations: ofstream myfileout; //declares that myfileout is a pointer to an //output file ifstream myfilein; //declares that myfilein is a pointer to an //input file . //beginning of code . . //culminating in calculation of a variable to be written to a file zpi(); (pi used as example of a variable to be written to a file) myfileout.open("myfile.dat", ios::out); //note: the path must be the for (i=prec;i>=0;i--) myfileout<=0;i--) myfilein>>z[i]; myfilein.close(); zprnt(z); zmessage="pi loaded from myfile"; zbreak(); . //resume the code } The file myfile is permanently saved. It is a text file and can be read, but the number is in base 32768. This code appears in genpex.cpp (which is part of the GENPREC package) in order to test it. There are many other ways of using C++ file commands to do the same thing. Also, z[i] could be a[j][i] where a is a user defined one dimen- sional array (the above code would occur inside a for (j= ) loop). The whole array could be stored provided the open statement occurs before for (j= ) statement and after the } terminating the j loop. More or less obvious generalizations apply to multi-dimen- sional arrays. Or, for a complex variable the first for statement would be replaced by for (i=0;i>cz[0][i]; myfilein>>cz[1][i];} -14- Again, cz[i] could be a one dimensional array of complex numbers a[j][i]. The location of the open and close statements must be as described just above for the case of real numbers. Again, more or less obvious generalizations apply to multi-dimensional arrays. It is possible to type a file such as myfile.dat using the DOS editor and it can then be used for assigning a value to a variable. However, it is desirable that such input be in base 10. A GENPREC command for converting base 10 input to base 32768 is zconinputtoMP(z); This command is used in the examples discussed in SECTION 7 "assigning values to variables". -15- SECTION 9. EXAMPLES WHICH ILLUSTRATE GENPREC Example 1: The first sample program is to calculate the square root of 2 to 32 significant figures: Example 2: Complex numbers. The square root of 1+i. Example 3: For loops and the multiplication of two matrices. Example 4: Branching. Example 1: The first sample program is to calculate the square root of 2 to 32 significant figures: #include #include #include int precision=8; int zmaxsize=0; //vectors and matrices not used int cmaxsize=0; #include "genprec.h" main() { zconinttomp(2); zsqrt(z); zprint(z); zmessage="should be the square root of two"; zbreak(); return(0); } This program should be typed and named in your favorite editor and saved with the extension .cpp (for example root2.cpp). It is then linked and compiled to create an executable. When the executable is run the square root of 2 to 32 significant figures should appear on the screen. The first lines with <> are part of any C++ code and show which parts of C++ are included. GENPREC requires the four shown and any other the user requires must be included at this point. The line int precision=8 asks for 32 figures of precision. The line #include "genprec.h" indicates that of all the multiple precision packages only genprec.h will be used (restricting the calculations to real arithmetical operations). -16- The real difference between the <> files and the " " files in the include statements is that the <> files are complete by themselves and the " " files require information from you. The first line in main runs a subroutine which converts the integer 2 to multiple precision and stores the result in "z" (see the manual under Assigning values to variables). The next line takes the square root of "z". The next two lines are subroutines that were written as a convenience for outputting a message. The message could just as easily have been displayed with normal C++ output statements. If you want more figures you must increase the value of the variable "precision" and recompile. For example the code has been checked to correctly calculate the value of pi to 10000 figures. Computing pi 10000 figures took 9 minutes with a 486SX 25MHz PC with 4 meg of RAM when compiled with Watcom C++ version 10. Besides taking a very long time there are some other problems in running calculations to high precision. One is storage space. Since each digit in base 10 takes about one byte of memory and GENPREC uses about 40 variables running simple calculations such as pi to 10000 digits takes about 400KB of memory. If your C++ compiler can access extended memory this limitation should not pose much of a problem. Another limitation is integer overflow. C++ does not give errors in the case of overflow and when running with calculations to a very large number of digits your PC can "hang up" or give incorrect results. In most scientific or engineering problems one is not really interested in 10000 digits. But often one would like more than the 15 digits corresponding to ordinary double precision, perhaps 32 or 64 or 100 significant figures. The notorious Wilkinson polynomial cannot be solved when computing with 15 significant figures, but it is easily solved if one keeps 32 significant figures. This polynomial is one of the examples in polyex.cpp. The second coefficient in the Wilkinson polynomial (210) when varied in the 10th significant figure (210.0000001) results in roots which are very different from the original roots. One may study this famous problem using polyex.cpp. -17- Example 2: Complex numbers. The square root of 1+i. #include #include #include int precision = 8; int zmaxsize=0; //vectors and matrices not used int cmaxsize=0; #include "genprec.h" #include "cgenprec.h" main() { cconinttomp(1,1); csqrt(cz); cprint(cz); zmessage="should be the square root of 1+i"; zbreak(); return(0); } The subroutine cconinttomp converts the integers (1,1) to the multiple precision complex number 1+i. The subroutine csqrt takes the square root of a complex number in rectangular coordinates and cprint prints a multiple precision complex number. Example 3: For loops and the multiplication of two matrices. In this example the two real square matrices a(i,j) and b(i,j) are multiplied where a(i,j)=i*j and b(i,j)=i+j #include #include #include int precision = 8; int zmaxsize = 50; //overly padded:could be same as size=10 (maybe 11) int cmaxsize =0; //below #include "genprec.h" extern declarations(int,nmax); // a user defined function int size; // the size of the matrix realmatrix a_ram;int * * *a=a_ram.m; // the matrices to be realmatrix b_ram;int * * *b=b_ram.m; // multiplied realmatrix c_ram;int * * *c=c_ram.m; // the result -18- main() { int i,j,k; size = 10; // a 10x10 matrix // set a(i,j)=i*j,b(i,j)=i+j for (i=1;i #include #include int precision=8; int zmaxsize=0; int cmaxsize=0; #include "genprec.h" realscalar a_ram;int *a=a_ram.s; realscalar b_ram;int *b=b_ram.s; main() { zconinttomp(1); zstore(a); zconinttomp(2); zstore(b); zmessage="a=1,b=2" zbreak(); zsub(a,b); if (z[prec]==0) {zmessage="a and b are equal";zbreak();} if (z[prec]>0) {zmessage="a>b";zbreak();} if (z[prec]<0) {zmessage="a,b";zbreak();} return(0); } This example makes use of the fact that z(prec) contains the sign and also that "z" is always calculated such that if z(prec) = 0 then "z" = 0. -20- SECTION 10. EXAMPLES PROGRAMS INCLUDED WITH THE GENPREC PACKAGE There are other examples included with the GENPREC package illustrating the use of each included file. The examples have a .cpp extension as in genlinex.cpp. An effort has been made to annotate the examples with suitable comments explaining them. The examples are: genpex.cpp which illustrates some arithmetic cgenpex.cpp arithmetic using complex numbers genlinex.cpp solves a test linear system (see notes below) cgenlnex.cpp which illustrates a test linear system with complex numbers pi.cpp calculates pi to 10000 figures. The output to the screen should be redirected to the printer if one wishes to view the result (the output has about 150 lines). One will want to check the result against anything one can find which gives so many figures. polyex.cpp illustrates the solution of several polynomials, including the dreaded Wilkinson polynomial. Be patient! The 2nd example takes time and the 14th a lot of time! (maybe 2 minutes on a 486DX250 machine). polyex1.cpp an example of the multiplication of two polynomials and the evaluation of various polynomials cpolyex.cpp illustrates the solution of a polynomial with complex coefficients, x**2+(1-3*i)x-4=0 which has roots 1+i and -2+i cpolyex1.cpp an example of the multiplication of two polynomials and the evaluation of various polynomials seriesex.cpp works on Pade approximants to f=sqrt((1+2x)/(1+x)), illustrating the creation and manipulation of series. series for df/dx and log der [f]=(df/dx)/f are generated. -21- seriesx1.cpp evaluates the series for (1+2x)/(1+x) at x=1+2i and repeats the above example. seriesx2.cpp further work on Pade approximants to sqrt((1+2x)/(1+x)), evaluating approximates at infinity up to the (20,20) approximant padeex.cpp simple case continued in seriesex.cpp and seriesx2.cpp cpadeex.cpp which is a detailed investigation of Pade approximants to sqrt(1+(2+i)x)/(1+(1+i)x)) including value and infinity and location of zeros of numerator and denominator. This test many other functions. cpadeex1.cpp this calculates residues at zeros of denominator for the above example. The residues are reasonable. cpadeex2.cpp Pade approximants to sqrt(1+(2+i)x) + (1+(1+i)x)) with evaluation of residues at zeros of denominator. Some residues are large. cpadeex3.cpp Pade approximants to log der [sqrt(1+(2+i)x)] with evaluation of residues at zeros of denominator (there is only one non-spurious pole which has residue 1/2, and the residues of the spurious poles are zero) cpadeex4.cpp (2/2) Pade approximant to log der [sqrt((1+(2+i)x)/(1+(1+i)x))] Both poles of the denominator are non-spurious and have residues 1/2 and -1/2 as expected. cseresex.cpp inverts the series for e^t (answer should be log(1+t). Tests the inversion of a series and substitution of one series into another in various ways, particularly (a->b)^-1=(b^-1)->(a^-1) that is, the result of substituting a into b and taking the inverse is the same as inverting b and inverting b and substituting the result of inverting b into the result of inverting b. The variation of this rule which is tested in the example is a^-1->b=(b^-1->a)-1. -22- SECTION 10.1 NOTES ON THE LINEAR TEST SYSTEM: m(i,j)*x(j)=r(i) (1) where m(i,j) = delta(i,j)+i*j (2) delta(i,j)=1 if i=j and is zero otherwise and r(i)=i (3) This linear system has a simple closed form answer which is derived as follows: Substituting (2) and (3) into (1) gives N Sum [delta(i,j)+(i*j)]*xj = i, i= 1 to N j=1 or, using the definition of delta(i,j) and dropping the explicit bounds on the Sum: xi +i*Sum j*xj = i Let Sum j*xj = lambda then xi=i*(1- lambda) or equivalently xj=j*(1- lambda) (4) substituting this back into the equation for lambda gives Sum j^2*(1-lambda) = lambda or lambda = Sum j^2/(1+Sum j^2) Further, it can be shown that Sum j^2 = (N^3)/3 + (N^2)/2 + N/6 so substituting back into (4) xj=j*(1-((N^3)/3+(N^2)/2+N/6)/(1+(N^3)/3+(N^2)/2+N/6) which is the exact closed form solution for xj. This is an example of what is called a separable kernel. In the complex case the test problem is defined by m(j,k)=delta(j,k)+(j+i)*(k+i) and ri=j+i where i is the square root of -1. This can be solved in closed form using a similar method. -23- SECTION 11. FUNCTIONS IN GENPREC Caution: The MP symbol has a definite meaning explained on p.5 above. SECTION 11.1 genprec.h zadd(a,b) input: real MP numbers a,b function: a+b output: z . zsub(a,b) input: real MP numbers a,b function: a-b output: z zmult(a,b) input: real MP numbers a,b function: a*b output: z zdiv(a,b) input: real MP numbers a,b function: a/b output: z zmultint(a,n) input: real MP number a and integer n function: a*n output: z zdivint(a,n) input: real MP number and integer n function: a/n output: z zzero(a) input: none (other than the name of the variable) function: put the real MP number a=0 output: none (does not change z unless a is z) zstore(a) input: z (result of a previous calculation) function: stores z as a real MP number a output: none (z remains unchanged) -24- zchs(a) input: real MP number a function: sets a = -a output: none if a is not z, -z if a is z zbreak() input: zmessage (example zmessage="output answers appear above";) function: prints zmessage and provides a break output: zmessage and "type any character to continue" to screen (cannot be redirected to printer or disk file) zrecip(a) input: real MP number a function: brings 1/a to register z output: z=1/a (the original a is not changed) zabs(a); input: real MP number a function: brings |a| to register z output: z=|a| (original a is not changed) zsqrt(a) input: real MP number a function: square root of a output: z=sqrt(a) zconinttomp(n) input: integer n function: convert n to an MP number output: z=n (z is a multiple precision number) zconinputtomp(a) (see SECTION 7) input: an array a of four digit numbers as described in SECTION 7 (where a was called zinput) function: converts this input to a multiple precision number output: z, which may be stored with any variable name zrecall(a) input: none (other than the name of the MP number a) function: bring the MP number a into the register z output: z (original a is not changed) -25- zpi() (requires zsuppi() to be run first) input: none function: rounds the value of pi calculated using zsuppi() at the beginning of main to the current precision output: z = pi zcos(a) (requires zsuppi() to be run first) input: real MP number a function: cos(a) where a is in radians output: z zsin(a) input: real MP number a function: sin(a) where a is in radians output: z zconmptof(a) input: real MP number a function: convert a to a standard floating point number output: zf a floating point number approximately equal to a. cout<