📄 lll_fp.c
字号:
#include <NTL/LLL.h>#include <NTL/fileio.h>#include <NTL/vec_double.h>#include <NTL/new.h>NTL_START_IMPLstatic double InnerProduct(double *a, double *b, long n){ double s; long i; s = 0; for (i = 1; i <= n; i++) s += a[i]*b[i]; return s;}static void RowTransform(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1)// x = x - y*MU{ static ZZ T, MU; long k; long n = A.length(); long i; MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) sub(A(i), A(i), B(i)); return; } if (MU == -1) { for (i = 1; i <= n; i++) add(A(i), A(i), B(i)); return; } if (MU == 0) return; if (NumTwos(MU) >= NTL_ZZ_NBITS) k = MakeOdd(MU); else k = 0; if (MU.WideSinglePrecision()) { long mu1; conv(mu1, MU); for (i = 1; i <= n; i++) { mul(T, B(i), mu1); if (k > 0) LeftShift(T, T, k); sub(A(i), A(i), T); } } else { for (i = 1; i <= n; i++) { mul(T, B(i), MU); if (k > 0) LeftShift(T, T, k); sub(A(i), A(i), T); } }}#define TR_BND (NTL_FDOUBLE_PRECISION/2.0)// Just to be safe!!static double max_abs(double *v, long n){ long i; double res, t; res = 0; for (i = 1; i <= n; i++) { t = fabs(v[i]); if (t > res) res = t; } return res;}static void RowTransformStart(double *a, long *in_a, long& in_float, long n){ long i; long inf = 1; for (i = 1; i <= n; i++) { in_a[i] = (a[i] < TR_BND && a[i] > -TR_BND); inf = inf & in_a[i]; } in_float = inf;}static void RowTransformFinish(vec_ZZ& A, double *a, long *in_a){ long n = A.length(); long i; for (i = 1; i <= n; i++) { if (in_a[i]) { conv(A(i), a[i]); } else { conv(a[i], A(i)); } }}static void RowTransform(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1, double mu, double *a, double *b, long *in_a, double& max_a, double max_b, long& in_float)// x = x - y*MU{ static ZZ T, MU; long k; long n = A.length(); long i; if (in_float) { max_a += fabs(mu)*max_b; if (max_a >= TR_BND) { in_float = 0; } } if (in_float) { if (mu == 1) { for (i = 1; i <= n; i++) a[i] -= b[i]; return; } if (mu == -1) { for (i = 1; i <= n; i++) a[i] += b[i]; return; } if (mu == 0) return; for (i = 1; i <= n; i++) a[i] -= mu*b[i]; return; } MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) { if (in_a[i] && a[i] < TR_BND && a[i] > -TR_BND && b[i] < TR_BND && b[i] > -TR_BND) { a[i] -= b[i]; } else { if (in_a[i]) { conv(A(i), a[i]); in_a[i] = 0; } sub(A(i), A(i), B(i)); } } return; } if (MU == -1) { for (i = 1; i <= n; i++) { if (in_a[i] && a[i] < TR_BND && a[i] > -TR_BND && b[i] < TR_BND && b[i] > -TR_BND) { a[i] += b[i]; } else { if (in_a[i]) { conv(A(i), a[i]); in_a[i] = 0; } add(A(i), A(i), B(i)); } } return; } if (MU == 0) return; double b_bnd = fabs(TR_BND/mu) - 1; if (b_bnd < 0) b_bnd = 0; if (NumTwos(MU) >= NTL_ZZ_NBITS) k = MakeOdd(MU); else k = 0; if (MU.WideSinglePrecision()) { long mu1; conv(mu1, MU); if (k > 0) { for (i = 1; i <= n; i++) { if (in_a[i]) { conv(A(i), a[i]); in_a[i] = 0; } mul(T, B(i), mu1); LeftShift(T, T, k); sub(A(i), A(i), T); } } else { for (i = 1; i <= n; i++) { if (in_a[i] && a[i] < TR_BND && a[i] > -TR_BND && b[i] < b_bnd && b[i] > -b_bnd) { a[i] -= b[i]*mu; } else { if (in_a[i]) { conv(A(i), a[i]); in_a[i] = 0; } mul(T, B(i), mu1); sub(A(i), A(i), T); } } } } else { for (i = 1; i <= n; i++) { if (in_a[i]) { conv(A(i), a[i]); in_a[i] = 0; } mul(T, B(i), MU); if (k > 0) LeftShift(T, T, k); sub(A(i), A(i), T); } }}static void RowTransform2(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1)// x = x + y*MU{ static ZZ T, MU; long k; long n = A.length(); long i; MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) add(A(i), A(i), B(i)); return; } if (MU == -1) { for (i = 1; i <= n; i++) sub(A(i), A(i), B(i)); return; } if (MU == 0) return; if (NumTwos(MU) >= NTL_ZZ_NBITS) k = MakeOdd(MU); else k = 0; if (MU.WideSinglePrecision()) { long mu1; conv(mu1, MU); for (i = 1; i <= n; i++) { mul(T, B(i), mu1); if (k > 0) LeftShift(T, T, k); add(A(i), A(i), T); } } else { for (i = 1; i <= n; i++) { mul(T, B(i), MU); if (k > 0) LeftShift(T, T, k); add(A(i), A(i), T); } }}staticvoid ComputeGS(mat_ZZ& B, double **B1, double **mu, double *b, double *c, long k, double bound, long st, double *buf){ long n = B.NumCols(); long i, j; double s, t1, y, t; ZZ T1; long test; double *mu_k = mu[k]; if (st < k) { for (i = 1; i < st; i++) buf[i] = mu_k[i]*c[i]; } for (j = st; j <= k-1; j++) { s = InnerProduct(B1[k], B1[j], n); // test = b[k]*b[j] >= NTL_FDOUBLE_PRECISION^2 test = (b[k]/NTL_FDOUBLE_PRECISION >= NTL_FDOUBLE_PRECISION/b[j]); // test = test && s^2 <= b[k]*b[j]/bound, // but we compute it in a strange way to avoid overflow if (test && (y = fabs(s)) != 0) { t = y/b[j]; t1 = b[k]/y; if (t <= 1) test = (t*bound <= t1); else if (t1 >= 1) test = (t <= t1/bound); else test = 0; } if (test) { InnerProduct(T1, B(k), B(j)); conv(s, T1); } double *mu_j = mu[j]; t1 = 0; for (i = 1; i <= j-1; i++) { t1 += mu_j[i]*buf[i]; } mu_k[j] = (buf[j] = (s - t1))/c[j]; }#if (!NTL_EXT_DOUBLE) // Kahan summation double c1; s = c1 = 0; for (j = 1; j <= k-1; j++) { y = mu_k[j]*buf[j] - c1; t = s+y; c1 = t-s; c1 = c1-y; s = t; }#else s = 0; for (j = 1; j <= k-1; j++) s += mu_k[j]*buf[j];#endif c[k] = b[k] - s;}static double red_fudge = 0;static long log_red = 0;static long verbose = 0;double LLLStatusInterval = 900.0;char *LLLDumpFile = 0;static unsigned long NumSwaps = 0;static double RR_GS_time = 0;static double StartTime = 0;static double LastTime = 0;static void LLLStatus(long max_k, double t, long m, const mat_ZZ& B){ cerr << "---- LLL_FP status ----\n"; cerr << "elapsed time: "; PrintTime(cerr, t-StartTime); cerr << ", stage: " << max_k; cerr << ", rank: " << m; cerr << ", swaps: " << NumSwaps << "\n"; ZZ t1; long i; double prodlen = 0; for (i = 1; i <= m; i++) { InnerProduct(t1, B(i), B(i)); if (!IsZero(t1)) prodlen += log(t1); } cerr << "log of prod of lengths: " << prodlen/(2.0*log(2.0)) << "\n"; if (LLLDumpFile) { cerr << "dumping to " << LLLDumpFile << "..."; ofstream f; OpenWrite(f, LLLDumpFile); f << "["; for (i = 1; i <= m; i++) { f << B(i) << "\n"; } f << "]\n"; f.close(); cerr << "\n"; } LastTime = t; }static void init_red_fudge(){ long i; log_red = long(0.50*NTL_DOUBLE_PRECISION); red_fudge = 1; for (i = log_red; i > 0; i--) red_fudge = red_fudge*0.5;}static void inc_red_fudge(){ red_fudge = red_fudge * 2; log_red--; cerr << "LLL_FP: warning--relaxing reduction (" << log_red << ")\n"; if (log_red < 4) Error("LLL_FP: too much loss of precision...stop!");}#if 0static void print_mus(double **mu, long k){ long i; for (i = k-1; i >= 1; i--) cerr << mu[k][i] << " "; cerr << "\n";}#endifvoid ComputeGS(const mat_ZZ& B, mat_RR& B1, mat_RR& mu, vec_RR& b, vec_RR& c, long k, const RR& bound, long st, vec_RR& buf, const RR& bound2);static void RR_GS(mat_ZZ& B, double **B1, double **mu, double *b, double *c, double *buf, long prec, long rr_st, long k, long m_orig, mat_RR& rr_B1, mat_RR& rr_mu, vec_RR& rr_b, vec_RR& rr_c){ double tt; cerr << "LLL_FP: RR refresh " << rr_st << "..." << k << "..."; tt = GetTime(); if (rr_st > k) Error("LLL_FP: can not continue!!!"); long old_p = RR::precision(); RR::SetPrecision(prec); long n = B.NumCols(); rr_B1.SetDims(k, n); rr_mu.SetDims(k, m_orig); rr_b.SetLength(k); rr_c.SetLength(k); vec_RR rr_buf; rr_buf.SetLength(k); long i, j; for (i = rr_st; i <= k; i++) for (j = 1; j <= n; j++) conv(rr_B1(i, j), B(i, j)); for (i = rr_st; i <= k; i++) InnerProduct(rr_b(i), rr_B1(i), rr_B1(i)); RR bound; power2(bound, 2*long(0.15*RR::precision())); RR bound2; power2(bound2, 2*RR::precision()); for (i = rr_st; i <= k; i++) ComputeGS(B, rr_B1, rr_mu, rr_b, rr_c, i, bound, 1, rr_buf, bound2); for (i = rr_st; i <= k; i++) for (j = 1; j <= n; j++) conv(B1[i][j], rr_B1(i,j)); for (i = rr_st; i <= k; i++) for (j = 1; j <= i-1; j++) { conv(mu[i][j], rr_mu(i,j)); if (!IsFinite(&mu[i][j])) Error("LLL_FP: numbers too big...use LLL_XD"); } for (i = rr_st; i <= k; i++) { conv(b[i], rr_b(i)); if (!IsFinite(&b[i])) Error("LLL_FP: numbers too big...use LLL_XD"); } for (i = rr_st; i <= k; i++) { conv(c[i], rr_c(i)); if (!IsFinite(&c[i])) Error("LLL_FP: numbers too big...use LLL_XD"); } for (i = 1; i <= k-1; i++) { conv(buf[i], rr_buf[i]); } RR::SetPrecision(old_p); tt = GetTime()-tt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -