realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/bernstein_eenv.hpp
Go to the documentation of this file.
00001 /********************************************************************
00002  *   This file is part of the source code of the realroot library.
00003  *   Author(s): J.P. Pavone, GALAAD, INRIA
00004  *   $Id: eenv.hpp,v 1.1 2005/07/11 10:03:55 jppavone Exp $
00005  ********************************************************************/
00006 #ifndef realroot_SOLVE_SBDSLV_BERNSTEIN_EENV_H
00007 #define realroot_SOLVE_SBDSLV_BERNSTEIN_EENV_H
00008 //--------------------------------------------------------------------
00009 #include <cstddef>
00010 #include <iostream>
00011 #include <realroot/loops_vctops.hpp>
00012 #include <realroot/loops_brnops.hpp>
00013 #include <realroot/loops_upoldse.hpp>
00014 #include <realroot/bernstein_bzenv.hpp>
00015 //--------------------------------------------------------------------
00016 namespace mmx {
00017 //--------------------------------------------------------------------
00018 #ifndef _valueof_ 
00019 #define _valueof_(x) std::cout << #x" = " << (x) << std::endl;
00020 #endif
00021 
00022 namespace bernstein
00023 {
00024   struct eenv_base
00025   {
00026     typedef int  sz_t;
00027     sz_t  m_nvr, * m_szs, * m_str;
00028   protected:
00029     inline void compute_strides()
00030     {
00031       m_str[m_nvr-1] = 1;    
00032       for ( int i = m_nvr-2; i >= -1; i-- ) m_str[i] = m_szs[i+1]*m_str[i+1];
00033     };
00034   public:
00035     eenv_base( sz_t nvr = 0 ) { m_nvr = nvr; };
00036     inline void   set_szs( sz_t * szs ) { m_szs = szs; compute_strides();  };    
00037     inline sz_t sz( sz_t v  ) const { return m_szs[v]; };
00038     inline sz_t nvars()     const { return m_nvr; };
00039     inline sz_t data_size() const { return m_str[-1]; };
00040 
00041     template<typename real_t>
00042     void hodograph( real_t * dst, real_t * src, int v  )
00043     {
00044       int i,j;
00045       int k;
00046       int kstr = (m_szs[v]-1)*m_str[v];
00047       for ( k = i = 0; i < data_size(); i += m_str[v-1], k += kstr )
00048         for ( j = 0; j < m_str[v]; j++ )
00049           brnops::hodograph(dst+k+j,src+i+j,m_szs[v],m_str[v]);
00050     };
00051     
00052     template<typename X, typename real_t>
00053     void copy( X * dst, real_t const * const src ) { std::copy(src, src + data_size(), dst ); };
00054     
00055     template<typename real_t>
00056     real_t eval( real_t * data,  const real_t *  prm, real_t * chunk =  0 )
00057     {
00058       sz_t i,j;
00059       real_t * tmp;
00060       if ( chunk ) tmp = chunk; 
00061       else tmp = new real_t[ data_size() ];
00062       std::copy(data,data+data_size(), tmp );
00063       for ( int v = nvars()-1; v >= 0 ; v -- )
00064         for ( i = 0; i <data_size(); i += m_str[v-1] )
00065           brnops::decasteljau(tmp+i,m_szs[v],prm[v],m_str[v]);
00066       real_t val = tmp[0];
00067       if ( !chunk ) delete[] tmp;
00068       return val;
00069     };
00070     
00071     template<typename real_t, typename X>
00072     void spmeval( X& res, real_t* src, X * prm, unsigned * supp, unsigned nsupp ) const
00073     {
00074       sz_t v, lg, d;
00075       unsigned i,add,o;
00076       lg = 0;
00077       for ( v = 0; v < m_nvr; v ++ ) if ( m_szs[v] > m_szs[lg] ) lg = v;
00078       X powers [m_nvr][m_szs[lg]];
00079       X acc;
00080       for ( v = 0; v < m_nvr; v ++ )
00081         for ( powers[v][0] = 1.0, d = 1; d < m_szs[v]; powers[v][d] = prm[v]*powers[v][d-1], d ++ );
00082       res = 0;
00083       for ( i = 0; i < nsupp; res += acc, i ++ )
00084         for ( add = supp[i], acc = src[add], v = m_nvr-1; add; add /= m_szs[v], v -- )
00085           acc *= powers[v][add%m_szs[v]];
00086     };
00087     
00088     
00089     template<typename real_t,typename X>
00090     void meval( X& res, real_t * data,  const X *  prm  ) const
00091     {
00092       sz_t i;
00093       X * tmp = new X[ data_size() ];
00094       std::copy(data,data+data_size(),tmp);
00095       for ( int v = nvars()-1; v >= 0 ; v -- )
00096         for ( i = 0; i < data_size(); i += m_str[v-1] )
00097           *(tmp+i) = univariate::horner(tmp+i,m_szs[v],prm[v],m_str[v]);
00098       res = tmp[0];
00099       delete[] tmp;
00100     };
00101     
00102     template<typename real_t>
00103     real_t monoms_eval( real_t * data,  const real_t *  prm  ) const
00104     {
00105       sz_t i;
00106       real_t * tmp = new real_t[ data_size() ];
00107       std::copy(data,data+data_size(), tmp );
00108       for ( int v = nvars()-1; v >= 0 ; v -- )
00109         for ( i = 0; i < data_size(); i += m_str[v-1] )
00110           *(tmp+i) = upoldse::horner(tmp+i,m_szs[v],prm[v],m_str[v]);
00111       real_t val = tmp[0];
00112       delete[] tmp;
00113       return val;
00114     };
00115     
00116      
00117     template<typename real_t>
00118     void mins( real_t * _mins_, real_t const * const data, sz_t v ) const 
00119     {
00120       sz_t p,k,i,j;
00121       for ( p = 0, k = 0; k < m_szs[v]; k++, p += m_str[v] )
00122         {
00123           _mins_[k] = data[p];
00124           for ( i = 0; i < data_size(); i += m_str[v-1] )
00125             for ( j = i; j < i + m_str[v]; j ++ )
00126               if ( data[j+p] < _mins_[k] ) _mins_[k] = data[j+p];
00127         };
00128     };
00129     
00130     template<typename real_t>
00131     void maxs( real_t * _maxs_, real_t const * const data, sz_t v ) const 
00132     {
00133       sz_t p,k,i,j;
00134 
00135       for ( p = 0, k = 0; k < m_szs[v]; k++, p += m_str[v] )
00136         {
00137           _maxs_[k] = data[p];
00138           for ( i = 0; i < data_size(); i += m_str[v-1] )
00139             for ( j = i; j < i + m_str[v]; j ++ )
00140               if ( data[j+p] > _maxs_[k] ) _maxs_[k] = data[j+p];
00141         };
00142     };
00143         
00144     template<typename real_t>
00145     inline void maxs( real_t * _maxs_, real_t const  * const data ) const 
00146     { for ( sz_t v = 0; v < m_nvr; v ++ ) { maxs(_maxs_,data,v); _maxs_ += m_szs[v];}; };
00147 
00148     template<typename real_t>
00149     inline void mins( real_t * _mins_, real_t const  * const data ) const 
00150     { for ( sz_t v = 0; v < m_nvr; v ++ ) { mins(_mins_,data,v); _mins_ += m_szs[v];}; };
00151 
00154     template<typename real_t> 
00155     void split( real_t * left, real_t * right, int v, const real_t& t )
00156     {
00157       int i,j,k;
00158       for ( i = 0; i < data_size(); i += m_str[v-1] )
00159         for ( j = i; j < i + m_str[v]; j++ )
00160           split(left+j,right+j,m_szs[v],m_str[v],t);
00161     };
00162   
00163     template<typename real_t>
00164     void split2( real_t * left, real_t * right, int v )
00165     {
00166       int i,j;
00167       for ( i = 0; i < data_size(); i += m_str[v-1] )
00168         for ( j = i; j < i + m_str[v]; j++ )
00169           split2(left+j,right+j,m_szs[v],m_str[v]);
00170     };
00171     
00172     template<typename real_t>
00173     void lrestrict( real_t * data, int v, const real_t& mn )
00174     {
00175       sz_t i,j;
00176       for ( i = 0; i < data_size(); i += m_str[v-1] )
00177         for ( j = i; j < i + m_str[v]; j++ )
00178           brnops::lrestrict(data+j,m_szs[v],mn,m_str[v]);
00179     };
00180     
00181     template<typename real_t>
00182     void rrestrict( real_t * data, int v, const real_t& mx )
00183     {
00184       int i,j;
00185       for ( i = 0; i < data_size(); i += m_str[v-1] )
00186         for ( j = i; j < i + m_str[v]; j++ )
00187           brnops::rrestrict(data+j,m_szs[v],mx,m_str[v]);
00188     };
00189  
00190     template<typename real_t>
00191     bool sgnchg( real_t * data ) { return vctops::sgnchg(data,data_size()); };
00192   
00193     template<typename real_t>
00194     inline void scale( real_t * data ) { vctops::scale(data,data_size()); };
00195     
00196 
00197     /* conversion sur [0,1]^n */
00198     
00199     /* monomiale -> bernstein */
00200     template< typename real_t >     /* conversion partielle */
00201     void fromMonoms( real_t * data, sz_t v, bzenv<real_t> * env = bzenv<real_t>::_default_ )
00202     {
00203       sz_t i,j;
00204       for ( i = 0; i < data_size(); i += m_str[v-1] )
00205         for ( j = i; j < i + m_str[v]; j++ )
00206           env->fromMonoms(data+j,m_szs[v],m_str[v]);
00207     };
00208     template< typename real_t >    /* conversion complete */
00209     inline void fromMonoms( real_t * data, bzenv<real_t> * env = bzenv<real_t>::_default_ ) { for ( sz_t v = 0; v < m_nvr; fromMonoms(data,v,env), v++ ); };
00210     
00211     /* bernstein -> monomiale */
00212     template< typename real_t >   /* conversion partielle */
00213     void toMonoms( real_t * data, sz_t v, bzenv<real_t> * env = bzenv<real_t>::_default_ )
00214     {
00215       sz_t i,j;
00216       for ( i = 0; i < data_size(); i += m_str[v-1] )
00217         for ( j = i; j < i + m_str[v]; j++ )
00218           env->toMonoms(data+j,m_szs[v],m_str[v]);
00219     };
00220     template< typename real_t >  /* conversion complete */
00221     inline void toMonoms(  real_t * data, bzenv<real_t> * env = bzenv<real_t>::_default_ ) { for ( sz_t v = 0; v < m_nvr; toMonoms(data,v,env), v ++ ); };
00222     
00223 //     template< typename real_t >
00224 //     void mshift( real_t * data, real_t * prm )
00225 //     {
00226 //       sz_t i,j;
00227 //       for ( i = 0; i < data_size(); i += m_str[v-1] )
00228 //      for ( j = i; j < i + m_str[v]; j++ )
00229 //        upoldse::shift(data+j,m_szs[v],m_str[v],prm[v]);
00230 //     };
00231 
00232     template< typename real_t >
00233     real_t flatness( real_t * data, int v )
00234     {
00235       real_t m = 10;
00236       sz_t i,j;
00237       for ( i = 0; i < data_size(); i += m_str[v-1] )
00238         for ( j = i; j < i + m_str[v]; j++ )
00239           std::max(m,flatness(data+j,m_szs[v],m_str[v]) );
00240       return m;
00241     };
00242   };
00243   
00244   
00245   //  eenv_base + dictionnaire local/global pour les variables
00246   struct eenv : public eenv_base
00247   {
00248     typedef eenv_base::sz_t sz_t;
00249     struct add
00250     {
00251       
00252     };
00253     sz_t * m_vrs;
00254     sz_t * m_pszs;
00255     sz_t   m_mxvr;
00256     void _alloc_( sz_t nvr )
00257     {
00258       m_nvr  = nvr;  
00259       m_szs  = new sz_t[4*m_nvr+2]; 
00260       m_vrs  = m_szs + m_nvr;
00261       m_str  = m_vrs + m_nvr + 1;
00262       m_pszs = m_str + m_nvr + 1;
00263     };
00264     eenv(){};
00265     eenv( sz_t szu, sz_t szv )
00266     {
00267       _alloc_(2);
00268       m_szs[0] = szu; m_szs[1] = szv;
00269       m_vrs[0] = 0; m_vrs[1] = 1;
00270       m_mxvr = 1;
00271       compute_strides();
00272       m_pszs[-1] = 0;
00273       for ( sz_t v = 0; v < m_nvr; v ++ )
00274         m_pszs[v] = m_pszs[v-1] + m_szs[v];
00275     };
00276     
00277     eenv( sz_t nvr, sz_t const * szs, sz_t const * vrs )
00278     {
00279       _alloc_(nvr);
00280       std::copy(szs,szs+m_nvr,m_szs);
00281       std::copy(vrs,vrs+m_nvr,m_vrs);
00282       compute_strides();
00283       m_pszs[-1] = 0;
00284       m_mxvr = m_vrs[0];
00285       for (sz_t v = 0; v < m_nvr; v ++ ) if ( m_vrs[v] > m_mxvr ) m_mxvr = m_vrs[v];
00286       for ( sz_t v = 0; v < m_nvr; v ++ )
00287         m_pszs[v] = m_pszs[v-1] + m_szs[v];
00288     };
00289     
00290     void swap( eenv& e )
00291     {
00292       std::swap(m_nvr,e_m.hpp_nvr);
00293       std::swap(m_szs,e_m.hpp_szs);
00294       std::swap(m_vrs,e_m.hpp_vrs);
00295       std::swap(m_pszs,e_m.hpp_pszs);
00296       std::swap(m_mxvr,e_m.hpp_mxvr);
00297     };
00298 
00299     sz_t psz(){ return m_pszs[m_nvr-1]; };
00300     sz_t psft( sz_t v ) { return m_pszs[v-1];}
00301     
00302     ~eenv()
00303     {
00304       if ( nvars() ) delete[] m_szs;
00305       m_nvr = 0;
00306     };
00307     
00308     sz_t stride( sz_t v ) const { return m_str[v]; };
00309     sz_t var ( sz_t v ) const { return m_vrs[v]; };
00310 
00311     int indexofvar( sz_t gv ) const 
00312     {
00313       //      if ( gv < m_vrs[0] ||  gv > m_vrs[m_nvr-1] ) return -1;
00314       // remplacer par dichotomie ?
00315       for ( sz_t v = 0; v < m_nvr; v ++ )
00316         if ( m_vrs[v] == gv ) return v;
00317       return -1;
00318     };
00319     
00320     /* operations */
00321     /* environement de diff(e,v), v est local a e */ 
00322     void diff( eenv * e, sz_t v )
00323     {
00324       if ( nvars () ) this->~eenv();
00325       _alloc_( e->nvars() );
00326       std::copy( e->m_vrs, e->m_vrs+e->nvars(), m_vrs );
00327       m_mxvr = e->m_mxvr;
00328       for  ( sz_t i = 0; i < m_nvr; m_szs[i] = e->sz(i), i ++ );
00329       m_szs[v]--;
00330       compute_strides();
00331     };
00332     
00333     template<typename real_t>
00334     static void mdiff( eenv * res, eenv * a, real_t * dst, real_t const * const src, int v )
00335     {
00336       sz_t is = 0;
00337       for ( sz_t i = 0; i < res->data_size(); i += res->m_str[v-1], is += a->m_str[v-1] )
00338         for ( sz_t j = 0; j < a->m_str[v]; j ++ )
00339           upoldse::diff(dst+i+j,src+is+j,a->sz(v),a->m_str[v]);
00340     };
00341     
00342     template<typename real_t>
00343     static void monoms_derivative(eenv * res, eenv * a, real_t ** dst, real_t ** src, int v, int n = 1 )
00344     {
00345       res->diff(a,v);
00346       for ( int c = 0; c < n; c ++ )
00347         {
00348           dst[c] = new real_t[ res->data_size() ];
00349           mdiff( res, a, dst[c], src[c], v );
00350         };
00351     };
00352     
00353 #include "bernstein_eenv_multiply.hpp"
00354 #include "bernstein_eenv_simplify.hpp"
00355     
00356     template<typename real_t>
00357     bool print_monom( std::ostream& o, const real_t& c, sz_t * add, bool first )
00358     {
00359       if ( c ) 
00360         {
00361           if ( c < 0 )  o << "-";
00362           else 
00363             if ( ! first ) o << "+";
00364           o << std::abs(c);
00365           for ( sz_t v = 0; v < nvars(); v ++ )
00366             if ( add[var(v)] ) o << "*x" << var(v) << "^" << add[var(v)];
00367           return true;
00368         };
00369       return false;
00370     };
00371     
00372     template<typename real_t>
00373     void monoms_print( std::ostream& o, real_t * src )
00374     {
00375       unsigned i;
00376       unsigned mcount = 0;
00377       int c;
00378       sz_t add[m_mxvr+1];
00379       std::fill(add,add+m_mxvr+1,0);
00380       bool first = true;
00381       for ( i = 0; i < data_size(); i ++ )
00382         {
00383           bool b = print_monom(o,src[i],add,first);
00384           if ( first && b ) first = false;
00385           mcount += b;
00386           c = nvars()-1;
00387           add[var(c)]++;
00388           while ( c >0 && (add[var(c)] == m_szs[c])) 
00389             { 
00390               add[var(c)] = 0;  
00391               c--; 
00392               add[var(c)]++; 
00393             };
00394         }
00395       if ( mcount == 0 ) o << "0";
00396     };
00397         
00398     
00399     
00400     
00401     template<typename real_t>
00402     static void elevation( eenv * out, eenv * in )
00403     {
00404       
00405     };
00406     template<typename real_t>
00407     static void elevation(  eenv * out, eenv * in, real_t * dst, real_t * src, bzenv< real_t > * bznv = bzenv<real_t>::_default_  )
00408     {
00409       sz_t io = 0;
00410       sz_t v  = 0;
00411       for ( sz_t i = 0; i < in->data_size(); i += in->m_str[v-1], io += out->m_str[v-1] )
00412         for ( sz_t j = 0; j < in->m_str[v]; j ++ )
00413           bznv->elevate( dst + io + j, src + i + j , in->m_szs[v], in->m_str[v], out->m_str[v], out->m_szs[v]-in->m_szs[v] );
00414     };
00415         
00416     #include "bernstein_eenv_vrestrict.hpp"
00417       
00418   };
00419   
00420   
00421   inline std::ostream& operator<<( std::ostream& out, const eenv& env )
00422   {
00423     out << "eenv:";
00424     out << "\n\tszs = ";
00425     vctops::print(env_m.hpp_szs,env_m.hpp_nvr,1,out);
00426     out << "\n\tvrs = ";
00427     vctops::print(env_m.hpp_vrs,env_m.hpp_nvr,1,out);
00428     out << "\n";
00429     out << "\n\ttsz = " << env.data_size() << std::endl;
00430     return out;
00431   };
00432 };
00433 //--------------------------------------------------------------------
00434 } //namespace mmx
00435 /********************************************************************/
00436 #endif //