\title{Appendix C: A complete program}

We give here the listing of the program seen in detail in \secref{se:prog},
with the slight modifications explained at the end of that section.
%
\bprog
\#include <genpari.h>
\h
GEN matexp(GEN x, long prec);
\h
main()
\obr
\q GEN x, y;
\q long d, prec = 3;
\q char s[512];
\h
\q init(1000000,2); /* take a stack of a million bytes, no prime table */
\q printf("precision of the computation in decimal digits? ");
\q scanf("\%d",\&d); if (d>0) prec = (long)(d*pariK1+3);
\h
\q printf("input your matrix in GP format:\bs n");
\q s[0]=0; while (!s[0]) gets(s);
\q x = flisexpr(s); y = matexp(x,prec);
\q sor(y,'g',d,0);
\cbr 
\h
GEN matexp(GEN x, long prec)
\obr
\q  long lx=lg(x),i,k,n, ltop = avma;
\q  GEN y,r,s,p1,p2;
\h
\q /* check that x is a square matrix */
\q if (typ(x) != t\_MAT) err(talker,"this expression is not a matrix");
\q if (lx == 1) return cgetg(1, t\_MAT);
\q if (lx != lg(x[1])) err(talker,"not a square matrix");
\h
\q /* convert x to real or complex of real and compute its L2 norm */
\q s = gzero; r = cgetr(prec+1); gaffsg(1,r); x = gmul(r,x);
\q for (i=1; i<lx; i++)
\q\q s = gadd(s, gnorml2((GEN)x[i]));
\q if (typ(s) == t\_REAL) setlg(s,3);
\q s = gsqrt(s,3); /* we do not need much precision on s */
\h
\q /* if s<1, we are happy */
\q k = expo(s);
\q if (k < 0) \obr\ n = 0; p1 = x; \cbr 
\q else \obr\ n = k+1; p1 = gmul2n(x,-n); setexpo(s,-1); \cbr 
\h
\q /* initialisations before the loop */
\q y = gscalmat(r,lx-1); /* creates scalar matrix with r on diagonal */
\q p2 = p1; r = s; k = 1;
\q y = gadd(y,p2);
\h
\q /* now the main loop */
\q while (expo(r) >= -BITS\_IN\_LONG*(prec-1))
\q\obr
\q\q k++; p2 = gdivgs(gmul(p2,p1),k);
\q\q r = gdivgs(gmul(s,r),k); y = gadd(y,p2);
\q\cbr 
\h
\q /* now square back n times */
\q for (i=0; i<n; i++) y = gsqr(y);
\q return gerepileupto(ltop,y);
\cbr 
\eprog\vfill\eject
