algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/crt_dicho.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : crt_dicho.hpp
00004 * DESCRIPTION: Multimod and Chinese remaindering with dichotomic algorithms
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_DICHO__HPP
00014 #define __MMX__CRT_DICHO__HPP
00015 #include <algebramix/crt_naive.hpp>
00016 
00017 namespace mmx {
00018 
00019 /******************************************************************************
00020 * Standard parameters
00021 ******************************************************************************/
00022 
00023 template<typename C>
00024 struct std_crt_dicho : std_crt_naive<C> {};
00025 
00026 /******************************************************************************
00027 * Variant
00028 ******************************************************************************/
00029 
00030 #define Crt_dicho_variant(C) crt_dicho_variant_helper<C>::CV
00031 
00032 template<typename V>
00033 struct crt_dicho: public V {};
00034     
00035 template<typename F, typename V, typename W>
00036 struct implementation<F,V,crt_dicho<W> >:
00037   public implementation<F,V,W> {};
00038 
00039 template<typename C>
00040 struct crt_dicho_variant_helper {
00041   typedef crt_dicho<typename crt_naive_variant_helper<C>::CV> CV;
00042 };
00043 
00044 /******************************************************************************
00045 * Dichotomic CRT implementations
00046 ******************************************************************************/
00047 
00048 template<typename V,typename W>
00049 struct implementation<crt_transform,V,crt_dicho<W> > :
00050     public implementation<crt_project,V> {
00051   typedef implementation<crt_project,V> Crt;
00052 
00053   template<typename C, typename Modulus> static inline void 
00054   down (C* c, const C& a, Modulus** tree, nat* k, nat depth, nat n) {
00055     if (n == 0) return;
00056     c[0]= Crt::mod (a, tree[depth-1][0]);
00057     if (depth == 1) return;
00058     for (nat i= depth-1; i > 0; i--) {
00059       if (k[i-1] & 1) c[k[i-1] - 1]= c[k[i] - 1];
00060       for (nat j= (k[i-1] >> 1) - 1; j + 1 > 0; j--) {
00061         c[(j << 1) + 1]= Crt::mod (c[j], tree[i-1][(j << 1) + 1]);
00062         c[(j << 1)    ]= Crt::mod (c[j], tree[i-1][(j << 1)    ]); } } }
00063 
00064   template<typename C, typename Modulus> static inline void
00065   up (C& a, C* c, Modulus** tree, nat* k, nat depth, nat n) {
00066     if (n == 0) return;
00067     for (nat i= 0; i < depth - 1; i++) {
00068       for (nat j= 0; j < (k[i] >> 1); j++)
00069         c[j]= c[j << 1]       * * tree[i][(j << 1) + 1] +
00070               c[(j << 1) + 1] * * tree[i][j << 1];
00071       if (k[i] & 1) c[k[i+1] - 1]= c[k[i] - 1]; }
00072     a= c[0]; }
00073 
00074   template<typename C, typename J, typename Modulus> static inline void
00075   direct (J* c, const C& a, 
00076           Modulus** tree, nat* k, nat depth, nat n, C* aux) {
00077     down (aux, a, tree, k, depth, n);
00078     for (nat i= 0; i < n; i++) c[i]= as<J> (aux[i]); }
00079   
00080   template<typename C, typename Modulus> static inline void
00081   direct (C* c, const C& a,
00082           Modulus** tree, nat* k, nat depth, nat n, C* aux) {
00083     (void) aux; down (c, a, tree, k, depth, n); }
00084   
00085   template<typename C, typename I, typename Modulus> static inline void
00086   combine (C& a, const I* c, Modulus** tree, nat* k, nat depth, nat n,
00087            C* aux) {
00088     if (n == 0) { a= C(0); return; }
00089     for (nat i= 0; i < n; i++) aux[i]= C (c[i]);
00090     up (a, aux, tree, k, depth, n); }
00091 
00092   template<typename C, typename I, typename Modulus> static inline void
00093   inverse (C& a, const I* c,
00094            Modulus** tree, nat* k, nat depth,
00095            C* m, nat n, const Modulus& P, C* aux) {
00096     if (n == 0) { a= C(0); return; }
00097     for (nat i= 0; i < n; i++)
00098       aux[i]= Crt::mod (C (c[i]) * m[i], tree[0][i]);
00099     up (a, aux, tree, k, depth, n);
00100     a= Crt::mod (a, P); }
00101 
00102 };
00103 
00104 /******************************************************************************
00105 * Transformer
00106 ******************************************************************************/
00107     
00108 template<typename C, typename S=std_crt_dicho<C>,
00109          typename V=typename Crt_dicho_variant(C)>
00110 struct crt_dicho_transformer : public S {
00111 private:
00112   typedef typename S::modulus_base I;
00113   typedef modulus<I, typename S::modulus_base_variant> M;
00114   typedef modulus<C, typename S::modulus_variant> Modulus;
00115   typedef implementation<vector_linear, vector_naive> Vec;
00116   typedef implementation<crt_transform,V> Crt;
00117 
00118   nat n;
00119   M* p;     // moduli
00120   modulus<C>** tree; // subproduct tree of depth 'depth' with 'n' leafs
00121   nat depth;// depth of the tree
00122   nat* k;   // size of each level of the tree
00123   Modulus P;
00124   C H;
00125   C* m;     // sequence of inverse P/p[i] mod p[i]
00126   C* aux;
00127 
00128   inline void setup_direct (const M* _p, nat nn) {
00129     m= NULL; // setup only if necessary
00130     n= nn;
00131     if (n == 0) { depth= 0; P= 1; H= 0; return; }
00132     p= mmx_new<M> (n);
00133     for (nat i= 0; i < n; i++) p[i]= _p[i];
00134     depth= log_2 (next_power_of_two (n)) + 1;
00135     tree= mmx_new<Modulus*> (depth);
00136     k= mmx_new<nat> (depth);
00137     k[0]= n;
00138     tree[0]= mmx_new<Modulus> (k[0]);
00139     for (nat j= 0; j < k[0]; j++) 
00140       tree[0][j]= C(* p[j]);
00141     for (nat i= 1; i < depth; i++) {
00142       k[i]= (k[i-1] >> 1) + (k[i-1] & 1);
00143       tree[i]= mmx_new<Modulus> (k[i]);
00144       for (nat j= 0; j < (k[i-1] >> 1); j++)
00145         tree[i][j]= * tree[i-1][j << 1] * * tree[i-1][(j << 1) + 1];
00146       if (k[i-1] & 1) tree[i][k[i] - 1]= * tree[i-1][k[i-1] - 1];
00147     }
00148     P= tree[depth-1][0];
00149     H= Crt::half (P); }
00150 
00151 public:
00152 
00153   inline void setup_inverse () {
00154     typedef implementation<vector_linear,vector_naive> Vec;
00155     if (n == 0 || m != NULL) return;
00156     m= mmx_new<C> (n);
00157     C c;
00158     Vec::set (m, C(1), n);
00159     Crt::up (c, m, tree, k, depth, n);
00160     Crt::down (m, c, tree, k, depth, n);
00161     for (nat i= 0; i < n; i++)
00162       inv_mod (m[i], tree[0][i]); }
00163 
00164   inline crt_dicho_transformer (const vector<M>& p, bool lazy= true)
00165     : tree(NULL), k(NULL) {
00166     setup_direct (seg (p), N(p));
00167     aux= mmx_new<C> (n);
00168     if (! lazy) setup_inverse (); }
00169 
00170   inline ~crt_dicho_transformer () {
00171     if (n == 0) return;
00172     mmx_delete<M> (p, n);
00173     mmx_delete<C> (aux, n);
00174     for (nat i= 0; i < depth; i++)
00175       mmx_delete<Modulus> (tree[i], k[i]);
00176     mmx_delete<Modulus*> (tree, depth);
00177     mmx_delete<nat> (k, depth);
00178     if (m != NULL) mmx_delete<C> (m, n); }
00179 
00180   inline M operator[] (nat i) const {
00181     VERIFY (i < n, "index out of range");
00182     return p[i]; }
00183 
00184   inline nat size () const {
00185     return n; }
00186 
00187   inline Modulus product () const {
00188     return P; }
00189 
00190   inline C comodulus (nat i) const {
00191     VERIFY (i < n, "index out of range");
00192     return *P / m[i]; }
00193     
00194   inline void direct_transform (I* c, const C& a) const {
00195     C b= Crt::encode (a, P);
00196     Crt::direct (c, b, tree, k, depth, n, aux); }
00197 
00198   inline void combine (C& a, const I* c) {
00199     Crt::combine (a, c, tree, k, depth, n, aux); }
00200 
00201   inline void inverse_transform (C& a, const I* c) {
00202     setup_inverse ();
00203     Crt::inverse (a, c, tree, k, depth, m, n, P, aux);
00204     a= Crt::decode (a, P, H); }
00205 };
00206 
00207 template<typename C, typename M, typename V> inline nat
00208 N (const crt_dicho_transformer<C,M,V>& crter) {
00209   return crter.size (); 
00210 }
00211 
00212 } // namespace mmx
00213 #endif //__MMX__CRT_DICHO__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines