static CYTHON_INLINE void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, struct ZZX** t, int proof) { *r = new ZZ(); *s = new ZZX(); *t = new ZZX(); XGCD(**r, **s, **t, *x, *y, proof); }
void HNF(mat_ZZ& W, const mat_ZZ& A_in, const ZZ& D_in) { mat_ZZ A = A_in; long n = A.NumRows(); long m = A.NumCols(); ZZ D = D_in; if (D < 0) negate(D, D); if (n == 0 || m == 0 || D == 0) Error("HNF: bad input"); W.SetDims(m, m); clear(W); long i, j, k; ZZ d, u, v, c1, c2; k = n; for (i = m; i >= 1; i--) { for (j = k-1; j >= 1; j--) { if (A(j, i) != 0) { XGCD(d, u, v, A(k, i), A(j, i)); div(c1, A(k, i), d); div(c2, A(j, i), d); negate(c2, c2); EuclUpdate(A(j), A(k), c1, c2, v, u, D); } } XGCD(d, u, v, A(k, i), D); FixDiag(W(i), u, A(k), D, i); if (W(i, i) == 0) W(i, i) = D; for (j = i+1; j <= m; j++) { div(c1, W(j, i), W(i, i)); ReduceW(W(j), c1, W(i), D, i); } div(D, D, d); k--; } }
int main() { long n; GF2X a, b, c, c1, ss, ss1, tt, tt1; double t; long iter, i; cout << WD(12,"n") << WD(12,"OldGCD") << WD(12,"GCD") << WD(12,"OldXGCD") << WD(12, "XGCD") << "\n"; cout.precision(3); cout.setf(ios::scientific); for (n = 32; n <= (1L << 18); n = n << 3) { random(a, n); random(b, n); OldGCD(c, a, b); GCD(c1, a, b); OldXGCD(c, ss, tt, a, b); XGCD(c1, ss1, tt1, a, b); if (c1 != c || ss1 != ss || tt1 != tt) { cerr << "**** GF2XTest FAILED!\n"; return 1; } cout << WD(12,n); iter = 0; do { iter = iter ? (2*iter) : 1; t = GetTime(); for (i = 0; i < iter; i++) OldGCD(c, a, b); t = GetTime()-t; } while (t < 0.5); cout << WD(12,t/iter); iter = 0; do { iter = iter ? (2*iter) : 1; t = GetTime(); for (i = 0; i < iter; i++) GCD(c, a, b); t = GetTime()-t; } while (t < 0.5); cout << WD(12,t/iter); iter = 0; do { iter = iter ? (2*iter) : 1; t = GetTime(); for (i = 0; i < iter; i++) OldXGCD(c, ss, tt, a, b); t = GetTime()-t; } while (t < 0.5); cout << WD(12,t/iter); iter = 0; do { iter = iter ? (2*iter) : 1; t = GetTime(); for (i = 0; i < iter; i++) XGCD(c, ss, tt, a, b); t = GetTime()-t; } while (t < 0.5); cout << WD(12,t/iter); cout << "\n"; } return 0; }
static long swap(long k, mat_ZZ& B, vec_long& P, vec_ZZ& D, vec_vec_ZZ& lam, mat_ZZ* U, long m, long verbose) // swaps vectors k-1 and k; assumes P(k-1) != 0 // returns 1 if vector k-1 need to be reduced after the swap... // this only occurs in 'case 2' when there are linear dependencies { long i, j; static ZZ t1, t2, t3, e, x, y; if (P(k) != 0) { swap(B(k-1), B(k)); if (U) swap((*U)(k-1), (*U)(k)); for (j = 1; j <= k-2; j++) if (P(j) != 0) swap(lam(k-1)(P(j)), lam(k)(P(j))); for (i = k+1; i <= m; i++) { MulAddDiv(t1, lam(i)(P(k)-1), lam(i)(P(k)), lam(k)(P(k)-1), D[P(k)-2], D[P(k)-1]); MulSubDiv(t2, lam(i)(P(k)-1), lam(i)(P(k)), D[P(k)], lam(k)(P(k)-1), D[P(k)-1]); lam(i)(P(k)-1) = t1; lam(i)(P(k)) = t2; } MulAddDiv(D[P(k)-1], D[P(k)], lam(k)(P(k)-1), D[P(k)-2], lam(k)(P(k)-1), D[P(k)-1]); return 0; } else if (!IsZero(lam(k)(P(k-1)))) { XGCD(e, x, y, lam(k)(P(k-1)), D[P(k-1)]); ExactDiv(t1, lam(k)(P(k-1)), e); ExactDiv(t2, D[P(k-1)], e); t3 = t2; negate(t2, t2); RowTransform(B(k-1), B(k), t1, t2, y, x); if (U) RowTransform((*U)(k-1), (*U)(k), t1, t2, y, x); for (j = 1; j <= k-2; j++) if (P(j) != 0) RowTransform(lam(k-1)(P(j)), lam(k)(P(j)), t1, t2, y, x); sqr(t2, t2); ExactDiv(D[P(k-1)], D[P(k-1)], t2); for (i = k+1; i <= m; i++) if (P(i) != 0) { ExactDiv(D[P(i)], D[P(i)], t2); for (j = i+1; j <= m; j++) { ExactDiv(lam(j)(P(i)), lam(j)(P(i)), t2); } } for (i = k+1; i <= m; i++) { ExactDiv(lam(i)(P(k-1)), lam(i)(P(k-1)), t3); } swap(P(k-1), P(k)); return 1; } else { swap(B(k-1), B(k)); if (U) swap((*U)(k-1), (*U)(k)); for (j = 1; j <= k-2; j++) if (P(j) != 0) swap(lam(k-1)(P(j)), lam(k)(P(j))); swap(P(k-1), P(k)); return 0; } }