void negate(vec_ZZ& x, const vec_ZZ& a) { long n = a.length(); x.SetLength(n); long i; for (i = 0; i < n; i++) negate(x[i], a[i]); }
void conv(vec_ZZ& x, const vec_zz_p& a) { long n = a.length(); x.SetLength(n); long i; for (i = 0; i < n; i++) x[i] = rep(a[i]); }
void mul(vec_ZZ& x, const vec_ZZ& a, long b) { long n = a.length(); x.SetLength(n); long i; for (i = 0; i < n; i++) mul(x[i], a[i], b); }
void sub(vec_ZZ& x, const vec_ZZ& a, const vec_ZZ& b) { long n = a.length(); if (b.length() != n) LogicError("vector sub: dimension mismatch"); x.SetLength(n); long i; for (i = 0; i < n; i++) sub(x[i], a[i], b[i]); }
void mul(vec_ZZ& x, const vec_ZZ& a, const ZZ& b_in) { ZZ b = b_in; long n = a.length(); x.SetLength(n); long i; for (i = 0; i < n; i++) mul(x[i], a[i], b); }
static void MulSubDiv(vec_ZZ& c, const vec_ZZ& c1, const vec_ZZ& c2, const ZZ& x, const ZZ& y, const ZZ& z) // c = (x*c1 + y*c2)/z { long n = c1.length(); if (c2.length() != n) Error("MulSubDiv: length mismatch"); c.SetLength(n); long i; for (i = 1; i <= n; i++) MulSubDiv(c(i), c1(i), c2(i), x, y, z); }
void VectorCopy(vec_ZZ& x, const vec_ZZ& a, long n) { if (n < 0) LogicError("VectorCopy: negative length"); if (NTL_OVERFLOW(n, 1, 0)) ResourceError("overflow in VectorCopy"); long m = min(n, a.length()); x.SetLength(n); long i; for (i = 0; i < m; i++) x[i] = a[i]; for (i = m; i < n; i++) clear(x[i]); }
//Ideal lattice challenge problem generator //modified from generate_ideal.cpp in Ideal lattice Challenge web page void gen_idealsvpchallenge(mat_ZZ& B,int index,ZZ seed,vec_ZZ& phivec) { ZZX phi=find_cyclotomic(index); long n=deg(phi); ZZ det=find_determinant(index,10*n,seed); ZZ alpha=find_unity_root(index,det,phi); B.SetDims(n,n); clear(B); B(1,1) = det; for (long i=2; i<=n; i++) { B(i,1)=det-PowerMod(alpha,i-1,det); B(i,i)=1; } phivec.SetLength(n+1); for (int i=0;i<=n;i++) phivec[i] = coeff(phi,i); }
static void MixedMul(vec_ZZ& x, const vec_zz_p& a, const mat_ZZ& B) { long n = B.NumRows(); long l = B.NumCols(); if (n != a.length()) Error("matrix mul: dimension mismatch"); x.SetLength(l); long i, k; ZZ acc, tmp; for (i = 1; i <= l; i++) { clear(acc); for (k = 1; k <= n; k++) { mul(tmp, B(k, i), rep(a(k))); add(acc, acc, tmp); } x(i) = acc; } }
static void mul_aux(vec_ZZ& x, const mat_ZZ& A, const vec_ZZ& b) { long n = A.NumRows(); long l = A.NumCols(); if (l != b.length()) Error("matrix mul: dimension mismatch"); x.SetLength(n); long i, k; ZZ acc, tmp; for (i = 1; i <= n; i++) { clear(acc); for (k = 1; k <= l; k++) { mul(tmp, A(i,k), b(k)); add(acc, acc, tmp); } x(i) = acc; } }
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 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; }
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; }
/* * Certificate format: * [N q m/q a b x y] */ bool ProvePrime_Atkin(const ZZ& N, vec_ZZ& cert, HilbertClassPolynomials& HCP) { ZZ threshold; // want: threshold = ceil((N^{1/2}+1)^2) = ceil(N^{1/2} + 2*N^{1/4} + 1) ZZ Ns,Nf; SqrRoot(Ns,N); // Ns+1 = ceil(N^{1/2}) SqrRoot(Nf,Ns+1); // Nf+1 >= ceil(N^{1/4}) threshold = Ns+1 + 2*(Nf+1) + 1; // threshold may be a little too high here std::cout<<std::endl; std::cout<<"N="<<N<<std::endl; std::cout<<"threshold = "<<threshold<<std::endl; ZZ_pBak bak1; bak1.save(); ZZ_p::init(N); EC_pBak bak2; bak2.save(); long n=0; ZZ D; while (!IsZero(D=-discriminant_array[n++])) { // long D4 = rem(D,4); //if (D4!=0 && D4!=1) // continue; if (Jacobi(D+N,N)!=1) continue; // step 3 ZZ u,v; if (!Cornacchia(u,v,D,N)) continue; // step 4 ZZ m,q; bool found=false; if (check_for_factor(q,m=N+1+u,threshold)) found=true; else if (check_for_factor(q,m=N+1-u,threshold)) found=true; else if (D==-4) { if (check_for_factor(q,m=N+1+2*v,threshold)) found=true; else if (check_for_factor(q,m=N+1-2*v,threshold)) found=true; } else if (D==-3) { if (check_for_factor(q,m=N+1+(u+3*v)/2,threshold)) found=true; else if (check_for_factor(q,m=N+1-(u+3*v)/2,threshold)) found=true; else if (check_for_factor(q,m=N+1+(u-3*v)/2,threshold)) found=true; else if (check_for_factor(q,m=N+1-(u-3*v)/2,threshold)) found=true; } if (!found) continue; std::cout<<"m="<<m<<std::endl; std::cout<<"q="<<q<<std::endl; // step 6 EC_pCurve curve; ZZ_p A,B; find_curve(A,B,to_long(D),N,HCP); SetCoeff(curve,1,A); SetCoeff(curve,0,B); std::cout<<"curve="<<curve<<std::endl; // step 7 ZZ_p g; do { random(g); if (Jacobi(rep(g),N)!=-1) continue; if ((N%3)==1) { // always happens in the case D==-3 ZZ_p t; power(t,g,(N-1)/3); if (IsOne(t)) continue; //std::cout<<"t="<<t<<std::endl; } break; } while (true); //std::cout<<"g="<<g<<std::endl; long k=0; EC_p::init(curve); EC_p P,P1,P2; do { // step 8 random(P); if (!IsValid(P)) return false; // step 9 //std::cout<<"P="<<P<<std::endl; mul(P2,P,m/q); //std::cout<<"P2="<<P2<<std::endl; // NOTE: if IsZero(P2) just choose a new point, not a new curve!!! if (!IsZero(P2)) { mul(P1,P2,q); //std::cout<<"P1="<<P1<<std::endl; if (IsZero(P1)) break; } // step 10 ++k; if (D==-3) { if (k>=6) { std::cout<<"P="<<P<<std::endl; std::cout<<"P1="<<P1<<std::endl; std::cout<<"P2="<<P2<<std::endl; return false; } SetCoeff(curve,0,coeff(curve,0)*g); } else if (D==-4) { if (k>=4) { std::cout<<"P="<<P<<std::endl; std::cout<<"P1="<<P1<<std::endl; std::cout<<"P2="<<P2<<std::endl; return false; } SetCoeff(curve,1,coeff(curve,1)*g); } else { if (k>=2) { std::cout<<"P="<<P<<std::endl; std::cout<<"P1="<<P1<<std::endl; std::cout<<"P2="<<P2<<std::endl; return false; } SetCoeff(curve,1,coeff(curve,1)*sqr(g)); SetCoeff(curve,0,coeff(curve,0)*sqr(g)*g); } EC_p::init(curve); } while (true); // check that P2 has an affine representation ZZ G; GCD(G,rep(P2.Z),N); if (!IsOne(G)) return false; // step 13 ZZ_p Px,Py; P.affine(Px,Py); cert.SetLength(7); cert[0] = N; cert[1] = q; cert[2] = m/q; cert[3] = coeff(curve,1)==-1 ? to_ZZ(-1) : rep(coeff(curve,1)); cert[4] = coeff(curve,0)==-1 ? to_ZZ(-1) : rep(coeff(curve,0)); cert[5] = rep(Px); cert[6] = rep(Py); return true; } Error("ProvePrime: ran out of discriminants"); return false; }