                               
                               
                               
                               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<a<1, b is the base, and p is zero or a positive 
     or negative integer.  When N significant figures are used, 
     "a" is further decomposed into

                  .a(N) a(N-1) a(N-2) ... a(1)

     where, unless a is zero,  a(N) is a signed integer whose 
     magnitude is less than b, and a(N-1),a(N-2), ... are  
     positive integers less than b (the base).  a(N),... are 
     referred to as the significant figures or "digits". 

     Internal to GENPREC, numbers are represented in base 32768 
     for calculational efficiency. Thus a multiple precision 
     number is stored as an integer array where each element of 
     the array is one significant digit in base 32768. The zeroth 
     element of the array is the power p. It is assumed that 

                      -32768 < p <32768

     (32768 to the 32768 power is a very large number and 32768 
     to the -32768th power is a very small one - in principle the 
     code can handle powers up to 2^32, but this feature has not 
     been tested).  The first element of the array is the last 
     digit and the Nth element of the array is the first digit. 
     The Nth element of the array is a signed integer and carries 
     the sign. If the Nth element is zero the number is zero.  
     The dimension of the array required is calculated by the 
     GENPREC program from the user specified precision.  
     Calculations are carried out to somewhat more accuracy than 
     specified by the user and then rounded. 

     The following variables used within GENPREC refer to the 
     number of significant figures. The number of significant 
     figures is restricted to be a multiple of four.

     precision:       number of significant figures = 4*precision
     prec10:          precision plus one (used in printing)
     prec:            the number N of base 32768 "digits"

     The user assigns the value of precision by the statement  
     
                int precision=8;   //32 significant figures

     placed before 
     
                #include "genprec.h"

     The variables prec10 and prec are calculated by 
     GENPREC from the value assigned to precision.


                                    -3-






     It is imagined that users will actually view results by 
     converting back to floating point at the end. However, a 
     facility is provided for printing output in base 10 when all 
     of the digits are of interest. There may be occasions when 
     one would like to know only the sign of a result (for 
     example in branching). In this case one would check the sign 
     of the Nth element of the internal array. Or there may be 
     occasions when one would like to know if a result is zero.
     Again, only the Nth element of the array needs to be checked
     since if this element is zero the result is zero.

     Complex numbers are internally represented as 2xN two 
     dimensional arrays. The zeroth element in the second 
     dimension is the real part and the first element is the 
     imaginary part (in the case of polar representation the 
     zeroth element is the radius and the first element is the 
     angle).

     SECTION 2.1  NEW VARIABLE TYPES DEFINED IN GENPREC.

     Six new variable types (or objects) are defined in Genprec 
     in zclasses.h and cclasses.h.  These new types are

     realscalar                       complexscalar
     realvector                       complexvector
     realmatrix                       complexmatrix

     A scalar is a 0-dimensional array,a vector is a 1-dimensional array
     whose last component is numbered n (the numbering may begin with 0
     or 1), and a matrix is an 2-dimensional n x n array. The words 
     "real" and "complex" refer to the components of these objects.

     By the size of these objects we mean 0 for the scalar,n for vectors,
     and the larger of n (not n^2 as one might expect) for matrices.

     These variable types extends the list of variable types 
     short int, int, float,double, etc. which occur in C/C++.


     SECTION 2.2 DECLARATION OF USER DEFINED VARIABLES

     The way in which variables a,b,c,d,e,f are declared to be one
     of these types is:

