algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/crt_naive.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : crt_naive.hpp
00004 * DESCRIPTION: Naive implementations for Chinese remaindering
00005 * COPYRIGHT  : (C) 2009  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_NAIVE__HPP
00014 #define __MMX__CRT_NAIVE__HPP
00015 #include <basix/vector.hpp>
00016 #include <numerix/modulus.hpp>
00017 
00018 namespace mmx {
00019 
00020 /******************************************************************************
00021 * Sequence of coprime moduli
00022 ******************************************************************************/
00023 
00024 struct coprime_moduli_sequence_naive {
00025   template<typename M> static bool
00026   extend (vector<M>& v, nat i) { return false; }
00027 };
00028 
00029 template<typename M>
00030 struct coprime_moduli_helper {
00031   typedef coprime_moduli_sequence_naive sequence;
00032 };
00033 
00034 #define Coprime_moduli_variant(M) coprime_moduli_helper<M>::sequence
00035 
00036 template<typename M, typename V= typename Coprime_moduli_variant(M)>
00037 struct coprime_moduli_sequence {
00038   vector<M> v;
00039 
00040   coprime_moduli_sequence () : v () {}
00041   coprime_moduli_sequence (const coprime_moduli_sequence& x) : v (x.v) {}
00042 
00043   M operator [] (nat i) {
00044     if (i >= N(v)) {
00045       bool b= V::extend (v, i+1);
00046       if (!b) return M(0);
00047     }
00048     return v[i]; }
00049 };
00050 
00051 template<typename M, typename V> vector<M>
00052 range (coprime_moduli_sequence<M, V>& seq, nat beg, nat end) {
00053   if (end <= beg) return vector<M> (M (), 0);
00054   vector<M> v (M (), end - beg);
00055   for (nat i= beg; i < end; i++) {
00056     if (seq[i] == M(0)) return vector<M> ();
00057     v[i-beg]= seq[i];
00058   }
00059   return v;
00060 }
00061 
00062 /******************************************************************************
00063 * Covering in size s for type C with moduli of type M
00064 ******************************************************************************/
00065 
00066 template<typename C, typename M=modulus<C>,
00067          typename W= typename Coprime_moduli_variant(M)>
00068 struct moduli_helper {
00069   template<typename V> static bool
00070   covering (vector<M, V>& v, nat s) {
00071     static coprime_moduli_sequence<M,W> seq;
00072     v= vector<M,V> (M (0), s);
00073     for (nat i= 0; i < s; i++) {
00074       v[i]= seq[i];
00075       if (v[i] == 0) return false;
00076     }
00077     return true; }
00078 };
00079 
00080 /******************************************************************************
00081 * Standard parameters
00082 ******************************************************************************/
00083 
00084 template<typename C>
00085 struct std_crt_naive {
00086   typedef C                           base;
00087   typedef C                           modulus_base;
00088   typedef typename Modulus_variant(C) modulus_base_variant;
00089   typedef typename Modulus_variant(C) modulus_variant;
00090 };
00091 
00092 /******************************************************************************
00093 * Naive variant for Crt
00094 ******************************************************************************/
00095 
00096 #define Crt_naive_variant(C) crt_naive_variant_helper<C>::CV
00097 
00098 struct crt_naive {};
00099 
00100 template<typename C>
00101 struct crt_naive_variant_helper {
00102   typedef crt_naive CV;
00103 };
00104 
00105 /******************************************************************************
00106 * Projection and lifting
00107 ******************************************************************************/
00108 
00109 struct crt_project {};
00110 
00111 template<typename V>
00112 struct implementation<crt_project,V,crt_naive> {
00113 
00114   template<typename M> static inline typename M::base
00115   half (const M& P) {
00116     // return *P >> 1 for signed integer types
00117     return typename M::base (0); }
00118 
00119   template<typename C, typename M> static inline typename M::base
00120   encode (const C& a, const M& p) {
00121     (void) p;
00122     return as<typename M::base> (a); }
00123 
00124   template<typename C, typename M> static inline C
00125   decode (const C& a, const M& P, const C& H) {
00126     (void) P; (void) H;
00127     return a; }
00128 
00129   template<typename C, typename M> static inline typename M::base
00130   mod (const C& a, const M& p) {
00131     return as<typename M::base> (rem (a, *p)); }
00132 
00133 };
00134 
00135 /******************************************************************************
00136 * Basic operations for signed structures
00137 ******************************************************************************/
00138 
00139 template<typename V> struct crt_signed {};
00140 
00141 template<typename F, typename V, typename W>
00142 struct implementation<F,V,crt_signed<W> >:
00143     public implementation<F,V,W> {};
00144 
00145 template<typename V,typename W>
00146 struct implementation<crt_project,V,crt_signed<W> > :
00147     public implementation<crt_project,V,W> {
00148 
00149   template<typename M> static inline typename M::base 
00150   half (const M& P) {
00151     return *P >> 1; }
00152 
00153   template<typename C, typename M> static inline typename M::base
00154   encode (const C& a, const M& p) {
00155     typename M::base b;
00156     if (a < 0) {
00157       b= as<typename M::base> (-a); neg_mod (b, p);
00158     }
00159     else 
00160       b= as<typename M::base> (a);
00161     return b; }
00162 
00163   template<typename C, typename M> static inline C
00164   decode (const C& a, const M& P, const C& H) {
00165     return a > H ? a - *P : a; }
00166 
00167 };
00168 
00169 /******************************************************************************
00170 * Direct and inverse transforms
00171 ******************************************************************************/
00172 
00173 struct crt_transform {};
00174 
00175 template<typename V>
00176 struct implementation<crt_transform,V,crt_naive> :
00177     public implementation<crt_project,V> {
00178   typedef implementation<crt_project,V> Crt;
00179 
00180   template<typename C, typename M, typename I> static inline void
00181   direct (I* c, const C& a, const M* p, nat n) {
00182     for (nat i= 0; i < n; i++)
00183       c[i]= Crt::mod (a, p[i]); }
00184 
00185   template<typename C, typename I> static inline void
00186   combine (C& a, const I* c, const C* q, nat n) {
00187     a= 0;
00188     for (nat i= 0; i < n; i++)
00189       mul_add (a, c[i], q[i]); }
00190 
00191   template<typename C, typename M, typename I, typename K> static inline void
00192   inverse (C& a, const I* c, const M* p, const K& P,
00193            const C* q, const I* m, nat n) {
00194     a= 0; I t;
00195     for (nat i= 0; i < n; i++) {
00196       mul_mod (t, m[i], c[i], p[i]);
00197       mul_add (a, t, q[i]);
00198     }
00199     a= Crt::mod (a, P); }
00200 };
00201 
00202 /******************************************************************************
00203 * The naive CRT transformer class
00204 ******************************************************************************/
00205 
00206 template<typename C, typename S=std_crt_naive<C>,
00207          typename V=typename Crt_naive_variant(C) >
00208 struct crt_naive_transformer : public S {
00209 
00210   typedef typename S::modulus_base I;
00211   typedef modulus<I, typename S::modulus_base_variant> M;
00212   typedef modulus<C, typename S::modulus_variant> Modulus;
00213   typedef implementation<vector_linear, vector_naive> Vec;
00214   typedef implementation<crt_transform,V> Crt;
00215 
00216   nat n;             // number of the moduli
00217   nat l_p, l_m, l_q; // allocated sizes
00218   M* p;              // sequence of the moduli
00219   Modulus P;      // product of all the p[i]
00220   C H;        // half of P -- used for integers
00221   C* q;       // sequence of P / p[i]
00222   I* m;       // sequence of inverse (q[i]) mod p[i]
00223   bool product_done, comoduli_done, inverse_done;
00224 
00225   inline void setup_product () {
00226     if (product_done) return;
00227     q= mmx_formatted_new<C> (l_q, format<C> (/*FIXME*/));
00228     for (nat i= 0; i < n; i++) q[i]= * p[i];
00229     P= Vec::template vec_unary_big<mul_op> (q, n);
00230     product_done= true; }
00231   
00232   inline void setup_comoduli () {
00233     if (comoduli_done) return;
00234     setup_product ();
00235     for (nat i= 0; i < n; i++) q[i]= * P / * p[i];
00236     comoduli_done= true; }
00237 
00238   inline void setup_inverse () {
00239     if (inverse_done) return;
00240     setup_comoduli ();
00241     H= Crt::half (P);
00242     m= mmx_formatted_new<I> (l_m, format<I> (/*FIXME*/));
00243     for (nat i= 0; i < n; i++) {
00244       I a (1), b;
00245       for (nat j= 0; j < n; j++) {
00246         reduce_mod (b, * p[j], p[i]);
00247         if (j != i) mul_mod (a, b, p[i]);
00248       }
00249       inv_mod (m[i], a, p[i]);
00250       ASSERT (m[i] != 0, "moduli must be pairwise coprime"); }
00251     inverse_done= true; }
00252 
00253   template<typename NV,typename VV> 
00254   inline crt_naive_transformer (const vector<NV,VV>& v, bool lazy= true) 
00255     : n(N(v)) {
00256     l_p= default_aligned_size<M> (n);
00257     l_m= default_aligned_size<I> (n);
00258     l_q= default_aligned_size<C> (n);
00259     p= mmx_formatted_new<M> (l_p, format<M> (/*FIXME*/));
00260     for (nat i= 0; i < n; i++) p[i]= as<M> (v[i]);
00261     q= NULL; m= NULL; P= C(1);
00262     product_done= false; comoduli_done= false; inverse_done= false;
00263     if (! lazy) setup_inverse (); }
00264 
00265   inline ~crt_naive_transformer () {
00266     mmx_delete<M> (p, l_p);
00267     if (q != NULL) mmx_delete<C> (q, l_q);
00268     if (m != NULL) mmx_delete<I> (m, l_m); }
00269 
00270   inline M operator[] (nat i) const {
00271     VERIFY (i < n, "index out of range");
00272     return p[i]; }
00273 
00274   inline nat size () const {
00275     return n; }
00276 
00277   inline Modulus product () {
00278     setup_product (); return P; }
00279 
00280   inline C comodulus (nat i) {
00281     VERIFY (i < n, "index out of range");
00282     setup_comoduli (); return q[i]; }
00283     
00284   inline void direct_transform (I* c, const C& a) const {
00285     C b= Crt::encode (a, P);
00286     Crt::direct (c, b, p, n); }
00287 
00288   inline void combine (C& a, const I* c) {
00289     setup_comoduli ();
00290     Crt::combine (a, c, q, n); }
00291 
00292   inline void inverse_transform (C& a, const I* c) {
00293     setup_inverse ();
00294     Crt::inverse (a, c, p, P, q, m, n);
00295     a= Crt::decode (a, P, H); }
00296 };
00297 
00298 template<typename C, typename M, typename V> inline nat
00299 N (const crt_naive_transformer<C,M,V>& crter) {
00300   return crter.size (); 
00301 }
00302 
00303 /******************************************************************************
00304 * Higher interface level -- common to all transformers
00305 ******************************************************************************/
00306 
00307 #define C typename Crter::base
00308 #define I typename Crter::modulus_base
00309 #define M modulus<typename Crter::modulus_base,\
00310                   typename Crter::modulus_base_variant>
00311 #define Modulus modulus<C, typename Crter::modulus_variant>
00312 
00313 template<typename Crter> inline Modulus
00314 moduli_product (Crter& crter) {
00315   return crter.product (); }
00316 
00317 template<typename Crter> inline typename Crter::base
00318 comodulus (const Crter& crter, nat i) {
00319   return crter.comodulus (i);
00320 }
00321 
00322 template<typename Crter> inline void
00323 direct_crt (I* dest, const C& s, Crter& crter) {
00324   crter.direct_transform (dest, s);
00325 }
00326 
00327 template<typename Crter, typename W> inline void
00328 direct_crt (vector<I,W>& dest, const C& s, Crter& crter) {
00329   nat l= aligned_size<I,W> (N(crter));
00330   I* tmp= mmx_formatted_new<I> (l, CF(dest));
00331   crter.direct_transform (tmp, s);
00332   dest= vector<I,W> (tmp, N(crter), l, CF(dest));
00333 }
00334 
00335 template<typename Crter> inline vector<I>
00336 direct_crt (const C& s, Crter& crter) {
00337   vector<I> dest;
00338   direct_crt (dest, s, crter);
00339   return dest;
00340 }
00341 
00342 template<typename Crter> inline void
00343 combine_crt (C& d, const I* src, Crter& crter) {
00344   crter.combine (d, src);
00345 }
00346 
00347 template<typename Crter, typename W> inline void
00348 combine_crt (C& d, const vector<I,W>& src, Crter& crter) {
00349   crter.combine (d, seg (src));
00350 }
00351 
00352 template<typename Crter, typename W> inline C
00353 combine_crt (const vector<I,W>& src, Crter& crter) {
00354   C d; combine_crt (d, seg (src), crter);
00355   return d;
00356 }
00357 
00358 template<typename Crter> inline void
00359 inverse_crt (C& d, const I* src, Crter& crter) {
00360   crter.inverse_transform (d, src);
00361 }
00362 
00363 template<typename Crter, typename W> inline void
00364 inverse_crt (C& d, const vector<I,W>& src, Crter& crter) {
00365   crter.inverse_transform (d, seg (src));
00366 }
00367 
00368 template<typename Crter, typename W> inline C
00369 inverse_crt (const vector<I,W>& src, Crter& crter) {
00370   C d; inverse_crt (d, seg (src), crter);
00371   return d;
00372 }
00373 
00374 #undef C
00375 #undef I
00376 #undef M
00377 #undef Modulus
00378 } // namespace mmx
00379 #endif //__MMX__CRT_NAIVE__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines