As already mentioned, modified versions of the PARI package should NOT be spread without our prior approval. If you do modify PARI, however, it is certainly for a good reason, hence we would like to know about it, so that everyone can benefit from it. There is then a good chance that the modifications that you have made will be incorporated into the next release.
(Recall the e-mail: pari@alioth.greco-prog.fr).
Roughly 3 types of modifications can be made. The first type is to modify the code, include files and the Makefile so that compilation is possible on a new system.
The second type is to modify existing code, either to correct bugs, to add new functionalities, or to improve efficiency.
Finally the third type is to add new functions to Pari. We explain here how to do this, so that in particular the new function can be called from GP.
First choose the appropriate file where you are going to code your function. For example alglin1.c or alglin2.c if it is a function dealing with vectors or matrices (linear algebra), trans1.c, trans2.c, trans3.c if it is a transcendental function, arith1.c or arith2.c if it is an arithmetic function, bibli1.c or bibli2.c for miscellaneous functions, etc... Note that the files gp.c, mp.c and versionXXX.c as well as the assembly files have a special role and should not be modified.
Then code your function, using as a guide other functions in the Pari sources. One important thing to remember is to always clean the stack before exiting your function (usually using the function gerepile) otherwise the successive calls to the function will clutter the stack with unnecessary garbage and stack overflow will occur sooner.
If error messages are to be generated in your function, use the general error handling routine err. Initially, use the syntax
err(talker,error message);
where error message is the message that you want printed. This function does not return, but ends with a longjmp statement.
Once the program is debugged, you can replace the above line by
err(errornumber);
where errornumber must be defined in the file erreurs.h, and the corresponding error message must be placed at the corresponding spot in the file errmessages.c. A look at these two files will tell you exactly what to do. Note however that to have the correct numbering of errors once again, hence the correct error messages, you must recompile the complete Pari distribution (for example after touch *.[chs]). This is not necessary if you use the talker syntax.
Finally, find the correct place in the file gencom.h to declare your function so that it is known to all other files and functions.
Your function is now ready to be used in library mode after compilation and creation of the library. It is however still inaccessible from GP.
To make your function accessible to GP, you must do the following. First, find a name for your function under GP, which does not have to be identical to the one used in library mode, but must use only lower case alphabetic characters and digits, the first character as usual being alphabetic. Then in the file anal.c place in exact alphabetical order of the name that you want to use under GP the following line (note that digits<letters):gpname,V,(void*)libname,0,
where libname is the name of your function in library mode, gpname the name that you have chosen to call it under GP, and V is a number between 0 and 99, chosen so as to correspond to the type of the function and its arguments. The first digit identifies the number of arguments, not counting the variable prec.
The most common values for V are the following, expressed as C-function prototypes. You can find the others by looking at the function identifier in the file anal.c. Note that the parameter prec (which denotes the real precision) is included in most of the given prototypes, but can be omitted if the function does not use it. Note also that we implicitly identify int with long.
V=0: GEN name(long prec); V=1: GEN name(GEN x, long prec); V=2: GEN name(GEN x, GEN y, long prec); V=3: GEN name(GEN x, GEN y, GEN z, long prec); V=10: long name(GEN x); V=11: GEN name(long x,long prec); V=15: long name(long x); V=20: long name(GEN x, GEN y); V=23: GEN name(GEN x, long y, long prec); V=24: GEN name(long x, GEN y, long prec); V=29: long name(GEN x, long y); V=30: long name(GEN x, GEN y, GEN z); V=32: GEN name(GEN x, GEN y, long z); V=33: GEN name(GEN x, long y, long z); V=35: GEN name(long x, GEN y, GEN z);
If your function does not correspond to any of the above prototypes, or to the few others which you can find in the function identifier, you can make up your own. The best at this point is to read the code for the existing values of V, and to modify it according to your needs. One important point must be stressed if you add a value of V to the function identifier: you must also correspondingly add it to the function skipidentifier. Read the code for that function to see how to proceed. Once this has been done, in the file helpmessages.c write in exact alphabetical order a short message describing the effect of your function:name(x,y,...)=short descriptive message,
The message must be a single line (which may have more than 80 characters). If the printed message would be more than one line, insert n as appropriate (see the other messages for comparative purposes).
Finally create (or append to) a file called, say, Mychanges, which lists the modifications that you have made. Never touch the file Changes itself otherwise you would corrupt the Pari distribution. After compiling and debugging, you now have a new function available under GP (and we would very much like to hear about it!).