algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/series_implicit.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : series_implicit.hpp
00004 * DESCRIPTION: Implicitly defined power series
00005 * COPYRIGHT  : (C) 2009  Joris van der Hoeven
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_IMPLICIT_HPP
00014 #define __MMX_SERIES_IMPLICIT_HPP
00015 #include <algebramix/series_vector.hpp>
00016 namespace mmx {
00017 #define TMPL_DEF template<typename C, typename V=typename Series_variant(C)>
00018 #define TMPL template<typename C, typename V>
00019 #define Series series<C,V>
00020 #define Series_rep series_rep<C,V>
00021 #define VC vector<C>
00022 #define VSeries series<vector<C>,V>
00023 #define VSeries_rep series_rep<vector<C>,V>
00024 #define UC unknown<C,V>
00025 #define UC_rep unknown_rep<C,V>
00026 #define USeries series<UC >
00027 #define USeries_rep series_rep<UC >
00028 #define Solver_rep solver_series_rep<C,V>
00029 TMPL class solver_series_rep;
00030 
00031 /******************************************************************************
00032 * Unknown coefficients
00033 ******************************************************************************/
00034 
00035 TMPL_DEF
00036 class unknown_rep REP_STRUCT {
00037 public:
00038   Solver_rep* f;   // underlying series
00039   C   b;           // base
00040   C*  s;           // slope
00041   nat l;           // number of allocated elements
00042   nat i1;          // starting coefficient
00043   nat i2;          // ending coefficient
00044 
00045   inline void normalize () {
00046     nat k=i1;
00047     while (i1 < i2 && is_exact_zero (s[i2-k-1])) i2--;
00048     while (i1 < i2 && is_exact_zero (s[i1-k])) i1++;
00049     if (i1 != k) {
00050       //mmerr << "    normalize " << i1 << " -- " << i2 << "\n";
00051       nat d= i1-k;
00052       C* s2= mmx_new<C> (i2-i1);
00053       for (nat i=0; i<i2-i1; i++) s2[i]= s[i+d];
00054       mmx_delete<C> (s, l);
00055       s= s2;
00056       l= i2-i1;
00057     }
00058   }
00059     
00060   inline unknown_rep ():
00061     f (NULL), b (), s (mmx_new<C> (0)), l (0), i1 (0), i2 (0) {}
00062   inline unknown_rep (const C& b2):
00063     f (NULL), b (b2), s (mmx_new<C> (0)), l (0), i1 (0), i2 (0) {}
00064   unknown_rep (Solver_rep* f2, const C& b2, C* ss, nat s2, nat e2):
00065     f (f2), b (b2), s (ss), l (e2 - s2), i1 (s2), i2 (e2) { normalize (); }
00066   inline virtual ~unknown_rep () {
00067     mmx_delete<C> (s, l); }
00068 };
00069 
00070 TMPL_DEF
00071 class unknown {
00072 INDIRECT_PROTO_2 (unknown, unknown_rep, C, V)
00073 public:
00074   inline unknown ():
00075     rep (new UC_rep ()) {}
00076   template<typename T> inline unknown (const T& b):
00077     rep (new UC_rep (as<C> (b))) {}
00078   inline unknown (Solver_rep* f, const C& b, C* s, nat i1, nat i2):
00079     rep (new UC_rep (f, b, s, i1, i2)) {}
00080 };
00081 INDIRECT_IMPL_2 (unknown, unknown_rep, typename C, C, typename V, V)
00082 
00083 TMPL inline bool
00084 is_known (const UC& c) {
00085   return c->i2 == c->i1;
00086 }
00087 
00088 TMPL inline C
00089 known (const UC& c) {
00090   ASSERT (c->i2 == c->i1, "cast failed");
00091   return c->b;
00092 }
00093 
00094 /******************************************************************************
00095 * Prototype for implicit series
00096 ******************************************************************************/
00097 
00098 TMPL_DEF
00099 class solver_series_rep: public VSeries_rep {
00100 public:
00101   nat m;
00102   vector<USeries > eqs;
00103   nat cur_n;
00104   vector<UC> sys;
00105 
00106 public:
00107   inline solver_series_rep (nat m, const vector<vector<C> >& init);
00108   virtual void Increase_order (nat l);
00109   virtual syntactic name_component (nat i);
00110   virtual vector<USeries > initialize () = 0;
00111   vector<USeries > me ();
00112   VC next ();
00113 };
00114 
00115 /******************************************************************************
00116 * Mandatory routines for unknown coefficients
00117 ******************************************************************************/
00118 
00119 TMPL bool
00120 is_exact_zero (const UC c) {
00121   return c->i1 == c->i2 && is_exact_zero (c->b);
00122 }
00123 
00124 template<typename Op, typename C, typename V> nat
00125 unary_hash (const UC& c) {
00126   register nat i, h= 78460;
00127   if (c->i1 == c->i2) return Op::op (c->b) ^ h;
00128   h += (c->i1 << 3) ^ Op::op (c->b);
00129   for (i=0; i<c->i2 - c->i1; i++)
00130     h= (h<<1) ^ (h<<5) ^ (h>>27) ^ Op::op (c->s[i]);
00131   return h;
00132 }
00133 
00134 template<typename Op,typename C,typename V> inline bool
00135 binary_test (const UC& c1, const UC& c2) {
00136   if (Op::not_op (c1->b, c2->b)) return false;
00137   if (c1->i1 == c1->i2 || c2->i1 == c2->i2)
00138     return c1->i1 == c1->i2 && c2->i1 == c2->i2;
00139   if (Op::not_op (c1->f, c2->f)) return false;
00140   if (Op::not_op (c1->i1, c2->i1)) return false;
00141   if (Op::not_op (c1->i2, c2->i2)) return false;
00142   for (nat i= c1->i1; i<c1->i2; i++)
00143     if (Op::not_op (c1->s[i - c1->i1], c2->s[i - c1->i1]))
00144       return false;
00145   return true;
00146 }
00147 
00148 TMPL syntactic
00149 flatten (const UC& c) {
00150   syntactic sum= flatten (c->b);
00151   for (nat i=c->i1; i<c->i2; i++) {
00152     nat k= i / c->f->m;
00153     nat j= i % c->f->m;
00154     sum= sum + flatten (c->s[i-c->i1]) *
00155                access (c->f->name_component (j), flatten (k));
00156   }
00157   return sum;
00158 }
00159 
00160 TRUE_IDENTITY_OP_SUGAR(TMPL,UC)
00161 EXACT_IDENTITY_OP_SUGAR(TMPL,UC)
00162 
00163 /******************************************************************************
00164 * Basic arithmetic on affine combinations of unknown coefficients
00165 ******************************************************************************/
00166 
00167 TMPL UC
00168 operator - (const UC& c) {
00169   //mmerr << "    negate " << c << "\n";
00170   if (is_exact_zero (c)) return c;
00171   nat n= c->i2 - c->i1;
00172   C* s= mmx_new<C> (n);
00173   for (nat i=0; i<n; i++)
00174     s[i]= -c->s[i];
00175   return UC (c->f, -c->b, s, c->i1, c->i2);
00176 }
00177 
00178 TMPL UC
00179 operator + (const UC& c1, const C& c2) {
00180   //mmerr << "    scalar plus " << c1 << ", " << c2 << "\n";
00181   if (is_exact_zero (c1))
00182     return UC (c1->f, c2, mmx_new<C> (0), c1->i1, c1->i1);
00183   if (is_exact_zero (c2)) return c1;
00184   nat n= c1->i2 - c1->i1;
00185   C* s= mmx_new<C> (n);
00186   for (nat i=0; i<n; i++)
00187     s[i]= c1->s[i];
00188   return UC (c1->f, c1->b + c2, s, c1->i1, c1->i2);
00189 }
00190 
00191 TMPL UC
00192 operator * (const UC& c1, const C& c2) {
00193   //mmerr << "    scalar times " << c1 << ", " << c2 << "\n";
00194   if (is_exact_zero (c1)) return c1;
00195   if (is_exact_zero (c2))
00196     return UC (c1->f, C (0), mmx_new<C> (0), c1->i1, c1->i1);
00197   nat n= c1->i2 - c1->i1;
00198   C* s= mmx_new<C> (n);
00199   for (nat i=0; i<n; i++)
00200     s[i]= c1->s[i] * c2;
00201   return UC (c1->f, c1->b * c2, s, c1->i1, c1->i2);
00202 }
00203 
00204 TMPL UC
00205 operator * (const C& c1, const UC& c2) {
00206   //mmerr << "    scalar times " << c1 << ", " << c2 << "\n";
00207   if (is_exact_zero (c2)) return c2;
00208   if (is_exact_zero (c1))
00209     return UC (c2->f, C (0), mmx_new<C> (0), c2->i1, c2->i1);
00210   nat n= c2->i2 - c2->i1;
00211   C* s= mmx_new<C> (n);
00212   for (nat i=0; i<n; i++)
00213     s[i]= c1 * c2->s[i];
00214   return UC (c2->f, c1 * c2->b, s, c2->i1, c2->i2);
00215 }
00216 
00217 TMPL UC
00218 operator + (const UC& c1, const UC& c2) {
00219   //mmerr << "    plus " << c1 << ", " << c2 << "\n";
00220   if (c1->i1 == c1->i2) return c2 + known (c1);
00221   if (c2->i1 == c2->i2) return c1 + known (c2);
00222   ASSERT (c1->f == c2->f, "incompatible unknown coefficients");
00223   nat i1= min (c1->i1, c2->i1);
00224   nat i2= max (c1->i2, c2->i2);
00225   C* s= mmx_new<C> (i2-i1);
00226   for (nat i= i1; i<i2; i++)
00227     s[i-i1]=
00228       (i >= c1->i1 && i < c1->i2? c1->s[i - c1->i1]: C(0)) +
00229       (i >= c2->i1 && i < c2->i2? c2->s[i - c2->i1]: C(0));
00230   return UC (c1->f, c1->b + c2->b, s, i1, i2);
00231 }
00232 
00233 TMPL UC
00234 operator - (const UC& c1, const UC& c2) {
00235   //mmerr << "    minus " << c1 << ", " << c2 << "\n";
00236   if (c1->i1 == c1->i2) return (-c2) + known (c1);
00237   if (c2->i1 == c2->i2) return c1 + (-known (c2));
00238   ASSERT (c1->f == c2->f, "incompatible unknown coefficients");
00239   nat i1= min (c1->i1, c2->i1);
00240   nat i2= max (c1->i2, c2->i2);
00241   C* s= mmx_new<C> (i2-i1);
00242   for (nat i=i1; i<i2; i++)
00243     s[i-i1]=
00244       (i >= c1->i1 && i < c1->i2? c1->s[i - c1->i1]: C(0)) -
00245       (i >= c2->i1 && i < c2->i2? c2->s[i - c2->i1]: C(0));
00246   return UC (c1->f, c1->b - c2->b, s, i1, i2);
00247 }
00248 
00249 TMPL UC
00250 substitute (const UC& c) {
00251   //mmerr << "    substitute " << c << "\n";
00252   if (c->i1 == c->i2 || c->i1 >= c->f->n * c->f->m) return c;
00253   nat i1= min (c->f->n * c->f->m, c->i2);
00254   nat d= i1 - c->i1;
00255   nat n= c->i2 - i1;
00256   C*  s= mmx_new<C> (n);
00257   C   b= c->b;
00258   for (nat i=0; i<d; i++) {
00259     nat k= (i + c->i1) / c->f->m;
00260     nat j= (i + c->i1) % c->f->m;
00261     b += c->s[i] * c->f->a[k][j];
00262   }
00263   for (nat i=0; i<n; i++)
00264     s[i]= c->s[i + d];
00265   return UC (c->f, b, s, i1, c->i2);
00266 }
00267 
00268 TMPL UC
00269 operator * (const UC& c1, const UC& c2) {
00270   //mmerr << "    times " << c1 << ", " << c2 << "\n";
00271   if (is_exact_zero (c1)) return c1;
00272   if (is_exact_zero (c2)) return c2;
00273   if (c1->i1 == c1->i2) return known (c1) * c2;
00274   if (c2->i1 == c2->i2) return c1 * known (c2);
00275   UC c1b= substitute (c1);
00276   UC c2b= substitute (c2);
00277   if (c1b->i1 == c1b->i2) return known (c1b) * c2b;
00278   if (c2b->i1 == c2b->i2) return c1b * known (c2b);
00279   ERROR ("invalid product of unknown coefficients");
00280 }
00281 
00282 /******************************************************************************
00283 * Incremental triangulation
00284 ******************************************************************************/
00285 
00286 TMPL void
00287 reduce (UC& c1, UC& c2) {
00288   // Triangulation of two "rows" c1 and c2
00289   // On exit, the simplest "row" is put into c1
00290   //mmerr << "    reduce " << c1 << ", " << c2 << "\n";
00291   if (is_exact_zero (c1)) return;
00292   if (is_exact_zero (c2)) { swap (c1, c2); return; }
00293   ASSERT (c1->f == c2->f, "incompatible unknown coefficients");
00294   if (c1->i2 < c2->i2) return;
00295   if (c2->i2 < c1->i2) { swap (c1, c2); return; }
00296   if (better_pivot (c1->s[c1->i2 - 1 - c1->i1],
00297                     c2->s[c2->i2 - 1 - c2->i1])) swap (c1, c2);
00298   C lambda= c1->s[c1->i2 - 1 - c1->i1] / c2->s[c2->i2 - 1 - c2->i1];
00299   nat i1= min (c1->i1, c2->i1);
00300   nat i2= c1->i2;
00301   C* s= mmx_new<C> (i2-i1-1);
00302   for (nat i= i1; i<i2-1; i++)
00303     s[i-i1]=
00304       (i >= c1->i1? c1->s[i - c1->i1]: C(0)) -
00305       lambda * (i >= c2->i1? c2->s[i - c2->i1]: C(0));
00306   c1= UC (c1->f, c1->b - lambda * c2->b, s, i1, i2-1);
00307 }
00308 
00309 TMPL void
00310 insert_and_reduce (vector<UC >& sys, UC& c) {
00311   for (nat i=0; i<N(sys); i++)
00312     reduce (c, sys[i]);
00313   if (is_exact_zero (c)) return;
00314   ASSERT (c->i1 != c->i2, "contradictory equations");
00315   sys << c;
00316 }
00317 
00318 /******************************************************************************
00319 * Unknown and known series
00320 ******************************************************************************/
00321 
00322 TMPL_DEF
00323 class unknown_series_rep: public USeries_rep {
00324   Solver_rep* f;
00325   nat k;
00326 public:
00327   unknown_series_rep (Solver_rep* f2, nat k2):
00328     USeries_rep (format<UC > (/*FIXME*/)), f (f2), k (k2)
00329   {
00330     this->n= f->n;
00331     Set_order (this->n);
00332     for (nat i=0; i<f->n; i++) {
00333       C* s= mmx_new<C> (0);
00334       this->a[i]= UC (f, f->a[i][k], s, i, i);
00335     }
00336   }
00337   syntactic expression (const syntactic& z) const {
00338     return syn (f->name_component (k), z); }
00339   UC next () {
00340     C* s= mmx_new<C> (1);
00341     s[0]= C (1);
00342     return UC (f, C(0), s, this->n * f->m + k, this->n * f->m + k + 1); } 
00343 };
00344 
00345 TMPL USeries
00346 unknown_series (Solver_rep* f, nat k) {
00347   return (USeries_rep*) new unknown_series_rep<C> (f, k);
00348 }
00349 
00350 template<typename C, typename V, typename UV>
00351 class known_series_rep: public Series_rep {
00352 public:
00353   series<UC,UV> f;
00354   inline known_series_rep (const series<UC,UV>& f2):
00355     Series_rep (format<C> (/*FIXME*/)), f (f2) {}
00356   inline syntactic expression (const syntactic& z) const {
00357     return syn ("known", flatten (f, z)); }
00358   inline void Increase_order (nat l) {
00359     Series_rep::Increase_order (l);
00360     increase_order (f, l); }
00361   inline C next () { return known (substitute (f[this->n])); }
00362 };
00363 
00364 template<typename C, typename V, typename UV> Series
00365 known (const series<UC,UV>& f) {
00366   return (Series_rep*) new known_series_rep<C,V,UV> (f);
00367 }
00368 
00369 /******************************************************************************
00370 * Substitution product
00371 ******************************************************************************/
00372 
00373 template<typename C, typename V, typename UV>
00374 class subst_mul_series_rep:
00375    public implementation<series_abstractions,UV>
00376      ::template binary_series_rep<mul_op,UC,UV> {
00377 public:
00378   nat f_sh, g_sh;
00379   Series f_kn, g_kn, inner;
00380   inline subst_mul_series_rep (const USeries& f, const USeries& g):
00381     implementation<series_abstractions,UV>
00382      ::template binary_series_rep<mul_op,UC,UV> (f, g),
00383     f_sh (1), g_sh (1), f_kn (known (f)), g_kn (known (g)),
00384     inner (rshiftz (f_kn, (int) f_sh) * rshiftz (g_kn, (int) g_sh)) {}
00385   UC next () {
00386     if (this->n >= g_sh &&
00387         !is_known (substitute (this->f [this->n - g_sh]))) {
00388       g_sh = g_sh << 1;
00389       inner= rshiftz (f_kn, (int) f_sh) * rshiftz (g_kn, (int) g_sh);
00390     }
00391     if (this->n >= f_sh &&
00392         !is_known (substitute (this->g [this->n - f_sh]))) {
00393       f_sh = f_sh << 1;
00394       inner= rshiftz (f_kn, (int) f_sh) * rshiftz (g_kn, (int) g_sh);
00395     }
00396     if (this->n < f_sh + g_sh) {
00397       UC acc= this->f[0] * this->g[this->n];
00398       for (nat i=1; i<=this->n; i++)
00399         acc += this->f[i] * this->g[this->n-i];
00400       return acc;
00401     }
00402     else {
00403       UC acc= f_kn[0] * this->g[this->n] + this->f[this->n] * g_kn[0];
00404       for (nat i=1; i<f_sh; i++)
00405         acc += f_kn[i] * this->g[this->n-i];
00406       for (nat i=1; i<g_sh; i++)
00407         acc += this->f[this->n-i] * g_kn[i];
00408       return acc + inner[this->n - f_sh - g_sh];
00409     }
00410   }
00411 };
00412 
00413 template<typename C, typename V, typename UV> series<UC,UV>
00414 operator * (const series<UC,UV>& f, const series<UC,UV>& g) {
00415   if (is_exact_zero (f) || is_exact_zero (g))
00416     return series<UC,UV> (CF(f));
00417   return (series_rep<UC,UV>*) new subst_mul_series_rep<C,V,UV> (f, g);
00418 }
00419 
00420 /******************************************************************************
00421 * Implicit series
00422 ******************************************************************************/
00423 
00424 TMPL inline
00425 Solver_rep::solver_series_rep (nat m2, const vector<vector<C> >& init):
00426   VSeries_rep (format<VC > (/*FIXME*/)), m (m2), cur_n (0)
00427 {
00428   this->n= N(init);
00429   Set_order (this->n);
00430   for (nat i=0; i<this->n; i++)
00431     this->a[i]= init[i];
00432 }
00433 
00434 TMPL void
00435 Solver_rep::Increase_order (nat l) {
00436   VSeries_rep::Increase_order (l);
00437   for (nat i=0; i<N(eqs); i++)
00438     increase_order (eqs[i], l);
00439 }
00440 
00441 TMPL syntactic
00442 Solver_rep::name_component (nat i) {
00443   if (m == 1) return syntactic ("f");
00444   else return access (syntactic ("f"), flatten (i+1));
00445 }
00446 
00447 TMPL vector<USeries >
00448 Solver_rep::me () {
00449   vector<USeries > r= fill<USeries > (m);
00450   for (nat i=0; i<m; i++)
00451     r[i]= unknown_series (this, i);
00452   return r;
00453 }
00454 
00455 TMPL VC
00456 Solver_rep::next () {
00457   //mmerr << "Solving " << this->n << "\n";
00458   for (nat i=0; i<N(sys); i++)
00459     sys[i]= substitute (sys[i]);
00460   VC  ret = fill<C> (m);
00461   nat done= 0;
00462   while (true) {
00463     ASSERT (cur_n < this->n + 100, "too large delay in implicit solve");
00464     //mmerr << "  Coefficient " << cur_n << "\n";
00465     for (nat j=0; j<N(eqs); j++) {
00466       UC c= eqs[j][cur_n];
00467       //mmerr << "    Equation " << j << "= " << c << "\n";
00468       insert_and_reduce (sys, c);
00469     }
00470     //mmerr << "  System= " << sys << "\n";
00471     cur_n++;
00472     for (nat i=0; i<N(sys); i++)
00473       ASSERT (sys[i]->f == ((Solver_rep*) this) &&
00474               sys[i]->i1 >= this->n * m && sys[i]->i2 > this->n * m,
00475               "invalid situation during implicit solving");
00476     while (N(sys) > 0 && done < m) {
00477       UC c= sys[N(sys)-1];
00478       if (c->i2 <= this->n * m + done + 1) {
00479         nat j1 = c->i1 - this->n * m;
00480         nat j2 = min (done, c->i2 - this->n * m);
00481         C   rhs= c->b;
00482         for (nat j=j1; j<j2; j++)
00483           rhs += c->s[j-j1] * ret[j];
00484         if (c->i2 <= this->n * m + done) {
00485           ASSERT (is_exact_zero (rhs), "contradictory equations"); }
00486         else {
00487           ret[done]= -rhs / c->s[done-j1];
00488           //mmerr << "  Component " << done << "= " << ret[done] << "\n";
00489           done++;
00490         }
00491         sys.secure ();
00492         inside (sys) -> resize (N(sys) - 1);
00493       }
00494       else break;
00495     }
00496     if (done == m) return ret;
00497   }
00498 }
00499 
00500 TMPL
00501 class solver_container_series_rep: public VSeries_rep {
00502   VSeries f;
00503 public:
00504   solver_container_series_rep (const VSeries& f2):
00505     VSeries_rep (CF(f2)), f (f2) {
00506     Solver_rep* rep= (Solver_rep*) f.operator -> ();
00507     rep->eqs= rep->initialize (); }
00508   ~solver_container_series_rep () {
00509     Solver_rep* rep= (Solver_rep*) f.operator -> ();
00510     rep->eqs= vector<USeries > (); }
00511   syntactic expression (const syntactic& z) const {
00512     return flatten (f, z); }
00513   virtual void Increase_order (nat l) {
00514     VSeries_rep::Increase_order (l);
00515     increase_order (f, l); }
00516   VC next () { return f[this->n]; }
00517 };
00518 
00519 TMPL VSeries
00520 solver (const VSeries& f) {
00521   return (VSeries_rep*) new solver_container_series_rep<C,V> (f);
00522 }
00523 
00524 #undef TMPL_DEF
00525 #undef TMPL
00526 #undef Series
00527 #undef Series_rep
00528 #undef VC
00529 #undef VSeries
00530 #undef VSeries_rep
00531 #undef UC
00532 #undef UC_rep
00533 #undef Iseries
00534 #undef Iseries_rep
00535 #undef Solver_rep
00536 } // namespace mmx
00537 #endif // __MMX_SERIES_IMPLICIT_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines