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

📄 reductio.c

📁 calc大数库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* reduction.c */
#ifdef _WIN32
#include "unistd_DOS.h"
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "integer.h"
#include "fun.h"

extern unsigned long PRIME[];
unsigned int llen;

unsigned int SQUAREFREE_TEST1000(USL n){
	USI i;
	USL temp;
	for(i=0; i <= 167; i++){
		temp = PRIME[i]*PRIME[i];
		if(n % temp == 0)
			return(0);
	}
	return(1);
}

USI global_count;
MPIA GLOBALARRAY_U;
MPIA GLOBALARRAY_V;

unsigned int PERIOD(MPI *D, MPI *U, MPI *V){
	USI j, k, cycle_length;
	MPI *F, *R, *S, *A, *tmp, *tmp1, *tmp2;

	F = BIG_MTHROOT(D, 2);
	k=global_count; /* initially set to 0 in POS() below */
	R = COPYI(U); 
	S = COPYI(V);
	for(j = k; 1; j++){
		tmp = ADD0I(F, R); 
		A = INT0(tmp, S); 
		FREEMPI(tmp);
		tmp = MULTI(A, S); 
		FREEMPI(A);
		tmp1 = R; 
		R = SUB0I(tmp, R);
                FREEMPI(tmp); 
		FREEMPI(tmp1);
                tmp = S; 
		tmp1 = MULTI(R, R);
                tmp2 = SUB0I(D, tmp1); 
		S = INT0(tmp2, S);
                ADD_TO_MPIA(GLOBALARRAY_U, R, j);
                ADD_TO_MPIA(GLOBALARRAY_V, S, j);
                FREEMPI(tmp); 
		FREEMPI(tmp1); 
                FREEMPI(tmp2);
 	
		if (EQUALI(U, R) && EQUALI(V, S)){
                        FREEMPI(R); 
			FREEMPI(S); 
			FREEMPI(F);
			break;
                }
                if(j == R0){
                        FREEMPI(R); 
			FREEMPI(S); 
			FREEMPI(F);
                        execerror("j = R0", "");
                }
	}
	cycle_length = j+1-k;
	global_count=global_count+cycle_length;
        return(cycle_length);
}
	
unsigned int CHECK_UVARRAYS(MPI *U, MPI *V){
	USI i;
	for(i = 0; i < global_count; i++){
		if(EQUALI(U, (GLOBALARRAY_U)->A[i]) && EQUALI(V, (GLOBALARRAY_V)->A[i])){
			return(0);
                }
        }
        return(1);
}

USI POS(MPI *D){
	USI a, b, e, t, z, parity_flag, class_number, x;
	USL d, f; /* d will be restricted to d < 10^6. */
	MPI *A, *B, *C, *TEMP, *F, *G, *H, *I, *J, *K, *L;
	MPI *ONE, *R, *DD;
	int sign, sign1;

	GLOBALARRAY_U = BUILDMPIA();
	GLOBALARRAY_V = BUILDMPIA();
	class_number = 0;
	ONE = ONEI();
	global_count = 0;
	parity_flag = 0;
	d = CONVERTI(D);
        /* creates a fundamental discriminant */
	if((d-1) % 4 != 0){
		d=4*d;
		e=2;
	}else{
		e=1;
	}
	DD = CHANGE(d);
        printf("Creating a complete list of reduced forms of discriminant %lu\n", d);
	F = BIG_MTHROOT(DD, 2);
	f = CONVERTI(F);
	G = INT0_(F, 2);
        for(a=1;a<=f;a++){
			A = CHANGE(a);
			I = MULT_I(A, 2);
			J = MULT_I(A, 4);
                for(b=e;b<=f;b=b+2){
			B = CHANGE(b);
			TEMP = MULTI(B, B);
			H = SUBI(TEMP, DD);
			FREEMPI(TEMP);
			TEMP = MOD(H, J);
			sign = TEMP->S;
			FREEMPI(TEMP);
			if(sign == 0){
			   TEMP = SUBI(F, I);
			   sign1 = COMPAREI(TEMP, B);
			   FREEMPI(TEMP);
	   if((RSV(A, G) <= 0 && sign1 < 0) || (RSV(A, G) > 0 && sign1 >= 0)){
				    R = INT(H, J);
		                    TEMP = ABSI(R);
				    K = GCD(A, B);
				    L = GCD(K, TEMP);
				    FREEMPI(K);
				    FREEMPI(TEMP);
				    t = EQONEI(L);
				    FREEMPI(L);
				    if(t){
					TEMP = MINUSI(H);
					C = INT0(TEMP, J); /* C > 0 */
				        FREEMPI(TEMP);
					TEMP = MULT_I(C, 2);
					x = CHECK_UVARRAYS(B, TEMP);
					if(x){
					    class_number=class_number+1;
					    z=PERIOD(DD,B,TEMP);
					    if(z % 2){
					       parity_flag = 1;
					    }
					    printf("[%u]: (",class_number);
				 	    PRINTI(A);
					    printf(", ");
				 	    PRINTI(B);
					    printf(", ");
				 	    PRINTI(R);
					    printf(")\n");
					}
				        FREEMPI(TEMP);
				        FREEMPI(C);
				    }
				    FREEMPI(R);
				}
			}
			FREEMPI(H); 
			FREEMPI(B);
		}
		FREEMPI(A);
		FREEMPI(I);
		FREEMPI(J);
	}
	if(parity_flag){
              printf("x^2-");PRINTI(D);printf("*y^2=-4 has a solution\n");
        }else{
              printf("x^2-");PRINTI(D);printf("*y^2=-4 has no solution\n");
        }
        printf("h(%lu)=%u\n", d, class_number);
	FREEMPI(ONE);
	FREEMPI(F);
	FREEMPI(G);
	FREEMPI(DD);
	FREEMPIA(GLOBALARRAY_U);
        FREEMPIA(GLOBALARRAY_V);
        return(class_number);
}

MPI *POSX(MPI *D){
	USI class_number, w;
	USL d;
	int t;	
	MPI *ONE, *N, *TEMP;

	d = CONVERTI(D);
	ONE = ONEI();
	t = COMPAREI(D, ONE);
	FREEMPI(ONE);
	if(t <= 0){
                printf(" D <= 1\n");
		return(NULL);
	}
	TEMP = POWER_I (10, 6);
	t = RSV(D, TEMP);
	FREEMPI(TEMP);
	if(t >= 0){
		printf("D >= 10^6\n");
		return(NULL);
	}
	w = SQUAREFREE_TEST1000(d);
	if(w == 0){
                printf("D is not squarefree\n");
                return(NULL);
        }else{
		class_number = POS(D);
		N = CHANGE(class_number);
		return(N);
	}
}

USI NEG(MPI *D, MPI *FLAG, MPI *TABLE_FLAG){
/*
 * This is Henri Cohen's Algorithm 5.3.5, p. 228.
 * for finding the class number h(D) of binary quadratic forms
 * of discriminant D, when D<0.
 * Here D=0(mod 4) or 1(mod 4).
 * If flag=1, we print only the primitive forms.
 * h(D) is returned in each case.
 * Davenport's Higher Arithmetic has a table of forms, which
 * lists the imprimitive ones with an asterisk.
 * If d is the discriminant of an imaginary quadratic field K,
 * then the primitive forms class-number h(D) is also the class number of K.
 * We print forms only when TABLE_FLAG is nonzero.
 */
	MPI *A, *B, *BB, *GG, *GGG, *TEMP, *TEMP1, *ABSD, *ONE;
	MPI *Q, *QQ, *T;
	int t;
	USI g, h;
	USL temp;

	ONE = ONEI();
	h = 0;
	g = 1;
	if(TABLE_FLAG->S){
		if(FLAG->S == 1){
		    printf("determining primitive forms\n");
		}else{
		    printf("determining primitive and imprimitive forms\n");
		}
	}
	temp = MOD_(D, 4);
	if(temp == 0){
                B = ZEROI();
	}else{
                B = ONEI();
	}
	ABSD = MINUSI(D);
	TEMP = INT0_(ABSD, 3);
	BB = BIG_MTHROOT(TEMP, 2);
	FREEMPI(TEMP);
	Q = NULL;
	A = NULL;
	while(RSV(B, BB)<=0){
		TEMP = MULTI(B, B);
		TEMP1 = ADD0I(TEMP, ABSD);
		FREEMPI(TEMP);
		Q = INT0_(TEMP1, 4);
		FREEMPI(TEMP1);
		A = COPYI(B);
		if(RSV(A, ONE) <= 0){
			TEMP = A;
			A = ONEI();
			FREEMPI(TEMP);
		}
		QQ = BIG_MTHROOT(Q, 2);
		while(RSV(A, QQ) <= 0){
			TEMP = MOD0(Q, A);
			t = TEMP->S;
			FREEMPI(TEMP);
			if(t == 0){
				T = INT0(Q, A);
				if(FLAG->S == 1){
					GG = GCD(A, B);
					GGG = GCD(GG, T);
					FREEMPI(GG);
					if(RSV(GGG, ONE) > 0){
						g = 0;
					}
					FREEMPI(GGG);
				}
				if(g == 1){
					if(RSV(A, B)==0 || RSV(A, T)==0 || B->S == 0){
						if(TABLE_FLAG->S){
							printf("(");
							PRINTI(A);
							printf(",");
							PRINTI(B);
							printf(",");
							PRINTI(T);
							printf(")\n");
						}
							h = h + 1;
						}else{
						if(TABLE_FLAG->S){
							printf("(");
							PRINTI(A);
							printf(",");
							PRINTI(B);
							printf(",");
							PRINTI (T);
							printf(")\n");

							printf("(");
							PRINTI(A);
							printf(",");
							TEMP = MINUSI(B);
							PRINTI(TEMP);
							FREEMPI(TEMP);
							printf(",");
							PRINTI(T);
							printf(")\n");
						}
							h = h + 2;
						}
					}else{
						g=1;
					}
				FREEMPI(T);
			}
			TEMP = A;
			A = ADD0_I(A, 1);
			FREEMPI (TEMP);
		}
		FREEMPI(A);
		FREEMPI(QQ);
		FREEMPI(Q);
		TEMP = B;
		B = ADD0_I(B, 2);
		FREEMPI(TEMP);
	}
	FREEMPI(B);
	FREEMPI(BB);
	FREEMPI(ABSD);
	FREEMPI(ONE);
	return(h);
}

MPI *NEGX(MPI *D, MPI *FLAG){
	MPI *ZERO, *H, *TEMP, *ONE;
	USL temp;
	USI h;
	int s, t;

	ZERO = ZEROI();
	ONE = ONEI();
	t = COMPAREI(D, ZERO);
	if(t >= 0){
		printf("D >= 0\n");
		FREEMPI(ZERO);
		FREEMPI(ONE);
		return(NULL);
	}
	TEMP = POWER_I (10, 6);
	s = RSV(D, TEMP);
	FREEMPI(TEMP);
	if(s >= 0){
		printf("|D| >= 10^6\n");
		FREEMPI(ZERO);
		FREEMPI(ONE);
		return(NULL);
	}
	t = COMPAREI(FLAG, ONE);
	if(t > 0){
		printf("flag > 1\n");
		FREEMPI(ONE);
		FREEMPI(ZERO);
		return(NULL);
	}
	t = COMPAREI(FLAG, ZERO);
	FREEMPI(ZERO);
	if(t < 0){
		printf("flag < 0\n");
		FREEMPI(ONE);
		return(NULL);
	}
	temp = MOD_(D, 4);
	if(temp == 2 || temp ==3){
		printf("D is not congruent to 0 or 1 (mod 4)\n");
		FREEMPI(ONE);
		return(NULL);
	}
	h = NEG(D, FLAG, ONE);
	FREEMPI(ONE);
	H = CHANGE((USL)h);
	return(H);
}

USI REDUCE_NEG(MPI *A, MPI *B, MPI *C){
/* This is Gauss' algorithm for reducing a positive definite binary
 * quadratic form. See L.E. Dickson, Introduction to the theory of numbers,
 * page 69. Here d=b^2-4ac <0, a>0,c>0, while the reduced form (A,B,C)
 * satisfies -A<B<=A, C>=A, with B>=0 if C=A.
 * The number of steps taken in the reduction is returned.
 */
	MPI *D, *X, *Y, *U, *V, *TEMP1, *TEMP2, *TEMP3;
	MPI *a, *b, *c, *TEMPX, *TEMPY, *TEMPU, *TEMPV, *MINUSD, *DELTA;
	MPI *TEMPB;
	USI i;
	int r, s, t;

	i = 0;
	TEMP1 = MULTI(B, B);
	TEMP2 = MULTI(A, C);
	TEMP3 = MULT_I(TEMP2, 4);
	D = SUBI(TEMP1, TEMP3);
	FREEMPI(TEMP1);
	FREEMPI(TEMP2);
	FREEMPI(TEMP3);
	TEMP1 = MINUSI(A);
	r = COMPAREI(TEMP1, B);
	FREEMPI(TEMP1);
	s = COMPAREI(B, A);
	t = COMPAREI(A, C);
	if(r < 0 && s <= 0 && t <= 0){/* -A < B <= A <= C */
		r = COMPAREI(A, C);
		if(t < 0 || (r == 0 && B->S >= 0)){/* A < C or A=C and B>=0 */
			printf("(");
			PRINTI(A);
			printf(",");
			PRINTI(B);
			printf(",");
			PRINTI(C);
			printf(") is reduced\n");
                	printf("Transforming matrix:1,0,0,1\n");
			FREEMPI(D);
                        return (0);
		}
	}
	X = ONEI();
	Y = ZEROI();
	U = ZEROI();
	V = ONEI();
	MINUSD = MINUSI(D);
	a=COPYI(A);
	b=COPYI(B);
	c=COPYI(C);
	while(1){
		TEMPB = b;
		TEMP1 = MINUSI(b);
		TEMP2 = MULT_I(c, 2);
		b = HALFMOD(TEMP1, TEMP2);
		FREEMPI(TEMP1);
		TEMP1 = ADDI(TEMPB, b);
		FREEMPI(TEMPB);
		TEMP3 = MINUSI(TEMP1);
		FREEMPI(TEMP1);
		DELTA = INT(TEMP3, TEMP2);
		FREEMPI(TEMP2);
		FREEMPI(TEMP3);
		TEMPU = U;
		TEMPX = X;
		TEMPY = Y;
		TEMPV = V;
		X = MINUSI(Y);
		Y = MULTABC(TEMPX, Y, DELTA);
		FREEMPI(TEMPX);
		FREEMPI(TEMPY);
		U = MINUSI(V);
		V = MULTABC(TEMPU, V, DELTA);
		FREEMPI(TEMPU);
		FREEMPI(TEMPV);
		FREEMPI(DELTA);
		TEMP1 = a;
		a = COPYI(c);
		FREEMPI(TEMP1);
		TEMP1 = c;
		TEMP2 = MULTABC(MINUSD, b, b);
		TEMP3 = MULT_I(a, 4);
		c = INT(TEMP2, TEMP3);
		FREEMPI(TEMP1);
		FREEMPI(TEMP2);
		FREEMPI(TEMP3);
		i++;
		printf("(");
		PRINTI(a);
		printf(",");
		PRINTI(b);
		printf(",");
		PRINTI(c);
		printf(")\n");
		if(COMPAREI(c, a) >= 0){
			break;
		}
	}
	if(COMPAREI(a, c) == 0 && b->S < 0){
		TEMP1 = b;
		b = MINUSI(b);
		FREEMPI(TEMP1);
		TEMPX = X;
		TEMPY = Y;
		X = COPYI(Y);
		Y = MINUSI(TEMPX);
		FREEMPI(TEMPX);
		FREEMPI(TEMPY);
		TEMPU = U;
		TEMPV = V;
		U = COPYI(V);
		V = MINUSI(TEMPU);
		FREEMPI(TEMPU);
		FREEMPI(TEMPV);
	}
	printf("(");
	PRINTI(a);
	printf(",");
	PRINTI(b);
	printf(",");
	PRINTI(c);
	printf(") is reduced\n");
	printf("Transforming matrix: ");
	PRINTI(X);
	printf(",");
	PRINTI(Y);
	printf(",");
	PRINTI(U);
	printf(",");
	PRINTI(V);
	printf("\n");
	FREEMPI(MINUSD);
	FREEMPI(D);
	FREEMPI(X);
	FREEMPI(Y);
	FREEMPI(U);
	FREEMPI(V);
	FREEMPI(a);
	FREEMPI(b);
	FREEMPI(c);
	return(i);
}

MPI *REDUCE_NEGX(MPI *A, MPI *B, MPI *C){
	MPI *D, *TEMP1, *TEMP2, *TEMP3;
	USI i;

	if(A->S <= 0){
		printf("A <= 0\n");
		return(NULL);
	}
	if(C->S <= 0){
		printf("C <= 0\n");
		return(NULL);
	}
	TEMP1 = MULTI(B, B);
	TEMP2 = MULTI(A, C);
	TEMP3 = MULT_I(TEMP2, 4);
	D = SUBI(TEMP1, TEMP3);
	FREEMPI(TEMP1);
	FREEMPI(TEMP2);
	FREEMPI(TEMP3);
	if(D->S >= 0){
		printf("B^2-4*A*C >= 0\n");
		FREEMPI(D);
		return(NULL);
	}
	i = REDUCE_NEG(A, B, C);
	FREEMPI(D);
	return(CHANGE(i));
}

USI CYCLE_PERIOD(MPI *D, MPI *U, MPI *V, USI i, int sign){
	MPI *A, *F, *UU, *VV, *X, *Y, *TEMP1, *TEMP2, *TEMP3;
	USI len, j;
	char buff[20];
	FILE *outfile;

        strcpy(buff, "reducepos.out");
	/*if(access(buff, R_OK) == 0)
	  unlink(buff);*/
	outfile = fopen(buff, "a");
	F = BIG_MTHROOT(D, 2);
	UU = COPYI(U);
	VV = COPYI(V);
	printf("\ncycle:\n->");
	fprintf(outfile, "\ncycle:\n->");
	/* i is created by reduce(a,b,c) below and indexes the ith
   convergent of the (U+sqrt(D))/V created there) */

	for(j=i;1;j++){
		TEMP1 = ADDI(F, UU);
		A = INT(TEMP1, VV);
		FREEMPI(TEMP1);

		TEMP1 = UU;
		TEMP2 = MULTI(A, VV);
		FREEMPI(A);
		UU = SUBI(TEMP2, UU);
		FREEMPI(TEMP1);
		FREEMPI(TEMP2);
		
		TEMP1 = VV;
		TEMP2 = MULTI(UU, UU);
		TEMP3 = SUBI(D, TEMP2);
		VV = INT(TEMP3, VV);
		FREEMPI(TEMP2);
		FREEMPI(TEMP3);

		TEMP2 = INT_(TEMP1, 2);
		X = MULT_I(TEMP2, (long)sign);
		FREEMPI(TEMP1);
		FREEMPI(TEMP2);
                if(j>i){
	            printf("->");
	            fprintf(outfile, "->");
                }
		printf("(");
		fprintf(outfile, "(");
		PRINTI(X);
		FPRINTI(outfile, X);
		printf(",");
		fprintf(outfile, ",");
		FREEMPI(X);
		PRINTI(UU);
		FPRINTI(outfile, UU);
		printf(",");
		fprintf(outfile, ",");
		TEMP1 = INT_(VV, 2);
		Y = MULT_I(TEMP1, (long)(-sign));
		FREEMPI(TEMP1);
		PRINTI(Y);
		FPRINTI(outfile, Y);
		FREEMPI(Y);
		printf(")");
		fprintf(outfile, ")");
		
		sign = -sign;
		if(COMPAREI(UU, U) == 0 && COMPAREI(VV, V) == 0){
			break;
		}
	}
	len = j + 1 - i;
        llen = len;

	if(len % 2 == 0){

⌨️ 快捷键说明

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