algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/crt_integer.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : crt_integer.hpp
00004 * DESCRIPTION: Subroutines for efficient Chinese remaindering
00005 * COPYRIGHT  : (C) 2008  Joris van der Hoeven and Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 * Naive variant
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 * Default parameters
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 * Covering
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 * Special variant for GMP
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 // Build auxiliary conversion information for the moduli p[i]
00106 
00107 integer mpz_moduli_product (const vector<mp_limb_t>& mods, 
00108                             const vector<mp_limb_t>& cv);
00109 // Product of all the moduli
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 // Compute src mod p[i] for each of the moduli p[i]
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 // Reconstruct the integer from its remainders w.r.t. p[i] for each i
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 } // namespace mmx
00194 #endif // __MMX_CRT_INTEGER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines