www.pudn.com > calc.rar > i6R.c
/* i6R.c */ /* matrix operations using MPR's */ #include/*#include */ #include #include #include "integer.h" #include "fun.h" MPMATR *TRANSPOSER(MPMATR *Mptr); MPMATR *MULTMATR(MPMATR *Mptr, MPMATR *Nptr); extern USI GCDVERBOSE; extern USI GCD3FLAG; extern USI GCD_MAX; MPMATR *BUILDMATR(USI m, USI n) /* * Allocates space for an m x n matrix of MPR's. */ { MPMATR *N; N=(MPMATR *)mmalloc(sizeof(MPMATR)); N->R = m; N->C = n; N->V = (MPR **)mmalloc(m * n * sizeof(MPR *)); return (N); } MPMATR *COPYMATR(MPMATR *Mptr) /* * a replacement for the assignment *Nptr = *Mptr. */ { unsigned int i, t; MPMATR *Nptr; t = Mptr->R * Mptr->C; Nptr = BUILDMATR(Mptr->R, Mptr->C); for (i = 0; i < t; i++) Nptr->V[i] = COPYR(Mptr->V[i]); return (Nptr); } void FREEMATR(MPMATR *Mptr) /* * frees the storage allocated to the two-dimensional array Mptr->V. */ { unsigned int i, t; if (Mptr == NULL) return; t = Mptr->R * Mptr->C; for (i = 0; i < t; i++) FREEMPR(Mptr->V[i]); ffree((char *)(Mptr->V), t * sizeof(MPR *)); ffree((char *)Mptr, sizeof(MPMATR)); return; } MPMATR *CHOLESKYR(MPMATR *A) /* * Input: A positive definite matrix A. * Output: The Cholesky decomposition of A. * See U.Finke and M. Pohst, "Improved methods for calculating vectors of * short length in a lattice, including a complexity analysis." Math. Comp. * 44, 463-471, 1985 */ { MPMATR *Q; unsigned int i, j, k, l, m; MPR *temp1, *temp2; m = A->R; Q = ZEROMNR(m, m); for (i = 0; i < m; i++) { for (j = i; j < m; j++) { FREEMPR(elt(Q, i, j)); elt(Q, i, j) = COPYR(elt(A, i, j)); } } for (i = 0; i < m - 1; i++) { for (j = i + 1; j < m; j++) { FREEMPR(elt(Q, j, i)); elt(Q, j, i) = COPYR(elt(Q, i, j)); temp1 = elt(Q, i, j); elt(Q, i, j) = RATIOR(elt(Q, i, j), elt(Q, i, i)); FREEMPR(temp1); } for (k = i + 1; k < m; k++) { for (l = k; l < m; l++) { temp1 = elt(Q, k, l); temp2 = MULTR(elt(Q, k, i), elt(Q, i, l)); elt(Q, k, l) = SUBR(temp1, temp2); FREEMPR(temp1); FREEMPR(temp2); } } } for (j = 0; j < m - 1; j++) { for (i = j + 1; i < m; i++) { FREEMPR(elt(Q, i, j)); elt(Q, i, j) = ZEROR(); } } return (Q); } void FINCKE_POHST(MPMATR *A, MPR *C, USI filename) /* * Input: A matrix of integers A with LI rows spanning a lattice L. * Output: The integer vectors X with ||X||^2 <= C, highest nonzero coord <=0. * See "Improved methods for calculating vectors of short length in a lattice, * including a complexity analysis, U. Fincke and M. Pohst, * Mathematics of Computation, 44, 1985, 463-471. */ { unsigned int i, j, n, flag, *l, *u, *t, *x, count = 0; unsigned int FLAG; MPR **X, **L, **T, **U, *Temp1, *Temp2, *Temp3, *Z, *ONE, *SUM; MPR *temp; char buff[20]; FILE *outfile; MPMATR *B, *BB, *Q, *VECTOR, *MATR; MPMATI *MATI; int e; B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); if (filename == 1) strcpy(buff, "fp.out"); else strcpy(buff, "slv.out"); outfile = fopen(buff, "w"); n = Q->R; i = n - 1; ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } T[i] = COPYR(C); t[i] = 1; U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = MINUSR(U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); FREEMPR(Temp2); Temp2 = INTROOT(Z, U[i]); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp2 = MULTR(Temp1, Temp1); FREEMPR(Temp1); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: flag = 0; for (j = 0; j < n; j++) { if (!EQZEROR(X[j])) { flag = 1; break; } } if (flag == 0) { FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); } ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); fclose(outfile); FREEMATR(Q); return; } else { VECTOR = BUILDMATR(1, A->R); printf("LATTICE_VECTOR[%u] = ", count + 1); fprintf(outfile, "LATTICE_VECTOR[%u]:", count + 1); FLAG = 0; for (j = 0; j < A->R; j++) { e = (X[j]->N)->S; if (e == -1) { if (FLAG) { printf("+"); fprintf(outfile, "+"); } if (FLAG == 0) FLAG = 1; temp = MINUSR(X[j]); if (!EQONER(temp)) { PRINTR(temp); FPRINTR(outfile, temp); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); FREEMPR(temp); } if (e == 1) { if (FLAG == 0) FLAG = 1; printf("-"); fprintf(outfile, "-"); if (!EQONER(X[j])) { PRINTR(X[j]); FPRINTR(outfile, X[j]); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); } elt(VECTOR, 0, j) = MINUSR(X[j]); } MATR = MULTMATR(VECTOR, A); FREEMATR(VECTOR); printf("="); fprintf(outfile, "="); MATI = BUILDMATI(1, A->C); for (j = 0; j < A->C; j++) { MATI->V[0][j] = COPYI((elt(MATR, 0, j))->N); PRINTI(MATI->V[0][j]); FPRINTI(outfile, MATI->V[0][j]); printf(" "); fprintf(outfile, " "); } printf(": "); fprintf(outfile, ": "); FREEMATR(MATR); FREEMATI(MATI); Temp1 = ADDR(X[0], U[0]); Temp2 = MULTR(Temp1, Temp1); FREEMPR(Temp1); Temp1 = MULTR(elt(Q, 0, 0), Temp2); FREEMPR(Temp2); Temp2 = SUBR(C, T[0]); Temp3 = ADDR(Temp2, Temp1); FREEMPR(Temp1); FREEMPR(Temp2); PRINTR(Temp3); FPRINTR(outfile, Temp3); printf("\n"); fprintf(outfile, "\n"); FREEMPR(Temp3); count++; goto loop; } } MPR *SLVECTOR(MPMATR *A, MPR *C, MPR **VALUE) /* * Input: A matrix of integers A with LI LLL reduced rows spanning a lattice L. * C is the length-squared of a small lattive vector. * Output: if 0 is returned, this means that VALUE is the shortest length. * Then in nfunc.c, FINCKE-POHST is applied to get all the shortest vectors in * L with highest nonzero coord > 0 are printed. * Otherwise a shorter length is returned and VALUE will be NULL. * See "Improved methods for calculating vectors of short length in a lattice, * including a complexity analysis, U. Fincke and M. Pohst, * Mathematics of Computation, 44, 1985, 463-471. */ { unsigned int i, j, n, flag, *l, *u, *t, *x, count = 0; MPR **X, **L, **T, **U, *Temp1, *Temp2, *Temp3, *Z, *ONE, *SUM; MPMATR *B, *BB, *Q; int s1, s2; *VALUE = (MPR *)NULL; B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); n = Q->R; i = n - 1; ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } T[i] = COPYR(C); t[i] = 1; U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = MINUSR(U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); FREEMPR(Temp2); Temp2 = INTROOT(Z, U[i]); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp2 = MULTR(Temp1, Temp1); FREEMPR(Temp1); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: flag = 0; for (j = 0; j < n; j++) { if (!EQZEROR(X[j])) { flag = 1; break; } } if (flag == 0) { FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); } ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); FREEMATR(Q); return (ZEROR()); } else { Temp1 = ADDR(X[0], U[0]); Temp2 = MULTR(Temp1, Temp1); FREEMPR(Temp1); Temp1 = MULTR(elt(Q, 0, 0), Temp2); FREEMPR(Temp2); Temp2 = SUBR(C, T[0]); Temp3 = ADDR(Temp2, Temp1); FREEMPR(Temp1); FREEMPR(Temp2); s1 = (Temp3->N)->S; if (s1) { if (*VALUE != NULL) FREEMPR(*VALUE); *VALUE = COPYR(Temp3); } s2 = RSV(Temp3->N, C->N); if (s1 && s2 == -1) { FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); } ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); FREEMATR(Q); return(Temp3); } FREEMPR(Temp3); count++; goto loop; } } MPR *INTROOT(MPR *Z, MPR *U) /* * Returns [sqrt(Z)+U]. First ANSWER = [sqrt(Z)] + [U]. One then * tests if Z < ([sqrt(Z)] + 1 -{U})^2. If this does not hold, ANSWER++. * For use in FINCKE_POHST(). */ { int t; MPR *X, *Y, *ANSWER, *R, *S, *T1, *T2, *ONE, *Temp; if (EQZEROR(Z)) return (INTR(U)); ONE = ONER(); X = MTHROOTR(Z, 2, 0); Y = INTR(U); ANSWER = ADDR(X, Y); R = SUBR(U, Y); FREEMPR(Y); S = SUBR(ONE, R); FREEMPR(R); T1 = ADDR(X, S); FREEMPR(S); FREEMPR(X); T2 = MULTR(T1, T1); FREEMPR(T1); t = COMPARER(T2, Z); FREEMPR(T2); if (t <= 0) { Temp = ANSWER; ANSWER = ADDR(ANSWER, ONE); FREEMPR(Temp); } FREEMPR(ONE); return (ANSWER); } int COMPARER(MPR *Aptr, MPR *Bptr) /* * 1 if *Aptr > *Bptr * Returns 0 if *Aptr = *Bptr * -1 if *Aptr < *Bptr */ { MPI *T1, *T2; int t; T1 = MULTI(Aptr->N, Bptr->D); T2 = MULTI(Aptr->D, Bptr->N); t = COMPAREI(T1, T2); FREEMPI(T1); FREEMPI(T2); return (t); } MPMATR *ZEROMNR(USI m, USI n) /* * returns the zero m x n matrix. */ { unsigned int i, j; MPMATR *Mptr; Mptr = BUILDMATR(m, n); for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) elt(Mptr, i, j) = ZEROR(); } return (Mptr); } MPMATR *TRANSPOSER(MPMATR *Mptr) /* * returns the transpose of *Mptr. */ { MPMATR *Nptr; unsigned int i, j; Nptr = BUILDMATR(Mptr->C, Mptr->R); for (j = 0; j <= Nptr->R - 1; j++) for (i = 0; i <= Nptr->C - 1; i++) elt(Nptr, j, i) = COPYR(elt(Mptr, i, j)); return (Nptr); } MPMATR *MULTMATR(MPMATR *Mptr, MPMATR *Nptr) /* * Here Mptr->C = Nptr->R. * returns (*Mptr) * (*Nptr). */ { MPR *X, *Y, *Temp; unsigned int i, j, k; MPMATR *Lptr; Lptr = BUILDMATR(Mptr->R, Nptr->C); for (i = 0; i <= Mptr->R - 1; i++) { for (j = 0; j <= Nptr->C - 1; j++) { X = ZEROR(); for (k = 0; k <= Mptr->C - 1; k++) { Y = MULTR(elt(Mptr, i, k), elt(Nptr, k, j)); Temp = X; X = ADDR(X, Y); FREEMPR(Temp); FREEMPR(Y); } elt(Lptr, i, j) = X; } } return (Lptr); } void SHORTEST(MPMATI *AA, MPI *I[], USI filename, USI number) /* * Input: An m x m matrix of integers AA = Q arising from the EXTGCD * LLLGCD or LLLGCD0. The last row of AA is assumed to be a multiplier * of shortest length. * Output: All multipliers of shortest length. * filename:1->egcdmult.out,2->lllgcdmult.out,3->lllgcd0mult.out. * 4->gcd3.out (used in GCD3()). * If number = 0, no printing. * If number > 0 prints out multipliers on screen and in .out file. * Only used in nfunc.c. */ { unsigned int i, j, k, m, n, *l, *u, *t, *x, w, count = 0; MPR **X, **Y, **L, **T, **U, **V, *Temp0, *Temp1, *Temp2, *Temp3; MPR *C, *Z, *ONE, *SUM, **N, *temp, *tempR, **XX; MPI *lengthi; char buff[25]; FILE *outfile; MPMATR *A, *B, *BB, *Q, *QQ, *MATR, *VECTOR; MPMATI *MATI; int e; /* First get the vector [V[0],...,V[n-2], where V[i]=.*/ m = AA->C; n = (AA->R) - 1; A = BUILDMATR(n + 1, m); for (i = 0; i < n + 1; i++) for (j = 0; j < m; j++) { elt(A, i, j) = BUILDMPR(); elt(A, i, j)->N = COPYI(AA->V[i][j]); elt(A, i, j)->D = ONEI(); } V = (MPR **)mmalloc(n * sizeof(MPR *)); for (i = 0; i < n; i++) { V[i] = ZEROR(); for (j = 0; j < m; j++) { Temp1 = V[i]; Temp2 = MULTR(elt(A, n, j), elt(A, i, j)); V[i] = ADDR(V[i], Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } } B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); QQ = COPYMATR(Q); for (i = 0; i < n; i++) { FREEMPR(elt(QQ, i, i)); elt(QQ, i, i) = ONER(); } /* Calculate (U^{-1})^tV = Y */ MATR = QQ; QQ = TRANSPOSER(QQ); FREEMATR(MATR); Y = (MPR **)mmalloc(n * sizeof(MPR *)); Y[0] = COPYR(V[0]); for (w = 1; w < n; w++) { SUM = ZEROR(); for ( k = 0; k < w; k++) { Temp1 = SUM; Temp2 = MULTR(elt(QQ, w, k), Y[k]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } Y[w] = SUBR(V[w], SUM); FREEMPR(SUM); } FREEMATR(QQ); N = (MPR **)mmalloc(n * sizeof(MPR *)); for (j = 0; j < n; j++) N[j] = RATIOR(Y[j], elt(Q, j, j)); if (filename == 1) strcpy(buff, "egcdmult.out"); else if (filename == 2) strcpy(buff, "lllgcdmult.out"); else if (filename == 3) strcpy(buff, "lllgcd0mult.out"); else if (filename == 4) strcpy(buff, "gcd3.out"); else if (filename == 5) strcpy(buff, "axb.out"); outfile = fopen(buff, "a"); ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } C = ZEROR(); for (i = 0; i < n; i++) { Temp1 = C; Temp2 = MULTR(Y[i], Y[i]); Temp3 = RATIOR(Temp2, elt(Q, i, i)); C = ADDR(C, Temp3); FREEMPR(Temp1); FREEMPR(Temp2); FREEMPR(Temp3); } i = n - 1; T[i] = COPYR(C); t[i] = 1; FREEMPR(C); U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = SUBR(N[i], U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); FREEMPR(Temp2); Temp0 = SUBR(U[i], N[i]); Temp2 = INTROOT(Z, Temp0); FREEMPR(Temp0); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; if (i == n) goto exiting; else goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp0 = SUBR(Temp1, N[i]); FREEMPR(Temp1); Temp2 = MULTR(Temp0, Temp0); FREEMPR(Temp0); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: VECTOR = BUILDMATR(1, AA->R); XX = (MPR **)mmalloc((USL)(n * sizeof(MPR *))); for (j = 0; j < n; j++) { tempR = BUILDMPR(); tempR->N = COPYI(I[j]); tempR->D = ONEI(); XX[j] = ADDR(X[j], tempR); FREEMPR(tempR); } if (number) { printf("\tMULTIPLIER[%u] = ", count + 1); fprintf(outfile, "\tMULTIPLIER[%u]:", count + 1); printf("b[%u]", n + 1); fprintf(outfile, "b[%u]", n + 1); for (j = 0; j < n; j++) { e = (XX[j]->N)->S; if (e == -1) { printf("+"); fprintf(outfile, "+"); temp = MINUSR(XX[j]); if (!EQONER(temp)) { PRINTR(temp); FPRINTR(outfile, temp); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); FREEMPR(temp); } if (e == 1) { printf("-"); fprintf(outfile, "-"); if (!EQONER(XX[j])) { PRINTR(XX[j]); FPRINTR(outfile, XX[j]); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); } } } for (j = 0; j < n; j++) { elt(VECTOR, 0, j) = MINUSR(X[j]); FREEMPR(XX[j]); } ffree((char *)XX, n * sizeof(MPR *)); elt(VECTOR, 0, n) = ONER(); MATR = MULTMATR(VECTOR, A); FREEMATR(VECTOR); if (number) { printf("="); fprintf(outfile, "="); } MATI = BUILDMATI(1, m); for (j = 0; j < m; j++) MATI->V[0][j] = COPYI((elt(MATR, 0, j))->N); if (number) { for (j = 0; j < m; j++) { PRINTI(MATI->V[0][j]); FPRINTI(outfile, MATI->V[0][j]); printf(" "); fprintf(outfile, " "); } fprintf(outfile, ": "); printf(": "); } lengthi = LENGTHSQRI(MATI, 0); if (number) { FPRINTI(outfile, lengthi); fprintf(outfile, "\n"); PRINTI(lengthi); printf("\n"); } FREEMPI(lengthi); FREEMATR(MATR); FREEMATI(MATI); count++; goto loop; exiting: FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(N[j]); FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); FREEMPR(Y[j]); FREEMPR(V[j]); } ffree((char *)N, n * sizeof(MPR *)); ffree((char *)V, n * sizeof(MPR *)); ffree((char *)Y, n * sizeof(MPR *)); ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); FREEMATR(Q); FREEMATR(A); if (number) { if (count > 1) { fprintf(outfile, "\tThere are exactly %u shortest multiplier vectors\n", count); printf("\tThere are exactly %u shortest multiplier vectors\n", count); } if (count == 1) { printf("\tThere is exactly one shortest multiplier vector\n"); fprintf(outfile, "\tThere is exactly one shortest multiplier vector\n"); } } fclose(outfile); return; } void SHORTESTTT(MPMATI *AA, MPI *BOUND) /* * This is used in INHOMFP(). * Input: An m x M matrix of integers AA whose first m - 1 rows Q[0],... * ,Q[m-2] are LI and span a lattice L. * Output: If P is the last row, finds all x[0],...,x[m-2] * satisfying ||P -x[0]Q[0]-...-x[m-2]Q[m-2]||^2<=BOUND. */ { unsigned int i, j, k, m, n, *l, *u, *t, *x, w, count = 0; unsigned int M, FLAG; MPR **X, **Y, **L, **T, **U, **V, *Temp0, *Temp1, *Temp2, *Temp3; MPR *C, *Z, *ONE, *SUM, **N, *temp; MPI *lengthi, *lengthj, *TempI1, *TempI2; MPMATR *A, *B, *BB, *Q, *QQ, *MATR, *VECTOR; MPMATI *MATI; int e; char buff[25]; FILE *outfile; strcpy(buff, "inhomfp.out"); outfile = fopen(buff, "w"); /* Compute ||AA[m - 1][*]||^2. */ m = AA->R; M = AA->C; n = m - 1; lengthj = ZEROI(); for (j = 0; j < M; j++) { TempI1 = lengthj; TempI2 = MULTI(AA->V[n][j], AA->V[n][j]); lengthj = ADDI(lengthj, TempI2); FREEMPI(TempI1); FREEMPI(TempI2); } /* First get the vector [V[0],...,V[n-2], where V[i]=.*/ A = BUILDMATR(m, M); for (i = 0; i < m; i++) for (j = 0; j < M; j++) { elt(A, i, j) = BUILDMPR(); elt(A, i, j)->N = COPYI(AA->V[i][j]); elt(A, i, j)->D = ONEI(); } V = (MPR **)mmalloc(n * sizeof(MPR *)); for (i = 0; i < n; i++) { V[i] = ZEROR(); for (j = 0; j < M; j++) { Temp1 = V[i]; Temp2 = MULTR(elt(A, n, j), elt(A, i, j)); V[i] = ADDR(V[i], Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } } B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); QQ = COPYMATR(Q); for (i = 0; i < n; i++) { FREEMPR(elt(QQ, i, i)); elt(QQ, i, i) = ONER(); } /* Calculate (U^{-1})^tV = Y */ MATR = QQ; QQ = TRANSPOSER(QQ); FREEMATR(MATR); Y = (MPR **)mmalloc(n * sizeof(MPR *)); Y[0] = COPYR(V[0]); for (w = 1; w < n; w++) { SUM = ZEROR(); for ( k = 0; k < w; k++) { Temp1 = SUM; Temp2 = MULTR(elt(QQ, w, k), Y[k]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } Y[w] = SUBR(V[w], SUM); FREEMPR(SUM); } FREEMATR(QQ); N = (MPR **)mmalloc(n * sizeof(MPR *)); for (j = 0; j < n; j++) N[j] = RATIOR(Y[j], elt(Q, j, j)); ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } C = ZEROR(); for (i = 0; i < n; i++) { Temp1 = C; Temp2 = MULTR(Y[i], Y[i]); Temp3 = RATIOR(Temp2, elt(Q, i, i)); C = ADDR(C, Temp3); FREEMPR(Temp1); FREEMPR(Temp2); FREEMPR(Temp3); } Temp0 = BUILDMPR(); Temp0->N = SUBI(BOUND, lengthj); Temp0->D = ONEI(); Temp1 = C; C = ADDR(C, Temp0); FREEMPR(Temp0); FREEMPR(Temp1); i = n - 1; T[i] = COPYR(C); t[i] = 1; FREEMPR(C); U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = SUBR(N[i], U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); /*printf("at L[%u]\n", i);*/ FREEMPR(Temp2); Temp0 = SUBR(U[i], N[i]); Temp2 = INTROOT(Z, Temp0); FREEMPR(Temp0); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; if (i == n) goto exiting; else goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp0 = SUBR(Temp1, N[i]); FREEMPR(Temp1); Temp2 = MULTR(Temp0, Temp0); FREEMPR(Temp0); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: VECTOR = BUILDMATR(1, AA->R); for (j = 0; j < n; j++) { /* printf("X[%u][%u] = ", count, j); PRINTR(X[j]); printf("\n"); fprintf(outfile, "X[%u][%u] = ", count, j); FPRINTR(outfile, X[j]); fprintf(outfile,"\n"); */ elt(VECTOR, 0, j) = COPYR(X[j]); } elt(VECTOR, 0, n) = ZEROR(); MATR = MULTMATR(VECTOR, A); FREEMATR(VECTOR); printf("LV[%u] = ", count + 1); fprintf(outfile, "LV[%u] = ", count + 1); FLAG = 0; for (j = 0; j < n; j++) { e = (X[j]->N)->S; if (e == -1) { if (FLAG == 0) FLAG = 1; printf("-"); fprintf(outfile, "-"); temp = MINUSR(X[j]); if (!EQONER(temp)) { PRINTR(temp); FPRINTR(outfile, temp); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); FREEMPR(temp); } if (e == 1) { if (FLAG) { printf("+"); fprintf(outfile, "+"); } if (FLAG == 0) FLAG = 1; if (!EQONER(X[j])) { PRINTR(X[j]); FPRINTR(outfile, X[j]); } printf("b[%u]", j + 1); fprintf(outfile, "b[%u]", j + 1); } } printf("="); fprintf(outfile, "="); MATI= BUILDMATI(1, A->C); for (j = 0; j < A->C; j++) { MATI->V[0][j] = COPYI((elt(MATR, 0, j))->N); PRINTI(MATI->V[0][j]); FPRINTI(outfile, MATI->V[0][j]); printf(" "); fprintf(outfile, " "); FREEMPI(MATI->V[0][j]); MATI->V[0][j] = SUBI(AA->V[n][j], ((elt(MATR, 0, j))->N)); } printf(": ||b[%u]-LV[%u]||^2=", AA->R, count + 1); fprintf(outfile, ": ||b[%u]-LV[%u]||^2=", AA->R, count + 1); lengthi = LENGTHSQRI(MATI, 0); PRINTI(lengthi); FPRINTI(outfile, lengthi); printf("\n"); fprintf(outfile, "\n"); FREEMPI(lengthi); FREEMATR(MATR); FREEMATI(MATI); count++; goto loop; exiting: FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(N[j]); FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); FREEMPR(Y[j]); FREEMPR(V[j]); } ffree((char *)N, n * sizeof(MPR *)); ffree((char *)V, n * sizeof(MPR *)); ffree((char *)Y, n * sizeof(MPR *)); ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); fclose(outfile); FREEMATR(Q); FREEMATR(A); FREEMPI(lengthj); if (count > 1) printf("There are exactly %u lattice vectors\n", count); if (count == 1) printf("There is exactly one lattice vector\n"); return; } MPMATI *SHORTESTT0(MPMATI *AA, MPI **XX[]) /* * Used in EXTGCD(), LLLGCD() and LLLGCD0() in nfunc.c. * Input: An m x M matrix of integers AA whose first m - 1 rows * Q[0],...,Q[m-2] are LI and span a lattice L. * Problem: If P is the last row, find a shorter multiplier * P-x[0]Q[0]-...-x[m-2]Q[m-2] */ { unsigned int i, j, k, m, n, *l, *u, *t, *x, w; unsigned int FOUND = 0, M; MPR **X, **Y, **L, **T, **U, **V, *Temp0, *Temp1, *Temp2, *Temp3; MPR *C, *Z, *ONE, *SUM, **N; MPI *lengthi, *lengthj, *TempI1, *TempI2; MPMATR *A, *B, *BB, *Q, *QQ, *MATR, *VECTOR; MPMATI *MATI; int tt; MATI = NULL; /* Compute ||AA[m - 1][*]||^2. */ m = AA->R; M = AA->C; n = m - 1; *XX = (MPI **)mmalloc((USL)(n * sizeof(MPI *))); lengthj = ZEROI(); for (j = 0; j < M; j++) { TempI1 = lengthj; TempI2 = MULTI(AA->V[n][j], AA->V[n][j]); lengthj = ADDI(lengthj, TempI2); FREEMPI(TempI1); FREEMPI(TempI2); } /* First get the vector [V[0],...,V[n-2], where V[i]=.*/ A = BUILDMATR(m, M); for (i = 0; i < m; i++) for (j = 0; j < M; j++) { elt(A, i, j) = BUILDMPR(); elt(A, i, j)->N = COPYI(AA->V[i][j]); elt(A, i, j)->D = ONEI(); } V = (MPR **)mmalloc(n * sizeof(MPR *)); for (i = 0; i < n; i++) { V[i] = ZEROR(); for (j = 0; j < M; j++) { Temp1 = V[i]; Temp2 = MULTR(elt(A, n, j), elt(A, i, j)); V[i] = ADDR(V[i], Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } } B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); QQ = COPYMATR(Q); for (i = 0; i < n; i++) { FREEMPR(elt(QQ, i, i)); elt(QQ, i, i) = ONER(); } /* Calculate (U^{-1})^tV = Y */ MATR = QQ; QQ = TRANSPOSER(QQ); FREEMATR(MATR); Y = (MPR **)mmalloc(n * sizeof(MPR *)); Y[0] = COPYR(V[0]); for (w = 1; w < n; w++) { SUM = ZEROR(); for ( k = 0; k < w; k++) { Temp1 = SUM; Temp2 = MULTR(elt(QQ, w, k), Y[k]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } Y[w] = SUBR(V[w], SUM); FREEMPR(SUM); } FREEMATR(QQ); N = (MPR **)mmalloc(n * sizeof(MPR *)); for (j = 0; j < n; j++) N[j] = RATIOR(Y[j], elt(Q, j, j)); ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } C = ZEROR(); for (i = 0; i < n; i++) { Temp1 = C; Temp2 = MULTR(Y[i], Y[i]); Temp3 = RATIOR(Temp2, elt(Q, i, i)); C = ADDR(C, Temp3); FREEMPR(Temp1); FREEMPR(Temp2); FREEMPR(Temp3); } i = n - 1; T[i] = COPYR(C); t[i] = 1; FREEMPR(C); U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = SUBR(N[i], U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); /*printf("at L[%u]\n", i);*/ FREEMPR(Temp2); Temp0 = SUBR(U[i], N[i]); Temp2 = INTROOT(Z, Temp0); FREEMPR(Temp0); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; if (i == n) goto exiting; else goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp0 = SUBR(Temp1, N[i]); FREEMPR(Temp1); Temp2 = MULTR(Temp0, Temp0); FREEMPR(Temp0); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: VECTOR = BUILDMATR(1, m); for (j = 0; j < n; j++) elt(VECTOR, 0, j) = MINUSR(X[j]); elt(VECTOR, 0, m - 1) = ONER(); MATR = MULTMATR(VECTOR, A); FREEMATR(VECTOR); MATI = BUILDMATI(1, M); for (j = 0; j < M; j++) MATI->V[0][j] = COPYI((elt(MATR, 0, j))->N); lengthi = LENGTHSQRI(MATI, 0); tt = RSV(lengthj, lengthi); FREEMPI(lengthi); FREEMATR(MATR); if (tt == 1) { FREEMPI(lengthj); FOUND = 1; for (j = 0; j < n; j++) (*XX)[j] = COPYI(X[j]->N); goto exiting; } else FREEMATI(MATI); goto loop; exiting: FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(N[j]); FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); FREEMPR(Y[j]); FREEMPR(V[j]); } ffree((char *)N, n * sizeof(MPR *)); ffree((char *)V, n * sizeof(MPR *)); ffree((char *)Y, n * sizeof(MPR *)); ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); FREEMATR(Q); FREEMATR(A); if (FOUND) { if (GCDVERBOSE) { printf("found a shorter multiplier:\n"); PRINTMATI(0, MATI->R - 1, 0, MATI->C - 1, MATI); lengthi = LENGTHSQRI(MATI, 0); printf("LENGTHSQUARED = "); PRINTI(lengthi); FREEMPI(lengthi); printf("\n"); printf("search continuing:\n\n"); } return(MATI); } else { FREEMPI(lengthj); if (GCDVERBOSE) printf("search ended.\n"); for (j = 0; j < n; j++) (*XX)[j] = ZEROI(); return(NULL); } } MPI ***SHORTESTX(MPMATI *AA, MPI *I[], USI *counter) /* * Input: An m x m matrix of integers AA = Q arising from LLLGCD. * The last row of AA is assumed to be a multiplier of shortest length. * Output: the XX[] defining the multipliers of shortest length. * Only used in GCD_CONJ in nfunc.c. * Warning: Array XX below only caters for up to GCD_MAX=100000 shortest multipliers. * If necessary, increase it and recompile. */ { unsigned int i, j, k, m, n, *l, *u, *t, *x, w, count = 0; MPR **X, **Y, **L, **T, **U, **V, *Temp0, *Temp1, *Temp2, *Temp3; MPR *C, *Z, *ONE, *SUM, **N; MPI ***XX, *tempI; MPMATR *A, *B, *BB, *Q, *QQ, *MATR; XX = (MPI ***)mmalloc((USL)(GCD_MAX * sizeof(MPI **))); /* First get the vector [V[0],...,V[n-2], where V[i]=.*/ m = AA->C; n = (AA->R) - 1; A = BUILDMATR(n + 1, m); for (i = 0; i < n + 1; i++) for (j = 0; j < m; j++) { elt(A, i, j) = BUILDMPR(); elt(A, i, j)->N = COPYI(AA->V[i][j]); elt(A, i, j)->D = ONEI(); } V = (MPR **)mmalloc(n * sizeof(MPR *)); for (i = 0; i < n; i++) { V[i] = ZEROR(); for (j = 0; j < m; j++) { Temp1 = V[i]; Temp2 = MULTR(elt(A, n, j), elt(A, i, j)); V[i] = ADDR(V[i], Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } } B = TRANSPOSER(A); BB = MULTMATR(A, B); FREEMATR(B); Q = CHOLESKYR(BB); FREEMATR(BB); QQ = COPYMATR(Q); for (i = 0; i < n; i++) { FREEMPR(elt(QQ, i, i)); elt(QQ, i, i) = ONER(); } /* Calculate (U^{-1})^tV = Y */ MATR = QQ; QQ = TRANSPOSER(QQ); FREEMATR(MATR); Y = (MPR **)mmalloc(n * sizeof(MPR *)); Y[0] = COPYR(V[0]); for (w = 1; w < n; w++) { SUM = ZEROR(); for ( k = 0; k < w; k++) { Temp1 = SUM; Temp2 = MULTR(elt(QQ, w, k), Y[k]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } Y[w] = SUBR(V[w], SUM); FREEMPR(SUM); } FREEMATR(QQ); N = (MPR **)mmalloc(n * sizeof(MPR *)); for (j = 0; j < n; j++) N[j] = RATIOR(Y[j], elt(Q, j, j)); ONE = ONER(); X = (MPR **)mmalloc(n * sizeof(MPR *)); L = (MPR **)mmalloc(n * sizeof(MPR *)); T = (MPR **)mmalloc(n * sizeof(MPR *)); U = (MPR **)mmalloc(n * sizeof(MPR *)); l = (USI *)mmalloc(n * sizeof(USI)); t = (USI *)mmalloc(n * sizeof(USI)); u = (USI *)mmalloc(n * sizeof(USI)); x = (USI *)mmalloc(n * sizeof(USI)); for (j = 0; j < n; j++) { l[j] = 0; t[j] = 0; u[j] = 0; x[j] = 0; } C = ZEROR(); for (i = 0; i < n; i++) { Temp1 = C; Temp2 = MULTR(Y[i], Y[i]); Temp3 = RATIOR(Temp2, elt(Q, i, i)); C = ADDR(C, Temp3); FREEMPR(Temp1); FREEMPR(Temp2); FREEMPR(Temp3); } i = n - 1; T[i] = COPYR(C); t[i] = 1; FREEMPR(C); U[i] = ZEROR(); u[i] = 1; bounds: Z = RATIOR(T[i], elt(Q, i, i)); Temp2 = SUBR(N[i], U[i]); if (l[i]) FREEMPR(L[i]); else l[i] = 1; L[i] = INTROOT(Z, Temp2); FREEMPR(Temp2); Temp0 = SUBR(U[i], N[i]); Temp2 = INTROOT(Z, Temp0); FREEMPR(Temp0); Temp3 = MINUSR(Temp2); if (x[i]) FREEMPR(X[i]); else x[i] = 1; X[i] = SUBR(Temp3, ONE); FREEMPR(Z); FREEMPR(Temp2); FREEMPR(Temp3); loop: Temp1 = X[i]; X[i] = ADDR(X[i], ONE); FREEMPR(Temp1); if (COMPAREI(X[i]->N, L[i]->N) == 1) { i++; if (i == n) goto exiting; else goto loop; } else { if (i) { Temp1 = ADDR(X[i], U[i]); Temp0 = SUBR(Temp1, N[i]); FREEMPR(Temp1); Temp2 = MULTR(Temp0, Temp0); FREEMPR(Temp0); Temp1 = MULTR(elt(Q, i, i), Temp2); FREEMPR(Temp2); if (t[i - 1]) FREEMPR(T[i - 1]); else t[i - 1] = 1; T[i - 1] = SUBR(T[i], Temp1); FREEMPR(Temp1); i--; SUM = ZEROR(); for (j = i + 1; j < n; j++) { Temp1 = SUM; Temp2 = MULTR(elt(Q, i, j), X[j]); SUM = ADDR(SUM, Temp2); FREEMPR(Temp1); FREEMPR(Temp2); } if (u[i]) FREEMPR(U[i]); else u[i] = 1; U[i] = COPYR(SUM); FREEMPR(SUM); goto bounds; } else goto found; } found: XX[count] = (MPI **)mmalloc((USL)(n * sizeof(MPI *))); for (j = 0; j < n; j++) { tempI = ADDI(X[j]->N, I[j]); XX[count][j] = MINUSI(tempI); FREEMPI(tempI); } count++; if (count > GCD_MAX) { fprintf(stderr, "count > %u\n", GCD_MAX); exit (1); } goto loop; exiting: FREEMPR(ONE); for (j = 0; j < n; j++) { FREEMPR(N[j]); FREEMPR(X[j]); FREEMPR(L[j]); FREEMPR(T[j]); FREEMPR(U[j]); FREEMPR(Y[j]); FREEMPR(V[j]); } ffree((char *)N, n * sizeof(MPR *)); ffree((char *)V, n * sizeof(MPR *)); ffree((char *)Y, n * sizeof(MPR *)); ffree((char *)X, n * sizeof(MPR *)); ffree((char *)L, n * sizeof(MPR *)); ffree((char *)T, n * sizeof(MPR *)); ffree((char *)U, n * sizeof(MPR *)); ffree((char *)l, n * sizeof(USI)); ffree((char *)t, n * sizeof(USI)); ffree((char *)u, n * sizeof(USI)); ffree((char *)x, n * sizeof(USI)); FREEMATR(Q); FREEMATR(A); /* if (count > 1) printf("There are exactly %u shortest multiplier vectors\n", count); if (count == 1) printf("There is exactly one shortest multiplier vector\n"); */ *counter = count; return (XX); }