www.pudn.com > calc.rar > davison.c
#include "integer.h" #include#include #include #include "fun.h" #include "stack.h" /*#include "unistd.h"*/ MPI *GLOBALA; MPI *GLOBALB; MPI *GLOBALC; MPI *GLOBALD; USL count, flagl, flagr, globalr, globall; char buff[20]; FILE *outfile; USL POSITIVITY(MPI *A, MPI *B, MPI *C, MPI *D){ if(A->S >= 0 && B->S >= 0 && C->S >= 0 && D->S >= 0){ return(1); }else{ return(0); } } /* NPROD(l,m) finds the least n such that A_n and D=A_0...A_n are * non-negative. * The matrix of global variables D=[GLOBALA,GLOBALB,GLOBALC,GLOBALD] is * returned along with n. See Proposition 4.1, J.L. Davison, 'An algorithm for * the continued fraction of e^{l/m}', Proceedings of the Eighth Manitoba * Conference on Numerical Mathematics and Computing (Univ. Manitoba, Winnipeg, * 1978), 169--179, Congress. Numer., XXII, Utilitas Math. */ USL NPROD(USL l,USL m){ USL k, s, temp; MPI *TEMPM, *TEMPL, *T, *TEMP1, *TEMP2, *A1, *B1, *C1, *D1; MPI *TEMP, *T1, *T2; TEMPM = CHANGE(m); TEMPL = CHANGE(l); temp = m + l; GLOBALA =CHANGE(temp); GLOBALB = CHANGE(m); GLOBALC = CHANGE(m); GLOBALD = SUBI(TEMPM, TEMPL); for(k = 1; 1; k++){ s = POSITIVITY(GLOBALA, GLOBALB, GLOBALC, GLOBALD); if(s) break; T = CHANGE((2 * k + 1) * m); T1 = ADDI(GLOBALA, GLOBALB); T2 = ADDI(GLOBALC, GLOBALD); TEMP1 = MULTI(T, T1); TEMP2 = MULTI(T, T2); FREEMPI(T); FREEMPI(T1); FREEMPI(T2); TEMP = MULTI(GLOBALA, TEMPL); A1 = ADDI(TEMP1, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALB, TEMPL); B1 = SUBI(TEMP1, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALC, TEMPL); C1 = ADDI(TEMP2, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALD, TEMPL); D1 = SUBI(TEMP2, TEMP); FREEMPI(TEMP); FREEMPI(TEMP1); FREEMPI(TEMP2); TEMP = GLOBALA; GLOBALA = A1; FREEMPI(TEMP); TEMP = GLOBALB; GLOBALB = B1; FREEMPI(TEMP); TEMP = GLOBALC; GLOBALC = C1; FREEMPI(TEMP); TEMP = GLOBALD; GLOBALD = D1; FREEMPI(TEMP); } FREEMPI(TEMPL); FREEMPI(TEMPM); return(k - 1); } MPI *REFINE(MPI *A, MPI *B, MPI *C, MPI *D){ MPI *G, *TEMP; G = GCD(A, B); TEMP = G; G = GCD(G, C); FREEMPI(TEMP); TEMP = G; G = GCD(G, D); FREEMPI(TEMP); return(G); } /* Raney factorization - G.N. Raney, Math, Annalen 206 (1973) 265-283. * Input: a non-singular matrix A=[p,q;r,s], p,q,r,s>=0, A!=I_2, A!=[0,1;1,0]. * With L=[1,0;1,1] and R=[1,1;0,1], we express A uniquely as * a product of non-negative powers of L and R, (at least one is positive) * followed by a row-balanced B. * B=[a,b;c,d] is row-balanced if (a d) or (cb) and a,b,c>=0. * The number k of powers of L and R is returned. */ USL RANEY(MPI *P, MPI *Q, MPI *R, MPI *S){ USL k, i, j; MPI *PP, *QQ, *RR, *SS, *TEMP; PP = COPYI(P); QQ = COPYI(Q); RR = COPYI(R); SS = COPYI(S); k = 0; while(1){ i = 0; while(COMPAREI(PP, RR)>= 0 && COMPAREI(QQ, SS) >= 0){ TEMP = PP; PP = SUBI(PP, RR); FREEMPI(TEMP); TEMP = QQ; QQ = SUBI(QQ, SS); FREEMPI(TEMP); i++; } if(i > 0){ globalr = globalr + i; flagr = 1; if(flagr * flagl){ flagl = 0; printf("a[%lu]:%lu\n", count, globall); fprintf(outfile, "a[%lu]:%lu\n", count, globall); globall = 0; count++; } k++; } j = 0; while(COMPAREI(RR, PP) >= 0 && COMPAREI(SS, QQ) >= 0){ TEMP = RR; RR = SUBI(RR, PP); FREEMPI(TEMP); TEMP = SS; SS = SUBI(SS, QQ); FREEMPI(TEMP); j++; } if(j > 0){ globall = globall + j; flagl = 1; if(flagr * flagl){ flagr = 0; printf("a[%lu]:%lu\n", count, globalr); fprintf(outfile, "a[%lu]:%lu\n", count, globalr); globalr = 0; count++; } k++; } if((COMPAREI(PP, RR) < 0 && COMPAREI(QQ, SS) > 0) || (COMPAREI(PP, RR) > 0 && COMPAREI(QQ, SS) < 0)){ break; } } TEMP = GLOBALA; GLOBALA = PP; FREEMPI(TEMP); TEMP = GLOBALB; GLOBALB = QQ; FREEMPI(TEMP); TEMP = GLOBALC; GLOBALC = RR; FREEMPI(TEMP); TEMP = GLOBALD; GLOBALD = SS; FREEMPI(TEMP); /*fclose(outfile);*/ return(k); } /* We perform the algorithm of J.L. Davison's paper. * With n > =0, we first find the n* of Davison's Proposition 4.1 * and apply Raney's factorisation to A_0...A_k, for n*<=k<=n*+n. * The number (count) of partial quotients of e^{l/m} found is returned. * count becomes positive for all large n. * We exit the program if count reaches 100000. */ USL DAVISON(USL l, USL m, USL n){ MPI *G, *ONE, *TEMP, *T, *T1, *T2, *TEMP1, *TEMP2; MPI *A1, *B1, *C1, *D1, *TEMPL; USL i, j, k, t; printf("l,m,n=%lu,%lu,%lu\n",l,m,n); strcpy(buff, "davison.out"); outfile = fopen(buff, "w"); count = 0; flagr= 0; flagl= 0; globalr = 0; globall= 0; k = NPROD(l, m); G = REFINE(GLOBALA, GLOBALB, GLOBALC, GLOBALD); ONE = ONEI(); if(RSV(G, ONE)>0){ TEMP = GLOBALA; GLOBALA = INT(GLOBALA, G); FREEMPI(TEMP); TEMP = GLOBALB; GLOBALB = INT(GLOBALB, G); FREEMPI(TEMP); TEMP = GLOBALC; GLOBALC = INT(GLOBALC, G); FREEMPI(TEMP); TEMP = GLOBALD; GLOBALD = INT(GLOBALD, G); FREEMPI(TEMP); } FREEMPI(G); i = k; j =k + n; TEMPL = CHANGE(l); while(i <= j){ if(i > k){ T = CHANGE((2 * i + 1) * m); T1 = ADDI(GLOBALA, GLOBALB); T2 = ADDI(GLOBALC, GLOBALD); TEMP1 = MULTI(T, T1); TEMP2 = MULTI(T, T2); FREEMPI(T); FREEMPI(T1); FREEMPI(T2); TEMP = MULTI(GLOBALA, TEMPL); A1 = ADDI(TEMP1, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALB, TEMPL); B1 = SUBI(TEMP1, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALC, TEMPL); C1 = ADDI(TEMP2, TEMP); FREEMPI(TEMP); TEMP = MULTI(GLOBALD, TEMPL); D1 = SUBI(TEMP2, TEMP); FREEMPI(TEMP); FREEMPI(TEMP1); FREEMPI(TEMP2); TEMP = GLOBALA; GLOBALA = A1; FREEMPI(TEMP); TEMP = GLOBALB; GLOBALB = B1; FREEMPI(TEMP); TEMP = GLOBALC; GLOBALC = C1; FREEMPI(TEMP); TEMP = GLOBALD; GLOBALD = D1; FREEMPI(TEMP); } i++; t = RANEY(GLOBALA, GLOBALB, GLOBALC, GLOBALD); if(count == 1000000){ printf("1000000 partial quotients found\n"); i = j + 1; } /* the input matrix will not be I_2 or [0,1;1,0] here. */ G = REFINE(GLOBALA, GLOBALB, GLOBALC, GLOBALD); if(RSV(G, ONE)>0){ TEMP = GLOBALA; GLOBALA = INT(GLOBALA, G); FREEMPI(TEMP); TEMP = GLOBALB; GLOBALB = INT(GLOBALB, G); FREEMPI(TEMP); TEMP = GLOBALC; GLOBALC = INT(GLOBALC, G); FREEMPI(TEMP); TEMP = GLOBALD; GLOBALD = INT(GLOBALD, G); FREEMPI(TEMP); } FREEMPI(G); } FREEMPI(TEMPL); FREEMPI(ONE); FREEMPI(GLOBALA); FREEMPI(GLOBALB); FREEMPI(GLOBALC); FREEMPI(GLOBALD); fflush(stdout); printf("n* = %lu, n = %lu\n", k, n); fprintf(outfile, "n* = %lu, n = %lu\n", k, n); printf("The number of partial quotients found for e^(%lu/%lu) is %lu\n", l, m, count); fprintf(outfile, "The number of partial quotients found for e^(%lu/%lu) is %lu\n", l, m, count); fclose(outfile); return(count); } MPI *DAVISONX(MPI *L, MPI *M, MPI *N){ USL l, m, n, t; MPI *G, *TEMP, *TEMPL, *TEMPM, *ONE; if(L->S <= 0){ printf("l<=0\n"); return(NULL); } if(M->S <= 0){ printf("m<=0\n"); return(NULL); } if(N->S < 0){ printf("n<0\n"); return(NULL); } TEMP = CHANGEI(1000); if(RSV(L, TEMP) > 0){ printf("l>1000\n"); FREEMPI(TEMP); return(NULL); } if(RSV(M, TEMP) > 0){ printf("m>1000\n"); FREEMPI(TEMP); return(NULL); } FREEMPI(TEMP); TEMP = CHANGEI(100000); if(RSV(N, TEMP) > 0){ printf("n>=10^6\n"); FREEMPI(TEMP); return(NULL); } FREEMPI(TEMP); TEMPL = COPYI(L); TEMPM = COPYI(M); ONE = ONEI(); G = GCD(L, M); if(RSV(G, ONE)>0){ TEMP = TEMPL; TEMPL = INT0(L, G); FREEMPI(TEMPL); TEMP = TEMPM; TEMPM = INT0(M, G); FREEMPI(TEMP); } FREEMPI(G); FREEMPI(ONE); l = CONVERTI(TEMPL); m = CONVERTI(TEMPM); FREEMPI(TEMPL); FREEMPI(TEMPM); n = CONVERTI(N); t = DAVISON(l, m, n); return (CHANGE(t)); } /* Raney factorization - G.N. Raney, Math, Annalen 206 (1973) 265-283. * Input: a non-singular matrix A=[p,q;r,s], p,q,r,s>=0, A!=I_2, A!=[0,1;1,0]. * With L=[1,0;1,1] and R=[1,1;0,1], we express A uniquely as * a product of non-negative powers of L and R, (at least one is positive) * followed by a row-balanced B. * B=[a,b;c,d] is row-balanced if (a d) or (cb) and a,b,c>=0. * The number k of powers of L and R is returned. */ USL RANEY1(MPI *P, MPI *Q, MPI *R, MPI *S){ USL k, i, j; MPI *PP, *QQ, *RR, *SS, *TEMP; char buff1[20]; FILE *outfile1; strcpy(buff1, "raney.out"); outfile1 = fopen(buff1, "w"); printf("["); fprintf(outfile1, "["); PRINTI(P); FPRINTI(outfile1, P); printf(","); fprintf(outfile1, ","); PRINTI(Q); FPRINTI(outfile1, Q); printf(";"); fprintf(outfile1, ";"); PRINTI(R); FPRINTI(outfile1, R); printf(","); fprintf(outfile1, ","); PRINTI(S); FPRINTI(outfile1, S); printf("]="); fprintf(outfile1, "]="); PP = COPYI(P); QQ = COPYI(Q); RR = COPYI(R); SS = COPYI(S); k = 0; while(1){ i = 0; while(COMPAREI(PP, RR)>= 0 && COMPAREI(QQ, SS) >= 0){ TEMP = PP; PP = SUBI(PP, RR); FREEMPI(TEMP); TEMP = QQ; QQ = SUBI(QQ, SS); FREEMPI(TEMP); i++; } if(i > 0){ k++; if(i > 1){ printf("R^%lu", i); fprintf(outfile1, "R^%lu", i); }else{ printf("R"); fprintf(outfile1, "R"); } } j = 0; while(COMPAREI(RR, PP) >= 0 && COMPAREI(SS, QQ) >= 0){ TEMP = RR; RR = SUBI(RR, PP); FREEMPI(TEMP); TEMP = SS; SS = SUBI(SS, QQ); FREEMPI(TEMP); j++; } if(j > 0){ if(j > 1){ printf("L^%lu", j); fprintf(outfile1, "L^%lu", j); }else{ printf("L"); fprintf(outfile1, "L"); } k++; } if((COMPAREI(PP, RR) < 0 && COMPAREI(QQ, SS) > 0) || (COMPAREI(PP, RR) > 0 && COMPAREI(QQ, SS) < 0)){ break; } } printf("D, where D=["); fprintf(outfile1, "D, where D=["); PRINTI(PP); FPRINTI(outfile1, PP); printf(","); fprintf(outfile1, ","); PRINTI(QQ); FPRINTI(outfile1, QQ); printf(";"); fprintf(outfile1, ";"); PRINTI(RR); FPRINTI(outfile1, RR); printf(","); fprintf(outfile1, ","); PRINTI(SS); FPRINTI(outfile1, SS); printf("] is row-balanced\n"); fprintf(outfile1, "] is row-balanced\n"); FREEMPI(PP); FREEMPI(QQ); FREEMPI(RR); FREEMPI(SS); fclose(outfile1); return(k); } MPI *RANEY1X(MPI *P, MPI *Q, MPI *R, MPI *S){ MPI *TEMP1, *TEMP2, *TEMP; USI t; USL k; if(P->S < 0){ printf("P < 0\n"); return(NULL); } if(Q->S < 0){ printf("Q < 0\n"); return(NULL); } if(R->S < 0){ printf("R < 0\n"); return(NULL); } if(S->S < 0){ printf("S < 0\n"); return(NULL); } if(EQONEI(P) && EQZEROI(Q) && EQZEROI(R) && EQONEI(S)){ printf("A = I_2\n"); return(NULL); } if(EQZEROI(P) && EQONEI(Q) && EQONEI(R) && EQZEROI(S)){ printf("A = J = [0,1;1,0]\n"); return(NULL); } TEMP1 = MULTI(P, S); TEMP = CHANGEI(1000); TEMP2 = MULTI(Q, R); t = EQUALI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); if(t){ printf("P*S-Q*R=0\n"); return(NULL); } k = RANEY1(P, Q, R, S); return(CHANGE(k)); } /* * This algorithm expresses a unimodular matrix A !=I_2 or U=[0 1] * [1 0] * with non-negative coefficients, as a product of one of the * following forms: * P, UP, PU, or UPU, where P is a product of matrices of the form * [a 1], a>0. * [1 0] * The representation is unique. See Kjell Kolden, 'Continued fractions * and linear substitutions', Arch. Math. Naturvid. 50 (1949), 141-196. * The number n of matrices in the product [d[0]1]***[d[n-1]1] * is returned. [ 1 0] [ 1 0] */ USL UNIMODULAR(MPI *P, MPI *Q, MPI *R, MPI *S){ USL i; MPI *D, *D1, *D2, *TEMP, *TEMPP, *TEMPQ, *PP, *QQ, *RR, *SS; char buff1[20]; FILE *outfile1; i = 0; strcpy(buff1, "unimodular.out"); outfile1 = fopen(buff1, "w"); printf("["); fprintf(outfile1, "["); PRINTI(P); FPRINTI(outfile1, P); printf(","); fprintf(outfile1, ","); PRINTI(Q); FPRINTI(outfile1, Q); printf(";"); fprintf(outfile1, ";"); PRINTI(R); FPRINTI(outfile1, R); printf(","); fprintf(outfile1, ","); PRINTI(S); FPRINTI(outfile1, S); printf("]="); fprintf(outfile1, "]="); PP = COPYI(P); QQ = COPYI(Q); RR = COPYI(R); SS = COPYI(S); while(1){ if(SS->S == 0){ printf("U["); fprintf(outfile1, "U["); PRINTI(PP); FPRINTI(outfile1, PP); printf("]"); fprintf(outfile1, "]"); fflush(stdout); i++; break; } if(RR->S == 0){ printf("U["); fprintf(outfile1, "U["); PRINTI(QQ); FPRINTI(outfile1, QQ); printf("]"); fprintf(outfile1, "]"); fflush(stdout); i++; printf("U[0]"); fprintf(outfile1, "U[0]"); fflush(stdout); i++; break; } D1 = INT0(QQ, SS); D2 = INT0(PP, RR); D = MINMPI(D1, D2); FREEMPI(D1); FREEMPI(D2); TEMPP = PP; PP = RR; TEMP = MULTI(D, RR); RR = SUBI(TEMPP, TEMP); FREEMPI(TEMPP); FREEMPI(TEMP); TEMPQ = QQ; QQ = SS; TEMP = MULTI(D, SS); SS = SUBI(TEMPQ, TEMP); FREEMPI(TEMPQ); FREEMPI(TEMP); printf("U["); fprintf(outfile1, "U["); PRINTI(D); FPRINTI(outfile1, D); printf("]"); fprintf(outfile1, "]"); FREEMPI(D); fflush(stdout); i++; } printf("\n"); fprintf(outfile1, "\n"); FREEMPI(PP); FREEMPI(QQ); FREEMPI(RR); FREEMPI(SS); fclose(outfile1); return(i); } MPI *UNIMODULARX(MPI *P, MPI *Q, MPI *R, MPI *S){ USI t1, t2; USL i; MPI *DET, *TEMP1, *TEMP2; if(P->S < 0){ printf("P < 0\n"); return(NULL); } if(Q->S < 0){ printf("Q < 0\n"); return(NULL); } if(R->S < 0){ printf("R < 0\n"); return(NULL); } if(S->S < 0){ printf("S < 0\n"); return(NULL); } TEMP1 = MULTI(P, S); TEMP2 = MULTI(Q, R); DET = SUBI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); t1 = EQONEI(DET); t2 = EQMINUSONEI(DET); FREEMPI(DET); if(EQONEI(P) && EQZEROI(Q) &&EQZEROI(R) &&EQONEI(S)){ printf("A=I_2\n"); return(NULL); } if(EQZEROI(P) && EQONEI(Q) &&EQONEI(R) &&EQZEROI(S)){ printf("A = U = [0,1;1,0]\n"); return(NULL); } if(t1 == 0 && t2 == 0){ printf("matrix is not unimodular\n"); return(NULL); } i = UNIMODULAR(P, Q, R, S); return(CHANGE(i)); }