long CRT(mat_ZZ& gg, ZZ& a, const mat_zz_p& G) { long n = gg.NumRows(); long m = gg.NumCols(); if (G.NumRows() != n || G.NumCols() != m) Error("CRT: dimension mismatch"); long p = zz_p::modulus(); ZZ new_a; mul(new_a, a, p); long a_inv; a_inv = rem(a, p); a_inv = InvMod(a_inv, p); long p1; p1 = p >> 1; ZZ a1; RightShift(a1, a, 1); long p_odd = (p & 1); long modified = 0; long h; ZZ g; long i, j; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { if (!CRTInRange(gg[i][j], a)) { modified = 1; rem(g, gg[i][j], a); if (g > a1) sub(g, g, a); } else g = gg[i][j]; h = rem(g, p); h = SubMod(rep(G[i][j]), h, p); h = MulMod(h, a_inv, p); if (h > p1) h = h - p; if (h != 0) { modified = 1; if (!p_odd && g > 0 && (h == p1)) MulSubFrom(g, a, h); else MulAddTo(g, a, h); } gg[i][j] = g; } } a = new_a; return modified; }
void solve(ZZ& d_out, vec_ZZ& x_out, const mat_ZZ& A, const vec_ZZ& b, long deterministic) { long n = A.NumRows(); if (A.NumCols() != n) Error("solve: nonsquare matrix"); if (b.length() != n) Error("solve: dimension mismatch"); if (n == 0) { set(d_out); x_out.SetLength(0); return; } zz_pBak zbak; zbak.save(); ZZ_pBak Zbak; Zbak.save(); vec_ZZ x(INIT_SIZE, n); ZZ d, d1; ZZ d_prod, x_prod; set(d_prod); set(x_prod); long d_instable = 1; long x_instable = 1; long check = 0; long gp_cnt = 0; vec_ZZ y, b1; long i; long bound = 2+DetBound(A); for (i = 0; ; i++) { if ((check || IsZero(d)) && !d_instable) { if (NumBits(d_prod) > bound) { break; } else if (!deterministic && bound > 1000 && NumBits(d_prod) < 0.25*bound) { ZZ P; long plen = 90 + NumBits(max(bound, NumBits(d))); GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++)); ZZ_p::init(P); mat_ZZ_p AA; conv(AA, A); ZZ_p dd; determinant(dd, AA); if (CRT(d, d_prod, rep(dd), P)) d_instable = 1; else break; } } zz_p::FFTInit(i); long p = zz_p::modulus(); mat_zz_p AA; conv(AA, A); if (!check) { vec_zz_p bb, xx; conv(bb, b); zz_p dd; solve(dd, xx, AA, bb); d_instable = CRT(d, d_prod, rep(dd), p); if (!IsZero(dd)) { mul(xx, xx, dd); x_instable = CRT(x, x_prod, xx); } else x_instable = 1; if (!d_instable && !x_instable) { mul(y, x, A); mul(b1, b, d); if (y == b1) { d1 = d; check = 1; } } } else { zz_p dd; determinant(dd, AA); d_instable = CRT(d, d_prod, rep(dd), p); } } if (check && d1 != d) { mul(x, x, d); ExactDiv(x, d1); } d_out = d; if (check) x_out = x; zbak.restore(); Zbak.restore(); }
void solve1(ZZ& d_out, vec_ZZ& x_out, const mat_ZZ& A, const vec_ZZ& b) { long n = A.NumRows(); if (A.NumCols() != n) Error("solve1: nonsquare matrix"); if (b.length() != n) Error("solve1: dimension mismatch"); if (n == 0) { set(d_out); x_out.SetLength(0); return; } ZZ num_bound, den_bound; hadamard(num_bound, den_bound, A, b); if (den_bound == 0) { clear(d_out); return; } zz_pBak zbak; zbak.save(); long i; long j; ZZ prod; prod = 1; mat_zz_p B; for (i = 0; ; i++) { zz_p::FFTInit(i); mat_zz_p AA, BB; zz_p dd; conv(AA, A); inv(dd, BB, AA); if (dd != 0) { transpose(B, BB); break; } mul(prod, prod, zz_p::modulus()); if (prod > den_bound) { d_out = 0; return; } } long max_A_len = MaxBits(A); long use_double_mul1 = 0; long use_double_mul2 = 0; long double_limit = 0; if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_DOUBLE_PRECISION-1) use_double_mul1 = 1; if (!use_double_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_DOUBLE_PRECISION-1) { use_double_mul2 = 1; double_limit = (1L << (NTL_DOUBLE_PRECISION-1-max_A_len-NTL_SP_NBITS)); } long use_long_mul1 = 0; long use_long_mul2 = 0; long long_limit = 0; if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_BITS_PER_LONG-1) use_long_mul1 = 1; if (!use_long_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_BITS_PER_LONG-1) { use_long_mul2 = 1; long_limit = (1L << (NTL_BITS_PER_LONG-1-max_A_len-NTL_SP_NBITS)); } if (use_double_mul1 && use_long_mul1) use_long_mul1 = 0; else if (use_double_mul1 && use_long_mul2) use_long_mul2 = 0; else if (use_double_mul2 && use_long_mul1) use_double_mul2 = 0; else if (use_double_mul2 && use_long_mul2) { if (long_limit > double_limit) use_double_mul2 = 0; else use_long_mul2 = 0; } double **double_A; double *double_h; typedef double *double_ptr; if (use_double_mul1 || use_double_mul2) { double_h = NTL_NEW_OP double[n]; double_A = NTL_NEW_OP double_ptr[n]; if (!double_h || !double_A) Error("solve1: out of mem"); for (i = 0; i < n; i++) { double_A[i] = NTL_NEW_OP double[n]; if (!double_A[i]) Error("solve1: out of mem"); } for (i = 0; i < n; i++) for (j = 0; j < n; j++) double_A[j][i] = to_double(A[i][j]); }
void determinant(ZZ& rres, const mat_ZZ& a, long deterministic) { long n = a.NumRows(); if (a.NumCols() != n) Error("determinant: nonsquare matrix"); if (n == 0) { set(rres); return; } zz_pBak zbak; zbak.save(); ZZ_pBak Zbak; Zbak.save(); long instable = 1; long gp_cnt = 0; long bound = 2+DetBound(a); ZZ res, prod; clear(res); set(prod); long i; for (i = 0; ; i++) { if (NumBits(prod) > bound) break; if (!deterministic && !instable && bound > 1000 && NumBits(prod) < 0.25*bound) { ZZ P; long plen = 90 + NumBits(max(bound, NumBits(res))); GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++)); ZZ_p::init(P); mat_ZZ_p A; conv(A, a); ZZ_p t; determinant(t, A); if (CRT(res, prod, rep(t), P)) instable = 1; else break; } zz_p::FFTInit(i); long p = zz_p::modulus(); mat_zz_p A; conv(A, a); zz_p t; determinant(t, A); instable = CRT(res, prod, rep(t), p); } rres = res; zbak.restore(); Zbak.restore(); }
void solve1(ZZ& d_out, vec_ZZ& x_out, const mat_ZZ& A, const vec_ZZ& b) { long n = A.NumRows(); if (A.NumCols() != n) LogicError("solve1: nonsquare matrix"); if (b.length() != n) LogicError("solve1: dimension mismatch"); if (n == 0) { set(d_out); x_out.SetLength(0); return; } ZZ num_bound, den_bound; hadamard(num_bound, den_bound, A, b); if (den_bound == 0) { clear(d_out); return; } zz_pBak zbak; zbak.save(); long i; long j; ZZ prod; prod = 1; mat_zz_p B; for (i = 0; ; i++) { zz_p::FFTInit(i); mat_zz_p AA, BB; zz_p dd; conv(AA, A); inv(dd, BB, AA); if (dd != 0) { transpose(B, BB); break; } mul(prod, prod, zz_p::modulus()); if (prod > den_bound) { d_out = 0; return; } } long max_A_len = MaxBits(A); long use_double_mul1 = 0; long use_double_mul2 = 0; long double_limit = 0; if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_DOUBLE_PRECISION-1) use_double_mul1 = 1; if (!use_double_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_DOUBLE_PRECISION-1) { use_double_mul2 = 1; double_limit = (1L << (NTL_DOUBLE_PRECISION-1-max_A_len-NTL_SP_NBITS)); } long use_long_mul1 = 0; long use_long_mul2 = 0; long long_limit = 0; if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_BITS_PER_LONG-1) use_long_mul1 = 1; if (!use_long_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_BITS_PER_LONG-1) { use_long_mul2 = 1; long_limit = (1L << (NTL_BITS_PER_LONG-1-max_A_len-NTL_SP_NBITS)); } if (use_double_mul1 && use_long_mul1) use_long_mul1 = 0; else if (use_double_mul1 && use_long_mul2) use_long_mul2 = 0; else if (use_double_mul2 && use_long_mul1) use_double_mul2 = 0; else if (use_double_mul2 && use_long_mul2) { if (long_limit > double_limit) use_double_mul2 = 0; else use_long_mul2 = 0; } double **double_A=0; double *double_h=0; Unique2DArray<double> double_A_store; UniqueArray<double> double_h_store; if (use_double_mul1 || use_double_mul2) { double_h_store.SetLength(n); double_h = double_h_store.get(); double_A_store.SetDims(n, n); double_A = double_A_store.get(); for (i = 0; i < n; i++) for (j = 0; j < n; j++) double_A[j][i] = to_double(A[i][j]); } long **long_A=0; long *long_h=0; Unique2DArray<long> long_A_store; UniqueArray<long> long_h_store; if (use_long_mul1 || use_long_mul2) { long_h_store.SetLength(n); long_h = long_h_store.get(); long_A_store.SetDims(n, n); long_A = long_A_store.get(); for (i = 0; i < n; i++) for (j = 0; j < n; j++) long_A[j][i] = to_long(A[i][j]); } vec_ZZ x; x.SetLength(n); vec_zz_p h; h.SetLength(n); vec_ZZ e; e = b; vec_zz_p ee; vec_ZZ t; t.SetLength(n); prod = 1; ZZ bound1; mul(bound1, num_bound, den_bound); mul(bound1, bound1, 2); while (prod <= bound1) { conv(ee, e); mul(h, B, ee); if (use_double_mul1) { for (i = 0; i < n; i++) double_h[i] = to_double(rep(h[i])); double_MixedMul1(t, double_h, double_A, n); } else if (use_double_mul2) { for (i = 0; i < n; i++) double_h[i] = to_double(rep(h[i])); double_MixedMul2(t, double_h, double_A, n, double_limit); } else if (use_long_mul1) { for (i = 0; i < n; i++) long_h[i] = to_long(rep(h[i])); long_MixedMul1(t, long_h, long_A, n); } else if (use_long_mul2) { for (i = 0; i < n; i++) long_h[i] = to_long(rep(h[i])); long_MixedMul2(t, long_h, long_A, n, long_limit); } else MixedMul(t, h, A); // t = h*A SubDiv(e, t, zz_p::modulus()); // e = (e-t)/p MulAdd(x, prod, h); // x = x + prod*h mul(prod, prod, zz_p::modulus()); } vec_ZZ num, denom; ZZ d, d_mod_prod, tmp1; num.SetLength(n); denom.SetLength(n); d = 1; d_mod_prod = 1; for (i = 0; i < n; i++) { rem(x[i], x[i], prod); MulMod(x[i], x[i], d_mod_prod, prod); if (!ReconstructRational(num[i], denom[i], x[i], prod, num_bound, den_bound)) LogicError("solve1 internal error: rat recon failed!"); mul(d, d, denom[i]); if (i != n-1) { if (denom[i] != 1) { div(den_bound, den_bound, denom[i]); mul(bound1, num_bound, den_bound); mul(bound1, bound1, 2); div(tmp1, prod, zz_p::modulus()); while (tmp1 > bound1) { prod = tmp1; div(tmp1, prod, zz_p::modulus()); } rem(tmp1, denom[i], prod); rem(d_mod_prod, d_mod_prod, prod); MulMod(d_mod_prod, d_mod_prod, tmp1, prod); } } } tmp1 = 1; for (i = n-1; i >= 0; i--) { mul(num[i], num[i], tmp1); mul(tmp1, tmp1, denom[i]); } x_out.SetLength(n); for (i = 0; i < n; i++) { x_out[i] = num[i]; } d_out = d; }
void CharPoly(ZZX& gg, const mat_ZZ& a, long deterministic) { long n = a.NumRows(); if (a.NumCols() != n) LogicError("CharPoly: nonsquare matrix"); if (n == 0) { set(gg); return; } if (n == 1) { ZZ t; SetX(gg); negate(t, a(1, 1)); SetCoeff(gg, 0, t); return; } long bound = 2 + CharPolyBound(a); zz_pBak bak; bak.save(); ZZ_pBak bak1; bak1.save(); ZZX g; ZZ prod; clear(g); set(prod); long i; long instable = 1; long gp_cnt = 0; for (i = 0; ; i++) { if (NumBits(prod) > bound) break; if (!deterministic && !instable && bound > 1000 && NumBits(prod) < 0.25*bound) { long plen = 90 + NumBits(max(bound, MaxBits(g))); ZZ P; GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++)); ZZ_p::init(P); mat_ZZ_p A; ZZ_pX G; conv(A, a); CharPoly(G, A); if (CRT(g, prod, G)) instable = 1; else break; } zz_p::FFTInit(i); mat_zz_p A; zz_pX G; conv(A, a); CharPoly(G, A); instable = CRT(g, prod, G); } gg = g; bak.restore(); bak1.restore(); }
static long LLL_XD(mat_ZZ& B, mat_ZZ* U, xdouble delta, long deep, LLLCheckFct check) { long m = B.NumRows(); long n = B.NumCols(); long i, j; long new_m, dep, quit; xdouble s; ZZ MU; xdouble mu1; xdouble t1; ZZ T1; init_red_fudge(); if (U) ident(*U, m); xdouble **B1; // approximates B typedef xdouble *xdoubleptr; B1 = NTL_NEW_OP xdoubleptr[m+1]; if (!B1) Error("LLL_XD: out of memory"); for (i = 1; i <= m; i++) { B1[i] = NTL_NEW_OP xdouble[n+1]; if (!B1[i]) Error("LLL_XD: out of memory"); } xdouble **mu; mu = NTL_NEW_OP xdoubleptr[m+1]; if (!mu) Error("LLL_XD: out of memory"); for (i = 1; i <= m; i++) { mu[i] = NTL_NEW_OP xdouble[m+1]; if (!mu[i]) Error("LLL_XD: out of memory"); } xdouble *c; // squared lengths of Gramm-Schmidt basis vectors c = NTL_NEW_OP xdouble[m+1]; if (!c) Error("LLL_XD: out of memory"); xdouble *b; // squared lengths of basis vectors b = NTL_NEW_OP xdouble[m+1]; if (!b) Error("LLL_XD: out of memory"); for (i = 1; i <=m; i++) for (j = 1; j <= n; j++) conv(B1[i][j], B(i, j)); for (i = 1; i <= m; i++) { b[i] = InnerProduct(B1[i], B1[i], n); } new_m = ll_LLL_XD(B, U, delta, deep, check, B1, mu, b, c, m, 1, quit); dep = m - new_m; m = new_m; if (dep > 0) { // for consistency, we move all of the zero rows to the front for (i = 0; i < m; i++) { swap(B(m+dep-i), B(m-i)); if (U) swap((*U)(m+dep-i), (*U)(m-i)); } } // clean-up for (i = 1; i <= m+dep; i++) { delete [] B1[i]; } delete [] B1; for (i = 1; i <= m+dep; i++) { delete [] mu[i]; } delete [] mu; delete [] c; delete [] b; return m; }
static long BKZ_XD(mat_ZZ& BB, mat_ZZ* UU, xdouble delta, long beta, long prune, LLLCheckFct check) { long m = BB.NumRows(); long n = BB.NumCols(); long m_orig = m; long i, j; ZZ MU; xdouble t1; ZZ T1; xdouble *tp; init_red_fudge(); mat_ZZ B; B = BB; B.SetDims(m+1, n); xdouble **B1; // approximates B typedef xdouble *xdoubleptr; B1 = NTL_NEW_OP xdoubleptr[m+2]; if (!B1) Error("BKZ_XD: out of memory"); for (i = 1; i <= m+1; i++) { B1[i] = NTL_NEW_OP xdouble[n+1]; if (!B1[i]) Error("BKZ_XD: out of memory"); } xdouble **mu; mu = NTL_NEW_OP xdoubleptr[m+2]; if (!mu) Error("BKZ_XD: out of memory"); for (i = 1; i <= m+1; i++) { mu[i] = NTL_NEW_OP xdouble[m+1]; if (!mu[i]) Error("BKZ_XD: out of memory"); } xdouble *c; // squared lengths of Gramm-Schmidt basis vectors c = NTL_NEW_OP xdouble[m+2]; if (!c) Error("BKZ_XD: out of memory"); xdouble *b; // squared lengths of basis vectors b = NTL_NEW_OP xdouble[m+2]; if (!b) Error("BKZ_XD: out of memory"); xdouble cbar; xdouble *ctilda; ctilda = NTL_NEW_OP xdouble[m+2]; if (!ctilda) Error("BKZ_XD: out of memory"); xdouble *vvec; vvec = NTL_NEW_OP xdouble[m+2]; if (!vvec) Error("BKZ_XD: out of memory"); xdouble *yvec; yvec = NTL_NEW_OP xdouble[m+2]; if (!yvec) Error("BKZ_XD: out of memory"); xdouble *uvec; uvec = NTL_NEW_OP xdouble[m+2]; if (!uvec) Error("BKZ_XD: out of memory"); xdouble *utildavec; utildavec = NTL_NEW_OP xdouble[m+2]; if (!utildavec) Error("BKZ_XD: out of memory"); long *Deltavec; Deltavec = NTL_NEW_OP long[m+2]; if (!Deltavec) Error("BKZ_XD: out of memory"); long *deltavec; deltavec = NTL_NEW_OP long[m+2]; if (!deltavec) Error("BKZ_XD: out of memory"); mat_ZZ Ulocal; mat_ZZ *U; if (UU) { Ulocal.SetDims(m+1, m); for (i = 1; i <= m; i++) conv(Ulocal(i, i), 1); U = &Ulocal; } else U = 0; long quit; long new_m; long z, jj, kk; long s, t; long h; xdouble eta; for (i = 1; i <=m; i++) for (j = 1; j <= n; j++) conv(B1[i][j], B(i, j)); for (i = 1; i <= m; i++) { b[i] = InnerProduct(B1[i], B1[i], n); } // cerr << "\n"; // cerr << "first LLL\n"; m = ll_LLL_XD(B, U, delta, 0, check, B1, mu, b, c, m, 1, quit); double tt; double enum_time = 0; unsigned long NumIterations = 0; unsigned long NumTrivial = 0; unsigned long NumNonTrivial = 0; unsigned long NumNoOps = 0; long verb = verbose; verbose = 0; if (m < m_orig) { for (i = m_orig+1; i >= m+2; i--) { // swap i, i-1 swap(B(i), B(i-1)); if (U) swap((*U)(i), (*U)(i-1)); } } long clean = 1; if (!quit && m > 1) { // cerr << "continuing\n"; if (beta > m) beta = m; if (prune > 0) ComputeBKZConstant(beta, prune); z = 0; jj = 0; while (z < m-1) { jj++; kk = min(jj+beta-1, m); if (jj == m) { jj = 1; kk = beta; clean = 1; } if (verb) { tt = GetTime(); if (tt > LastTime + LLLStatusInterval) BKZStatus(tt, enum_time, NumIterations, NumTrivial, NumNonTrivial, NumNoOps, m, B); } // ENUM double tt1; if (verb) { tt1 = GetTime(); } if (prune > 0) ComputeBKZThresh(&c[jj], kk-jj+1); cbar = c[jj]; utildavec[jj] = uvec[jj] = 1; yvec[jj] = vvec[jj] = 0; Deltavec[jj] = 0; s = t = jj; deltavec[jj] = 1; for (i = jj+1; i <= kk+1; i++) { ctilda[i] = uvec[i] = utildavec[i] = yvec[i] = 0; Deltavec[i] = 0; vvec[i] = 0; deltavec[i] = 1; } long enum_cnt = 0; while (t <= kk) { if (verb) { enum_cnt++; if (enum_cnt > 100000) { enum_cnt = 0; tt = GetTime(); if (tt > LastTime + LLLStatusInterval) { enum_time += tt - tt1; tt1 = tt; BKZStatus(tt, enum_time, NumIterations, NumTrivial, NumNonTrivial, NumNoOps, m, B); } } } ctilda[t] = ctilda[t+1] + (yvec[t]+utildavec[t])*(yvec[t]+utildavec[t])*c[t]; if (prune > 0 && t > jj) { eta = BKZThresh(t-jj); } else eta = 0; if (ctilda[t] < cbar - eta) { if (t > jj) { t--; t1 = 0; for (i = t+1; i <= s; i++) { t1 += utildavec[i]*mu[i][t]; } yvec[t] = t1; t1 = -t1; if (t1 >= 0) t1 = ceil(t1-0.5); else t1 = floor(t1+0.5); utildavec[t] = vvec[t] = t1; Deltavec[t] = 0; if (utildavec[t] > -yvec[t]) deltavec[t] = -1; else deltavec[t] = 1; } else { cbar = ctilda[jj]; for (i = jj; i <= kk; i++) { uvec[i] = utildavec[i]; } } } else { t++; s = max(s, t); if (t < s) Deltavec[t] = -Deltavec[t]; if (Deltavec[t]*deltavec[t] >= 0) Deltavec[t] += deltavec[t]; utildavec[t] = vvec[t] + Deltavec[t]; } } if (verb) { tt1 = GetTime() - tt1; enum_time += tt1; } NumIterations++; h = min(kk+1, m); if ((delta-8*red_fudge)*c[jj] > cbar) { clean = 0; // we treat the case that the new vector is b_s (jj < s <= kk) // as a special case that appears to occur most of the time. s = 0; for (i = jj+1; i <= kk; i++) { if (uvec[i] != 0) { if (s == 0) s = i; else s = -1; } } if (s == 0) Error("BKZ_XD: internal error"); if (s > 0) { // special case NumTrivial++; for (i = s; i > jj; i--) { // swap i, i-1 swap(B(i-1), B(i)); if (U) swap((*U)(i-1), (*U)(i)); tp = B1[i-1]; B1[i-1] = B1[i]; B1[i] = tp; t1 = b[i-1]; b[i-1] = b[i]; b[i] = t1; } // cerr << "special case\n"; new_m = ll_LLL_XD(B, U, delta, 0, check, B1, mu, b, c, h, jj, quit); if (new_m != h) Error("BKZ_XD: internal error"); if (quit) break; } else { // the general case NumNonTrivial++; for (i = 1; i <= n; i++) conv(B(m+1, i), 0); if (U) { for (i = 1; i <= m_orig; i++) conv((*U)(m+1, i), 0); } for (i = jj; i <= kk; i++) { if (uvec[i] == 0) continue; conv(MU, uvec[i]); RowTransform2(B(m+1), B(i), MU); if (U) RowTransform2((*U)(m+1), (*U)(i), MU); } for (i = m+1; i >= jj+1; i--) { // swap i, i-1 swap(B(i-1), B(i)); if (U) swap((*U)(i-1), (*U)(i)); tp = B1[i-1]; B1[i-1] = B1[i]; B1[i] = tp; t1 = b[i-1]; b[i-1] = b[i]; b[i] = t1; } for (i = 1; i <= n; i++) conv(B1[jj][i], B(jj, i)); b[jj] = InnerProduct(B1[jj], B1[jj], n); if (b[jj] == 0) Error("BKZ_XD: internal error"); // remove linear dependencies // cerr << "general case\n"; new_m = ll_LLL_XD(B, U, delta, 0, 0, B1, mu, b, c, kk+1, jj, quit); if (new_m != kk) Error("BKZ_XD: internal error"); // remove zero vector for (i = kk+2; i <= m+1; i++) { // swap i, i-1 swap(B(i-1), B(i)); if (U) swap((*U)(i-1), (*U)(i)); tp = B1[i-1]; B1[i-1] = B1[i]; B1[i] = tp; t1 = b[i-1]; b[i-1] = b[i]; b[i] = t1; } quit = 0; if (check) { for (i = 1; i <= kk; i++) if ((*check)(B(i))) { quit = 1; break; } } if (quit) break; if (h > kk) { // extend reduced basis new_m = ll_LLL_XD(B, U, delta, 0, check, B1, mu, b, c, h, h, quit); if (new_m != h) Error("BKZ_XD: internal error"); if (quit) break; } } z = 0; } else { // LLL_XD // cerr << "progress\n"; NumNoOps++; if (!clean) { new_m = ll_LLL_XD(B, U, delta, 0, check, B1, mu, b, c, h, h, quit); if (new_m != h) Error("BKZ_XD: internal error"); if (quit) break; } z++; } } } if (verb) { BKZStatus(GetTime(), enum_time, NumIterations, NumTrivial, NumNonTrivial, NumNoOps, m, B); } // clean up if (m_orig > m) { // for consistency, we move zero vectors to the front for (i = m+1; i <= m_orig; i++) { swap(B(i), B(i+1)); if (U) swap((*U)(i), (*U)(i+1)); } for (i = 0; i < m; i++) { swap(B(m_orig-i), B(m-i)); if (U) swap((*U)(m_orig-i), (*U)(m-i)); } } B.SetDims(m_orig, n); BB = B; if (U) { U->SetDims(m_orig, m_orig); *UU = *U; } for (i = 1; i <= m_orig+1; i++) { delete [] B1[i]; } delete [] B1; for (i = 1; i <= m_orig+1; i++) { delete [] mu[i]; } delete [] mu; delete [] c; delete [] b; delete [] ctilda; delete [] vvec; delete [] yvec; delete [] uvec; delete [] utildavec; delete [] Deltavec; delete [] deltavec; return m; }
static long G_LLL_XD(mat_ZZ& B, mat_ZZ* U, xdouble delta, long deep, LLLCheckFct check) { long m = B.NumRows(); long n = B.NumCols(); long i, j; long new_m, dep, quit; xdouble s; ZZ MU; xdouble mu1; xdouble t1; ZZ T1; init_red_fudge(); if (U) ident(*U, m); xdouble **B1; // approximates B typedef xdouble *xdoubleptr; B1 = NTL_NEW_OP xdoubleptr[m+1]; if (!B1) Error("G_LLL_XD: out of memory"); for (i = 1; i <= m; i++) { B1[i] = NTL_NEW_OP xdouble[n+1]; if (!B1[i]) Error("G_LLL_XD: out of memory"); } xdouble **mu; mu = NTL_NEW_OP xdoubleptr[m+1]; if (!mu) Error("G_LLL_XD: out of memory"); for (i = 1; i <= m; i++) { mu[i] = NTL_NEW_OP xdouble[n+2]; if (!mu[i]) Error("G_LLL_XD: out of memory"); } xdouble **aux; aux = NTL_NEW_OP xdoubleptr[m+1]; if (!aux) Error("G_LLL_XD: out of memory"); for (i = 1; i <= m; i++) { aux[i] = NTL_NEW_OP xdouble[n+1]; if (!aux[i]) Error("G_LLL_XD: out of memory"); } for (i = 1; i <=m; i++) for (j = 1; j <= n; j++) conv(B1[i][j], B(i, j)); GivensCache_XD cache(m, n); new_m = ll_G_LLL_XD(B, U, delta, deep, check, B1, mu, aux, m, 1, quit, cache); dep = m - new_m; m = new_m; if (dep > 0) { // for consistency, we move all of the zero rows to the front for (i = 0; i < m; i++) { swap(B(m+dep-i), B(m-i)); if (U) swap((*U)(m+dep-i), (*U)(m-i)); } } // clean-up for (i = 1; i <= m+dep; i++) { delete [] B1[i]; } delete [] B1; for (i = 1; i <= m+dep; i++) { delete [] mu[i]; } delete [] mu; for (i = 1; i <= m+dep; i++) { delete [] aux[i]; } delete [] aux; return m; }
long LatticeSolve(vec_ZZ& x, const mat_ZZ& A, const vec_ZZ& y, long reduce) { long n = A.NumRows(); long m = A.NumCols(); if (y.length() != m) Error("LatticeSolve: dimension mismatch"); if (reduce < 0 || reduce > 2) Error("LatticeSolve: bad reduce parameter"); if (IsZero(y)) { x.SetLength(n); clear(x); return 1; } mat_ZZ A1, U1; ZZ det2; long im_rank, ker_rank; A1 = A; im_rank = image(det2, A1, U1); ker_rank = n - im_rank; mat_ZZ A2, U2; long new_rank; long i; A2.SetDims(im_rank + 1, m); for (i = 1; i <= im_rank; i++) A2(i) = A1(ker_rank + i); A2(im_rank + 1) = y; new_rank = image(det2, A2, U2); if (new_rank != im_rank || (U2(1)(im_rank+1) != 1 && U2(1)(im_rank+1) != -1)) return 0; vec_ZZ x1; x1.SetLength(im_rank); for (i = 1; i <= im_rank; i++) x1(i) = U2(1)(i); if (U2(1)(im_rank+1) == 1) negate(x1, x1); vec_ZZ x2, tmp; x2.SetLength(n); clear(x2); tmp.SetLength(n); for (i = 1; i <= im_rank; i++) { mul(tmp, U1(ker_rank+i), x1(i)); add(x2, x2, tmp); } if (reduce == 0) { x = x2; return 1; } else if (reduce == 1) { U1.SetDims(ker_rank+1, n); U1(ker_rank+1) = x2; image(det2, U1); x = U1(ker_rank + 1); return 1; } else if (reduce == 2) { U1.SetDims(ker_rank, n); LLL(det2, U1); U1.SetDims(ker_rank+1, n); U1(ker_rank+1) = x2; image(det2, U1); x = U1(ker_rank + 1); return 1; } return 0; }
static long LLL(vec_ZZ& D, mat_ZZ& B, mat_ZZ* U, long a, long b, long verbose) { long m = B.NumRows(); long n = B.NumCols(); long force_reduce = 1; vec_long P; P.SetLength(m); D.SetLength(m+1); D[0] = 1; vec_vec_ZZ lam; lam.SetLength(m); long j; for (j = 1; j <= m; j++) lam(j).SetLength(m); if (U) ident(*U, m); long s = 0; long k = 1; long max_k = 0; while (k <= m) { if (k > max_k) { IncrementalGS(B, P, D, lam, s, k); max_k = k; } if (k == 1) { force_reduce = 1; k++; continue; } if (force_reduce) for (j = k-1; j >= 1; j--) reduce(k, j, B, P, D, lam, U); if (P(k-1) != 0 && (P(k) == 0 || SwapTest(D[P(k)], D[P(k)-1], D[P(k)-2], lam(k)(P(k)-1), a, b))) { force_reduce = swap(k, B, P, D, lam, U, max_k, verbose); k--; } else { force_reduce = 1; k++; } } D.SetLength(s+1); return s; }
static long LLL_XD(mat_ZZ& B, mat_ZZ* U, xdouble delta, long deep, LLLCheckFct check) { long m = B.NumRows(); long n = B.NumCols(); long i, j; long new_m, dep, quit; xdouble s; ZZ MU; xdouble mu1; xdouble t1; ZZ T1; init_red_fudge(); if (U) ident(*U, m); Unique2DArray<xdouble> B1_store; B1_store.SetDimsFrom1(m+1, n+1); xdouble **B1 = B1_store.get(); // approximates B Unique2DArray<xdouble> mu_store; mu_store.SetDimsFrom1(m+1, m+1); xdouble **mu = mu_store.get(); UniqueArray<xdouble> c_store; c_store.SetLength(m+1); xdouble *c = c_store.get(); // squared lengths of Gramm-Schmidt basis vectors UniqueArray<xdouble> b_store; b_store.SetLength(m+1); xdouble *b = b_store.get(); // squared lengths of basis vectors for (i = 1; i <=m; i++) for (j = 1; j <= n; j++) conv(B1[i][j], B(i, j)); for (i = 1; i <= m; i++) { b[i] = InnerProduct(B1[i], B1[i], n); } new_m = ll_LLL_XD(B, U, delta, deep, check, B1, mu, b, c, m, 1, quit); dep = m - new_m; m = new_m; if (dep > 0) { // for consistency, we move all of the zero rows to the front for (i = 0; i < m; i++) { swap(B(m+dep-i), B(m-i)); if (U) swap((*U)(m+dep-i), (*U)(m-i)); } } return m; }
RR ReductionQualityChecker::computeHermiteFactor(mat_ZZ &mat) { RR numerator = findShortestNormVector(mat); RR denominator = pow(abs(determinant(mat)), (1./mat.NumRows())); RR result = numerator/denominator; return result; }