📄 lll_qp.c
字号:
#include <NTL/LLL.h>#include <NTL/vec_quad_float.h>#include <NTL/fileio.h>#include <NTL/new.h>NTL_START_IMPLstatic quad_float InnerProduct(quad_float *a, quad_float *b, long n){ quad_float 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 quad_float max_abs(quad_float *v, long n){ long i; quad_float res, t; res = 0; for (i = 1; i <= n; i++) { t = fabs(v[i]); if (t > res) res = t; } return res;}static void RowTransformStart(quad_float *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].hi < TR_BND && a[i].hi > -TR_BND); inf = inf & in_a[i]; } in_float = inf;}static void RowTransformFinish(vec_ZZ& A, quad_float *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].hi); } else { conv(a[i], A(i)); } }} static void RowTransform(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1, quad_float *a, quad_float *b, long *in_a, quad_float& max_a, quad_float max_b, long& in_float)// x = x - y*MU{ static ZZ T, MU; long k; double mu; long n = A.length(); long i; conv(mu, MU1); 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].hi -= b[i].hi; return; } if (mu == -1) { for (i = 1; i <= n; i++) a[i].hi += b[i].hi; return; } if (mu == 0) return; for (i = 1; i <= n; i++) a[i].hi -= mu*b[i].hi; return; } MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) { if (in_a[i] && a[i].hi < TR_BND && a[i].hi > -TR_BND && b[i].hi < TR_BND && b[i].hi > -TR_BND) { a[i].hi -= b[i].hi; } else { if (in_a[i]) { conv(A(i), a[i].hi); 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].hi < TR_BND && a[i].hi > -TR_BND && b[i].hi < TR_BND && b[i].hi > -TR_BND) { a[i].hi += b[i].hi; } else { if (in_a[i]) { conv(A(i), a[i].hi); 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].hi); 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].hi < TR_BND && a[i].hi > -TR_BND && b[i].hi < b_bnd && b[i].hi > -b_bnd) { a[i].hi -= b[i].hi*mu; } else { if (in_a[i]) { conv(A(i), a[i].hi); 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].hi); 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, quad_float **B1, quad_float **mu, quad_float *b, quad_float *c, long k, double bound, long st, quad_float *buf){ long n = B.NumCols(); long i, j; quad_float s, t1, y, t; ZZ T1; long test; quad_float *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++) { if (b[k].hi/NTL_FDOUBLE_PRECISION < NTL_FDOUBLE_PRECISION/b[j].hi) { // we can compute inner product exactly in double precision double z = 0; quad_float *B1_k = B1[k]; quad_float *B1_j = B1[j]; for (i = 1; i <= n; i++) z += B1_k[i].hi * B1_j[i].hi; s = z; } else { s = InnerProduct(B1[k], B1[j], n); y = fabs(s); if (y.hi == 0) test = (b[k].hi != 0); else { double t = y.hi/b[j].hi; double t1 = b[k].hi/y.hi; 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); } } quad_float *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]; } s = 0; for (j = 1; j <= k-1; j++) s += mu_k[j]*buf[j]; c[k] = b[k] - s;}static quad_float red_fudge = to_quad_float(0);static long log_red = 0;static long verbose = 0;static unsigned long NumSwaps = 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_QP 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; // initial log_red should be <= NTL_DOUBLE_PRECISION-2, // to help ensure stability in BKZ_QP1 log_red = NTL_DOUBLE_PRECISION-2; 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_QP: warning--relaxing reduction (" << log_red << ")\n"; if (log_red < 4) Error("LLL_QP: too much loss of precision...stop!");}staticlong ll_LLL_QP(mat_ZZ& B, mat_ZZ* U, quad_float delta, long deep, LLLCheckFct check, quad_float **B1, quad_float **mu, quad_float *b, quad_float *c, long m, long init_k, long &quit){ long n = B.NumCols(); long i, j, k, Fc1; ZZ MU; quad_float mu1; quad_float t1; ZZ T1; quad_float *tp; static double bound = 0; if (bound == 0) { // we tolerate a 15% loss of precision in computing // inner products in ComputeGS. bound = 1; for (i = 2*long(0.15*2*NTL_DOUBLE_PRECISION); i > 0; i--) { bound = bound * 2; } } quad_float half = to_quad_float(0.5); quad_float half_plus_fudge = 0.5 + red_fudge; quit = 0; k = init_k; vec_long st_mem; st_mem.SetLength(m+2); long *st = st_mem.elts(); for (i = 1; i < k; i++) st[i] = i; for (i = k; i <= m+1; i++) st[i] = 1; quad_float *buf; buf = NTL_NEW_OP quad_float [m+1]; if (!buf) Error("out of memory in lll_LLL_QP"); vec_long in_vec_mem; in_vec_mem.SetLength(n+1); long *in_vec = in_vec_mem.elts(); quad_float *max_b; max_b = NTL_NEW_OP quad_float [m+1]; if (!max_b) Error("out of memory in lll_LLL_QP"); for (i = 1; i <= m; i++) max_b[i] = max_abs(B1[i], n); long in_float; long rst; long counter; long trigger_index; long small_trigger; long cnt; long max_k = 0; double tt; while (k <= m) { if (k > max_k) { max_k = k; } if (verbose) { tt = GetTime(); if (tt > LastTime + LLLStatusInterval) LLLStatus(max_k, tt, m, B); } if (st[k] == k) rst = 1; else rst = k; if (st[k] < st[k+1]) st[k+1] = st[k]; ComputeGS(B, B1, mu, b, c, k, bound, st[k], buf); if (!IsFinite(&c[k])) Error("LLL_QP: numbers too big...use LLL_XD"); st[k] = k; counter = 0; trigger_index = k; small_trigger = 0; cnt = 0; do { // size reduction counter++; if (counter > 10000) { cerr << "LLL_QP: warning--possible infinite loop\n"; counter = 0; } Fc1 = 0; for (j = rst-1; j >= 1; j--) { t1 = fabs(mu[k][j]); if (t1 > half_plus_fudge) { if (!Fc1) { if (j > trigger_index || (j == trigger_index && small_trigger)) { cnt++; if (cnt > 10) { inc_red_fudge(); half_plus_fudge = 0.5 + red_fudge; cnt = 0; } } trigger_index = j; small_trigger = (t1 < 4); Fc1 = 1; RowTransformStart(B1[k], in_vec, in_float, n); } mu1 = mu[k][j]; if (mu1 >= 0) mu1 = ceil(mu1-half); else mu1 = floor(mu1+half); quad_float *mu_k = mu[k]; quad_float *mu_j = mu[j]; if (mu1 == 1) { for (i = 1; i <= j-1; i++) mu_k[i] -= mu_j[i]; } else if (mu1 == -1) { for (i = 1; i <= j-1; i++) mu_k[i] += mu_j[i]; } else { for (i = 1; i <= j-1; i++) mu_k[i] -= mu1*mu_j[i]; } // cout << j << " " << mu[k][j] << " " << mu1 << "\n"; mu_k[j] -= mu1; conv(MU, mu1); RowTransform(B(k), B(j), MU, B1[k], B1[j], in_vec, max_b[k], max_b[j], in_float); if (U) RowTransform((*U)(k), (*U)(j), MU); } } if (Fc1) { RowTransformFinish(B(k), B1[k], in_vec); max_b[k] = max_abs(B1[k], n); b[k] = InnerProduct(B1[k], B1[k], n); ComputeGS(B, B1, mu, b, c, k, bound, 1, buf); if (!IsFinite(&b[k])) Error("LLL_QP: numbers too big...use LLL_XD"); if (!IsFinite(&c[k])) Error("LLL_QP: numbers too big...use LLL_XD"); } } while (Fc1); if (check && (*check)(B(k))) quit = 1; if (b[k] == 0) { for (i = k; i < m; i++) { // swap i, i+1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -