00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX_CRT_INTEGER_HPP
00014 #define __MMX_CRT_INTEGER_HPP
00015 #include <numerix/modular_integer.hpp>
00016 #include <algebramix/crt_naive.hpp>
00017 #include <algebramix/crt_dicho.hpp>
00018 #include <algebramix/crt_blocks.hpp>
00019 #include <algebramix/crt_int.hpp>
00020
00021 namespace mmx {
00022
00023
00024
00025
00026
00027 DEFINE_VARIANT(crt_naive_integer,crt_signed<crt_naive>)
00028
00029 #if defined(__GNU_MP__)
00030 template<typename V>
00031 struct implementation<crt_project,V,crt_naive_integer> :
00032 public implementation<crt_project,crt_signed<crt_naive> >
00033 {
00034 template<typename C, typename I, typename W> static inline I
00035 mod (const C& a, const modulus<I,W>& p) {
00036 static integer r;
00037 return (I) mpz_fdiv_r_ui (*r, *a, *p); }
00038
00039 template<typename C, typename W> static inline C
00040 mod (const C& a, const modulus<integer,W>& p) {
00041 return rem (a, *p); }
00042 };
00043 #endif
00044
00045 STMPL
00046 struct crt_naive_variant_helper<integer> {
00047 typedef crt_naive_integer CV; };
00048
00049 DEFINE_VARIANT(crt_dicho_integer,crt_dicho<crt_naive_integer>)
00050
00051 STMPL
00052 struct crt_dicho_variant_helper<integer> {
00053 typedef crt_dicho_integer CV; };
00054
00055
00056
00057
00058
00059 STMPL
00060 struct std_crt_naive<integer> {
00061 typedef integer base;
00062 typedef int modulus_base;
00063 typedef modulus_int_preinverse<8*sizeof(int)-9> modulus_base_variant;
00064 typedef Modulus_variant(integer) modulus_variant;
00065 };
00066
00067 STMPL
00068 struct std_crt_dicho<integer> {
00069 typedef integer base;
00070 typedef integer modulus_base;
00071 typedef Modulus_variant(integer) modulus_base_variant;
00072 typedef Modulus_variant(integer) modulus_variant;
00073 };
00074
00075
00076
00077
00078
00079 template<typename M, typename W>
00080 struct moduli_helper<integer,M,W> :
00081 moduli_signed_integer_helper<integer,M,W> {};
00082
00083 template <typename M, nat t>
00084 struct moduli_helper<integer, M, fft_prime_sequence_int<t> > {
00085 template<typename V> static bool
00086 covering (vector<M, V>& v, nat s) {
00087 static coprime_moduli_sequence<M, fft_prime_sequence_int<t> > seq;
00088 if (t < 2) {
00089 v= vector<M, V> ();
00090 return s == 0;
00091 }
00092 nat n= (s + t) / (t - 1);
00093 v= range (seq, 0, n);
00094 return N(v) == n; }
00095 };
00096
00097
00098
00099
00100
00101 #if defined(__GNU_MP__)
00102 #define C integer
00103
00104 vector<mp_limb_t> mpz_setup_crt (const vector<mp_limb_t>& mods);
00105
00106
00107 integer mpz_moduli_product (const vector<mp_limb_t>& mods,
00108 const vector<mp_limb_t>& cv);
00109
00110
00111 void mpz_encode_crt (mp_limb_t* dest, const integer& src,
00112 const vector<mp_limb_t>& mods,
00113 const vector<mp_limb_t>& cv);
00114
00115
00116 integer mpz_decode_crt (const mp_limb_t* src,
00117 const vector<mp_limb_t>& mods,
00118 const vector<mp_limb_t>& cv);
00119
00120
00121 template<typename I>
00122 struct crt_gmp_transformer {
00123 typedef C base;
00124 typedef int modulus_base;
00125 typedef modulus_int_preinverse<23> modulus_base_variant;
00126 typedef typename Modulus_variant(C) modulus_variant;
00127 private:
00128 typedef modulus<modulus_base,modulus_base_variant> M;
00129
00130 nat n;
00131 vector<mp_limb_t> mods;
00132 vector<mp_limb_t> cv;
00133 modulus<C> P;
00134 mp_limb_t* aux;
00135
00136 public:
00137 inline void setup_inverse () {}
00138
00139 inline crt_gmp_transformer (const vector<M>& p, bool lazy=true) {
00140 (void) lazy;
00141 ASSERT (sizeof (I) <= sizeof (mp_limb_t), "moduli too large");
00142 n= N(p); mods= vector<mp_limb_t> ((mp_limb_t) 0, n);
00143 for (nat i= 0; i < n; i++) mods[i]= (mp_limb_t) * p[i];
00144 cv= mpz_setup_crt (mods);
00145 P= mpz_moduli_product (mods, cv);
00146 if (sizeof (I) != sizeof (mp_limb_t))
00147 aux= mmx_new<mp_limb_t> (n); }
00148
00149 inline ~crt_gmp_transformer () {
00150 if (sizeof (I) != sizeof (mp_limb_t))
00151 mmx_delete<mp_limb_t> (aux, n); }
00152
00153 inline M operator[] (nat i) const {
00154 VERIFY (i < n, "index out of range");
00155 return M (mods[i]); }
00156
00157 inline nat size () const {
00158 return n; }
00159
00160 inline modulus<C> product () const {
00161 return P; }
00162
00163 inline C comodulus (nat i) {
00164 VERIFY (i < n, "index out of range");
00165 return (* P) / mods[i]; }
00166
00167 inline void direct_transform (I* c, const C& a) const {
00168 mp_limb_t* tmp= sizeof (I) == sizeof (mp_limb_t) ?
00169 (mp_limb_t*) (void*) c : aux;
00170 mpz_encode_crt (tmp, a, mods, cv);
00171 if (sizeof (I) != sizeof (mp_limb_t))
00172 for (nat i= 0; i < n; i++) c[i]= (I) tmp[i]; }
00173
00174 inline void inverse_transform (C& a, const I* c) {
00175 mp_limb_t* tmp;
00176 if (sizeof (I) == sizeof (mp_limb_t))
00177 tmp= (mp_limb_t*) (void*) c;
00178 else {
00179 for (nat i= 0; i < n; i++) aux[i]= (mp_limb_t) c[i];
00180 tmp= aux;
00181 }
00182 a= mpz_decode_crt (tmp, mods, cv); }
00183 };
00184
00185 template<typename I> inline nat
00186 N (const crt_gmp_transformer<I>& crter) {
00187 return crter.size ();
00188 }
00189
00190 #undef C
00191 #endif // __GNU_MP__
00192
00193 }
00194 #endif // __MMX_CRT_INTEGER_HPP