00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX_CRT_INT_HPP
00014 #define __MMX_CRT_INT_HPP
00015 #include <numerix/integer.hpp>
00016 #include <numerix/modular_int.hpp>
00017 #include <algebramix/crt_naive.hpp>
00018
00019 namespace mmx {
00020
00021
00022
00023
00024
00025 DEFINE_VARIANT(crt_int,crt_signed<crt_naive>)
00026 DEFINE_VARIANT(crt_unsigned_int,crt_naive)
00027
00028 #define DECLARE_HELPER(C) \
00029 STMPL struct crt_naive_variant_helper<C> { \
00030 typedef crt_int CV; };
00031 DECLARE_HELPER (signed char)
00032 DECLARE_HELPER (short int)
00033 DECLARE_HELPER (int)
00034 DECLARE_HELPER (long int)
00035 DECLARE_HELPER (long long int)
00036 #undef DECLARE_HELPER
00037
00038 #define DECLARE_HELPER(C) \
00039 STMPL struct crt_naive_variant_helper<C> { \
00040 typedef crt_unsigned_int CV; };
00041 DECLARE_HELPER (unsigned char)
00042 DECLARE_HELPER (unsigned short int)
00043 DECLARE_HELPER (unsigned int)
00044 DECLARE_HELPER (unsigned long int)
00045 DECLARE_HELPER (unsigned long long int)
00046 #undef DECLARE_HELPER
00047
00048
00049
00050
00051
00052 template<typename V>
00053 struct implementation<crt_transform,V,crt_int> :
00054 public implementation<crt_project,V> {
00055 typedef implementation<crt_project,V> Crt;
00056
00057 template<typename C, typename M, typename I> static inline void
00058 direct (I* c, const C& a, const M* p, nat n) {
00059 for (nat i= 0; i < n; i++)
00060 c[i]= Crt::mod (a, p[i]); }
00061
00062 template<typename C, typename M, typename I, typename K> static inline void
00063 inverse (C& a, const I* c, const M* p, const K& P,
00064 const C* q, const I* m, nat n) {
00065 a= 0; I t;
00066 for (nat i= 0; i < n; i++) {
00067 mul_mod (t, m[i], c[i], p[i]);
00068 add_mod (a, t * q[i], P); } }
00069 };
00070
00071 template<typename V>
00072 struct implementation<crt_transform,V,crt_unsigned_int> :
00073 public implementation<crt_transform,V,crt_int> {};
00074
00075
00076
00077
00078
00079 #define TMPL template<typename M>
00080
00081 struct prime_sequence_int {
00082 private:
00083 TMPL static inline bool
00084 is_prime (const vector<M>& v, nat n) {
00085 for (nat i= 0; true; i++) {
00086 nat p= (nat) *v[i];
00087 if (n % p == 0) return false;
00088 if (p * p >= n) break;
00089 }
00090 return true; }
00091
00092 public:
00093 TMPL static bool
00094 extend (vector<M>& v, nat i) {
00095 if (N(v) == 0) v= vec (M(2), M(3));
00096 nat p= *(v[N(v) - 1]) + 2;
00097 while (N(v) < i) {
00098 if (is_prime (v, p)) v << M(p);
00099 p += 2;
00100 }
00101 return true; }
00102 };
00103
00104 #define DECLARE_HELPER(I) \
00105 template<typename V> \
00106 struct coprime_moduli_helper<modulus<I, V> > { \
00107 typedef prime_sequence_int sequence; \
00108 };
00109 DECLARE_HELPER (signed char)
00110 DECLARE_HELPER (unsigned char)
00111 DECLARE_HELPER (short int)
00112 DECLARE_HELPER (unsigned short int)
00113 DECLARE_HELPER (int)
00114 DECLARE_HELPER (unsigned int)
00115 DECLARE_HELPER (long int)
00116 DECLARE_HELPER (unsigned long int)
00117 DECLARE_HELPER (long long int)
00118 DECLARE_HELPER (unsigned long long int)
00119 #undef DECLARE_HELPER
00120
00121
00122
00123
00124
00125 template<typename C, typename M, typename W>
00126 struct moduli_unsigned_integer_helper {
00127
00128 template<typename V> static bool
00129 covering (vector<M, V>& v, nat s) {
00130 static coprime_moduli_sequence<M,W> seq;
00131 v= vector<M, V> ();
00132 C p (1), q; nat i= 0;
00133 while (bit_size (p) < s + 1) {
00134 if (seq [i] == 0) return false;
00135 v << seq [i];
00136 q = p * C (* seq [i]);
00137 if (quo (q, p) != C (* seq [i])) return false;
00138 p = q;
00139 i++;
00140 }
00141 return true; }
00142 };
00143
00144 template<typename C, typename M, typename W>
00145 struct moduli_signed_integer_helper {
00146
00147 template<typename V> static bool
00148 covering (vector<M, V>& v, nat s) {
00149 static coprime_moduli_sequence<M,W> seq;
00150 v= vector<M, V> ();
00151 C p (1), q; nat i= 0;
00152 while (bit_size (p) < s + 2) {
00153 if (seq [i] == 0) return false;
00154 v << seq [i];
00155 q = p * C (* (seq [i]));
00156 if (quo (q, p) != C (* seq [i])) return false;
00157 p = q;
00158 i++;
00159 }
00160 return true; }
00161 };
00162
00163 #define DECLARE_HELPER(C) \
00164 template<typename M, typename W> \
00165 struct moduli_helper<C,M,W> : moduli_signed_integer_helper<C,M,W> {};
00166 DECLARE_HELPER (signed char)
00167 DECLARE_HELPER (short int)
00168 DECLARE_HELPER (int)
00169 DECLARE_HELPER (long int)
00170 DECLARE_HELPER (long long int)
00171 #undef DECLARE_HELPER
00172
00173 #define DECLARE_HELPER(C) \
00174 template<typename M, typename W> \
00175 struct moduli_helper<C,M,W> : moduli_unsigned_integer_helper<C,M,W> {};
00176 DECLARE_HELPER (unsigned char)
00177 DECLARE_HELPER (unsigned short int)
00178 DECLARE_HELPER (unsigned int)
00179 DECLARE_HELPER (unsigned long int)
00180 DECLARE_HELPER (unsigned long long int)
00181 #undef DECLARE_HELPER
00182
00183
00184
00185
00186
00187 bool is_prime (nat n);
00188 bool is_probable_prime (unsigned long int n);
00189
00190
00191
00192
00193
00194 template <nat s>
00195 struct fft_prime_sequence_int {
00196
00197
00198 private:
00199 static nat
00200 bit_reverse (nat i, nat n) {
00201 if (n <= 1) return i;
00202 nat n2= n >> 1;
00203 nat n1= n - n2;
00204 return (bit_reverse (i & ((1 << n2) - 1), n2) << n1) +
00205 bit_reverse (i >> n2, n1);
00206 }
00207 public:
00208 template<typename C, typename V> static bool
00209 extend (vector<modulus<C,V> >& v, nat n) {
00210
00211
00212
00213 typedef modulus<C,V> M;
00214 const nat b= V::template maximum_size_helper<C>::value;
00215 ASSERT (s <= b, "bitsize overflow");
00216 ASSERT (b <= 8 * sizeof (nat), "bitsize overflow");
00217 if (s < 2 && n > 0) return false;
00218 const C m= 1 + MMX_SAFE_LEFT_SHIFT_INT (C, 1, (s-1));
00219 const C l= MMX_SAFE_LEFT_SHIFT_INT (C, 1, s);
00220 for (nat i= N(v); i < n; i++) {
00221 C j= i == 0 ? m : (bit_reverse (* v[i-1], s) + 2), k;
00222 for (; j <= l - 1 && j >= m; j += 2)
00223 if (is_prime (k= bit_reverse (j, s))) break;
00224 if (j > l - 1 || j < m) return false;
00225 v << M(k); }
00226 return true; }
00227 };
00228
00229
00230
00231
00232
00233 template <nat s>
00234 struct probable_prime_sequence_int {
00235
00236
00237 template<typename C, typename V> static bool
00238 extend (vector<modulus<C,V> >& v, nat n) {
00239
00240 typedef modulus<C,V> M;
00241 const nat b= V::template maximum_size_helper<C>::value;
00242 ASSERT (s <= b, "bitsize overflow");
00243 if (s < 2 && n > 0) return false;
00244 integer a (N(v) == 0 ? (integer (1) << (s-1)) : integer (* v[N(v)-1]));
00245 integer p= probable_next_prime (a);
00246 if (bit_size (p) > b) return false;
00247 v << M(as <C> (p));
00248 return true; }
00249 };
00250
00251 #undef TMPL
00252 }
00253 #endif // __MMX_CRT_INT_HPP