realscalar a_ram; int *a=a_ram.s;           //declares a to be realscalar
realvector b_ram; int * *b=b_ram.v;         //         b       realvector
realmatrix c_ram; int * * *c=c_ram.m;       //         c       realmatrix
complexscalar d_ram; int * *d=d_ram.cs;     //         d       complexscalar
complexvector e_ram; int * * *e=e_ram.cv;   //         e       complexvector
complexmatrix f_ram; int * * * *f=f_ram.cm; //         f       complexmatrix

     the mnemonics used here (the third line, for example) are 







                                 -4-






     realmatrix c_ram;  assigns c to be of realmatrix type and
                        allocates the memory (ram) which c will 
                        require based on the precision and zmaxsize 
                        (or cmaxsize) requested
     int * * *c = c_ram.m;  assures that c points to the ram allocated 
                            for c and reconfirms that the allocation was 
                            of realmatrix type (.m).

     The reconfirmations .s .v .m .cs .cv .cm (s v and m are mnemonics 
     for scalar,vector,and matrix respectively and c is a mnemonic for 
     complex) must not be omitted. 
     
     Multiple precision variables are declared before the program main.  
     after the include statements.

     The user may define other types (classes) by adding their definition
     to the file zclasses.h following as examples the definitions of the
     above six classes in zclasses.h and cclasses.h. 
     
     Genprec accomodates objects of different sizes but it allocates the
     same memory for a small object that it would have had the small 
     object been of the same size as the largest object in the code.
     However, the memory allocated for real vectors and matrices and  
     complex vectors and matrices depend on zmaxsize and cmaxsize 
     respectively and since these may be different some memory is saved.
     C++ itself accomodates only two sizes (short int and int, for example,
     or float and double.)  Short objects could be defined in zclasses.h
     and cclasses.h but we have not done it.

     Note that the coefficients in polynomials and power series form
     vectors (1-dimensional arrays numbered from 0 which causes no problems
     in genprec since memory is allocated for the 0th position).  

     The i-th (or i,j-th) components of a vector (or matrix) are
     
     b[i]                      e[i]
     c[i][j]                   f[i][j]

     Any statement about real scalar a  is equivalent to a statement
     about b[i] or c[i][j] (with a similar remark about d,e[i],and 
     f[i][j]). The following summarizes these equivalences: 
     
              real MP number: a or b[i] or c[i][j].  
              complex MP number: d or e[i], or f[i][j].
              real MP vector: b or c[i]     //these latter two are
              complex MP vector: e or f[i]  //not of much use
     
     These quantities are passed to subroutines in the usual C/C++
     fashion. For example, the protype for a user defined subroutine f 
     might be f(  ,  ,int * asub,  ).   The subrourtine would be 
     called by f(  ,  ,a,  ). 
     
     The examples in genlinex.cpp and cgnlinex.cpp illustrate these points.
                                  

                                 
                                 
                                 
                                 
                                 -5-






     SECTION 3. THE GENPREC PACKAGE AND THE DEPENDENCE TREE

     The GENPREC package consists of include files for doing 
     multiple precision calculations of the following types.

                                            REAL       COMPLEX

     Arithmetic (including the elementary   genprec.h  cgenprec.h
     transcendental functions
     Solving Linear Systems                 genlin.h   cgenlin.h
     Solving Polynomials                    poly.h     cpoly.h
     Manipulating Power Series              series.h   cseries.h
     Forming Pade approximants (*) to       pade.h     cpade.h
     Power Series

     * A Pade approximant is a ratio of polynomials. The n1,n2 
     Pade approximant has a polynomial of degree n1 in the 
     numerator and n2 in the denominator.

     The notation means (for example) that if one wants to solve 
     a polynomial with complex coefficients one includes cpoly.h.

     Including one package (such as cpoly.h) may require 
     inclusion of other packages according to the following 
     dependence tree:

                       GENPREC DEPENDENCE TREE

           include files <> 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<prec10;i++) zinput[i] = 0;
     zinput[precision]=3141;
     zinput[precision-1]=5926;
     zinput[precision-2]=5358;
     zinput[precision-3]=9793;
     zinput[precision-4]=2384;
     zinput[0]=1;
     zconinputtomp(zinput);
     zstore(a);           //this last line stores result in a


                                  
                                  -10-







     Another way of accomplishing this is to use the DOS editor to create 
     a file named filename.dat (or any other name) containing the above 
     data on successive lines: 
                          3141   //the number of entries must = precision
                          5926
                          .
                          .
                          .
                          1      //plus one (the last is the exponent)
     Then, the user code would contain            

     #include <fstream.h>  //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 <fstream.h>      //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<<z[i]<<'\n';  //current directory
     myfileout.close();
      .
      .       //in this or any other code to read the myfile stored above        
     myfilein.open("myfile.dat", ios::in);    //see note above
     for (i=prec;i>=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<prec+1;i++) 
              {myfileout<<cz[0][i]<<'\n';  
               myfileout<<cz[1][i]<<'\n';}
     and the second for statement by
            for (i=0;i<prec+1;i++) 
              {myfilein>>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 <iostream.h>
     #include <stdio.h>
     #include <stdlib.h>
     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 <iostream.h>
     #include <stdio.h>
     #include <stdlib.h>
     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 <iostream.h>
     #include <stdio.h>
     #include <stdlib.h>
     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<size+1;i++
           {
           for (j=1;j<size+1,j++)
              {
              zconinttomp(i*j);
              zstore(a[i][j]);       
              zconinttomp(i+j);        
              zstore(b[i][j]);
              }
           }
        for (i=1;i<size+1;i++)
           {
           for (j=1;j<size+1;j++)
              {
              zzero(c[i][j]);
              for (k=1;ksize+1;,k++)
                 {
                 zmult(a[i][k],b[k][j]);
                 zadd(z,c[i][j]);     
                 zstore(c[i][j];
                 }
              }
           }
        return(0);
        }                             
                                  
























                                  -19-










                                          size
     The above example calculates c(i,j)= SUM a(i,k)*b(k,j), the usual rule 
                                          k=1
     for multiplying matrices.

     Example 4: Branching. This simple example prints which is 
     greater the multiple precision variable "a" or "b". In the 
     example, "a" is set to 1 and "b" is set to 2. In a real 
     example "a" and "b" would be the result of a calculation.

     #include <iostream.h>
     #include <stdio.h>
     #include <stdlib.h>
     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<<zf<<'\n'; may be redirected to printer 
                 or disk file.

     zprnt(a)

         input: real MP number a
         function: prints a in base 10 to the user specified 
                   precision
         output: the printout (may be redirected to printer or diskfile)

     zconftomp(a)

         input: real, double precision C++ number (type double) a
         function: converts a to a real MP number
         output: z           

     zarcsin(a)    (requires zsuppi();)

         input: real MP number a
         function: arcsin(a)
         output: z

     zee()         (requires zsupe(); zsuplogsp();)

         input: none
         function: rounds the value of e calculated by zsupe();
                   to the current precision
         output: z



                                  -26-










     zlogsp()      (requires zsupe(); zsuplogsp();)

         input: none
         function: rounds the value of logbase10(e) calculated by 
                   zsupe(); to the current precision
         output: z

     zexp(a)      (requires zsupe(); zsuplogsp();)

         input: real MP number a
         function: e^a
         output: z

     zln(a)      (requires zsupe; zsuplogsp();)

         input: real MP number a
         function: log_base_e(a)
         output: z

     zarctan(a)    (requires zsuppi();)

         input: real MP number a
         function: arctan(a)
         output: z

     zxtonth(a,n)

         input: real MP number and integer n
         function: a^n
         output: z

     Notes:

     zsinh(a) and zcosh(a) are included in cgenprec.h and require 
     zsupe() and zsuplogsp().




















                                  -27-
     






     SECTION 11.2 cgenprec.h

     cprnt(a)

         input: a complex MP number a
         function: prints a in base 10 to the user specified 
                   precision the real and imaginary parts appear 
                   on successive lines
         output: the printout.  May be redirected to printer or a 
                                disk file.

     cstore(a)

         input: cz
         function: stores cz as a
         output: none (cz is not changed)

     crecall(a)

         input: none
         function: recalls complex MP number to register cz
         output: cz (a is not changed)

     crecip(a)

         input: complex MP number in rectangular representation
         function: calls 1/a to cz register.
         output: cz in rectangular representation. original a is 
                                                   not changed. 
     cchs(a)

         input: complex MP number in rectangular representation
         function: calls -a to cz register.
         output cz in rectangular coordinates. a is not changed.
         Note : This function differs from zchs(a)

     cchspol(a)

         input: complex MP number in polar representation
         function: recalls -a to cz register.
         output: cz in polar representation.  a is not changed.

     cadd(a,b)

         input: complex MP numbers a,b in rectangular representation
         function: a+b
         output: cz in rectangular representation

     csub(a,b)

         input: complex MP numbers a,b in rectangular representation
         function: a-b
         output: cz in rectangular representation


                                  
                                  
                                  
                                  -28-










     cmult(a,b)

         input: complex MP numbers a,b in rectangular representation
         function: a*b
         output: cz in rectangular representation

     cmultpol(a,b)

         input: complex MP numbers a,b both in polar representation
         function: a*b
         output: cz in polar representation

     cdiv(a,b)

         input: complex MP numbers a,b in rectangular representation
         function: a/b
         output: cz in rectangular representation

     cdivpol(a,b)

         input: complex MP numbers a,b both in polar representation
         function: a/b
         output: cz in polar representation

     cabs(a)

         input: complex MP number a in rectangular coordinates
         function: calls |a| to z register
         output: z a real MP number.  a is not changed.

     ccompconj(a)

         input: complex MP number a in rectangular
         function: calls a* to cz register
         output: cz in rectangular.  a is not changed.

     ccompconjpol(a)

         input: complex MP number a in polar representation
         function: calls a* to cz register.
         output: cz in polar. a is not changed. 

     crectopol(a)       (requires zsuppi();)

         input: complex MP number a in rectangular
         function: convert to polar
         output: cz in polar. a is not changed.

     cpoltorec(a)      (requires zsuppi();)

         input: complex MP number a in polar
         function: convert to rectangular
         output: cz in rectangular. a is not changed.


                                  -29-










     cxtonthpol(a,n)

         input: complex MP number in polar and integer n
         function: a^n
         output: cz in polar

     zsinh(a)        (requires zsupe(); zsuplogsp();)

         input: real MP number a
         function: sinh(a)
         output: z

     zcosh(a)        (requires zsupe(); zsuplogsp();)

         input: real MP number a
         function: cosh(a)
         output: z

     csin(a)        (requires zsuppi(); zsupe(); zsuplogsp();)

         input: complex MP number a in rectangular
         function: sin(a)
         output: cz in rectangular

     ccos(a)        (requires zsuppi(); zsupe(); zsuplogsp();)

         input: complex MP number a in rectangular
         function: cos(a)
         output: cz in rectangular

     clogofpolinrec(a) (requires zsupe(); zsuplogsp();)

         input: complex MP number in polar
         function: log(a)
         output: cz in rectangular

     cln(a)        (requires zsuppi(); zsupe(); zsuplogsp();)

         input: complex MP number a in rectangular
         function: log(a)
         output: cz in rectangular

     cexp(a)        (requires zsuppi(); zsupe(); zsuplogsp();)

         input: complex MP number a in rectangular
         function: e^a
         output: cz in rectangular








                                  -30-










     carctan(a)    (requires zsuppi(); zsupe(); zsuplogsp();)

         input: complex MP number a in rectangular
         function: arctan(a)
         output: cz in rectangular

     cconinttomp(n1,n2)

         input: integers n1 and n2
         function: express n1 + i*n2 (or n1e^(i*n2)) in MP
         output: cz in rectangular (or polar)

     czero(a);

         input: name of complex MP number a
         function: a=0
         output: none

     cmultint(a,n)

         input: complex MP number a in rectangular and real 
                integer n
         function: a*n
         output: cz in rectangular

     cdivint(a,n)

         input: complex MP number a in rectangular and real 
                integer n
         function: a/n
         output: cz in rectangular

     cmultcbyr(a,f)

         input: complex MP number a in rectangular and real 
                MP number f
         function: a*f
         output: cz in rectangular

     cdivcbyr(a,f)

         input: complex MP number a in rectangular and real 
                MP number f
         function: a/f
         output: cz in rectangular

     caddcplusr(a,f)

         input: complex MP number a in rectangular and real 
                MP number f
         function: a+f
         output: cz in rectangular


                                
                                  -31-










     cexpitheta(f)    (requires zsuppi();)

         input: a real MP number f
         function: e^(i*f)
         output: cz in rectangular

     csqrt(a)

         input: a complex MP number a in rectangular
         function: sqrt(a)
         output: cz in rectangular

     csqrtpol(a)

         input: a complex MP number a in polar
         function: sqrt(a)
         output: cz in polar






































                                  -32-










     SECTION 11.3 EXAMPLES OF FUNCTIONS WHICH CAN BE DERIVED FROM 
     IDENTITIES

     While the above functions are fairly exhaustive the user may 
     have to derive further functions using identities such as 
     the following:

     csinh(cz) = csin(i*cz)/i

     ccosh(cz) = ccos(i*cz)

     carctanh(cz) = carctan(i*cz)/i

     carcsinh(cz) = carctan(i*cz/csqrt(1+cz^2))/i

     carccosh(cz) = carctan(sqrt(1+cz^2)/(i*cz))

     where cz is any complex MP number and i=sqrt(-1).

     SECTION 11.4 genlin.h

     zsolvlin(n,a,r)

         input: integer n
                nxn array of real MP numbers a
                vector (of length n) of real MP numbers r
         function: solve the nxn linear system ax=r
         output: wx, a vector (of length n) of real MP numbers 

     SECTION 11.5 cgenlin.h

     csolvlin(n,a,r)

         input: integer n
                nxn array of complex MP numbers a
                vector (of length n) of complex MP numbers r
         function: solve the nxn linear system ax=r
         output:cwx, a vector (of length n) of complex MP numbers
















                                  
                                  -33-










     SECTION 11.6 poly.h   

     solvpoly(n,a)  (requires zsupe(); zsuplogsp();)

         input: integer n
                array of real MP numbers a (the coefficients of 
                the polynomial numbered from 0)
         function: find the roots of the polynomial
         output: ynpasses = the number of roots counting complex
                            conjugate pairs as one root
                 ymess[i] i= 1 to ynpasses where 
                     ymess = 2 if the root is real
                     ymess = 3 if the root is complex
                 yxroot[i] for i= 1 to ynpasses is the real part
                 yyroot[i] for i= 1 to ynpasses is the magnitude
                     of the complex part (complex roots are 
                     always in conjugate pairs)

     multiplyout()

         input: assumes the output of solvpoly
         function: multiplies out (x-r1)*(x-r2)*...*(x-rn)
                       = x^n - (r1+r2+...+rn)x^(n-1) + ...
                   so that it can be checked that the 
                   coefficients of the various powers of x are 
                   those input to solvpoly
         output: yb[i] i= 0 to n

     multpolys(n1,a,n2,b)

         input: polynomial a (with real MP coefficients) of order n1
                polynomial b (with real MP coefficients) of order n2
                note: numbering starts from 0
         function: a*b, a polynomial (with real MP coefficients) of 
                        order n1+n2 
         output: yb[i] i = 0 to n1+n2 

     notes: since a polynomial of degree n and a power series truncated at
            the nth term are the same thing, including series.h adds these 
            facilities for the manipulation of polynomials:

     evaluating a polynomial: use commands described in note for seval(n,a)
     multiplying a polynomial by a real MP factor: use smultfac(n,a,f)
     storing a polynomial: use sstoreit(n,a,b)
     differentiation of a polynomial: use sder(n,a)
     converting a real polynomial to a complex polynomial: use scontoc(n,a) 








                                 
                                 -34-










     SECTION 11.7 cpoly.h   

     csolvpoly(n,a)  (requires zsupe(); zsuplogsp();)

         input: integer n
                array of complex MP coefficients a
         function: find the roots of the polynomial
         output: croot[i], i = 1 to n 

     Note: This program may fail if there exist multiple roots or 
           complex conjugate pairs of roots !

     cmultiplyout()

         input: assumes the output of csolvpoly
         function: multiplies out (x-r1)*(x-r2)*...*(x-rn)
                       = x^n - (r1+r2+...+rn)x^(n-1) + ...
                   so that it can be checked that the 
                   coefficients of the various powers of x are 
                   those input to solvpoly
         output: cyb[i] i= 0 to n 

     cmultpolys(n1,a,n2,b)

         input: polynomial a (of degree n1) with complex MP coefficients
                polynomial b (of degree n2) with complex MP coefficients
         function: a*b (of degree n1+n2) with complex MP coefficients
         output: cyb[i] i=0 to n1+n2 

     notes: see the notes at the end of the section poly.h:
     evaluation of complex polynomials: use cseval(n,a,z)
     differentiation of complex polynomials: use csder(n,a)
     multiplication of complex polynomials by a complex: use csmultfac(n,a,f)
     storing a complex polynomial: use csstorit(n,a,b)





















                                  -35-










     SECTION 11.8 series.h    

     sadd(n,a,b) 

         input: integer n, the length of the series a and b with
                real MP coefficients numbered from 0
         function: a + b to length n
         output: sout, a series with real MP coefficients of
                 length n 

     ssub(n,a,b) 

         input: integer n, the length of the series a and b with
                real MP coefficients
         function: a - b to length n
         output: sout, a series with real MP coefficients of
                 length n 

     smult(n,a,b)

         input: integer n, the length of the series a and b with
                real MP coefficients
         function: a*b to length n
         output: sout, a series with real MP coefficients of                  
                 length n 

     sdiv(n,a,b)  There is no such command.  To accomplish its equivalent 
                  use the following commands: 
                          zconinttomp(-1);
                          zstore(p);  //p must be declared, of course 
                          stonth(n,b,p);
                          smult(n,a,sout); 
                  The output is sout.

     stonth(n,a,f)

         input: integer n
                series a with real MP coefficients numbered from 0
                real MP number f
         function: a^f
         output: sout, a series with real MP coefficients of
                 length n.

     smultfac(n,a,f)

         input: integer n
                series a with real MP coefficients
                real MP number f
         function: a*f
         output: sout, a series with real MP coefficients of
                 length n 




                                  -36-






     
     sstorit(n,a,b)

         input: integer n, the length of the series
                series a with real MP coefficients numbered from 0
         function: stores a as b
         output: none

     sder(n,a)
    
         input: integer n, the length of the series 
                series a with real MP coefficients
         function: da/dx
         output: sout (of length one less than n, of course)      

     slogder(n,a)

         input: integer n, the length of the series
                a with real MP coefficients
         function: d(log a)/dx = (da/dx)/a 
         output: sout (of length one less than n, of course)

     scontoc(n,a)  requires cgenprec.h

         input: integer n, the length of the series
                a with real MP coefficients
         function: converts this to a complex series soutc with complex
                   coefficients whose imaginary parts are zero
         output: soutc (with complex MP coefficients and of length n)

     seval(n,a,b)  (to evaluate a series for complex b 
                    see note immediately below)

         input: integer n, the length of the series a with real MP 
                coefficients and a real MP point b at which the series 
                is to be evaluated

         function: a(b) 
         output: z=a(b) 

     note:  To evaluate a real series a for a complex value of b first 
            convert a to a complex series as follows
                                scontoc(n,a);
            and then evaluate the output complex series soutc:
                                cseval(n,soutc,b);  (requires cseries.h)
            The output is cz=a(b).  

     sinvert(n,a)

            input: integer n, the lenth of series a with real MP
                   coefficients.
            function: let a=a0 +a1*x + a2*x^2 + ... + an*x^n.
                   the function is to determine coefficients x1,...,xn
                   such that
                          x=x1*(a-a0) + x2*(a-a0)^2 + ... +xn*(a-a0)^n
            output:  sout[i], the xi, i=1 to n.
             


                                    -37-






     ssubstitute(n,x,b)

            input: integer n, the length of the series x and b both with
                   real MP coefficients

            function:  let x=x1*t + x2*t^2 +.....+ xn*t^n
                           b=b0 + b1*x + b2*x^2+..+ bn*x^n

                   substitutes series x(t) into series b
                   
                           b=c0 + c1*t + c2*t^2 + ...+ cn*t^n 

                   (if the first term in x,that is x0, is not 0 
                   then x-x0 is substituted into b).

            output: sout[i], the ci, i=0 to n/

     SECTION 11.9 cseries.h   

         Same as series.h, except that command names begin with c,
         the output is cz or csout. There is no analog of scontoc (none 
         is needed).
   
     SECTION 11.10 pade.h   

     padeapprox(n1,n2,a)

         input: integers n1,n2
                series a of length n1+n2 with real MP coefficients  
         function: forms the (n1/n2) Pade approximant to a
         output: pnum[i], the real MP coefficients of the 
                          numerator polynomial,i=0 to n1
                 pden[i], the real MP coefficients of the 
                          denominator polynomial, i=0 to n2

     SECTION 11.11 cpade.h

     cpadeapprox(n1,n2,a)
 
         input: integers n1,n2
                series a of length n1+n2 with complex MP coefficients
         function: forms the (n1/n2) Pade approximant to a
         output: cpnum[i], the complex MP coefficients of the 
                           numerator polynomial,i=0 to n1
                 cpden[i], the complex MP coefficients of the 
                           denominator polynomial,i=0 to n2













                                  -38-


