MC++
~tmodel.hpp
00001 // Copyright (C) 2009-2013 Benoit Chachuat, Imperial College London.
00002 // All Rights Reserved.
00003 
00378 #ifndef MC__TMODEL_H
00379 #define MC__TMODEL_H
00380 
00381 #include <iostream>
00382 #include <iomanip>
00383 #include <typeinfo>
00384 #include <sstream>
00385 #include <string>
00386 #include <stdarg.h>
00387 #include <cassert>
00388 #include <climits>
00389 #include <stdlib.h>
00390 #include <complex>
00391 
00392 #include "mcfunc.hpp"
00393 #include "mcop.hpp"
00394 
00395 #undef  MC__TMODEL_DEBUG
00396 #undef  MC__TMODEL_DEBUG_SCALE
00397 #define MC__TMODEL_CHECK
00398 #undef  MC__TVAR_DEBUG_EXP
00399 #undef  MC__TVAR_DEBUG_EIGEN
00400 #undef  MC__TVAR_DEBUG_BERSTEIN
00401 #undef  MC__TVAR_HYBRID_EIGEN
00402 
00403 extern "C" void dsyev_
00404 ( const char*jobz, const char*uplo, const unsigned int*n, double*a,
00405   const unsigned int*lda, double*w, double*work, const int*lwork, int*info );
00406 
00407 namespace mc
00408 {
00409 
00410 template <typename T> class TVar;
00411 typedef unsigned long long TM_size;
00412 
00420 template <typename T>
00421 class TModel
00423 {
00424   friend class TVar<T>;
00425   template <typename U> friend class TModel;
00426 
00427   template <typename U> friend TVar<U> inv
00428     ( const TVar<U>& );
00429   template <typename U> friend TVar<U> sqrt
00430     ( const TVar<U>& );
00431   template <typename U> friend TVar<U> log
00432     ( const TVar<U>& );
00433   template <typename U> friend TVar<U> exp
00434     ( const TVar<U>& );
00435   template <typename U> friend TVar<U> pow
00436     ( const TVar<U>&, const int );
00437     
00438 public:
00439 
00443 
00444   TModel
00445     ( const unsigned int nvar, const unsigned int nord )
00446     { _size( nvar, nord ); }
00448 
00449   ~TModel()
00450     { _cleanup(); }
00451 
00453   unsigned int nvar() const
00454     { return _nvar; };
00455 
00457   unsigned int nord() const
00458     { return _nord; };
00459 
00461   unsigned int nmon() const
00462     { return _nmon; };
00463 
00465   const T* bndmon() const
00466     { return _bndmon; };
00467 
00469   const unsigned int* expmon() const
00470     { return _expmon; };
00471 
00473   unsigned int loc_expmon
00474     ( const unsigned int *iexp ) const
00475     { return _loc_expmon( iexp ); }
00476 
00478   class Exceptions
00479   {
00480   public:
00482     enum TYPE{
00483       DIV=1,   
00484       EIGEN,   
00485       BERNSTEIN,
00486       SIZE=-1, 
00487       INIT=-2, 
00488       INCON=-3, 
00489       TMODEL=-4,
00490       MAXSIZE=-5,
00491       UNDEF=-33 
00492     };
00494     Exceptions( TYPE ierr ) : _ierr( ierr ){}
00496     int ierr(){ return _ierr; }
00498     std::string what(){
00499       switch( _ierr ){
00500       case DIV:
00501         return "mc::TModel\t Division by zero scalar";
00502       case EIGEN:
00503         return "mc::TModel\t Range bounder with eigenvalue decomposition failed";
00504       case BERNSTEIN:
00505         return "mc::TModel\t Bernstein remainder evalution failed";
00506       case SIZE:
00507         return "mc::TModel\t Inconsistent Taylor model dimension";
00508       case INIT:
00509         return "mc::TModel\t Taylor variable initialization failed";
00510       case INCON:
00511         return "mc::TModel\t Inconsistent bounds with template parameter arithmetic";
00512       case TMODEL:
00513         return "mc::TModel\t Operation between Taylor variables in different Taylor model environment not allowed";
00514       case MAXSIZE:
00515         return "mc::TModel\t Maximum size in Taylor model reached";
00516       case UNDEF:
00517         return "mc::Specbnd\t Feature not yet implemented in mc::Specbnd class";
00518       default:
00519         return "mc::TModel\t Undocument error";
00520       }
00521       }
00522       return "mc::TModel\t Undocument error";
00523     }
00524 
00525   private:
00526     TYPE _ierr;
00527   };
00528 
00530   struct Options
00531   {
00533     Options():
00534       BOUNDER_TYPE(LSB), BOUNDER_ORDER(0), PROPAGATE_BNDT(false),
00535       INTER_WITH_BNDT(false), SCALE_VARIABLES(false), CENTER_REMAINDER(false),
00536       REF_MIDPOINT(true), REF_POLY(0.), BERNSTEIN_USE(false),
00537       BERNSTEIN_OPT(true), BERNSTEIN_MAXIT(100), BERNSTEIN_TOL(1e-10),
00538       DISPLAY_DIGITS(5)
00539       {}
00541     template <typename U> Options
00542       ( U&options )
00543       : BOUNDER_TYPE( options.BOUNDER_TYPE ),
00544         BOUNDER_ORDER( options.BOUNDER_ORDER ),
00545         PROPAGATE_BNDT( options.PROPAGATE_BNDT ),
00546         INTER_WITH_BNDT( options.INTER_WITH_BNDT ),
00547         SCALE_VARIABLES( options.SCALE_VARIABLES ),
00548         CENTER_REMAINDER( options.CENTER_REMAINDER ),
00549         REF_MIDPOINT( options.REF_MIDPOINT ),
00550         REF_POLY(options.REF_POLY),
00551    BERNSTEIN_USE(options.BERNSTEIN_USE),
00552    BERNSTEIN_OPT(options.BERNSTEIN_OPT),
00553         BERNSTEIN_MAXIT(options.BERNSTEIN_MAXIT),
00554    BERNSTEIN_TOL(options.BERNSTEIN_TOL),
00555    DISPLAY_DIGITS(options.DISPLAY_DIGITS)
00556       {}
00558     template <typename U> Options& operator =
00559       ( U&options ){
00560         BOUNDER_TYPE     = options.BOUNDER_TYPE;
00561         BOUNDER_ORDER    = options.BOUNDER_ORDER;
00562         PROPAGATE_BNDT   = options.PROPAGATE_BNDT;
00563         INTER_WITH_BNDT  = options.INTER_WITH_BNDT;
00564         SCALE_VARIABLES  = options.SCALE_VARIABLES;
00565         CENTER_REMAINDER = options.CENTER_REMAINDER;
00566         REF_MIDPOINT     = options.REF_MIDPOINT,
00567         REF_POLY         = options.REF_POLY,
00568    BERNSTEIN_USE    = options.BERNSTEIN_USE,
00569    BERNSTEIN_OPT    = options.BERNSTEIN_OPT,
00570         BERNSTEIN_MAXIT  = options.BERNSTEIN_MAXIT,
00571    BERNSTEIN_TOL    = options.BERNSTEIN_TOL,
00572    DISPLAY_DIGITS   = options.DISPLAY_DIGITS;
00573         return *this;
00574       }
00576     enum BOUNDER{
00577       NAIVE=0, 
00578       LSB,  
00579       EIGEN,   
00580       BERNSTEIN,
00581       HYBRID   
00582     };
00584     int BOUNDER_TYPE;
00586     unsigned int BOUNDER_ORDER;
00588     static const std::string BOUNDER_NAME[5];
00590     bool PROPAGATE_BNDT;
00592     bool INTER_WITH_BNDT;
00594     bool SCALE_VARIABLES;
00596     bool CENTER_REMAINDER;
00598     bool REF_MIDPOINT;
00600     double REF_POLY;
00602     unsigned int BERNSTEIN_ORDER;
00604     bool BERNSTEIN_USE;
00606     bool BERNSTEIN_OPT;
00608     unsigned int BERNSTEIN_MAXIT;
00610     double BERNSTEIN_TOL;
00612     unsigned int DISPLAY_DIGITS;
00613   } options;
00616 
00617   static void pause();
00618 
00619 private:  
00621   unsigned int _nord;
00623   unsigned int _nvar;
00625   unsigned int _nmon;
00627   unsigned int *_posord;
00629   unsigned _posord_size;
00631   unsigned int *_expmon;
00633   unsigned _expmon_size;
00635   unsigned int **_prodmon;
00637   T *_bndmon;
00639   bool _modvar;
00641   TM_size *_binom;
00643   std::pair<unsigned int, unsigned int> _binom_size;
00645   T **_bndpow;
00647   double *_refpoint;
00649   double *_scaling; 
00651   double *_cbern; 
00652 
00654   TVar<T>* _TV;
00655 
00657   void _size
00658     ( const unsigned int nvar, const unsigned int nord );
00659 
00661   void _set_bndpow
00662     ( const unsigned int ivar, const T&X, const double Xref,
00663       const double scaling );
00664 
00666   void _set_bndmon();
00667 
00669   void _set_posord
00670     ( const unsigned int nord );
00671 
00673   void _ext_posord
00674     ( const unsigned int maxord );
00675 
00677   void _set_expmon
00678     ( const unsigned int nord );
00679 
00681   void _ext_expmon
00682     ( const unsigned int maxord, const bool full=false );
00683   
00685   void _next_expmon
00686     ( unsigned int *iexp, const unsigned int iord ) const;
00687 
00689   void _set_prodmon();
00690     
00692   unsigned int _loc_expmon
00693     ( const unsigned int *iexp ) const;
00694     
00696   void _set_binom
00697     ( const unsigned int nord );
00698     
00700   void _ext_binom
00701     ( const unsigned int nord );
00702 
00704   TM_size _get_binom
00705     ( const unsigned int n, const unsigned int k ) const;
00706 
00708   void _scale
00709     ( const unsigned int ivar, double*coef ) const;
00710       
00712   void _reset();
00713 
00715   void _cleanup();
00716 
00718   template< typename U > static void _display
00719     ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda,
00720       const std::string&stra, std::ostream&os );
00721     
00723   typedef double (puniv)
00724     ( const double x, const double*rusr, const int*iusr );
00725     
00727   typedef double (punivopt)
00728     ( const double x, const double*rusr, const int*iusr, puniv df,
00729       const T&I,  const std::pair<unsigned int,const double*>&bern );
00730 
00732   typedef T (punivext)
00733     ( const T&x, const double*rusr, const int*iusr );
00734 
00736   TVar<T> _univ_bernstein
00737     ( const TVar<T>&TV, puniv f, puniv df, punivext If,
00738       punivext d2If, const double*rusr, const int*iusr );
00739 
00741   static double _gap_bernstein
00742     ( const double x, const double*rusr, const int*iusr, puniv df,
00743       const T&I, const std::pair<unsigned int,const double*>&bern );
00744 
00746   static double _dgap_bernstein
00747     ( const double x, const double*rusr, const int*iusr, puniv df,
00748       const T&I, const std::pair<unsigned int,const double*>&bern );
00749 
00751   double _goldsect
00752     ( const double xL, const double xU, punivopt fopt, const double*rusr,
00753       const int*iusr, puniv df,  const T&Ix,
00754       const std::pair<unsigned int,const double*>&bern );
00755 
00757   double _goldsect_iter
00758     ( const bool init, const double a, const double fa, const double b,
00759       const double fb, const double c, const double fc, punivopt fopt,
00760       const double*rusr, const int*iusr, puniv df, const T&Ix,
00761       const std::pair<unsigned int,const double*>&bern );
00762 
00764   TVar<T> _intpow
00765     ( const TVar<T>&TV, const int n );
00766 
00768   TVar<T> _inv_taylor
00769     ( const TVar<T>&TV );
00770 
00772   TVar<T> _inv_bernstein
00773     ( const TVar<T>&TV );
00774 
00776   TVar<T> _sqrt_taylor
00777     ( const TVar<T>&TV );
00778 
00780   TVar<T> _sqrt_bernstein
00781     ( const TVar<T>&TV );
00782 
00784   TVar<T> _exp_taylor
00785     ( const TVar<T>&TV );
00786 
00788   TVar<T> _exp_bernstein
00789     ( const TVar<T>&TV );
00790 
00792   TVar<T> _log_taylor
00793     ( const TVar<T>&TV );
00794 
00796   TVar<T> _log_bernstein
00797     ( const TVar<T>&TV );
00798 
00800   static double* _eigen
00801     ( const unsigned int n, double*a );
00802 } ;
00803 
00804 template <typename T> const std::string TModel<T>::Options::BOUNDER_NAME[5]
00805   = { "NAIVE", "LSB", "EIGEN", "BERNSTEIN", "HYBRID" };
00806 
00813 template <typename T>
00814 class TVar
00816 {
00817   template <typename U> friend class TVar;
00818   template <typename U> friend class TModel;
00819 
00820   template <typename U> friend TVar<U> operator+
00821     ( const TVar<U>& );
00822   template <typename U, typename V> friend TVar<U> operator+
00823     ( const TVar<U>&, const TVar<V>& );
00824   template <typename U, typename V> friend TVar<U> operator+
00825     ( const TVar<U>&, const V& );
00826   template <typename U, typename V> friend TVar<U> operator+
00827     ( const V&, const TVar<U>& );
00828   template <typename U> friend TVar<U> operator+
00829     ( const double, const TVar<U>& );
00830   template <typename U> friend TVar<U> operator+
00831     ( const TVar<U>&, const double );
00832   template <typename U> friend TVar<U> operator-
00833     ( const TVar<U>& );
00834   template <typename U, typename V> friend TVar<U> operator-
00835     ( const TVar<U>&, const TVar<V>& );
00836   template <typename U, typename V> friend TVar<U> operator-
00837     ( const TVar<U>&, const V& );
00838   template <typename U, typename V> friend TVar<U> operator-
00839     ( const V&, const TVar<U>& );
00840   template <typename U> friend TVar<U> operator-
00841     ( const double, const TVar<U>& );
00842   template <typename U> friend TVar<U> operator-
00843     ( const TVar<U>&, const double );
00844   template <typename U> friend TVar<U> operator*
00845     ( const TVar<U>&, const TVar<U>& );
00846   template <typename U> friend TVar<U> operator*
00847     ( const double, const TVar<U>& );
00848   template <typename U> friend TVar<U> operator*
00849     ( const TVar<U>&, const double );
00850   template <typename U> friend TVar<U> operator*
00851     ( const U&, const TVar<U>& );
00852   template <typename U> friend TVar<U> operator*
00853     ( const TVar<U>&, const U& );
00854   template <typename U> friend TVar<U> operator/
00855     ( const TVar<U>&, const TVar<U>& );
00856   template <typename U> friend TVar<U> operator/
00857     ( const double, const TVar<U>& );
00858   template <typename U> friend TVar<U> operator/
00859     ( const TVar<U>&, const double );
00860   template <typename U> friend std::ostream& operator<<
00861     ( std::ostream&, const TVar<U>& );
00862 
00863   template <typename U> friend TVar<U> inv
00864     ( const TVar<U>& );
00865   template <typename U> friend TVar<U> sqr
00866     ( const TVar<U>& );
00867   template <typename U> friend TVar<U> sqrt
00868     ( const TVar<U>& );
00869   template <typename U> friend TVar<U> exp
00870     ( const TVar<U>& );
00871   template <typename U> friend TVar<U> log
00872     ( const TVar<U>& );
00873   template <typename U> friend TVar<U> xlog
00874     ( const TVar<U>& );
00875   template <typename U> friend TVar<U> pow
00876     ( const TVar<U>&, const int );
00877   template <typename U> friend TVar<U> pow
00878     ( const TVar<U>&, const double );
00879   template <typename U> friend TVar<U> pow
00880     ( const double, const TVar<U>& );
00881   template <typename U> friend TVar<U> pow
00882     ( const TVar<U>&, const TVar<U>& );
00883   template <typename U> friend TVar<U> monomial
00884     ( const unsigned int, const TVar<U>*, const int* );
00885   template <typename U> friend TVar<U> cos
00886     ( const TVar<U>& );
00887   template <typename U> friend TVar<U> sin
00888     ( const TVar<U>& );
00889   template <typename U> friend TVar<U> tan
00890     ( const TVar<U>& );
00891   template <typename U> friend TVar<U> acos
00892     ( const TVar<U>& );
00893   template <typename U> friend TVar<U> asin
00894     ( const TVar<U>& );
00895   template <typename U> friend TVar<U> atan
00896     ( const TVar<U>& );
00897   template <typename U> friend TVar<U> hull
00898     ( const TVar<U>&, const TVar<U>& );
00899   template <typename U> friend bool inter
00900     ( TVar<U>&, const TVar<U>&, const TVar<U>& );
00901 
00902 private:
00904   TModel<T> *_TM;
00906   TVar<T>* _TV() const
00907     { return _TM->_TV; };
00909   unsigned int _nord() const
00910     { return _TM->_nord; };
00912   unsigned int _nvar() const
00913     { return _TM->_nvar; };
00915   unsigned int _nmon() const
00916     { return _TM->_nmon; };
00918   unsigned int _posord
00919     ( const unsigned int iord ) const
00920     { return _TM->_posord[iord]; };
00922   const unsigned int* _expmon
00923     ( const unsigned int imon ) const
00924     { return _TM->_expmon+imon*_TM->_nvar; };
00926   unsigned int _prodmon
00927     ( const unsigned int imon, const unsigned int jmon ) const
00928     { return _TM->_prodmon[imon][jmon]; };
00930   const T& _bndmon
00931     ( const unsigned int imon ) const
00932     { return _TM->_bndmon[imon]; };
00934   double _refpoint
00935     ( const unsigned int ivar ) const
00936     { return _TM->_refpoint[ivar]; };
00938   double _scaling
00939     ( const unsigned int ivar ) const
00940     { return _TM->_scaling[ivar]; };
00941 
00942 public:
00946 
00947   TVar
00948     ( const double d=0. );
00950   TVar
00951     ( const T&B );
00953   TVar
00954     ( TModel<T>*TM, const unsigned int ix, const T&X,
00955       const double Xref );
00957   TVar
00958     ( TModel<T>*TM, const unsigned int ix, const T&X );
00960   TVar
00961     ( const TVar<T>&TV );
00963   template <typename U> TVar
00964     ( TModel<T>*&TM, const TVar<U>&TV );
00966   template <typename U> TVar
00967     ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const );
00969   template <typename U> TVar
00970     ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) );
00971 
00973   ~TVar()
00974     { delete [] _coefmon; delete [] _bndord; }
00975 
00977   TVar<T>& set
00978     ( TModel<T>*TM, const unsigned int ix, const T&X )
00979     { *this = TVar( TM, ix, X ); return *this; }
00980 
00982   TVar<T>& set
00983     ( TModel<T>*TM, const unsigned int ix, const T&X,
00984       const double Xref )
00985     { *this = TVar( TM, ix, X, Xref ); return *this; }
00986 
00988   TVar<T>& set
00989     ( TModel<T>*env )
00990     { *this = TVar( env ); return *this; }
00991 
00993   TVar<T>& set
00994     ( const double*coefmon )
00995     { for( unsigned int imon=0; imon<(_TM?_nmon():1); imon++ )
00996         _coefmon[imon] = coefmon[imon];
00997       _update_bndord(); return *this; }
00998 
01000   TVar<T>& set
01001     ( std::pair<unsigned int, const double*> coefmon )
01002     { for( unsigned int imon=0; imon<(_TM?_nmon():1); imon++ )
01003         _coefmon[imon] = ( imon<coefmon.first && coefmon.second?
01004                       coefmon.second[imon]: 0. );
01005       _update_bndord(); return *this; }
01006 
01008   TVar<T>& set
01009     ( const T&bndrem )
01010     { *_bndrem = bndrem; _update_bndord(); return *this; }
01011 
01013   TVar<T>& set
01014     ( TVar<T>& TV, const bool reset=true )
01015     { if( !_TM || !TV._TM || _nvar() < TV._nvar() || _nord() < TV._nord() )
01016         return *this;
01017       // Reset coefficients to 0
01018       for( unsigned int imon=0; reset && imon<_nmon(); imon++ )
01019         _coefmon[imon] = 0.;
01020       // Copy coefficients from TV --> *this
01021       unsigned int*iexp = new unsigned int[_nvar()];
01022       for( unsigned int jmon=0; jmon<TV._nmon(); jmon++ ){
01023         for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
01024      iexp[ivar] = (ivar<TV._nvar()? TV._TM->_expmon[jmon*TV._nvar()+ivar]: 0);
01025         _coefmon[_TM->_loc_expmon(iexp)] = TV._coefmon[jmon];
01026       }
01027       delete[] iexp;
01028       *_bndrem = *TV._bndrem; _update_bndord(); return *this; }
01029 
01031   TVar<T>& get
01032     ( TVar<T>&TV, const bool reset=false )
01033     { if( !_TM ){
01034         TV._coefmon[0] = _coefmon[0];
01035         // Reset coefficients to 0
01036    if( reset ) _coefmon[0] = 0.;
01037         return *this;
01038       }
01039       if( !TV._TM || _nvar() < TV._nvar() || _nord() < TV._nord() )
01040         return *this;
01041       // Copy coefficients from *this --> TV
01042       unsigned int*iexp = new unsigned int[_nvar()];
01043       for( unsigned int jmon=0; jmon<(TV._TM?TV._nmon():1); jmon++ ){
01044         for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
01045      iexp[ivar] = (ivar<TV._nvar()? TV._TM->_expmon[jmon*TV._nvar()+ivar]: 0);
01046         TV._coefmon[jmon] = _coefmon[_TM->_loc_expmon(iexp)];
01047         // Reset coefficients to 0
01048    if( reset ) _coefmon[_TM->_loc_expmon(iexp)] = 0.;
01049       }
01050       delete[] iexp;
01051       if( reset ) _update_bndord();
01052       *TV._bndrem = 0.; TV._update_bndord(); return *this; }
01053 
01055   TModel<T>* env() const
01056     { return _TM; }
01057 
01059   T bound
01060     ( const unsigned int iord ) const
01061     { return (!iord || (_TM && iord<=_nord()))? _bndord[iord]: 0.; }
01062 
01064   T bound() const
01065     { T bndmod; return _bound( bndmod ); }
01066 
01068   const T& boundT() const
01069     { return _bndT; }
01070 
01072   T remainder() const
01073     { return( *_bndrem ); }
01074 
01076   TVar<T>& center()
01077     { _center_TM(); return *this; }
01078 
01080   TVar<T> polynomial() const
01081   { TVar<T> TV = *this; *(TV._bndrem) = 0.; return TV; }
01082 
01084   double polynomial
01085     ( const double*x ) const;
01086 
01088   T B
01089     ( const unsigned int iord ) const
01090     { return iord<=_nord()? _bndord[iord]: 0.; }
01091 
01093   T B() const
01094     { T bndmod; return _bound( bndmod ); }
01095 
01097   T R() const
01098     { return remainder(); }
01099 
01101   TVar<T>& C()
01102     { return center(); }
01103 
01105   TVar<T> P() const
01106     { return polynomial(); }
01107 
01109   double P
01110     ( const double*x ) const
01111     { return polynomial( x ); }
01112 
01114   double* reference() const;
01115 
01117   double constant() const;
01118 
01120   double* linear() const;
01121 
01123   double  linear
01124     ( const unsigned int ivar, const bool reset=false );
01125 
01127   double coefmon
01128     ( const unsigned int*iexp ) const;
01129 
01131   std::pair<unsigned int, const double*> coefmon() const;
01132 
01134   std::pair<unsigned int, const unsigned int*> expmon() const;
01137   TVar<T>& operator =
01138     ( const double );
01139   TVar<T>& operator =
01140     ( const TVar<T>& );
01141   TVar<T>& operator =
01142     ( const T& );
01143   template <typename U> TVar<T>& operator +=
01144     ( const TVar<U>& );
01145   template <typename U> TVar<T>& operator +=
01146     ( const U& );
01147   TVar<T>& operator +=
01148     ( const double );
01149   template <typename U> TVar<T>& operator -=
01150     ( const TVar<U>& );
01151   template <typename U> TVar<T>& operator -=
01152     ( const U& );
01153   TVar<T>& operator -=
01154     ( const double );
01155   TVar<T>& operator *=
01156     ( const TVar<T>& );
01157   TVar<T>& operator *=
01158     ( const double );
01159   TVar<T>& operator *=
01160     ( const T& );
01161   TVar<T>& operator /=
01162     ( const TVar<T>& );
01163   TVar<T>& operator /=
01164     ( const double );
01165 
01166 private:
01167 
01169   TVar
01170     ( TModel<T>*TM, const double d=0. );
01172   TVar
01173     ( TModel<T>*TM, const T&B );
01174 
01176   double *_coefmon;
01178   T * _bndord; 
01180   T * _bndrem;
01182   T _bndT;
01183 
01185   void _update_bndord();
01187   void _center_TM();
01188 
01190   T& _bound
01191     ( T& bndmod ) const;
01193   T& _bound_naive
01194     ( T& bndmod ) const;
01196   T& _bound_LSB
01197     ( T& bndmod ) const;
01199   T& _bound_eigen
01200     ( T& bndmod ) const;
01202   T& _bound_bernstein
01203     ( T& bndmod ) const;
01205   double _coef_bernstein
01206     ( const double*coefmon, const unsigned int*jexp,
01207       const unsigned int jmon, const unsigned int maxord ) const;
01208 
01210   void _init();
01212   void _reinit();
01214   void _clean();
01215 
01216 };
01217 
01219 
01220 template <typename T> inline void
01221 TModel<T>::_size
01222 ( const unsigned int nvar, const unsigned int nord )
01223 {
01224   if( !nvar ) throw Exceptions( Exceptions::SIZE );
01225 
01226   //_cleanup();
01227   _nvar = nvar;
01228   _nord = nord; 
01229   _binom = new TM_size[(nvar+nord-1)*(nord+1)];
01230   _binom_size = std::make_pair( nvar+nord-1, nord+1 );
01231   _set_binom( nord );
01232   _posord = new unsigned int[nord+2];
01233   _posord_size = nord;
01234   _set_posord( nord );
01235   _nmon = _posord[_nord+1];
01236   _expmon = new unsigned int[_nmon*nvar];
01237   _expmon_size = _nmon;
01238   _set_expmon( nord );
01239   _set_prodmon();
01240   _bndpow = new T*[_nvar];
01241   for( unsigned int i=0; i<_nvar; i++ ) _bndpow[i] = 0;
01242   _bndmon = new T[_nmon];  
01243   _refpoint = new double[_nvar];
01244   _scaling = new double[_nvar];
01245   _modvar = true;
01246   _cbern = new double[_nord+1];
01247 
01248   _TV = new TVar<T>( this );
01249 }
01250 
01251 template <typename T> inline void
01252 TModel<T>::_set_bndpow
01253 ( const unsigned int ivar, const T&X, const double Xref,
01254   const double scaling )
01255 {
01256   if( ivar>=_nvar ) throw Exceptions( Exceptions::INIT );
01257 
01258   delete[] _bndpow[ivar];
01259   _bndpow[ivar] = new T [_nord+1];
01260   _refpoint[ivar] = Xref/scaling;
01261   _scaling[ivar] = scaling;
01262   T Xr = X/scaling - _refpoint[ivar];
01263   _bndpow[ivar][0] = 1.;
01264   for( unsigned int i=1; i<=_nord; i++ ){
01265     _bndpow[ivar][i] = Op<T>::pow(Xr,(int)i);
01266   }
01267   _modvar = true;
01268 }
01269 
01270 template <typename T> inline void
01271 TModel<T>::_set_bndmon()
01272 {
01273   if( !_modvar ) return;
01274   
01275   _bndmon[0] = 1.;
01276   for( unsigned int i=1; i<_nmon; i++ ){
01277     _bndmon[i] = 1.;
01278     for( unsigned int j=0; j<_nvar; j++)
01279       if( _bndpow[j] ) _bndmon[i] *= _bndpow[j][_expmon[i*_nvar+j]];
01280   }
01281   _modvar = false;
01282 
01283 #ifdef MC__TMODEL_DEBUG
01284   _display( 1, _nmon, _bndmon, 1, "_bndmon", std::cout );
01285 #endif
01286 }
01287 
01288 template <typename T> inline void
01289 TModel<T>::_set_posord
01290 ( const unsigned int nord )
01291 {
01292   _posord[0] = 0;
01293   _posord[1] = 1;
01294   for( unsigned int i=1; i<=nord; i++ ){
01295     TM_size _posord_next = _posord[i] + _get_binom( _nvar+i-1, i );
01296     if( _posord_next > UINT_MAX )
01297       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::MAXSIZE );
01298     _posord[i+1] = _posord_next;
01299   }
01300 
01301 #ifdef MC__TMODEL_DEBUG
01302   _display( 1, nord+2, _posord, 1, "_posord", std::cout );
01303 #endif
01304 }
01305     
01306 template <typename T> inline void
01307 TModel<T>::_ext_posord
01308 ( const unsigned int maxord )
01309 {
01310   if( maxord < _posord_size ) return;
01311   delete[] _posord;
01312   _posord = new unsigned int[maxord+2];
01313   _posord_size = maxord;
01314   _set_posord( maxord );
01315 }
01316 
01317 template <typename T> inline void
01318 TModel<T>::_set_expmon
01319 ( const unsigned int nord )
01320 {
01321   unsigned int *iexp = new unsigned int[_nvar] ;
01322   for( unsigned int k=0; k<_nvar; k++ ) _expmon[k] = 0;
01323   for( unsigned int i=1; i<=nord; i++ ){
01324     for( unsigned int j=0; j<_nvar; j++ ) iexp[j] = 0;
01325     for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
01326       _next_expmon( iexp, i );
01327       for( unsigned int k=0; k<_nvar; k++ )
01328         _expmon[j*_nvar+k] = iexp[k];
01329     }
01330   }
01331   delete[] iexp;
01332 
01333 #ifdef MC__TMODEL_DEBUG
01334   _display( _nvar, _expmon_size, _expmon, _nvar, "_expmon", std::cout );
01335 #endif
01336 }
01337   
01338 template <typename T> inline void
01339 TModel<T>::_next_expmon
01340 ( unsigned int *iexp, const unsigned int iord ) const
01341 {
01342   unsigned int curord;
01343   do{
01344     iexp[_nvar-1] += iord;
01345     unsigned int j = _nvar;
01346     while( j > 0 && iexp[j-1] > iord ){
01347       iexp[j-1] -= iord + 1;
01348       j-- ;
01349       iexp[j-1]++;
01350     }
01351     curord = 0;
01352     for( unsigned int i=0; i<_nvar; i++ ) curord += iexp[i];
01353   } while( curord != iord );
01354 }
01355     
01356 template <typename T> inline void
01357 TModel<T>::_ext_expmon
01358 ( const unsigned int maxord, const bool full )
01359 {
01360   _ext_binom( maxord );
01361   _ext_posord( maxord ); 
01362   delete[] _expmon;
01363   if( full ) _expmon_size = std::pow(maxord+1,_nvar);
01364   else       _expmon_size = _posord[maxord+1];
01365   _expmon = new unsigned int[ _expmon_size*_nvar];
01366   _set_expmon( maxord );
01367   if( !full ) return;
01368 
01369   unsigned int *iexp = new unsigned int[_nvar];
01370   for( unsigned int iord=maxord+1, jmon=_posord[maxord+1];
01371        jmon<_expmon_size; iord++ ){
01372     _ext_binom( iord );
01373     _ext_posord( iord );
01374     if( _posord[iord] >= _posord[iord+1] )
01375       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::MAXSIZE );
01376     for( unsigned int ivar=0; ivar<_nvar; ivar++ ) iexp[ivar] = 0;
01377     for( unsigned int kmon=_posord[iord]; kmon<_posord[iord+1]; kmon++ ){
01378       _next_expmon( iexp, iord );
01379       bool lt_maxord = true;
01380       for( unsigned int ivar=0; ivar<_nvar; ivar++ ){
01381         if( iexp[ivar] > maxord ){ lt_maxord = false; break; }
01382         _expmon[jmon*_nvar+ivar] = iexp[ivar];
01383       }
01384       if( lt_maxord ){
01385 #ifdef MC__TMODEL_DEBUG
01386    std::cout << jmon << ":";
01387         for( unsigned int ivar=0; ivar<_nvar; ivar++ )
01388      std::cout << "  " << _expmon[jmon*_nvar+ivar];
01389    std::cout << std::endl;
01390 #endif
01391         jmon++;
01392       }
01393     }
01394   }
01395   delete[] iexp;
01396   return;
01397 }
01398 
01399 template <typename T> inline void
01400 TModel<T>::_set_prodmon()
01401 {
01402   _prodmon = new unsigned int*[_nmon];
01403   _prodmon[0] = new unsigned int[_nmon+1];
01404   _prodmon[0][0] = _nmon;
01405   for( unsigned int i=1; i<=_nmon; i++ ) _prodmon[0][i] = i-1;
01406 #ifdef MC__TMODEL_DEBUG
01407   std::ostringstream ohead0;
01408   ohead0 << "_prodmon[" << 0 << "]";
01409   _display( 1, _nmon+1, _prodmon[0], 1, ohead0.str(), std::cout );
01410 #endif
01411 
01412   unsigned int *iexp = new unsigned int[_nvar];
01413   for( unsigned int i=1; i<_nord; i++ ){    
01414     for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
01415       _prodmon[j] = new unsigned int [_posord[_nord+1-i]+1];
01416       _prodmon[j][0] = _posord[_nord+1-i];
01417       for( unsigned int k=0; k<_posord[_nord+1-i]; k++ ){
01418         for( unsigned int in=0; in<_nvar; in++ ) 
01419           iexp[in] = _expmon[j*_nvar+in] + _expmon[k*_nvar+in] ;
01420         _prodmon[j][k+1] = _loc_expmon( iexp );
01421       }
01422 #ifdef MC__TMODEL_DEBUG
01423       std::ostringstream oheadj;
01424       oheadj << "_prodmon[" << j << "]";
01425       _display( 1, _posord[_nord+1-i]+1, _prodmon[j], 1, oheadj.str(), std::cout );
01426 #endif
01427     }
01428   }
01429   delete[] iexp;
01430 
01431   for( unsigned int i=_posord[_nord]; i<_nmon; i++ ){
01432     _prodmon[i] = new unsigned int[2];
01433     _prodmon[i][0] = 1;
01434     _prodmon[i][1] = i;
01435 #ifdef MC__TMODEL_DEBUG
01436     std::ostringstream oheadi;
01437     oheadi << "_prodmon[" << i << "]";
01438     _display( 1, 2, _prodmon[i], 1, oheadi.str(), std::cout );
01439 #endif
01440   }
01441 }
01442     
01443 template <typename T> inline unsigned int
01444 TModel<T>::_loc_expmon
01445 ( const unsigned int *iexp ) const
01446 {
01447   unsigned int ord = 0;
01448   for( unsigned int i=0; i<_nvar; i++ ) ord += iexp[i];
01449   assert( ord<_nord+2 );
01450   unsigned int pos = _posord[ord];
01451   
01452   unsigned int p = _nvar ; 
01453   for( unsigned int i=0; i<_nvar-1; i++ ){
01454     p--;
01455     for( unsigned int j=0; j<iexp[i]; j++ )
01456       pos += _get_binom( p-1+ord-j, ord-j );
01457     ord -= iexp[i];
01458   }
01459 
01460   return pos;    
01461 }
01462     
01463 template <typename T> inline void
01464 TModel<T>::_set_binom
01465 ( const unsigned int nord )
01466 {
01467   TM_size *p;
01468   unsigned int k;
01469   for( unsigned int i=0; i<_nvar+nord-1; i++ ){
01470     p = &_binom[i*(nord+1)];
01471     *p = 1;
01472     p++;
01473     *p = i+1;
01474     p++;
01475     k = ( i+1<nord? i+1: nord );
01476     for( unsigned int j=2; j<=k; j++, p++ ) *p = *(p-1) * (i+2-j)/j;
01477     for( unsigned int j=k+1; j<=nord; j++, p++ ) *p = 0.;
01478   }
01479 #ifdef MC__TMODEL_DEBUG
01480   _display( _binom_size.second, _binom_size.first, _binom,
01481     _binom_size.second, "_binom", std::cout );
01482 #endif
01483 }
01484     
01485 template <typename T> inline void
01486 TModel<T>::_ext_binom
01487 ( const unsigned int maxord )
01488 {
01489   if( maxord < _binom_size.second ) return;
01490   delete[] _binom;
01491   _binom = new TM_size[(_nvar+maxord-1)*(maxord+1)];
01492   _binom_size = std::make_pair( _nvar+maxord-1, maxord+1 );
01493   _set_binom( maxord );
01494 }
01495 
01496 template <typename T> inline TM_size
01497 TModel<T>::_get_binom
01498 ( const unsigned int n, const unsigned int k ) const
01499 {
01500 #ifdef MC__TMODEL_CHECK
01501   assert( n<=_binom_size.first );
01502   assert( k<=_binom_size.second );
01503   assert( k<=n );
01504 #endif
01505   return( n? _binom[(n-1)*_binom_size.second+k]: 1. );
01506 }
01507 
01508 template <typename T> inline void
01509 TModel<T>::_scale
01510 ( const unsigned int ivar, double*coef ) const
01511 {
01512   if( ivar>=_nvar || !_nord ) return;
01513   double dscale = Op<T>::diam(_bndpow[ivar][1]);
01514   double fscale = Op<T>::l(_bndpow[ivar][1]) / dscale;
01515   unsigned int iexp[_nvar];
01516   for( unsigned int imon=0; imon<_nmon; imon++ ){
01517     unsigned int iord = 0;
01518     for( unsigned int jvar=0; jvar<_nvar; jvar++ ){
01519       iexp[jvar] = _expmon[imon*_nvar+jvar];
01520       iord += iexp[jvar];
01521     }
01522     double coefmod = coef[imon] * std::pow(dscale,iexp[ivar]);
01523     iexp[ivar]++;
01524     for( unsigned int k=1; k<=_nord-iord; k++, iexp[ivar]++ ){
01525       coefmod += coef[_loc_expmon(iexp)]
01526         * _get_binom(iexp[ivar],k) * std::pow(fscale,k)
01527         * std::pow(dscale,iexp[ivar]);
01528     }
01529 #ifdef  MC__TMODEL_DEBUG_SCALE
01530     std::cout << "    a" << std::left << std::setw(3) << imon << " = "
01531         << std::right << std::setw(12) << coef[imon]
01532         << std::right << std::setw(14) << coefmod << std::endl;
01533 #endif
01534     coef[imon] = coefmod;
01535   }
01536   return;
01537 }
01538 
01539 template <typename T> inline TVar<T>
01540 TModel<T>::_univ_bernstein
01541 ( const TVar<T>&TV, puniv f, puniv df, punivext If,
01542   punivext d2If, const double*rusr, const int*iusr )
01543 {
01544   assert( TV._TM == this );
01545   
01546   const T B( TV.B() );
01547   const TVar<T> TVs( (TV-Op<T>::l(B))/Op<T>::diam(B) );
01548   TVar<T> TV2( this, 0. ), MON( 1. );
01549   for( unsigned int j=0; j<=_nord; j++ ){
01550     double sign = ( j%2? -1.: 1. );
01551     _cbern[j] = sign * _get_binom(_nord,j) * f( Op<T>::l(B), rusr, iusr );
01552     for( unsigned int i=1; i<=j; i++ ){
01553       sign *= -1.;
01554       _cbern[j] += sign * _get_binom(_nord,i) * _get_binom(_nord-i,j-i)
01555         * f( Op<T>::l(B)+(double)i/(double)_nord*Op<T>::diam(B), rusr, iusr );
01556     }
01557     TV2 += _cbern[j] * MON;
01558     MON *= TVs;
01559   }
01560 
01561   T R( - d2If( B, rusr, iusr ) * sqr(Op<T>::diam(B)) / 2. / _nord );
01562   if( Op<T>::l( R ) * Op<T>::u( R ) < 0 )
01563     return TV2 + Op<T>::zeroone() * R;
01564 
01565   if( !options.BERNSTEIN_OPT ){
01566     T R0( If(B,rusr,iusr) );
01567     R = Op<T>::zeroone() * ( Op<T>::u(R) <= 0.?
01568          -std::min( Op<T>::diam(R0), -Op<T>::l(R) ):
01569           std::min( Op<T>::diam(R0),  Op<T>::u(R) ) );
01570     return TV2 + R;
01571   }
01572 
01573   std::pair<unsigned int,const double*> bern = std::make_pair(_nord+1,_cbern);
01574   double xopt = _goldsect( 0., 1., _dgap_bernstein,  rusr, iusr, df, B, bern );
01575   R = Op<T>::zeroone() * _gap_bernstein( xopt, rusr, iusr, f, B, bern );
01576   return TV2 + R;
01577 }
01578 
01579 template <typename T> inline double
01580 TModel<T>::_dgap_bernstein
01581 ( const double x, const double*rusr, const int*iusr, puniv df,
01582   const T&B, const std::pair<unsigned int,const double*>&bern )
01583 {
01584   double phi = df(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr)*Op<T>::diam(B);
01585   for( unsigned int j=1; j<bern.first; j++ )
01586     phi -= j * bern.second[j] * std::pow(x,j-1);
01587   return phi;
01588 }
01589 
01590 template <typename T> inline double
01591 TModel<T>::_gap_bernstein
01592 ( const double x, const double*rusr, const int*iusr, puniv f,
01593   const T&B, const std::pair<unsigned int,const double*>&bern )
01594 {
01595   double phi = f(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr);
01596   for( unsigned int j=0; j<bern.first; j++ )
01597     phi -= bern.second[j] * std::pow(x,j);
01598   return phi;
01599 }
01600 
01601 template <typename T> inline double
01602 TModel<T>::_goldsect
01603 ( const double xL, const double xU, punivopt fopt, const double*rusr,
01604   const int*iusr, puniv df,  const T&Ix,
01605   const std::pair<unsigned int,const double*>&bern )
01606 {
01607   const double phi = 2.-(1.+std::sqrt(5.))/2.;
01608   const double fL = fopt( xL, rusr, iusr, df, Ix, bern ),
01609                fU = fopt( xU, rusr, iusr, df, Ix, bern );
01610   if( fL*fU > 0 ) throw Exceptions( Exceptions::BERNSTEIN );
01611   const double xm = xU-phi*(xU-xL),
01612                fm = fopt( xm, rusr, iusr, df, Ix, bern );
01613   return _goldsect_iter( true, xL, fL, xm, fm, xU, fU, fopt, rusr, iusr,
01614                          df, Ix, bern );
01615 }
01616 
01617 template <typename T> inline double
01618 TModel<T>::_goldsect_iter
01619 ( const bool init, const double a, const double fa, const double b,
01620   const double fb, const double c, const double fc, punivopt fopt,
01621   const double*rusr, const int*iusr, puniv df, const T&Ix,
01622   const std::pair<unsigned int,const double*>&bern )
01623 // a and c are the current bounds; the minimum is between them.
01624 // b is a center point
01625 {
01626   static unsigned int iter;
01627   iter = ( init? 1: iter+1 );
01628   const double phi = 2.-(1.+std::sqrt(5.))/2.;
01629   bool b_then_x = ( c-b > b-a );
01630   double x = ( b_then_x? b+phi*(c-b): b-phi*(b-a) );
01631   if( std::fabs(c-a) < options.BERNSTEIN_TOL*(std::fabs(b)+std::fabs(x)) 
01632    || iter > options.BERNSTEIN_MAXIT ) return (c+a)/2.;
01633   double fx = fopt( x, rusr, iusr, df, Ix, bern );
01634   if( b_then_x )
01635     return( fa*fx<0?
01636       _goldsect_iter( false, a, fa, b, fb, x, fx, fopt, rusr, iusr, df, Ix, bern ):
01637      _goldsect_iter( false, b, fb, x, fx, c, fc, fopt, rusr, iusr, df, Ix, bern ) );
01638   return( fa*fb<0?
01639      _goldsect_iter( false, a, fa, x, fx, b, fb, fopt, rusr, iusr, df, Ix, bern ):
01640      _goldsect_iter( false, x, fx, b, fb, c, fc, fopt, rusr, iusr, df, Ix, bern ) );
01641 }
01642 
01643 template <typename T> inline void
01644 TModel<T>::_reset()
01645 {
01646   for( unsigned int i=0; i<_nvar; i++ ){
01647     delete[] _bndpow[i];
01648     _bndpow[i] = 0;
01649   }
01650 }
01651 
01652 template <typename T> inline void
01653 TModel<T>::_cleanup()
01654 {
01655   for( unsigned int i=0; i<_nmon; i++ ) delete[] _prodmon[i];
01656   delete[] _prodmon;
01657   delete[] _expmon;
01658   delete[] _posord;
01659   for( unsigned int i=0; i<_nvar; i++ ) delete[] _bndpow[i];
01660   delete[] _bndpow;
01661   delete[] _bndmon;
01662   delete[] _refpoint;
01663   delete[] _scaling;
01664   delete[] _cbern;
01665   delete[] _binom;
01666   delete _TV;
01667 }
01668 
01669 template <typename T> template< typename U > inline void
01670 TModel<T>::_display
01671 ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda,
01672   const std::string&stra, std::ostream&os )
01673 {
01674   os << stra << " =" << std::endl << std::scientific
01675      << std::setprecision(5);
01676   for( unsigned int im=0; a && im<m; im++ ){
01677     for( unsigned int in=0; in<n; in++ ){
01678       os << a[in*lda+im] << "  ";
01679     }
01680     os << std::endl;
01681   }
01682   os << std::endl;
01683 
01684   if( os == std::cout || os == std::cerr ) pause();
01685 }
01686 
01687 template <typename T> void
01688 TModel<T>::pause()
01689 {
01690   double tmp;
01691   std::cout << "ENTER <1> TO CONTINUE" << std::endl;
01692   std::cin  >> tmp;
01693 }
01694 
01696 
01697 template <typename T> inline
01698 TVar<T>::TVar
01699 ( const double d )
01700 : _TM( 0 ), _bndT( d )
01701 {
01702   _init();
01703   _coefmon[0] = d;
01704   _bndord[0] = 0.;
01705 }
01706 
01707 template <typename T> inline TVar<T>&
01708 TVar<T>::operator =
01709 ( const double d )
01710 {
01711   if( _TM ){ _TM = 0; _reinit(); }
01712   _coefmon[0] = d;
01713   _bndord[0] = 0.;
01714   return *this;
01715 }
01716 
01717 template <typename T> inline
01718 TVar<T>::TVar
01719 ( TModel<T>*TM, const double d )
01720 : _TM( TM )
01721 {
01722   if( !_TM ){
01723     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01724   }
01725   _init();
01726   _coefmon[0] = d;
01727   for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.;
01728   _bndord[0] = d;
01729   for( unsigned int i=1; i<_nord()+2; i++) _bndord[i] = 0.;
01730   if( _TM->options.PROPAGATE_BNDT ) _bndT = d;
01731 }
01732 
01733 template <typename T> inline
01734 TVar<T>::TVar
01735 ( const T&B )
01736 : _TM( 0 ), _bndT( B )
01737 {
01738   _init();
01739   _coefmon[0] = 0.;
01740   _bndord[0] = B;
01741 }
01742 
01743 template <typename T> inline TVar<T>&
01744 TVar<T>::operator =
01745 ( const T&B )
01746 {
01747   if( _TM ){ _TM = 0; _reinit(); }
01748   _coefmon[0] = 0.;
01749   _bndord[0] = B;
01750   return *this;
01751 }
01752 
01753 template <typename T> inline
01754 TVar<T>::TVar
01755 ( TModel<T>*TM, const T&B )
01756 : _TM( TM )
01757 {
01758   if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01759   _init();
01760   for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = 0.;
01761   for( unsigned int i=0; i<_nord()+1; i++) _bndord[i] = 0.;
01762   *_bndrem = B;
01763   if( _TM->options.PROPAGATE_BNDT ) _bndT = B;
01764   if( _TM->options.CENTER_REMAINDER ) _center_TM();
01765 }
01766 
01767 template <typename T> inline
01768 TVar<T>::TVar
01769 ( const TVar<T>&TV )
01770 : _TM(0)
01771 {
01772   _init();
01773   *this = TV;
01774 }
01775 
01776 template <typename T> inline TVar<T>&
01777 TVar<T>::operator =
01778 ( const TVar<T>&TV )
01779 {
01780   // Same TVar
01781   if( this == &TV ) return *this;
01782 
01783   // Reinitialization needed?
01784   if( _TM != TV._TM ){ _TM = TV._TM; _reinit(); }
01785 
01786   // Set to TVar not linked to TModel (either scalar or range)
01787   if( !_TM ){
01788     _coefmon[0] = TV._coefmon[0];
01789     _bndord[0] = TV._bndord[0];
01790     return *this; 
01791   }
01792   // Set to TVar linked to TModel
01793   for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = TV._coefmon[i];
01794   for( unsigned int i=0; i<_nord()+2; i++) _bndord[i] = TV._bndord[i];
01795   if( _TM->options.PROPAGATE_BNDT ) _bndT = TV._bndT;
01796   return *this;
01797 }
01798 
01799 template <typename T> template <typename U> inline
01800 TVar<T>::TVar
01801 ( TModel<T>*&TM, const TVar<U>&TV )
01802 : _TM(TM), _coefmon(0), _bndord(0), _bndrem(0)
01803 {
01804   _init();
01805   TVar<U> TVtrunc( TV );
01806   _coefmon[0] = TVtrunc._coefmon[0];
01807   TVtrunc._coefmon[0] = 0. ;
01808   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01809     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01810       _coefmon[i] = TVtrunc._coefmon[i];
01811       TVtrunc._coefmon[i] = 0.;
01812     }
01813     else
01814       _coefmon[i] = 0.;
01815   }
01816   TVtrunc._update_bndord();
01817   *_bndrem = T( TVtrunc.B() );
01818   if( !_TM ) return;
01819   _update_bndord();
01820   if( _TM->options.PROPAGATE_BNDT ) _bndT = T( TV._bndT );
01821   return;
01822 }
01823 
01824 template <typename T> template <typename U> inline
01825 TVar<T>::TVar
01826 ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) )
01827 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01828 {
01829   if( !method )
01830     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01831   _init();
01832   TVar<U> TVtrunc( TV );
01833   _coefmon[0] = TVtrunc._coefmon[0];
01834   TVtrunc._coefmon[0] = 0. ;
01835   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01836     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01837       _coefmon[i] = TVtrunc._coefmon[i];
01838       TVtrunc._coefmon[i] = 0.;
01839     }
01840     else
01841       _coefmon[i] = 0.;
01842   }
01843   TVtrunc._update_bndord();
01844   *_bndrem = (*method)( TVtrunc.B() );
01845   if( !_TM ) return;
01846   _update_bndord();
01847   if( _TM->options.PROPAGATE_BNDT ) _bndT = (*method)( TV._bndT );
01848   return;
01849 }
01850 
01851 template <typename T> template <typename U> inline
01852 TVar<T>::TVar
01853 ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const )
01854 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01855 {
01856   if( !method )
01857     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01858   _init();
01859   TVar<U> TVtrunc( TV );
01860   _coefmon[0] = TVtrunc._coefmon[0];
01861   TVtrunc._coefmon[0] = 0. ;
01862   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01863     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01864       _coefmon[i] = TVtrunc._coefmon[i];
01865       TVtrunc._coefmon[i] = 0.;
01866     }
01867     else
01868       _coefmon[i] = 0.;
01869   }
01870   TVtrunc._update_bndord();
01871   *_bndrem = (TVtrunc.B().*method)();
01872   if( !_TM ) return;
01873   _update_bndord();
01874   if( _TM->options.PROPAGATE_BNDT ) _bndT = (TV._bndT.*method)();
01875   return;
01876 }
01877 
01878 template <typename T> inline
01879 TVar<T>::TVar
01880 ( TModel<T>*TM, const unsigned int ivar, const T&X )
01881 : _TM( TM )
01882 {
01883   if( !TM ){
01884     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01885   }
01886 
01887   // Scale variables and keep track of them in TModel
01888   double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. );
01889   if( isequal( scaling, 0. ) ) scaling = 1.;
01890   _TM->_set_bndpow( ivar, X, Op<T>::mid(X), scaling );
01891   _TM->_set_bndmon();
01892   _init();
01893 
01894   // Populate _coefmon w/ TVar coefficients
01895   _coefmon[0] = Op<T>::mid(X);
01896   for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.;
01897   if( _nord() > 0 ) _coefmon[_nvar()-ivar] = scaling;
01898 
01899   // Populate _bndord w/ bounds on TVar terms
01900   _bndord[0] = _coefmon[0];
01901   _bndord[1] = X-_coefmon[0];
01902   for( unsigned int i=2; i<_nord()+2; i++) _bndord[i] = 0.;
01903   if( _TM->options.PROPAGATE_BNDT ) _bndT = X;
01904 }
01905 
01906 template <typename T> inline
01907 TVar<T>::TVar
01908 ( TModel<T>*TM, const unsigned int ivar, const T&X, const double Xref )
01909 : _TM( TM )
01910 {
01911   if( !TM ){
01912     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01913   }
01914 
01915   // Scale variables and keep track of them in TModel
01916   double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. );
01917   if( isequal( scaling, 0. ) ) scaling = 1.;
01918   _TM->_set_bndpow( ivar, X, Xref, scaling );
01919   _TM->_set_bndmon();
01920   _init();
01921 
01922   // Populate _coefmon w/ TVar coefficients
01923   _coefmon[0] = Xref;
01924   for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.;
01925   if( _nord() > 0 ) _coefmon[_nvar()-ivar] = scaling;
01926 
01927   // Populate _bndord w/ bounds on TVar terms
01928   _bndord[0] = _coefmon[0];
01929   _bndord[1] = X-_coefmon[0];
01930   for( unsigned int i=2; i<_nord()+2; i++) _bndord[i] = 0.;
01931   if( _TM->options.PROPAGATE_BNDT ) _bndT = X;
01932 }
01933 
01934 template <typename T> inline void
01935 TVar<T>::_init()
01936 {
01937   if( !_TM ){
01938     _coefmon = new double[1];
01939     _bndord  = new T[1];
01940     _bndrem  = _bndord;
01941     return;
01942   }
01943   _coefmon = new double[_nmon()];
01944   _bndord  = new T[_nord()+2];
01945   _bndrem  = _bndord + _nord()+1;
01946 }
01947 
01948 template <typename T> inline void
01949 TVar<T>::_clean()
01950 {
01951   delete [] _coefmon; delete [] _bndord;
01952   _coefmon = 0; _bndord = _bndrem = 0;
01953 }
01954 
01955 template <typename T> inline void
01956 TVar<T>::_reinit()
01957 {
01958   _clean(); _init();
01959 }
01960 
01961 template <typename T> inline void
01962 TVar<T>::_update_bndord()
01963 {
01964   if( !_TM ) return;
01965   _TM->_set_bndmon();
01966   _bndord[0] = _coefmon[0];
01967   for( unsigned int i=1; i<=_nord(); i++ ){
01968     _bndord[i] = 0.; 
01969     for( unsigned int j=_posord(i); j<_posord(i+1); j++ )
01970       _bndord[i] += _coefmon[j] * _bndmon(j);
01971   }
01972 }
01973 
01974 template <typename T> inline void
01975 TVar<T>::_center_TM()
01976 {
01977   const double remmid = Op<T>::mid(*_bndrem);
01978   _coefmon[0] += remmid;
01979   if( _TM ) _bndord[0] = _coefmon[0];
01980   *_bndrem -= remmid;
01981 }
01982 
01983 template <typename T> inline double*
01984 TModel<T>::_eigen
01985 ( const unsigned int n, double*a )
01986 {
01987   int info;
01988   double*d = new double[n];
01989 #ifdef MC__TVAR_DEBUG_EIGEN
01990   TModel<T>::_display( n, n, a, n, "Matrix Q", std::cout );
01991 #endif
01992 
01993   // get optimal size
01994   char JOBZ = 'V', UPLO = 'U';
01995   double worktmp;
01996   int lwork = -1;
01997   dsyev_( &JOBZ, &UPLO, &n, a, &n, d, &worktmp, &lwork, &info );
01998 
01999   // perform eigenvalue decomposition
02000   lwork = (int)worktmp;
02001   double*work = new double[lwork];
02002   dsyev_( &JOBZ, &UPLO, &n, a, &n, d, work, &lwork, &info );
02003 #ifdef MC__TVAR_DEBUG_EIGEN
02004   TModel<T>::_display( n, n, a, n, "Matrix U", std::cout );
02005   TModel<T>::_display( 1, n, d, 1, "Matrix D", std::cout );
02006 #endif
02007   delete[] work;
02008 
02009 #ifdef MC__TVAR_DEBUG_EIGEN
02010   std::cout << "INFO: " << info << std::endl;
02011   TModel<T>::pause();
02012 #endif
02013   if( info ){ delete[] d; return 0; }
02014   return d;
02015 }
02016 
02017 template <typename T> inline T&
02018 TVar<T>::_bound_eigen
02019 ( T& bndmod ) const
02020 {
02021   static const double TOL = 1e-8;
02022 
02023   bndmod = _coefmon[0];
02024   if( _nord() == 1 ) bndmod += _bndord[1];
02025 
02026   else if( _nord() > 1 ){
02027     double*U = new double[_nvar()*_nvar()];
02028     for( unsigned int i=0; i<_nvar(); i++ ){
02029       for( unsigned int j=0; j<i; j++ ){
02030         U[_nvar()*(_nvar()-i-1)+_nvar()-j-1] = 0.;
02031         U[_nvar()*(_nvar()-j-1)+_nvar()-i-1] = _coefmon[_prodmon(i+1,j+2)]/2.;
02032       }
02033       U[(_nvar()+1)*(_nvar()-i-1)] = _coefmon[_prodmon(i+1,i+2)];
02034     }
02035     double*D = TModel<T>::_eigen( _nvar(), U );
02036     if( !D ){
02037       delete[] U;
02038       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::EIGEN );
02039     }
02040 
02041 #ifdef MC__TVAR_HYBRID_EIGEN
02042     T bndtype1(0.);
02043 #endif
02044     T bndtype2(0.);
02045     for( unsigned int i=0; i<_nvar(); i++ ){
02046       double linaux = 0.;
02047       T bndaux(0.);
02048       for( unsigned int k=0; k<_nvar(); k++ ){
02049         linaux += U[i*_nvar()+k] * _coefmon[_nvar()-k];
02050         bndaux += U[i*_nvar()+k] * _bndmon(_nvar()-k);
02051       }
02052 #ifdef MC__TVAR_DEBUG_EIGEN
02053       std::cout << i << ": LINAUX = " << linaux
02054                 << "  BNDAUX = " << bndaux << std::endl;
02055 #endif
02056 #ifdef MC__TVAR_HYBRID_EIGEN
02057       bndtype1 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
02058 #endif
02059 #ifdef MC__TVAR_DEBUG_EIGEN
02060       std::cout << std::endl << "BNDTYPE1: " << bndtype1 << std::endl;
02061 #endif
02062       if( std::fabs(D[i]) > TOL )
02063         bndtype2 += D[i] * Op<T>::sqr( linaux/D[i]/2. + bndaux )
02064           - linaux*linaux/D[i]/4.;
02065       else     
02066         //bndtype2 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
02067         bndtype2 += linaux * bndaux + D[i] * Op<T>::sqr( bndaux );
02068 #ifdef MC__TVAR_DEBUG_EIGEN
02069         std::cout << "BNDTYPE2: " << bndtype2 << std::endl;
02070 #endif
02071     }
02072     delete[] U;
02073     delete[] D;
02074 
02075 #ifdef MC__TVAR_HYBRID_EIGEN
02076     if( !Op<T>::inter( bndtype1, bndtype1, bndtype2 ) ){
02077       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
02078 #ifdef MC__TVAR_DEBUG_EIGEN
02079       std::cout << "BNDTYPE3: " << bndtype1 << std::endl;
02080 #endif
02081     }
02082     bndmod += bndtype1;
02083 #else
02084     bndmod += bndtype2;
02085 #endif
02086   }
02087 #ifdef MC__TVAR_DEBUG_EIGEN
02088       int tmp; std::cin >> tmp;
02089 #endif
02090 
02091   for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i];
02092   bndmod += *_bndrem;
02093 
02094   return bndmod;
02095 }
02096 
02097 template <typename T> inline T&
02098 TVar<T>::_bound_LSB
02099 ( T& bndmod ) const
02100 {
02101   static const double TOL = 1e-8;
02102   bndmod = _coefmon[0];
02103   if( _nord() == 1 ) bndmod += _bndord[1];
02104   else if( _nord() > 1 ){
02105     for( unsigned int i=1; i<=_nvar(); i++ ){
02106       // linear and diagonal quadratic terms
02107       unsigned int ii = _prodmon(i,i+1);
02108       if( std::fabs(_coefmon[ii]) > TOL )
02109         bndmod += _coefmon[ii] * Op<T>::sqr( _coefmon[i]/_coefmon[ii]/2.
02110           + _bndmon(i) ) - _coefmon[i]*_coefmon[i]/_coefmon[ii]/4.;
02111       else
02112         bndmod += _coefmon[i] * _bndmon(i) + _coefmon[ii] * _bndmon(ii);
02113       // off-diagonal quadratic terms
02114       for( unsigned int k=i+1; k<=_nvar(); k++ ){
02115    unsigned int ik = _prodmon(i,k+1) ;
02116    bndmod += _coefmon[ik] * _bndmon(ik);
02117       }
02118     }
02119   }
02120   // higher-order terms
02121   for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i];
02122   bndmod += *_bndrem;
02123   return bndmod;
02124 }
02125 
02126 template <typename T> inline T&
02127 TVar<T>::_bound_bernstein
02128 ( T& bndmod ) const
02129 {
02130   // Scale Taylor model in unit hypercube with reference point at the origin
02131   double *coeftrans = new double[_nmon()];
02132   for( unsigned int imon=0; imon<_nmon(); imon++ )
02133     coeftrans[imon] = _coefmon[imon]; 
02134   for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
02135     _TM->_scale( ivar, coeftrans );
02136   
02137   // Expand binomial coefficient and exponent arrays if needed
02138   const unsigned int maxord = (_TM->options.BOUNDER_ORDER>_nord()? 
02139     _TM->options.BOUNDER_ORDER: _nord() );
02140   const unsigned int maxmon = std::pow(maxord+1,_nvar());
02141   _TM->_ext_expmon( maxord, true );
02142 
02143   // Compute min/max amongst all Bernstein coefficients
02144   bndmod = coeftrans[0];
02145 #ifdef  MC__TVAR_DEBUG_BERSTEIN
02146   std::cout << "\n0:  " << bndmod << std::endl;
02147 #endif
02148   for( unsigned int jmon=1; jmon<maxmon; jmon++ ){
02149     const unsigned int*jexp = _TM->_expmon + jmon*_nvar();
02150     const double coefbern = _coef_bernstein( coeftrans, jexp, jmon, maxord );
02151     bndmod = Op<T>::hull( bndmod, coefbern );
02152 #ifdef  MC__TVAR_DEBUG_BERNSTEIN
02153     std::cout << jmon << " ["; 
02154     for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
02155       std::cout << std::setw(3) << jexp[ivar];
02156     std::cout << "] : " << coefbern << " : " << bndmod << std::endl;
02157 #endif
02158   }
02159 
02160   delete[] coeftrans;
02161   bndmod += *_bndrem;
02162   return bndmod;
02163 }
02164 
02165 template <typename T> inline double
02166 TVar<T>::_coef_bernstein
02167 ( const double*coefmon, const unsigned int*jexp,
02168   const unsigned int jmon, const unsigned int maxord ) const
02169 {
02170   // Compute bernstein coefficient with variables indices <tt>jexp</tt>
02171   double coefbern = coefmon[0];
02172   for( unsigned int imon=1; imon<=std::min(jmon,_nmon()-1); imon++ ){
02173     const unsigned int*iexp = _TM->_expmon + imon*_nvar();
02174     // Only append term if monomial degrees are lower
02175     bool inrange = true;
02176     for( unsigned int ivar=0; ivar<_nvar() && inrange; ivar++ )
02177       if( iexp[ivar] > jexp[ivar] ) inrange = false;
02178     if( !inrange ) continue;
02179     double termbern = coefmon[imon];
02180 #ifdef  MC__TVAR_DEBUG_BERSTEIN
02181     std::cout << "  ["; 
02182     for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
02183       std::cout << std::setw(3) << iexp[ivar];
02184     std::cout << "]";
02185 #endif
02186     for( unsigned int ivar=0; ivar<_nvar(); ivar++ )
02187       termbern *= (double)_TM->_get_binom(jexp[ivar],iexp[ivar])
02188                 / (double)_TM->_get_binom(maxord,iexp[ivar]);
02189     coefbern += termbern;
02190   }
02191 #ifdef  MC__TVAR_DEBUG_BERSTEIN
02192   std::cout << std::endl;
02193 #endif
02194   return coefbern;
02195 }
02196 
02197 template <typename T> inline T&
02198 TVar<T>::_bound_naive
02199 ( T& bndmod ) const
02200 {
02201   bndmod = _coefmon[0];
02202   for( unsigned int i=1; i<=_nord()+1; i++ ) bndmod += _bndord[i];
02203   return bndmod;
02204 }
02205 
02206 template <typename T> inline T&
02207 TVar<T>::_bound
02208 ( T& bndmod ) const
02209 {
02210   if( !_TM ){ bndmod = _coefmon[0] + _bndord[0]; return bndmod; }
02211 
02212   switch( _TM->options.BOUNDER_TYPE ){
02213   case TModel<T>::Options::NAIVE:     bndmod = _bound_naive(bndmod);     break;
02214   case TModel<T>::Options::LSB:       bndmod = _bound_LSB(bndmod);       break;
02215   case TModel<T>::Options::EIGEN:     bndmod = _bound_eigen(bndmod);     break;
02216   case TModel<T>::Options::BERNSTEIN: bndmod = _bound_bernstein(bndmod); break;
02217   case TModel<T>::Options::HYBRID: default:{
02218     T bndlsb(0.), bndeig(0.);
02219     if( !Op<T>::inter( bndmod, _bound_LSB(bndlsb), _bound_eigen(bndeig) ) )
02220       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
02221    }
02222   }
02223 
02224   if( _TM->options.PROPAGATE_BNDT && _TM->options.INTER_WITH_BNDT
02225     && !Op<T>::inter( bndmod, bndmod, _bndT ) )
02226     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
02227 
02228   return bndmod;
02229 }
02230 
02231 template <typename T> inline double
02232 TVar<T>::polynomial
02233 ( const double*x ) const
02234 {
02235   if( !_TM ) return _coefmon[0];
02236   double Pval = _coefmon[0];
02237   for( unsigned int i=1; i<_nmon(); i++ ){
02238     double valmon = 1.;
02239     for( unsigned int k=0; k<_nvar(); k++ )
02240       valmon *= std::pow( x[k]/_scaling(k)-_refpoint(k), _expmon(i)[k] );
02241     Pval += _coefmon[i] * valmon;
02242   }
02243   return Pval;
02244 }
02245 
02246 template <typename T> inline double*
02247 TVar<T>::reference() const
02248 {
02249   if( !_TM ) return 0;
02250   if( _nvar() < 1 ) return 0;
02251   double*pref = new double[_nvar()];
02252   for( unsigned int i=0; i<_nvar(); i++ ) pref[i] = _refpoint(i)*_scaling(i);
02253   return pref;
02254 }
02255 
02256 template <typename T> inline double
02257 TVar<T>::constant() const
02258 {
02259   return _coefmon[0];
02260 }
02261 
02262 template <typename T> inline double*
02263 TVar<T>::linear() const
02264 {
02265   if( !_TM || !_nvar() || !_nord() ) return 0;
02266 
02267   double*plin = new double[_nvar()];
02268   for( unsigned int i=0; i<_nvar(); i++ )
02269     plin[i] = _coefmon[_nvar()-i] / _scaling(i);
02270   return plin;
02271 }
02272 
02273 template <typename T> inline double
02274 TVar<T>::linear
02275 ( const unsigned int ivar, const bool reset )
02276 {
02277   if( !_TM || ivar>=_nvar() || !_nord() ) return 0.;
02278   const double coeflin = _coefmon[_nvar()-ivar] / _scaling(ivar);
02279   if( reset ){ _coefmon[_nvar()-ivar] = 0.; _update_bndord(); }
02280   return coeflin;
02281 }
02282 
02283 template <typename T> inline double
02284 TVar<T>::coefmon
02285 ( const unsigned int*iexp ) const
02286 {
02287   if( !_TM ) return 0;
02288   const unsigned int imon = _TM->_loc_expmon( iexp );
02289   return( imon<_nmon()? _coefmon[imon]: 0. );
02290 }
02291 
02292 template <typename T> inline std::pair<unsigned int, const double*>
02293 TVar<T>::coefmon() const
02294 {
02295   return std::make_pair( (_TM?_nmon():1), _coefmon );
02296 }
02297 
02298 template <typename T> inline std::pair<unsigned int, const unsigned int*>
02299 TVar<T>::expmon() const
02300 {
02301   return std::make_pair( (_TM?_nmon()*_nvar():1), _TM->_expmon );
02302 }
02303 
02304 template <typename T> inline std::ostream&
02305 operator <<
02306 ( std::ostream&out, const TVar<T>&TV )
02307 {
02308   out << std::endl
02309       << std::scientific << std::setprecision(5)
02310       << std::right;
02311 
02312   // Constant model
02313   if( !TV._TM ){
02314     out << "   a0    = " << std::right << std::setw(12) << TV._coefmon[0]
02315         << "      0  0"
02316         << std::endl
02317         << "   R     = " << *(TV._bndrem) << std::endl;
02318   }
02319 
02320   // Monomial term coefficients and corresponding exponents
02321   else{
02322     out << std::setprecision(TV._TM->options.DISPLAY_DIGITS);
02323     for( unsigned int i=0; i<TV._nmon(); i++ ){
02324       double scal = 1.;
02325       for( unsigned int k=0; k<TV._nvar(); k++ )
02326         scal *= std::pow( TV._scaling(k), TV._expmon(i)[k] );
02327       out << "   a" << std::left << std::setw(4) << i << " = "
02328           << std::right << std::setw(TV._TM->options.DISPLAY_DIGITS+7)
02329      << TV._coefmon[i]*scal << "   ";
02330       for( unsigned int k=0; k<TV._nvar(); k++ )
02331         out << std::setw(3) << TV._expmon(i)[k];
02332       out << std::endl;
02333     }
02334     // Remainder term
02335     out << std::right << "   R     =  " << *(TV._bndrem)
02336         << std::endl;
02337   }
02338 
02339   // Range bounder
02340   out << std::right << "   B     =  " << TV.B()
02341       << std::endl;
02342 
02343   return out;
02344 }
02345 
02346 template <typename T> inline TVar<T>
02347 operator +
02348 ( const TVar<T>&TV )
02349 {
02350   return TV;
02351 }
02352 
02353 template <typename T> template <typename U> inline TVar<T>&
02354 TVar<T>::operator +=
02355 ( const TVar<U>&TV )
02356 {
02357   if( !TV._TM ){
02358     if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT;
02359     _coefmon[0] += TV._coefmon[0];
02360     *_bndrem += *(TV._bndrem);
02361   }
02362   else if( !_TM ){
02363     TVar<T> TV2(*this);
02364     *this = TV; *this += TV2;
02365   }
02366   else{
02367     if( _TM != TV._TM )
02368       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02369     if( _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT;
02370     for( unsigned int i=0; i<_nmon(); i++ )
02371       _coefmon[i] += TV._coefmon[i];
02372     *_bndrem += *(TV._bndrem);
02373     _update_bndord();
02374   }
02375   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02376   return *this;
02377 }
02378 
02379 template <typename T, typename U> inline TVar<T>
02380 operator +
02381 ( const TVar<T>&TV1, const TVar<U>&TV2 )
02382 {
02383   TVar<T> TV3( TV1 );
02384   TV3 += TV2;
02385   return TV3;
02386 }
02387 
02388 template <typename T> inline TVar<T>&
02389 TVar<T>::operator +=
02390 ( const double c )
02391 {
02392   _coefmon[0] += c;
02393   if( _TM ) _bndord[0] = _coefmon[0];
02394   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += c;
02395   return *this;
02396 }
02397 
02398 template <typename T> inline TVar<T>
02399 operator +
02400 ( const TVar<T>&TV1, const double c )
02401 {
02402   TVar<T> TV3( TV1 );
02403   TV3 += c;
02404   return TV3;
02405 }
02406 
02407 template <typename T> inline TVar<T>
02408 operator +
02409 ( const double c, const TVar<T>&TV2 )
02410 {
02411   TVar<T> TV3( TV2 );
02412   TV3 += c;
02413   return TV3;
02414 }
02415 
02416 template <typename T> template <typename U> inline TVar<T>&
02417 TVar<T>::operator +=
02418 ( const U&I )
02419 {
02420   *_bndrem += I;
02421   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += I;
02422   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02423   return *this;
02424 }
02425 
02426 template <typename T, typename U> inline TVar<T>
02427 operator +
02428 ( const TVar<T>&TV1, const U&I )
02429 {
02430   TVar<T> TV3( TV1 );
02431   TV3 += I;
02432   return TV3;
02433 }
02434 
02435 template <typename T, typename U> inline TVar<T>
02436 operator +
02437 ( const U&I, const TVar<T>&TV2 )
02438 {
02439   TVar<T> TV3( TV2 );
02440   TV2 += I;
02441   return TV3;
02442 }
02443 
02444 template <typename T> inline TVar<T>
02445 operator -
02446 ( const TVar<T>&TV )
02447 {
02448   if( !TV._TM ){
02449     TVar<T> TV2;
02450     TV2._coefmon[0] = -TV._coefmon[0];
02451     TV2._bndord[0] = -TV._bndord[0];
02452     return TV2;
02453   }
02454   TVar<T>& TV2 = *TV._TV();
02455   //TVar<T> TV2( TV._TM );
02456   for( unsigned int i=0; i<TV._nmon(); i++ ) TV2._coefmon[i] = -TV._coefmon[i];
02457   for( unsigned int i=0; i<TV._nord()+2; i++ ) TV2._bndord[i] = -TV._bndord[i];
02458   if( TV._TM->options.PROPAGATE_BNDT ) TV2._bndT = -TV._bndT;
02459   if( TV._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02460   return TV2;
02461 }
02462 
02463 template <typename T> template <typename U> inline TVar<T>&
02464 TVar<T>::operator -=
02465 ( const TVar<U>&TV )
02466 {
02467   if( !TV._TM ){
02468     if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT;
02469     _coefmon[0] -= TV._coefmon[0];
02470     *_bndrem -= *(TV._bndrem);
02471   }
02472   else if( !_TM ){
02473     TVar<T> TV2(*this);
02474     *this = -TV; *this += TV2;
02475   }
02476   else{
02477     if( _TM != TV._TM )
02478       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02479     if( _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT;
02480     for( unsigned int i=0; i<_nmon(); i++ )
02481       _coefmon[i] -= TV._coefmon[i];
02482     *_bndrem -= *(TV._bndrem);
02483     _update_bndord();
02484   }
02485   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02486   return *this;
02487 }
02488 
02489 template <typename T, typename U> inline TVar<T>
02490 operator-
02491 ( const TVar<T>&TV1, const TVar<U>&TV2 )
02492 {
02493   TVar<T> TV3( TV1 );
02494   TV3 -= TV2;
02495   return TV3;
02496 }
02497 
02498 template <typename T> inline TVar<T>&
02499 TVar<T>::operator -=
02500 ( const double c )
02501 {
02502   _coefmon[0] -= c;
02503   if( _TM ) _bndord[0] = _coefmon[0];
02504   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= c;
02505   return *this;
02506 }
02507 
02508 template <typename T> inline TVar<T>
02509 operator -
02510 ( const TVar<T>&TV1, const double c )
02511 {
02512   TVar<T> TV3( TV1 );
02513   TV3 -= c;
02514   return TV3;
02515 }
02516 
02517 template <typename T> inline TVar<T>
02518 operator -
02519 ( const double c, const TVar<T>&TV2 )
02520 {
02521   TVar<T> TV3( -TV2 );
02522   TV3 += c;
02523   return TV3;
02524 }
02525 
02526 template <typename T> template <typename U> inline TVar<T>&
02527 TVar<T>::operator -=
02528 ( const U&I )
02529 {
02530   *_bndrem -= I;
02531   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= I;
02532   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02533   return *this;
02534 }
02535 
02536 template <typename T, typename U> inline TVar<T>
02537 operator -
02538 ( const TVar<T>&TV1, const U&I )
02539 {
02540   TVar<T> TV3( TV1 );
02541   TV3 -= I;
02542   return TV3;
02543 }
02544 
02545 template <typename T, typename U> inline TVar<T>
02546 operator -
02547 ( const U&I, const TVar<T>&TV2 )
02548 {
02549   TVar<T> TV3( -TV2 );
02550   TV3 += I;
02551   return TV3;
02552 }
02553 
02554 template <typename T> inline TVar<T>&
02555 TVar<T>::operator *=
02556 ( const TVar<T>&TV )
02557 {
02558    TVar<T> TV2( *this );
02559    *this = TV * TV2;
02560    return *this;
02561 }
02562 
02563 template <typename T> inline TVar<T>
02564 operator *
02565 ( const TVar<T>&TV1, const TVar<T>&TV2 )
02566 {
02567   if( !TV2._TM )      return( TV1 * TV2._coefmon[0] + TV1 * *(TV2._bndrem) );
02568   else if( !TV1._TM ) return( TV2 * TV1._coefmon[0] + TV2 * *(TV1._bndrem) );
02569 
02570   if( TV1._TM != TV2._TM )
02571     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02572   TVar<T>& TV3 = *TV1._TV();
02573   for( unsigned int i=0; i<TV3._nmon(); i++ ) TV3._coefmon[i] = 0.;
02574   //TVar<T> TV3( TV1._TM, 0. );
02575 
02576   // Populate _coefmon for product term
02577   for( unsigned int i=0; i<TV3._posord(TV3._nord()/2+1); i++){
02578     TV3._coefmon[TV3._prodmon(i,i+1)] += TV1._coefmon[i] * TV2._coefmon[i];
02579     for( unsigned int j=i+1; j<TV3._prodmon(i,0); j++ )
02580       TV3._coefmon[TV3._prodmon(i,j+1)] += TV1._coefmon[i] * TV2._coefmon[j]
02581                                          + TV1._coefmon[j] * TV2._coefmon[i];
02582   }
02583   // Calculate remainder term _bndrem for product term
02584   T s1 = 0., s2 = 0.;
02585   for( unsigned int i=0; i<=TV3._nord()+1; i++ ){
02586     T r1 = 0., r2 = 0.;
02587     for( unsigned int j=TV3._nord()+1-i; j<=TV3._nord()+1; j++ ){
02588       r1 += TV1._bndord[j];
02589       r2 += TV2._bndord[j];
02590     }
02591     s1 += TV2._bndord[i] * r1 ;
02592     s2 += TV1._bndord[i] * r2 ;
02593   }
02594   if( !Op<T>::inter( *(TV3._bndrem), s1, s2) ){
02595     *(TV3._bndrem) = s1;
02596     //throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::SQUARE );
02597   }
02598   // Populate _bndord for product term (except remainder term)
02599   TV3._update_bndord();
02600   if( TV3._TM->options.PROPAGATE_BNDT ) TV3._bndT = TV1._bndT * TV2._bndT;
02601   if( TV3._TM->options.CENTER_REMAINDER ) TV3._center_TM();
02602   return TV3;
02603 }
02604 
02605 template <typename T> inline TVar<T>
02606 sqr
02607 ( const TVar<T>&TV )
02608 {
02609   if( !TV._TM ){
02610     TVar<T> TV2( TV );
02611     TV2._coefmon[0] *= TV2._coefmon[0];
02612     *(TV2._bndrem) *= 2. + *(TV2._bndrem);
02613     return TV2;
02614  }
02615 
02616   // Populate _coefmon for product term
02617   TVar<T> TV2( TV._TM, 0. );
02618   for( unsigned int i=0; i<TV2._posord(TV2._nord()/2+1); i++){
02619     TV2._coefmon[TV2._prodmon(i,i+1)] += TV._coefmon[i] * TV._coefmon[i];
02620     for( unsigned int j=i+1; j<TV2._prodmon(i,0); j++ )
02621       TV2._coefmon[TV2._prodmon(i,j+1)] += TV._coefmon[i] * TV._coefmon[j] * 2.;
02622   }
02623 
02624   T s = 0.;
02625   for( unsigned int i=0; i<=TV2._nord()+1; i++ ){
02626     unsigned int k = std::max(TV2._nord()+1-i, i+1);
02627     T r = 0.;
02628     for( unsigned int j=k; j<=TV2._nord()+1; j++ )
02629       r += TV._bndord[j];
02630     s += TV._bndord[i] * r;
02631   }
02632 
02633   T r = 0.;
02634   for( unsigned int i=TV2._nord()/2+1; i<=TV2._nord()+1; i++ )
02635     r += Op<T>::sqr(TV._bndord[i]) ;
02636   *(TV2._bndrem) = 2. * s + r;
02637   
02638   // Populate _bndord for product term (except remainder term)
02639   TV2._update_bndord();
02640   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqr( TV._bndT );
02641   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02642   return TV2;
02643 }
02644 
02645 template <typename T> inline TVar<T>&
02646 TVar<T>::operator *=
02647 ( const double c )
02648 {
02649   if( !_TM ){
02650     _coefmon[0] *= c;
02651     *(_bndrem) *= c;
02652   }
02653   else{
02654     for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= c;
02655     for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= c;
02656     if( _TM->options.PROPAGATE_BNDT ) _bndT *= c;
02657   }
02658   return *this;
02659 }
02660 
02661 template <typename T> inline TVar<T>
02662 operator *
02663 ( const TVar<T>&TV1, const double c )
02664 {
02665   TVar<T> TV3( TV1 );
02666   TV3 *= c;
02667   return TV3;
02668 }
02669 
02670 template <typename T> inline TVar<T>
02671 operator *
02672 ( const double c, const TVar<T>&TV2 )
02673 {
02674   TVar<T> TV3( TV2 );
02675   TV3 *= c;
02676   return TV3;
02677 }
02678 
02679 template <typename T> inline TVar<T>&
02680 TVar<T>::operator *=
02681 ( const T&I )
02682 {
02683   if( !_TM ){
02684     *(_bndrem) += _coefmon[0];
02685     _coefmon[0] = 0.;
02686     *(_bndrem) *= I;
02687   }
02688   else{
02689     const double Imid = Op<T>::mid(I);
02690     T Icur = bound();
02691     for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= Imid;
02692     for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= Imid;
02693     *_bndrem += (I-Imid)*Icur;
02694   }
02695   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02696   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT *= I;
02697   return (*this);
02698 }
02699 
02700 template <typename T> inline TVar<T>
02701 operator *
02702 ( const TVar<T>&TV1, const T&I )
02703 {
02704   TVar<T> TV3( TV1 );
02705   TV3 *= I;
02706   return TV3;
02707 }
02708 
02709 template <typename T> inline TVar<T>
02710 operator *
02711 ( const T&I, const TVar<T>&TV2 )
02712 {
02713   TVar<T> TV3( TV2 );
02714   TV3 *= I;
02715   return TV3;
02716 }
02717 
02718 template <typename T> inline TVar<T>&
02719 TVar<T>::operator /=
02720 ( const TVar<T>&TV )
02721 {
02722    *this *= inv(TV);
02723    return *this;
02724 }
02725 
02726 template <typename T> inline TVar<T>
02727 operator /
02728 ( const TVar<T>&TV1, const TVar<T>&TV2 )
02729 {
02730   return TV1 * inv(TV2);
02731 }
02732 
02733 template <typename T> inline TVar<T>&
02734 TVar<T>::operator /=
02735 ( const double c )
02736 {
02737   if ( isequal( c, 0. ))
02738     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
02739    *this *= (1./c);
02740    return *this;
02741 }
02742 
02743 template <typename T> inline TVar<T>
02744 operator /
02745 ( const TVar<T>&TV, const double c )
02746 {
02747   if ( isequal( c, 0. ))
02748     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
02749   return TV * (1./c);
02750 }
02751 
02752 template <typename T> inline TVar<T>
02753 operator /
02754 ( const double c, const TVar<T>&TV )
02755 {
02756   return inv(TV) * c;
02757 }
02758 
02759 template <typename T> inline TVar<T>
02760 inv
02761 ( const TVar<T>&TV )
02762 {
02763   if( !TV._TM ){
02764     TVar<T> TV2( TV );
02765     TV2._coefmon[0] = 0.;
02766     *(TV2._bndrem) = Op<T>::inv(TV._coefmon[0] + *(TV._bndrem));
02767     TV2._update_bndord();
02768     return TV2;
02769   }
02770 
02771   TVar<T> TV2 = TV._TM->_inv_taylor( TV );
02772   if( TV2._TM->options.BERNSTEIN_USE ){
02773     TVar<T> TV2b = TV._TM->_inv_bernstein( TV );
02774     if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
02775       TV2 = TV2b;
02776   }
02777 
02778   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::inv( TV._bndT );
02779   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02780   return TV2;
02781 }
02782 
02783 template <typename T> inline TVar<T>
02784 TModel<T>::_inv_taylor
02785 ( const TVar<T>&TV )
02786 {
02787   const T I( TV.B() );
02788   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02789                 TV._coefmon[0] );
02790   const TVar<T> TVmx0( TV - x0 );
02791   const T Imx0( I - x0 );
02792 
02793   TVar<T> TV2( TV._TM, 1. ), MON( 1. );
02794   for( unsigned int i=1; i<=TV._nord(); i++ ){
02795     MON *= TVmx0 / (-x0);
02796     TV2 += MON;
02797   }
02798   TV2 /= x0;
02799   TV2 += Op<T>::pow( -Imx0, (int)TV2._nord()+1 )
02800        / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+2 );
02801   return TV2;
02802 }
02803 
02804 template <typename T> inline TVar<T>
02805 TModel<T>::_inv_bernstein
02806 ( const TVar<T>&TV )
02807 {
02808   struct loc{
02809     static double inv
02810       ( const double x, const double*rusr, const int*iusr )
02811       { return 1./x; }
02812     static double dinv
02813       ( const double x, const double*rusr, const int*iusr )
02814       { return -1./mc::sqr(x); }
02815     static T Iinv
02816       ( const T&x, const double*rusr, const int*iusr )
02817       { return Op<T>::inv(x); }
02818     static T d2Iinv
02819       ( const T&x, const double*rusr, const int*iusr )
02820       { return 2.*Op<T>::pow( Op<T>::inv(x), 3 ); }
02821   };
02822   return TV._TM->_univ_bernstein( TV, loc::inv, loc::dinv, loc::Iinv,
02823     loc::d2Iinv, 0, 0 );
02824 }
02825 
02826 template <typename T> inline TVar<T>
02827 sqrt
02828 ( const TVar<T>&TV )
02829 {
02830   if( !TV._TM ){
02831     TVar<T> TV2( TV );
02832     TV2._coefmon[0] = 0.;
02833     *(TV2._bndrem) = Op<T>::sqrt(TV._coefmon[0] + *(TV._bndrem));
02834     TV2._update_bndord();
02835     return TV2;
02836   }
02837 
02838   TVar<T> TV2 = TV._TM->_sqrt_taylor( TV );
02839   if( TV2._TM->options.BERNSTEIN_USE ){
02840     TVar<T> TV2b = TV._TM->_sqrt_bernstein( TV );
02841     if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
02842       TV2 = TV2b;
02843   }
02844 
02845   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqrt( TV._bndT );
02846   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02847   return TV2;
02848 }
02849 
02850 template <typename T> inline TVar<T>
02851 TModel<T>::_sqrt_taylor
02852 ( const TVar<T>&TV )
02853 {
02854   const T I( TV.B() );
02855   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02856                 TV._coefmon[0] );
02857   const TVar<T> TVmx0( TV - x0 );
02858   const T Imx0( I - x0 );
02859 
02860   double s = 0.5;
02861   TVar<T> TV2( TV._TM, 1. ), MON( 1. );
02862   for( unsigned int i=1; i<=TV._nord(); i++ ){
02863     MON *= TVmx0 / x0;
02864     TV2 += MON * s;
02865     s *= -(2.*i-1.)/(2.*i+2.);
02866   }
02867   TV2 *= std::sqrt(x0);
02868   TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02869            / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+1/2 );
02870   return TV2;
02871 }
02872 
02873 template <typename T> inline TVar<T>
02874 TModel<T>::_sqrt_bernstein
02875 ( const TVar<T>&TV )
02876 {
02877   struct loc{
02878     static double sqrt
02879       ( const double x, const double*rusr, const int*iusr )
02880       { return std::sqrt(x); }
02881     static double dsqrt
02882       ( const double x, const double*rusr, const int*iusr )
02883       { return 1./(2.*std::sqrt(x)); }
02884     static T Isqrt
02885       ( const T&x, const double*rusr, const int*iusr )
02886       { return Op<T>::sqrt(x); }
02887     static T d2Isqrt
02888       ( const T&x, const double*rusr, const int*iusr )
02889       { return -Op<T>::inv( 4.*Op<T>::sqrt(Op<T>::pow(x,3)) ); }
02890   };
02891   return TV._TM->_univ_bernstein( TV, loc::sqrt, loc::dsqrt, loc::Isqrt,
02892     loc::d2Isqrt, 0, 0 );
02893 }
02894 
02895 template <typename T> inline TVar<T>
02896 exp
02897 ( const TVar<T>&TV )
02898 { 
02899   if( !TV._TM ){
02900     TVar<T> TV2( TV );
02901     TV2._coefmon[0] = 0.;
02902     *(TV2._bndrem) = Op<T>::exp(TV._coefmon[0] + *(TV._bndrem));
02903     TV2._update_bndord();
02904     return TV2;
02905   }
02906 
02907   TVar<T> TV2 = TV._TM->_exp_taylor( TV );
02908   if( TV2._TM->options.BERNSTEIN_USE ){
02909     TVar<T> TV2b = TV._TM->_exp_bernstein( TV );
02910     //std::cout << *(TV2b._bndrem) << " <=? " << *(TV2._bndrem) << std::endl;
02911     if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
02912       TV2 = TV2b;
02913   }
02914 
02915   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::exp( TV._bndT );
02916   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02917   return TV2;
02918 }
02919 
02920 template <typename T> inline TVar<T>
02921 TModel<T>::_exp_taylor
02922 ( const TVar<T>&TV )
02923 {
02924   const T I( TV.B() );
02925   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02926                 TV._coefmon[0] );
02927   const TVar<T> TVmx0( TV - x0 );
02928   const T Imx0( I - x0 );
02929 
02930   double s = 1.;
02931   TVar<T> TV2( TV._TM, 1. ), MON( 1. );
02932   for( unsigned int i=1; i<=TV._nord(); i++ ){
02933     MON *= TVmx0;
02934     TV2 += MON * s;
02935     s /= i+1.;
02936   }
02937   TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02938            * Op<T>::exp( Op<T>::zeroone()*Imx0 );
02939   TV2 *= std::exp(x0);
02940   TV2._update_bndord();
02941   return TV2;
02942 }
02943 
02944 template <typename T> inline TVar<T>
02945 TModel<T>::_exp_bernstein
02946 ( const TVar<T>&TV )
02947 {
02948   struct loc{
02949     static double exp
02950       ( const double x, const double*rusr, const int*iusr )
02951       { return std::exp(x); }
02952     static double dexp
02953       ( const double x, const double*rusr, const int*iusr )
02954       { return std::exp(x); }
02955     static T Iexp
02956       ( const T&x, const double*rusr, const int*iusr )
02957       { return Op<T>::exp(x); }
02958     static T d2Iexp
02959       ( const T&x, const double*rusr, const int*iusr )
02960       { return Op<T>::exp(x); }
02961   };
02962   return TV._TM->_univ_bernstein( TV, loc::exp, loc::dexp, loc::Iexp,
02963     loc::d2Iexp, 0, 0 );
02964 }
02965 
02966 template <typename T> inline TVar<T>
02967 log
02968 ( const TVar<T>&TV )
02969 {
02970   if( !TV._TM ){
02971     TVar<T> TV2( TV );
02972     TV2._coefmon[0] = 0.;
02973     *(TV2._bndrem) = Op<T>::log(TV._coefmon[0] + *(TV._bndrem));
02974     TV2._update_bndord();
02975     return TV2;
02976   }
02977 
02978   TVar<T> TV2 = TV._TM->_log_taylor( TV );
02979   if( TV2._TM->options.BERNSTEIN_USE ){
02980     TVar<T> TV2b = TV._TM->_log_bernstein( TV );
02981     if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
02982       TV2 = TV2b;
02983   }
02984 
02985   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::log( TV._bndT );
02986   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02987   return TV2;
02988 }
02989 
02990 template <typename T> inline TVar<T>
02991 TModel<T>::_log_taylor
02992 ( const TVar<T>&TV )
02993 {
02994   const T I( TV.B() );
02995   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02996                 TV._coefmon[0] );
02997   const TVar<T> TVmx0( TV - x0 );
02998   const T Imx0( I - x0 );
02999 
03000   TVar<T> TV2( TV._TM, 0. ), MON( -1. );
03001   for( unsigned int i=1; i<=TV._nord(); i++ ){
03002     MON *= TVmx0 / (-x0);
03003     TV2 += MON / (double)i;
03004   }
03005   TV2._coefmon[0] += std::log(x0);
03006   TV2._update_bndord();
03007   TV2 -= Op<T>::pow( - Imx0 / ( Op<T>::zeroone()*Imx0+x0 ),
03008        (int)TV2._nord()+1 ) / ( TV2._nord()+1. );
03009   return TV2;
03010 }
03011 
03012 template <typename T> inline TVar<T>
03013 TModel<T>::_log_bernstein
03014 ( const TVar<T>&TV )
03015 {
03016   struct loc{
03017     static double log
03018       ( const double x, const double*rusr, const int*iusr )
03019       { return std::log(x); }
03020     static double dlog
03021       ( const double x, const double*rusr, const int*iusr )
03022       { return 1./x; }
03023     static T Ilog
03024       ( const T&x, const double*rusr, const int*iusr )
03025       { return Op<T>::log(x); }
03026     static T d2Ilog
03027       ( const T&x, const double*rusr, const int*iusr )
03028       { return -Op<T>::sqr( Op<T>::inv(x) ); }
03029   };
03030   return TV._TM->_univ_bernstein( TV, loc::log, loc::dlog, loc::Ilog,
03031     loc::d2Ilog, 0, 0 );
03032 }
03033 
03034 template <typename T> inline TVar<T>
03035 xlog
03036 ( const TVar<T>&TV )
03037 {
03038   return TV * log( TV );
03039 }
03040 
03041 template <typename T> inline TVar<T>
03042 pow
03043 ( const TVar<T>&TV, const int n )
03044 {
03045   if( !TV._TM ){
03046     TVar<T> TV2( TV );
03047     TV2._coefmon[0] = 0.;
03048     *(TV2._bndrem) = Op<T>::pow(TV._coefmon[0] + *(TV._bndrem), n);
03049     TV2._update_bndord();
03050     return TV2;
03051   }
03052 
03053   if( n < 0 ) return pow( inv( TV ), -n );
03054   TVar<T> TV2( TV._TM->_intpow( TV, n ) );
03055   if( TV2._TM && TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::pow( TV._bndT, n );
03056   if( TV2._TM && TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
03057   return TV2;
03058 }
03059 
03060 template <typename T> inline TVar<T>
03061 TModel<T>::_intpow
03062 ( const TVar<T>&TV, const int n )
03063 {
03064   if( n == 0 ) return 1.;
03065   else if( n == 1 ) return TV;
03066   return n%2 ? sqr( _intpow( TV, n/2 ) ) * TV : sqr( _intpow( TV, n/2 ) );
03067 }
03068 
03069 template <typename T> inline TVar<T>
03070 pow
03071 ( const TVar<T> &TV, const double a )
03072 {
03073   return exp( a * log( TV ) );
03074 }
03075 
03076 template <typename T> inline TVar<T>
03077 pow
03078 ( const TVar<T> &TV1, const TVar<T> &TV2 )
03079 {
03080   return exp( TV2 * log( TV1 ) );
03081 }
03082 
03083 template <typename T> inline TVar<T>
03084 pow
03085 ( const double a, const TVar<T> &TV )
03086 {
03087   return exp( TV * std::log( a ) );
03088 }
03089 
03090 template <typename T> inline TVar<T>
03091 monomial
03092 (const unsigned int n, const TVar<T>*TV, const int*k)
03093 {
03094   if( n == 0 ){
03095     return 1.;
03096   }
03097   if( n == 1 ){
03098     return pow( TV[0], k[0] );
03099   }
03100   return pow( TV[0], k[0] ) * monomial( n-1, TV+1, k+1 );
03101 }
03102 
03103 template <typename T> inline TVar<T>
03104 cos
03105 ( const TVar<T> &TV )
03106 {
03107   if( !TV._TM ){
03108     TVar<T> TV2( TV );
03109     TV2._coefmon[0] = 0.;
03110     *(TV2._bndrem) = Op<T>::cos(TV._coefmon[0] + *(TV._bndrem));
03111     TV2._update_bndord();
03112     return TV2;
03113   }
03114 
03115   const T I( TV.B() );
03116   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
03117                 TV._coefmon[0] );
03118   const TVar<T> TVmx0( TV - x0 );
03119   const T Imx0( I - x0 );
03120   double s = 1., c;
03121 
03122   TVar<T> TV2( TV._TM, 0. ), MON( 1. );
03123   for( unsigned int i=1; i<=TV._nord(); i++ ){
03124     switch( i%4 ){
03125     case 0: c =  std::cos(x0); break;
03126     case 1: c = -std::sin(x0); break;
03127     case 2: c = -std::cos(x0); break;
03128     case 3:
03129     default: c =  std::sin(x0); break;
03130     }
03131     MON *= TVmx0;
03132     TV2 += c * s * MON;
03133     s /= i+1;
03134   }
03135 
03136   TV2._coefmon[0] += std::cos(x0);
03137   TV2._update_bndord();
03138   switch( (TV2._nord()+1)%4 ){
03139   case 0: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
03140                    * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
03141   case 1: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
03142                    * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
03143   case 2: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
03144                    * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
03145   case 3: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
03146                    * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
03147   }
03148 
03149   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::cos( TV._bndT );
03150   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
03151   return TV2;
03152 }
03153 
03154 template <typename T> inline TVar<T>
03155 sin
03156 ( const TVar<T> &TV )
03157 {
03158   return cos( TV - PI/2. );
03159 }
03160 
03161 template <typename T> inline TVar<T>
03162 asin
03163 ( const TVar<T> &TV )
03164 {
03165   if( !TV._TM ){
03166     TVar<T> TV2( TV );
03167     TV2._coefmon[0] = 0.;
03168     *(TV2._bndrem) = Op<T>::asin(TV._coefmon[0] + *(TV._bndrem));
03169     TV2._update_bndord();
03170     return TV2;
03171   }
03172 
03173   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()):
03174                 TV._coefmon[0] );
03175   double s = 1., t = 1.;
03176   TVar<T> G = TV * std::sqrt(1-x0*x0) - x0 * sqrt(1.-sqr(TV));
03177   TVar<T> TV2( G ), MON( G ), sqrG( sqr(G) );
03178   T IG( G.B() ), IG0( IG*Op<T>::zeroone() ), sqrIG0( Op<T>::sqr(IG0) ) ;
03179   T ASIN1, ASIN2( 1./Op<T>::sqrt(1-sqrIG0) ),
03180     ASIN3( IG0*Op<T>::pow(Op<T>::sqrt(1-sqrIG0),-3) );
03181   for( unsigned int i=1; i<=TV._nord(); i++ ){
03182     MON *= sqrG;
03183     s *= (double)(2*i-1)*(double)(2*i-1)/(double)(2*i)/(double)(2*i+1);
03184     TV2 += MON * s;
03185     t *= double(i+1);
03186     ASIN1 = ASIN2; ASIN2 = ASIN3;
03187     ASIN3 = ((2*i-1)*IG0*ASIN2+(i-1)*(i-1)*ASIN1)/(1-sqrIG0);
03188   }
03189   TV2._coefmon[0] += std::asin(x0);
03190   TV2._update_bndord();
03191   TV2 += Op<T>::pow( IG, (int)TV2._nord()+1 ) / t * ASIN2;
03192   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::asin( TV._bndT );
03193   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
03194   return TV2;
03195 }
03196 
03197 template <typename T> inline TVar<T>
03198 acos
03199 ( const TVar<T> &TV )
03200 {
03201   return PI/2. - asin( TV );
03202 }
03203 
03204 template <typename T> inline TVar<T>
03205 tan
03206 ( const TVar<T> &TV )
03207 {
03208   return sin(TV) / cos(TV);
03209 }
03210 
03211 template <typename T> inline TVar<T>
03212 atan
03213 ( const TVar<T> &TV )
03214 {
03215   if( !TV._TM ){
03216     TVar<T> TV2( TV );
03217     TV2._coefmon[0] = 0.;
03218     *(TV2._bndrem) = Op<T>::atan(TV._coefmon[0] + *(TV._bndrem));
03219     TV2._update_bndord();
03220     return TV2;
03221   }
03222 
03223   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()):
03224                 TV._coefmon[0] );
03225   TVar<T> G = ( TV - x0 ) / ( 1. + x0 * TV );
03226   TVar<T> TV2( G ), MON( G ), msqrG( -sqr(G) );
03227   T IG( G.B() ), IG0( IG*Op<T>::zeroone() );
03228   for( unsigned int i=1; i<=TV._nord(); i++ ){
03229     MON *= msqrG;
03230     TV2 += MON / (2*i+1);
03231   }
03232   TV2._coefmon[0] += std::atan(x0);
03233   TV2._update_bndord();
03234   TV2 += Op<T>::pow( IG * Op<T>::cos( Op<T>::atan(IG0) ),
03235          (int)TV2._nord()+1 ) / (double)(TV2._nord()+1)
03236          * sin( (TV2._nord()+1) * (atan(IG0)+PI/2.) );
03237   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::asin( TV._bndT );
03238   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
03239   return TV2;
03240 }
03241 
03242 template <typename T> inline TVar<T>
03243 hull
03244 ( const TVar<T>&TV1, const TVar<T>&TV2 )
03245 {
03246   // Neither operands associated to TModel -- Make intersection in T type     
03247   if( !TV1._TM && !TV2._TM ){
03248     T R1 = TV1._coefmon[0] + TV1._bndord[0];
03249     T R2 = TV2._coefmon[0] + TV2._bndord[0];
03250     return Op<T>::hull(R1, R2);
03251   }
03252 
03253   // First operand not associated to TModel
03254   else if( !TV1._TM )
03255     return hull( TV2, TV1 );
03256 
03257   // Second operand not associated to TModel
03258   else if( !TV2._TM )
03259     return TV1.P() + Op<T>::hull( TV1.R(), TV2._coefmon[0]+TV2._bndord[0]-TV1.B() );
03260 
03261   // TModel for first and second operands are inconsistent
03262   else if( TV1._TM != TV2._TM )
03263     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
03264 
03265   // Perform union
03266   TVar<T> TV1C( TV1 ), TV2C( TV2 );
03267   const double eta = TV1._TM->options.REF_POLY;
03268   T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 
03269   TV1C.set(T(0.));
03270   TV2C.set(T(0.));
03271   T BTVD = (TV1C-TV2C).B();
03272   return (1.-eta)*TV1C + eta*TV2C + Op<T>::hull( R1C+eta*BTVD, R2C+(eta-1.)*BTVD );
03273 }
03274 
03275 template <typename T> inline bool
03276 inter
03277 ( TVar<T>&TVR, const TVar<T>&TV1, const TVar<T>&TV2 )
03278 {
03279   // Neither operands associated to TModel -- Make intersection in T type     
03280   if( !TV1._TM && !TV2._TM ){
03281     T R1 = TV1._coefmon[0] + TV1._bndord[0];
03282     T R2 = TV2._coefmon[0] + TV2._bndord[0];
03283     T RR( 0. );
03284     bool flag = Op<T>::inter(RR, R1, R2);
03285     TVR = RR;
03286     return flag;
03287   }
03288 
03289   // First operand not associated to TModel
03290   else if( !TV1._TM )
03291     return inter( TVR, TV2, TV1 );
03292 
03293   // Second operand not associated to TModel
03294   else if( !TV2._TM ){
03295     TVR = TV1.P();
03296     return( Op<T>::inter(*(TVR._bndrem), TV1.R(),
03297       TV2._coefmon[0]+TV2._bndord[0]-TV1.B())? true: false );
03298   }
03299 
03300   // TModel for first and second operands are inconsistent
03301   else if( TV1._TM != TV2._TM )
03302     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
03303 
03304   // Perform intersection
03305   TVar<T> TV1C( TV1 ), TV2C( TV2 );
03306   const double eta = TV1._TM->options.REF_POLY;
03307   T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 
03308   TV1C.set(T(0.));
03309   TV2C.set(T(0.));
03310   TVR = (1.-eta)*TV1C + eta*TV2C;
03311   TV1C -= TV2C;
03312   T BTVD = TV1C.B();
03313   return( Op<T>::inter( *(TVR._bndrem), R1C+eta*BTVD, R2C+(eta-1.)*BTVD )?
03314     true: false );
03315 }
03316 
03317 } // namespace mc
03318 
03319 #include "mcop.hpp"
03320 
03321 namespace mc
03322 {
03323 
03325 template <> template<typename T> struct Op< mc::TVar<T> >
03326 {
03327   typedef mc::TVar<T> TV;
03328   static TV point( const double c ) { return TV(c); }
03329   static TV zeroone() { return TV( mc::Op<T>::zeroone() ); }
03330   static void I(TV& x, const TV&y) { x = y; }
03331   static double l(const TV& x) { return mc::Op<T>::l(x.B()); }
03332   static double u(const TV& x) { return mc::Op<T>::u(x.B()); }
03333   static double abs (const TV& x) { return mc::Op<T>::abs(x.B());  }
03334   static double mid (const TV& x) { return mc::Op<T>::mid(x.B());  }
03335   static double diam(const TV& x) { return mc::Op<T>::diam(x.B()); }
03336   static TV inv (const TV& x) { return mc::inv(x);  }
03337   static TV sqr (const TV& x) { return mc::sqr(x);  }
03338   static TV sqrt(const TV& x) { return mc::sqrt(x); }
03339   static TV log (const TV& x) { return mc::log(x);  }
03340   static TV xlog(const TV& x) { return x*mc::log(x); }
03341   static TV fabs(const TV& x) { return TV( mc::Op<T>::fabs(x.B()) ); }
03342   static TV exp (const TV& x) { return mc::exp(x);  }
03343   static TV sin (const TV& x) { return mc::sin(x);  }
03344   static TV cos (const TV& x) { return mc::cos(x);  }
03345   static TV tan (const TV& x) { return mc::tan(x);  }
03346   static TV asin(const TV& x) { return mc::asin(x); }
03347   static TV acos(const TV& x) { return mc::acos(x); }
03348   static TV atan(const TV& x) { return mc::atan(x); }
03349   static TV erf (const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ) }
03350   static TV erfc(const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ) }
03351   static TV hull(const TV& x, const TV& y) { return mc::hull(x,y); }
03352   static TV min (const TV& x, const TV& y) { return mc::Op<T>::min(x.B(),y.B());  }
03353   static TV max (const TV& x, const TV& y) { return mc::Op<T>::max(x.B(),y.B());  }
03354   static TV arh (const TV& x, const double k) { return mc::exp(-k/x); }
03355   template <typename X, typename Y> static TV pow(const X& x, const Y& y) { return mc::pow(x,y); }
03356   static TV monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); }
03357   static bool inter(TV& xIy, const TV& x, const TV& y) { return mc::inter(xIy,x,y); }
03358   static bool eq(const TV& x, const TV& y) { return mc::Op<T>::eq(x.B(),y.B()); }
03359   static bool ne(const TV& x, const TV& y) { return mc::Op<T>::ne(x.B(),y.B()); }
03360   static bool lt(const TV& x, const TV& y) { return mc::Op<T>::lt(x.B(),y.B()); }
03361   static bool le(const TV& x, const TV& y) { return mc::Op<T>::le(x.B(),y.B()); }
03362   static bool gt(const TV& x, const TV& y) { return mc::Op<T>::gt(x.B(),y.B()); }
03363   static bool ge(const TV& x, const TV& y) { return mc::Op<T>::ge(x.B(),y.B()); }
03364 };
03365 
03366 } // namespace mc
03367 
03368 #endif