www.pudn.com > calc.rar > lagrange.c
#include "integer.h" #include#include #include "fun.h" #include "stack.h" /*#include "unistd.h"*/ #include extern USI sqroot2_number; void PATZ(MPI *D, MPI* N) /* This solves the diophantine equations x^2-Dy^2=N and -N. * If patz_verbose=1, all solutions in the range to be tested are printed. * If patz_verbose=0, only the fundamental solutions are printed. */ { MPI *Q0, *S, *M, *M0, *TMP1, *TMP2, *X, *QQ, *ONE; MPI *X1, *X2, *Y1, *Y2, *Y, *TMP3, *TMP4, *Q0_2; MPIA A, AA, U, V, P, Q, FSX1, FSX2, FSY1, FSY2; USI l, period_length, k, r, s, flag1, flag2, kk, tmp; USI FLAG1, FLAG2, patz_verbose=1, n1 = 0, n2 = 0; int t0, t, tt, ttt=0 /*(to get rid of compiler complaint) */; USL i, j, m0; FILE *outfile; char buff[20]; FSX1 = BUILDMPIA(); FSX2 = BUILDMPIA(); FSY1 = BUILDMPIA(); FSY2 = BUILDMPIA(); Q0 = ABSI(N); Q0_2 = INT0_(Q0, 2); tt = N->S; /* First solve x^2=D (mod Q_0), where Q_0=|N|. */ S = SQROOT(D, Q0, &A, &M, &l); if(EQMINUSONEI(S)){ /* cleanup of nettbytes */ FREEMPI(S); FREEMPIA(A); FREEMPI(M); FREEMPI(N); FREEMPI(Q0_2); FREEMPIA(FSX1); FREEMPIA(FSY1); FREEMPIA(FSX2); FREEMPIA(FSY2); printf("x^2="); PRINTI(D); FREEMPI(D); printf("(mod "); PRINTI(Q0); FREEMPI(Q0); printf(") not soluble;\n"); execerror("Hence no primitive solutions", ""); } FREEMPI(S); M0 = INT0(Q0, M); /* FREEMPI(M); *//* bugfix 4th July 2000 */ m0 = CONVERTI(M0); FREEMPI(M0); if(l * m0 > 100){ FREEMPI(Q0); FREEMPIA(A); FREEMPI(D); FREEMPI(N); FREEMPI(Q0_2); FREEMPIA(FSX1); FREEMPIA(FSY1); FREEMPIA(FSX2); FREEMPIA(FSY2); execerror("number of positive solutions of X^2=D(mod Q0) > 100", ""); } ONE = ONEI(); flag1 = 0; flag2 = 0; if(EQONEI(Q0)) kk = 1; else kk = 0; strcpy(buff, "patz.out"); outfile = fopen(buff, "w"); for(i = 0; i < l; i++){ for(j = 0; j < m0; j++){ TMP2 = MULT_I(M, j); /* bugfix: formerly had M0 here */ QQ = ADD0I(A->A[i], TMP2); FREEMPI(TMP2); /* inserted on 27th March 2002 */ TMP2 = MULT_I(QQ, 2); t = RSV(TMP2, Q0); FREEMPI(TMP2); TMP2 = MULT_I(A->A[i], 2);/* inserted on 28th March 2002 */ t0 = RSV(TMP2, M); FREEMPI(TMP2); if (t == 1){ if(t0){ TMP2 = QQ; QQ = SUB0I(Q0,QQ); FREEMPI(TMP2); } else { FREEMPI(QQ); continue; } } X1 = ZEROI(); Y1 = ZEROI(); X2 = ZEROI(); Y2 = ZEROI(); FLAG1 = 0; FLAG2 = 0; for (t = 1; t >= -1; t = t -2){ /* finding the rcf of (QQ+sqrt(D))/Q0 and (-QQ+sqrt(D))/Q0 */ if(t == -1) QQ->S = -(QQ->S); if(QQ->S == 0) /* (0+sqrt(D))/Q0= (-0+sqrt(D))/Q0 */ t = -2; tmp = EQUALI(Q0_2, QQ); if (((Q0)->V[0]) % 2 == 0 && tmp) t = -2; /* (Q0/2+sqrt(D))/Q0 and (-Q0/2+sqrt(D))/Q0 give the same fundamental solutions */ printf("rcf:("); fprintf(outfile, "rcf:("); PRINTI(QQ); FPRINTI(outfile, QQ); printf("+sqrt("); fprintf(outfile, "+sqrt("); PRINTI(D); FPRINTI(outfile, D); printf("))/"); fprintf(outfile, "))/"); PRINTI(Q0); FPRINTI(outfile, Q0); printf("\n"); fprintf(outfile, "\n"); period_length = SURD(D, ONE, QQ, Q0, &AA, &U, &V, &P, &Q, 1); r = AA->size; if(period_length %2) period_length = 2 * period_length; s = r - period_length; for( k = kk; k < r; k++){ if ((V->A[k])->D == 0 && (V->A[k])->V[0] == 1){ TMP1 = MULTI(Q0, P->A[k - 1]); TMP2 = MULTI(QQ, Q->A[k - 1]); X = SUBI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); if(patz_verbose){ printf("(X,Y) = ("); fprintf(outfile, "(X,Y) = ("); PRINTI(X); FPRINTI(outfile, X); printf(", "); fprintf(outfile, ", "); PRINTI(Q->A[k - 1]); FPRINTI(outfile, Q->A[k - 1]); } Y = COPYI(Q->A[k - 1]); if(patz_verbose){ printf("); X^2-"); fprintf(outfile, "); X^2-"); PRINTI(D); FPRINTI(outfile, D); printf("*Y^2="); fprintf(outfile, "*Y^2="); } if(k % 2) ttt = -((V->A[k])->S); else ttt = (V->A[k])->S; if(ttt == -1){ if(patz_verbose){ printf("-"); fprintf(outfile, "-"); } if(FLAG1){ if(RSV(Y, Y1) < 0){ FREEMPI(X1); FREEMPI(Y1); X1 = X; Y1 = Y; ADD_TO_MPIA(FSX1, X1, n1 - 1); ADD_TO_MPIA(FSY1, Y1, n1 - 1); } else{ FREEMPI(X); FREEMPI(Y); } } else{ FLAG1 = 1; FREEMPI(X1); FREEMPI(Y1); X1 = X; Y1 = Y; ADD_TO_MPIA(FSX1, X1, n1); ADD_TO_MPIA(FSY1, Y1, n1); n1++; } } else{ if(FLAG2){ if(RSV(Y, Y2) < 0 && FLAG2){ FREEMPI(X2); FREEMPI(Y2); X2 = X; Y2 = Y; ADD_TO_MPIA(FSX2, X2, n2 - 1); ADD_TO_MPIA(FSY2, Y2, n2 - 1); } else{ FREEMPI(X); FREEMPI(Y); } } else{ FLAG2 = 1; FREEMPI(X2); FREEMPI(Y2); X2 = X; Y2 = Y; ADD_TO_MPIA(FSX2, X2, n2); ADD_TO_MPIA(FSY2, Y2, n2); n2++; } } if(patz_verbose){ PRINTI(Q0); FPRINTI(outfile, Q0); printf("\n"); fprintf(outfile, "\n"); GetReturn(); } if (k >= s){ if(period_length % 2) { flag1 = 1; flag2 = 1; } else{ if(k % 2) flag1 = 1; if((k % 2) == 0) flag2 = 1; } } } } FREEMPIA(AA); FREEMPIA(U); FREEMPIA(V); FREEMPIA(P); FREEMPIA(Q); } if (Y1->S){ printf("Fundamental solution for x^2-"); fprintf(outfile, "Fundamental solution for x^2-"); PRINTI(D); FPRINTI(outfile, D); printf("y^2=-"); fprintf(outfile, "y^2=-"); PRINTI(Q0); FPRINTI(outfile, Q0); printf(": (x,y)=("); fprintf(outfile, ": (x,y)=("); if(X1->S <0) X1->S = -(X1->S); PRINTI(X1); FPRINTI(outfile, X1); printf(","); fprintf(outfile, ","); PRINTI(Y1); FPRINTI(outfile, Y1); printf(")\n"); fprintf(outfile, ")\n"); } FREEMPI(X1); FREEMPI(Y1); if (Y2->S){ printf("Fundamental solution for x^2-"); fprintf(outfile, "Fundamental solution for x^2-"); PRINTI(D); FPRINTI(outfile, D); printf("y^2="); fprintf(outfile, "y^2="); PRINTI(Q0); FPRINTI(outfile, Q0); printf(": (x,y)=("); fprintf(outfile, ": (x,y)=("); if(X2->S <0) X2->S = -(X2->S); PRINTI(X2); FPRINTI(outfile, X2); printf(","); fprintf(outfile, ","); PRINTI(Y2); FPRINTI(outfile, Y2); printf(")\n"); fprintf(outfile, ")\n"); } FREEMPI(X2); FREEMPI(Y2); FREEMPI(QQ); } } FREEMPIA(A); FREEMPI(ONE); printf("--------------------------\n"); fprintf(outfile, "--------------------------\n"); printf("X^2-"); fprintf(outfile, "X^2-"); PRINTI(D); FPRINTI(outfile, D); printf("*Y^2="); fprintf(outfile, "*Y^2="); if(flag1){ printf("-"); fprintf(outfile, "-"); PRINTI(Q0); FPRINTI(outfile, Q0); printf(" is soluble\n"); fprintf(outfile, " is soluble\n"); for(i = 0; i < n1; i++){ printf("Fundamental solution ("); fprintf(outfile, "Fundamental solution ("); if((FSX1->A)[i]->S <0) (FSX1->A)[i]->S = -((FSX1->A)[i]->S); PRINTI((FSX1->A)[i]); FPRINTI(outfile, (FSX1->A)[i]); printf(","); fprintf(outfile, ","); PRINTI((FSY1->A)[i]); FPRINTI(outfile, (FSY1->A)[i]); printf(")\n"); fprintf(outfile, ")\n"); TMP1 = GCD((FSX1->A)[i], (FSY1->A)[i]); if(EQONEI(TMP1) == 0){ printf("imprimitive solution!\n"); fprintf(outfile, "imprimitive solution!\n"); } FREEMPI(TMP1); } } else{ printf("-"); fprintf(outfile, "-"); PRINTI(Q0); FPRINTI(outfile, Q0); printf(" is insoluble\n"); fprintf(outfile, " is insoluble\n"); } printf("--------------------------\n"); fprintf(outfile, "--------------------------\n"); printf("X^2-"); fprintf(outfile, "X^2-"); PRINTI(D); FPRINTI(outfile, D); printf("*Y^2="); fprintf(outfile, "*Y^2="); if(flag2){ PRINTI(Q0); FPRINTI(outfile, Q0); printf(" is soluble\n"); fprintf(outfile, " is soluble\n"); if(EQONEI(Q0) && ttt == -1){ /* calculating eta^2, when Norm(eta)= -1 */ TMP1 = MULTI((FSX1->A)[0], (FSX1->A)[0]); TMP2 = MULTI((FSY1->A)[0], (FSY1->A)[0]); TMP3 = MULTI(TMP2, D); FREEMPI(TMP2); TMP4 = ADD0I(TMP1, TMP3); FREEMPI(TMP1); FREEMPI(TMP3); ADD_TO_MPIA(FSX2, TMP4, 0); FREEMPI(TMP4); TMP1 = MULTI((FSX1->A)[0], (FSY1->A)[0]); TMP2 = MULT_I(TMP1, 2); FREEMPI(TMP1); ADD_TO_MPIA(FSY2, TMP2, 0); FREEMPI(TMP2); n2 = 1; /* need to increment n2 from 0 */ } for(i = 0; i < n2; i++){ printf("Fundamental solution ("); fprintf(outfile, "Fundamental solution ("); if((FSX2->A)[i]->S <0) (FSX2->A)[i]->S = -((FSX2->A)[i]->S); PRINTI((FSX2->A)[i]); FPRINTI(outfile, (FSX2->A)[i]); printf(","); fprintf(outfile, ","); PRINTI((FSY2->A)[i]); FPRINTI(outfile, (FSY2->A)[i]); printf(")\n"); fprintf(outfile, ")\n"); TMP1 = GCD((FSX2->A)[i], (FSY2->A)[i]); if(EQONEI(TMP1) == 0){ printf("imprimitive solution!\n"); fprintf(outfile, "imprimitive solution!\n"); } FREEMPI(TMP1); } } else{ PRINTI(Q0); FPRINTI(outfile, Q0); printf(" is insoluble\n"); fprintf(outfile, " is insoluble\n"); } FREEMPI(Q0); FREEMPI(Q0_2); FREEMPIA(FSX1); FREEMPIA(FSY1); FREEMPIA(FSX2); FREEMPIA(FSY2); FREEMPI(M); /* placed this here on 4th July 2000 */ fclose(outfile); return; } MPI *PATZX(MPI *D, MPI *N) { MPI *G, *X; unsigned long f; if (D->S <= 0) { printf("D <= 0\n"); return NULL; } if (EQONEI(D)) { printf("D = 1\n"); return NULL; } X = BIG_MTHROOT(D, 2); G = MULTI(X, X); f = EQUALI(D, G); FREEMPI(G); FREEMPI(X); if (f) { printf("D is a perfect square\n"); return NULL; } if (N->S == 0) { printf("N = 0\n"); return NULL; } PATZ(D, N); return(ONEI()); } MPI *QUADRATIC(MPI *A, MPI *B, MPI *C, MPI *N, MPIA *SOL) /* Solving the congruence AX^2+BX+C=0 (mod N). */ /* returns -1 if no solution, otherwise returns the number of solutions. * The actual solutions are returned as the array SOL. * Finished 14th December 2000. */ { MPI *D, *T, *TMP1, *TMP2, *M, *MM, *Z, *M0, *FOUR; MPI *NN, *QQ, *BB, *NNN, *NUMBER, *ABSN, *HALFN; MPIA SOL1, SOL2; USL i, j, k, m0, s; USI l, flag = 0; int t, tt; TMP1 = MULTI(B, B); FOUR = CHANGEI(4); TMP2 = MULTI3(FOUR, A, C); FREEMPI(FOUR); ABSN = ABSI(N); NN = MULT_I(ABSN, 4); NNN = MULT_I(ABSN, 2); D = SUBI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); BB = COPYI(B); if(((B->V[0]) % 2) == 0){ TMP1 = D; D = INT_(D, 4); FREEMPI(TMP1); TMP1 = BB; BB = INT_(B, 2); FREEMPI(TMP1); TMP1 = NN; NN = INT_(NN, 4); FREEMPI(TMP1); } T = SQROOT(D, NN, &SOL1, &M, &l); *SOL = BUILDMPIA(); SOL2 = BUILDMPIA(); k = 0; if (EQMINUSONEI(T)){ FREEMPI(D); FREEMPI(NN); FREEMPI(BB); FREEMPI(NNN); FREEMPIA(SOL1); FREEMPI(M); FREEMPI(T); FREEMPI(ABSN); ADD_TO_MPIA(*SOL, NULL, k); return(ZEROI()); } FREEMPI(T); M0 = INT0(NN, M); m0 = CONVERTI(M0); FREEMPI(M0); s = N->V[0] % 2; HALFN = INT_(ABSN, 2); for(i = 0; i < l; i++){ for(j = 0; j < m0; j++){ TMP2 = MULT_I(M, j); QQ = ADD0I(SOL1->A[i], TMP2); FREEMPI(TMP2); if (((B->V[0]) % 2)){ t = RSV(QQ, NNN); if (t == 1){ TMP1 = QQ; QQ = SUBI(NN, QQ); FREEMPI(TMP1); } ADD_TO_MPIA(SOL2, QQ, k); k++; } else{ ADD_TO_MPIA(SOL2, QQ, k); k++; if (s == 0){ tt = RSV(QQ, HALFN); if(tt == 0) flag = 1; } if(QQ->S && (flag == 0)){ TMP2 = MINUSI(QQ); ADD_TO_MPIA(SOL2, TMP2, k); k++; FREEMPI(TMP2); } } FREEMPI(QQ); } } for(i = 0; i < k; i++){ TMP1 = SUBI(SOL2->A[i], BB); if(((B->V[0]) % 2) == 0) TMP2 = COPYI(TMP1); else TMP2 = INT_(TMP1, 2); Z = CONGR(A, TMP2, ABSN, &MM); ADD_TO_MPIA(*SOL, Z, i); FREEMPI(Z); FREEMPI(TMP1); FREEMPI(TMP2); FREEMPI(MM); } FREEMPIA(SOL1); FREEMPIA(SOL2); FREEMPI(NNN); FREEMPI(NN); FREEMPI(ABSN); FREEMPI(HALFN); FREEMPI(BB); FREEMPI(M); FREEMPI(D); NUMBER = CHANGEI(k); return(NUMBER); } MPI *QUADRATICX(MPI *A, MPI *B, MPI *C, MPI *N, MPIA *SOL) { MPI *T, *X; USI t; if (A->S == 0 || N->S <= 0){ *SOL = BUILDMPIA(); ADD_TO_MPIA(*SOL, NULL, 0); printf("A = 0 or N <= 0\n"); return(NULL); } X = GCD(A, N); t = EQONEI(X); FREEMPI(X); if (!t){ *SOL = BUILDMPIA(); ADD_TO_MPIA(*SOL, NULL, 0); printf("gcd(a,n)>1\n"); return(NULL); } T = QUADRATIC(A, B, C, N, SOL); return(T); } /* Below we implement the algorithm in my paper * "The diophantine equation ax^2+bxy+cy^2=N, D=b^2-4ac >0". * gcd(A,N)=1." */ void BINARYFORM(MPI *A, MPI *B, MPI *C, MPI *N, MPIA *FSX1, MPIA *FSY1, USI *N1, USI FLAG, USI verbose) /* first solve the congruence a\theta^2+b\theta+c=0 (mod |N|) * Let \Delta = B[1]^2-ac if B=2*B[1], else D = B^2-4AC and Q = A*|N|. * Then let n= 2A\theta + B, P = int(n/2). * If B is even, * let \omega=(-P +\sqrt{\Delta})/Q,\omega* =(-P -\sqrt{\Delta})/Q, * If B is odd. * let \omega=(-n +\sqrt{D})/2Q,\omega* =(-n -\sqrt{D})/2Q, * Let l = period length of omega and omega*. * If B is even (or odd): * test up to the first period of \omega for * Q[k]=(-1)^{k}N/|N| (Q[k]=2(-1)^{k}N/|N|) if l is even, * but up to the second period, if l is odd. * Similarly for \omega* but with Q[k]=(-1)^(k+1)N/|N| (Q[k]=2(-1)^(k+1)N/|N|) * There will be no solution if the test always fails. Otherwise * let X/y=p[k-1]/q[k-1], be the corresponding convergent. * Then x=y\theta+|N|X will be a solution of our diophantine equation * for the class determined by n. Choose y to be minimal. * If FLAG = 1, we print output, as GCD(A,N)=1 in BINARYFORM1. * If FLAG = 0, we do not print output, as GCD(A,N)>1 in BINARYFORM1. */ { MPI *L, *TMP1, *TMP2, *FOUR, *D, *ABSN, *THETA, *TMP3, *TMP4, *MODULUS; MPI *Q, *n, *P, *P01, *P02, *Q01, *Q02, *MINUSQ, *MINUS2Q; MPI *ONE, *X, *TWOQ, *Y, *TWOABSN, *x, *y, *SUM; MPI *Z, *DELTA, *BETA, *TWOA, *TWOC, *TMP5, *TMP6; MPIA SOL, AA1, U1, V1, P1, Q1; MPIA AA2, U2, V2, P2, Q2, FSX, FSY; USL l, v1, v2; USI s, t, period_length, k, r1, r2, r, d1, d2, flag = 0; USI i, FLAGE = 0, FLAG1 = 0, FLAG2 = 0; int tt, ttt, u, n1 = 0; FILE *outfile; char buff[20]; TWOA = MULT_I(A, 2); TWOC = MULT_I(C, 2); /* first solve the congruence a\theta^2+b\theta+c=0 (mod |N|) */ L = QUADRATIC(A,B,C,N,&SOL); if(L->S == 0){ FREEMPI(L); FREEMPIA(SOL); execerror("There are no primitive solutions", ""); } FSX = BUILDMPIA(); FSY = BUILDMPIA(); strcpy(buff, "binform.out"); outfile = fopen(buff, "a"); /* Let \Delta = B[1]^2-ac if B=2*B[1], else D = B^2-4AC. */ TMP1 = MULTI(B, B); FOUR = CHANGEI(4); TMP2 = MULTI3(FOUR, A, C); FREEMPI(FOUR); D = SUBI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); t = (B->V[0]) % 2; if(t){ printf("D="); fprintf(outfile, "D="); PRINTI(D); FPRINTI(outfile, D); printf("\n"); fprintf(outfile, "\n"); if(((D->D == 0) && (D->V[0] == 5)) && (((A->S) * (N ->S)) == -1)) flag = 1; } else{ TMP1 = D; D = INT_(D, 4); FREEMPI(TMP1); printf("Delta="); fprintf(outfile, "Delta="); PRINTI(D); FPRINTI(outfile, D); printf("\n"); fprintf(outfile, "\n"); } ABSN = ABSI(N); TWOABSN = MULT_I(ABSN, 2); tt = N->S; Q = MULTI(A, ABSN); TWOQ = MULT_I(Q, 2); MINUS2Q = MINUSI(TWOQ); MINUSQ = MINUSI(Q); ONE = ONEI(); l = CONVERTI(L); FREEMPI(L); for (r = 0; r < l; r++){ THETA = COPYI(SOL->A[r]); if(verbose){ printf("THETA[%u]=", r); fprintf(outfile, "THETA[%u]=", r); PRINTI(THETA); FPRINTI(outfile, THETA); printf("\n"); fprintf(outfile, "\n"); } TMP1 = MULT_I(THETA, 2); TMP2 = MULTI(TMP1, A); FREEMPI(TMP1); n = ADDI(TMP2, B); FREEMPI(TMP2); P = INT_(n, 2); if(verbose){ printf("n="); fprintf(outfile, "n="); PRINTI(n); FPRINTI(outfile, n); printf("\n"); fprintf(outfile, "\n"); } if (t == 0){ P01 = MINUSI(P); P02 = COPYI(P); Q01 = COPYI(Q); Q02 = COPYI(MINUSQ); } else{ P01 = MINUSI(n); P02 = COPYI(n); Q01 = COPYI(TWOQ); Q02 = COPYI(MINUS2Q); } period_length = SURD(D, ONE, P01, Q01, &AA1, &U1, &V1, &P1, &Q1, 1); period_length = SURD(D, ONE, P02, Q02, &AA2, &U2, &V2, &P2, &Q2, 1); if(period_length %2) period_length = 2 * period_length; r1 = AA1->size; r2 = AA2->size; if(flag){ s = r1 - period_length; if (s > 1){ TMP1 = SUBI(P1->A[s - 1], P1->A[s - 2]); TMP2 = SUBI(Q1->A[s - 1], Q1->A[s - 2]); TMP3 = MULTI(ABSN, TMP1); TMP4 = MULTI(THETA, TMP2); X = ADDI(TMP3, TMP4); FREEMPI(TMP1); FREEMPI(TMP3); FREEMPI(TMP4); } else{ TMP1 = ONEI(); X = SUBI(P1->A[0], TMP1); FREEMPI(TMP1); TMP2 = COPYI(Q1->A[0]); } /* print from here */ if(verbose){ printf("Exceptional solution: s=%u, (X,Y) = (", s); fprintf(outfile, "Exceptional solution: s=%u, (X,Y) = (", s); PRINTI(X); FPRINTI(outfile, X); printf(", "); fprintf(outfile, ", "); PRINTI(TMP2); FPRINTI(outfile, TMP2); printf(")\n"); fprintf(outfile, ")\n"); GetReturn(); } /* to from here */ ADD_TO_MPIA(FSX, X, n1); ADD_TO_MPIA(FSY, TMP2, n1); FLAGE = 1; FREEMPI(X); FREEMPI(TMP2); } for( k = 1; k < r1; k++){ ttt = (k % 2) ? -1 : 1; d1 = (V1->A[k])->D; v1 = (V1->A[k])->V[0]; /*printf("V1->A[%u]=", k); PRINTI(V1->A[k]);printf("\n"); */ if((!t && ((d1 == 0) && (v1 == 1))) || (t && ((d1 == 0) && (v1 == 2)))){ if(verbose){ printf("processing omega:\n"); fprintf(outfile, "processing omega:\n"); printf("rcf:("); fprintf(outfile, "rcf:("); PRINTI(P01); FPRINTI(outfile, P01); printf("+sqrt("); fprintf(outfile, "+sqrt("); PRINTI(D); FPRINTI(outfile, D); printf("))/"); fprintf(outfile, "))/"); PRINTI(Q01); FPRINTI(outfile, Q01); printf("\n"); fprintf(outfile, "\n"); GetReturn(); } if (!flag && ((V1->A[k])->S == ttt * tt)){/* calculate x=y\theta+|N|X */ TMP1 = MULTI(ABSN, P1->A[k - 1]); TMP2 = MULTI(THETA, Q1->A[k - 1]); X = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); Y = COPYI(Q1->A[k - 1]); /* print from here */ if(verbose){ printf("(X1,Y1) = ("); fprintf(outfile, "(X1,Y1) = ("); PRINTI(X); FPRINTI(outfile, X); printf(", "); fprintf(outfile, ", "); PRINTI(Y); FPRINTI(outfile, Y); printf(")\n"); fprintf(outfile, ")\n"); GetReturn(); } /* to from here */ ADD_TO_MPIA(FSX, X, n1); ADD_TO_MPIA(FSY, Y, n1); FREEMPI(X); FREEMPI(Y); FLAG1 = 1; break; } } } for( k = 1; k < r2; k++){ ttt = (k % 2) ? 1 : -1; d2 = (V2->A[k])->D ; v2 = (V2->A[k])->V[0]; /* printf("V2->A[%u]=", k); PRINTI(V2->A[k]);printf("\n");*/ if((!t && ((d2 == 0) && (v2 == 1))) || (t && ((d2 == 0) && (v2 == 2)))){ if(verbose){ printf("processing omega_star\n"); fprintf(outfile, "processing omega_star\n"); printf("rcf:("); fprintf(outfile, "rcf:("); PRINTI(P02); FPRINTI(outfile, P02); printf("+sqrt("); fprintf(outfile, "+sqrt("); PRINTI(D); FPRINTI(outfile, D); printf("))/"); fprintf(outfile, "))/"); PRINTI(Q02); FPRINTI(outfile, Q02); printf("\n"); fprintf(outfile, "\n"); GetReturn(); } if ((V2->A[k])->S == ttt * tt){/* calculate x=y\theta+|N|X */ TMP1 = MULTI(ABSN, P2->A[k - 1]); TMP2 = MULTI(THETA, Q2->A[k - 1]); X = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); Y = COPYI(Q2->A[k - 1]); /* print from here */ if(verbose){ printf("(X2,Y2) = ("); fprintf(outfile, "(X2,Y2) = ("); PRINTI(X); FPRINTI(outfile, X); printf(", "); fprintf(outfile, ", "); PRINTI(Y); FPRINTI(outfile, Y); printf(")\n"); fprintf(outfile, ")\n"); GetReturn(); } /* to from here */ if(!FLAG1 && !FLAGE){ ADD_TO_MPIA(FSX, X, n1); ADD_TO_MPIA(FSY, Y, n1); FLAG2 = 1; } else{ u = RSV(FSY->A[n1], Y); if(u > 0){ TMP1 = FSX->A[n1]; TMP2 = FSY->A[n1]; FSX->A[n1] = COPYI(X); FSY->A[n1] = COPYI(Y); FREEMPI(TMP1); FREEMPI(TMP2); } } FREEMPI(X); FREEMPI(Y); break; } } } if(FLAGE || FLAG1 || FLAG2){ n1++; FLAGE = 0; FLAG1 = 0; FLAG2 = 0; } FREEMPIA(AA1); FREEMPIA(AA2); FREEMPIA(U1); FREEMPIA(U2); FREEMPIA(V1); FREEMPIA(V2); FREEMPIA(P1); FREEMPIA(P2); FREEMPIA(Q1); FREEMPIA(Q2); FREEMPI(THETA); FREEMPI(P01); FREEMPI(P02); FREEMPI(Q01); FREEMPI(Q02); FREEMPI(P); FREEMPI(n); } /*TMP1 = MULTI(A, N); t = EQONEI(TMP1); FREEMPI(TMP1); if(t && (n1 == 0)){ ADD_TO_MPIA(FSX, ONE, n1); TMP1 = ZEROI(); ADD_TO_MPIA(FSY, TMP1, n1); FREEMPI(TMP1); n1++; }*/ if(FLAG){ if(n1 == 0) printf("There are no primitive solutions (x,y)!\n"); else{ for (i = 0; i < n1; i++){ printf("solution ("); fprintf(outfile, "solution ("); PRINTI(FSX->A[i]); FPRINTI(outfile, FSX->A[i]); printf(","); fprintf(outfile, ","); PRINTI(FSY->A[i]); FPRINTI(outfile, FSY->A[i]); printf(")"); fprintf(outfile, ")"); x = FSX->A[i]; y = FSY->A[i]; Z = EUCLIDI(x, y, &DELTA, &BETA); FREEMPI(Z); BETA->S = -(BETA->S); /* x(DELTA)-y(BETA)=1 */ TMP1 = MULTI3(TWOA, x, BETA); TMP2 = MULTI3(TWOC, y, DELTA); TMP5 = MULTI3(B, x, DELTA); TMP6 = MULTI3(B, BETA, y); /* now add TMP1, TMP2, TPM5, TMP6 */ SUM = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); FREEMPI(BETA); FREEMPI(DELTA); TMP1 = SUM; SUM = ADDI(SUM, TMP5); FREEMPI(TMP1); FREEMPI(TMP5); TMP1 = SUM; SUM = ADDI(SUM, TMP6); FREEMPI(TMP1); FREEMPI(TMP6); TMP1 = SUM; SUM = MOD(SUM, TWOABSN); FREEMPI(TMP1); if(RSV(SUM, ABSN) > 0){ TMP1 = SUM; SUM = SUBI(SUM, TWOABSN); FREEMPI(TMP1); } MODULUS = MULT_I(ABSN, 2); printf(": n = "); fprintf(outfile, ": n = "); PRINTI(SUM); FPRINTI(outfile, SUM); printf("(mod "); PRINTI(MODULUS); printf(")\n"); fprintf(outfile, "(mod "); FPRINTI(outfile, MODULUS); fprintf(outfile, ")\n"); FREEMPI(SUM); FREEMPI(MODULUS); GetReturn(); } } } FREEMPIA(SOL); FREEMPI(D); FREEMPI(Q); FREEMPI(ABSN); FREEMPI(TWOABSN); FREEMPI(TWOQ); FREEMPI(TWOA); FREEMPI(TWOC); FREEMPI(MINUSQ); FREEMPI(MINUS2Q); FREEMPI(ONE); *N1 = n1; *FSX1 = FSX; *FSY1 = FSY; fclose(outfile); return; } void BINARYFORM1(MPI *AA, MPI *BB, MPI *CC, MPI *NN, MPI *VERB) /* We reduce to the case GCD(AA,NN)=1 and then use BINARYFORM. * The n of p.3 of paper http://www.maths.uq.edu.au/~krm/binary.pdf * is also printed. * Verbose output if VERB = 1; otherwise 0; * Completed 21/12/00. */ { MPI *a, *b, *c, *x, *y, *TWOA, *TWOC, *MODULUS; MPI *G, *alpha, *beta, *M, *gamma, *delta, *Z; MPI *ABSN, *TWOABSN, *BETA, *DELTA, *X, *D, *FOUR; MPI *TMP1, *TMP2, *TMP3, *TMP4, *TMP5, *TMP6, *SUM; MPI *A, *B, *C, *N; USI t, length, i, FLAG = 0, verb; MPIA FSX1, FSY1; int s; FILE *outfile; char buff[20]; strcpy(buff, "binform.out"); outfile = fopen(buff, "w"); /* Check that NN is non-zero */ s = NN->S; if (s == 0) { printf("NN = 0\n"); return; } /* Check to see d=gcd(AA,BB,CC) divides NN and if so * to replace AA,BB,CC,NN by AA/d,BB/d,CC/d,NN/d. */ TMP1 = GCD(AA,BB); TMP2 = GCD(TMP1,CC); TMP3 = MOD(NN, TMP2); s = TMP3->S; FREEMPI(TMP1); FREEMPI(TMP3); if (s){ printf("gcd(A,B,C) does not divide N\n"); FREEMPI(TMP2); return; } else{ A = INT(AA, TMP2); B = INT(BB, TMP2); C = INT(CC, TMP2); N = INT(NN, TMP2); } FREEMPI(TMP2); /* Check that B^2-4AC > 0 */ TMP1 = MULTI(B, B); FOUR = CHANGEI(4); TMP2 = MULTI3(FOUR, A, C); FREEMPI(FOUR); D = SUBI(TMP1, TMP2); s = D->S; FREEMPI(TMP1); FREEMPI(TMP2); if (s <= 0) { printf("D <= 0\n"); FREEMPI(D); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(N); return; } /* Check that B^2-4AC is not a perfect square */ X = BIG_MTHROOT(D, 2); G = MULTI(X, X); t = EQUALI(D, G); FREEMPI(G); FREEMPI(X); FREEMPI(D); if (t) { printf("D is a perfect square\n"); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(N); return; } TWOA = MULT_I(A, 2); TWOC = MULT_I(C, 2); ABSN = ABSI(N); TWOABSN = MULT_I(ABSN, 2); G = GCD(A,N); t = EQONEI(G); FREEMPI(G); if(t){ a = COPYI(A); b = COPYI(B); c = COPYI(C); FLAG = 1; } else{ GAUSS(A, B, C, N, &alpha, &gamma, &M); Z = EUCLIDI(alpha, gamma, &delta, &beta); FREEMPI(Z); beta->S = -(beta->S); a = M; strcpy(buff, "binform.out"); outfile = fopen(buff, "w"); /* alpha * delta - beta * gamma = 1 */ if(VERB->S){ printf("alpha=");PRINTI(alpha);printf("\n"); fprintf(outfile, "alpha=");FPRINTI(outfile, alpha);fprintf(outfile, "\n"); printf("beta=");PRINTI(beta);printf("\n"); fprintf(outfile, "beta=");FPRINTI(outfile, beta);fprintf(outfile, "\n"); printf("gamma=");PRINTI(gamma);printf("\n"); fprintf(outfile, "gamma=");FPRINTI(outfile, gamma);fprintf(outfile, "\n"); printf("delta=");PRINTI(delta);printf("\n"); fprintf(outfile, "delta=");FPRINTI(outfile, delta);fprintf(outfile, "\n"); GetReturn(); } /* now calculate a, b, c, when A*x^2+B*x*y+C*y^2 is transformed into a*X^2+b*X*Y+c*Y^2 under the transformation x=alpha*X+beta*Y, y=gamma*X+delta*Y */ TMP1 = MULTI3(A, beta, beta); TMP2 = MULTI3(B, beta, delta); TMP3 = MULTI3(C, delta, delta); TMP4 = ADDI(TMP1, TMP2); c = ADDI(TMP4, TMP3); FREEMPI(TMP1); FREEMPI(TMP2); FREEMPI(TMP3); FREEMPI(TMP4); TMP1 = MULTI3(TWOA, alpha, beta); TMP2 = MULTI3(TWOC, gamma, delta); TMP5 = MULTI3(B, alpha, delta); TMP6 = MULTI3(B, beta, gamma); /* now add TMP1, TMP2, TPM5, TMP6 */ SUM = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); TMP1 = SUM; SUM = ADDI(SUM, TMP5); FREEMPI(TMP1); FREEMPI(TMP5); TMP1 = SUM; SUM = ADDI(SUM, TMP6); FREEMPI(TMP1); FREEMPI(TMP6); b = COPYI(SUM); FREEMPI(SUM); /* Now we have gcd(a,N)=1 */ } verb = CONVERTI(VERB); fclose(outfile); BINARYFORM(a, b, c, N, &FSX1, &FSY1, &length, FLAG, verb); outfile = fopen(buff, "a"); if(!t){ for(i = 0; i < length; i++){ printf("i=%u: ",i); fprintf(outfile, "i=%u: ",i); TMP1 = MULTI(alpha, FSX1->A[i]); TMP2 = MULTI(beta, FSY1->A[i]); TMP3 = MULTI(gamma, FSX1->A[i]); TMP4 = MULTI(delta, FSY1->A[i]); x = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); y = ADDI(TMP3, TMP4); FREEMPI(TMP3); FREEMPI(TMP4); printf("Solution ("); fprintf(outfile, "Solution ("); PRINTI(x); FPRINTI(outfile, x); printf(","); fprintf(outfile, ","); PRINTI(y); FPRINTI(outfile, y); printf("): "); fprintf(outfile, "): "); Z = EUCLIDI(x, y, &DELTA, &BETA); FREEMPI(Z); BETA->S = -(BETA->S); TMP1 = MULTI3(TWOA, x, BETA); TMP2 = MULTI3(TWOC, y, DELTA); TMP5 = MULTI3(B, x, DELTA); TMP6 = MULTI3(B, BETA, y); /* now add TMP1, TMP2, TPM5, TMP6 */ SUM = ADDI(TMP1, TMP2); FREEMPI(TMP1); FREEMPI(TMP2); FREEMPI(BETA); FREEMPI(DELTA); TMP1 = SUM; SUM = ADDI(SUM, TMP5); FREEMPI(TMP1); FREEMPI(TMP5); TMP1 = SUM; SUM = ADDI(SUM, TMP6); FREEMPI(TMP1); FREEMPI(TMP6); TMP1 = SUM; SUM = MOD(SUM, TWOABSN); FREEMPI(TMP1); if(RSV(SUM, ABSN) > 0){ TMP1 = SUM; SUM = SUBI(SUM, TWOABSN); FREEMPI(TMP1); } MODULUS = MULT_I(ABSN, 2); printf(": n = "); fprintf(outfile, ": n = "); PRINTI(SUM); FPRINTI(outfile, SUM); printf("(mod "); PRINTI(MODULUS); printf(")\n"); fprintf(outfile, "(mod "); FPRINTI(outfile, MODULUS); fprintf(outfile, ")\n"); FREEMPI(SUM); FREEMPI(MODULUS); FREEMPI(x); FREEMPI(y); } FREEMPI(alpha); FREEMPI(beta); FREEMPI(gamma); FREEMPI(delta); } FREEMPIA(FSX1); FREEMPIA(FSY1); FREEMPI(a); FREEMPI(b); FREEMPI(c); FREEMPI(TWOA); FREEMPI(TWOC); FREEMPI(ABSN); FREEMPI(TWOABSN); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(N); fclose(outfile); return; }