⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 davison.c

📁 calc大数库
💻 C
字号:
#include "integer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<c & b>d) or (c<a & d>b) 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<c & b>d) or (c<a & d>b) 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));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -