realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/tensor_eenv_loops.hpp
Go to the documentation of this file.
00001 #ifndef realroot_tensor_eenvops_hpp
00002 #define realroot_tensor_eenvops_hpp
00003 
00004 #include <realroot/texp_sup.hpp>
00005 #include <realroot/tensor_vctops.hpp>
00006 #include <realroot/binomials.hpp>
00007 
00008 namespace mmx {
00009 
00010 namespace tensor
00011 {
00019   template < class R, class C, class eenv, class P >
00020   void levalm (R & result, const C * data, const eenv & env, const P & p)
00021   {
00022     typedef R result_type;
00023 
00024     // query for the environment information
00025 
00026     const int esz = env.sz ();  // number of coefficients
00027     const int nvr = env.nvr (); // number of variables 
00028     const int *szs = env.szs ();        // sizes in each variables
00029     const int *str = env.str ();        // corresponding strides.
00030 
00031     result_type tmp[env.sz ()], r;      // temporary array used by the inplace evaluation loop
00032     std::copy (data, data + env.sz (), tmp);
00033     for (int v = nvr - 1; v >= 0; v--)
00034       for (int i = 0; i < esz; i += str[v - 1]) {
00035         vct::horner(r,tmp + i, szs[v], p[v], str[v]);
00036         tmp[i] =  r;
00037       }
00038 //    let::assign(result,tmp[0]);
00039       result= tmp[0];
00040   };
00041 
00042   template < class R, class C, class eenv, class P >
00043   void hevalm (R & result, const C * data, const eenv & env, const P & p)
00044   {
00045     typedef R result_type;
00046 
00047     // query for the environment information
00048 
00049     const int esz = env.sz ();  // number of coefficients
00050     const int nvr = env.nvr (); // number of variables 
00051     const int *szs = env.szs ();        // sizes in each variables
00052     const int *str = env.str ();        // corresponding strides.
00053 
00054     result_type tmp[env.sz ()],r;   // temporary array used by the inplace evaluation loop
00055     std::copy (data, data + env.sz (), tmp);
00056     for (int v = nvr - 1; v >= 0; v--)
00057       for (int i = 0; i < esz; i += str[v - 1]) {
00058         vct::hhorner(r,tmp + i, szs[v], p[v+1],p[0],str[v]);
00059         tmp[i] =  r;
00060       }
00061 
00062     let::assign(result,tmp[0]);
00063 
00064   };
00065 
00066   template<typename real_t, typename value_t>
00067   void decasteljau( real_t * r, unsigned sz, const value_t& t, int str = 1 )
00068   {
00069     real_t *er, *p;
00070       for ( er = r + (sz-1)*str; er != r; er -= str )
00071         for ( p = r; p != er; p += str )
00072           *p = real_t(value_t(1)-t)* *p+t**(p+str);
00073   };  
00074 
00076   template < class R, class C, class eenv, class P >
00077   void levalb (R & result, const C * data, const eenv & env, const P & p)
00078   {
00079     //    typename sup<typename texp::value_type<P>::result_t, C >::T tmp[env.sz()];
00080     //XXX    typename texp::ringof_ < typename texp::value_type<P>::T,C >::T
00081 
00082     R tmp[env.sz()];
00083 
00084     const int esz  (env.sz ());
00085     const int nvr  (env.nvr ());
00086     const int *szs (env.szs ());
00087     const int *str (env.str ());
00088 
00089     std::copy (data, data + env.sz (), tmp);
00090 
00091     for (int v = nvr - 1; v >= 0; v--)
00092       for (int i = 0; i < esz; i += str[v - 1])
00093         decasteljau (tmp + i, szs[v], p[v], str[v]);
00094 
00095     let::assign(result,tmp[0]);
00096   };
00097 
00098   
00099 
00100   template < class OutputIterator, class C, class eenv  >
00101   void maxs (OutputIterator _maxs_, const C * data, const eenv & env, int v)
00102   {
00103     const int *eszs = env.szs ();
00104     const int *estr = env.str ();
00105     //    const int envr = env.nvr ();
00106     int p, k, i; //, j;
00107     for (p = 0, k = 0; k < eszs[v]; k++, data += estr[v], _maxs_++)
00108       {
00109         *_maxs_ = *data;
00110         for (i = 0; i < estr[-1]; i += estr[v - 1])
00111           for (const C * edata = data + i; edata < data + i + estr[v]; edata++)
00112             if (*edata > *_maxs_)
00113               *_maxs_ = *edata;
00114       };
00115   };
00116   
00117   template < class OutputIterator, class C, class eenv >
00118   void mins (OutputIterator _mins_, const C * data, const eenv & env, int v)
00119   {
00120     const int *eszs = env.szs ();
00121     const int *estr = env.str ();
00122     //    const int envr = env.nvr ();
00123     int p, k, i, j;
00124     for (p = 0, k = 0; k < eszs[v]; k++, p += estr[v], _mins_++)
00125       {
00126         *_mins_ = data[p];
00127         for (i = 0; i < estr[-1]; i += estr[v - 1])
00128           for (j = i; j < i + estr[v]; j++)
00129             if (data[j + p] < *_mins_)
00130               *_mins_ = data[j + p];
00131       };
00132   };
00133 
00134   
00135 
00136   template < class C, class eenv >
00137   void vswap( C * data, const eenv & env, int *perm, int *supp = 0, int nsupp = 0  )
00138   {
00139     const int *szs = env.szs ();
00140     const int *str = env.str ();
00141     int ostr[env.nvr ()];
00142     int i;
00143     for (i = env.nvr () - 2, str[env.nvr () - 1] = 1; i >= -1;
00144          ostr[i] = szs[perm[i + 1]] * str[i + 1], i--) ;
00145     if (supp == 0)
00146       {
00147         int a, o, v;
00148         for (i = 0; i < env.esz (); i++)
00149           {
00150             for (a = i, v = env.nvr () - 1; a; a /= szs[v], v--)
00151               o += (a % szs[v]) * ostr[perm[v]];
00152             std::swap (data[i], data[o]) ;
00153           };
00154       }
00155     else
00156       {
00157         int a, o, v;
00158         for (i = 0; i < nsupp; supp[i++] = o)
00159           {
00160             for (a = supp[i], v = env.nvr () - 1; a; a /= szs[v], v--)
00161               o += (a % szs[v]) * ostr[perm[v]];
00162             std::swap (data[i], data[o]);
00163           };
00164       };
00165     env.vswap (perm);
00166   };
00167   
00168 
00169   template < class C, class eenv  >
00170   void binoms (C * data, const eenv & env, binomials < C > & binms)
00171   {
00172     const int *estr = env.str ();
00173     const int *eszs = env.szs ();
00174     const int envr = env.nvr ();
00175     const int esz = env.sz ();
00176     const C *bins = binms[eszs[envr - 1] - 1];
00177     for (C * pdata = data; pdata < data + esz; pdata += estr[envr - 2])
00178       vct::copy (pdata, bins, eszs[envr - 1]);
00179     for (int v = 0; v < envr - 1; v++)
00180       {
00181         bins = binms[eszs[v] - 1];
00182         //      int k = 0;
00183         for (int i = 0; i < esz; i += estr[v - 1])
00184           for (int j = 0; j < estr[v]; j++)
00185             vct::pmul (data + i + j, bins, eszs[v], estr[v], 1);
00186       };
00187   };
00188   
00189   template < class C >
00190   void ibinoms (C * data, const eenv & env, binomials < C > & binms)
00191   {
00192     binoms(data,env,binms);
00193     vct::inverses(data,data+env.sz());
00194   };
00195   
00197   template < class C, class eenv >
00198   void scale (C * data, const eenv & env, binomials < C > &binoms)
00199   {
00200     const int *estr = env.str ();
00201     const int *eszs = env.szs ();
00202     const int  envr = env.nvr ();
00203     const int  esz  = env.sz ();
00204     const C *  bins = binoms[eszs[envr - 1] - 1];
00205     
00206     for (C *  pdata = data; pdata < data + esz; vct::pmul (pdata, bins, eszs[envr - 1]), pdata += estr[envr - 2]) ;
00207     
00208     for (int v = 0; v < envr - 1; v++)
00209       {
00210         bins = binoms[eszs[v] - 1];
00211         //      int k = 0;
00212         for (int i = 0; i < esz; i += estr[v - 1])
00213           for (int j = 0; j < estr[v]; j++)
00214             vct::pmul (data + i + j, bins, eszs[v], estr[v], 1);
00215       };
00216   };
00217   
00219   template < class C, class eenv >
00220   void uscale (C * data, const eenv & env, binomials < C > &binoms)
00221   {
00222     const int *estr = env.str ();
00223     const int *eszs = env.szs ();
00224     const int envr = env.nvr ();
00225     const int esz = env.sz ();
00226     const C *bins = binoms[eszs[envr - 1] - 1];
00227     for (C * pdata = data; pdata < data + esz; pdata += estr[envr - 2])
00228       vct::pdiv (pdata, bins, eszs[envr - 1]);
00229     for (int v = 0; v < envr - 1; v++)
00230       {
00231         bins = binoms[eszs[v] - 1];
00232         //      int k = 0;
00233         for (int i = 0; i < esz; i += estr[v - 1])
00234           for (int j = 0; j < estr[v]; j++)
00235             vct::pdiv (data + i + j, bins, eszs[v], estr[v], 1);
00236       };
00237   };
00238 
00239   template<class C> inline
00240   void convertb2m( C * bzc, unsigned sz, int st, binomials<C>& binom ) {
00241     int i,k;
00242     for ( i = st; i != st*int(sz); i += st )
00243     for ( k = (sz-1)*st; k != i-st; k -= st )
00244       bzc[k] -= bzc[k-st];
00245     vct::pmul(bzc,binom[sz-1],sz,st,1);
00246   };
00247   
00248 
00249   template<class C> inline
00250   void convertm2b( C * bzc, unsigned sz, int st, binomials<C>& binoms ) {
00251     C tmp[sz];
00252     const C * bin;
00253     unsigned i,k,p,l;
00254     
00255     for ( p = 0, i = 0; i < sz; i++, p += st ) 
00256       { tmp[i] = bzc[p]; bzc[p] = C(0); };
00257     for ( p = 0, i = 0; i < sz; i++, p += st )
00258       for ( bin = binoms[sz-i-1], l = p, k = 0; k < sz-i; k++, l += st )
00259         bzc[l] += tmp[i]*bin[k];
00260     bin = binoms[sz-1];
00261     for ( i = 0, l = 0; i < sz; i ++, l += st  )
00262       bzc[l] /= bin[i];
00263   };
00264   
00268   template < class C, class eenv >
00269   void convertm2b (C * data, const eenv & e, binomials < C > &bins, int v)
00270   {
00271     const int *esz = e.szs ();
00272     const int *est = e.str ();
00273     int i, j;
00274     for (i = 0; i < e.sz (); i += est[v - 1])
00275       for (j = i; j < i + est[v]; convertm2b (data + j, esz[v], est[v], bins), j++) ;
00276   };
00277   
00279   template < class C, class eenv >
00280   void convertm2b (C * data, const eenv & env, binomials < C > &bins)
00281   {
00282     for (int v = 0; v < env.nvr (); convertm2b (data, env, bins, v++)) ;
00283   };
00284   
00288   template < class C, class eenv >
00289   void convertb2m (C * data, const eenv & e, binomials < C > &bins, int v)
00290   {
00291     const int *esz = e.szs ();
00292     const int *est = e.str ();
00293     int i, j;
00294     for (i = 0; i < e.sz (); i += est[v - 1])
00295       for (j = i; j < i + est[v];
00296            convertb2m (data + j, esz[v], est[v], bins), j++) ;
00297   };
00298   
00300   template < class C, class eenv  >
00301   void convertb2m (C * data, const eenv & env, binomials < C > &bins)
00302   {
00303     for (int v = 0; v < env.nvr (); convertb2m (data, env, bins, v++)) ;
00304   };
00305 
00306 
00307 
00308 
00309 
00310   template<typename C> inline 
00311   void diff( C * b, const C * a, unsigned sz, int sb, int sa )
00312   {
00313     assert(sa==sb);
00314     for ( unsigned i = 1; i < sz; i ++ ) { b[(i-1)*sb] = i*a[i]; };
00315     //    for ( unsigned i = 1, a += sa; i < sz; *b = *a*i++, b += sb, a += sa ) ; 
00316   };
00317   
00318   template<typename C> inline /* differentiation */
00319   void diff( C * b, C * e, C const * a, int s )
00320   { 
00321     unsigned i;
00322     for ( i = 1, a += s; b != e; *b = *a*i++, b += s, a += s ) ;
00323   };
00324 
00325   template<typename C> inline /* differentiation */
00326   void diff( C * b, C * e, C const * a )
00327   { 
00328     for ( int i = 1; b != e; *b++ = *(++a)*i++ ) ;
00329   };
00330 
00331 
00332   template<typename C>
00333   void m_diff( C * op, const eenv& o, C const * ap, const eenv& a, int v )
00334   {
00335     typedef int sz_t;
00336     sz_t is = 0;
00337     for ( sz_t i = 0; i < o.sz(); i += o.st(v-1), is += a.st(v-1) )
00338       for ( sz_t j = 0; j < a.st(v); j ++ )
00339         diff(op+i+j, ap+is+j,a.sz(v), o.st(v), a.st(v)) ;
00340   };
00341 
00342   template<typename C>
00343   void mdiff( C * dst, const eenv& a, C const * const src, const eenv& esrc, int v )
00344   {
00345     const int   ssz  = esrc.sz ();
00346     //    const int * sszs = a.szs();
00347     const int * sstr = esrc.str();
00348     int rst = sstr[v-1]-sstr[v];
00349     unsigned i;
00350     C * ed, * fd;
00351     const C * es, * fs;
00352     for ( ed = dst, es = src; es < src+ssz; ed += rst, es += sstr[v-1] )
00353       for ( i = 1, fd = ed, fs = es+sstr[v]; fs != es+sstr[v-1]; fd += sstr[v], fs += sstr[v], i ++  )
00354         vct::scmul(fd,fd+sstr[v],fs,C(i));
00355   }
00356 
00357   
00358   
00359   template<typename C>
00360   static void bdiff( C * dst, const eenv& a, C const * const src, int v )
00361   {
00362     const int   ssz  = a.sz ();
00363     const int * sszs = a.szs();
00364     const int * sstr = a.str();
00365     int rst = sstr[v-1]-sstr[v];
00366     //    unsigned i;
00367     C * ed; const C * es;
00368     for ( ed = dst, es = src; es < src+ssz; ed += rst, es += sstr[v-1] )
00369       {
00370         C * fd; const C * fs;
00371         for ( fs = es, fd = ed; fs < es + sstr[v]; fs++, fd ++ )
00372           {
00373             C * dp; const C * p;
00374             for ( p = fs, dp = fd; p < fs+rst; p += sstr[v], dp += sstr[v] )
00375               *dp = (*(p+sstr[v])-*p)*(sszs[v]-1);
00376           };
00377       };
00378   }
00379   
00380   template<class C, class T> inline 
00381   void bsplit_uloop( C * r, C * rlast, C * l, const T& t, int st )
00382   {
00383     C * er, * p;
00384     for ( er = rlast - st ; er != r; er -= st, l += st )
00385       {
00386         *l = *r;
00387         for ( p = r; p != er; p += st )
00388           *p = (1.0-t)**p+t**(p+st);
00389       };
00390     *l = *r;
00391   };
00392   
00393   template < class C, class eenv, class T> inline
00394   void bsplit (C * l, C * r, const eenv & env, const T & t, int v )
00395   {
00396     //  const int *sszs = env.szs ();
00397     const int *sstr = env.str ();
00398     //  int i, j, k;
00399     C *er,*el;
00400     for ( el = l, er = r; el != l + sstr[-1]; el += sstr[v-1], er += sstr[v-1] )
00401       {
00402         C *fr,*fl;
00403         for ( fl = el, fr = er; fl != el + sstr[v]; fl++, fr++ )
00404           bsplit_uloop(fr,fr+sstr[v-1],fl,t,sstr[v]) ;
00405       };
00406   };
00407   
00408   
00409   template<class C> inline 
00410   void bsplit2_uloop( C * r, C * rlast, C * l,  int st )
00411   {
00412     C * er, * p;
00413     for ( er = rlast - st ; er != r; er -= st, l += st )
00414       {
00415         *l = *r;
00416         for ( p = r; p != er; p += st )
00417           *p = (*p+*(p+st))/C(2);
00418       };
00419     *l = *r;
00420   };
00421 
00422   template < class C, class eenv > 
00423   void bsplit2 (C * l, C * r, const eenv & env, int v )
00424   {
00425     //    const int *sszs = env.szs ();
00426     const int *sstr = env.str ();
00427     C *er,*el;
00428     for ( el = l, er = r; el != l + sstr[-1]; el += sstr[v-1], er += sstr[v-1] )
00429       {
00430         C *fr,*fl;
00431         for ( fl = el, fr = er; fl != el + sstr[v]; fl++, fr++ )
00432           bsplit2_uloop(fr,fr+sstr[v-1],fl,sstr[v]);
00433       };
00434   };
00435 
00436   
00437   template<class C,class T> inline 
00438   void brestrict_uloop( C * r, C * rlast, int st, const T& a, const T& b  )
00439   {
00440     C * er, * p;
00441     for ( er = rlast - st ; er != r; er -= st )
00442       for ( p = r; p != er; p += st )
00443         *p = (a**p+b**(p+st));
00444   };
00445   
00446 
00447 
00448   template<class C, class T> inline
00449   void brestrictLR  (C * s, const eenv & env, int v, const T& a, const T& b, const T& c, const T& d  )
00450   {
00451     //    std::cout << a << " " << b << std::endl;
00452     //    std::cout << c << " " << d << std::endl;
00453     //    const int *sszs = env.szs ();
00454     const int *sstr = env.str ();
00455     //    int i, j, k;
00456     for ( C * es = s; es != s + sstr[-1]; es += sstr[v-1] )
00457       for ( C * fs = es; fs != es + sstr[v]; fs ++ )
00458         {
00459           brestrict_uloop(fs,fs+sstr[v-1],sstr[v],a,b);
00460           brestrict_uloop(fs+sstr[v-1]-sstr[v],fs-sstr[v],-sstr[v],c,d);
00461         };
00462   };
00463 
00464   template<class C, class T> inline
00465   void brestrictRL  (C * s, const eenv & env, int v, const T& a, const T& b, const T& c, const T& d  )
00466   {
00467     //    std::cout << a << " " << b << std::endl;
00468     //    std::cout << c << " " << d << std::endl;
00469    
00470     
00471 
00472     //    const int *sszs = env.szs ();
00473     const int *sstr = env.str ();
00474     //    int i, j, k;
00475     for ( C * es = s; es != s + sstr[-1]; es += sstr[v-1] )
00476       for ( C * fs = es; fs != es + sstr[v]; fs ++ )
00477         {
00478           brestrict_uloop(fs+sstr[v-1]-sstr[v],fs-sstr[v],-sstr[v],c,d);        
00479           brestrict_uloop(fs,fs+sstr[v-1],sstr[v],a,b);
00480         };
00481   };
00482 
00483   template<class C, class eenv, class T > inline
00484   void  brestrict( C * src, const eenv& env, int v, const T& a, const T& b )
00485   {
00486     brestrictLR   ( src, env, v, T(1-a), a, T((b-a)/(T(1)-a)), T((T(1)-b)/(T(1)-a)) );
00487   };
00488 
00489 
00490   template<class C>
00491   void lface( C * dst, const eenv& a, const C * src, int v )
00492   {
00493     const int   ssz  = a.sz ();
00494     //    const int * sszs = a.szs();
00495     const int * sstr = a.str();
00496 
00497     C * ed; const C * es;
00498     const C * fs;
00499     for ( ed = dst, es = src; es < src+ssz; es += sstr[v-1] )
00500       for ( fs = es; fs < es + sstr[v]; *ed++ = *fs++ ) ;
00501   };
00502 
00503   template<class C>
00504   void rface( C * dst, const eenv& a, const C * src, int v )
00505   {
00506     const int   ssz  = a.sz ();
00507     //    const int * sszs = a.szs();
00508     const int * sstr = a.str();
00509 
00510     C * ed; const C * es;
00511     const C * fs;
00512     es = src +  sstr[v-1]-sstr[v];
00513     for ( ed = dst; es < src+ssz; es += sstr[v-1] )
00514       {
00515         for ( fs = es; fs < es + sstr[v]; *ed++ = *fs++ ) ;
00516       };
00517   };
00518 
00519   template<class C>
00520   void slice( C * dst, const eenv& a, const C * src, int v, int n)
00521   {
00522     const int   ssz  = a.sz ();
00523     const int * sstr = a.str();
00524 
00525     C * ed; const C * es;
00526     const C * fs;
00527     es = src +  sstr[v-1]-sstr[v];
00528     for ( ed = dst; es < src+ssz; es += sstr[v-1] )
00529       {
00530         //      fs = es + sstr[v-1] - sstr[v];
00531         for ( fs = es; fs < es + sstr[v]; *ed++ = *fs++ ) ;
00532       };
00533   };
00534 
00535   template<class C, class X, class O, class eenv >
00536   void mpolfill( C * data, const sparse::monomial_seq<X,O>& mpol, const eenv& env )
00537   {
00538     const int *vr = env.vrs ();
00539     const int *st = env.str ();
00540     const int  nvr = env.nvr();
00541     typename sparse::monomial_seq<X,O>::const_iterator it;
00542     C c;
00543     for (it =mpol.begin (); it != mpol.end (); it++)
00544       {
00545         int a = 0;
00546         for (int v = 0; v < nvr; a += (*it)[vr[v]] * st[v], v++) ;
00547         let::assign(c,(*it).coeff ());
00548         data[a] += c;
00549       };
00550   }
00551 }
00552 
00553 } //namespace mmx
00554 #endif