algebramix_doc 0.3
|
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