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