MC++
tmodel.h
00001 // Copyright (C) 2009-2011 Benoit Chachuat (b.chachuat@imperial.ac.uk)
00002 // All rights reserved.
00003 
00004 // This code is provided "as is", without any warranty of any kind,
00005 // either expressed or implied, including but not limited to, any implied
00006 // warranty of merchantibility or fitness for any purpose. In no event
00007 // will any party who distributed the code be liable for damages or for
00008 // any claim(s) by any other party, including but not limited to, any
00009 // lost profits, lost monies, lost data or data rendered inaccurate,
00010 // losses sustained by third parties, or any other special, incidental or
00011 // consequential damages arising out of the use or inability to use the
00012 // program, even if the possibility of such damages has been advised
00013 // against. The entire risk as to the quality, the performance, and the
00014 // fitness of the program for any particular purpose lies with the party
00015 // using the code.
00016 
00017 // This code, and any derivative of this code, may not be used in a
00018 // commercial package without the prior explicit written permission of
00019 // the authors. Verbatim copies of this code may be made and distributed
00020 // in any medium, provided that this copyright notice is not removed or
00021 // altered in any way. No fees may be charged for distribution of the
00022 // codes, other than a fee to cover the cost of the media and a
00023 // reasonable handling fee.
00024 
00025 // ***************************************************************
00026 // ANY USE OF THIS CODE CONSTITUTES ACCEPTANCE OF THE TERMS OF THE
00027 //                         COPYRIGHT NOTICE
00028 // ***************************************************************
00029 
00294 #ifndef MC__TMODEL_H
00295 #define MC__TMODEL_H
00296 
00297 #include <iostream>
00298 #include <iomanip>
00299 #include <typeinfo>
00300 #include <sstream>
00301 #include <string>
00302 #include <stdarg.h>
00303 #include <cassert>
00304 #include "mcfunc.h"
00305 #include "mcop.h"
00306 
00307 #undef  MC__TMODEL_DEBUG
00308 #define MC__TMODEL_CHECK
00309 #undef  MC__TVAR_DEBUG_EXP
00310 #undef  MC__TVAR_DEBUG_EIGEN
00311 #undef  MC__TVAR_HYBRID_EIGEN
00312 
00313 extern "C" void dsyev_
00314 ( const char*jobz, const char*uplo, const unsigned int*n, double*a,
00315   const unsigned int*lda, double*w, double*work, const int*lwork, int*info );
00316 
00317 namespace mc
00318 {
00319 
00320 template <typename T> class TVar;
00321 
00329 template <typename T>
00330 class TModel
00332 {
00333 
00334 //template <typename U> friend TVar<U>::TVar
00335 //  ( TModel<U>*TM, const unsigned int ivar, const U&X );
00336 //template <typename U> friend void TVar<U>::_update_bndord();
00337 friend class TVar<T>;
00338 template <typename U> friend class TModel;
00339 
00340 public:
00341 
00343   TModel
00344     ( const unsigned int nvar, const unsigned int nord )
00345     { _size( nvar, nord ); }
00346 //   //! @brief Copy constructor for different range bounder with implicit type conversion
00347 //   template <typename U> TModel
00348 //     ( const TModel<U>&TM );
00349 //   //! @brief Copy constructor for different range bounder with explicit type conversion member function
00350 //   template <typename U> TModel
00351 //     ( const TModel<U>&TM, const T& (U::*method)() const );
00352 //   //! @brief Copy constructor for different range bounder with explicit type conversion non-class function
00353 //   template <typename U> TModel
00354 //     ( const TModel<U>&TM, T (*method)( const U& ) );
00355 
00357   ~TModel()
00358     { _cleanup(); }
00359 
00361   unsigned int nvar() const
00362     { return _nvar; };
00364   unsigned int nord() const
00365     { return _nord; };
00367   void reset()
00368     { _reset(); };
00369 
00371   class Exceptions
00372   {
00373   public:
00375     enum TYPE{
00376       DIV=1,   
00377       INTER,   
00378       EIGEN,   
00379       SCALING, 
00380       SIZE=-1, 
00381       INIT=-2, 
00382       INCON=-3, 
00383       TMODEL=-4,
00384       UNDEF=-33   
00385     };
00387     Exceptions( TYPE ierr ) : _ierr( ierr ){}
00389     int ierr(){ return _ierr; }
00390 
00391   private:
00392     TYPE _ierr;
00393   };
00394 
00396   struct Options
00397   {
00399     Options():
00400       BOUNDER_TYPE(LSB), PROPAGATE_BNDT(false), INTER_WITH_BNDT(false),
00401       SCALE_VARIABLES(true), CENTER_REMAINDER(true), REF_MIDPOINT(true),
00402       REF_INTER(0.)
00403       {}
00405     template <typename U> Options
00406       ( U&options )
00407       : BOUNDER_TYPE( options.BOUNDER_TYPE ),
00408         PROPAGATE_BNDT( options.PROPAGATE_BNDT ),
00409         INTER_WITH_BNDT( options.INTER_WITH_BNDT ),
00410         SCALE_VARIABLES( options.SCALE_VARIABLES ),
00411         CENTER_REMAINDER( options.CENTER_REMAINDER ),
00412         REF_MIDPOINT( options.REF_MIDPOINT )
00413       {}
00414     template <typename U> Options& operator =
00415       ( U&options ){
00416         BOUNDER_TYPE = options.BOUNDER_TYPE;
00417         PROPAGATE_BNDT = options.PROPAGATE_BNDT;
00418         INTER_WITH_BNDT = options.INTER_WITH_BNDT;
00419         SCALE_VARIABLES = options.SCALE_VARIABLES;
00420         CENTER_REMAINDER = options.CENTER_REMAINDER;
00421         REF_MIDPOINT = options.REF_MIDPOINT;
00422         return *this;
00423       }
00425     enum BOUNDER{
00426       NAIVE=0, 
00427       LSB,  
00428       EIGEN,   
00429       HYBRID   
00430     };
00432     int BOUNDER_TYPE;
00434     bool PROPAGATE_BNDT;
00436     bool INTER_WITH_BNDT;
00438     bool SCALE_VARIABLES;
00440     bool CENTER_REMAINDER;
00442     bool REF_MIDPOINT;
00444     double REF_INTER;
00445   } options;
00446   
00448   static void pause();
00449     
00450 private:  
00452   unsigned int _nord;
00454   unsigned int _nvar;
00456   unsigned int _nmon;
00458   unsigned int *_posord;
00460   unsigned int *_expmon;
00462   unsigned int **_prodmon;
00464   T *_bndmon;
00466   bool _modvar;
00468   unsigned int *_binom;
00470   T **_bndpow;
00472   double *_refpoint;
00474   double *_scaling; 
00475 
00477   TVar<T>* _TV;
00478 
00480   void _size
00481     ( const unsigned int nvar, const unsigned int nord );
00482 
00483 //   //! @brief Set the order (nord) and number of variables (nvar)
00484 //   template <typename U> void _copy_data
00485 //     ( const TModel<U>&TM );
00486 
00488   void _set_bndpow
00489     ( const unsigned int ix, const T&X, const double scaling );
00490 
00492   void _set_bndmon();
00493 
00495   void _set_posord();
00496 
00498   void _set_expmon();
00499   
00501   void _next_expmon
00502     ( unsigned int *iexp, const unsigned int iord );
00503 
00505   void _set_prodmon();
00506     
00508   unsigned int _loc_expmon
00509     ( const unsigned int *iexp );
00510     
00512   void _set_binom();
00513 
00515   unsigned int _get_binom
00516     ( const unsigned int n, const unsigned int k ) const;
00517 
00519   void _reset();
00520 
00522   void _cleanup();
00523 
00525   template< typename U > static void _display
00526     ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda,
00527       const std::string&stra, std::ostream&os );
00528 } ;
00529 
00537 template <typename T>
00538 class TVar
00540 {
00541   // friends of class TVar
00542   template <typename U> friend void TModel<U>::_size
00543     ( const unsigned int nvar, const unsigned int nord );
00544 
00545   template <typename U> friend class TVar;
00546 
00547   template <typename U> friend TVar<U> operator+
00548     ( const TVar<U>& );
00549   template <typename U, typename V> friend TVar<U> operator+
00550     ( const TVar<U>&, const TVar<V>& );
00551   template <typename U, typename V> friend TVar<U> operator+
00552     ( const TVar<U>&, const V& );
00553   template <typename U, typename V> friend TVar<U> operator+
00554     ( const V&, const TVar<U>& );
00555   template <typename U> friend TVar<U> operator+
00556     ( const double, const TVar<U>& );
00557   template <typename U> friend TVar<U> operator+
00558     ( const TVar<U>&, const double );
00559   template <typename U> friend TVar<U> operator-
00560     ( const TVar<U>& );
00561   template <typename U, typename V> friend TVar<U> operator-
00562     ( const TVar<U>&, const TVar<V>& );
00563   template <typename U, typename V> friend TVar<U> operator-
00564     ( const TVar<U>&, const V& );
00565   template <typename U, typename V> friend TVar<U> operator-
00566     ( const V&, const TVar<U>& );
00567   template <typename U> friend TVar<U> operator-
00568     ( const double, const TVar<U>& );
00569   template <typename U> friend TVar<U> operator-
00570     ( const TVar<U>&, const double );
00571   template <typename U> friend TVar<U> operator*
00572     ( const TVar<U>&, const TVar<U>& );
00573   template <typename U> friend TVar<U> operator*
00574     ( const double, const TVar<U>& );
00575   template <typename U> friend TVar<U> operator*
00576     ( const TVar<U>&, const double );
00577   template <typename U> friend TVar<U> operator*
00578     ( const U&, const TVar<U>& );
00579   template <typename U> friend TVar<U> operator*
00580     ( const TVar<U>&, const U& );
00581   template <typename U> friend TVar<U> operator/
00582     ( const TVar<U>&, const TVar<U>& );
00583   template <typename U> friend TVar<U> operator/
00584     ( const double, const TVar<U>& );
00585   template <typename U> friend TVar<U> operator/
00586     ( const TVar<U>&, const double );
00587   template <typename U> friend std::ostream& operator<<
00588     ( std::ostream&, const TVar<U>& );
00589 
00590   template <typename U> friend TVar<U> inv
00591     ( const TVar<U>& );
00592   template <typename U> friend TVar<U> sqr
00593     ( const TVar<U>& );
00594   template <typename U> friend TVar<U> sqrt
00595     ( const TVar<U>& );
00596   template <typename U> friend TVar<U> exp
00597     ( const TVar<U>& );
00598   template <typename U> friend TVar<U> log
00599     ( const TVar<U>& );
00600   template <typename U> friend TVar<U> xlog
00601     ( const TVar<U>& );
00602   template <typename U> friend TVar<U> pow
00603     ( const TVar<U>&, const int );
00604   template <typename U> friend TVar<U> pow
00605     ( const TVar<U>&, const double );
00606   template <typename U> friend TVar<U> pow
00607     ( const double, const TVar<U>& );
00608   template <typename U> friend TVar<U> pow
00609     ( const TVar<U>&, const TVar<U>& );
00610   template <typename U> friend TVar<U> monomial
00611     ( const unsigned int, const TVar<U>*, const int* );
00612   template <typename U> friend TVar<U> cos
00613     ( const TVar<U>& );
00614   template <typename U> friend TVar<U> sin
00615     ( const TVar<U>& );
00616   template <typename U> friend TVar<U> tan
00617     ( const TVar<U>& );
00618   template <typename U> friend TVar<U> acos
00619     ( const TVar<U>& );
00620   template <typename U> friend TVar<U> asin
00621     ( const TVar<U>& );
00622   template <typename U> friend TVar<U> atan
00623     ( const TVar<U>& );
00624   template <typename U> friend TVar<U> hull
00625     ( const TVar<U>&, const TVar<U>& );
00626   template <typename U> friend bool inter
00627     ( TVar<U>&, const TVar<U>&, const TVar<U>& );
00628 
00629 private:
00631   TModel<T> *_TM;
00633   TVar<T>* _TV() const
00634     { return _TM->_TV; };
00636   unsigned int _nord() const
00637     { return _TM->_nord; };
00639   unsigned int _nvar() const
00640     { return _TM->_nvar; };
00642   unsigned int _nmon() const
00643     { return _TM->_nmon; };
00645   unsigned int _posord
00646     ( const unsigned int i ) const
00647     { return _TM->_posord[i]; };
00649   unsigned int _expmon
00650     ( const unsigned int i ) const
00651     { return _TM->_expmon[i]; };
00653   unsigned int _prodmon
00654     ( const unsigned int i, const unsigned int j ) const
00655     { return _TM->_prodmon[i][j]; };
00657   const T& _bndmon
00658     ( const unsigned int i ) const
00659     { return _TM->_bndmon[i]; };
00661   double _refpoint
00662     ( const unsigned int i ) const
00663     { return _TM->_refpoint[i]; };
00665   double _scaling
00666     ( const unsigned int i ) const
00667     { return _TM->_scaling[i]; };
00668 
00669 public:
00673 
00674   TVar
00675     ( const double d=0. );
00677   TVar
00678     ( const T&B );
00680   TVar
00681     ( TModel<T>*TM, const unsigned int ix, const T&X );
00683   TVar
00684     ( const TVar<T>&TV );
00686   template <typename U> TVar
00687     ( TModel<T>*&TM, const TVar<U>&TV );
00689   template <typename U> TVar
00690     ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const );
00692   template <typename U> TVar
00693     ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) );
00694 
00696   ~TVar()
00697     { delete [] _coefmon; delete [] _bndord; }
00698 
00700   TVar<T>& set
00701     ( TModel<T>*TM, const unsigned int ix, const T&X )
00702     { *this = TVar( TM, ix, X ); return *this; }
00703 
00705   TModel<T>* env() const
00706     { return _TM; }
00707 
00709   T bound() const
00710     { T bndmod; return _bound( bndmod ); }
00711 
00713   T B() const
00714     { T bndmod; return _bound( bndmod ); }
00715 
00717   const T& boundT() const
00718     { return _bndT; }
00719 
00721   T remainder() const
00722     { return( *_bndrem ); }
00723 
00725   T R() const
00726     { return remainder(); }
00727 
00729   //T& R()
00730   //  { return remainder(); }
00731 
00733   TVar<T>& center()
00734     { _center_TM(); return *this; }
00735 
00737   TVar<T>& C()
00738     { return center(); }
00739 
00741   TVar<T> polynomial() const
00742   { TVar<T> TV = *this; *(TV._bndrem) = 0.; return TV; }
00743 
00745   double polynomial
00746     ( const double*x ) const;
00747 
00749   TVar<T> P() const
00750     { return polynomial(); }
00751 
00753   double P
00754     ( const double*x ) const
00755     { return polynomial( x ); }
00756 
00758   double* reference() const;
00759 
00761   double constant() const;
00762 
00764   double* linear() const;
00765 
00767   double* quadratic
00768     ( const int opt=0 ) const;
00771 
00772   TVar<T>& operator =
00773     ( const double );
00774   TVar<T>& operator =
00775     ( const TVar<T>& );
00776   TVar<T>& operator =
00777     ( const T& );
00778   template <typename U> TVar<T>& operator +=
00779     ( const TVar<U>& );
00780   template <typename U> TVar<T>& operator +=
00781     ( const U& );
00782   TVar<T>& operator +=
00783     ( const double );
00784   template <typename U> TVar<T>& operator -=
00785     ( const TVar<U>& );
00786   template <typename U> TVar<T>& operator -=
00787     ( const U& );
00788   TVar<T>& operator -=
00789     ( const double );
00790   TVar<T>& operator *=
00791     ( const TVar<T>& );
00792   TVar<T>& operator *=
00793     ( const double );
00794   TVar<T>& operator *=
00795     ( const T& );
00796   TVar<T>& operator /=
00797     ( const TVar<T>& );
00798   TVar<T>& operator /=
00799     ( const double );
00800 
00801 private:
00802 
00804   TVar
00805     ( TModel<T>*TM, const double d=0. );
00807   TVar
00808     ( TModel<T>*TM, const T&B );
00809 
00811   double *_coefmon;
00813   T * _bndord; 
00815   T * _bndrem;
00817   T _bndT;
00818 
00820   void _init();
00822   void _reinit();
00824   void _clean();
00825 
00827   void _update_bndord();
00828 
00830   void _center_TM();
00831 
00833   T& _bound
00834     ( T& bndmod ) const;
00836   T& _bound_naive
00837     ( T& bndmod ) const;
00839   T& _bound_LSB
00840     ( T& bndmod ) const;
00842   T& _bound_eigen
00843     ( T& bndmod ) const;
00845   static double* _eigen
00846     ( const unsigned int n, double*a );
00847 
00849   TVar<T> _intpow
00850     ( const TVar<T>&TM, const int n );
00851 
00852 };
00853 
00855 
00856 // template <typename T> template <typename U> inline
00857 // TModel<T>::TModel
00858 // ( const TModel<U>&TM )
00859 // {
00860 //   // Set size and copy integer arrays
00861 //   _copy_data( TM );
00862 // 
00863 //   // Copy bound arrays
00864 //   _bndpow = new T*[_nvar];
00865 //   for( unsigned int i=0; i<_nvar; i++ ){
00866 //     if( TM._bndpow[i] ){
00867 //       _bndpow[i] = new T[_nord+1];
00868 //       for( unsigned int k=0; k<_nord+1; k++ )
00869 //         _bndpow[i][k] = T(TM._bndpow[i][k]);
00870 //     }
00871 //     else
00872 //       _bndpow[i] = 0;
00873 //   }
00874 //   _modvar = true;
00875 //   _bndmon = new T[_nmon];  
00876 //   for( unsigned int i=0; i<_nmon; i++ )
00877 //     _bndmon[i] = T(TM._bndmon[i]);
00878 // 
00879 //   return;
00880 // }
00881 // 
00882 // template <typename T> template <typename U> inline
00883 // TModel<T>::TModel
00884 // ( const TModel<U>&TM, T (*method)( const U& ) )
00885 // {
00886 //   assert( method );
00887 //   // Set size and copy integer arrays
00888 //   _copy_data( TM );
00889 // 
00890 //   // Copy bound arrays
00891 //   _bndpow = new T*[_nvar];
00892 //   for( unsigned int i=0; i<_nvar; i++ ){
00893 //     if( TM._bndpow[i] ){
00894 //       _bndpow[i] = new T[_nord+1];
00895 //       for( unsigned int k=0; k<_nord+1; k++ )
00896 //         //_bndpow[i][k] = ( method? (*method)( TM._bndpow[i][k] ):
00897 //         //                          T( TM._bndpow[i][k] ) );
00898 //         _bndpow[i][k] = (*method)( TM._bndpow[i][k] );
00899 //     }
00900 //     else
00901 //       _bndpow[i] = 0;
00902 //   }
00903 //   _modvar = true;
00904 //   _bndmon = new T[_nmon];  
00905 //   for( unsigned int i=0; i<_nmon; i++ )
00906 //     //_bndmon[i] = ( method? (*method)( TM._bndmon[i] ): T( TM._bndmon[i] ) );
00907 //     _bndmon[i] = (*method)( TM._bndmon[i] );
00908 // 
00909 //   return;
00910 // }
00911 // 
00912 // template <typename T> template <typename U> inline
00913 // TModel<T>::TModel
00914 // ( const TModel<U>&TM, const T& (U::*method)() const )
00915 // {
00916 //   // Set size and copy integer arrays
00917 //   _copy_data( TM );
00918 // 
00919 //   // Copy bound arrays
00920 //   _bndpow = new T*[_nvar];
00921 //   for( unsigned int i=0; i<_nvar; i++ ){
00922 //     if( TM._bndpow[i] ){
00923 //       _bndpow[i] = new T[_nord+1];
00924 //       for( unsigned int k=0; k<_nord+1; k++ )
00925 //         _bndpow[i][k] = (TM._bndpow[i][k].*method)();
00926 //     }
00927 //     else
00928 //       _bndpow[i] = 0;
00929 //   }
00930 //   _modvar = true;
00931 //   _bndmon = new T[_nmon];  
00932 //   for( unsigned int i=0; i<_nmon; i++ )
00933 //     _bndmon[i] = (TM._bndmon[i].*method)();
00934 // }
00935 
00936 template <typename T> inline void
00937 TModel<T>::_size
00938 ( const unsigned int nvar, const unsigned int nord )
00939 {
00940   if( !nvar ) throw Exceptions( Exceptions::SIZE );
00941 
00942   //_cleanup();
00943   _nvar = nvar;
00944   _nord = nord; 
00945   _set_binom();
00946   _set_posord();
00947   _nmon = _posord[_nord+1];
00948   _set_expmon();
00949   _set_prodmon();
00950   _bndpow = new T*[_nvar];
00951   for( unsigned int i=0; i<_nvar; i++ ) _bndpow[i] = 0;
00952   _bndmon = new T[_nmon];  
00953   _refpoint = new double[_nvar];
00954   _scaling = new double[_nvar];
00955   _modvar = true;
00956 
00957   _TV = new TVar<T>( this );
00958 }
00959 
00960 // template <typename T> template <typename U> inline void
00961 // TModel<T>::_copy_data
00962 // ( const TModel<U>&TM )
00963 // {
00964 //   _nvar = TM._nvar;
00965 //   _nord = TM._nord; 
00966 //   _binom = new unsigned int[(_nvar+_nord-1)*(_nord+1)];
00967 //   for( unsigned int i=0; i<(_nvar+_nord-1)*(_nord+1); i++ )
00968 //     _binom[i] = TM._binom[i];
00969 //   _posord = new unsigned int[_nord+2];
00970 //   for( unsigned int i=0; i<_nord+2; i++ )
00971 //     _posord[i] = TM._posord[i];
00972 //   _nmon = _posord[_nord+1];
00973 //   _expmon = new unsigned int[_nmon*_nvar];
00974 //   for( unsigned int i=0; i<_nord*_nvar; i++ )
00975 //     _expmon[i] = TM._expmon[i];
00976 //   // Copy prodmon
00977 //   _prodmon = new unsigned int*[_nmon];
00978 //   _prodmon[0] = new unsigned int[_nmon+1];
00979 //   for( unsigned int i=0; i<_nmon+1; i++ )
00980 //     _prodmon[0][i] = TM._prodmon[0][i];
00981 //   for( unsigned int i=1; i<_nord; i++ ){
00982 //     for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
00983 //       _prodmon[j] = new unsigned int [_posord[_nord+1-i]+1];
00984 //       for( unsigned int k=0; k<_posord[_nord+1-i]+1; k++ )
00985 //         _prodmon[j][k] = TM._prodmon[j][k];
00986 //     }
00987 //   }
00988 //   for( unsigned int i=_posord[_nord]; i<_nmon; i++ ){
00989 //     _prodmon[i] = new unsigned int[2];
00990 //     for( unsigned int k=0; k<2; k++ )
00991 //       _prodmon[i][k] = TM._prodmon[i][k];
00992 //   }
00993 //   // Copy reference and scaling arrays
00994 //   _refpoint = new double[_nvar];
00995 //   _scaling = new double[_nvar];
00996 //   for( unsigned int i=0; i<_nvar; i++ ){
00997 //     _refpoint[i] = TM._refpoint[i];
00998 //     _scaling[i]  = TM._scaling[i];
00999 //   }
01000 //   // Copy options
01001 //   options = TM.options;
01002 // }
01003 
01004 template <typename T> inline void
01005 TModel<T>::_set_bndpow
01006 ( const unsigned int ivar, const T&X, const double scaling )
01007 {
01008   if( ivar>=_nvar ) throw Exceptions( Exceptions::INIT );
01009 
01010   delete[] _bndpow[ivar];
01011   _bndpow[ivar] = new T [_nord+1];
01012   _refpoint[ivar] = Op<T>::mid(X)/scaling;
01013   _scaling[ivar] = scaling;
01014   T Xr = X/scaling - _refpoint[ivar];
01015   _bndpow[ivar][0] = 1.;
01016   for( unsigned int i=1; i<=_nord; i++ ){
01017     _bndpow[ivar][i] = Op<T>::pow(Xr,(int)i);
01018   }
01019   _modvar = true;
01020 }
01021 
01022 template <typename T> inline void
01023 TModel<T>::_set_bndmon()
01024 {
01025   if( !_modvar ) return;
01026   
01027   _bndmon[0] = 1.;
01028   for( unsigned int i=1; i<_nmon; i++ ){
01029     _bndmon[i] = 1.;
01030     for( unsigned int j=0; j<_nvar; j++)
01031       if( _bndpow[j] ) _bndmon[i] *= _bndpow[j][_expmon[i*_nvar+j]];
01032   }
01033   _modvar = false;
01034 
01035 #ifdef MC__TMODEL_DEBUG
01036   _display( 1, _nmon, _bndmon, 1, "_bndmon", std::cout );
01037 #endif
01038 }
01039 
01040 template <typename T> inline void
01041 TModel<T>::_set_posord()
01042 {
01043   _posord = new unsigned int[_nord+2];
01044   _posord[0] = 0;
01045   _posord[1] = 1;
01046   for( unsigned int i=1; i<=_nord; i++ )
01047     _posord[i+1] = _posord[i] + _get_binom( _nvar+i-1, i );     
01048 
01049 #ifdef MC__TMODEL_DEBUG
01050   _display( 1, _nord+2, _posord, 1, "_posord", std::cout );
01051 #endif
01052 }
01053 
01054 template <typename T> inline void
01055 TModel<T>::_set_expmon()
01056 {
01057   _expmon = new unsigned int[_nmon*_nvar];
01058   unsigned int *iexp = new unsigned int[_nvar] ;
01059   for( unsigned int k=0; k<_nvar; k++ ) _expmon[k] = 0;
01060   for( unsigned int i=1; i<=_nord; i++ ){
01061     for( unsigned int j=0; j<_nvar; j++ ) iexp[j] = 0;
01062     for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
01063       _next_expmon( iexp, i );
01064       for( unsigned int k=0; k<_nvar; k++ )
01065         _expmon[j*_nvar+k] = iexp[k];
01066     }
01067   }
01068   delete[] iexp;
01069 
01070 #ifdef MC__TMODEL_DEBUG
01071   _display( _nvar, _nmon, _expmon, _nvar, "_expmon", std::cout );
01072 #endif
01073 }
01074   
01075 template <typename T> inline void
01076 TModel<T>::_next_expmon
01077 ( unsigned int *iexp, const unsigned int iord )
01078 {
01079   unsigned int curord;
01080   do{
01081     iexp[_nvar-1] += iord;
01082     unsigned int j = _nvar;
01083     while( j > 0 && iexp[j-1] > iord ){
01084       iexp[j-1] -= iord + 1;
01085       j-- ;
01086       iexp[j-1]++;
01087     }
01088     curord = 0;
01089     for( unsigned int i=0; i<_nvar; i++ ) curord += iexp[i];
01090   } while( curord != iord );
01091 }
01092 
01093 template <typename T> inline void
01094 TModel<T>::_set_prodmon()
01095 {
01096   _prodmon = new unsigned int*[_nmon];
01097   _prodmon[0] = new unsigned int[_nmon+1];
01098   _prodmon[0][0] = _nmon;
01099   for( unsigned int i=1; i<=_nmon; i++ ) _prodmon[0][i] = i-1;
01100 #ifdef MC__TMODEL_DEBUG
01101   std::ostringstream ohead0;
01102   ohead0 << "_prodmon[" << 0 << "]";
01103   _display( 1, _nmon+1, _prodmon[0], 1, ohead0.str(), std::cout );
01104 #endif
01105 
01106   unsigned int *iexp = new unsigned int[_nvar];
01107   for( unsigned int i=1; i<_nord; i++ ){    
01108     for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
01109       _prodmon[j] = new unsigned int [_posord[_nord+1-i]+1];
01110       _prodmon[j][0] = _posord[_nord+1-i];
01111       for( unsigned int k=0; k<_posord[_nord+1-i]; k++ ){
01112         for( unsigned int in=0; in<_nvar; in++ ) 
01113           iexp[in] = _expmon[j*_nvar+in] + _expmon[k*_nvar+in] ;
01114         _prodmon[j][k+1] = _loc_expmon( iexp );
01115       }
01116 #ifdef MC__TMODEL_DEBUG
01117       std::ostringstream oheadj;
01118       oheadj << "_prodmon[" << j << "]";
01119       _display( 1, _posord[_nord+1-i]+1, _prodmon[j], 1, oheadj.str(), std::cout );
01120 #endif
01121     }
01122   }
01123   delete[] iexp;
01124 
01125   for( unsigned int i=_posord[_nord]; i<_nmon; i++ ){
01126     _prodmon[i] = new unsigned int[2];
01127     _prodmon[i][0] = 1;
01128     _prodmon[i][1] = i;
01129 #ifdef MC__TMODEL_DEBUG
01130     std::ostringstream oheadi;
01131     oheadi << "_prodmon[" << i << "]";
01132     _display( 1, 2, _prodmon[i], 1, oheadi.str(), std::cout );
01133 #endif
01134   }
01135 }
01136     
01137 template <typename T> inline unsigned int
01138 TModel<T>::_loc_expmon
01139 ( const unsigned int *iexp )
01140 {
01141   unsigned int ord = 0;
01142   for( unsigned int i=0; i<_nvar; i++ ) ord += iexp[i];
01143   assert( ord<_nord+2 );
01144   unsigned int pos = _posord[ord];
01145   
01146   unsigned int p = _nvar ; 
01147   for( unsigned int i=0; i<_nvar-1; i++ ){
01148     p--;
01149     for( unsigned int j=0; j<iexp[i]; j++ )
01150       pos += _get_binom( p-1+ord-j, ord-j );
01151     ord -= iexp[i];
01152   }
01153 
01154   return pos;    
01155 }
01156     
01157 template <typename T> inline void
01158 TModel<T>::_set_binom()
01159 {
01160   _binom = new unsigned int[(_nvar+_nord-1)*(_nord+1)];
01161   unsigned int *p, k;
01162   for( unsigned int i=0; i<_nvar+_nord-1; i++ ){
01163     p = &_binom[i*(_nord+1)];
01164     *p = 1;
01165     p++;
01166     *p = i+1;
01167     p++;
01168     k = ( i+1<_nord? i+1: _nord );
01169     for( unsigned int j=2; j<=k; j++, p++ ) *p = *(p-1) * (i+2-j)/j;
01170     for( unsigned int j=k+1; j<=_nord; j++, p++ ) *p = 0.;
01171   }
01172 #ifdef MC__TMODEL_DEBUG
01173   _display( _nord+1, _nvar+_nord-1, _binom, _nord+1, "_binom", std::cout );
01174 #endif
01175 }
01176 
01177 template <typename T> inline unsigned int
01178 TModel<T>::_get_binom
01179 ( const unsigned int n, const unsigned int k ) const
01180 {
01181 #ifdef MC__TMODEL_CHECK
01182   assert( n>0 && n<_nord+_nvar && k<=n );
01183 #endif
01184   return _binom[(n-1)*(_nord+1)+k] ;
01185 }
01186 
01187 template <typename T> inline void
01188 TModel<T>::_reset()
01189 {
01190   for( unsigned int i=0; i<_nvar; i++ ){
01191     delete[] _bndpow[i];
01192     _bndpow[i] = 0;
01193   }
01194 }
01195 
01196 template <typename T> inline void
01197 TModel<T>::_cleanup()
01198 {
01199   for( unsigned int i=0; i<_nmon; i++ ) delete[] _prodmon[i];
01200   delete[] _prodmon;
01201   delete[] _expmon;
01202   delete[] _posord;
01203   for( unsigned int i=0; i<_nvar; i++ ) delete[] _bndpow[i];
01204   delete[] _bndpow;
01205   delete[] _bndmon;
01206   delete[] _refpoint;
01207   delete[] _scaling;
01208   delete[] _binom;
01209   delete _TV;
01210 }
01211 
01212 template <typename T> template< typename U > inline void
01213 TModel<T>::_display
01214 ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda,
01215   const std::string&stra, std::ostream&os )
01216 {
01217   os << stra << " =" << std::endl << std::scientific
01218      << std::setprecision(5);
01219   for( unsigned int im=0; a && im<m; im++ ){
01220     for( unsigned int in=0; in<n; in++ ){
01221       os << a[in*lda+im] << "  ";
01222     }
01223     os << std::endl;
01224   }
01225   os << std::endl;
01226 
01227   if( os == std::cout || os == std::cerr ) pause();
01228 }
01229 
01230 template <typename T> void
01231 TModel<T>::pause()
01232 {
01233   double tmp;
01234   std::cout << "ENTER <1> TO CONTINUE" << std::endl;
01235   std::cin  >> tmp;
01236 }
01237 
01239 
01240 template <typename T> inline
01241 TVar<T>::TVar
01242 ( const double d )
01243 : _TM( 0 ), _bndT( d )
01244 {
01245   _init();
01246   _coefmon[0] = d;
01247   _bndord[0] = 0.;
01248 }
01249 
01250 template <typename T> inline TVar<T>&
01251 TVar<T>::operator =
01252 ( const double d )
01253 {
01254   if( _TM ){ _TM = 0; _reinit(); }
01255   _coefmon[0] = d;
01256   _bndord[0] = 0.;
01257   return *this;
01258 }
01259 
01260 template <typename T> inline
01261 TVar<T>::TVar
01262 ( TModel<T>*TM, const double d )
01263 : _TM( TM )
01264 {
01265   if( !_TM ){
01266     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01267   }
01268   _init();
01269   _coefmon[0] = d;
01270   for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.;
01271   _bndord[0] = d;
01272   for( unsigned int i=1; i<_nord()+2; i++) _bndord[i] = 0.;
01273   if( _TM->options.PROPAGATE_BNDT ) _bndT = d;
01274 }
01275 
01276 template <typename T> inline
01277 TVar<T>::TVar
01278 ( const T&B )
01279 : _TM( 0 ), _bndT( B )
01280 {
01281   _init();
01282   _coefmon[0] = 0.;
01283   _bndord[0] = B;
01284 }
01285 
01286 template <typename T> inline TVar<T>&
01287 TVar<T>::operator =
01288 ( const T&B )
01289 {
01290   if( _TM ){ _TM = 0; _reinit(); }
01291   _coefmon[0] = 0.;
01292   _bndord[0] = B;
01293   return *this;
01294 }
01295 
01296 template <typename T> inline
01297 TVar<T>::TVar
01298 ( TModel<T>*TM, const T&B )
01299 : _TM( TM )
01300 {
01301   if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01302   _init();
01303   for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = 0.;
01304   for( unsigned int i=0; i<_nord()+1; i++) _bndord[i] = 0.;
01305   *_bndrem = B;
01306   if( _TM->options.PROPAGATE_BNDT ) _bndT = B;
01307   if( _TM->options.CENTER_REMAINDER ) _center_TM();
01308 }
01309 
01310 template <typename T> inline
01311 TVar<T>::TVar
01312 ( const TVar<T>&TV )
01313 : _TM(0)
01314 {
01315   _init();
01316   *this = TV;
01317 }
01318 
01319 template <typename T> inline TVar<T>&
01320 TVar<T>::operator =
01321 ( const TVar<T>&TV )
01322 {
01323   // Same TVar
01324   if( this == &TV ) return *this;
01325 
01326   // Reinitialization needed?
01327   if( _TM != TV._TM ){ _TM = TV._TM; _reinit(); }
01328 
01329   // Set to TVar not linked to TModel (either scalar or range)
01330   if( !_TM ){
01331     _coefmon[0] = TV._coefmon[0];
01332     _bndord[0] = TV._bndord[0];
01333     return *this; 
01334   }
01335   // Set to TVar linked to TModel
01336   for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = TV._coefmon[i];
01337   for( unsigned int i=0; i<_nord()+2; i++) _bndord[i] = TV._bndord[i];
01338   if( _TM->options.PROPAGATE_BNDT ) _bndT = TV._bndT;
01339   return *this;
01340 }
01341 
01342 template <typename T> template <typename U> inline
01343 TVar<T>::TVar
01344 ( TModel<T>*&TM, const TVar<U>&TV )
01345 : _TM(TM), _coefmon(0), _bndord(0), _bndrem(0)
01346 {
01347   _init();
01348   TVar<U> TVtrunc( TV );
01349   _coefmon[0] = TVtrunc._coefmon[0];
01350   TVtrunc._coefmon[0] = 0. ;
01351   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01352     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01353       _coefmon[i] = TVtrunc._coefmon[i];
01354       TVtrunc._coefmon[i] = 0.;
01355     }
01356     else
01357       _coefmon[i] = 0.;
01358   }
01359   TVtrunc._update_bndord();
01360   *_bndrem = T( TVtrunc.B() );
01361   if( !_TM ) return;
01362   _update_bndord();
01363 //   std::cout << TV;
01364 //   std::cout << *this;
01365 //   int dum; std::cin >> dum;
01366   if( _TM->options.PROPAGATE_BNDT ) _bndT = T( TV._bndT );
01367   return;
01368 }
01369 
01370 // template <typename T> template <typename U> inline
01371 // TVar<T>::TVar
01372 // ( TModel<T>*&TM, const TVar<U>&TV )
01373 // : _TM(TM), _coefmon(0), _bndord(0), _bndrem(0)
01374 // {
01375 //   if( !_TM && TV._TM )
01376 //     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01377 // 
01378 //   // Set to TVar linked to TModel
01379 //   //if( !_TM && TV._TM ) _TM = new TModel<T>( *(TV._TM) );
01380 // 
01381 //   _init();
01382 //   if( !_TM ){
01383 //     _coefmon[0] = TV._coefmon[0];
01384 //     *_bndrem = T( *TV._bndrem );
01385 //   }
01386 //   else{
01387 //     _coefmon[0] = TV._coefmon[0];
01388 //     for( unsigned int i=1; i<_nmon(); i++ )
01389 //       _coefmon[i] = ( TV._TM? TV._coefmon[i]: 0. );
01390 //     *_bndrem = T( *TV._bndrem );
01391 //     _update_bndord();
01392 //     if( _TM->options.PROPAGATE_BNDT ) _bndT = T( TV._bndT );
01393 //   }
01394 //   return;
01395 // }
01396 
01397 template <typename T> template <typename U> inline
01398 TVar<T>::TVar
01399 ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) )
01400 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01401 {
01402   if( !method )
01403     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01404   _init();
01405   TVar<U> TVtrunc( TV );
01406   _coefmon[0] = TVtrunc._coefmon[0];
01407   TVtrunc._coefmon[0] = 0. ;
01408   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01409     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01410       _coefmon[i] = TVtrunc._coefmon[i];
01411       TVtrunc._coefmon[i] = 0.;
01412     }
01413     else
01414       _coefmon[i] = 0.;
01415   }
01416   TVtrunc._update_bndord();
01417   *_bndrem = (*method)( TVtrunc.B() );
01418   if( !_TM ) return;
01419   _update_bndord();
01420   if( _TM->options.PROPAGATE_BNDT ) _bndT = (*method)( TV._bndT );
01421   return;
01422 }
01423 
01424 // template <typename T> template <typename U> inline
01425 // TVar<T>::TVar
01426 // ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) )
01427 // : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01428 // {
01429 //   if( !method || ( !_TM && TV._TM ) )
01430 //     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01431 // 
01432 //   // Set to TVar linked to TModel
01433 //   //if( !_TM && TV._TM ) _TM = new TModel<T>( *(TV._TM), method );
01434 // 
01435 //   _init();
01436 //   if( !_TM ){
01437 //     _coefmon[0] = TV._coefmon[0];
01438 //     *_bndrem = (*method)( *TV._bndrem );
01439 //   }
01440 //   else{
01441 //     _coefmon[0] = TV._coefmon[0];
01442 //     for( unsigned int i=1; i<_nmon(); i++ )
01443 //       _coefmon[i] = ( TV._TM? TV._coefmon[i]: 0. );
01444 //     *_bndrem = (*method)( *TV._bndrem );
01445 //     _update_bndord();
01446 //     if( _TM->options.PROPAGATE_BNDT ) _bndT = (*method)( TV._bndT );
01447 //   }
01448 //   return;
01449 // }
01450 
01451 template <typename T> template <typename U> inline
01452 TVar<T>::TVar
01453 ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const )
01454 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01455 {
01456   if( !method )
01457     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01458   _init();
01459   TVar<U> TVtrunc( TV );
01460   _coefmon[0] = TVtrunc._coefmon[0];
01461   TVtrunc._coefmon[0] = 0. ;
01462   for( unsigned int i=1; _TM && i<_nmon(); i++ ){
01463     if( TVtrunc._TM && i < TVtrunc._nmon() ){
01464       _coefmon[i] = TVtrunc._coefmon[i];
01465       TVtrunc._coefmon[i] = 0.;
01466     }
01467     else
01468       _coefmon[i] = 0.;
01469   }
01470   TVtrunc._update_bndord();
01471   *_bndrem = (TVtrunc.B().*method)();
01472   if( !_TM ) return;
01473   _update_bndord();
01474   if( _TM->options.PROPAGATE_BNDT ) _bndT = (TV._bndT.*method)();
01475   return;
01476 }
01477 
01478 // template <typename T> template <typename U> inline
01479 // TVar<T>::TVar
01480 // ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const )
01481 // : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 )
01482 // {
01483 //   if( !_TM && TV._TM )
01484 //     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01485 // 
01486 //   // Set to TVar linked to TModel
01487 //   //if( !_TM && TV._TM ) _TM = new TModel<T>( *(TV._TM), method );
01488 // 
01489 //   _init();
01490 //   if( !_TM ){
01491 //     _coefmon[0] = TV._coefmon[0];
01492 //     *_bndrem = (TV._bndrem->*method)();
01493 //   }
01494 //   else{
01495 //     _coefmon[0] = TV._coefmon[0];
01496 //     for( unsigned int i=1; i<_nmon(); i++ )
01497 //       _coefmon[i] = ( TV._TM? TV._coefmon[i]: 0. );
01498 //     *_bndrem = (TV._bndrem->*method)();
01499 //     _update_bndord();
01500 //     if( _TM->options.PROPAGATE_BNDT ) _bndT = (TV._bndT.*method)();
01501 //   }
01502 //   return;
01503 // }
01504 
01505 template <typename T> inline
01506 TVar<T>::TVar
01507 ( TModel<T>*TM, const unsigned int ivar, const T&X )
01508 : _TM( TM )
01509 {
01510   if( !TM ){
01511     std::cerr << "No Environment!\n";
01512     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
01513   }
01514 
01515   // Scale variables and keep track of them in TModel
01516   double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. );
01517   if( isequal( scaling, 0. ) ) scaling = 1.;
01518   //if( isequal( scaling, 0. ) ){
01519   //  std::cerr << "P(" << ivar << ") = " << X << std::endl;
01520   //  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::SCALING );
01521   //}
01522   _TM->_set_bndpow( ivar, X, scaling );
01523   _TM->_set_bndmon();
01524   _init();
01525 
01526   // Populate _coefmon w/ TVar coefficients
01527   _coefmon[0] = Op<T>::mid(X);
01528   for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.;
01529   if( _nord() > 0 ) _coefmon[_nvar()-ivar] = scaling;
01530 
01531   // Populate _bndord w/ bounds on TVar terms
01532   _bndord[0] = _coefmon[0];
01533   _bndord[1] = X-_coefmon[0];
01534   for( unsigned int i=2; i<_nord()+2; i++) _bndord[i] = 0.;
01535   if( _TM->options.PROPAGATE_BNDT ) _bndT = X;
01536 }
01537 
01538 template <typename T> inline void
01539 TVar<T>::_init()
01540 {
01541   if( !_TM ){
01542     _coefmon = new double[1];
01543     _bndord  = new T[1];
01544     _bndrem  = _bndord;
01545     return;
01546   }
01547   _coefmon = new double[_nmon()];
01548   _bndord  = new T[_nord()+2];
01549   _bndrem  = _bndord + _nord()+1;
01550 }
01551 
01552 template <typename T> inline void
01553 TVar<T>::_clean()
01554 {
01555   delete [] _coefmon; delete [] _bndord;
01556   _coefmon = 0; _bndord = _bndrem = 0;
01557 }
01558 
01559 template <typename T> inline void
01560 TVar<T>::_reinit()
01561 {
01562   _clean(); _init();
01563 }
01564 
01565 template <typename T> inline void
01566 TVar<T>::_update_bndord()
01567 {
01568   if( !_TM ) return;
01569   _TM->_set_bndmon();
01570   _bndord[0] = _coefmon[0];
01571   for( unsigned int i=1; i<=_nord(); i++ ){
01572     _bndord[i] = 0.; 
01573     for( unsigned int j=_posord(i); j<_posord(i+1); j++ )
01574       _bndord[i] += _coefmon[j] * _bndmon(j);
01575   }
01576 }
01577 
01578 template <typename T> inline void
01579 TVar<T>::_center_TM()
01580 {
01581   const double remmid = Op<T>::mid(*_bndrem);
01582   _coefmon[0] += remmid;
01583   if( _TM ) _bndord[0] = _coefmon[0];
01584   *_bndrem -= remmid;
01585 }
01586 
01587 template <typename T> inline double*
01588 TVar<T>::_eigen
01589 ( const unsigned int n, double*a )
01590 {
01591   int info;
01592   double*d = new double[n];
01593 #ifdef MC__TVAR_DEBUG_EIGEN
01594   TModel<T>::_display( n, n, a, n, "Matrix Q", std::cout );
01595 #endif
01596 
01597   // get optimal size
01598   double worktmp;
01599   int lwork = -1;
01600   dsyev_( "Vectors", "Upper", &n, a, &n, d, &worktmp, &lwork, &info );
01601 
01602   // perform eigenvalue decomposition
01603   lwork = (int)worktmp;
01604   double*work = new double[lwork];
01605   dsyev_( "Vectors", "Upper", &n, a, &n, d, work, &lwork, &info );
01606 #ifdef MC__TVAR_DEBUG_EIGEN
01607   TModel<T>::_display( n, n, a, n, "Matrix U", std::cout );
01608   TModel<T>::_display( 1, n, d, 1, "Matrix D", std::cout );
01609 #endif
01610   delete[] work;
01611 
01612 #ifdef MC__TVAR_DEBUG_EIGEN
01613   std::cout << "INFO: " << info << std::endl;
01614   TModel<T>::pause();
01615 #endif
01616   if( info ){ delete[] d; return 0; }
01617   return d;
01618 }
01619 
01620 template <typename T> inline T&
01621 TVar<T>::_bound_eigen
01622 ( T& bndmod ) const
01623 {
01624   static const double TOL = 1e-8;
01625 
01626   bndmod = _coefmon[0];
01627   if( _nord() == 1 ) bndmod += _bndord[1];
01628 
01629   else if( _nord() > 1 ){
01630     double*U = new double[_nvar()*_nvar()];
01631     for( unsigned int i=0; i<_nvar(); i++ ){
01632       for( unsigned int j=0; j<i; j++ ){
01633         U[_nvar()*(_nvar()-i-1)+_nvar()-j-1] = 0.;
01634         U[_nvar()*(_nvar()-j-1)+_nvar()-i-1] = _coefmon[_prodmon(i+1,j+2)]/2.;
01635       }
01636       U[(_nvar()+1)*(_nvar()-i-1)] = _coefmon[_prodmon(i+1,i+2)];
01637     }
01638     double*D = _eigen( _nvar(), U );
01639     if( !D ){
01640       delete[] U;
01641       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::EIGEN );
01642     }
01643 
01644 #ifdef MC__TVAR_HYBRID_EIGEN
01645     T bndtype1(0.);
01646 #endif
01647     T bndtype2(0.);
01648     for( unsigned int i=0; i<_nvar(); i++ ){
01649       double linaux = 0.;
01650       T bndaux(0.);
01651       for( unsigned int k=0; k<_nvar(); k++ ){
01652         linaux += U[i*_nvar()+k] * _coefmon[_nvar()-k];
01653         bndaux += U[i*_nvar()+k] * _bndmon(_nvar()-k);
01654       }
01655 #ifdef MC__TVAR_DEBUG_EIGEN
01656       std::cout << i << ": LINAUX = " << linaux
01657                 << "  BNDAUX = " << bndaux << std::endl;
01658 #endif
01659 #ifdef MC__TVAR_HYBRID_EIGEN
01660       bndtype1 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
01661 #endif
01662 #ifdef MC__TVAR_DEBUG_EIGEN
01663       std::cout << std::endl << "BNDTYPE1: " << bndtype1 << std::endl;
01664 #endif
01665       if( std::fabs(D[i]) > TOL )
01666         bndtype2 += D[i] * Op<T>::sqr( linaux/D[i]/2. + bndaux )
01667           - linaux*linaux/D[i]/4.;
01668       else     
01669         //bndtype2 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
01670         bndtype2 += linaux * bndaux + D[i] * Op<T>::sqr( bndaux );
01671 #ifdef MC__TVAR_DEBUG_EIGEN
01672         std::cout << "BNDTYPE2: " << bndtype2 << std::endl;
01673 #endif
01674     }
01675     delete[] U;
01676     delete[] D;
01677 
01678 #ifdef MC__TVAR_HYBRID_EIGEN
01679     if( !Op<T>::inter( bndtype1, bndtype1, bndtype2 ) ){
01680       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
01681 #ifdef MC__TVAR_DEBUG_EIGEN
01682       std::cout << "BNDTYPE3: " << bndtype1 << std::endl;
01683 #endif
01684     }
01685     bndmod += bndtype1;
01686 #else
01687     bndmod += bndtype2;
01688 #endif
01689   }
01690 #ifdef MC__TVAR_DEBUG_EIGEN
01691       int tmp; std::cin >> tmp;
01692 #endif
01693 
01694   for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i];
01695   bndmod += *_bndrem;
01696 
01697   return bndmod;
01698 }
01699 
01700 template <typename T> inline T&
01701 TVar<T>::_bound_LSB
01702 ( T& bndmod ) const
01703 {
01704   static const double TOL = 1e-8;
01705   bndmod = _coefmon[0];
01706   if( _nord() == 1 ) bndmod += _bndord[1];
01707   else if( _nord() > 1 ){
01708     for( unsigned int i=1; i<=_nvar(); i++ ){
01709       // linear and diagonal quadratic terms
01710       unsigned int ii = _prodmon(i,i+1);
01711       if( std::fabs(_coefmon[ii]) > TOL )
01712         bndmod += _coefmon[ii] * Op<T>::sqr( _coefmon[i]/_coefmon[ii]/2.
01713           + _bndmon(i) ) - _coefmon[i]*_coefmon[i]/_coefmon[ii]/4.;
01714       else
01715         bndmod += _coefmon[i] * _bndmon(i) + _coefmon[ii] * _bndmon(ii);
01716       // off-diagonal quadratic terms
01717       for( unsigned int k=i+1; k<=_nvar(); k++ ){
01718    unsigned int ik = _prodmon(i,k+1) ;
01719    bndmod += _coefmon[ik] * _bndmon(ik);
01720       }
01721     }
01722   }
01723   // higher-order terms
01724   for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i];
01725   bndmod += *_bndrem;
01726   return bndmod;
01727 }
01728 
01729 template <typename T> inline T&
01730 TVar<T>::_bound_naive
01731 ( T& bndmod ) const
01732 {
01733   bndmod = _coefmon[0];
01734   for( unsigned int i=1; i<=_nord()+1; i++ ) bndmod += _bndord[i];
01735   return bndmod;
01736 }
01737 
01738 template <typename T> inline T&
01739 TVar<T>::_bound
01740 ( T& bndmod ) const
01741 {
01742   if( !_TM ){ bndmod = _coefmon[0] + _bndord[0]; return bndmod; }
01743 
01744   switch( _TM->options.BOUNDER_TYPE ){
01745   case TModel<T>::Options::NAIVE: bndmod = _bound_naive(bndmod); break;
01746   case TModel<T>::Options::LSB:   bndmod = _bound_LSB(bndmod);   break;
01747   case TModel<T>::Options::EIGEN: bndmod = _bound_eigen(bndmod); break;
01748   case TModel<T>::Options::HYBRID: default:{
01749     T bndlsb(0.), bndeig(0.);
01750     if( !Op<T>::inter( bndmod, _bound_LSB(bndlsb), _bound_eigen(bndeig) ) )
01751       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
01752    }
01753   }
01754 
01755   if( _TM->options.PROPAGATE_BNDT && _TM->options.INTER_WITH_BNDT
01756     && !Op<T>::inter( bndmod, bndmod, _bndT ) )
01757     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
01758 
01759   return bndmod;
01760 }
01761 
01762 template <typename T> inline double
01763 TVar<T>::polynomial
01764 ( const double*x ) const
01765 {
01766   if( !_TM ) return _coefmon[0];
01767   double Pval = _coefmon[0];
01768   for( unsigned int i=1; i<_nmon(); i++ ){
01769     double valmon = 1.;
01770     for( unsigned int k=0; k<_nvar(); k++ )
01771       valmon *= std::pow( x[k]/_scaling(k)-_refpoint(k),
01772                           _expmon(i*_nvar()+k) );
01773     Pval += _coefmon[i] * valmon;
01774   }
01775   return Pval;
01776 }
01777 
01778 template <typename T> inline double*
01779 TVar<T>::reference() const
01780 {
01781   if( !_TM ) return 0;
01782   if( _nvar() < 1 ) return 0;
01783   double*pref = new double[_nvar()];
01784   for( unsigned int i=0; i<_nvar(); i++ ) pref[i] = _refpoint(i)*_scaling(i);
01785   return pref;
01786 }
01787 
01788 template <typename T> inline double
01789 TVar<T>::constant() const
01790 {
01791   return _coefmon[0];
01792 }
01793 
01794 template <typename T> inline double*
01795 TVar<T>::linear() const
01796 {
01797   if( !_TM || !_nvar() || !_nord() ) return 0;
01798 
01799   double*plin = new double[_nvar()];
01800   for( unsigned int i=0; i<_nvar(); i++ )
01801     plin[i] = _coefmon[_nvar()-i] / _scaling(i);
01802   return plin;
01803 }
01804 
01805 template <typename T> inline double*
01806 TVar<T>::quadratic
01807 ( const int opt ) const
01808 {
01809   if( !_TM || !_nvar() || _nord() < 2 ) return 0;
01810 
01811   if( opt == 0 ){
01812     double*pquad = new double[_nvar()];
01813     for( unsigned int i=0; i<_nvar(); i++ )
01814       pquad[_nvar()-i-1] = _coefmon[_prodmon(i+1,i+2)]
01815         / _scaling(_nvar()-i-1) / _scaling(_nvar()-i-1);
01816     return pquad;
01817   }
01818 
01819   double*pquad = new double[_nvar()*_nvar()];
01820   for( unsigned int i=0; i<_nvar(); i++ ){
01821     for( unsigned int j=0; j<i; j++ ){
01822       pquad[_nvar()*(_nvar()-i-1)+_nvar()-j-1] = 0.;
01823       pquad[_nvar()*(_nvar()-j-1)+_nvar()-i-1] = _coefmon[_prodmon(i+1,j+2)]/2.
01824         / _scaling(_nvar()-i-1) / _scaling(_nvar()-j-1);
01825     }       
01826     pquad[(_nvar()+1)*(_nvar()-i-1)] = _coefmon[_prodmon(i+1,i+2)]
01827       / _scaling(_nvar()-i-1) / _scaling(_nvar()-i-1);
01828   }
01829   return pquad;  
01830 }
01831 
01832 template <typename T> inline std::ostream&
01833 operator <<
01834 ( std::ostream&out, const TVar<T>&TV )
01835 {
01836   const unsigned int iprec = 5;
01837   out << std::endl
01838       << std::scientific << std::setprecision(iprec) << std::right;
01839 
01840   // Display constant model
01841   if( !TV._TM ){
01842     out << "    a0   = " << std::right << std::setw(12) << TV._coefmon[0]
01843         << std::endl << std::endl;
01844     out << "  Order:        Bound:" << std::endl;
01845     out << std::setw(8) << "R" << "        " << *(TV._bndrem) << std::endl;
01846   }
01847 
01848   // Display monomial term coefficients and corresponding exponents
01849   else{
01850     for( unsigned int i=0; i<TV._nmon(); i++ ){
01851       out << "    a" << std::left << std::setw(3) << i << " = "
01852           << std::right << std::setw(12) << TV._coefmon[i] << "      ";
01853       for( unsigned int k=0; k<TV._nvar(); k++ )
01854         out << std::setw(3) << TV._expmon(i*TV._nvar()+k);
01855       out << "    B" << std::left << std::setw(3) << i << " = "
01856           << TV._bndmon(i) << std::endl;
01857     }
01858     out << std::endl;
01859 
01860     // Display bounds on terms of order 0,...,nord and remainder term
01861     out << "  Order:        Bound:" << std::endl;
01862     for( unsigned int i=0; i<=TV._nord(); i++ )
01863       out << std::right << std::setw(8) << i << "        " << TV._bndord[i]
01864           << std::endl;
01865     out << std::right << std::setw(8) << "R" << "        " << *(TV._bndrem)
01866         << std::endl << std::endl
01867         << "  TM Bounder:" << std::right << TV._TM->options.BOUNDER_TYPE;
01868   }
01869 
01870   // Display Taylor model bounds
01871   out << std::endl
01872       << "  TM Bound:" << std::right << std::setw(12) << TV.B()
01873       << std::endl;
01874   if( TV._TM && TV._TM->options.PROPAGATE_BNDT )
01875     out << "   T Bound:" << std::right << std::setw(12) << TV.boundT()
01876         << std::endl;
01877 
01878   return out;
01879 }
01880 
01881 template <typename T> inline TVar<T>
01882 operator +
01883 ( const TVar<T>&TV )
01884 {
01885   return TV;
01886 }
01887 
01888 template <typename T> template <typename U> inline TVar<T>&
01889 TVar<T>::operator +=
01890 ( const TVar<U>&TV )
01891 {
01892   if( !TV._TM ){
01893     if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT;
01894     _coefmon[0] += TV._coefmon[0];
01895     *_bndrem += *(TV._bndrem);
01896   }
01897   else if( !_TM ){
01898     TVar<T> TV2(*this);
01899     *this = TV; *this += TV2;
01900   }
01901   else{
01902     if( _TM != TV._TM )
01903       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
01904     if( _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT;
01905     for( unsigned int i=0; i<_nmon(); i++ )
01906       _coefmon[i] += TV._coefmon[i];
01907     *_bndrem += *(TV._bndrem);
01908     _update_bndord();
01909   }
01910   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
01911   return *this;
01912 }
01913 
01914 template <typename T, typename U> inline TVar<T>
01915 operator +
01916 ( const TVar<T>&TV1, const TVar<U>&TV2 )
01917 {
01918   TVar<T> TV3( TV1 );
01919   TV3 += TV2;
01920   return TV3;
01921 }
01922 
01923 template <typename T> inline TVar<T>&
01924 TVar<T>::operator +=
01925 ( const double c )
01926 {
01927   _coefmon[0] += c;
01928   if( _TM ) _bndord[0] = _coefmon[0];
01929   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += c;
01930   return *this;
01931 }
01932 
01933 template <typename T> inline TVar<T>
01934 operator +
01935 ( const TVar<T>&TV1, const double c )
01936 {
01937   TVar<T> TV3( TV1 );
01938   TV3 += c;
01939   return TV3;
01940 }
01941 
01942 template <typename T> inline TVar<T>
01943 operator +
01944 ( const double c, const TVar<T>&TV2 )
01945 {
01946   TVar<T> TV3( TV2 );
01947   TV3 += c;
01948   return TV3;
01949 }
01950 
01951 template <typename T> template <typename U> inline TVar<T>&
01952 TVar<T>::operator +=
01953 ( const U&I )
01954 {
01955   *_bndrem += I;
01956   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += I;
01957   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
01958   return *this;
01959 }
01960 
01961 template <typename T, typename U> inline TVar<T>
01962 operator +
01963 ( const TVar<T>&TV1, const U&I )
01964 {
01965   TVar<T> TV3( TV1 );
01966   TV3 += I;
01967   return TV3;
01968 }
01969 
01970 template <typename T, typename U> inline TVar<T>
01971 operator +
01972 ( const U&I, const TVar<T>&TV2 )
01973 {
01974   TVar<T> TV3( TV2 );
01975   TV2 += I;
01976   return TV3;
01977 }
01978 
01979 template <typename T> inline TVar<T>
01980 operator -
01981 ( const TVar<T>&TV )
01982 {
01983   if( !TV._TM ){
01984     TVar<T> TV2;
01985     TV2._coefmon[0] = -TV._coefmon[0];
01986     TV2._bndord[0] = -TV._bndord[0];
01987     return TV2;
01988   }
01989   TVar<T>& TV2 = *TV._TV();
01990   //TVar<T> TV2( TV._TM );
01991   for( unsigned int i=0; i<TV._nmon(); i++ ) TV2._coefmon[i] = -TV._coefmon[i];
01992   for( unsigned int i=0; i<TV._nord()+2; i++ ) TV2._bndord[i] = -TV._bndord[i];
01993   if( TV._TM->options.PROPAGATE_BNDT ) TV2._bndT = -TV._bndT;
01994   if( TV._TM->options.CENTER_REMAINDER ) TV2._center_TM();
01995   return TV2;
01996 }
01997 
01998 template <typename T> template <typename U> inline TVar<T>&
01999 TVar<T>::operator -=
02000 ( const TVar<U>&TV )
02001 {
02002   if( !TV._TM ){
02003     if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT;
02004     _coefmon[0] -= TV._coefmon[0];
02005     *_bndrem -= *(TV._bndrem);
02006   }
02007   else if( !_TM ){
02008     TVar<T> TV2(*this);
02009     *this = -TV; *this += TV2;
02010   }
02011   else{
02012     if( _TM != TV._TM )
02013       throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02014     if( _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT;
02015     for( unsigned int i=0; i<_nmon(); i++ )
02016       _coefmon[i] -= TV._coefmon[i];
02017     *_bndrem -= *(TV._bndrem);
02018     _update_bndord();
02019   }
02020   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02021   return *this;
02022 }
02023 
02024 template <typename T, typename U> inline TVar<T>
02025 operator-
02026 ( const TVar<T>&TV1, const TVar<U>&TV2 )
02027 {
02028   TVar<T> TV3( TV1 );
02029   TV3 -= TV2;
02030   return TV3;
02031 }
02032 
02033 template <typename T> inline TVar<T>&
02034 TVar<T>::operator -=
02035 ( const double c )
02036 {
02037   _coefmon[0] -= c;
02038   if( _TM ) _bndord[0] = _coefmon[0];
02039   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= c;
02040   return *this;
02041 }
02042 
02043 template <typename T> inline TVar<T>
02044 operator -
02045 ( const TVar<T>&TV1, const double c )
02046 {
02047   TVar<T> TV3( TV1 );
02048   TV3 -= c;
02049   return TV3;
02050 }
02051 
02052 template <typename T> inline TVar<T>
02053 operator -
02054 ( const double c, const TVar<T>&TV2 )
02055 {
02056   TVar<T> TV3( -TV2 );
02057   TV3 += c;
02058   return TV3;
02059 }
02060 
02061 template <typename T> template <typename U> inline TVar<T>&
02062 TVar<T>::operator -=
02063 ( const U&I )
02064 {
02065   *_bndrem -= I;
02066   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= I;
02067   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02068   return *this;
02069 }
02070 
02071 template <typename T, typename U> inline TVar<T>
02072 operator -
02073 ( const TVar<T>&TV1, const U&I )
02074 {
02075   TVar<T> TV3( TV1 );
02076   TV3 -= I;
02077   return TV3;
02078 }
02079 
02080 template <typename T, typename U> inline TVar<T>
02081 operator -
02082 ( const U&I, const TVar<T>&TV2 )
02083 {
02084   TVar<T> TV3( -TV2 );
02085   TV3 += I;
02086   return TV3;
02087 }
02088 
02089 template <typename T> inline TVar<T>&
02090 TVar<T>::operator *=
02091 ( const TVar<T>&TV )
02092 {
02093    TVar<T> TV2( *this );
02094    *this = TV * TV2;
02095    return *this;
02096 }
02097 
02098 template <typename T> inline TVar<T>
02099 operator *
02100 ( const TVar<T>&TV1, const TVar<T>&TV2 )
02101 {
02102   if( !TV2._TM )      return( TV1 * TV2._coefmon[0] + TV1 * *(TV2._bndrem) );
02103   else if( !TV1._TM ) return( TV2 * TV1._coefmon[0] + TV2 * *(TV1._bndrem) );
02104 
02105   if( TV1._TM != TV2._TM )
02106     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02107   TVar<T>& TV3 = *TV1._TV();
02108   for( unsigned int i=0; i<TV3._nmon(); i++ ) TV3._coefmon[i] = 0.;
02109   //TVar<T> TV3( TV1._TM, 0. );
02110 
02111   // Populate _coefmon for product term
02112   for( unsigned int i=0; i<TV3._posord(TV3._nord()/2+1); i++){
02113     TV3._coefmon[TV3._prodmon(i,i+1)] += TV1._coefmon[i] * TV2._coefmon[i];
02114     for( unsigned int j=i+1; j<TV3._prodmon(i,0); j++ )
02115       TV3._coefmon[TV3._prodmon(i,j+1)] += TV1._coefmon[i] * TV2._coefmon[j]
02116                                          + TV1._coefmon[j] * TV2._coefmon[i];
02117   }
02118   // Calculate remainder term _bndrem for product term
02119   T s1 = 0., s2 = 0.;
02120   for( unsigned int i=0; i<=TV3._nord()+1; i++ ){
02121     T r1 = 0., r2 = 0.;
02122     for( unsigned int j=TV3._nord()+1-i; j<=TV3._nord()+1; j++ ){
02123       r1 += TV1._bndord[j];
02124       r2 += TV2._bndord[j];
02125     }
02126     s1 += TV2._bndord[i] * r1 ;
02127     s2 += TV1._bndord[i] * r2 ;
02128   }
02129   if( !Op<T>::inter( *(TV3._bndrem), s1, s2) )
02130     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INTER );
02131   // Populate _bndord for product term (except remainder term)
02132   TV3._update_bndord();
02133   if( TV3._TM->options.PROPAGATE_BNDT ) TV3._bndT = TV1._bndT * TV2._bndT;
02134   if( TV3._TM->options.CENTER_REMAINDER ) TV3._center_TM();
02135   return TV3;
02136 }
02137 
02138 template <typename T> inline TVar<T>
02139 sqr
02140 ( const TVar<T>&TV )
02141 {
02142   if( !TV._TM ){
02143     TVar<T> TV2( TV );
02144     TV2._coefmon[0] *= TV2._coefmon[0];
02145     *(TV2._bndrem) *= 2. + *(TV2._bndrem);
02146     return TV2;
02147  }
02148 
02149   // Populate _coefmon for product term
02150   TVar<T> TV2( TV._TM, 0. );
02151   for( unsigned int i=0; i<TV2._posord(TV2._nord()/2+1); i++){
02152     TV2._coefmon[TV2._prodmon(i,i+1)] += TV._coefmon[i] * TV._coefmon[i];
02153     for( unsigned int j=i+1; j<TV2._prodmon(i,0); j++ )
02154       TV2._coefmon[TV2._prodmon(i,j+1)] += TV._coefmon[i] * TV._coefmon[j] * 2.;
02155   }
02156 
02157   T s = 0.;
02158   for( unsigned int i=0; i<=TV2._nord()+1; i++ ){
02159     unsigned int k = std::max(TV2._nord()+1-i, i+1);
02160     T r = 0.;
02161     for( unsigned int j=k; j<=TV2._nord()+1; j++ )
02162       r += TV._bndord[j];
02163     s += TV._bndord[i] * r;
02164   }
02165 
02166   T r = 0.;
02167   for( unsigned int i=TV2._nord()/2+1; i<=TV2._nord()+1; i++ )
02168     r += Op<T>::sqr(TV._bndord[i]) ;
02169   *(TV2._bndrem) = 2. * s + r;
02170   
02171   // Populate _bndord for product term (except remainder term)
02172   TV2._update_bndord();
02173   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqr( TV._bndT );
02174   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02175   return TV2;
02176 }
02177 
02178 template <typename T> inline TVar<T>&
02179 TVar<T>::operator *=
02180 ( const double c )
02181 {
02182   if( !_TM ){
02183     _coefmon[0] *= c;
02184     *(_bndrem) *= c;
02185   }
02186   else{
02187     for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= c;
02188     for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= c;
02189     if( _TM->options.PROPAGATE_BNDT ) _bndT *= c;
02190   }
02191   return *this;
02192 }
02193 
02194 template <typename T> inline TVar<T>
02195 operator *
02196 ( const TVar<T>&TV1, const double c )
02197 {
02198   TVar<T> TV3( TV1 );
02199   TV3 *= c;
02200   return TV3;
02201 }
02202 
02203 template <typename T> inline TVar<T>
02204 operator *
02205 ( const double c, const TVar<T>&TV2 )
02206 {
02207   TVar<T> TV3( TV2 );
02208   TV3 *= c;
02209   return TV3;
02210 }
02211 
02212 template <typename T> inline TVar<T>&
02213 TVar<T>::operator *=
02214 ( const T&I )
02215 {
02216   if( !_TM ){
02217     *(_bndrem) += _coefmon[0];
02218     _coefmon[0] = 0.;
02219     *(_bndrem) *= I;
02220   }
02221   else{
02222     const double Imid = Op<T>::mid(I);
02223     T Icur = bound();
02224     for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= Imid;
02225     for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= Imid;
02226     *_bndrem += (I-Imid)*Icur;
02227   }
02228   if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM();
02229   if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT *= I;
02230   return (*this);
02231 }
02232 
02233 template <typename T> inline TVar<T>
02234 operator *
02235 ( const TVar<T>&TV1, const T&I )
02236 {
02237   TVar<T> TV3( TV1 );
02238   TV3 *= I;
02239   return TV3;
02240 }
02241 
02242 template <typename T> inline TVar<T>
02243 operator *
02244 ( const T&I, const TVar<T>&TV2 )
02245 {
02246   TVar<T> TV3( TV2 );
02247   TV3 *= I;
02248   return TV3;
02249 }
02250 
02251 template <typename T> inline TVar<T>&
02252 TVar<T>::operator /=
02253 ( const TVar<T>&TV )
02254 {
02255    *this *= inv(TV);
02256    return *this;
02257 }
02258 
02259 template <typename T> inline TVar<T>
02260 operator /
02261 ( const TVar<T>&TV1, const TVar<T>&TV2 )
02262 {
02263   return TV1 * inv(TV2);
02264 }
02265 
02266 template <typename T> inline TVar<T>&
02267 TVar<T>::operator /=
02268 ( const double c )
02269 {
02270   if ( isequal( c, 0. ))
02271     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
02272    *this *= (1./c);
02273    return *this;
02274 }
02275 
02276 template <typename T> inline TVar<T>
02277 operator /
02278 ( const TVar<T>&TV, const double c )
02279 {
02280   if ( isequal( c, 0. ))
02281     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
02282   return TV * (1./c);
02283 }
02284 
02285 template <typename T> inline TVar<T>
02286 operator /
02287 ( const double c, const TVar<T>&TV )
02288 {
02289   return inv(TV) * c;
02290 }
02291 
02292 template <typename T> inline TVar<T>
02293 inv
02294 ( const TVar<T>&TV )
02295 {
02296   if( !TV._TM ){
02297     TVar<T> TV2( TV );
02298     TV2._coefmon[0] = 0.;
02299     *(TV2._bndrem) = Op<T>::inv(TV._coefmon[0] + *(TV._bndrem));
02300     return TV2;
02301   }
02302 
02303   const T I( TV.B() );
02304   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02305                 TV._coefmon[0] + Op<T>::mid(*TV._bndrem) );
02306   const TVar<T> TVmx0( TV - x0 );
02307   const T Imx0( I - x0 );
02308 
02309   TVar<T> TV2( 1. ), MON( 1. );
02310   for( unsigned int i=1; i<=TV._nord(); i++ ){
02311     MON *= TVmx0 / (-x0);
02312     TV2 += MON;
02313   }
02314   TV2 /= x0;
02315   TV2 += Op<T>::pow( -Imx0, (int)TV2._nord()+1 )
02316        / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+2 );
02317   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::inv( TV._bndT );
02318   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02319   return TV2;
02320 }
02321 
02322 template <typename T> inline TVar<T>
02323 sqrt
02324 ( const TVar<T>&TV )
02325 {
02326   if( !TV._TM ){
02327     TVar<T> TV2( TV );
02328     TV2._coefmon[0] = 0.;
02329     *(TV2._bndrem) = Op<T>::sqrt(TV._coefmon[0] + *(TV._bndrem));
02330     return TV2;
02331   }
02332 
02333   const T I( TV.B() );
02334   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02335                 TV._coefmon[0] + Op<T>::mid(*TV._bndrem) );
02336   const TVar<T> TVmx0( TV - x0 );
02337   const T Imx0( I - x0 );
02338 
02339   double s = 0.5;
02340   TVar<T> TV2( 1. ), MON( 1. );
02341   for( unsigned int i=1; i<=TV._nord(); i++ ){
02342     MON *= TVmx0 / x0;
02343     TV2 += MON * s;
02344     s *= -(2.*i-1.)/(2.*i+2.);
02345   }
02346   TV2 *= std::sqrt(x0);
02347   TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02348            / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+1/2 );
02349   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqrt( TV._bndT );
02350   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02351   return TV2;
02352 }
02353 
02354 template <typename T> inline TVar<T>
02355 exp
02356 ( const TVar<T>&TV )
02357 { 
02358   if( !TV._TM ){
02359     TVar<T> TV2( TV );
02360     TV2._coefmon[0] = 0.;
02361     *(TV2._bndrem) = Op<T>::exp(TV._coefmon[0] + *(TV._bndrem));
02362     return TV2;
02363   }
02364 
02365   const T I( TV.B() );
02366 #ifdef MC__TVAR_DEBUG_EXP
02367   std::cout << "DEBUG EXP TV:" << TV << std::endl;
02368 #endif
02369   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02370                 TV._coefmon[0] + Op<T>::mid(*TV._bndrem) );
02371 #ifdef MC__TVAR_DEBUG_EXP
02372   std::cout << "DEBUG EXP X0:" << x0 << std::endl;
02373 #endif
02374   const TVar<T> TVmx0( TV - x0 );
02375 #ifdef MC__TVAR_DEBUG_EXP
02376   std::cout << "DEBUG EXP TV-X0:" << TVmx0 << std::endl;
02377 #endif
02378   const T Imx0( I - x0 );
02379 
02380   double s = 1.;
02381   TVar<T> TV2( 1. ), MON( 1. );
02382 #ifdef MC__TVAR_DEBUG_EXP
02383   std::cout << "DEBUG EXP TV2:" << TV2 << std::endl;
02384 #endif
02385   for( unsigned int i=1; i<=TV._nord(); i++ ){
02386     MON *= TVmx0;
02387     TV2 += MON * s;
02388     s /= i+1.;
02389 #ifdef MC__TVAR_DEBUG_EXP
02390     std::cout << "DEBUG EXP TV2:" << TV2 << std::endl;
02391 #endif
02392   }
02393 #ifdef MC__TVAR_DEBUG_EXP
02394     std::cout << "DEBUG EXP REM:" << s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02395            * Op<T>::exp( Op<T>::zeroone()*Imx0 ) << std::endl;
02396 #endif
02397   TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02398            * Op<T>::exp( Op<T>::zeroone()*Imx0 );
02399 #ifdef MC__TVAR_DEBUG_EXP
02400   std::cout << "DEBUG EXP TV2:" << TV2 << std::endl;
02401 #endif
02402   TV2 *= std::exp(x0);
02403 #ifdef MC__TVAR_DEBUG_EXP
02404   std::cout << "DEBUG EXP TV2:" << TV2 << std::endl;
02405 #endif
02406   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::exp( TV._bndT );
02407   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02408   return TV2;
02409 }
02410 
02411 template <typename T> inline TVar<T>
02412 log
02413 ( const TVar<T>&TV )
02414 {
02415   if( !TV._TM ){
02416     TVar<T> TV2( TV );
02417     TV2._coefmon[0] = 0.;
02418     *(TV2._bndrem) = Op<T>::log(TV._coefmon[0] + *(TV._bndrem));
02419     return TV2;
02420   }
02421 
02422   const T I( TV.B() );
02423   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02424                 TV._coefmon[0] + Op<T>::mid(*TV._bndrem) );
02425   const TVar<T> TVmx0( TV - x0 );
02426   const T Imx0( I - x0 );
02427 
02428   TVar<T> TV2( 0. ), MON( -1. );
02429   for( unsigned int i=1; i<=TV._nord(); i++ ){
02430     MON *= TVmx0 / (-x0);
02431     TV2 += MON / (double)i;
02432   }
02433   TV2 += std::log(x0) - Op<T>::pow( - Imx0 / ( Op<T>::zeroone()*Imx0+x0 ),
02434        (int)TV2._nord()+1 ) / ( TV2._nord()+1. );
02435   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::log( TV._bndT );
02436   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02437   return TV2;
02438 }
02439 
02440 template <typename T> inline TVar<T>
02441 xlog
02442 ( const TVar<T>&TV )
02443 {
02444   return TV * log( TV );
02445 }
02446 
02447 template <typename T> inline TVar<T>
02448 pow
02449 ( const TVar<T>&TV, const int n )
02450 {
02451   if( !TV._TM ){
02452     TVar<T> TV2( TV );
02453     TV2._coefmon[0] = 0.;
02454     *(TV2._bndrem) = Op<T>::pow(TV._coefmon[0] + *(TV._bndrem), n);
02455     return TV2;
02456   }
02457 
02458   if( n < 0 ) return pow( inv( TV ), -n );
02459   TVar<T> TV2( _intpow( TV, n ) );
02460   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::pow( TV._bndT, n );
02461   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02462   return TV2;
02463 }
02464 
02465 template <typename T> inline TVar<T>
02466 _intpow
02467 ( const TVar<T>&TV, const int n )
02468 {
02469   if( n == 0 ) return 1.;
02470   else if( n == 1 ) return TV;
02471   return n%2 ? sqr( _intpow( TV, n/2 ) ) * TV : sqr( _intpow( TV, n/2 ) );
02472 }
02473 
02474 template <typename T> inline TVar<T>
02475 pow
02476 ( const TVar<T> &TV, const double a )
02477 {
02478   return exp( a * log( TV ) );
02479 }
02480 
02481 template <typename T> inline TVar<T>
02482 pow
02483 ( const TVar<T> &TV1, const TVar<T> &TV2 )
02484 {
02485   return exp( TV2 * log( TV1 ) );
02486 }
02487 
02488 template <typename T> inline TVar<T>
02489 pow
02490 ( const double a, const TVar<T> &TV )
02491 {
02492   return exp( TV * std::log( a ) );
02493 }
02494 
02495 template <typename T> inline TVar<T>
02496 monomial
02497 (const unsigned int n, const TVar<T>*TV, const int*k)
02498 {
02499   if( n == 0 ){
02500     return 1.;
02501   }
02502   if( n == 1 ){
02503     return pow( TV[0], k[0] );
02504   }
02505   return pow( TV[0], k[0] ) * monomial( n-1, TV+1, k+1 );
02506 }
02507 
02508 template <typename T> inline TVar<T>
02509 cos
02510 ( const TVar<T> &TV )
02511 {
02512   if( !TV._TM ){
02513     TVar<T> TV2( TV );
02514     TV2._coefmon[0] = 0.;
02515     *(TV2._bndrem) = Op<T>::cos(TV._coefmon[0] + *(TV._bndrem));
02516     return TV2;
02517   }
02518 
02519   const T I( TV.B() );
02520   double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
02521                 TV._coefmon[0] + Op<T>::mid(*TV._bndrem) );
02522   const TVar<T> TVmx0( TV - x0 );
02523   const T Imx0( I - x0 );
02524   double s = 1., c;
02525 
02526   TVar<T> TV2( 0. ), MON( 1. );
02527   for( unsigned int i=1; i<=TV._nord(); i++ ){
02528     switch( i%4 ){
02529     case 0: c =  std::cos(x0); break;
02530     case 1: c = -std::sin(x0); break;
02531     case 2: c = -std::cos(x0); break;
02532     case 3:
02533     default: c =  std::sin(x0); break;
02534     }
02535     MON *= TVmx0;
02536     TV2 += c * s * MON;
02537     s /= i+1;
02538   }
02539 
02540   switch( (TV2._nord()+1)%4 ){
02541   case 0: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02542                    * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
02543   case 1: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02544                    * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
02545   case 2: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02546                    * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
02547   case 3: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 )
02548                    * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
02549   }
02550   TV2 += std::cos(x0);
02551 
02552   if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::cos( TV._bndT );
02553   if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM();
02554   return TV2;
02555 }
02556 
02557 template <typename T> inline TVar<T>
02558 sin
02559 ( const TVar<T> &TV )
02560 {
02561   return cos( TV - PI/2. );
02562 }
02563 
02564 template <typename T> inline TVar<T>
02565 asin
02566 ( const TVar<T> &TV )
02567 {
02568   throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF );
02569   return 0.;
02570 }
02571 
02572 template <typename T> inline TVar<T>
02573 acos
02574 ( const TVar<T> &TV )
02575 {
02576   return asin( -TV ) + PI/2.;
02577 }
02578 
02579 template <typename T> inline TVar<T>
02580 tan
02581 ( const TVar<T> &TV )
02582 {
02583   return sin(TV) / cos(TV);
02584 }
02585 
02586 template <typename T> inline TVar<T>
02587 atan
02588 ( const TVar<T> &TV )
02589 {
02590   return asin(TV) / acos(TV);
02591 }
02592 
02593 template <typename T> inline TVar<T>
02594 hull
02595 ( const TVar<T>&TV1, const TVar<T>&TV2 )
02596 {
02597   if( TV1._TM != TV2._TM )
02598     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02599   return TV1.P() + ( TV2.P() - TV1.P() ).B() + Op<T>::hull( TV1.R(), TV2.R() );
02600 }
02601 
02602 template <typename T> inline bool
02603 inter
02604 ( TVar<T>&TVR, const TVar<T>&TV1, const TVar<T>&TV2 )
02605 {
02606   if( TV1._TM != TV2._TM )
02607     throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
02608   TVar<T> TV1C( TV1 ), TV2C( TV2 );
02609 
02610 //   if( !TV1._TM->options.REF_INTER ){
02611 //     T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 
02612 //     TVR = TV1C;
02613 //     T R1C = TV1C.R(), R2C = TV2C.C().R(); 
02614 //     TV1C -= TV2C;
02615 //     *(TV1C._bndrem) = 0;
02616 //     T BTVD = TV1C.B();
02617 //     return Op<T>::inter(*(TVR._bndrem), R1C, R2C-BTVD)? true: false;
02618 //   }
02619 
02620   double eta = TV1._TM->options.REF_INTER;
02621   T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 
02622   TVR = (1.-eta)*TV1C + eta*TV2C;
02623   TV1C -= TV2C;
02624   *(TV1C._bndrem) = 0;
02625   T BTVD = TV1C.B();
02626   return Op<T>::inter(*(TVR._bndrem), R1C+eta*BTVD, R2C-(1.-eta)*BTVD)? true: false;
02627 
02628 //   TVR = TV1C.C();
02629 //   T R1C = TV1C.R(), R2C = TV2C.C().R(); 
02630 //   TV1C -= TV2C;
02631 //   TV1C *= 0.5;
02632 //   *(TV1C._bndrem) = 0;
02633 //   T BTVD = TV1C.B();
02634 //   return( Op<T>::inter( *(TVR._bndrem), R1C+BTVD, R2C-BTVD ) ? true: false );
02635 }
02636 
02637 } // namespace mc
02638 
02639 #include "mcop.h"
02640 
02641 namespace mc
02642 {
02643 
02645 template <> template<typename T> struct Op< mc::TVar<T> >
02646 {
02647   typedef mc::TVar<T> TV;
02648   static TV point( const double c ) { return TV(c); }
02649   static TV zeroone() { return TV( mc::Op<T>::zeroone() ); }
02650   static void I(TV& x, const TV&y) { x = y; }
02651   static double l(const TV& x) { return mc::Op<T>::l(x.B()); }
02652   static double u(const TV& x) { return mc::Op<T>::u(x.B()); }
02653   static double abs (const TV& x) { return mc::Op<T>::abs(x.B());  }
02654   static double mid (const TV& x) { return mc::Op<T>::mid(x.B());  }
02655   static double diam(const TV& x) { return mc::Op<T>::diam(x.B()); }
02656   static TV inv (const TV& x) { return mc::inv(x);  }
02657   static TV sqr (const TV& x) { return mc::sqr(x);  }
02658   static TV sqrt(const TV& x) { return mc::sqrt(x); }
02659   static TV log (const TV& x) { return mc::log(x);  }
02660   static TV xlog(const TV& x) { return x*mc::log(x); }
02661   static TV fabs(const TV& x) { return TV( mc::Op<T>::fabs(x.B()) ); }
02662   static TV exp (const TV& x) { return mc::exp(x);  }
02663   static TV sin (const TV& x) { return mc::sin(x);  }
02664   static TV cos (const TV& x) { return mc::cos(x);  }
02665   static TV tan (const TV& x) { return mc::tan(x);  }
02666   static TV asin(const TV& x) { return mc::asin(x); }
02667   static TV acos(const TV& x) { return mc::acos(x); }
02668   static TV atan(const TV& x) { return mc::atan(x); }
02669   static TV erf (const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ); return 0.; }
02670   static TV erfc(const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ); return 0.; }
02671   static TV hull(const TV& x, const TV& y) { return mc::hull(x,y); }
02672   static TV min (const TV& x, const TV& y) { return mc::Op<T>::min(x.B(),y.B());  }
02673   static TV max (const TV& x, const TV& y) { return mc::Op<T>::max(x.B(),y.B());  }
02674   static TV arh (const TV& x, const double k) { return mc::exp(-k/x); }
02675   template <typename X, typename Y> static TV pow(const X& x, const Y& y) { return mc::pow(x,y); }
02676   static TV monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); }
02677   static bool inter(TV& xIy, const TV& x, const TV& y) { return mc::inter(xIy,x,y); }//T xIy0; bool flag = mc::Op<T>::inter(xIy0,x.B(),y.B()); xIy = xIy0; return flag; }
02678   static bool eq(const TV& x, const TV& y) { return mc::Op<T>::eq(x.B(),y.B()); }
02679   static bool ne(const TV& x, const TV& y) { return mc::Op<T>::ne(x.B(),y.B()); }
02680   static bool lt(const TV& x, const TV& y) { return mc::Op<T>::lt(x.B(),y.B()); }
02681   static bool le(const TV& x, const TV& y) { return mc::Op<T>::le(x.B(),y.B()); }
02682   static bool gt(const TV& x, const TV& y) { return mc::Op<T>::gt(x.B(),y.B()); }
02683   static bool ge(const TV& x, const TV& y) { return mc::Op<T>::ge(x.B(),y.B()); }
02684 };
02685 
02686 } // namespace mc
02687 
02688 #endif