00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _ARAGELI_intalg_hpp_
00020 #define _ARAGELI_intalg_hpp_
00021
00022 #include "config.hpp"
00023
00024 #include <cmath>
00025
00026 #include "exception.hpp"
00027 #include "type_traits.hpp"
00028 #include "factory.hpp"
00029 #include "cmp.hpp"
00030 #include "gcd.hpp"
00031 #include "powerest.hpp"
00032
00033 #include "std_import.hpp"
00034
00035
00036 namespace Arageli
00037 {
00038
00039
00041
00042 template <typename T, typename T_factory>
00043 inline T inverse_mod (const T& a, const T& m, const T_factory& tfctr)
00044 {
00045 ARAGELI_ASSERT_0(is_positive(a));
00046 ARAGELI_ASSERT_0(m >= 2);
00047
00048 T u, v;
00049 T r = euclid_bezout(a, m, u, v, tfctr);
00050 ARAGELI_ASSERT_0(is_unit(r));
00051 return is_negative(u) ? u + m : u;
00052 }
00053
00054
00056
00057 template <typename T>
00058 inline T inverse_mod (const T& a, const T& n)
00059 { return inverse_mod(a, n, factory<T>()); }
00060
00061
00063
00064 template <typename T, typename I, typename T_factory>
00065 T power_mod (T a, I n, const T& m, const T_factory& tfctr);
00066
00068
00069 template <typename T, typename I>
00070 inline T power_mod (const T& a, const I& n, const T& m)
00071 { return power_mod(a, n, m, factory<T>()); }
00072
00073
00074 namespace _Internal
00075 {
00076
00077
00078
00079
00080
00081
00082
00083
00084 template <typename T>
00085 T conditioner (const T& a, const T& b, const T& N);
00086
00087
00088
00089
00090 template <typename T, typename V>
00091 T conditioner (const T& _a, const T& _b, const T& N, V &d);
00092
00093 }
00094
00095
00096
00097
00098 template <typename T1, typename T2, typename T3>
00099 T3 mod (const T1& a, const T2& b, const T3& d)
00100 { return mod(a*div_mod(unit(a), b, d), d);}
00101
00102
00104 template <typename T1, typename T2>
00105 inline T2 mod (const T1& a, const T2& b)
00106 { return prrem(a, b); }
00107
00108
00110 template <typename T1, typename T2, typename T3>
00111 T3 div_mod (const T1& a, const T2& b, const T3& d);
00112
00113
00115
00116 template <typename T1, typename T2, typename T3>
00117 inline T3 rem_mod (const T1& a, const T2& b, const T3& d)
00118 { return prrem(a, gcd(b, d)); }
00119
00120
00122 template <typename T1, typename T2>
00123 inline T2 ann (const T1& a, const T2& n)
00124 { return n/gcd(a, n);}
00125
00126
00127
00128 template <typename T1, typename T2, typename T3>
00129 T3 quo_mod (const T1& a, const T2& b, const T3& d);
00130
00131
00132 template <typename T>
00133 T split (const T& a, const T& d);
00134
00135
00136
00137 template <typename T>
00138 T stab (const T& a, const T& b, const T& N);
00139
00140
00141
00142 template <typename T>
00143 T split_stab (const T& a, const T& b, const T& N);
00144
00145
00146
00147
00148 template <typename T>
00149 T unit (const T& a, const T& N);
00150
00151
00152
00153 template <typename T>
00154 inline T stab (const T& a, const T& b, const T& N, const T& d)
00155 { return stab(a, b, gcd(d, N)); }
00156
00157
00158
00159 template <typename T>
00160 inline T split_stab (const T& a, const T& b, const T& N, const T& d)
00161 { return split_stab(a, b, gcd(d, N)); }
00162
00163
00164
00165 template <typename T>
00166 T split_mod (const T& a, const T& d);
00167
00168
00169
00170 template <typename T>
00171 T stab_mod (const T& a, const T& b, const T& N);
00172
00173
00174
00175 template <typename T>
00176 inline T stab_mod (const T& a, const T& b, const T& N, const T& d)
00177 { return stab_mod(a, b, gcd(d, N)); }
00178
00179
00181 template<typename T>
00182 bool is_invertible_mod (const T& a, const T& N);
00183
00184
00186 template <typename T>
00187 inline std::size_t nbits (const T& a)
00188 { return nbits(a, factory<T>()); }
00189
00190
00192 template <typename T, typename T_factory>
00193 std::size_t nbits(T a, const T_factory& tfctr);
00194
00195
00197
00198 template <typename T, typename T_factory>
00199 T factorial_successive_multiplication (T a, const T_factory& tfctr);
00200
00202 template <typename T>
00203 inline T factorial_successive_multiplication (const T& a)
00204 { return factorial_successive_multiplication(a, factory<T>()); }
00205
00206
00208 template <typename T, typename T_factory>
00209 T factorial_even_odd_multiplication (T a, const T_factory& tfctr);
00210
00212 template <typename T>
00213 inline T factorial_even_odd_multiplication (const T& a)
00214 { return factorial_even_odd_multiplication(a, factory<T>()); }
00215
00216
00218 template <typename T, typename T_factory>
00219 inline T factorial (const T& a, const T_factory& tfctr)
00220 { return factorial_even_odd_multiplication(a, tfctr); }
00221
00223 template <typename T>
00224 inline T factorial (const T& a)
00225 { return factorial(a, factory<T>()); }
00226
00227
00228
00230
00232
00234
00235 template <typename T, typename T_factory>
00236 int jacobi (T a, T n, const T_factory& tfctr);
00237
00238
00240
00241 template <typename T>
00242 inline int jacobi (const T& a, const T& n)
00243 { return jacobi(a, n, factory<T>()); }
00244
00245
00247
00249
00251 template <typename T>
00252 T intsqrt (const T& a);
00253
00255
00257 template <typename T, typename TT>
00258 T sqrt_mod_shenks (const T& a, const T& n, const TT& tt);
00259
00260
00262
00264 template <typename T>
00265 inline T sqrt_mod_shenks (const T& a, const T& n)
00266 { return sqrt_mod_shenks(a, n, type_traits<T>()); }
00267
00268
00270
00273
00274
00275
00276
00277
00280
00281
00282
00283
00284
00287
00288
00289
00290
00291
00292
00295
00296
00297
00298
00299
00302
00303
00304
00305
00306
00308
00309 }
00310
00311
00312 namespace std
00313 {
00314
00315
00317
00319
00320 inline char sqrt (char a) { return Arageli::intsqrt(a); }
00321 inline unsigned char sqrt (unsigned char a) { return Arageli::intsqrt(a); }
00322 inline signed char sqrt (signed char a) { return Arageli::intsqrt(a); }
00323 inline unsigned short sqrt (unsigned short a) { return Arageli::intsqrt(a); }
00324 inline signed short sqrt (signed short a) { return Arageli::intsqrt(a); }
00325 inline unsigned int sqrt (unsigned int a) { return Arageli::intsqrt(a); }
00326 inline signed int sqrt (signed int a) { return Arageli::intsqrt(a); }
00327 inline unsigned long sqrt (unsigned long a) { return Arageli::intsqrt(a); }
00328 inline signed long sqrt (signed long a) { return Arageli::intsqrt(a); }
00329
00330 #ifdef ARAGELI_INT64_SUPPORT
00331 inline unsigned __int64 sqrt (unsigned __int64 a) { return Arageli::intsqrt(a); }
00332 inline signed __int64 sqrt (signed __int64 a) { return Arageli::intsqrt(a); }
00333 #endif
00334
00335 #ifdef ARAGELI_LONG_LONG_SUPPORT
00336 inline unsigned long long sqrt (unsigned long long a) { return Arageli::intsqrt(a); }
00337 inline signed long long sqrt (signed long long a) { return Arageli::intsqrt(a); }
00338 #endif
00339
00341
00342
00343 }
00344
00345
00346 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00347 #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTALG
00348 #include "intalg.cpp"
00349 #undef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTALG
00350 #endif
00351
00352
00353 #endif // #ifndef _ARAGELI_intalg_hpp_