00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "config.hpp"
00013
00014 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00015 defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_PRIME)
00016
00017 #include <list>
00018 #include <iterator>
00019
00020 #include "prime.hpp"
00021 #include "exception.hpp"
00022 #include "powerest.hpp"
00023 #include "rand.hpp"
00024
00025
00026 namespace Arageli
00027 {
00028
00029 template <typename Out, typename T>
00030 Out small_primes (Out primes, const T& N)
00031 {
00032
00033
00034 typedef typename std::iterator_traits<Out>::value_type Val;
00035 typedef typename std::iterator_traits<Out>::reference Ref;
00036
00037 primes[0] = 2;
00038 Val n = 3;
00039
00040 for (T j = 1; j < N; j++)
00041 {
00042 primes[j] = n;
00043 for(;;)
00044 {
00045 n += 2;
00046 for(T k = 1; ; k++)
00047 {
00048 Val q, r;
00049 Ref pk = primes[k];
00050 divide(n, pk, q, r);
00051 if(is_null(r))break;
00052 if(q <= pk)goto next_prime;
00053 }
00054 }
00055 next_prime: ;
00056 }
00057
00058 return primes + N;
00059 }
00060
00061 template <typename T, typename T_factory>
00062 bool is_prime_division (const T& x, const T_factory& tfctr)
00063 {
00064 T d = tfctr.unit(x);
00065 if(x <= d)return false;
00066 ++d;
00067 if(x == d)return true;
00068 if(is_null(x % d))return false;
00069 ++d;
00070 if(x == d)return true;
00071 if(is_null(x % d))return false;
00072
00073 d += 2;
00074
00075 T q, r;
00076
00077 for(;;)
00078 for(unsigned s = 2; s <= 4; s += 2)
00079 {
00080 divide(x, d, q, r);
00081 if(q < d)return true;
00082 if(is_null(r))return false;
00083 d += s;
00084 }
00085 }
00086
00087 template <typename T, typename N, typename T_factory>
00088 bool is_pseudoprime_solovay_strassen (const T& x, const N& n, const T_factory& tfctr)
00089 {
00090 if (x<=unit(x)) return false;
00091 if (x == T(2)) return true;
00092 T jac;
00093 T a;
00094 for (N i = null(n); i < n; ++i)
00095 {
00096 a = rand(x-3);
00097 a += 2;
00098 if (!is_unit(gcd(a,x))) return false;
00099 jac = jacobi(a, x);
00100 if (is_opposite_unit(jac)) jac += x;
00101 if (power_mod(a, (x-1)/2, x) != jac ) return false;
00102 }
00103 return true;
00104 }
00105
00106 template <typename T, typename N, typename T_factory>
00107 bool is_pseudoprime_miller_rabin (const T& x, const N& n, const T_factory& tfctr)
00108 {
00109 ARAGELI_ASSERT_0(is_positive(x));
00110 if(is_unit(x))return false;
00111 if(x == 2) return true;
00112 if(is_even(x)) return false;
00113 T a, q, c;
00114 N k;
00115 const T unt = unit(x);
00116 const T start_q = (x - 1) >> 1;
00117 for (N i = null(n); i < n; ++i)
00118 {
00119 a = rand(x-3);
00120 a += 2;
00121 if(!is_unit(gcd(a,x))) return false;
00122 q = start_q;
00123 k = unit(n);
00124 while (is_even(q))
00125 {
00126 q = q >> 1;
00127 ++k;
00128 }
00129 c = power_mod(a, q, x);
00130 if (is_unit(c) || c == x - unt) continue;
00131
00132 N j = unit(k);
00133 for (; j < k; ++j)
00134 {
00135 (c *= c) %= x;
00136 if (c == x - unt) break;
00137 if (is_unit(c)) return false;
00138 }
00139 if (j == k)
00140 return false;
00141 }
00142 return true;
00143 }
00144
00145 template <typename T>
00146 T LPF(T p)
00147 {
00148 T s = p;
00149 T i = 2;
00150 T j = intsqrt(s);
00151 while (i <= j)
00152 {
00153 if (s%i == 0)
00154 {
00155 s=s/i;
00156 j = intsqrt(s);
00157 }
00158 else ++i;
00159 }
00160 return s;
00161 }
00162
00163 template <typename T>
00164 bool is_power_of_prime(T n, long b)
00165 {
00166 T p = square(nbits(n)/b + 1);
00167 T q;
00168 while (true)
00169 {
00170 q = (p*(b-1) + n/(power(p,b-1)))/b;
00171 if (q>=p)
00172 break;
00173 p=q;
00174 }
00175 if ( n == power(p,b))
00176 return true;
00177 return false;
00178 }
00179
00180 template <typename T>
00181 bool is_prime_AKS_classic (const T& n)
00182 {
00183 T N = intsqrt(n);
00184 if (square(N) == n) return false;
00185 int i;
00186 int len = n.length();
00187 for (i = 3; i < len; i+=2)
00188 if (is_power_of_prime(n,i)) return false;
00189
00190 T r = 3;
00191 T q, s;
00192 int len4 = 4*len;
00193 while (r<N)
00194 {
00195 if (is_prime(r))
00196 {
00197 if (gcd(r,n) != 1) return false;
00198 q = LPF(r-1);
00199 if ((q >= 4*intsqrt(r)+len4) &&
00200 (power_mod((n%r),((r-1)/q),r) <= 1))
00201 break;
00202 }
00203 r+=2;
00204 }
00205 if (r >= N) return true;
00206 sparse_polynom<T> mod_part;
00207 sparse_polynom<T> right_part;
00208 mod_part = power(sparse_polynom<T>("x"), r)-1;
00209 right_part = power_mod(sparse_polynom<T>("x"), n, mod_part);
00210 s = 2*N*len;
00211 for(i = 1; i <= s; ++i)
00212 {
00213 sparse_polynom<T> left_part("x");
00214 left_part -= i;
00215 left_part = power_mod(left_part, n, mod_part);
00216 left_part += i;
00217 sparse_polynom_reduction_mod(left_part, n);
00218 if (left_part != right_part) return false;
00219 }
00220 return true;
00221 }
00222 template<typename T>
00223 long primitive_root(T n, T r)
00224 {
00225 long i;
00226 long r_len = r.length();
00227 for (i = 1; i <= r_len; ++i)
00228 {
00229 if( is_unit(power_mod(n%r,i,r)) )
00230 return i;
00231 }
00232 return 0;
00233 }
00234
00235 template <typename T>
00236 bool is_prime_AKS (const T& n)
00237 {
00238 T N = intsqrt(n);
00239 if (square(N) == n) return false;
00240 long i;
00241 long len = n.length();
00242 for (i = 3; i < len; i+=2)
00243 if (is_power_of_prime(n,i)) return false;
00244 T r = next_prime(power(len,2));
00245 T q, s;
00246
00247 for (;primitive_root(n,r+2);r=next_prime(r+2));
00248 for (q = 3; (is_unit(gcd(q,n)) || (gcd(q,n) == n)) && (q < r); ++q);
00249 if (q<r) { return false; }
00250 else
00251 if (n<=r) { return false;}
00252
00253 sparse_polynom<T> mod_part;
00254 sparse_polynom<T> right_part;
00255 mod_part = power(sparse_polynom<T>("x"), r)-1;
00256 right_part = power_mod(sparse_polynom<T>("x"), n, mod_part);
00257 s = intsqrt(r)*len;
00258 for(i = 1; i <= s; ++i)
00259 {
00260 sparse_polynom<T> left_part("x");
00261 left_part -= i;
00262 left_part = power_mod(left_part, n, mod_part);
00263 left_part += i;
00264 sparse_polynom_reduction_mod(left_part, n);
00265 if (left_part != right_part) return false;
00266 }
00267 return true;
00268 }
00269
00270 template <typename T, typename N>
00271 int is_prime_small_primes_division (const T& n, const N& np)
00272 {
00273 ARAGELI_ASSERT_0(n > unit(n));
00274
00275 vector<int, false> small_primes;
00276 small_primes(small_primes, np);
00277
00278 for(int j = 0; j < np; j++)
00279 {
00280 if(n == small_primes[j])return 1;
00281 if(is_divisible(n, small_primes[j]))return 0;
00282 }
00283
00284
00285 return -1;
00286 }
00287
00288 template <typename T1, typename T2, bool REFCNT2, typename T_factory>
00289 vector<T2, REFCNT2>& factorize_division
00290 (T1 x, vector<T2, REFCNT2>& res, const T_factory& tfctr)
00291 {
00292 ARAGELI_DEBUG_EXEC_2(T1 xx = x);
00293 ARAGELI_ASSERT_0(is_positive(x));
00294
00295 if(is_unit(x))
00296 {
00297 res.resize(0);
00298 return res;
00299 }
00300
00301 T1 d = tfctr.unit(x);
00302 ARAGELI_ASSERT_0(x >= d);
00303 ++d;
00304
00305 std::list<T2> resbuf;
00306
00307 while(is_null(x % 2))
00308 {
00309 x >>= 1;
00310 resbuf.push_back(d);
00311 }
00312
00313 T1 q, r;
00314
00315 ++d;
00316
00317 for(;;)
00318 {
00319 divide(x, d, q, r);
00320 if(is_null(r))
00321 {
00322 x = q;
00323 resbuf.push_back(d);
00324 }
00325 else break;
00326 }
00327
00328 d += 2;
00329
00330 unsigned s = 2;
00331
00332 while(!is_unit(x))
00333 {
00334 ARAGELI_ASSERT_1(x >= d);
00335
00336 divide(x, d, q, r);
00337 if(is_null(r))
00338 {
00339 x = q;
00340 resbuf.push_back(d);
00341 }
00342 else if(q < d)
00343 {
00344 ARAGELI_ASSERT_1(is_prime(x, tfctr));
00345
00346 resbuf.push_back(x);
00347 break;
00348 }
00349 else
00350 {
00351
00352 d += s;
00353 if(s == 2)s = 4;
00354 else s = 2;
00355 }
00356 }
00357
00358 res.assign(resbuf.size(), resbuf.begin());
00359
00360 ARAGELI_DEBUG_EXEC_2(T1 tt);
00361 ARAGELI_ASSERT_2(product(res, tt) == xx);
00362
00363 return res;
00364 }
00365
00366 namespace _Internal
00367 {
00368 template<typename T>
00369 T random_function(T x, T n)
00370 {
00371 return (x*x+5)%n;
00372 }
00373 }
00374
00375 template<typename T, typename T_factory>
00376 T rho_pollard(const T& n, const T_factory& tfctr)
00377 {
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 ARAGELI_ASSERT_1(n >= 4);
00396 T x0 = rand(n-1);
00397 T x = x0;
00398 T d;
00399 unsigned int i, j = 1;
00400 while (true)
00401 {
00402 x0 = x;
00403 for (i = 1; i <= j; ++i)
00404 {
00405 x = _Internal::random_function(x, n);
00406 d = gcd(std::abs(x-x0), n);
00407 if ((d > 1) && (d <= n)) return d;
00408 }
00409 j*=2;
00410 }
00411 }
00412
00413 template<typename T, typename N, typename T_factory>
00414 T brent(const T& n, N no_of_iter, const T_factory& tfctr)
00415 {
00416 N r = 1;
00417 N m = 10;
00418 N iter = 0;
00419
00420 T y = 0;
00421 T q = 1;
00422 T x, ys, g;
00423
00424 do
00425 {
00426 x = y;
00427 for (N j = 1; j <= r; j++)
00428 y = _Internal::random_function(y, n);
00429
00430 N k = 0;
00431
00432 do
00433 {
00434 iter++;
00435 if (iter > no_of_iter)
00436 return 0;
00437 ys = y;
00438 T mn = r - k;
00439 if (m < mn) mn = m;
00440 for (N j = 1; j <= mn; j++)
00441 {
00442 y = _Internal::random_function(y, n);
00443 q = (q * std::abs(x - y)) % n;
00444 }
00445 g = gcd(q, n);
00446 k = k + m;
00447
00448 }
00449 while(k < r && g <= 1);
00450
00451 r = 2 * r;
00452 }
00453 while (g <= 1);
00454
00455 if (g == n)
00456 {
00457 do
00458 {
00459 ys = _Internal::random_function(ys, n);
00460 g = gcd(x - ys, n);
00461 }
00462 while (g <= 1);
00463 }
00464
00465 if (g == n)
00466 return 0;
00467 else
00468 return g;
00469 }
00470
00471 template<typename T, typename N, typename T_factory>
00472 T pollard_pm1(const T& n, const N& no_of_iter, const T_factory& tfctr)
00473 {
00474 T b = 2, t = 2, p = unit(n);
00475 for(N i = 2; i <= no_of_iter; i++)
00476 {
00477
00478 t = power_mod(t, i, n);
00479 p = gcd(n, t - 1);
00480 if (p > unit(n) && p < n)
00481 return p;
00482 if (p == n)
00483 {
00484 i = 2;
00485 t = ++b;
00486 if (b == 5)
00487 return null(n);
00488 }
00489 }
00490 return null(n);
00491 }
00492
00493 template
00494 <
00495 typename T1,
00496 typename T2, bool REFCNT2,
00497 typename T3, typename T4
00498 >
00499 vector<T2, REFCNT2>& partial_factorize_division
00500 (T1 x, vector<T2, REFCNT2>& res, const T3& max, T4& rest)
00501 {
00502 ARAGELI_DEBUG_EXEC_2(T1 xx = x);
00503
00504 if(is_unit(x) || max < 2)
00505 {
00506 res.resize(0);
00507 rest = x;
00508
00509 ARAGELI_DEBUG_EXEC_2(T1 tt);
00510 ARAGELI_ASSERT_2(product(res, tt)*rest == xx);
00511
00512 return res;
00513 }
00514
00515 T1 d = unit(x);
00516 ARAGELI_ASSERT_0(x >= d);
00517 ++d;
00518
00519 std::list<T2> resbuf;
00520
00521 while(is_null(x % 2))
00522 {
00523 x >>= 1;
00524 resbuf.push_back(d);
00525 }
00526
00527 if(max < 3)
00528 {
00529 res.assign(resbuf.size(), resbuf.begin());
00530 rest = x;
00531
00532 ARAGELI_DEBUG_EXEC_2(T1 tt);
00533 ARAGELI_ASSERT_2(product(res, tt)*rest == xx);
00534
00535 return res;
00536 }
00537
00538 T1 q, r;
00539
00540 ++d;
00541
00542 for(;;)
00543 {
00544 divide(x, d, q, r);
00545 if(is_null(r))
00546 {
00547 x = q;
00548 resbuf.push_back(d);
00549 }
00550 else break;
00551 }
00552
00553 d += 2;
00554
00555 unsigned s = 2;
00556 rest = x;
00557 while(!is_unit(x))
00558 {
00559 ARAGELI_ASSERT_1(x >= d);
00560
00561 if(max < d)
00562 {
00563 if (is_prime(x))
00564 {
00565 resbuf.push_back(x);
00566 rest = unit(rest);
00567 }
00568 else
00569 {
00570 rest = x;
00571 }
00572 res.assign(resbuf.size(), resbuf.begin());
00573
00574 ARAGELI_DEBUG_EXEC_2(T1 tt);
00575 ARAGELI_ASSERT_2(product(res, tt)*rest == xx);
00576
00577 return res;
00578 }
00579
00580 divide(x, d, q, r);
00581 if(is_null(r))
00582 {
00583 x = q;
00584 resbuf.push_back(d);
00585 }
00586 else if(q < d)
00587 {
00588 ARAGELI_ASSERT_1(is_prime(x));
00589 rest = 1;
00590 resbuf.push_back(x);
00591 break;
00592 }
00593 else
00594 {
00595
00596 d += s;
00597 if(s == 2)s = 4;
00598 else s = 2;
00599 }
00600 }
00601
00602 res.assign(resbuf.size(), resbuf.begin());
00603
00604 ARAGELI_DEBUG_EXEC_2(T1 tt);
00605 ARAGELI_ASSERT_2(product(res, tt)*rest == xx);
00606
00607 return res;
00608 }
00609
00610
00611 template <typename T1, typename T2, typename T3, typename T4>
00612 const T4& factorize_multiplier (T1 x, const T2& m, T3& remx, T4& nm)
00613 {
00614 ARAGELI_ASSERT_0(!is_null(m));
00615 ARAGELI_ASSERT_0(!is_unit(m));
00616 ARAGELI_ASSERT_0(!is_opposite_unit(m));
00617
00618 T1 q = x; T2 r;
00619 nm = null(nm);
00620
00621 for(;;)
00622 {
00623 remx = x;
00624 divide(remx, m, x, r);
00625 if(!is_null(r))break;
00626 ++nm;
00627 }
00628
00629 return nm;
00630 }
00631
00632
00633 template <typename T>
00634 T next_prime_successive_checking (T x)
00635 {
00636 for(++x; !is_prime(x); ++x);
00637 return x;
00638 }
00639
00640
00641 template <typename T>
00642 T prev_prime_successive_checking (T x)
00643 {
00644 ARAGELI_ASSERT_0(x > 2);
00645 for(--x; !is_prime(x); --x);
00646 return x;
00647 }
00648
00649 template <typename T>
00650 T next_probably_prime (T x)
00651 {
00652 for(++x; !is_probably_prime(x); ++x);
00653 return x;
00654 }
00655
00656
00657 template <typename T>
00658 T prev_probably_prime (T x)
00659 {
00660 ARAGELI_ASSERT_0(x > 2);
00661 for(--x; !is_probably_prime(x); --x);
00662 return x;
00663 }
00664
00665
00666 template<typename T, typename N>
00667 void rsa_generate_keys(N l, T& c, T& public_key, T& d)
00668 {
00669 T p = rand(l/2);
00670
00671 T q = rand(l/2);
00672 public_key = p * q;
00673
00674 T phi = (p-1)*(q-1);
00675
00676 for (c = 3; !is_unit(gcd(c, phi)); c = c + 2)
00677 ;
00678
00679 d = inverse_mod(c, phi);
00680 }
00681
00682 template<typename T>
00683 T rsa_encyph(const T& x, const T& c, const T& key)
00684 {
00685 return power_mod(x, c, key);
00686 }
00687
00688 template<typename T>
00689 T rsa_decyph(const T& y, const T& d, const T& key)
00690 {
00691 return power_mod(y, d, key);
00692 }
00693
00694
00695 template <typename T>
00696 T next_mersen_prime_degree (const T& n)
00697 {
00698 static const unsigned mersen_degrees[] =
00699 {
00700 2,3,5,7,13,17,19,31,61,89,107,127,521,607,1279,
00701 2203,2281,3217,4253,4423,9689,9941,11213,19937,
00702 21701,23209,44497,86243,110503,132049,216091,
00703 756839,859433,1257787,1398269,2976221,3021377,
00704 6972593,13466917
00705 };
00706
00707 const unsigned* res = std::upper_bound
00708 (
00709 &mersen_degrees[0],
00710 &mersen_degrees[sizeof(mersen_degrees)/sizeof(unsigned)],
00711 n
00712 );
00713
00714 if(res == &mersen_degrees[sizeof(mersen_degrees)/sizeof(unsigned)])
00715 throw invalid_argument();
00716
00717 return *res;
00718 }
00719
00720
00721
00722 }
00723
00724 #endif
00725