www.pudn.com > calc.rar > reductio.c
/* reduction.c */ #ifdef _WIN32 #include "unistd_DOS.h" #else #include#endif #include #include #include #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=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){ FREEMPI(UU); FREEMPI(VV); FREEMPI(F); fclose(outfile); return(len); }else{ printf("->"); fprintf(outfile, "->"); 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); FREEMPI(TEMP2); VV = INT(TEMP3, VV); 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){ FREEMPI(UU); FREEMPI(VV); FREEMPI(F); printf("\n"); fprintf(outfile, "\n"); fclose(outfile); return(2*len); } } } } USI REDUCE_POS(MPI *A, MPI *B, MPI *C){ MPI *D, *F, *ONE, *U, *V, *TEMP, *TEMP1, *TEMP2, *TEMP3, *TEMP4, *TEMP5; MPI *X, *Y, *AA, *BB, *CC; MPI *A_ORIG, *B_ORIG,*C_ORIG, *PP, *QQ, *RR, *SS, *HH; MPI *A_TMP, *B_TMP,*C_TMP, *T1, *T2, *T3, *T4; int r, s, sign; USI j, len, y; char buff[20]; FILE *outfile; A_ORIG = COPYI(A); B_ORIG = COPYI(B); C_ORIG = COPYI(C); A_TMP = COPYI(A); B_TMP = COPYI(B); C_TMP = COPYI(C); PP = ONEI(); QQ = ZEROI(); RR = ZEROI(); SS = ONEI(); strcpy(buff, "reducepos.out"); if(access(buff, R_OK) == 0) unlink(buff); outfile = fopen(buff, "w"); ONE = ONEI(); AA = COPYI(A); BB = COPYI(B); CC = COPYI(C); TEMP1 = MULTI(BB, BB); TEMP2 = MULTI(AA, CC); TEMP3 = MULT_I(TEMP2, 4); FREEMPI(TEMP2); D = SUBI(TEMP1, TEMP3); FREEMPI(TEMP1); FREEMPI(TEMP3); F = BIG_MTHROOT(D, 2); printf("("); fprintf(outfile, "("); PRINTI(AA); FPRINTI(outfile, AA); printf(","); fprintf(outfile, ","); PRINTI(BB); FPRINTI(outfile, BB); printf(","); fprintf(outfile, ","); PRINTI(CC); FPRINTI(outfile, CC); printf(")->"); fprintf(outfile, ")->"); sign = 1; U = COPYI(BB); TEMP1 = MULT_I(CC, 2); V = MULT_I(TEMP1, (long)(-sign)); FREEMPI(TEMP1); for(j=0; 1; j++){ if(j){ TEMP1 = MULTI(U, U); TEMP2 = SUBI(D, TEMP1); TEMP3 = MULT_I(V, 2); TEMP4 = INTI(TEMP2, TEMP3); X = MULT_I(TEMP4, (long)sign); A_TMP = COPYI(TEMP4); B_TMP = COPYI(U); FREEMPI(TEMP1); FREEMPI(TEMP2); FREEMPI(TEMP3); FREEMPI(TEMP4); TEMP1 = INT_(V, 2); TEMP2 = MINUSI(TEMP1); Y = MULT_I(TEMP2, (long)sign); C_TMP = COPYI(Y); FREEMPI(TEMP1); FREEMPI(TEMP2); if(j>1){ printf("->"); fprintf(outfile, "->"); } printf("("); fprintf(outfile, "("); PRINTI(X); FPRINTI(outfile, X); printf(","); fprintf(outfile, ","); PRINTI(U); FPRINTI(outfile, U); printf(","); fprintf(outfile, ","); PRINTI(Y); FPRINTI(outfile, Y); printf(")"); fprintf(outfile, ")"); FREEMPI(X); FREEMPI(Y); } sign = -sign; if(V->S >0 && U->S > 0 && COMPAREI(U, F) <= 0){ TEMP1 = ADDI(U, V); r = COMPAREI(F, TEMP1); FREEMPI(TEMP1); TEMP2 = SUBI(V, U); s = COMPAREI(TEMP2, F); FREEMPI(TEMP2); if(r < 0 && s <= 0){ printf("\nUnimodular matrix ("); fprintf(outfile, "\nUnimodular matrix ("); PRINTI(PP); FPRINTI(outfile, PP); printf(","); fprintf(outfile, ","); PRINTI(QQ); FPRINTI(outfile, QQ); printf(","); fprintf(outfile, ","); PRINTI(RR); FPRINTI(outfile, RR); printf(","); fprintf(outfile, ","); PRINTI(SS); FPRINTI(outfile, SS); printf(") transforms ("); fprintf(outfile, ") transforms ("); PRINTI(A_ORIG); FPRINTI(outfile, A_ORIG); printf(","); fprintf(outfile, ","); PRINTI(B_ORIG); FPRINTI(outfile, B_ORIG); printf(","); fprintf(outfile, ","); PRINTI(C_ORIG); FPRINTI(outfile, C_ORIG); printf(") to the reduced form ("); fprintf(outfile, ") to the reduced form ("); if (j){ PRINTI(A_TMP); FPRINTI(outfile, A_TMP); printf(","); fprintf(outfile, ","); PRINTI(B_TMP); FPRINTI(outfile, B_TMP); printf(","); fprintf(outfile, ","); PRINTI(C_TMP); FPRINTI(outfile, C_TMP); printf(")\n"); fprintf(outfile, ")\n"); }else{ PRINTI(A_ORIG); FPRINTI(outfile, A_ORIG); printf(","); fprintf(outfile, ","); PRINTI(B_ORIG); FPRINTI(outfile, B_ORIG); printf(","); fprintf(outfile, ","); PRINTI(C_ORIG); FPRINTI(outfile, C_ORIG); printf(")\n"); fprintf(outfile, ")\n"); } FREEMPI(A_ORIG); FREEMPI(B_ORIG); FREEMPI(C_ORIG); FREEMPI(A_TMP); FREEMPI(B_TMP); FREEMPI(C_TMP); FREEMPI(PP); FREEMPI(QQ); FREEMPI(RR); FREEMPI(SS); fclose(outfile); len = CYCLE_PERIOD(D, U, V, j, sign); outfile = fopen(buff, "a"); printf("cfrac has period length %u\n", llen); fprintf(outfile, "cfrac has period length %u\n", llen); printf("cycle of reduced forms has period length %u\n", len); fprintf(outfile, "cycle of reduced forms has period length %u\n", len); FREEMPI(ONE); FREEMPI(D); FREEMPI(F); FREEMPI(U); FREEMPI(V); FREEMPI(AA); FREEMPI(BB); FREEMPI(CC); fclose(outfile); return(len); } } FREEMPI(A_TMP); FREEMPI(B_TMP); FREEMPI(C_TMP); if(V->S > 0){ TEMP1 = ADDI(F, U); X = INTI(TEMP1, V); FREEMPI(TEMP1); }else{ TEMP1 = ADDI(F, U); TEMP2 = ADDI(TEMP1, ONE); FREEMPI(TEMP1); X = INTI(TEMP2, V); FREEMPI(TEMP2); } T1 = MINUSI(QQ); T3 = MINUSI(SS); y = j % 2; if(y == 0){ HH = COPYI(X); }else{ HH = MINUSI(X); } TEMP5 = MULTI(QQ, HH); T2 = ADDI(PP, TEMP5); FREEMPI(TEMP5); TEMP5 = MULTI(SS, HH); T4 = ADDI(RR, TEMP5); FREEMPI(TEMP5); FREEMPI(HH); TEMP = PP; PP = T1; FREEMPI(TEMP); TEMP = QQ; QQ = T2; FREEMPI(TEMP); TEMP = RR; RR = T3; FREEMPI(TEMP); TEMP = SS; SS = T4; FREEMPI(TEMP); TEMP1 = U; TEMP2 = MULTI(X, V); U = SUBI(TEMP2, U); FREEMPI(TEMP1); FREEMPI(TEMP2); FREEMPI(X); TEMP1 = V; TEMP2 = MULTI(U, U); TEMP3 = SUBI(D, TEMP2); V = INTI(TEMP3, V); FREEMPI(TEMP1); FREEMPI(TEMP2); FREEMPI(TEMP3); } } MPI *REDUCE_POSX(MPI *A, MPI *B, MPI *C){ MPI *D, *F, *G, *TEMP, *TEMP1, *TEMP2, *TEMP3; USI len; int t; TEMP1 = MULTI(B, B); TEMP2 = MULTI(A, C); TEMP3 = MULT_I(TEMP2, 4); FREEMPI(TEMP2); D = SUBI(TEMP1, TEMP3); FREEMPI(TEMP1); FREEMPI(TEMP3); F = BIG_MTHROOT(D, 2); G = MULTI(F, F); t = COMPAREI(G, D); FREEMPI(F); FREEMPI(G); if(t == 0){ printf("B^2-4AC is a perfect square\n"); FREEMPI(D); return(NULL); } t = D->S; if(t <= 0){ printf("B^2-4*A*C <= 0\n"); FREEMPI(D); return(NULL); } TEMP = POWER_I (10, 6); t = RSV(D, TEMP); FREEMPI(TEMP); if(t >= 0){ printf("D >= 10^6\n"); FREEMPI(D); return(NULL); } FREEMPI(D); len = REDUCE_POS(A, B, C); TEMP1 = CHANGE((USL)len); return(TEMP1); } USI POS0(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; int sign, sign1; GLOBALARRAY_U = BUILDMPIA(); GLOBALARRAY_V = BUILDMPIA(); class_number = 0; ONE = ONEI(); global_count = 0; parity_flag = 0; d = CONVERTI(D); if((d-1) % 4 != 0){ e=2; }else{ e=1; } printf("Creating a complete list of reduced forms of discriminant %lu\n", d); F = BIG_MTHROOT(D, 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, D); 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(D,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-%lu*y^2=-4 has a solution\n", d); }else{ printf("x^2-%lu*y^2=-4 has no solution\n", d); class_number = 2*class_number; printf("There are reduced forms (-a,b,-c) as well\n"); } printf("h(%lu)=%u\n", d, class_number); FREEMPI(ONE); FREEMPI(F); FREEMPI(G); FREEMPIA(GLOBALARRAY_U); FREEMPIA(GLOBALARRAY_V); return(class_number); } MPI *POS0X(MPI *D){ USI class_number; USL d; int t; MPI *ONE, *N, *TEMP, *F, *G; 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); } F = BIG_MTHROOT(D, 2); G = MULTI(F, F); t = COMPAREI(G, D); FREEMPI(F); FREEMPI(G); if(t == 0){ printf("B^2-4AC is a perfect square\n"); return(NULL); }else{ class_number = POS0(D); N = CHANGE(class_number); return(N); } } USL TABLENEG(MPI *M, MPI *N){ /* The following gives a table of h(-d) for all squarefree d * in the range M<=d<=N<10^6. */ MPI *DD, *ONE, *ZERO; USL count, m, n, d, r; USI h, t; long dd; char buff[20]; FILE *outfile; count = 0; m = CONVERTI(M); n = CONVERTI(N); strcpy(buff, "tableneg.out"); if(access(buff, R_OK) == 0) unlink(buff); outfile = fopen(buff, "a"); for(d = m; d <= n; d++){ h = SQUAREFREE_TEST1000(d); if(h == 0){ continue; }else{ r = d % 4; dd = (long)d; if(r != 3){ DD = CHANGEL((long)(-4) * d); }else{ DD = CHANGEL(-dd); } ONE = ONEI(); ZERO = ZEROI(); t = NEG(DD, ONE, ZERO); FREEMPI(DD); FREEMPI(ONE); FREEMPI(ZERO); count++; printf("h(%ld) = %u\n",-d, t); fprintf(outfile, "h(%ld) = %u\n",-d, t); } } if(count==0){ printf("no squarefree d in the range [%lu,%lu]\n",m,n); } fclose(outfile); return (count); } MPI *TABLENEGX(MPI *M, MPI *N){ MPI *LIMIT, *COUNT; USL count; LIMIT = POWER_I(10, 6); if(COMPAREI(M, N) > 0){ printf("M > N\n"); FREEMPI(LIMIT); return (NULL); } if(COMPAREI(N, LIMIT) >= 0){ printf("N >= 10^6\n"); FREEMPI(LIMIT); return (NULL); } FREEMPI(LIMIT); if(M->S <= 0 || N->S <= 0){ printf("M < 1 or N < 1\n"); return (NULL); } count = TABLENEG(M, N); COUNT = CHANGE(count); return(COUNT); } USI POS1(MPI *D, int *norm){ /* D is squarefree. This function performs Lagrange's method on all * reduced quadratic irrationals (b+\sqrt(Disc))/2|c|, where 4*c divides * Disc-b^2, Disc being the discriminant. The class-number h(D) of Q(sqrt(D) * is calculated, as well as the norm of the fundamental unit. * For use in TABLEPOS(M,N) below. */ 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); 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; } } FREEMPI(TEMP); FREEMPI(C); } FREEMPI(R); } } FREEMPI(H); FREEMPI(B); } FREEMPI(A); FREEMPI(I); FREEMPI(J); } if(e==2){ d = d / 4; } if(parity_flag){ *norm = -1; }else{ *norm = 1; } /*printf("h(%lu)=%u, N(eta)=%d\n", d, class_number, *norm);*/ FREEMPI(ONE); FREEMPI(F); FREEMPI(G); FREEMPI(DD); FREEMPIA(GLOBALARRAY_U); FREEMPIA(GLOBALARRAY_V); return(class_number); } USL TABLEPOS(MPI *M, MPI *N){ /* The following gives a table of h(d) for all squarefree d * in the range 2<=M<=d<=N<10^6. * The number of squarefree d encountered is returned. */ MPI *DD; USL count, m, n, d; USI h; char buff[20]; FILE *outfile; int norm; count = 0; m = CONVERTI(M); n = CONVERTI(N); strcpy(buff, "tablepos.out"); if(access(buff, R_OK) == 0) unlink(buff); outfile = fopen(buff, "a"); for(d = m; d <= n; d++){ h = SQUAREFREE_TEST1000(d); if(h == 0){ continue; }else{ DD = CHANGE(d); h = POS1(DD, &norm); FREEMPI(DD); count++; printf("h(%lu) = %u, N(eta)= %d\n",d, h, norm); fprintf(outfile, "h(%lu) = %u, N(eta)= %d\n",d, h, norm); } } if(count==0){ printf("no squarefree d in the range [%lu,%lu]\n",m,n); } fclose(outfile); return (count); } MPI *TABLEPOSX(MPI *M, MPI *N){ MPI *LIMIT, *COUNT, *ONE; USL count; int t; LIMIT = POWER_I(10, 6); if(COMPAREI(M, N) > 0){ printf("M > N\n"); FREEMPI(LIMIT); return (NULL); } if(COMPAREI(N, LIMIT) >= 0){ printf("N >= 10^6\n"); FREEMPI(LIMIT); return (NULL); } FREEMPI(LIMIT); ONE = ONEI(); t = COMPAREI(M, ONE); FREEMPI(ONE); if(t <= 0){ printf("M <= 1\n"); return (NULL); } count = TABLEPOS(M, N); COUNT = CHANGE(count); return(COUNT); } USI REDUCE_NEG0(MPI *A, MPI *B, MPI *C, MPI **AA, MPI **BB, MPI **CC, MPI **alpha, MPI **beta, MPI **gamma, MPI **delta, USI print_flag){ /* This is Gauss' algorithm for reducing a positive definite binary * quadratic form (A,B,C). * 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 (AA,BB,CC) * satisfies -AA =AA, with BB>=0 if CC=AA. * 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){ r = COMPAREI(A, C); if(t < 0 || (r == 0 && B->S >= 0)){ if(print_flag){ printf("("); PRINTI(A); printf(","); PRINTI(B); printf(","); PRINTI(C); printf(") is reduced\n"); printf("Transforming matrix:1,0,0,1\n"); } FREEMPI(D); *alpha = ONEI(); *beta = ZEROI(); *gamma = ZEROI(); *delta = ONEI(); *AA = COPYI(A); *BB = COPYI(B); *CC = COPYI(C); 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++; if(print_flag){ 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); } *alpha = COPYI(X); *beta = COPYI(Y); *gamma = COPYI(U); *delta = COPYI(V); *AA = COPYI(a); *BB = COPYI(b); *CC = COPYI(c); if(print_flag){ 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); } USI REP_DEFINITE(MPI *A, MPI *B, MPI *C, MPI *M, USI print_flag){ /* Given a positive definite binary quadratic form Ax^2+Bxy+Cy^2, * we use an algorithm of Gauss to determine if a given positive integer M * is expressible as M = AX^2+BXY+CY^2, X and Y integers, gcd(X,Y) = 1. * Note: Here D = B^2 - 4AC < 0, A > 0, C > 0. * See L.E. Dickson, Introduction to the theory of numbers, pages 74-75. */ USI solution_number; MPI *AA1, *BB1, *CC1, *R1, *S1, *T1, *U1, *D; MPI *AA2, *BB2, *CC2, *R2, *S2, *T2, *U2; MPI *TEMP0, *TEMP1, *TEMP2, *FOURM, *S, *MODULUS, *TWOM; MPI *L, *X, *Y, *XX, *YY, *T, *U; MPI *ALPHA1, *BETA1, *GAMMA1, *DELTA1, *N, *M0, *TEMP3, *TEMP; MPIA SOLUTION, SOL; USI l, i, r, s, t, numbr, m0, j, k; FILE *outfile; char buff[20]; solution_number = 0; REDUCE_NEG0(A, B, C, &AA1, &BB1, &CC1, &R1, &S1, &T1, &U1, 0); TEMP0 = MULTI(B, B); TEMP1 = MULTI(A, C); TEMP2 = MULT_I(TEMP1, 4); D = SUBI(TEMP0, TEMP2); FREEMPI(TEMP0); FREEMPI(TEMP1); FREEMPI(TEMP2); FOURM = MULT_I(M, 4); /* First solve x^2=D (mod FOURM). */ S = SQROOT(D, FOURM, &SOLUTION, &MODULUS, &l); if(EQMINUSONEI(S)){ /* cleanup of nettbytes */ FREEMPI(S); FREEMPIA(SOLUTION); FREEMPI(MODULUS); printf("x^2="); PRINTI(D); FREEMPI(D); printf("(mod "); PRINTI(FOURM); FREEMPI(FOURM); printf(") not soluble.\n"); printf("Hence no primitive solutions.\n"); return(0); } FREEMPI(S); M0 = INT0(FOURM, MODULUS); if(M0->D > 1){ execerror("M0 >= 2^32", ""); } m0 = CONVERTI(M0); /* valid, as 0 < M0 < 2^32 */ TEMP = MULT_I(M0, l); FREEMPI(M0); TEMP1 = INT0_(TEMP, 100); FREEMPI(TEMP); t = TEMP1->D; FREEMPI(TEMP1); if(t){ execerror("number of positive solutions of X^2=N(mod FOURM) > 100", ""); } numbr = 0; SOL = BUILDMPIA(); ADD_TO_MPIA(SOL, NULL, 0); for(j=0;j A[j],TEMP1); TEMP3 = MULT_I(TEMP2, 2); if(COMPAREI(TEMP3, FOURM) <= 0){ ADD_TO_MPIA(SOL, TEMP2, numbr); numbr++; }else{ TEMP0 = SUB0I(FOURM, TEMP2); ADD_TO_MPIA(SOL, TEMP0, numbr); FREEMPI(TEMP0); numbr++; } FREEMPI(TEMP2); FREEMPI(TEMP3); FREEMPI(TEMP1); } } FREEMPI(MODULUS); FREEMPIA(SOLUTION); strcpy(buff, "repdefinite.out"); outfile = fopen(buff, "w"); TWOM = MULT_I(M, 2); for(i = 0; i < numbr; i++){ N = COPYI(SOL->A[i]); /*if(RSV(N, TWOM) > 0){ TEMP = N; N = SUBI(FOURM, N); FREEMPI(TEMP); }*/ fprintf(outfile, "N = "); FPRINTI(outfile, N); fprintf(outfile, "\n"); if(EQUALI(N, TWOM)){ FREEMPI(N); continue; } /* now calculate L, where N^2-4ML=D */ TEMP1 = MULTI(N, N); TEMP2 = SUBI(TEMP1, D); L = INT0(TEMP2, FOURM); FREEMPI(TEMP1); FREEMPI(TEMP2); REDUCE_NEG0(M, N, L, &AA2, &BB2, &CC2, &R2, &S2, &T2, &U2, 0); r = EQUALI(AA1, AA2); s = EQUALI(BB1, BB2); t = EQUALI(CC1, CC2); FREEMPI(AA2); FREEMPI(BB2); FREEMPI(CC2); if(r && s && t){ TEMP1 = MULTI(R1, U2); TEMP2 = MULTI(S1, T2); ALPHA1 = SUBI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); TEMP1 = MULTI(S1, R2); TEMP2 = MULTI(S2, R1); BETA1 = SUBI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); TEMP1 = MULTI(U2, T1); TEMP2 = MULTI(U1, T2); GAMMA1 = SUBI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); TEMP1 = MULTI(U1, R2); TEMP2 = MULTI(S2, T1); DELTA1 = SUBI(TEMP1, TEMP2); FREEMPI(TEMP1); FREEMPI(TEMP2); FREEMPI(R2); FREEMPI(S2); FREEMPI(T2); FREEMPI(U2); if(print_flag){ fprintf(outfile, "The unimodular transformation\n"); fprintf(outfile, "x = "); FPRINTI(outfile, ALPHA1); fprintf(outfile, "X + "); FPRINTI(outfile, BETA1); fprintf(outfile, "Y\n"); fprintf(outfile, "y = "); FPRINTI(outfile, GAMMA1); fprintf(outfile, "X + "); FPRINTI(outfile, DELTA1); fprintf(outfile, "Y\n"); fprintf(outfile, "converts ("); FPRINTI(outfile, A); fprintf(outfile, ","); FPRINTI(outfile, B); fprintf(outfile, ","); FPRINTI(outfile, C); fprintf(outfile, ") to "); fprintf(outfile, "("); FPRINTI(outfile, M); fprintf(outfile, ","); FPRINTI(outfile, N); fprintf(outfile, ","); FPRINTI(outfile, L); fprintf(outfile, ")\n"); } FREEMPI(N); FREEMPI(L); fprintf(outfile, "solution: ("); FPRINTI(outfile, ALPHA1); fprintf(outfile, ","); FPRINTI(outfile, GAMMA1); fprintf(outfile, ")\n"); X = MINUSI(ALPHA1); Y = MINUSI(GAMMA1); fprintf(outfile, "solution: ("); FPRINTI(outfile, X); fprintf(outfile, ","); FPRINTI(outfile, Y); fprintf(outfile, ")\n"); solution_number = solution_number + 2; if(D->D == 0 && D->S == -1 && D->V[0] == 4){ /* D = -4 */ T = ZEROI(); U = ONEI(); AUTOMORPH(A, B, D, T, U, X, Y, &XX, &YY); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); AUTOMORPH(A, B, D, T, U, ALPHA1, GAMMA1, &XX, &YY); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); FREEMPI(T); FREEMPI(U); solution_number = solution_number + 2; } if(D->D == 0 && D->S == -1 && D->V[0] == 3){ /* D = -3 */ T = ONEI(); U = ONEI(); AUTOMORPH(A, B, D, T, U, X, Y, &XX, &YY); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); AUTOMORPH(A, B, D, T, U, ALPHA1, GAMMA1, &XX, &YY); FREEMPI(T); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); T = MINUS_ONEI(); AUTOMORPH(A, B, D, T, U, X, Y, &XX, &YY); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); AUTOMORPH(A, B, D, T, U, ALPHA1, GAMMA1, &XX, &YY); fprintf(outfile, "solution: ("); FPRINTI(outfile, XX); fprintf(outfile, ","); FPRINTI(outfile, YY); fprintf(outfile, ")\n"); FREEMPI(XX); FREEMPI(YY); FREEMPI(T); FREEMPI(U); solution_number = solution_number + 4; } FREEMPI(X); FREEMPI(Y); fprintf(outfile, "\n"); FREEMPI(ALPHA1); FREEMPI(BETA1); FREEMPI(GAMMA1); FREEMPI(DELTA1); }else{ continue; } } FREEMPI(R1); FREEMPI(S1); FREEMPI(T1); FREEMPI(U1); FREEMPI(AA1); FREEMPI(BB1); FREEMPI(CC1); FREEMPI(TWOM); FREEMPI(FOURM); FREEMPI(D); FREEMPIA(SOL); fclose(outfile); return(solution_number); } void AUTOMORPH(MPI *A, MPI *B, MPI *D, MPI *T, MPI *U, MPI *X, MPI *Y, MPI **XX, MPI **YY){ /* From Loo-Keng Hua, Introduction to Number Theory, * Theorem 4.2, pages 279-281 */ MPI *TEMP0, *TEMP1, *TEMP2, *TEMP3, *TEMP4, *TEMP5, *TEMP6; MPI *T1, *T2, *T3, *T4, *T5, *T6, *TEMP; TEMP1 = MULT_I(A, 2); TEMP2 = MULTI(TEMP1, X); TEMP0 = MULTI(Y, B); TEMP3 = ADDI(TEMP2, TEMP0); TEMP4 = MULTI(TEMP3, U); TEMP5 = MULTI(Y, T); TEMP6 = ADDI(TEMP4, TEMP5); *YY = INT_(TEMP6, 2); T1 = MULTI(TEMP3, T); T2 = MULTI(D, Y); TEMP = T2; T2 = MULTI(T2, U); FREEMPI(TEMP); T3 = ADDI(T1, T2); TEMP = T3; T3 = INT_(T3, 2); FREEMPI(TEMP); T4 = MULTI(B, *YY); T5 = SUBI(T3, T4); T6 = MULT_I(A, 2); *XX = INT(T5, T6); FREEMPI(TEMP0); FREEMPI(TEMP1); FREEMPI(TEMP2); FREEMPI(TEMP3); FREEMPI(TEMP4); FREEMPI(TEMP5); FREEMPI(TEMP6); FREEMPI(T1); FREEMPI(T2); FREEMPI(T3); FREEMPI(T4); FREEMPI(T5); FREEMPI(T6); } MPI *REP_DEFINITEX(MPI *A, MPI *B, MPI *C, MPI *M, MPI *PRINT_FLAG){ MPI *D, *TEMP1, *TEMP2, *TEMP3; USI i, print_flag; if(M->S <= 0){ printf("M <= 0\n"); return(NULL); } 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); } print_flag = (USI)CONVERTI(PRINT_FLAG); if(print_flag != 0 && print_flag != 1){ printf("print_flag != 0 or 1\n"); FREEMPI(D); return(NULL); } i = REP_DEFINITE(A, B, C, M, print_flag); FREEMPI(D); return(CHANGE(i)); }