📄 nbtheory.cpp
字号:
cout << hex << t3 << endl; Integer t4 = p * t3; cout << hex << t4 << endl; Integer t5 = t4 + xp; cout << hex << t5 << endl; return t5;*/}Integer ModularSquareRoot(const Integer &a, const Integer &p){ if (p%4 == 3) return a_exp_b_mod_c(a, (p+1)/4, p); Integer q=p-1; unsigned int r=0; while (q.IsEven()) { r++; q >>= 1; } Integer n=2; while (Jacobi(n, p) != -1) ++n; Integer y = a_exp_b_mod_c(n, q, p); Integer x = a_exp_b_mod_c(a, (q-1)/2, p); Integer b = (x.Squared()%p)*a%p; x = a*x%p; Integer tempb, t; while (b != 1) { unsigned m=0; tempb = b; do { m++; b = b.Squared()%p; if (m==r) return Integer::Zero(); } while (b != 1); t = y; for (unsigned i=0; i<r-m-1; i++) t = t.Squared()%p; y = t.Squared()%p; r = m; x = x*t%p; b = tempb*y%p; } assert(x.Squared()%p == a); return x;}bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p){ Integer D = (b.Squared() - 4*a*c) % p; switch (Jacobi(D, p)) { default: assert(false); // not reached return false; case -1: return false; case 0: r1 = r2 = (-b*(a+a).InverseMod(p)) % p; assert(((r1.Squared()*a + r1*b + c) % p).IsZero()); return true; case 1: Integer s = ModularSquareRoot(D, p); Integer t = (a+a).InverseMod(p); r1 = (s-b)*t % p; r2 = (-s-b)*t % p; assert(((r1.Squared()*a + r1*b + c) % p).IsZero()); assert(((r2.Squared()*a + r2*b + c) % p).IsZero()); return true; }}Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u){ Integer p2, q2; #pragma omp parallel #pragma omp sections { #pragma omp section p2 = ModularExponentiation((a % p), dp, p); #pragma omp section q2 = ModularExponentiation((a % q), dq, q); } return CRT(p2, p, q2, q, u);}Integer ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q){ Integer dp = EuclideanMultiplicativeInverse(e, p-1); Integer dq = EuclideanMultiplicativeInverse(e, q-1); Integer u = EuclideanMultiplicativeInverse(p, q); assert(!!dp && !!dq && !!u); return ModularRoot(a, dp, dq, p, q, u);}/*Integer GCDI(const Integer &x, const Integer &y){ Integer a=x, b=y; unsigned k=0; assert(!!a && !!b); while (a[0]==0 && b[0]==0) { a >>= 1; b >>= 1; k++; } while (a[0]==0) a >>= 1; while (b[0]==0) b >>= 1; while (1) { switch (a.Compare(b)) { case -1: b -= a; while (b[0]==0) b >>= 1; break; case 0: return (a <<= k); case 1: a -= b; while (a[0]==0) a >>= 1; break; default: assert(false); } }}Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b){ assert(b.Positive()); if (a.Negative()) return EuclideanMultiplicativeInverse(a%b, b); if (b[0]==0) { if (!b || a[0]==0) return Integer::Zero(); // no inverse if (a==1) return 1; Integer u = EuclideanMultiplicativeInverse(b, a); if (!u) return Integer::Zero(); // no inverse else return (b*(a-u)+1)/a; } Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1; if (a[0]) { t1 = Integer::Zero(); t3 = -b; } else { t1 = b2; t3 = a>>1; } while (!!t3) { while (t3[0]==0) { t3 >>= 1; if (t1[0]==0) t1 >>= 1; else { t1 >>= 1; t1 += b2; } } if (t3.Positive()) { u = t1; d = t3; } else { v1 = b-t1; v3 = -t3; } t1 = u-v1; t3 = d-v3; if (t1.Negative()) t1 += b; } if (d==1) return u; else return Integer::Zero(); // no inverse}*/int Jacobi(const Integer &aIn, const Integer &bIn){ assert(bIn.IsOdd()); Integer b = bIn, a = aIn%bIn; int result = 1; while (!!a) { unsigned i=0; while (a.GetBit(i)==0) i++; a>>=i; if (i%2==1 && (b%8==3 || b%8==5)) result = -result; if (a%4==3 && b%4==3) result = -result; std::swap(a, b); a %= b; } return (b==1) ? result : 0;}Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n){ unsigned i = e.BitCount(); if (i==0) return Integer::Two(); MontgomeryRepresentation m(n); Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two()); Integer v=p, v1=m.Subtract(m.Square(p), two); i--; while (i--) { if (e.GetBit(i)) { // v = (v*v1 - p) % m; v = m.Subtract(m.Multiply(v,v1), p); // v1 = (v1*v1 - 2) % m; v1 = m.Subtract(m.Square(v1), two); } else { // v1 = (v*v1 - p) % m; v1 = m.Subtract(m.Multiply(v,v1), p); // v = (v*v - 2) % m; v = m.Subtract(m.Square(v), two); } } return m.ConvertOut(v);}// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm.// The total number of multiplies and squares used is less than the binary// algorithm (see above). Unfortunately I can't get it to run as fast as// the binary algorithm because of the extra overhead./*Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus){ if (!n) return 2;#define f(A, B, C) m.Subtract(m.Multiply(A, B), C)#define X2(A) m.Subtract(m.Square(A), two)#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three)) MontgomeryRepresentation m(modulus); Integer two=m.ConvertIn(2), three=m.ConvertIn(3); Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U; while (d!=1) { p = d; unsigned int b = WORD_BITS * p.WordCount(); Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1); r = (p*alpha)>>b; e = d-r; B = A; C = two; d = r; while (d!=e) { if (d<e) { swap(d, e); swap(A, B); } unsigned int dm2 = d[0], em2 = e[0]; unsigned int dm3 = d%3, em3 = e%3;// if ((dm6+em6)%3 == 0 && d <= e + (e>>2)) if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t)) { // #1// t = (d+d-e)/3;// t = d; t += d; t -= e; t /= 3;// e = (e+e-d)/3;// e += e; e -= d; e /= 3;// d = t;// t = (d+e)/3 t = d; t += e; t /= 3; e -= t; d -= t; T = f(A, B, C); U = f(T, A, B); B = f(T, B, A); A = U; continue; }// if (dm6 == em6 && d <= e + (e>>2)) if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t)) { // #2// d = (d-e)>>1; d -= e; d >>= 1; B = f(A, B, C); A = X2(A); continue; }// if (d <= (e<<2)) if (d <= (t = e, t <<= 2)) { // #3 d -= e; C = f(A, B, C); swap(B, C); continue; } if (dm2 == em2) { // #4// d = (d-e)>>1; d -= e; d >>= 1; B = f(A, B, C); A = X2(A); continue; } if (dm2 == 0) { // #5 d >>= 1; C = f(A, C, B); A = X2(A); continue; } if (dm3 == 0) { // #6// d = d/3 - e; d /= 3; d -= e; T = X2(A); C = f(T, f(A, B, C), C); swap(B, C); A = f(T, A, A); continue; } if (dm3+em3==0 || dm3+em3==3) { // #7// d = (d-e-e)/3; d -= e; d -= e; d /= 3; T = f(A, B, C); B = f(T, A, B); A = X3(A); continue; } if (dm3 == em3) { // #8// d = (d-e)/3; d -= e; d /= 3; T = f(A, B, C); C = f(A, C, B); B = T; A = X3(A); continue; } assert(em2 == 0); // #9 e >>= 1; C = f(C, B, A); B = X2(B); } A = f(A, B, C); }#undef f#undef X2#undef X3 return m.ConvertOut(A);}*/Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u){ Integer d = (m*m-4); Integer p2, q2; #pragma omp parallel #pragma omp sections { #pragma omp section { p2 = p-Jacobi(d,p); p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p); } #pragma omp section { q2 = q-Jacobi(d,q); q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q); } } return CRT(p2, p, q2, q, u);}unsigned int FactoringWorkFactor(unsigned int n){ // extrapolated from the table in Odlyzko's "The Future of Integer Factorization" // updated to reflect the factoring of RSA-130 if (n<5) return 0; else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5);}unsigned int DiscreteLogWorkFactor(unsigned int n){ // assuming discrete log takes about the same time as factoring if (n<5) return 0; else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5);}// ********************************************************void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits){ // no prime exists for delta = -1, qbits = 4, and pbits = 5 assert(qbits > 4); assert(pbits > qbits); if (qbits+1 == pbits) { Integer minP = Integer::Power2(pbits-1); Integer maxP = Integer::Power2(pbits) - 1; bool success = false; while (!success) { p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12); PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta); while (sieve.NextCandidate(p)) { assert(IsSmallPrime(p) || SmallDivisorsTest(p)); q = (p-delta) >> 1; assert(IsSmallPrime(q) || SmallDivisorsTest(q)); if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p)) { success = true; break; } } } if (delta == 1) { // find g such that g is a quadratic residue mod p, then g has order q // g=4 always works, but this way we get the smallest quadratic residue (other than 1) for (g=2; Jacobi(g, p) != 1; ++g) {} // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity assert((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4); } else { assert(delta == -1); // find g such that g*g-4 is a quadratic non-residue, // and such that g has order q for (g=3; ; ++g) if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) break; } } else { Integer minQ = Integer::Power2(qbits-1); Integer maxQ = Integer::Power2(qbits) - 1; Integer minP = Integer::Power2(pbits-1); Integer maxP = Integer::Power2(pbits) - 1; do { q.Randomize(rng, minQ, maxQ, Integer::PRIME); } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, delta%q, q)); // find a random g of order q if (delta==1) { do { Integer h(rng, 2, p-2, Integer::ANY); g = a_exp_b_mod_c(h, (p-1)/q, p); } while (g <= 1); assert(a_exp_b_mod_c(g, q, p)==1); } else { assert(delta==-1); do { Integer h(rng, 3, p-1, Integer::ANY); if (Jacobi(h*h-4, p)==1) continue; g = Lucas((p+1)/q, h, p); } while (g <= 2); assert(Lucas(q, g, p) == 2); } }}NAMESPACE_END#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -