MC++
tmodel.hpp
1 // Copyright (C) 2009-2014 Benoit Chachuat, Imperial College London.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 
375 #ifndef MC__TMODEL_H
376 #define MC__TMODEL_H
377 
378 #include "polymodel.hpp"
379 #include "mcop.hpp"
380 #include "mclapack.hpp"
381 
382 #undef MC__TMODEL_DEBUG
383 #undef MC__TMODEL_DEBUG_SCALE
384 #define MC__TMODEL_CHECK
385 #undef MC__TMODEL_CHECK_PMODEL
386 #undef MC__TVAR_DISPLAY_EXT
387 #undef MC__TVAR_DEBUG_EXP
388 #undef MC__TVAR_DEBUG_BERSTEIN
389 #undef MC__TVAR_HYBRID_EIGEN
390 #define MC__TMODEL_TIGHT_REMAINDER
391 
392 namespace mc
393 {
394 
395 template <typename T> class TVar;
396 
405 template <typename T>
406 class TModel: public PolyModel
408 {
409  friend class TVar<T>;
410  template <typename U> friend class TModel;
411 
412  template <typename U> friend TVar<U> inv
413  ( const TVar<U>& );
414  template <typename U> friend TVar<U> sqrt
415  ( const TVar<U>& );
416  template <typename U> friend TVar<U> log
417  ( const TVar<U>& );
418  template <typename U> friend TVar<U> exp
419  ( const TVar<U>& );
420  template <typename U> friend TVar<U> pow
421  ( const TVar<U>&, const int );
422 
423 public:
424 
428  TModel
430  ( const unsigned int nvar, const unsigned int nord )
431  : PolyModel( nvar, nord )
432  { _size(); }
433 
436  { _cleanup(); }
437 
439  const T* bndmon() const
440  { return _bndmon; };
441 
443  const unsigned int* const* prodmon() const
444  { return _prodmon; };
445 
447  const double* reference() const
448  { return _refpoint; }
449 
451  const double* scaling() const
452  { return _scaling; }
453 
455  void reset()
456  { _reset(); };
457 
460  {
461  public:
463  enum TYPE{
464  DIV=1,
465  INV,
466  LOG,
471  INIT=-1,
472  INCON=-2,
473  TMODEL=-3,
474  UNDEF=-33
475  };
477  Exceptions( TYPE ierr ) : _ierr( ierr ){}
479  int ierr(){ return _ierr; }
481  std::string what(){
482  switch( _ierr ){
483  case DIV:
484  return "mc::TModel\t Division by zero scalar";
485  case INV:
486  return "mc::TModel\t Inverse operation with zero in range";
487  case LOG:
488  return "mc::TModel\t Log operation with non-positive numbers in range";
489  case SQRT:
490  return "mc::TModel\t Square-root operation with negative numbers in range";
491  case ASIN:
492  return "mc::TModel\t Sine/Cosine inverse operation with range outside [-1,1]";
493  case EIGEN:
494  return "mc::TModel\t Range bounder with eigenvalue decomposition failed";
495  case BERNSTEIN:
496  return "mc::TModel\t Bernstein remainder evalution failed";
497  case INIT:
498  return "mc::TModel\t Taylor variable initialization failed";
499  case INCON:
500  return "mc::TModel\t Inconsistent bounds with template parameter arithmetic";
501  case TMODEL:
502  return "mc::TModel\t Operation between Taylor variables in different Taylor model environment not allowed";
503  case UNDEF:
504  return "mc::TModel\t Feature not yet implemented in mc::TModel class";
505  default:
506  return "mc::TModel\t Undocumented error";
507  }
508  }
509 
510  private:
511  TYPE _ierr;
512  };
513 
515  struct Options
516  {
520  CENTER_REMAINDER(false), REF_MIDPOINT(false), REF_POLY(0.),
521  BERNSTEIN_USE(false), BERNSTEIN_OPT(true), BERNSTEIN_MAXIT(100),
522  BERNSTEIN_TOL(1e-10), DISPLAY_DIGITS(5)
523  {}
525  template <typename U> Options
526  ( U&options )
527  : BOUNDER_TYPE( options.BOUNDER_TYPE ),
528  BOUNDER_ORDER( options.BOUNDER_ORDER ),
529  SCALE_VARIABLES( options.SCALE_VARIABLES ),
530  CENTER_REMAINDER( options.CENTER_REMAINDER ),
531  REF_MIDPOINT( options.REF_MIDPOINT ),
532  REF_POLY(options.REF_POLY),
533  BERNSTEIN_USE(options.BERNSTEIN_USE),
534  BERNSTEIN_OPT(options.BERNSTEIN_OPT),
535  BERNSTEIN_MAXIT(options.BERNSTEIN_MAXIT),
536  BERNSTEIN_TOL(options.BERNSTEIN_TOL),
537  DISPLAY_DIGITS(options.DISPLAY_DIGITS)
538  {}
540  template <typename U> Options& operator =
541  ( U&options ){
542  BOUNDER_TYPE = options.BOUNDER_TYPE;
543  BOUNDER_ORDER = options.BOUNDER_ORDER;
544  SCALE_VARIABLES = options.SCALE_VARIABLES;
545  CENTER_REMAINDER = options.CENTER_REMAINDER;
546  REF_MIDPOINT = options.REF_MIDPOINT,
547  REF_POLY = options.REF_POLY,
548  BERNSTEIN_USE = options.BERNSTEIN_USE,
549  BERNSTEIN_OPT = options.BERNSTEIN_OPT,
550  BERNSTEIN_MAXIT = options.BERNSTEIN_MAXIT,
551  BERNSTEIN_TOL = options.BERNSTEIN_TOL,
552  DISPLAY_DIGITS = options.DISPLAY_DIGITS;
553  return *this;
554  }
556  enum BOUNDER{
557  NAIVE=0,
558  LSB,
562  };
566  unsigned int BOUNDER_ORDER;
568  static const std::string BOUNDER_NAME[5];
576  double REF_POLY;
582  unsigned int BERNSTEIN_MAXIT;
586  unsigned int DISPLAY_DIGITS;
587  } options;
590 private:
592  unsigned int **_prodmon;
593 
595  T *_bndmon;
596 
598  T **_bndpow;
599 
601  double *_refpoint;
602 
604  double *_scaling;
605 
607  double *_cbern;
608 
610  TVar<T>* _TV;
611 
613  void _size
614  ();
615 
617  void _reset();
618 
620  void _cleanup();
621 
623  void _set_bndpow
624  ( const unsigned int ivar, const T&X, const double Xref,
625  const double scaling );
626 
628  void _set_bndmon();
629 
631  void _set_prodmon();
632 
634  void _scale
635  ( const unsigned int ivar, double*coef ) const;
636 
638  typedef double (puniv)
639  ( const double x, const double*rusr, const int*iusr );
640 
642  typedef double (punivopt)
643  ( const double x, const double*rusr, const int*iusr, puniv df,
644  const T&I, const std::pair<unsigned int,const double*>&bern );
645 
647  typedef T (punivext)
648  ( const T&x, const double*rusr, const int*iusr );
649 
651  TVar<T> _univ_bernstein
652  ( const TVar<T>&TV, puniv f, puniv df, punivext If,
653  punivext d2If, const double*rusr, const int*iusr );
654 
656  static double _gap_bernstein
657  ( const double x, const double*rusr, const int*iusr, puniv df,
658  const T&I, const std::pair<unsigned int,const double*>&bern );
659 
661  static double _dgap_bernstein
662  ( const double x, const double*rusr, const int*iusr, puniv df,
663  const T&I, const std::pair<unsigned int,const double*>&bern );
664 
666  double _goldsect
667  ( const double xL, const double xU, punivopt fopt, const double*rusr,
668  const int*iusr, puniv df, const T&Ix,
669  const std::pair<unsigned int,const double*>&bern );
670 
672  double _goldsect_iter
673  ( const bool init, const double a, const double fa, const double b,
674  const double fb, const double c, const double fc, punivopt fopt,
675  const double*rusr, const int*iusr, puniv df, const T&Ix,
676  const std::pair<unsigned int,const double*>&bern );
677 
679  TVar<T> _intpow
680  ( const TVar<T>&TV, const int n );
681 
683  TVar<T> _inv_taylor
684  ( const TVar<T>&TV );
685 
687  TVar<T> _inv_bernstein
688  ( const TVar<T>&TV );
689 
691  TVar<T> _sqrt_taylor
692  ( const TVar<T>&TV );
693 
695  TVar<T> _sqrt_bernstein
696  ( const TVar<T>&TV );
697 
699  TVar<T> _exp_taylor
700  ( const TVar<T>&TV );
701 
703  TVar<T> _exp_bernstein
704  ( const TVar<T>&TV );
705 
707  TVar<T> _log_taylor
708  ( const TVar<T>&TV );
709 
711  TVar<T> _log_bernstein
712  ( const TVar<T>&TV );
713 } ;
714 
715 template <typename T> const std::string TModel<T>::Options::BOUNDER_NAME[5]
716  = { "NAIVE", "LSB", "EIGEN", "BERNSTEIN", "HYBRID" };
717 
724 template <typename T>
725 class TVar: public PolyVar<T>
727 {
728  template <typename U> friend class TVar;
729  template <typename U> friend class TModel;
730 
731  template <typename U> friend TVar<U> operator+
732  ( const TVar<U>& );
733  template <typename U, typename V> friend TVar<U> operator+
734  ( const TVar<U>&, const TVar<V>& );
735  template <typename U> friend TVar<U> operator+
736  ( const TVar<U>&, const U& );
737  template <typename U> friend TVar<U> operator+
738  ( const U&, const TVar<U>& );
739  template <typename U> friend TVar<U> operator+
740  ( const double, const TVar<U>& );
741  template <typename U> friend TVar<U> operator+
742  ( const TVar<U>&, const double );
743  template <typename U> friend TVar<U> operator-
744  ( const TVar<U>& );
745  template <typename U, typename V> friend TVar<U> operator-
746  ( const TVar<U>&, const TVar<V>& );
747  template <typename U> friend TVar<U> operator-
748  ( const TVar<U>&, const U& );
749  template <typename U> friend TVar<U> operator-
750  ( const U&, const TVar<U>& );
751  template <typename U> friend TVar<U> operator-
752  ( const double, const TVar<U>& );
753  template <typename U> friend TVar<U> operator-
754  ( const TVar<U>&, const double );
755  template <typename U> friend TVar<U> operator*
756  ( const TVar<U>&, const TVar<U>& );
757  template <typename U> friend TVar<U> operator*
758  ( const double, const TVar<U>& );
759  template <typename U> friend TVar<U> operator*
760  ( const TVar<U>&, const double );
761  template <typename U> friend TVar<U> operator*
762  ( const U&, const TVar<U>& );
763  template <typename U> friend TVar<U> operator*
764  ( const TVar<U>&, const U& );
765  template <typename U> friend TVar<U> operator/
766  ( const TVar<U>&, const TVar<U>& );
767  template <typename U> friend TVar<U> operator/
768  ( const double, const TVar<U>& );
769  template <typename U> friend TVar<U> operator/
770  ( const TVar<U>&, const double );
771  template <typename U> friend std::ostream& operator<<
772  ( std::ostream&, const TVar<U>& );
773 
774  template <typename U> friend TVar<U> inv
775  ( const TVar<U>& );
776  template <typename U> friend TVar<U> sqr
777  ( const TVar<U>& );
778  template <typename U> friend TVar<U> sqrt
779  ( const TVar<U>& );
780  template <typename U> friend TVar<U> exp
781  ( const TVar<U>& );
782  template <typename U> friend TVar<U> log
783  ( const TVar<U>& );
784  template <typename U> friend TVar<U> xlog
785  ( const TVar<U>& );
786  template <typename U> friend TVar<U> pow
787  ( const TVar<U>&, const int );
788  template <typename U> friend TVar<U> pow
789  ( const TVar<U>&, const double );
790  template <typename U> friend TVar<U> pow
791  ( const double, const TVar<U>& );
792  template <typename U> friend TVar<U> pow
793  ( const TVar<U>&, const TVar<U>& );
794  template <typename U> friend TVar<U> monomial
795  ( const unsigned int, const TVar<U>*, const int* );
796  template <typename U> friend TVar<U> cos
797  ( const TVar<U>& );
798  template <typename U> friend TVar<U> sin
799  ( const TVar<U>& );
800  template <typename U> friend TVar<U> tan
801  ( const TVar<U>& );
802  template <typename U> friend TVar<U> acos
803  ( const TVar<U>& );
804  template <typename U> friend TVar<U> asin
805  ( const TVar<U>& );
806  template <typename U> friend TVar<U> atan
807  ( const TVar<U>& );
808  template <typename U> friend TVar<U> hull
809  ( const TVar<U>&, const TVar<U>& );
810  template <typename U> friend bool inter
811  ( TVar<U>&, const TVar<U>&, const TVar<U>& );
812 
813 public:
814  using PolyVar<T>::_coefmon;
815  using PolyVar<T>::_bndord;
816  using PolyVar<T>::_bndord_uptd;
817  using PolyVar<T>::_bndrem;
818  using PolyVar<T>::_bndpol;
819  using PolyVar<T>::_set_bndpol;
820  using PolyVar<T>::_unset_bndpol;
821  using PolyVar<T>::nvar;
822  using PolyVar<T>::nord;
823  using PolyVar<T>::nmon;
824  using PolyVar<T>::_posord;
825  using PolyVar<T>::_expmon;
826  using PolyVar<T>::_loc_expmon;
827  using PolyVar<T>::_get_binom;
828  using PolyVar<T>::_resize;
829  using PolyVar<T>::_set;
830  using PolyVar<T>::set;
831  using PolyVar<T>::get;
832  using PolyVar<T>::bound;
833  using PolyVar<T>::bndord;
834  using PolyVar<T>::_center;
835  //using PolyVar<T>::remainder;
836  //using PolyVar<T>::polynomial;
837  //using PolyVar<T>::B;
838  //using PolyVar<T>::R;
839  //using PolyVar<T>::P;
840  //using PolyVar<T>::coefmon;
841  //using PolyVar<T>::expmon;
842 
843 private:
845  TModel<T> *_TM;
846 
848  TVar<T>* _TV() const
849  { return _TM->_TV; };
850 
852  unsigned int _prodmon
853  ( const unsigned int imon, const unsigned int jmon ) const
854  { return _TM->prodmon()[imon][jmon]; };
855 
857  const T& _bndmon
858  ( const unsigned int imon ) const
859  { return _TM->bndmon()[imon]; };
860 
862  double _refpoint
863  ( const unsigned int ivar ) const
864  { return _TM->_refpoint[ivar]; };
865 
867  double _scaling
868  ( const unsigned int ivar ) const
869  { return _TM->_scaling[ivar]; };
870 
871 public:
875  TModel<T>* env() const
877  { return _TM; }
878 
880  TVar
881  ( const double d=0. );
882 
884  TVar
885  ( const T&B );
886 
888  TVar
889  ( TModel<T>*TM, const unsigned int ix, const T&X, const double Xref );
890 
892  TVar
893  ( TModel<T>*TM, const unsigned int ix, const T&X );
894 
896  template <typename U> TVar
897  ( TModel<T>*&TM, const TVar<U>&TV );
898 
900  template <typename U> TVar
901  ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const );
902 
904  template <typename U> TVar
905  ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) );
906 
908  TVar
909  ( const TVar<T>&TV )
910  : PolyVar<T>( TV ), _TM( TV._TM )
911  {
912 #ifdef MC__TMODEL_CHECK_PMODEL
913  if( _TM != dynamic_cast< TModel<T>* >( PolyVar<T>::_PM ) ) assert( false );
914 #endif
915  }
916 
919  {}
922 private:
924  TVar
925  ( TModel<T>*TM, const double d=0. );
926 
928  TVar
929  ( TModel<T>*TM, const T&B );
930 
932  TVar<T>& _set
933  ( const unsigned int ivar, const T&X, const double Xref );
934 
935 public:
939  TVar<T>& set
941  ( TModel<T>*TM, const unsigned int ix, const T&X, const double Xref )
942  { set( TM ); _TM = TM; _set( ix, X, Xref ); return *this; }
943 
945  TVar<T>& set
946  ( TModel<T>*TM, const unsigned int ix, const T&X )
947  { return set( TM, ix, X, Op<T>::mid(X) ); }
948 
950  TVar<T>& set
951  ( TModel<T>*TM )
952  { if( TM != _TM ){ _TM = TM; PolyVar<T>::set( _TM ); } return *this; }
953 
955  double polynomial
956  ( const double*x ) const;
957 
959  double P
960  ( const double*x ) const
961  { return polynomial( x ); }
962 
965  ()
966  const
967  { TVar<T> var = *this; *(var._bndrem) = 0.; return var; }
968 
970  TVar<T> P
971  ()
972  const
973  { return polynomial(); }
974 
977  { _center(); return *this; }
978 
981  { return center(); }
982 
984  double constant
985  ( const bool reset=false );
986 
988  double* linear() const;
989 
991  double linear
992  ( const unsigned int ivar, const bool reset=false );
995  TVar<T>& operator =
996  ( const TVar<T>& );
997  TVar<T>& operator =
998  ( const double );
999  TVar<T>& operator =
1000  ( const T& );
1001  template <typename U> TVar<T>& operator +=
1002  ( const TVar<U>& );
1003  template <typename U> TVar<T>& operator +=
1004  ( const U& );
1005  TVar<T>& operator +=
1006  ( const double );
1007  template <typename U> TVar<T>& operator -=
1008  ( const TVar<U>& );
1009  template <typename U> TVar<T>& operator -=
1010  ( const U& );
1011  TVar<T>& operator -=
1012  ( const double );
1013  TVar<T>& operator *=
1014  ( const TVar<T>& );
1015  TVar<T>& operator *=
1016  ( const double );
1017  TVar<T>& operator *=
1018  ( const T& );
1019  TVar<T>& operator /=
1020  ( const TVar<T>& );
1021  TVar<T>& operator /=
1022  ( const double );
1023 
1024 private:
1026  void _update_bndord() const;
1027 
1029  T _polybound
1030  ( const int type ) const;
1031 
1033  T _polybound
1034  () const
1035  { return _polybound( _TM? _TM->options.BOUNDER_TYPE: 0 ); }
1036 
1038  T _polybound_naive() const;
1039 
1041  T _polybound_LSB() const;
1042 
1044  T _polybound_eigen() const;
1045 
1047  T _polybound_bernstein() const;
1048 
1050  double _coef_bernstein
1051  ( const double*coefmon, const unsigned int*jexp,
1052  const unsigned int jmon, const unsigned int maxord ) const;
1053 };
1054 
1056 
1057 template <typename T> inline void
1058 TModel<T>::_size
1059 ()
1060 {
1061  _set_prodmon();
1062  _bndpow = new T*[_nvar];
1063  for( unsigned int i=0; i<_nvar; i++ ) _bndpow[i] = 0;
1064  _bndmon = new T[_nmon];
1065 
1066  _refpoint = new double[_nvar];
1067  _scaling = new double[_nvar];
1068  _cbern = new double[_nord+1];
1069 
1070  _TV = new TVar<T>( this );
1071 }
1072 
1073 template <typename T> inline void
1074 TModel<T>::_reset()
1075 {
1076  for( unsigned int i=0; i<_nvar; i++ ){
1077  delete[] _bndpow[i];
1078  _bndpow[i] = 0;
1079  }
1080 }
1081 
1082 template <typename T> inline void
1083 TModel<T>::_cleanup()
1084 {
1085  for( unsigned int i=0; i<_nmon; i++ ) delete[] _prodmon[i];
1086  delete[] _prodmon;
1087  for( unsigned int i=0; i<_nvar; i++ ) delete[] _bndpow[i];
1088  delete[] _bndpow;
1089  delete[] _bndmon;
1090  delete[] _refpoint;
1091  delete[] _scaling;
1092  delete[] _cbern;
1093  delete _TV;
1094 }
1095 
1096 template <typename T> inline void
1097 TModel<T>::_set_prodmon()
1098 {
1099  _prodmon = new unsigned int*[_nmon];
1100  _prodmon[0] = new unsigned int[_nmon+1];
1101  _prodmon[0][0] = _nmon;
1102  for( unsigned int i=1; i<=_nmon; i++ ) _prodmon[0][i] = i-1;
1103 #ifdef MC__TMODEL_DEBUG
1104  std::ostringstream ohead0;
1105  ohead0 << "_prodmon[" << 0 << "]";
1106  mc::display( 1, _nmon+1, _prodmon[0], 1, ohead0.str(), std::cout );
1107 #endif
1108  if( !_nord ) return;
1109 
1110  unsigned int *iexp = new unsigned int[_nvar];
1111  for( unsigned int i=1; i<_nord; i++ ){
1112  for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){
1113  _prodmon[j] = new unsigned int [_posord[_nord+1-i]+1];
1114  _prodmon[j][0] = _posord[_nord+1-i];
1115  for( unsigned int k=0; k<_posord[_nord+1-i]; k++ ){
1116  for( unsigned int in=0; in<_nvar; in++ )
1117  iexp[in] = _expmon[j*_nvar+in] + _expmon[k*_nvar+in] ;
1118  _prodmon[j][k+1] = _loc_expmon( iexp );
1119  }
1120 #ifdef MC__TMODEL_DEBUG
1121  std::ostringstream oheadj;
1122  oheadj << "_prodmon[" << j << "]";
1123  mc::display( 1, _posord[_nord+1-i]+1, _prodmon[j], 1, oheadj.str(), std::cout );
1124 #endif
1125  }
1126  }
1127  delete[] iexp;
1128 
1129  for( unsigned int i=_posord[_nord]; i<_nmon; i++ ){
1130  _prodmon[i] = new unsigned int[2];
1131  _prodmon[i][0] = 1;
1132  _prodmon[i][1] = i;
1133 #ifdef MC__TMODEL_DEBUG
1134  std::ostringstream oheadi;
1135  oheadi << "_prodmon[" << i << "]";
1136  mc::display( 1, 2, _prodmon[i], 1, oheadi.str(), std::cout );
1137 #endif
1138  }
1139 }
1140 
1141 template <typename T> inline void
1142 TModel<T>::_set_bndpow
1143 ( const unsigned int ivar, const T&X, const double Xref,
1144  const double scaling )
1145 {
1146  if( ivar>=_nvar ) throw Exceptions( Exceptions::INIT );
1147 
1148  delete[] _bndpow[ivar];
1149  _bndpow[ivar] = new T [_nord+1];
1150  _refpoint[ivar] = Xref/scaling;
1151  _scaling[ivar] = scaling;
1152  T Xr = X/scaling - _refpoint[ivar];
1153  _bndpow[ivar][0] = 1.;
1154  for( unsigned int i=1; i<=_nord; i++ ){
1155  _bndpow[ivar][i] = Op<T>::pow(Xr,(int)i);
1156  }
1157  _modvar = true;
1158 }
1159 
1160 template <typename T> inline void
1161 TModel<T>::_set_bndmon()
1162 {
1163  if( !_modvar ) return;
1164 
1165  _bndmon[0] = 1.;
1166  for( unsigned int i=1; i<_nmon; i++ ){
1167  _bndmon[i] = 1.;
1168  for( unsigned int j=0; j<_nvar; j++)
1169  if( _bndpow[j] ) _bndmon[i] *= _bndpow[j][_expmon[i*_nvar+j]];
1170  }
1171  _modvar = false;
1172 
1173 #ifdef MC__TMODEL_DEBUG
1174  mc::display( 1, _nmon, _bndmon, 1, "_bndmon", std::cout );
1175 #endif
1176 }
1177 
1178 template <typename T> inline void
1179 TModel<T>::_scale
1180 ( const unsigned int ivar, double*coef ) const
1181 {
1182  if( ivar>=_nvar || !_nord ) return;
1183  double dscale = Op<T>::diam(_bndpow[ivar][1]);
1184  double fscale = Op<T>::l(_bndpow[ivar][1]) / dscale;
1185  unsigned int iexp[_nvar];
1186  for( unsigned int imon=0; imon<_nmon; imon++ ){
1187  unsigned int iord = 0;
1188  for( unsigned int jvar=0; jvar<_nvar; jvar++ ){
1189  iexp[jvar] = _expmon[imon*_nvar+jvar];
1190  iord += iexp[jvar];
1191  }
1192  double coefmod = coef[imon] * std::pow(dscale,iexp[ivar]);
1193  iexp[ivar]++;
1194  for( unsigned int k=1; k<=_nord-iord; k++, iexp[ivar]++ ){
1195  coefmod += coef[_loc_expmon(iexp)]
1196  * _get_binom(iexp[ivar],k) * std::pow(fscale,k)
1197  * std::pow(dscale,iexp[ivar]); // double-check binomial coefficient...
1198  }
1199 #ifdef MC__TMODEL_DEBUG_SCALE
1200  std::cout << " a" << std::left << std::setw(3) << imon << " = "
1201  << std::right << std::setw(12) << coef[imon]
1202  << std::right << std::setw(14) << coefmod << std::endl;
1203 #endif
1204  coef[imon] = coefmod;
1205  }
1206  return;
1207 }
1208 
1209 template <typename T> inline TVar<T>
1210 TModel<T>::_univ_bernstein
1211 ( const TVar<T>&TV, puniv f, puniv df, punivext If,
1212  punivext d2If, const double*rusr, const int*iusr )
1213 {
1214  assert( TV._TM == this );
1215 
1216  const T B( TV.B() );
1217  const TVar<T> TVs( (TV-Op<T>::l(B))/Op<T>::diam(B) );
1218  TVar<T> TV2( this, 0. ), MON( 1. );
1219  for( unsigned int j=0; j<=_nord; j++ ){
1220  double sign = ( j%2? -1.: 1. );
1221  _cbern[j] = sign * _get_binom(_nord,j) * f( Op<T>::l(B), rusr, iusr );
1222  for( unsigned int i=1; i<=j; i++ ){
1223  sign *= -1.;
1224  _cbern[j] += sign * _get_binom(_nord,i) * _get_binom(_nord-i,j-i)
1225  * f( Op<T>::l(B)+(double)i/(double)_nord*Op<T>::diam(B), rusr, iusr );
1226  }
1227  TV2 += _cbern[j] * MON;
1228  MON *= TVs;
1229  }
1230 
1231  T R( - d2If( B, rusr, iusr ) * sqr(Op<T>::diam(B)) / 2. / _nord );
1232  if( Op<T>::l( R ) * Op<T>::u( R ) < 0 )
1233  return TV2 + Op<T>::zeroone() * R;
1234 
1235  if( !options.BERNSTEIN_OPT ){
1236  T R0( If(B,rusr,iusr) );
1237  R = Op<T>::zeroone() * ( Op<T>::u(R) <= 0.?
1238  -std::min( Op<T>::diam(R0), -Op<T>::l(R) ):
1239  std::min( Op<T>::diam(R0), Op<T>::u(R) ) );
1240  return TV2 + R;
1241  }
1242 
1243  std::pair<unsigned int,const double*> bern = std::make_pair(_nord+1,_cbern);
1244  double xopt = _goldsect( 0., 1., _dgap_bernstein, rusr, iusr, df, B, bern );
1245  R = Op<T>::zeroone() * _gap_bernstein( xopt, rusr, iusr, f, B, bern );
1246  return TV2 + R;
1247 }
1248 
1249 template <typename T> inline double
1250 TModel<T>::_dgap_bernstein
1251 ( const double x, const double*rusr, const int*iusr, puniv df,
1252  const T&B, const std::pair<unsigned int,const double*>&bern )
1253 {
1254  double phi = df(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr)*Op<T>::diam(B);
1255  for( unsigned int j=1; j<bern.first; j++ )
1256  phi -= j * bern.second[j] * std::pow(x,j-1);
1257  return phi;
1258 }
1259 
1260 template <typename T> inline double
1261 TModel<T>::_gap_bernstein
1262 ( const double x, const double*rusr, const int*iusr, puniv f,
1263  const T&B, const std::pair<unsigned int,const double*>&bern )
1264 {
1265  double phi = f(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr);
1266  for( unsigned int j=0; j<bern.first; j++ )
1267  phi -= bern.second[j] * std::pow(x,j);
1268  return phi;
1269 }
1270 
1271 template <typename T> inline double
1272 TModel<T>::_goldsect
1273 ( const double xL, const double xU, punivopt fopt, const double*rusr,
1274  const int*iusr, puniv df, const T&Ix,
1275  const std::pair<unsigned int,const double*>&bern )
1276 {
1277  const double phi = 2.-(1.+std::sqrt(5.))/2.;
1278  const double fL = fopt( xL, rusr, iusr, df, Ix, bern ),
1279  fU = fopt( xU, rusr, iusr, df, Ix, bern );
1280  if( fL*fU > 0 ) throw Exceptions( Exceptions::BERNSTEIN );
1281  const double xm = xU-phi*(xU-xL),
1282  fm = fopt( xm, rusr, iusr, df, Ix, bern );
1283  return _goldsect_iter( true, xL, fL, xm, fm, xU, fU, fopt, rusr, iusr,
1284  df, Ix, bern );
1285 }
1286 
1287 template <typename T> inline double
1288 TModel<T>::_goldsect_iter
1289 ( const bool init, const double a, const double fa, const double b,
1290  const double fb, const double c, const double fc, punivopt fopt,
1291  const double*rusr, const int*iusr, puniv df, const T&Ix,
1292  const std::pair<unsigned int,const double*>&bern )
1293 // a and c are the current bounds; the minimum is between them.
1294 // b is a center point
1295 {
1296  static unsigned int iter;
1297  iter = ( init? 1: iter+1 );
1298  const double phi = 2.-(1.+std::sqrt(5.))/2.;
1299  bool b_then_x = ( c-b > b-a );
1300  double x = ( b_then_x? b+phi*(c-b): b-phi*(b-a) );
1301  if( std::fabs(c-a) < options.BERNSTEIN_TOL*(std::fabs(b)+std::fabs(x))
1302  || iter > options.BERNSTEIN_MAXIT ) return (c+a)/2.;
1303  double fx = fopt( x, rusr, iusr, df, Ix, bern );
1304  if( b_then_x )
1305  return( fa*fx<0?
1306  _goldsect_iter( false, a, fa, b, fb, x, fx, fopt, rusr, iusr, df, Ix, bern ):
1307  _goldsect_iter( false, b, fb, x, fx, c, fc, fopt, rusr, iusr, df, Ix, bern ) );
1308  return( fa*fb<0?
1309  _goldsect_iter( false, a, fa, x, fx, b, fb, fopt, rusr, iusr, df, Ix, bern ):
1310  _goldsect_iter( false, x, fx, b, fb, c, fc, fopt, rusr, iusr, df, Ix, bern ) );
1311 }
1312 
1314 
1315 template <typename T> inline TVar<T>&
1316 TVar<T>::operator =
1317 ( const TVar<T>&TV )
1318 {
1319  _TM = TV._TM;
1320  _set( TV );
1321 #ifdef MC__TMODEL_CHECK_PMODEL
1322  if( _TM != dynamic_cast< TModel<T>* >( PolyVar<T>::_PM ) ) assert( false );
1323 #endif
1324  return *this;
1325 }
1326 
1327 template <typename T> inline
1328 TVar<T>::TVar
1329 ( const double d )
1330 : PolyVar<T>(), _TM( 0 )
1331 {
1332  _coefmon[0] = d;
1333  *_bndrem = 0.;
1334  _set_bndpol( d );
1335 }
1336 
1337 template <typename T> inline TVar<T>&
1339 ( const double d )
1340 {
1341  if( _TM ){ _TM = 0; _resize( _TM ); }
1342  _coefmon[0] = d;
1343  *_bndrem = 0.;
1344  _set_bndpol( d );
1345  return *this;
1346 }
1347 
1348 template <typename T> inline
1349 TVar<T>::TVar
1350 ( const T&B )
1351 : PolyVar<T>(), _TM( 0 )
1352 {
1353  _coefmon[0] = 0.;
1354  *_bndrem = B;
1355  _set_bndpol( 0. );
1356 }
1357 
1358 template <typename T> inline TVar<T>&
1360 ( const T&B )
1361 {
1362  if( _TM ){ _TM = 0; _resize( _TM ); }
1363  _coefmon[0] = 0.;
1364  *_bndrem = B;
1365  _set_bndpol( 0. );
1366  return *this;
1367 }
1368 
1369 template <typename T> inline
1370 TVar<T>::TVar
1371 ( TModel<T>*TM, const double d )
1372 : PolyVar<T>( TM ), _TM( TM )
1373 {
1374  if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
1375  _coefmon[0] = d; for( unsigned int i=1; i<nmon(); i++ ) _coefmon[i] = 0.;
1376  _bndord[0] = d; for( unsigned int i=1; i<nord()+2; i++) _bndord[i] = 0.;
1377  _bndord_uptd = true;
1378  _set_bndpol( d );
1379 }
1380 
1381 template <typename T> inline
1382 TVar<T>::TVar
1383 ( TModel<T>*TM, const T&B )
1384 : PolyVar<T>( TM ), _TM( TM )
1385 {
1386  if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
1387  for( unsigned int i=0; i<nmon(); i++ ) _coefmon[i] = 0.;
1388  for( unsigned int i=0; i<=nord(); i++) _bndord[i] = 0.;
1389  _bndord_uptd = true;
1390  *_bndrem = B;
1391  _set_bndpol( 0. );
1392  //if( _TM->options.CENTER_REMAINDER ) _center();
1393  _center();
1394 }
1395 
1396 template <typename T> template <typename U> inline
1397 TVar<T>::TVar
1398 ( TModel<T>*&TM, const TVar<U>&TV )
1399 : PolyVar<T>( TM ), _TM( TM )
1400 {
1401  TVar<U> TVtrunc( TV );
1402  _coefmon[0] = TVtrunc._coefmon[0];
1403  TVtrunc._coefmon[0] = 0. ;
1404  for( unsigned int i=1; TM && i<nmon(); i++ ){
1405  if( TVtrunc.TM && i < TVtrunc.nmon() ){
1406  _coefmon[i] = TVtrunc._coefmon[i];
1407  TVtrunc._coefmon[i] = 0.;
1408  }
1409  else
1410  _coefmon[i] = 0.;
1411  }
1412  TVtrunc._bndord_uptd = false;
1413  *_bndrem = T( TVtrunc.B() );
1414  _bndord_uptd = false;
1415  return;
1416 }
1417 
1418 template <typename T> template <typename U> inline
1420 ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) )
1421 : PolyVar<T>( TM ), _TM( TM )
1422 {
1423  if( !method ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
1424  TVar<U> TVtrunc( TV );
1425  _coefmon[0] = TVtrunc._coefmon[0];
1426  TVtrunc._coefmon[0] = 0. ;
1427  for( unsigned int i=1; TM && i<nmon(); i++ ){
1428  if( TVtrunc.TM && i < TVtrunc.nmon() ){
1429  _coefmon[i] = TVtrunc._coefmon[i];
1430  TVtrunc._coefmon[i] = 0.;
1431  }
1432  else
1433  _coefmon[i] = 0.;
1434  }
1435  TVtrunc._bndord_uptd = false;
1436  *_bndrem = (*method)( TVtrunc.B() );
1437  _bndord_uptd = false;
1438  return;
1439 }
1440 
1441 template <typename T> template <typename U> inline
1443 ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const )
1444 : PolyVar<T>( TM ), _TM( TM )
1445 {
1446  if( !method ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
1447  TVar<U> TVtrunc( TV );
1448  _coefmon[0] = TVtrunc._coefmon[0];
1449  TVtrunc._coefmon[0] = 0. ;
1450  for( unsigned int i=1; TM && i<nmon(); i++ ){
1451  if( TVtrunc.TM && i < TVtrunc.nmon() ){
1452  _coefmon[i] = TVtrunc._coefmon[i];
1453  TVtrunc._coefmon[i] = 0.;
1454  }
1455  else
1456  _coefmon[i] = 0.;
1457  }
1458  TVtrunc._bndord_uptd = false;
1459  *_bndrem = (TVtrunc.B().*method)();
1460  _bndord_uptd = false;
1461  return;
1462 }
1463 
1464 template <typename T> inline TVar<T>&
1466 ( const unsigned int ivar, const T&X, const double Xref )
1467 {
1468  if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT );
1469 
1470  // Scale variables and keep track of them in TModel
1471  double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. );
1472  if( isequal( scaling, 0. ) ) scaling = 1.;
1473  _TM->_set_bndpow( ivar, X, Xref, scaling );
1474  _TM->_set_bndmon();
1475 
1476  // Populate _coefmon w/ TVar coefficients
1477  _coefmon[0] = Xref;
1478  for( unsigned int i=1; i<nmon(); i++ ) _coefmon[i] = 0.;
1479  if( nord() > 0 ) _coefmon[nvar()-ivar] = scaling;
1480 
1481  // Populate _bndord w/ bounds on TVar terms
1482  _bndord[0] = _coefmon[0];
1483  if( nord() ){
1484  _bndord[1] = X-_coefmon[0];
1485  for( unsigned int i=2; i<nord()+2; i++) _bndord[i] = 0.;
1486  _set_bndpol( X );
1487  }
1488  else{ // 0th-order Taylor model
1489  *_bndrem = X-_coefmon[0];
1490  _set_bndpol( _coefmon[0] );
1491  }
1492  _bndord_uptd = true;
1493 
1494  return *this;
1495 }
1496 
1497 template <typename T> inline
1498 TVar<T>::TVar
1499 ( TModel<T>*TM, const unsigned int ivar, const T&X )
1500 : PolyVar<T>( TM ), _TM( TM )
1501 {
1502  _set( ivar, X, Op<T>::mid(X) );
1503 }
1504 
1505 template <typename T> inline
1507 ( TModel<T>*TM, const unsigned int ivar, const T&X, const double Xref )
1508 : PolyVar<T>( TM ), _TM( TM )
1509 {
1510  _set( ivar, X, Xref );
1511 }
1512 
1513 template <typename T> inline void
1515 {
1516  if( !_TM || _bndord_uptd ) return;
1517  _TM->_set_bndmon();
1518  _bndord[0] = _coefmon[0];
1519  for( unsigned int i=1; i<=nord(); i++ ){
1520  _bndord[i] = 0.;
1521  for( unsigned int j=_posord(i); j<_posord(i+1); j++ )
1522  _bndord[i] += _coefmon[j] * _bndmon(j);
1523  }
1524  _bndord_uptd = true;
1525 }
1526 
1527 template <typename T> inline T
1528 TVar<T>::_polybound_eigen() const
1529 {
1530  static const double TOL = 1e-8;
1531 
1532  T bndpol = _coefmon[0];
1533  if( nord() == 1 ) bndpol += _bndord[1];
1534 
1535  else if( nord() > 1 ){
1536  double*U = new double[nvar()*nvar()];
1537  for( unsigned int i=0; i<nvar(); i++ ){
1538  for( unsigned int j=0; j<i; j++ ){
1539  U[nvar()*(nvar()-i-1)+nvar()-j-1] = 0.;
1540  U[nvar()*(nvar()-j-1)+nvar()-i-1] = _coefmon[_prodmon(i+1,j+2)]/2.;
1541  }
1542  U[(nvar()+1)*(nvar()-i-1)] = _coefmon[_prodmon(i+1,i+2)];
1543  }
1544 #ifdef MC__TVAR_DEBUG_EIGEN
1545  display( nvar(), nvar(), U, nvar(), "Matrix U", std::cout );
1546 #endif
1547  double*D = mc::dsyev_wrapper( nvar(), U, true );
1548  if( !D ){
1549  delete[] U;
1550  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::EIGEN );
1551  }
1552 
1553 #ifdef MC__TVAR_HYBRID_EIGEN
1554  T bndtype1(0.);
1555 #endif
1556  T bndtype2(0.);
1557  for( unsigned int i=0; i<nvar(); i++ ){
1558  double linaux = 0.;
1559  T bndaux(0.);
1560  for( unsigned int k=0; k<nvar(); k++ ){
1561  linaux += U[i*nvar()+k] * _coefmon[nvar()-k];
1562  bndaux += U[i*nvar()+k] * _bndmon(nvar()-k);
1563  }
1564 #ifdef MC__TVAR_DEBUG_EIGEN
1565  std::cout << i << ": LINAUX = " << linaux
1566  << " BNDAUX = " << bndaux << std::endl;
1567 #endif
1568 #ifdef MC__TVAR_HYBRID_EIGEN
1569  bndtype1 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
1570 #endif
1571 #ifdef MC__TVAR_DEBUG_EIGEN
1572  std::cout << std::endl << "BNDTYPE1: " << bndtype1 << std::endl;
1573 #endif
1574  if( std::fabs(D[i]) > TOL )
1575  bndtype2 += D[i] * Op<T>::sqr( linaux/D[i]/2. + bndaux )
1576  - linaux*linaux/D[i]/4.;
1577  else
1578  //bndtype2 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux );
1579  bndtype2 += linaux * bndaux + D[i] * Op<T>::sqr( bndaux );
1580 #ifdef MC__TVAR_DEBUG_EIGEN
1581  std::cout << "BNDTYPE2: " << bndtype2 << std::endl;
1582 #endif
1583  }
1584  delete[] U;
1585  delete[] D;
1586 
1587 #ifdef MC__TVAR_HYBRID_EIGEN
1588  if( !Op<T>::inter( bndtype1, bndtype1, bndtype2 ) ){
1589  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
1590 #ifdef MC__TVAR_DEBUG_EIGEN
1591  std::cout << "BNDTYPE3: " << bndtype1 << std::endl;
1592 #endif
1593  }
1594  bndpol += bndtype1;
1595 #else
1596  bndpol += bndtype2;
1597 #endif
1598  }
1599 #ifdef MC__TVAR_DEBUG_EIGEN
1600  int tmp; std::cin >> tmp;
1601 #endif
1602 
1603  for( unsigned int i=3; i<=nord(); i++ ) bndpol += _bndord[i];
1604  return bndpol;
1605 }
1606 
1607 template <typename T> inline T
1608 TVar<T>::_polybound_LSB() const
1609 {
1610  static const double TOL = 1e-8;
1611 
1612  T bndpol = _coefmon[0];
1613  if( nord() == 1 ) bndpol += _bndord[1];
1614  else if( nord() > 1 ){
1615  for( unsigned int i=1; i<=nvar(); i++ ){
1616  // linear and diagonal quadratic terms
1617  unsigned int ii = _prodmon(i,i+1);
1618  if( std::fabs(_coefmon[ii]) > TOL )
1619  bndpol += _coefmon[ii] * Op<T>::sqr( _coefmon[i]/_coefmon[ii]/2.
1620  + _bndmon(i) ) - _coefmon[i]*_coefmon[i]/_coefmon[ii]/4.;
1621  else
1622  bndpol += _coefmon[i] * _bndmon(i) + _coefmon[ii] * _bndmon(ii);
1623  // off-diagonal quadratic terms
1624  for( unsigned int k=i+1; k<=nvar(); k++ ){
1625  unsigned int ik = _prodmon(i,k+1) ;
1626  bndpol += _coefmon[ik] * _bndmon(ik);
1627  }
1628  }
1629  }
1630  // higher-order terms
1631  for( unsigned int i=3; i<=nord(); i++ ) bndpol += _bndord[i];
1632  return bndpol;
1633 }
1634 
1635 template <typename T> inline T
1636 TVar<T>::_polybound_bernstein() const
1637 {
1638  // Scale Taylor model in unit hypercube with reference point at the origin
1639  double *coeftrans = new double[nmon()];
1640  for( unsigned int imon=0; imon<nmon(); imon++ )
1641  coeftrans[imon] = _coefmon[imon];
1642  for( unsigned int ivar=0; ivar<nvar(); ivar++ )
1643  _TM->_scale( ivar, coeftrans );
1644 
1645  // Expand binomial coefficient and exponent arrays if needed
1646  const unsigned int maxord = (_TM->options.BOUNDER_ORDER>nord()?
1647  _TM->options.BOUNDER_ORDER: nord() );
1648  const unsigned int maxmon = std::pow(maxord+1,nvar());
1649  _TM->_ext_expmon( maxord, true );
1650 
1651  // Compute min/max amongst all Bernstein coefficients
1652  T bndpol = coeftrans[0];
1653 #ifdef MC__TVAR_DEBUG_BERSTEIN
1654  std::cout << "\n0: " << bndpol << std::endl;
1655 #endif
1656  for( unsigned int jmon=1; jmon<maxmon; jmon++ ){
1657  const unsigned int*jexp = _expmon(jmon);
1658  const double coefbern = _coef_bernstein( coeftrans, jexp, jmon, maxord );
1659  bndpol = Op<T>::hull( bndpol, coefbern );
1660 #ifdef MC__TVAR_DEBUG_BERNSTEIN
1661  std::cout << jmon << " [";
1662  for( unsigned int ivar=0; ivar<nvar(); ivar++ )
1663  std::cout << std::setw(3) << jexp[ivar];
1664  std::cout << "] : " << coefbern << " : " << bndpol << std::endl;
1665 #endif
1666  }
1667  delete[] coeftrans;
1668  return bndpol;
1669 }
1670 
1671 template <typename T> inline double
1672 TVar<T>::_coef_bernstein
1673 ( const double*coefmon, const unsigned int*jexp,
1674  const unsigned int jmon, const unsigned int maxord ) const
1675 {
1676  // Compute bernstein coefficient with variables indices <tt>jexp</tt>
1677  double coefbern = coefmon[0];
1678  for( unsigned int imon=1; imon<=std::min(jmon,nmon()-1); imon++ ){
1679  const unsigned int*iexp = _expmon(imon);
1680  // Only append term if monomial degrees are lower
1681  bool inrange = true;
1682  for( unsigned int ivar=0; ivar<nvar() && inrange; ivar++ )
1683  if( iexp[ivar] > jexp[ivar] ) inrange = false;
1684  if( !inrange ) continue;
1685  double termbern = coefmon[imon];
1686 #ifdef MC__TVAR_DEBUG_BERSTEIN
1687  std::cout << " [";
1688  for( unsigned int ivar=0; ivar<nvar(); ivar++ )
1689  std::cout << std::setw(3) << iexp[ivar];
1690  std::cout << "]";
1691 #endif
1692  for( unsigned int ivar=0; ivar<nvar(); ivar++ )
1693  termbern *= (double)_get_binom(jexp[ivar],iexp[ivar])
1694  / (double)_get_binom(maxord,iexp[ivar]);
1695  coefbern += termbern;
1696  }
1697 #ifdef MC__TVAR_DEBUG_BERSTEIN
1698  std::cout << std::endl;
1699 #endif
1700  return coefbern;
1701 }
1702 
1703 template <typename T> inline T
1704 TVar<T>::_polybound_naive() const
1705 {
1706  T bndpol = _coefmon[0];
1707  for( unsigned int i=1; i<=nord(); i++ ) bndpol += _bndord[i];
1708  return bndpol;
1709 }
1710 
1711 template <typename T> inline T
1712 TVar<T>::_polybound
1713 ( const int type ) const
1714 {
1715  if( !_TM ) return _coefmon[0];
1716 
1717  _update_bndord();
1718  switch( type ){
1720  return _polybound_naive();
1722  return _polybound_bernstein();
1724  return _polybound_eigen();
1726  T bndpol, bndpol_LSB = _polybound_LSB();
1727  if( !Op<T>::inter( bndpol, bndpol_LSB, _polybound_eigen() ) )
1728  // throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON );
1729  return bndpol_LSB;
1730  return bndpol;
1731  }
1732  case TModel<T>::Options::LSB: default:
1733  return _polybound_LSB();
1734  }
1735 }
1736 
1737 template <typename T> inline double
1739 ( const double*x ) const
1740 {
1741  if( !_TM ) return _coefmon[0];
1742  double Pval = _coefmon[0];
1743  for( unsigned int i=1; i<nmon(); i++ ){
1744  double valmon = 1.;
1745  for( unsigned int k=0; k<nvar(); k++ )
1746  valmon *= std::pow( x[k]/_scaling(k)-_refpoint(k), _expmon(i)[k] );
1747  Pval += _coefmon[i] * valmon;
1748  }
1749  return Pval;
1750 }
1751 
1752 template <typename T> inline double
1754 ( const bool reset )
1755 {
1756  const double coefconst = _coefmon[0];
1757  if( reset ) *this -= coefconst;
1758  return coefconst;
1759 }
1760 
1761 template <typename T> inline double*
1763 {
1764  if( !nvar() || !nord() ) return 0;
1765 
1766  double*plin = new double[nvar()];
1767  for( unsigned int i=0; i<nvar(); i++ )
1768  plin[i] = _coefmon[nvar()-i] / _scaling(i);
1769  return plin;
1770 }
1771 
1772 template <typename T> inline double
1774 ( const unsigned int ivar, const bool reset )
1775 {
1776  if( ivar>=nvar() || !nord() ) return 0.;
1777  const double coeflin = _coefmon[nvar()-ivar] / _scaling(ivar);
1778  if( reset ){ _coefmon[nvar()-ivar] = 0.; _bndord_uptd = false; _unset_bndpol(); }
1779  return coeflin;
1780 }
1781 
1782 template <typename T> inline std::ostream&
1783 operator <<
1784 ( std::ostream&out, const TVar<T>&TV )
1785 {
1786  out << std::endl
1787  << std::scientific << std::setprecision(5)
1788  << std::right;
1789 
1790 #ifdef MC__TVAR_DISPLAY_EXT
1791  out << " TM: " << TV._TM << " PM: " << TV._PM << std::endl;
1792 #endif
1793 
1794  // Constant model
1795  if( !TV._TM ){
1796  out << " a0 = " << std::right << std::setw(12) << TV._coefmon[0]
1797  << std::endl
1798  << " R = " << *(TV._bndrem) << std::endl;
1799  }
1800 
1801  // Monomial term coefficients and corresponding exponents
1802  else{
1803  out << std::setprecision(TV._TM->options.DISPLAY_DIGITS);
1804  for( unsigned int i=0; i<TV.nmon(); i++ ){
1805  double scal = 1.;
1806  for( unsigned int k=0; k<TV.nvar(); k++ )
1807  scal *= std::pow( TV._scaling(k), TV._expmon(i)[k] );
1808  out << " a" << std::left << std::setw(4) << i << " = "
1809  << std::right << std::setw(TV._TM->options.DISPLAY_DIGITS+7)
1810  << TV._coefmon[i]*scal << " ";
1811  for( unsigned int k=0; k<TV.nvar(); k++ )
1812  out << std::setw(3) << TV._expmon(i)[k];
1813  out << std::endl;
1814  }
1815 #ifdef MC__TVAR_DISPLAY_EXT
1816  // Order bounds
1817  for( unsigned int j=0; j<=TV.nord(); j++ )
1818  out << std::right << " B" << std::left << std::setw(2) << j << " = "
1819  << std::right << TV.bndord(j) << std::endl;
1820 #endif
1821  // Remainder term
1822  out << std::right << " R = " << *(TV._bndrem)
1823  << std::endl;
1824  }
1825 
1826  // Range bounder
1827  out << std::right << " B = " << TV.B()
1828  << std::endl;
1829 
1830  return out;
1831 }
1832 
1833 template <typename T> inline TVar<T>
1834 operator +
1835 ( const TVar<T>&TV )
1836 {
1837  return TV;
1838 }
1839 
1840 template <typename T> template <typename U> inline TVar<T>&
1841 TVar<T>::operator +=
1842 ( const TVar<U>&TV )
1843 {
1844  if( !TV._TM ){
1845  _coefmon[0] += TV._coefmon[0];
1846  if( _TM && _bndord_uptd ) _bndord[0] += TV._coefmon[0];
1847  *_bndrem += *(TV._bndrem);
1848  if( _bndpol ) *_bndpol += TV._coefmon[0];
1849  }
1850  else if( !_TM ){
1851  TVar<T> TV2(*this);
1852  *this = TV; *this += TV2;
1853  }
1854  else{
1855  if( _TM != TV._TM )
1856  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
1857  for( unsigned int i=0; i<nmon(); i++ )
1858  _coefmon[i] += TV._coefmon[i];
1859  if( TV._bndord_uptd )
1860  for( unsigned int i=0; _bndord_uptd && i<=nord(); i++ )
1861  _bndord[i] += TV._bndord[i];
1862  else _bndord_uptd = false;
1863  *_bndrem += *(TV._bndrem);
1864  if( _bndpol && TV._bndpol ) *_bndpol += *(TV._bndpol);
1865  else _unset_bndpol();
1866  }
1867  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
1868  return *this;
1869 }
1870 
1871 template <typename T, typename U> inline TVar<T>
1872 operator +
1873 ( const TVar<T>&TV1, const TVar<U>&TV2 )
1874 {
1875  TVar<T> TV3( TV1 );
1876  TV3 += TV2;
1877  return TV3;
1878 }
1879 
1880 template <typename T> inline TVar<T>&
1881 TVar<T>::operator +=
1882 ( const double c )
1883 {
1884  _coefmon[0] += c;
1885  if( _TM && _bndord_uptd ) _bndord[0] += c;
1886  if( _bndpol ) *_bndpol += c;
1887  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
1888  return *this;
1889 }
1890 
1891 template <typename T> inline TVar<T>
1892 operator +
1893 ( const TVar<T>&TV1, const double c )
1894 {
1895  TVar<T> TV3( TV1 );
1896  TV3 += c;
1897  return TV3;
1898 }
1899 
1900 template <typename T> inline TVar<T>
1901 operator +
1902 ( const double c, const TVar<T>&TV2 )
1903 {
1904  TVar<T> TV3( TV2 );
1905  TV3 += c;
1906  return TV3;
1907 }
1908 
1909 template <typename T> template <typename U> inline TVar<T>&
1910 TVar<T>::operator +=
1911 ( const U&I )
1912 {
1913  *_bndrem += I;
1914  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
1915  return *this;
1916 }
1917 
1918 template <typename T> inline TVar<T>
1919 operator +
1920 ( const TVar<T>&TV1, const T&I )
1921 {
1922  TVar<T> TV3( TV1 );
1923  TV3 += I;
1924  return TV3;
1925 }
1926 
1927 template <typename T> inline TVar<T>
1928 operator +
1929 ( const T&I, const TVar<T>&TV2 )
1930 {
1931  TVar<T> TV3( TV2 );
1932  TV2 += I;
1933  return TV3;
1934 }
1935 
1936 template <typename T> inline TVar<T>
1937 operator -
1938 ( const TVar<T>&TV )
1939 {
1940  if( !TV._TM ){
1941  TVar<T> TV2;
1942  TV2._coefmon[0] = -TV._coefmon[0];
1943  *TV2._bndrem = - *TV._bndrem;
1944  if( TV._bndpol ) TV2._set_bndpol( - *TV._bndpol );
1945  return TV2;
1946  }
1947  TVar<T>& TV2 = *TV._TV(); // Use internal Taylor variable to save time
1948  TV2._unset_bndpol(); TV2._bndord_uptd = false;
1949  for( unsigned int i=0; i<TV.nmon(); i++ ) TV2._coefmon[i] = -TV._coefmon[i];
1950  *TV2._bndrem = - *TV._bndrem;
1951  if( TV._bndord_uptd ){
1952  for( unsigned int i=0; i<=TV.nord(); i++ ) TV2._bndord[i] = -TV._bndord[i];
1953  TV2._bndord_uptd = true;
1954  }
1955  if( TV._bndpol ) TV2._set_bndpol( - *TV._bndpol );
1956  if( TV._TM->options.CENTER_REMAINDER ) TV2._center();
1957  return TV2;
1958 }
1959 
1960 template <typename T> template <typename U> inline TVar<T>&
1961 TVar<T>::operator -=
1962 ( const TVar<U>&TV )
1963 {
1964  if( !TV._TM ){
1965  _coefmon[0] -= TV._coefmon[0];
1966  if( _TM && _bndord_uptd ) _bndord[0] -= TV._coefmon[0];
1967  *_bndrem -= *(TV._bndrem);
1968  if( _bndpol ) *_bndpol -= TV._coefmon[0];
1969  }
1970  else if( !_TM ){
1971  TVar<T> TV2(*this);
1972  *this = -TV; *this += TV2;
1973  }
1974  else{
1975  if( _TM != TV._TM )
1976  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
1977  for( unsigned int i=0; i<nmon(); i++ )
1978  _coefmon[i] -= TV._coefmon[i];
1979  if( TV._bndord_uptd )
1980  for( unsigned int i=0; _bndord_uptd && i<=nord(); i++ )
1981  _bndord[i] -= TV._bndord[i];
1982  else _bndord_uptd = false;
1983  *_bndrem -= *(TV._bndrem);
1984  if( _bndpol && TV._bndpol ) *_bndpol -= *(TV._bndpol);
1985  else _unset_bndpol();
1986  }
1987  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
1988  return *this;
1989 }
1990 
1991 template <typename T, typename U> inline TVar<T>
1992 operator-
1993 ( const TVar<T>&TV1, const TVar<U>&TV2 )
1994 {
1995  TVar<T> TV3( TV1 );
1996  TV3 -= TV2;
1997  return TV3;
1998 }
1999 
2000 template <typename T> inline TVar<T>&
2001 TVar<T>::operator -=
2002 ( const double c )
2003 {
2004  _coefmon[0] -= c;
2005  if( _TM && _bndord_uptd ) _bndord[0] -= c;
2006  if( _bndpol ) *_bndpol -= c;
2007  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
2008  return *this;
2009 }
2010 
2011 template <typename T> inline TVar<T>
2012 operator -
2013 ( const TVar<T>&TV1, const double c )
2014 {
2015  TVar<T> TV3( TV1 );
2016  TV3 -= c;
2017  return TV3;
2018 }
2019 
2020 template <typename T> inline TVar<T>
2021 operator -
2022 ( const double c, const TVar<T>&TV2 )
2023 {
2024  TVar<T> TV3( -TV2 );
2025  TV3 += c;
2026  return TV3;
2027 }
2028 
2029 template <typename T> template <typename U> inline TVar<T>&
2030 TVar<T>::operator -=
2031 ( const U&I )
2032 {
2033  *_bndrem -= I;
2034  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
2035  return *this;
2036 }
2037 
2038 template <typename T> inline TVar<T>
2039 operator -
2040 ( const TVar<T>&TV1, const T&I )
2041 {
2042  TVar<T> TV3( TV1 );
2043  TV3 -= I;
2044  return TV3;
2045 }
2046 
2047 template <typename T> inline TVar<T>
2048 operator -
2049 ( const T&I, const TVar<T>&TV2 )
2050 {
2051  TVar<T> TV3( -TV2 );
2052  TV3 += I;
2053  return TV3;
2054 }
2055 
2056 template <typename T> inline TVar<T>&
2057 TVar<T>::operator *=
2058 ( const TVar<T>&TV )
2059 {
2060  TVar<T> TV2( *this );
2061  *this = TV * TV2;
2062  return *this;
2063 }
2064 
2065 template <typename T> inline TVar<T>
2066 operator *
2067 ( const TVar<T>&TV1, const TVar<T>&TV2 )
2068 {
2069  if( !TV2._TM ) return( TV1 * TV2._coefmon[0] + TV1 * *(TV2._bndrem) );
2070  else if( !TV1._TM ) return( TV2 * TV1._coefmon[0] + TV2 * *(TV1._bndrem) );
2071  else if( &TV1 == &TV2 ) return sqr(TV1);
2072 
2073  if( TV1._TM != TV2._TM )
2074  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
2075  TVar<T>& TV3 = *TV1._TV(); // Use internal Taylor variable to save time
2076  for( unsigned int i=0; i<TV3.nmon(); i++ ) TV3._coefmon[i] = 0.;
2077 
2078  // Populate _coefmon for product term
2079  for( unsigned int i=0; i<TV3._posord(TV3.nord()/2+1); i++){
2080  TV3._coefmon[TV3._prodmon(i,i+1)] += TV1._coefmon[i] * TV2._coefmon[i];
2081  for( unsigned int j=i+1; j<TV3._prodmon(i,0); j++ )
2082  TV3._coefmon[TV3._prodmon(i,j+1)] += TV1._coefmon[i] * TV2._coefmon[j]
2083  + TV1._coefmon[j] * TV2._coefmon[i];
2084  }
2085  // Calculate remainder term _bndrem for product term
2086  TV1._update_bndord(); TV2._update_bndord();
2087  T s1 = 0., s2 = 0.;
2088  for( unsigned int i=0; i<=TV3.nord()+1; i++ ){
2089  T r1 = 0., r2 = 0.;
2090  for( unsigned int j=TV3.nord()+1-i; j<=TV3.nord()+1; j++ ){
2091  r1 += TV1._bndord[j];
2092  r2 += TV2._bndord[j];
2093  }
2094  s1 += TV2._bndord[i] * r1 ;
2095  s2 += TV1._bndord[i] * r2 ;
2096  }
2097  if( !Op<T>::inter( *(TV3._bndrem), s1, s2) ){
2098  *(TV3._bndrem) = s1;
2099  }
2100 
2101  // Populate _bndord for product term (except remainder term)
2102  TV3._unset_bndpol();
2103  TV3._bndord_uptd = false;
2104  if( TV3._TM->options.CENTER_REMAINDER ) TV3._center();
2105  return TV3;
2106 }
2107 
2108 template <typename T> inline TVar<T>
2109 sqr
2110 ( const TVar<T>&TV )
2111 {
2112  if( !TV._TM ){
2113  TVar<T> TV2( TV );
2114  TV2._coefmon[0] *= TV2._coefmon[0];
2115  *(TV2._bndrem) *= 2. + *(TV2._bndrem);
2116  TV2._unset_bndpol();
2117  return TV2;
2118  }
2119 
2120  // Populate _coefmon for product term
2121  TVar<T> TV2( TV._TM, 0. );
2122  for( unsigned int i=0; i<TV2._posord(TV2.nord()/2+1); i++){
2123  TV2._coefmon[TV2._prodmon(i,i+1)] += TV._coefmon[i] * TV._coefmon[i];
2124  for( unsigned int j=i+1; j<TV2._prodmon(i,0); j++ )
2125  TV2._coefmon[TV2._prodmon(i,j+1)] += TV._coefmon[i] * TV._coefmon[j] * 2.;
2126  }
2127 
2128  TV._update_bndord();
2129  T s = 0.;
2130  for( unsigned int i=0; i<=TV2.nord()+1; i++ ){
2131  unsigned int k = std::max(TV2.nord()+1-i, i+1);
2132  T r = 0.;
2133  for( unsigned int j=k; j<=TV2.nord()+1; j++ )
2134  r += TV._bndord[j];
2135  s += TV._bndord[i] * r;
2136  }
2137 
2138  T r = 0.;
2139  for( unsigned int i=TV2.nord()/2+1; i<=TV2.nord()+1; i++ )
2140  r += Op<T>::sqr(TV._bndord[i]) ;
2141  *(TV2._bndrem) = 2. * s + r;
2142 
2143  // Populate _bndord for product term (except remainder term)
2144  TV2._unset_bndpol();
2145  TV2._bndord_uptd = false;
2146  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2147  return TV2;
2148 }
2149 
2150 template <typename T> inline TVar<T>&
2151 TVar<T>::operator *=
2152 ( const double c )
2153 {
2154  if( !_TM ){
2155  _coefmon[0] *= c;
2156  *(_bndrem) *= c;
2157  }
2158  else{
2159  for( unsigned int i=0; i<nmon(); i++ ) _coefmon[i] *= c;
2160  for( unsigned int i=0; _bndord_uptd && i<=nord(); i++ ) _bndord[i] *= c;
2161  *_bndrem *= c;
2162  }
2163  if( _bndpol ) *_bndpol *= c;
2164  return *this;
2165 }
2166 
2167 template <typename T> inline TVar<T>
2168 operator *
2169 ( const TVar<T>&TV1, const double c )
2170 {
2171  TVar<T> TV3( TV1 );
2172  TV3 *= c;
2173  return TV3;
2174 }
2175 
2176 template <typename T> inline TVar<T>
2177 operator *
2178 ( const double c, const TVar<T>&TV2 )
2179 {
2180  TVar<T> TV3( TV2 );
2181  TV3 *= c;
2182  return TV3;
2183 }
2184 
2185 template <typename T> inline TVar<T>&
2186 TVar<T>::operator *=
2187 ( const T&I )
2188 {
2189  if( !_TM ){
2190  *(_bndrem) += _coefmon[0];
2191  _coefmon[0] = 0.;
2192  *(_bndrem) *= I;
2193  }
2194  else{
2195  const double Imid = Op<T>::mid(I);
2196  T Icur = bound();
2197  for( unsigned int i=0; i<nmon(); i++ ) _coefmon[i] *= Imid;
2198  for( unsigned int i=0; _bndord_uptd && i<=nord(); i++ ) _bndord[i] *= Imid;
2199  *_bndrem *= Imid;
2200  *_bndrem += (I-Imid)*Icur;
2201  }
2202  //_bndord_uptd = false;
2203  _unset_bndpol();
2204  if( _TM && _TM->options.CENTER_REMAINDER ) _center();
2205  return (*this);
2206 }
2207 
2208 template <typename T> inline TVar<T>
2209 operator *
2210 ( const TVar<T>&TV1, const T&I )
2211 {
2212  TVar<T> TV3( TV1 );
2213  TV3 *= I;
2214  return TV3;
2215 }
2216 
2217 template <typename T> inline TVar<T>
2218 operator *
2219 ( const T&I, const TVar<T>&TV2 )
2220 {
2221  TVar<T> TV3( TV2 );
2222  TV3 *= I;
2223  return TV3;
2224 }
2225 
2226 template <typename T> inline TVar<T>&
2227 TVar<T>::operator /=
2228 ( const TVar<T>&TV )
2229 {
2230  *this *= inv(TV);
2231  return *this;
2232 }
2233 
2234 template <typename T> inline TVar<T>
2235 operator /
2236 ( const TVar<T>&TV1, const TVar<T>&TV2 )
2237 {
2238  return TV1 * inv(TV2);
2239 }
2240 
2241 template <typename T> inline TVar<T>&
2242 TVar<T>::operator /=
2243 ( const double c )
2244 {
2245  if ( isequal( c, 0. ))
2246  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
2247  *this *= (1./c);
2248  return *this;
2249 }
2250 
2251 template <typename T> inline TVar<T>
2252 operator /
2253 ( const TVar<T>&TV, const double c )
2254 {
2255  if ( isequal( c, 0. ))
2256  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV );
2257  return TV * (1./c);
2258 }
2259 
2260 template <typename T> inline TVar<T>
2261 operator /
2262 ( const double c, const TVar<T>&TV )
2263 {
2264  return inv(TV) * c;
2265 }
2266 
2267 template <typename T> inline TVar<T>
2268 inv
2269 ( const TVar<T>&TV )
2270 {
2271  if( !TV._TM )
2272  return TVar<T>( Op<T>::inv(TV._coefmon[0] + *(TV._bndrem)) );
2273 
2274  TVar<T> TV2 = TV._TM->_inv_taylor( TV );
2275  if( TV2._TM->options.BERNSTEIN_USE ){
2276  TVar<T> TV2b = TV._TM->_inv_bernstein( TV );
2277  if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
2278  TV2 = TV2b;
2279  }
2280 
2281  TV2._bndord_uptd = false;
2282  TV2._unset_bndpol();
2283  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2284  return TV2;
2285 }
2286 
2287 template <typename T> inline TVar<T>
2288 TModel<T>::_inv_taylor
2289 ( const TVar<T>&TV )
2290 {
2291  const T I( TV.B() );
2292  if ( Op<T>::l(TV.B()) <= 0. && Op<T>::u(TV.B()) >= 0. )
2293  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INV );
2294  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
2295  TV._coefmon[0] );
2296  const TVar<T> TVmx0( TV - x0 );
2297  const T Imx0( I - x0 );
2298 
2299  TVar<T> TV2( TV._TM, 1. ), MON( 1. );
2300 #ifdef MC__TMODEL_TIGHT_REMAINDER
2301  double R[3] = { 0., 1./Op<T>::l(I)-1./x0, 1./Op<T>::u(I)-1./x0 };
2302  double aL = 1./x0, aU = 1./x0;
2303 #endif
2304  for( unsigned int i=1; i<=TV.nord(); i++ ){
2305  MON *= TVmx0 / (-x0);
2306  TV2 += MON;
2307 #ifdef MC__TMODEL_TIGHT_REMAINDER
2308  aL *= (Op<T>::l(I)-x0) / (-x0);
2309  R[1] -= aL;
2310  aU *= (Op<T>::u(I)-x0) / (-x0);
2311  R[2] -= aU;
2312 #endif
2313  }
2314  TV2 /= x0;
2315 #ifdef MC__TMODEL_TIGHT_REMAINDER
2316  TV2 += max(3,R) + Op<T>::zeroone() * ( min(3,R) - max(3,R) );
2317 #else
2318  TV2 += Op<T>::pow( -Imx0, (int)TV2.nord()+1 )
2319  / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2.nord()+2 );
2320 #endif
2321  return TV2;
2322 }
2323 
2324 template <typename T> inline TVar<T>
2325 TModel<T>::_inv_bernstein
2326 ( const TVar<T>&TV )
2327 {
2328  const T I( TV.B() );
2329  if ( Op<T>::l(TV.B()) <= 0. && Op<T>::u(TV.B()) >= 0. )
2330  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INV );
2331  struct loc{
2332  static double inv
2333  ( const double x, const double*rusr, const int*iusr )
2334  { return 1./x; }
2335  static double dinv
2336  ( const double x, const double*rusr, const int*iusr )
2337  { return -1./mc::sqr(x); }
2338  static T Iinv
2339  ( const T&x, const double*rusr, const int*iusr )
2340  { return Op<T>::inv(x); }
2341  static T d2Iinv
2342  ( const T&x, const double*rusr, const int*iusr )
2343  { return 2.*Op<T>::pow( Op<T>::inv(x), 3 ); }
2344  };
2345  return TV._TM->_univ_bernstein( TV, loc::inv, loc::dinv, loc::Iinv,
2346  loc::d2Iinv, 0, 0 );
2347 }
2348 
2349 template <typename T> inline TVar<T>
2350 sqrt
2351 ( const TVar<T>&TV )
2352 {
2353  if( !TV._TM )
2354  return TVar<T>( Op<T>::sqrt(TV._coefmon[0] + *(TV._bndrem)) );
2355 
2356  TVar<T> TV2 = TV._TM->_sqrt_taylor( TV );
2357  if( TV2._TM->options.BERNSTEIN_USE ){
2358  TVar<T> TV2b = TV._TM->_sqrt_bernstein( TV );
2359  if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
2360  TV2 = TV2b;
2361  }
2362 
2363  TV2._bndord_uptd = false;
2364  TV2._unset_bndpol();
2365  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2366  return TV2;
2367 }
2368 
2369 template <typename T> inline TVar<T>
2370 TModel<T>::_sqrt_taylor
2371 ( const TVar<T>&TV )
2372 {
2373  const T I( TV.B() );
2374  if ( Op<T>::l(I) < 0. )
2375  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::SQRT );
2376  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
2377  TV._coefmon[0] );
2378  const TVar<T> TVmx0( TV - x0 );
2379  const T Imx0( I - x0 );
2380 
2381  double s = 0.5;
2382  TVar<T> TV2( TV._TM, 1. ), MON( 1. );
2383 #ifdef MC__TMODEL_TIGHT_REMAINDER
2384  double R[3] = { 0., std::sqrt(Op<T>::l(I))-std::sqrt(x0), std::sqrt(Op<T>::u(I))-std::sqrt(x0) };
2385  double aL = std::sqrt(x0), aU = std::sqrt(x0);
2386 #endif
2387  for( unsigned int i=1; i<=TV.nord(); i++ ){
2388  MON *= TVmx0 / x0;
2389  TV2 += MON * s;
2390 #ifdef MC__TMODEL_TIGHT_REMAINDER
2391  aL *= (Op<T>::l(I)-x0) / x0;
2392  R[1] -= aL * s;
2393  aU *= (Op<T>::u(I)-x0) / x0;
2394  R[2] -= aU * s;
2395 #endif
2396  s *= -(2.*i-1.)/(2.*i+2.);
2397  }
2398  TV2 *= std::sqrt(x0);
2399 #ifdef MC__TMODEL_TIGHT_REMAINDER
2400  TV2 += max(3,R) + Op<T>::zeroone() * ( min(3,R) - max(3,R) );
2401 #else
2402  TV2 += s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2403  / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2.nord()+1/2 );
2404 #endif
2405  return TV2;
2406 }
2407 
2408 template <typename T> inline TVar<T>
2409 TModel<T>::_sqrt_bernstein
2410 ( const TVar<T>&TV )
2411 {
2412  const T I( TV.B() );
2413  if ( Op<T>::l(I) < 0. )
2414  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::SQRT );
2415  struct loc{
2416  static double sqrt
2417  ( const double x, const double*rusr, const int*iusr )
2418  { return std::sqrt(x); }
2419  static double dsqrt
2420  ( const double x, const double*rusr, const int*iusr )
2421  { return 1./(2.*std::sqrt(x)); }
2422  static T Isqrt
2423  ( const T&x, const double*rusr, const int*iusr )
2424  { return Op<T>::sqrt(x); }
2425  static T d2Isqrt
2426  ( const T&x, const double*rusr, const int*iusr )
2427  { return -Op<T>::inv( 4.*Op<T>::sqrt(Op<T>::pow(x,3)) ); }
2428  };
2429  return TV._TM->_univ_bernstein( TV, loc::sqrt, loc::dsqrt, loc::Isqrt,
2430  loc::d2Isqrt, 0, 0 );
2431 }
2432 
2433 template <typename T> inline TVar<T>
2434 exp
2435 ( const TVar<T>&TV )
2436 {
2437  if( !TV._TM )
2438  return TVar<T>( Op<T>::exp(TV._coefmon[0] + *(TV._bndrem)) );
2439 
2440  TVar<T> TV2 = TV._TM->_exp_taylor( TV );
2441  if( TV2._TM->options.BERNSTEIN_USE ){
2442  TVar<T> TV2b = TV._TM->_exp_bernstein( TV );
2443  //std::cout << *(TV2b._bndrem) << " <=? " << *(TV2._bndrem) << std::endl;
2444  if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
2445  TV2 = TV2b;
2446  }
2447 
2448  TV2._bndord_uptd = false;
2449  TV2._unset_bndpol();
2450  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2451  return TV2;
2452 }
2453 
2454 template <typename T> inline TVar<T>
2455 TModel<T>::_exp_taylor
2456 ( const TVar<T>&TV )
2457 {
2458  const T I( TV.B() );
2459  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
2460  TV._coefmon[0] );
2461  const TVar<T> TVmx0( TV - x0 );
2462  const T Imx0( I - x0 );
2463 
2464  double s = 1.;
2465  TVar<T> TV2( TV._TM, 1. ), MON( 1. );
2466 #ifdef MC__TMODEL_TIGHT_REMAINDER
2467  double R[3] = { 0., std::exp(Op<T>::l(I))-std::exp(x0), std::exp(Op<T>::u(I))-std::exp(x0) };
2468  double aL = std::exp(x0), aU = std::exp(x0);
2469 #endif
2470  for( unsigned int i=1; i<=TV.nord(); i++ ){
2471  MON *= TVmx0;
2472  TV2 += MON * s;
2473 #ifdef MC__TMODEL_TIGHT_REMAINDER
2474  aL *= (Op<T>::l(I)-x0);
2475  R[1] -= aL * s;
2476  aU *= (Op<T>::u(I)-x0);
2477  R[2] -= aU * s;
2478 #endif
2479  s /= i+1.;
2480  }
2481 #ifdef MC__TMODEL_TIGHT_REMAINDER
2482  TV2 *= std::exp(x0);
2483  TV2 += max(3,R) + Op<T>::zeroone() * ( min(3,R) - max(3,R) );
2484 #else
2485  TV2 += s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2486  * Op<T>::exp( Op<T>::zeroone()*Imx0 );
2487  TV2 *= std::exp(x0);
2488 #endif
2489  return TV2;
2490 }
2491 
2492 template <typename T> inline TVar<T>
2493 TModel<T>::_exp_bernstein
2494 ( const TVar<T>&TV )
2495 {
2496  struct loc{
2497  static double exp
2498  ( const double x, const double*rusr, const int*iusr )
2499  { return std::exp(x); }
2500  static double dexp
2501  ( const double x, const double*rusr, const int*iusr )
2502  { return std::exp(x); }
2503  static T Iexp
2504  ( const T&x, const double*rusr, const int*iusr )
2505  { return Op<T>::exp(x); }
2506  static T d2Iexp
2507  ( const T&x, const double*rusr, const int*iusr )
2508  { return Op<T>::exp(x); }
2509  };
2510  return TV._TM->_univ_bernstein( TV, loc::exp, loc::dexp, loc::Iexp,
2511  loc::d2Iexp, 0, 0 );
2512 }
2513 
2514 template <typename T> inline TVar<T>
2515 log
2516 ( const TVar<T>&TV )
2517 {
2518  if( !TV._TM )
2519  return TVar<T>( Op<T>::log(TV._coefmon[0] + *(TV._bndrem)) );
2520 
2521  TVar<T> TV2 = TV._TM->_log_taylor( TV );
2522  if( TV2._TM->options.BERNSTEIN_USE ){
2523  TVar<T> TV2b = TV._TM->_log_bernstein( TV );
2524  if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) )
2525  TV2 = TV2b;
2526  }
2527 
2528  TV2._bndord_uptd = false;
2529  TV2._unset_bndpol();
2530  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2531  return TV2;
2532 }
2533 
2534 template <typename T> inline TVar<T>
2535 TModel<T>::_log_taylor
2536 ( const TVar<T>&TV )
2537 {
2538  const T I( TV.B() );
2539  if ( Op<T>::l(I) <= 0. )
2540  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::LOG );
2541  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
2542  TV._coefmon[0] );
2543  const TVar<T> TVmx0( TV - x0 );
2544  const T Imx0( I - x0 );
2545 
2546  TVar<T> TV2( TV._TM, 0. ), MON( -1. );
2547 #ifdef MC__TMODEL_TIGHT_REMAINDER
2548  double R[3] = { 0., std::log(Op<T>::l(I))-std::log(x0), std::log(Op<T>::u(I))-std::log(x0) };
2549  double aL = -1., aU = -1.;
2550 #endif
2551  for( unsigned int i=1; i<=TV.nord(); i++ ){
2552  MON *= TVmx0 / (-x0);
2553  TV2 += MON / (double)i;
2554 #ifdef MC__TMODEL_TIGHT_REMAINDER
2555  aL *= (Op<T>::l(I)-x0) / (-x0);
2556  R[1] -= aL / (double)i;
2557  aU *= (Op<T>::u(I)-x0) / (-x0);
2558  R[2] -= aU / (double)i;
2559 #endif
2560  }
2561  TV2._coefmon[0] += std::log(x0);
2562 #ifdef MC__TMODEL_TIGHT_REMAINDER
2563  TV2 += max(3,R) + Op<T>::zeroone() * ( min(3,R) - max(3,R) );
2564 #else
2565  TV2 -= Op<T>::pow( - Imx0 / ( Op<T>::zeroone()*Imx0+x0 ),
2566  (int)TV2.nord()+1 ) / ( TV2.nord()+1. );
2567 #endif
2568  return TV2;
2569 }
2570 
2571 template <typename T> inline TVar<T>
2572 TModel<T>::_log_bernstein
2573 ( const TVar<T>&TV )
2574 {
2575  const T I( TV.B() );
2576  if ( Op<T>::l(I) <= 0. )
2577  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::LOG );
2578  struct loc{
2579  static double log
2580  ( const double x, const double*rusr, const int*iusr )
2581  { return std::log(x); }
2582  static double dlog
2583  ( const double x, const double*rusr, const int*iusr )
2584  { return 1./x; }
2585  static T Ilog
2586  ( const T&x, const double*rusr, const int*iusr )
2587  { return Op<T>::log(x); }
2588  static T d2Ilog
2589  ( const T&x, const double*rusr, const int*iusr )
2590  { return -Op<T>::sqr( Op<T>::inv(x) ); }
2591  };
2592  return TV._TM->_univ_bernstein( TV, loc::log, loc::dlog, loc::Ilog,
2593  loc::d2Ilog, 0, 0 );
2594 }
2595 
2596 template <typename T> inline TVar<T>
2597 xlog
2598 ( const TVar<T>&TV )
2599 {
2600  return TV * log( TV );
2601 }
2602 
2603 template <typename T> inline TVar<T>
2604 pow
2605 ( const TVar<T>&TV, const int n )
2606 {
2607  if( !TV._TM )
2608  return TVar<T>( Op<T>::pow(TV._coefmon[0] + *(TV._bndrem), n) );
2609 
2610  if( n < 0 ) return pow( inv( TV ), -n );
2611  TVar<T> TV2( TV._TM->_intpow( TV, n ) );
2612  if( TV2._TM && TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2613  return TV2;
2614 }
2615 
2616 template <typename T> inline TVar<T>
2617 TModel<T>::_intpow
2618 ( const TVar<T>&TV, const int n )
2619 {
2620  if( n == 0 ) return 1.;
2621  else if( n == 1 ) return TV;
2622  return n%2 ? sqr( _intpow( TV, n/2 ) ) * TV : sqr( _intpow( TV, n/2 ) );
2623 }
2624 
2625 template <typename T> inline TVar<T>
2626 pow
2627 ( const TVar<T> &TV, const double a )
2628 {
2629  return exp( a * log( TV ) );
2630 }
2631 
2632 template <typename T> inline TVar<T>
2633 pow
2634 ( const TVar<T> &TV1, const TVar<T> &TV2 )
2635 {
2636  return exp( TV2 * log( TV1 ) );
2637 }
2638 
2639 template <typename T> inline TVar<T>
2640 pow
2641 ( const double a, const TVar<T> &TV )
2642 {
2643  return exp( TV * std::log( a ) );
2644 }
2645 
2646 template <typename T> inline TVar<T>
2647 monomial
2648 (const unsigned int n, const TVar<T>*TV, const int*k)
2649 {
2650  if( n == 0 ){
2651  return 1.;
2652  }
2653  if( n == 1 ){
2654  return pow( TV[0], k[0] );
2655  }
2656  return pow( TV[0], k[0] ) * monomial( n-1, TV+1, k+1 );
2657 }
2658 
2659 template <typename T> inline TVar<T>
2660 cos
2661 ( const TVar<T> &TV )
2662 {
2663  if( !TV._TM )
2664  return TVar<T>( Op<T>::cos(TV._coefmon[0] + *(TV._bndrem)) );
2665 
2666  const T I( TV.B() );
2667  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I):
2668  TV._coefmon[0] );
2669  const TVar<T> TVmx0( TV - x0 );
2670  const T Imx0( I - x0 );
2671  double s = 1., c;
2672 
2673  TVar<T> TV2( TV._TM, 0. ), MON( 1. );
2674  for( unsigned int i=1; i<=TV.nord(); i++ ){
2675  switch( i%4 ){
2676  case 0: c = std::cos(x0); break;
2677  case 1: c = -std::sin(x0); break;
2678  case 2: c = -std::cos(x0); break;
2679  case 3:
2680  default: c = std::sin(x0); break;
2681  }
2682  MON *= TVmx0;
2683  TV2 += c * s * MON;
2684  s /= (double)(i+1);
2685  }
2686  TV2._coefmon[0] += std::cos(x0);
2687 
2688  switch( (TV2.nord()+1)%4 ){
2689  case 0: TV2 += s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2690  * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
2691  case 1: TV2 -= s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2692  * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
2693  case 2: TV2 -= s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2694  * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break;
2695  case 3: TV2 += s * Op<T>::pow( Imx0, (int)TV2.nord()+1 )
2696  * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break;
2697  }
2698 
2699  TV2._bndord_uptd = false;
2700  TV2._unset_bndpol();
2701  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2702  return TV2;
2703 }
2704 
2705 template <typename T> inline TVar<T>
2706 sin
2707 ( const TVar<T> &TV )
2708 {
2709  return cos( TV - PI/2. );
2710 }
2711 
2712 template <typename T> inline TVar<T>
2713 asin
2714 ( const TVar<T> &TV )
2715 {
2716  if( !TV._TM )
2717  return TVar<T>( Op<T>::asin(TV._coefmon[0] + *(TV._bndrem)) );
2718  if ( Op<T>::l(TV.B()) < -1. && Op<T>::u(TV.B()) > 1. )
2719  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::ASIN );
2720 
2721  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()):
2722  TV._coefmon[0] );
2723  double s = 1., t = 1.;
2724  TVar<T> G = TV * std::sqrt(1-x0*x0) - x0 * sqrt(1.-sqr(TV));
2725  TVar<T> TV2( G ), MON( G ), sqrG( sqr(G) );
2726  T IG( G.B() ), IG0( IG*Op<T>::zeroone() ), sqrIG0( Op<T>::sqr(IG0) ) ;
2727  T ASIN1, ASIN2( 1./Op<T>::sqrt(1-sqrIG0) ),
2728  ASIN3( IG0*Op<T>::pow(Op<T>::sqrt(1-sqrIG0),-3) );
2729  for( unsigned int i=1; i<=TV.nord(); i++ ){
2730  MON *= sqrG;
2731  s *= (double)(2*i-1)*(double)(2*i-1)/(double)(2*i)/(double)(2*i+1);
2732  TV2 += MON * s;
2733  t *= double(i+1);
2734  ASIN1 = ASIN2; ASIN2 = ASIN3;
2735  ASIN3 = ((2*i-1)*IG0*ASIN2+(i-1)*(i-1)*ASIN1)/(1-sqrIG0);
2736  }
2737  TV2._coefmon[0] += std::asin(x0);
2738  TV2 += Op<T>::pow( IG, (int)TV2.nord()+1 ) / t * ASIN2;
2739 
2740  TV2._bndord_uptd = false;
2741  TV2._unset_bndpol();
2742  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2743  return TV2;
2744 }
2745 
2746 template <typename T> inline TVar<T>
2747 acos
2748 ( const TVar<T> &TV )
2749 {
2750  return PI/2. - asin( TV );
2751 }
2752 
2753 template <typename T> inline TVar<T>
2754 tan
2755 ( const TVar<T> &TV )
2756 {
2757  return sin(TV) / cos(TV);
2758 }
2759 
2760 template <typename T> inline TVar<T>
2761 atan
2762 ( const TVar<T> &TV )
2763 {
2764  if( !TV._TM )
2765  return TVar<T>( Op<T>::atan(TV._coefmon[0] + *(TV._bndrem)) );
2766 
2767  double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()):
2768  TV._coefmon[0] );
2769  TVar<T> G = ( TV - x0 ) / ( 1. + x0 * TV );
2770  TVar<T> TV2( G ), MON( G ), msqrG( -sqr(G) );
2771  T IG( G.B() ), IG0( IG*Op<T>::zeroone() );
2772  for( unsigned int i=1; i<=TV.nord(); i++ ){
2773  MON *= msqrG;
2774  TV2 += MON / (2*i+1);
2775  }
2776  TV2._coefmon[0] += std::atan(x0);
2777  TV2 += Op<T>::pow( IG * Op<T>::cos( Op<T>::atan(IG0) ),
2778  (int)TV2.nord()+1 ) / (double)(TV2.nord()+1)
2779  * sin( (TV2.nord()+1) * (atan(IG0)+PI/2.) );
2780 
2781  TV2._bndord_uptd = false;
2782  TV2._unset_bndpol();
2783  if( TV2._TM->options.CENTER_REMAINDER ) TV2._center();
2784  return TV2;
2785 }
2786 
2787 template <typename T> inline TVar<T>
2788 hull
2789 ( const TVar<T>&TV1, const TVar<T>&TV2 )
2790 {
2791  // Neither operands associated to TModel -- Make intersection in T type
2792  if( !TV1._TM && !TV2._TM ){
2793  T R1 = TV1._coefmon[0] + *(TV1._bndrem);
2794  T R2 = TV2._coefmon[0] + *(TV2._bndrem);
2795  return Op<T>::hull(R1, R2);
2796  }
2797 
2798  // First operand not associated to TModel
2799  else if( !TV1._TM )
2800  return hull( TV2, TV1 );
2801 
2802  // Second operand not associated to TModel
2803  else if( !TV2._TM ){
2804  TVar<T> TVR = TV1.P();
2805  return TVR + Op<T>::hull( TV1.R(), TV2._coefmon[0]+*(TV2._bndrem)-TVR.B() );
2806  }
2807 
2808  // TModel for first and second operands are inconsistent
2809  else if( TV1._TM != TV2._TM )
2810  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
2811 
2812  // Perform union
2813  TVar<T> TV1C( TV1 ), TV2C( TV2 );
2814  const double eta = TV1._TM->options.REF_POLY;
2815  T R1C = TV1C.C().R(), R2C = TV2C.C().R();
2816  TV1C.set(T(0.));
2817  TV2C.set(T(0.));
2818  T BTVD = (TV1C-TV2C).B();
2819  TVar<T> TVR = (1.-eta)*TV1C + eta*TV2C + Op<T>::hull( R1C+eta*BTVD, R2C+(eta-1.)*BTVD );
2820 
2821  //TVR._bndord_uptd = false;
2822  //TVR._unset_bndpol();
2823  if( TVR._TM->options.CENTER_REMAINDER ) TVR._center();
2824  return TVR;
2825 }
2826 
2827 template <typename T> inline bool
2828 inter
2829 ( TVar<T>&TVR, const TVar<T>&TV1, const TVar<T>&TV2 )
2830 {
2831  // Neither operands associated to TModel -- Make intersection in T type
2832  if( !TV1._TM && !TV2._TM ){
2833  T R1 = TV1._coefmon[0] + *TV1._bndrem;
2834  T R2 = TV2._coefmon[0] + *TV2._bndrem;
2835  T RR( 0. );
2836  bool flag = Op<T>::inter(RR, R1, R2);
2837  TVR = RR;
2838  return flag;
2839  }
2840 
2841  // First operand not associated to TModel
2842  else if( !TV1._TM )
2843  return inter( TVR, TV2, TV1 );
2844 
2845  // Second operand not associated to TModel
2846  else if( !TV2._TM ){
2847  T R1 = TV1.R(), B2 = TV2.B();
2848  TVR = TV1.P();
2849  if( !Op<T>::inter(*(TVR._bndrem), R1, B2-TVR.B()) )
2850  return false;
2851 
2852  if( TVR._TM->options.CENTER_REMAINDER ) TVR._center();
2853  return true;
2854  }
2855 
2856  // TModel for first and second operands are inconsistent
2857  else if( TV1._TM != TV2._TM )
2858  throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL );
2859 
2860  // Perform intersection
2861  TVar<T> TV1C( TV1 ), TV2C( TV2 );
2862  const double eta = TV1._TM->options.REF_POLY;
2863  T R1C = TV1C.C().R(), R2C = TV2C.C().R();
2864  TV1C.set(T(0.));
2865  TV2C.set(T(0.));
2866  TVR = (1.-eta)*TV1C + eta*TV2C;
2867  TV1C -= TV2C;
2868  T BTVD = TV1C.B();
2869  if( !Op<T>::inter( *(TVR._bndrem), R1C+eta*BTVD, R2C+(eta-1.)*BTVD ) )
2870  return false;
2871 
2872  TVR._bndord_uptd = false;
2873  TVR._unset_bndpol();
2874  if( TVR._TM->options.CENTER_REMAINDER ) TVR._center();
2875  return true;
2876 }
2877 
2878 } // namespace mc
2879 
2880 #include "mcop.hpp"
2881 
2882 namespace mc
2883 {
2884 
2886 template <> template<typename T> struct Op< mc::TVar<T> >
2887 {
2888  typedef mc::TVar<T> TV;
2889  static TV point( const double c ) { return TV(c); }
2890  static TV zeroone() { return TV( mc::Op<T>::zeroone() ); }
2891  static void I(TV& x, const TV&y) { x = y; }
2892  static double l(const TV& x) { return mc::Op<T>::l(x.B()); }
2893  static double u(const TV& x) { return mc::Op<T>::u(x.B()); }
2894  static double abs (const TV& x) { return mc::Op<T>::abs(x.B()); }
2895  static double mid (const TV& x) { return mc::Op<T>::mid(x.B()); }
2896  static double diam(const TV& x) { return mc::Op<T>::diam(x.B()); }
2897  static TV inv (const TV& x) { return mc::inv(x); }
2898  static TV sqr (const TV& x) { return mc::sqr(x); }
2899  static TV sqrt(const TV& x) { return mc::sqrt(x); }
2900  static TV log (const TV& x) { return mc::log(x); }
2901  static TV xlog(const TV& x) { return x*mc::log(x); }
2902  static TV fabs(const TV& x) { return TV( mc::Op<T>::fabs(x.B()) ); }
2903  static TV exp (const TV& x) { return mc::exp(x); }
2904  static TV sin (const TV& x) { return mc::sin(x); }
2905  static TV cos (const TV& x) { return mc::cos(x); }
2906  static TV tan (const TV& x) { return mc::tan(x); }
2907  static TV asin(const TV& x) { return mc::asin(x); }
2908  static TV acos(const TV& x) { return mc::acos(x); }
2909  static TV atan(const TV& x) { return mc::atan(x); }
2910  static TV erf (const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ); }
2911  static TV erfc(const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ); }
2912  static TV fstep(const TV& x) { return TV( mc::Op<T>::fstep(x.B()) ); }
2913  static TV bstep(const TV& x) { return TV( mc::Op<T>::bstep(x.B()) ); }
2914  static TV hull(const TV& x, const TV& y) { return mc::hull(x,y); }
2915  static TV min (const TV& x, const TV& y) { return mc::Op<T>::min(x.B(),y.B()); }
2916  static TV max (const TV& x, const TV& y) { return mc::Op<T>::max(x.B(),y.B()); }
2917  static TV arh (const TV& x, const double k) { return mc::exp(-k/x); }
2918  template <typename X, typename Y> static TV pow(const X& x, const Y& y) { return mc::pow(x,y); }
2919  static TV monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); }
2920  static bool inter(TV& xIy, const TV& x, const TV& y) { return mc::inter(xIy,x,y); }
2921  static bool eq(const TV& x, const TV& y) { return mc::Op<T>::eq(x.B(),y.B()); }
2922  static bool ne(const TV& x, const TV& y) { return mc::Op<T>::ne(x.B(),y.B()); }
2923  static bool lt(const TV& x, const TV& y) { return mc::Op<T>::lt(x.B(),y.B()); }
2924  static bool le(const TV& x, const TV& y) { return mc::Op<T>::le(x.B(),y.B()); }
2925  static bool gt(const TV& x, const TV& y) { return mc::Op<T>::gt(x.B(),y.B()); }
2926  static bool ge(const TV& x, const TV& y) { return mc::Op<T>::ge(x.B(),y.B()); }
2927 };
2928 
2929 } // namespace mc
2930 
2931 #endif
~TVar()
Destructor of Taylor variable.
Definition: tmodel.hpp:918
C++ class for Taylor model computation of factorable function - Taylor model propagation.
Definition: tmodel.hpp:395
bool CENTER_REMAINDER
Whether to center the remainder term during Taylor model propagation.
Definition: tmodel.hpp:572
const T * bndmon() const
Const pointer to array of size nmon() with bounds on each monomial term in Taylor model...
Definition: tmodel.hpp:439
Eigenvalue decomposition-based bounder.
Definition: tmodel.hpp:559
Exceptions of mc::TModel.
Definition: tmodel.hpp:459
int ierr()
Error flag.
Definition: tmodel.hpp:479
unsigned int nmon() const
Total number of monomial terms in polynomial model.
Definition: polymodel.hpp:463
Lin & Stadtherr range bounder.
Definition: tmodel.hpp:558
C++ base class for the computation of polynomial models for factorable functions: Environment...
Definition: polymodel.hpp:36
unsigned int BOUNDER_ORDER
Order of Bernstein polynomial for Taylor model range bounding (no less than Taylor model order!)...
Definition: tmodel.hpp:566
std::pair< unsigned int, const double * > coefmon() const
Get pair of size of, and const pointer to, array of (possibly scaled) monomial coefficients in multiv...
Definition: polymodel.hpp:870
bool REF_MIDPOINT
Whether to take the midpoint of the inner range as the reference in the outer composition with a univ...
Definition: tmodel.hpp:574
TVar< T > & C()
Shortcut to mc::TVar::center.
Definition: tmodel.hpp:980
TModel< T > * env() const
Get pointer to linked Taylor model environment.
Definition: tmodel.hpp:876
std::string what()
Error description.
Definition: tmodel.hpp:481
double constant(const bool reset=false)
Get coefficient of constant term in Taylor variable. The value of this coefficient is reset to 0 if r...
Definition: tmodel.hpp:1754
virtual void _center()
Center remainder error term _bndrem
Definition: polymodel.hpp:850
TVar< T > P() const
Shortcut to mc::TVar::polynomial.
Definition: tmodel.hpp:971
Options of mc::TModel.
Definition: tmodel.hpp:515
Square-root operation with negative numbers in range.
Definition: tmodel.hpp:467
const unsigned int *const * prodmon() const
Const pointer to double array of size (_nmon+1,<=_nmon) with indices of monomial terms from product o...
Definition: tmodel.hpp:443
bool SCALE_VARIABLES
Whether to scale the variable ranges to [-1,1] internally.
Definition: tmodel.hpp:570
~TModel()
Destructor of Taylor model environment.
Definition: tmodel.hpp:435
T * _bndrem
Pointer to remainder bound of variable (possibly NULL if not computed)
Definition: polymodel.hpp:443
Options()
Constructor of mc::TModel::Options.
Definition: tmodel.hpp:518
bool BERNSTEIN_USE
Whether to compute a Berstein model [Stancu, 1963] of the outer function in a univariate composition ...
Definition: tmodel.hpp:578
Operation between Taylor variables linked to different Taylor models.
Definition: tmodel.hpp:473
void reset()
Reset the bounds on powers of (possibly scaled) variable ranges.
Definition: tmodel.hpp:455
C++ class for the computation of Taylor models of factorable function - Taylor model environment...
Definition: tmodel.hpp:406
BOUNDER
Taylor model range bounder option.
Definition: tmodel.hpp:556
Hybrid LSB + EIGEN range bounder.
Definition: tmodel.hpp:561
int BOUNDER_TYPE
Taylor model range bounder - See How are the options set for the computation of a Taylor model...
Definition: tmodel.hpp:564
Exceptions(TYPE ierr)
Constructor for error ierr
Definition: tmodel.hpp:477
unsigned int BERNSTEIN_MAXIT
Maximum number of iterations for determination of the exact remainder bounds in a Berstein model of c...
Definition: tmodel.hpp:582
const double * reference() const
Get const pointer to array of size nvar with references for all variables in Taylor model...
Definition: tmodel.hpp:447
Sine/Cosine inverse operation with range outside [-1,1].
Definition: tmodel.hpp:468
TVar< T > & center()
Center remainder term of Taylor variable.
Definition: tmodel.hpp:976
const double * scaling() const
Get const pointer to array of size nvar with scaling coefficients in Taylor model.
Definition: tmodel.hpp:451
Log operation with non-positive numbers in range.
Definition: tmodel.hpp:466
virtual T B() const
Shortcut to mc::PolyVar::bound.
Definition: polymodel.hpp:651
bool BERNSTEIN_OPT
Whether to compute exact remainder bounds for Berstein models of convex/concave univariates exp...
Definition: tmodel.hpp:580
Division by zero scalar.
Definition: tmodel.hpp:464
virtual PolyVar< T > & set(PolyModel *env)
Set polynomial model environment in variable as env
Definition: polymodel.hpp:573
static const std::string BOUNDER_NAME[5]
Array of Taylor model range bounder names (for display)
Definition: tmodel.hpp:568
C++ base class for the computation of polynomial models for factorable functions: Variable...
Definition: polymodel.hpp:425
virtual T B(const int type) const
Shortcut to mc::PolyVar::bound.
Definition: polymodel.hpp:645
unsigned int nord() const
Order of polynomial model.
Definition: polymodel.hpp:451
virtual void _set_bndpol(const T &bndpol)
Set polynomial bound in variable as bndpol
Definition: polymodel.hpp:841
Failed to construct Taylor variable.
Definition: tmodel.hpp:471
bool _bndord_uptd
Whether the bounds in bndord are up-to-date.
Definition: polymodel.hpp:440
unsigned int nord() const
Order of polynomial model environment.
Definition: polymodel.hpp:62
unsigned int DISPLAY_DIGITS
Number of digits in output stream for Taylor model coefficients.
Definition: tmodel.hpp:586
double BERNSTEIN_TOL
Termination tolerance for determination of the exact remainder bounds in a Berstein model of convex/c...
Definition: tmodel.hpp:584
TVar< T > & set(TModel< T > *TM, const unsigned int ix, const T &X, const double Xref)
Set Taylor variable with index ix (starting from 0), bounded by X and with reference point Xref...
Definition: tmodel.hpp:941
Inverse operation with zero in range.
Definition: tmodel.hpp:465
Feature not yet implemented in mc::TModel.
Definition: tmodel.hpp:474
PolyModel(const unsigned int nvar, const unsigned int nord)
Constructor of polynomial model environment for nvar variables and order nord
Definition: polymodel.hpp:46
TYPE
Enumeration type for TModel exception handling.
Definition: tmodel.hpp:463
double * linear() const
Get pointer to array of size nvar with coefficients of linear term in Taylor variable.
Definition: tmodel.hpp:1762
double * _coefmon
Array of size _nmon with monomial coefficients of variable.
Definition: polymodel.hpp:434
Taylor model bound does not intersect with bound in template parameter arithmetic.
Definition: tmodel.hpp:472
Naive polynomial range bounder.
Definition: tmodel.hpp:557
T * _bndord
Array of size _nord+2 with bounds for all terms of degrees iord=0,...,_nord as well as the remainder ...
Definition: polymodel.hpp:437
TVar< T > polynomial() const
Return new Taylor variable with same multivariate polynomial part but zero remainder.
Definition: tmodel.hpp:965
unsigned int nvar() const
Number of variables in polynomial model environment.
Definition: polymodel.hpp:56
double REF_POLY
Scalar in related to the choice of the polynomial part in the overloaded functions mc::inter and mc:...
Definition: tmodel.hpp:576
Bernstein range bounder.
Definition: tmodel.hpp:560
Failed to compute the maximum gap between a univariate term and its Bernstein model.
Definition: tmodel.hpp:470
C++ structure to allow usage of various template parameters in the types mc::McCormick, mc::TModel, mc::TVar, and mc::SpecBnd of MC++ _ Specialization of this structure is required for the template parameters can be found in the header files defining the types mc::McCormick, mc::TModel, mc::TVar, and mc::SpecBnd.
Definition: mcop.hpp:13
Failed to compute eigenvalue decomposition in range bounder TModel::Options::EIGEN.
Definition: tmodel.hpp:469