00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.hpp"
00020
00021 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00022 defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTALG)
00023
00024 #include "intalg.hpp"
00025 #include "powerest.hpp"
00026 #include "vector.hpp"
00027
00028
00029 namespace Arageli
00030 {
00031
00032
00033 template <typename T, typename T_factory>
00034 std::size_t nbits (T a, const T_factory& tfctr)
00035 {
00036 std::size_t res = tfctr.null(a);
00037 std::size_t n = a;
00038 while(n)
00039 {
00040 ++res;
00041 n >>= 1;
00042 }
00043 return res;
00044 }
00045
00046
00047 template <typename T, typename I, typename T_factory>
00048 T power_mod (T a, I n, const T& m, const T_factory& tfctr)
00049 {
00050 ARAGELI_ASSERT_0(!is_null(a) || is_positive(n));
00051
00052 T res = tfctr.unit(a);
00053 while(!is_null(n))
00054 {
00055 if(is_odd(n))(res *= a) %= m;
00056 (a *= a) %= m;
00057 n >>= 1;
00058 }
00059
00060 return res;
00061 }
00062
00063
00064 namespace _Internal
00065 {
00066
00067 template <typename T, typename V>
00068 T conditioner (const T& _a, const T& _b, const T& N, V &d)
00069 {
00070 typedef unsigned long index;
00071
00072 typename V::template other_element_type<T>::type a(d.size()), b(d.size());
00073 index t, K = 2*std::pow(nbits(N), 1.5);
00074 typename V::template other_element_type<bool>::type B(K + 1, true);
00075
00076 for(std::size_t i = 0; i < d.size(); i ++)
00077 {
00078 a[i] = prrem(_a, d[i]);
00079 b[i] = prrem(_b, d[i]);
00080 T gi = gcd(b[i], d[i]);
00081
00082 if(gi > unit<T>() && gi < d[i])
00083 { d[i] /= gi;
00084 d.insert(d.begin() + i, gi);
00085 return opposite_unit<T>();
00086 }
00087 }
00088
00089 for(std::size_t i = 0; i < d.size(); i ++)if(!is_null(b[i]))
00090 {
00091 T si = mod(-a[i], b[i], d[i]);
00092 if(K < si) continue;
00093 index M = index(si);
00094
00095 for(;;)
00096 {
00097 B[M] = false;
00098 if(M + d[i] > K) break;
00099 M += index(d[i]);
00100 }
00101 }
00102
00103 for(t = 0; t < B.size(); t++)if(B[t])break;
00104
00105 for(std::size_t i = 0; i < d.size(); i ++)
00106 {
00107 T gi = gcd(a[i] + t*b[i], d[i]);
00108
00109 if(gi > unit<T>())
00110 {
00111 d[i] /= gi;
00112 d.insert(d.begin() + i, gi);
00113 return opposite_unit<T>();
00114 }
00115 }
00116
00117 return t;
00118 }
00119
00120
00121 template <typename T>
00122 T conditioner (const T& a, const T& b, const T& N)
00123 {
00124 ARAGELI_ASSERT_0(is_unit(gcd(a, b)));
00125 ARAGELI_ASSERT_0(is_positive(N));
00126
00127 vector<T> d(1, N);
00128 T c;
00129
00130 do
00131 {
00132 c = conditioner(a, b, N, d);
00133 }while(is_opposite_unit(c));
00134
00135 ARAGELI_ASSERT_1(is_unit(gcd3(a, b, N) == gcd(a + c*b, N)));
00136
00137 return c;
00138 }
00139
00140
00141 }
00142
00143
00144 template <typename T1, typename T2, typename T3>
00145 T3 div_mod (const T1& a, const T2& b, const T3& d)
00146 {
00147
00148 T3 u, v, g = euclid_bezout(b, d, u, v);
00149 return mod(u*a/g, d);
00150 }
00151
00152
00153 template <typename T1, typename T2, typename T3>
00154 T3 quo_mod (const T1& a, const T2& b, const T3& d)
00155 {
00156 T3 r = rem_mod(a, b, d);
00157 T3 c = div_mod(a - r, b, d);
00158 return mod(c, d);
00159 }
00160
00161
00162 template <typename T>
00163 T split (const T& a, const T& d)
00164 {
00165 T x = a, t = d;
00166
00167 while(!is_unit(x))
00168 {
00169 x = gcd(x, t);
00170 t /= x;
00171 }
00172
00173 return t;
00174 }
00175
00176
00177 template <typename T>
00178 T stab (const T& A, const T& B, const T& N)
00179 {
00180 ARAGELI_ASSERT_0(is_positive(N));
00181
00182 if(is_null(B))return null(A);
00183 if(is_null(A))return unit(A);
00184
00185 T c,
00186 g1 = gcd3(A, B, N),
00187 g2 = gcd(A/g1, B/g1),
00188 a = A/(g1*g2),
00189 b = B/(g1*g2),
00190 d = N/g1;
00191
00192 if(is_unit(gcd(a, d)))
00193 return null(A);
00194 if(is_unit(gcd(a + b, d)))
00195 return unit(A);
00196
00197 c = _Internal::conditioner(a, b, d);
00198
00199 ARAGELI_ASSERT_1(gcd3(A, B, N) == gcd(A + c*B, N));
00200
00201 return c;
00202 }
00203
00204
00205 template <typename T>
00206 T unit (const T& a, const T& N)
00207 {
00208 ARAGELI_ASSERT_0(is_positive(N));
00209
00210 T u, v, w, z,
00211 g = gcdex(a, N, u, v, w, z),
00212 c = mod(u + stab(u, w, N)*w, N);
00213
00214 ARAGELI_ASSERT_1(is_unit(gcd(c, N)));
00215
00216
00217 ARAGELI_ASSERT_1(mod(c*a, N) == mod(gcd(a, N), N));
00218
00219 return c;
00220 }
00221
00222
00223 template <typename T>
00224 T split_stab (const T& A, const T& B, const T& N)
00225 {
00226 ARAGELI_ASSERT_0(is_positive(N));
00227
00228 if(is_null(B))return null(A);
00229 if(is_null(A))return unit(A);
00230
00231 T c,
00232 g1 = gcd(A, B, N),
00233 g2 = gcd(A/g1, B/g1),
00234 a = A/(g1*g2),
00235 b = B/(g1*g2),
00236 d = N/g1;
00237
00238 if(is_unit(gcd(a, d)))
00239 return null(A);
00240 if(is_unit(gcd(a + b, d)))
00241 return unit(A);
00242
00243 c = split(a, d);
00244
00245 ARAGELI_ASSERT_1(gcd3(A, B, N) == gcd(A + c*B, N));
00246
00247 return c;
00248 }
00249
00250
00251 template <typename T>
00252 T split_mod (const T& a, const T& d)
00253 {
00254
00255
00256 std::size_t N = nbits(nbits(a));
00257 T x = a;
00258 for(std::size_t i = 0; i <= N + 1; i++)
00259 x = mod(x*x, d);
00260 return d/gcd(x, d);
00261 }
00262
00263
00264 template <typename T>
00265 T stab_mod (const T& a, const T& b, const T& N)
00266 {
00267 ARAGELI_ASSERT_0(is_positive(N));
00268
00269 if(is_null(b)) return null<T>();
00270 if(is_null(a)) return unit<T>();
00271 T g = gcd3(a, b, N),
00272 c = split_mod(a/g, N/g);
00273
00274 ARAGELI_ASSERT_1(gcd3(a, b, N) == gcd(a + c*b, N));
00275
00276 return c;
00277 }
00278
00279
00280 template<typename T>
00281 bool is_invertible_mod (const T& a, const T& N)
00282 { return is_unit(gcd(mod(a, N), N)); }
00283
00284
00285 template <typename T, typename T_factory>
00286 T factorial_successive_multiplication (T a, const T_factory& tfctr)
00287 {
00288 ARAGELI_ASSERT_0(sign(a, tfctr) >= 0);
00289
00290 if(is_null(a) || is_unit(a))return tfctr.unit(a);
00291 T res = a;
00292
00293 for(--a; !is_unit(a); --a)
00294 res *= a;
00295
00296
00297
00298
00299
00300 return res;
00301 }
00302
00303
00304 template <typename T, typename T_factory>
00305 T factorial_even_odd_multiplication (T a, const T_factory& tfctr)
00306 {
00307
00308
00309 ARAGELI_ASSERT_0(sign(a) >= 0);
00310
00311 if(is_null(a) || is_unit(a))return tfctr.unit(a);
00312 T unit = tfctr.unit(a), two = unit; ++two;
00313 if(a == two)return two;
00314
00315 T res = unit;
00316 T n2q, n2r, n4q, n4r;
00317 divide(a - unit, two, n2q, n2r);
00318 divide(n2q - unit, two, n4q, n4r);
00319
00320 if(!is_null(n2r))res *= a;
00321 if(!is_null(n4r))res *= n2q;
00322
00323 res *= factorial_even_odd_multiplication(n4q, tfctr);
00324
00325 T t = unit;
00326 T iend = (n4q << 1u) + unit;
00327 T i = (n2q << 1u) + unit;
00328 for(; i != iend; ----i)
00329 t *= i;
00330
00331 T t1 = unit;
00332 for(; !is_unit(i); ----i)
00333 t1 *= i;
00334
00335 return (res*t)*(t1*t1) << (n2q + n4q);
00336 }
00337
00338
00339 template <typename T, typename T_factory>
00340 int jacobi (T n, T p, const T_factory& tfctr)
00341 {
00342 ARAGELI_ASSERT_0(is_positive(p));
00343 ARAGELI_ASSERT_0(is_odd(p));
00344
00346
00347 T g;
00348 T a = n;
00349 T b = p;
00350
00351
00352 if (a >= b) a = a%b;
00353 if (a == 0) return 0;
00354 if (a == 1) return 1;
00355
00356 if (a < 0)
00357 if ((b-1)/2 % 2 == 0)
00358 return jacobi(-a,b);
00359 else
00360 return -jacobi(-a,b);
00361
00362 if (a % 2 == 0)
00363 if (((b*b - 1)/8) % 2 == 0)
00364 return +jacobi(a/2,b);
00365 else
00366 return -jacobi(a/2,b);
00367
00368 g = gcd(a, b);
00369
00370
00371 if (g == a)return 0;
00372 else
00373 if (g != 1)
00374 return jacobi(g,b)*jacobi(a/g,b);
00375 else
00376 if (((a-1)*(b-1)/4) % 2 == 0)
00377 return +jacobi(b,a);
00378 else
00379 return -jacobi(b,a);
00380
00381
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 }
00421
00422
00423 template <typename T>
00424 T intsqrt (const T& a)
00425 {
00426 ARAGELI_ASSERT_1(sign(a) >= 0);
00427 if(is_null(a) || is_unit(a))return a;
00428
00429 T r = a >> 1;
00430 T q;
00431 for(;;)
00432 {
00433 q = a / r;
00434 if(q >= r)break;
00435 else r = (r + q) >> 1;
00436 }
00437
00438 ARAGELI_ASSERT_1(r*r <= a && (r+1)*(r+1) > a);
00439 return r;
00440 }
00441
00442
00443 template <typename T, typename TT>
00444 T sqrt_mod_shenks (const T& a, const T& n, const TT& tt)
00445 {
00446 ARAGELI_ASSERT_0(is_positive(a));
00447 ARAGELI_ASSERT_0(is_positive(n));
00448 ARAGELI_ASSERT_0(a < n);
00449 ARAGELI_ASSERT_0(is_prime(n));
00450 ARAGELI_ASSERT_0(jacobi(a, n) == 1);
00451 ARAGELI_ASSERT_0(is_unit(n%4));
00452
00454
00455
00456 T b, j, r;
00457 T p = 2;
00458 for(;jacobi(p, n)>-1;p+=1);
00459 T temp = (n-1)/2;
00460 unsigned alpha = 1;
00461 while (!(temp % 2))
00462 {
00463 temp = temp /2;
00464 ++alpha;
00465 }
00466 T s = temp;
00467 r = power_mod(a, (s+1)/2, n);
00468 b = power_mod(p, s, n);
00469
00470 T inva = inverse_mod(a, n);
00471 T temp1 = (r*r*inva) % n;
00472 j = "0";
00473 const T two = "2";
00474 T t1 = power(two, alpha - two);
00475 if (is_null(power_mod(temp1, t1, n) - n-1)) j=1;
00476 int i;
00477 T t2;
00478 for (i = 1; i <= alpha - 2; ++i)
00479 {
00480 j*=2;
00481 t2 = power(two, alpha-i-two);
00482 if (is_null(power_mod(r*r*inva*b*b, t2, n) - n-1))
00483 {
00484 j++;
00485 }
00486 }
00487 return power(b,j)*r%n;
00488 }
00489
00490
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00516
00517
00518 }
00519
00520 #endif
00521