algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/series_carry_blocks.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : series_carry_blocks.hpp
00004 * DESCRIPTION: blocks p-adic numbers
00005 * COPYRIGHT  : (C) 2009  Jeremy Berthomieu 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_SERIES_CARRY_BLOCKS_HPP
00014 #define __MMX_SERIES_CARRY_BLOCKS_HPP
00015 #include <algebramix/series_carry.hpp>
00016 
00017 namespace mmx {
00018 #define Series     series<M,V>
00019 #define Series_rep series_rep<M,V>
00020 #define C       typename M::C
00021 #define Modulus typename M::modulus
00022 #define TMPL    template<typename M,typename V>
00023 #define Monoblock_transformer series_carry_monoblock_transformer<M,V,s,BV>
00024 
00025 /******************************************************************************
00026 * Monoblock variant
00027 ******************************************************************************/
00028 
00029 // V fallback variant
00030 // s is the size of the blocks
00031 // BV block variant
00032 // t is the threshold
00033 template<typename V,
00034          nat s,
00035          typename BV,
00036          nat t=s>
00037 struct series_carry_monoblock {};
00038 
00039 template<typename V,typename BV,typename U,typename W,nat s,nat t>
00040 struct implementation<U,W,series_carry_monoblock<V,s,BV,t> >:
00041   public implementation<U,W,V> {};
00042 
00043 /******************************************************************************
00044 * Relaxed blocks variant
00045 ******************************************************************************/
00046 
00047 template<typename V,
00048          nat s,
00049          typename BV,
00050          nat t=s>
00051 struct series_carry_blocks {};
00052 
00053 template<typename V,typename BV,typename U,typename W,nat s,nat t>
00054 struct implementation<U,W,series_carry_blocks<V,s,BV,t> >:
00055   public implementation<U,W,V> {};
00056 
00057 /******************************************************************************
00058 * Blocks transformer
00059 ******************************************************************************/
00060 
00061 #define Monoblock_modular modular<modulus<Lift_type(M)>,                \
00062                                   modular_global_series_carry_monoblock \
00063                                   <M,s,BV> >
00064 
00065 #define Monoblock_series_rep series_rep<Monoblock_modular,BV>
00066 #define Monoblock_series     series    <Monoblock_modular,BV>
00067 
00068 template<typename M,nat s,typename BV>
00069 struct modular_global_series_carry_monoblock {
00070   template<typename P>
00071   class modulus_storage {
00072     static inline P& dyn_modulus () {
00073       static P modulus = P ();
00074       return modulus; }
00075   public:
00076     static inline void set_modulus (const P& p) { dyn_modulus () = p; }
00077     static inline P get_modulus () { return dyn_modulus (); }
00078   };
00079 };
00080 
00081 template<typename M, typename V, nat s, typename BV>
00082 class series_carry_monoblock_transformer {
00083 
00084 class to_monoblock_series_rep: public Monoblock_series_rep {
00085 public:
00086   typedef Lift_type(M) L;
00087   typedef typename Base_transformer_unsigned(L,C) Baser;
00088    
00089 protected:
00090   Series f;
00091   C* buf;
00092   Baser* baser;
00093 
00094 public:
00095   to_monoblock_series_rep (const Series& f2):
00096     Monoblock_series_rep (format<Monoblock_modular > (/*FIXME*/)), f(f2) {
00097     Monoblock_modular::set_modulus (binpow (L(* M::get_modulus ()), s));
00098     buf= mmx_new<C> (s);
00099     baser= mmx_new<Baser> (1, * M::get_modulus ()); }
00100 
00101   ~to_monoblock_series_rep () {
00102     mmx_delete<Baser> (baser, 1);
00103     mmx_delete<C> (buf, s); }
00104 
00105   syntactic expression (const syntactic& z) const {
00106     return apply ("to_monoblock", flatten (f, z), flatten (s)); }
00107 
00108   void Increase_order (nat l) {
00109     Monoblock_series_rep::Increase_order (l);
00110     increase_order (f, l * s); }
00111 
00112   Monoblock_modular next () {
00113     nat start = s * this->n;
00114     for (nat i= 0; i < s; i++) buf[i]= * f[start + i];
00115     L e; inverse_base (e, buf, s, * baser);
00116     return Monoblock_modular (e, true); }
00117 };
00118 
00119 class from_monoblock_series_rep: public Series_rep {
00120 public:
00121   typedef Lift_type(M) L;
00122   typedef typename Base_transformer_unsigned(L,C) Baser;
00123   
00124 protected:
00125   Monoblock_series F;
00126   C* buf; // p-adic decomposition of current term of F
00127   Baser* baser;
00128 public:
00129 
00130   from_monoblock_series_rep (const Monoblock_series& F2):
00131     Series_rep (format<M> (/*FIXME*/)), F(F2) {
00132     buf= mmx_new<C> (s);
00133     baser= mmx_new<Baser> (1, * M::get_modulus ()); }
00134 
00135   ~from_monoblock_series_rep () {
00136     mmx_delete<C> (buf, s);
00137     mmx_delete<Baser> (baser, 1); }
00138 
00139   syntactic expression (const syntactic& z) const {
00140     return apply ("from_monoblock", flatten (F, z), flatten (s)); }
00141 
00142   void Increase_order (nat l) {
00143     Series_rep::Increase_order (l);
00144     increase_order (F, (l + s - 1) / s); }
00145   
00146   M next () {
00147     nat q= this->n / s, r= this->n % s;
00148     if (r == 0) {
00149       nat m= direct_base (buf, s, * F[q], * baser);
00150       for (nat i= m; i < s; i++) buf[i]= 0;
00151     }
00152     return buf[r];
00153   }
00154 };
00155 
00156 public:
00157 
00158 inline series_carry_monoblock_transformer () {}
00159 
00160 inline Monoblock_series
00161 to_monoblock (const Series& f) const {
00162   if (is_exact_zero (f))
00163     return Monoblock_series (Monoblock_modular (0) /*FIXME*/);
00164   return (Monoblock_series_rep*) new to_monoblock_series_rep (f);
00165 }
00166 
00167 inline Series
00168 from_monoblock (const Monoblock_series& f) const {
00169   if (is_exact_zero (f))
00170     return Series (C(0) /*FIXME*/);
00171   return (Series_rep*) new from_monoblock_series_rep (f);
00172 }
00173 
00174 };
00175 
00176 // Top level conversions
00177 
00178 template<typename M, typename V, nat s, typename BV> Monoblock_series
00179 to_monoblock (const Series& f,
00180               const Monoblock_transformer& blocker) {
00181   return blocker.to_monoblock (f);
00182 }
00183 
00184 template<typename M, typename V, nat s, typename BV> Series
00185 from_monoblock (const Monoblock_series& f,
00186                 const Monoblock_transformer& blocker) {
00187   return blocker.from_monoblock (f);
00188 }
00189 
00190 /******************************************************************************
00191 * Monoblock abstractions
00192 ******************************************************************************/
00193 
00194 template<typename Op, typename M, typename V, nat s, typename BV, nat t>
00195 class binary_monoblock_series_rep: public Series_rep {
00196   Monoblock_transformer blocker;
00197   Series f, g;
00198   bool h1_init;
00199   Series h0, h1;  
00200 
00201 public:
00202   binary_monoblock_series_rep (const Series& f2, const Series& g2):
00203     Series_rep (CF(f2)), f(f2), g(g2), h1_init (false) {
00204     h0= Op::op (f, g); }
00205   syntactic expression (const syntactic& z) const {
00206     return Op::op (flatten (f, z), flatten (g, z)); }
00207   virtual void Increase_order (nat l) {
00208     Series_rep::Increase_order (l);
00209     if (l <= t)
00210       increase_order (h0, l);
00211     else {
00212       if (! h1_init) {
00213         h1= from_monoblock (Op::op (to_monoblock (f, blocker),
00214                                     to_monoblock (g, blocker)),
00215                              blocker);
00216         h1_init= true;
00217       }
00218       increase_order (h1, l); } }
00219   M next () {
00220     return this->n < t ? h0[this->n] : h1[this->n]; }
00221 };
00222 
00223 template<typename Op, typename M, typename V, nat s, typename BV, nat t>
00224 inline Series
00225 binary_monoblock_series (const Series& f, const Series& g) {
00226   typedef binary_monoblock_series_rep<Op,M,V,s,BV,t> Op_rep;
00227   return (Series_rep*) new Op_rep (f, g); }
00228 
00229 /******************************************************************************
00230 * Truncate and multiply
00231 ******************************************************************************/
00232 
00233 template<typename M, typename V, nat s, typename BV, nat t>
00234 class truncate_mul_monoblock_series_rep: public Series_rep {
00235   Monoblock_transformer blocker;
00236   Series f, g;
00237   nat nf, ng;
00238   bool h1_init;
00239   Series h0, h1;  
00240 
00241 public:
00242   truncate_mul_monoblock_series_rep (const Series& f2, const Series& g2,
00243                                      nat nf2, nat ng2):
00244     Series_rep (CF(f2)), f(f2), g(g2), nf (nf2), ng (ng2), h1_init (false) {
00245     h0= truncate_mul (f, g, nf, ng); }
00246   syntactic expression (const syntactic& z) const {
00247     return apply ("truncate_mul", flatten (f, z), flatten (g, z),
00248                   flatten (nf), flatten (ng)); }
00249   virtual void Increase_order (nat l) {
00250     Series_rep::Increase_order (l);
00251     if (l <= t)
00252       increase_order (h0, l);
00253     else {
00254       if (! h1_init) {
00255         Series f0= piecewise (f, Series (CF(f)), nf);
00256         Series g0= piecewise (g, Series (CF(g)), ng);
00257         h1= from_monoblock (truncate_mul (to_monoblock (f0, blocker),
00258                                           to_monoblock (g0, blocker),
00259                                           (nf + s - 1) / s,
00260                                           (ng + s - 1) / s),
00261                             blocker);
00262         h1_init= true;
00263       }
00264       increase_order (h1, l); } }
00265   M next () {
00266     return this->n < t ? h0[this->n] : h1[this->n]; }
00267 };
00268 
00269 template<typename M, typename V, nat s, typename BV, nat t>
00270 inline Series
00271 truncate_mul_monoblock_series (const Series& f, const Series& g,
00272                                nat nf, nat ng) {
00273   typedef truncate_mul_monoblock_series_rep<M,V,s,BV,t> Mul_rep;
00274   return (Series_rep*) new Mul_rep (f, g, nf, ng); }
00275 
00276 /******************************************************************************
00277 * Recursive monoblock abstractions -- require monoblock-recursivity!
00278 ******************************************************************************/
00279 
00280 template<typename Op, typename M, typename V, nat s,
00281          typename BV, nat t, typename X>
00282 class binary_scalar_recursive_monoblock_series_rep: public Series_rep {
00283   Monoblock_transformer blocker;
00284   Series f;
00285   X x;
00286   bool h1_init;
00287   Series h0, h1;  
00288 
00289 public:
00290   binary_scalar_recursive_monoblock_series_rep (const Series& f2, const X& x2):
00291     Series_rep (CF(f2)), f(f2), x(x2), h1_init (false) {
00292     h0= Op::op (f, x); }
00293   binary_scalar_recursive_monoblock_series_rep (const Series& f2, const X& x2,
00294                                                 const M& init):
00295     Series_rep (CF(f2)), f(f2), x(x2), h1_init (false) {
00296     h0= Op::op (f, x, init); }
00297   syntactic expression (const syntactic& z) const {
00298     return apply (Op::name (), flatten (f, z), flatten (x)); }
00299   virtual void Increase_order (nat l) {
00300     Series_rep::Increase_order (l);
00301     if (l <= t)
00302       increase_order (h0, l);
00303     else {
00304       if (! h1_init) {
00305         Monoblock_modular init= as<Lift_type(M)> (truncate (h0, s));
00306         h1= from_monoblock (Op::op_init (to_monoblock (f, blocker), x, init),
00307                             blocker);
00308         h1_init= true;
00309       }
00310       increase_order (h1, l); } }
00311   M next () {
00312     return this->n < t ? h0[this->n] : h1[this->n]; }
00313 };
00314 
00315 template<typename Op, typename M, typename V, nat s,
00316          typename BV, nat t, typename X> inline Series
00317 binary_scalar_recursive_monoblock_series (const Series& f, const X& x) {
00318   typedef binary_scalar_recursive_monoblock_series_rep<Op,M,V,s,BV,t,X> Op_rep;
00319   return (Series_rep*) new Op_rep (f, x); }
00320 
00321 #undef Monoblock_modular
00322 #undef Monoblock_series_rep
00323 #undef Monoblock_series
00324 
00325 /******************************************************************************
00326 * Monoblock multiplication
00327 ******************************************************************************/
00328 
00329 template<typename U,typename W,nat s,typename BV,nat t>
00330 struct implementation<series_multiply,U,series_carry_monoblock<W,s,BV,t> >:
00331   public implementation<series_abstractions,U>
00332 {
00333 
00334 TMPL static inline Series
00335 ser_mul (const Series& f, const Series& g) {
00336   if (is_exact_zero (f) || is_exact_zero (g))
00337     return Series (CF(f));
00338   return as<Series> (binary_monoblock_series<mul_op,M,W,s,BV,t>
00339                      (as<series<M,W> > (f), as<series<M,W> > (g))); }
00340 
00341 TMPL static inline Series
00342 ser_truncate_mul (const Series& f, const Series& g, nat nf, nat ng) {
00343   if (is_exact_zero (f) || is_exact_zero (g) || nf == 0 || ng == 0)
00344     return Series (CF(f));
00345   return as<Series> (binary_monoblock_series<mul_op,M,W,s,BV,t>
00346                      (as<series<M,W> > (f), as<series<M,W> > (g))); }
00347 }; // implementation<series_multiply,U,series_carry_monoblock<W> >:
00348 
00349 /******************************************************************************
00350 * Monoblock Division
00351 ******************************************************************************/
00352 
00353 template<typename U,typename W,nat s,typename BV,nat t>
00354 struct implementation<series_divide,U,series_carry_monoblock<W,s,BV,t> >:
00355   public implementation<series_multiply,U>
00356 {
00357 
00358 TMPL static inline Series
00359 ser_rdiv_sc (const Series& f, const M& c) {
00360   typedef implementation<series_divide,W> Ser;
00361   return Ser::ser_rdiv_sc (f, c); }
00362 
00363 TMPL static inline Series
00364 ser_div (const Series& f, const Series& g) {
00365   if (is_exact_zero (f))
00366     return Series (CF(f));
00367   return as<Series> (binary_monoblock_series<div_op,M,W,s,BV,t>
00368                      (as<series<M,W> > (f), as<series<M,W> > (g))); }
00369 
00370 TMPL static inline Series
00371 ser_quo (const Series& f, const M& c) {
00372   return ser_div_sc (f, c); }
00373   
00374 TMPL static inline Series
00375 ser_quo (const Series& f, const Series& g) {
00376   return ser_div (f, g); }
00377 
00378 TMPL static inline Series
00379 ser_rrem_sc (const Series& f, const M& c) {
00380   return Series (CF(f)); }
00381 
00382 }; // implementation<series_divide,U,series_carry_monoblock<W> >
00383 
00384 /******************************************************************************
00385 * separable roots
00386 ******************************************************************************/
00387 
00388 template<typename U,typename W,nat s,typename BV,nat t>
00389 struct implementation<series_separable_root,U,
00390                       series_carry_monoblock<W,s,BV,t> >:
00391     public implementation<series_multiply,U>
00392 {
00393 
00394 TMPL static inline Series
00395 sep_root (const Series& f, nat r) {
00396   ASSERT (M(r) != 0, "not implemented");
00397   return as<Series>
00398     (binary_scalar_recursive_monoblock_series
00399      <ser_separable_root_op,M,W,s,BV,t,nat> (as<series<M,W> > (f), r)); }
00400 
00401 TMPL static inline Series
00402 sep_root_init (const Series& f, nat r, const M& init) {
00403   ASSERT (M(r) != 0, "not implemented");
00404   return as<Series>
00405     (binary_scalar_recursive_monoblock_series
00406      <ser_separable_root_op,M,W,s,BV,t,nat> (as<series<M,W> > (f), r, init)); }
00407 };
00408 
00409 /******************************************************************************
00410 * Relaxed blocks multiplication
00411 ******************************************************************************/
00412 
00413 template<typename U,typename W,nat s,typename BV,nat t>
00414 struct implementation<series_multiply,U,series_carry_blocks<W,s,BV,t> >:
00415   public implementation<series_abstractions,U>
00416 {
00417 
00418 TMPL
00419 class mul_series_rep: public Series_rep {
00420   series_carry_monoblock_transformer<M,W,s,BV> blocker;
00421   Series f, g, h;
00422   
00423 public:
00424   mul_series_rep (const Series& f2, const Series& g2):
00425     Series_rep (CF(f2)), f(f2), g(g2)
00426   {
00427     VERIFY (t >= s-1, "wrong threshold");
00428     series<M,W> f0 = as<series<M,W> > (f);
00429     series<M,W> g0 = as<series<M,W> > (g);
00430     series<M,W> f1 = rshiftz (f0, (int) t);
00431     series<M,W> g1 = rshiftz (g0, (int) t);
00432     h= as<Series> (truncate_mul (f0, g0, t, t)
00433                    + lshiftz (truncate_mul (f0, g1, t, Maximal (nat)) +
00434                               truncate_mul (f1, g0, Maximal (nat), t),
00435                               (int) t)
00436                    + lshiftz (from_monoblock (to_monoblock (f1, blocker) *
00437                                               to_monoblock (g1, blocker),
00438                                               blocker),((int) t) << 1)); }
00439   syntactic expression (const syntactic& z) const {
00440     return flatten (f, z) * flatten (g, z); }
00441   virtual void Increase_order (nat l) {
00442     Series_rep::Increase_order (l);
00443     increase_order (h, l); }
00444   M next () {
00445     return h[this->n]; }
00446 };
00447 
00448 TMPL static inline Series
00449 ser_mul (const Series& f, const Series& g) {
00450   if (is_exact_zero (f) || is_exact_zero (g))
00451     return Series (CF(f));
00452   return (Series_rep*) new mul_series_rep<M,V> (f, g); }
00453 
00454 TMPL static inline Series
00455 ser_truncate_mul (const Series& f, const Series& g, nat nf, nat ng) {
00456   typedef mul_series_rep<M,V> Mul_rep;
00457   if (is_exact_zero (f) || is_exact_zero (g) || nf == 0 || ng == 0)
00458     return Series (CF(f));
00459   return (Series_rep*)
00460     new Mul_rep (piecewise (f, Series (CF(f)), nf),
00461                  piecewise (g, Series (CF(g)), ng)); }
00462 
00463 }; // implementation<series_multiply,U,series_carry_blocks<W> >:
00464 
00465 #undef Series
00466 #undef Series_rep
00467 #undef C
00468 #undef Modulus
00469 #undef TMPL
00470 #undef Monoblock_transformer
00471 } // namespace mmx
00472 #endif // __MMX_SERIES_CARRY_BLOCKS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines