MC++
ellimage.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 
268 #ifndef MC__ELLIMAGE_H
269 #define MC__ELLIMAGE_H
270 
271 #include <assert.h>
272 #include <exception>
273 
274 #include "mcfunc.hpp"
275 #include "mcop.hpp"
276 #include "mclapack.hpp"
277 #include "ellipsoid.hpp"
278 #include "cmodel.hpp"
279 
280 #include <fstream>
281 #include <iomanip>
282 
283 #undef MC__ELLIMAGE_DEBUG
284 
285 namespace mc
286 {
287 
288 template< class T > class EllVar;
289 
290 
300 template< class T >
301 class EllImg: public Ellipsoid
303 {
304 
305  friend class EllVar<T>;
306 
307  template< class U > friend EllVar<U> operator+( const EllVar<U>& );
308  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const EllVar<U>& );
309  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const double );
310  template< class U > friend EllVar<U> operator+( const double, const EllVar<U>& );
311  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const U& );
312  template< class U > friend EllVar<U> operator+( const U&, const EllVar<U>& );
313  template< class U > friend EllVar<U> operator-( const EllVar<U>& );
314  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const EllVar<U>& );
315  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const double );
316  template< class U > friend EllVar<U> operator-( const double, const EllVar<U>& );
317  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const U& );
318  template< class U > friend EllVar<U> operator-( const U&, const EllVar<U>& );
319  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const EllVar<U>& );
320  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const double );
321  template< class U > friend EllVar<U> operator*( const double, const EllVar<U>& );
322  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const U& );
323  template< class U > friend EllVar<U> operator*( const U&, const EllVar<U>& );
324  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const EllVar<U>& );
325  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const double );
326  template< class U > friend EllVar<U> operator/( const double, const EllVar<U>& );
327  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const U& );
328  template< class U > friend EllVar<U> operator/( const U&, const EllVar<U>& );
329 
330  template< class U > friend EllVar<U> inv ( const EllVar<U>& );
331  template< class U > friend EllVar<U> exp ( const EllVar<U>& );
332  template< class U > friend EllVar<U> log ( const EllVar<U>& );
333  template< class U > friend EllVar<U> sqrt( const EllVar<U>& );
334  template< class U > friend EllVar<U> sqr ( const EllVar<U>& );
335  template< class U > friend EllVar<U> pow ( const EllVar<U>&, const int );
336  template< class U > friend EllVar<U> cos ( const EllVar<U>& );
337  template< class U > friend EllVar<U> sin ( const EllVar<U>& );
338  template< class U > friend EllVar<U> tan ( const EllVar<U>& );
339  template< class U > friend EllVar<U> acos( const EllVar<U>& );
340  template< class U > friend EllVar<U> asin( const EllVar<U>& );
341  template< class U > friend EllVar<U> atan( const EllVar<U>& );
342 
343  public:
347  class Exceptions{
349  public:
351  enum TYPE{
352  DIV = 1,
353  INV,
354  LOG,
356  TAN,
358  INIT = -1,
359  EIMG = -3,
360  UNDEF = -33
361  };
363  Exceptions( TYPE ierr ) : _ierr( ierr ){}
365  int ierr(){ return _ierr; }
367  std::string what(){
368  switch( _ierr ){
369  case DIV : return "mc::EllImg\t Division by zero scalar";
370  case INV : return "mc::EllImg\t Inverse operation with zero in domain";
371  case LOG : return "mc::EllImg\t Log operation with non-positive numbers in domain";
372  case SQRT : return "mc::EllImg\t Square-root operation with negative numbers in domain";
373  case TAN : return "mc::EllImg\t Tangent operation with zero in domain of cosine";
374  case ACOS : return "mc::EllImg\t Inverse sine/cosine operation with domain outside [-1,1]";
375  case EIMG : return "mc::EllImg\t EllVars belong to different ellipsoids, operation not allowed";
376  case UNDEF : return "mc::EllImg\t Feature not yet implemented in mc::EllImg class";
377  default : return "mc::EllImg\t Undocumented error";
378  }
379  }
380 
381  private:
383  TYPE _ierr;
384  };
385 
388  {
391  Ellipsoid::Options(), PREALLOC( 0 ), CHEBUSE( false ), CHEBORDER( 5 )
392  {}
394  long PREALLOC;
396  bool CHEBUSE;
398  unsigned CHEBORDER;
399  } options;
402  private:
404  CPPL::dssmatrix _Q;
406  CPPL::dcovector _q;
408  long _nx;
410  long _current_row;
412  CModel<T>* _CMpt;
414  bool _depmap_flag;
416  CPPL::dssmatrix _depmap;
418  long _ip;
419 
420 #ifdef MC__ELLIMAGE_DEBUG
421  std::ofstream _dbugout;
423 #endif
424 
425  public:
429  CPPL::dssmatrix Q_lift()
431  { return _Q; }
432 
434  CPPL::dcovector c_lift()
435  { return _q; }
436 
438  EllImg();
439 
441  EllImg
442  ( const CPPL::dsymatrix& Q, const CPPL::dcovector& c=CPPL::dcovector(),
443  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() );
444 
446  EllImg
447  ( const unsigned int n, const double*Q, const double*c=0,
448  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() );
449 
451  EllImg
452  ( const CPPL::dcovector& r, const CPPL::dcovector& c=CPPL::dcovector(),
453  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() );
454 
456  EllImg
457  ( const EllImg<T>& E );
458 
460  virtual ~EllImg();
461 
463  EllImg<T>& set
464  ( const EllImg<T>& E )
465  { Ellipsoid::set( E.Q(), E.c() ); return _reset( E._depmap ); }
466 
468  EllImg<T>& set
469  ( const CPPL::dsymatrix& Q, const CPPL::dcovector& c=CPPL::dcovector(),
470  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() )
471  { Ellipsoid::set( Q, c ); return _reset( depmap ); }
472 
474  EllImg<T>& set
475  ( const unsigned int n, const double*Q, const double*c=0,
476  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() )
477  { Ellipsoid::set( n, Q, c ); return _reset( depmap ); }
478 
480  EllImg<T>& set
481  ( const CPPL::dcovector& r, const CPPL::dcovector& c=CPPL::dcovector(),
482  const CPPL::dssmatrix& depmap = CPPL::dssmatrix() )
483  { Ellipsoid::set( r, c ); return _reset( depmap ); }
484 
487  { return _reset(); }
488 
490  EllImg<T> get( unsigned nvar, EllVar<T>* var )
491  { return _get( nvar, var ); }
492 
494  std::ostream& output( std::ostream&os = std::cout );
497  private:
499  void _minksum( const EllVar<T>&, double );
500 
502  void _minksum( long, double );
503 
505  double _trQ();
506 
508  EllImg<T>& _set( const CPPL::dssmatrix& depmap );
509 
511  EllImg<T>& _reset( const CPPL::dssmatrix& depmap = CPPL::dssmatrix() )
512  { delete _CMpt; return _set( depmap ); }
513 
515  EllImg<T> _get( unsigned, EllVar<T>* );
516 
518  void _univupdate( long, long, double, double, double );
519 
521  void _univupdate( long, long, CPPL::drovector, double, double, double );
522 
524  typedef CVar<T> (univariate_function) ( const CVar<T>& ) ;
525 
527  typedef std::tuple<double, double, double> lin_param;
528 
530  lin_param _cmodel_linear( univariate_function, const T& );
531 
533  lin_param _cmodel_linear( const int, const T& );
534 
536  lin_param _linearize_sqr( const T& );
537 };
538 
546 template< class T >
547 class EllVar
549 {
550  friend class EllImg<T>;
551 
552  template< class U > friend EllVar<U> operator+( const EllVar<U>& );
553  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const EllVar<U>& );
554  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const double );
555  template< class U > friend EllVar<U> operator+( const double, const EllVar<U>& );
556  template< class U > friend EllVar<U> operator+( const EllVar<U>&, const U& );
557  template< class U > friend EllVar<U> operator+( const U&, const EllVar<U>& );
558  template< class U > friend EllVar<U> operator-( const EllVar<U>& );
559  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const EllVar<U>& );
560  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const double );
561  template< class U > friend EllVar<U> operator-( const double, const EllVar<U>& );
562  template< class U > friend EllVar<U> operator-( const EllVar<U>&, const U& );
563  template< class U > friend EllVar<U> operator-( const U&, const EllVar<U>& );
564  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const EllVar<U>& );
565  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const double );
566  template< class U > friend EllVar<U> operator*( const double, const EllVar<U>& );
567  template< class U > friend EllVar<U> operator*( const EllVar<U>&, const U& );
568  template< class U > friend EllVar<U> operator*( const U&, const EllVar<U>& );
569  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const EllVar<U>& );
570  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const double );
571  template< class U > friend EllVar<U> operator/( const double, const EllVar<U>& );
572  template< class U > friend EllVar<U> operator/( const EllVar<U>&, const U& );
573  template< class U > friend EllVar<U> operator/( const U&, const EllVar<U>& );
574 
575  template< class U > friend EllVar<U> inv ( const EllVar<U>& );
576  template< class U > friend EllVar<U> exp ( const EllVar<U>& );
577  template< class U > friend EllVar<U> log ( const EllVar<U>& );
578  template< class U > friend EllVar<U> sqrt( const EllVar<U>& );
579  template< class U > friend EllVar<U> sqr ( const EllVar<U>& );
580  template< class U > friend EllVar<U> pow ( const EllVar<U>&, const int );
581  template< class U > friend EllVar<U> cos ( const EllVar<U>& );
582  template< class U > friend EllVar<U> sin ( const EllVar<U>& );
583  template< class U > friend EllVar<U> tan ( const EllVar<U>& );
584  template< class U > friend EllVar<U> acos( const EllVar<U>& );
585  template< class U > friend EllVar<U> asin( const EllVar<U>& );
586  template< class U > friend EllVar<U> atan( const EllVar<U>& );
587 
588  private:
590  EllImg<T>* _EI;
592  long _RowInd;
594  bool _is_constant;
596  double _const_val;
598  T _Range;
599 
600  public:
604  EllVar();
607  EllVar( const EllVar<T>& );
609  EllVar( const double d );
611  EllVar( const T& );
613  EllVar( const double l, const double u );
615  EllVar( EllImg<T>&, const unsigned );
617  EllVar( EllImg<T>&, const unsigned, const T& );
618 
620  virtual ~EllVar(){};
621 
623  EllVar<T>& set( EllImg<T>& EI, const unsigned i )
624  { return _set( EI, i ); }
626  EllVar<T>& set( EllImg<T>& EI, const unsigned i, const T& Irange )
627  { return _set( EI, i, Irange ); }
628 
630  T range() const
631  { return !_is_constant? _Range: _const_val; }
633  EllImg<T>* image() const
634  { return _EI; }
636  long index() const
637  { return _RowInd; }
640  private:
642  EllVar( EllImg<T>*, long );
644  EllVar( EllImg<T>*, long, long );
645 
647  EllVar<T>& _set( EllImg<T>&, const unsigned );
649  EllVar<T>& _set( EllImg<T>&, const unsigned, const T& );
650 
652  const T& _range() const
653  { return _Range; }
655  T& _range()
656  { return _Range; }
657 
658  public:
659  // Public overloads
660  EllVar<T>& operator= ( const EllVar<T>& );
661  EllVar<T>& operator= ( const double );
662  EllVar<T>& operator= ( const T& );
663 
664  EllVar<T>& operator+=( const EllVar<T>& );
665  EllVar<T>& operator-=( const EllVar<T>& );
666  EllVar<T>& operator*=( const EllVar<T>& );
667  EllVar<T>& operator/=( const EllVar<T>& );
668 
669 };
670 
672 
673 template <class T>
674 inline
676 : _nx(0), _current_row(0), _CMpt(0), _depmap_flag(false), _depmap(), _ip(-1)
677 {
678 #ifdef MC__ELLIMAGE_DEBUG
679  _dbugout.open( "debug.log" , std::ios_base::out );
680 #endif
681 }
682 
683 template <class T>
684 inline
686 ( const CPPL::dsymatrix& Q, const CPPL::dcovector& c, const CPPL::dssmatrix& depmap )
687 : Ellipsoid( Q, c )
688 {
689 #ifdef MC__ELLIMAGE_DEBUG
690  _dbugout.open( "debug.log" , std::ios_base::out );
691 #endif
692  _set( depmap );
693 }
694 
695 template <class T>
696 inline
698 ( const EllImg<T>& E )
699 : Ellipsoid( E ), options( E.options )
700 {
701 #ifdef MC__ELLIMAGE_DEBUG
702  _dbugout.open( "debug.log" , std::ios_base::out );
703 #endif
704  _set( E._depmap );
705  //_depmap = E._depmap;
706 }
707 
708 template <class T>
709 inline
711 ( const unsigned int n, const double*Q, const double*c, const CPPL::dssmatrix& depmap )
712 : Ellipsoid( n, Q, c )
713 {
714 #ifdef MC__ELLIMAGE_DEBUG
715  _dbugout.open( "debug.log" , std::ios_base::out );
716 #endif
717  _set( depmap );
718 }
719 
720 template <class T>
721 inline
723 ( const CPPL::dcovector& r, const CPPL::dcovector& c, const CPPL::dssmatrix& depmap )
724 : Ellipsoid( r, c )
725 {
726 #ifdef MC__ELLIMAGE_DEBUG
727  _dbugout.open( "debug.log" , std::ios_base::out );
728 #endif
729  _set( depmap );
730 }
731 
732 template <class T>
733 inline
735 {
736 #ifdef MC__ELLIMAGE_DEBUG
737  _dbugout.close();
738 #endif
739  delete _CMpt;
740 }
741 
742 template <class T>
743 inline
744 EllImg<T>&
746 ( const CPPL::dssmatrix& depmap )
747 {
748  _nx = Q().n ; // resets the number of dependent variables to the dimension of the shape matrix provided
749  _current_row = _nx ; // resets _current_row to the number of dependent variables
750  _ip = -1 ; // resets the row index for the product to the
751  _CMpt = 0 ;
752 
753  // No depmap available
754  if( !depmap.n ){
755  // set Ellipsoid to E0(Q0,q0)
756  _Q = Q().to_dssmatrix();
757  _q = c();
758  _depmap_flag = false;
759  _depmap.clear();
760  }
761 
762  //depmap available
763  else{
764  _Q.resize( depmap.n );
765  _q.resize( depmap.n );
766  _q.zero();
767  _depmap_flag = true;
768  _depmap = depmap;
769  // Set the underlying lifted ellipsoid
770  for( long j=0; j<Q().n; ++j ){
771  // Initialise the varindex-th row of _Q with the varindex-th row of the shape matrix of Ell ;
772  for (long i=0; i<=j; ++i ) _Q.put( i, j, Q(i,j) );
773  // Initialise the varindex-th row of _q with the varindex-th row of the centre vector of Ell ;
774  _q(j) = c(j);
775  }
776  }
777 
778  return *this;
779 }
780 
781 template <class T>
782 inline
783 EllImg<T>
784 EllImg<T>::_get
785 ( unsigned nvar, EllVar<T>* var )
786 {
787  CPPL::dsymatrix Q0( nvar ); Q0.zero();
788  CPPL::dcovector q0( nvar ); q0.zero();
789  for( long j=0 ; j<nvar; ++j )
790  {
791  long prev = var[j]._RowInd;
792  for ( long i=j ; i<nvar ; ++i )
793  {
794  Q0( i , j ) = _Q( var[i]._RowInd , prev ) ;
795  q0( j ) = _q( var[j]._RowInd ) ;
796  }
797  }
798  return EllImg<T>( Q0, q0 );
799 }
800 
801 template <class T>
802 inline
803 std::ostream&
805 ( std::ostream&os )
806 {
807  if( !_Q.n ) return os;
808  const int iprec = 5;
809  os << std::scientific << std::setprecision(iprec);
810  os << "\nlifted center:\n" << _q;
811  os << "lifted shape matrix:\n" << _Q;
812  return os;
813 }
814 
815 template <class T>
816 inline
817 void
819 ( long i ,
820  long k ,
821  double c0 ,
822  double c1 ,
823  double eta )
824 {
833  // Update centre
834  _q( i ) = c0;
835  // Update matrix when the shape matrix has been initialised with a dependency map
836  if( _depmap_flag )
837  {
838  // Update shape matrix
839  for(long j = 0; j < i ; ++j) if( _depmap.isListed( i, j ) ) _Q(i, j) = c1 * _Q(k,j) ;
840  // Update diagonal element
841  _Q( i, i ) = std::pow(c1,2) * _Q(k,k) ;
842  }
843  else // No dependecy map available
844  {
845  // Update shape matrix
846  for(long j = 0; j < i ; ++j) if( _Q.isListed( k, j ) ) _Q.put(i, j, c1 * _Q(k,j) );
847  // Update diagonal element
848  _Q.put( i, i, std::pow(c1,2) * _Q(k,k) );
849  }
850  // Minkowski sum with an interval centered at 0 with radius eta
851  _minksum( i , eta );
860 }
861 
862 template <class T>
863 inline
864 void
865 EllImg<T>::_univupdate
866 ( long i ,
867  long k ,
868  CPPL::drovector rQ ,
869  double c0 ,
870  double c1 ,
871  double eta )
872 {
873  // Update centre
874  _q( i ) = c0;
875  // Update matrix when the shape matrix has been initialised with a dependency map
876  if( _depmap_flag )
877  {
878  // Update shape matrix
879  for(long j = 0; j < i ; ++j) if( _depmap.isListed( i, j ) ) _Q(i, j) = c1 * _Q(k,j) ;
880  // Update diagonal element
881  if( _depmap.isListed( i, i ) ) _Q( i, i ) = std::pow(c1,2) * _Q(k,k) ;
882  }
883  else // No dependecy map available
884  {
885  // Update shape matrix
886  for(long j = 0; j < i ; ++j) _Q.put(i, j, c1 * _Q(k,j) );
887  // Update diagonal element
888  _Q.put( i, i, std::pow(c1,2) * _Q(k,k) );
889  }
890  // Minkowski sum with an interval centered at 0 with radius eta
891  _minksum( i , eta );
892 }
893 
895 template <class T>
896 inline
897 typename EllImg<T>::lin_param
898 EllImg<T>::_linearize_sqr
899 ( const T& domain )
900 {
901  if( options.CHEBUSE ) return _cmodel_linear( sqr , domain );
902 
903  // Compute linear approximation of sqr(m+r*x) with x \in [-1,1] using minimax linearisation
904  double c0, c1, eta;
905  double m = Op<T>::mid( domain );
906  double r = 0.5 * Op<T>::diam( domain );
907  double c_sec=0., x_tan=0., c_tan=0.;
908  c_sec = m*m+r*r;
909  c1 = 2.0*m*r;
910  x_tan = (c1-2.*m*r)/(2.*r*r);
911  c_tan = sqr(m+r*x_tan) - c1*x_tan;
912  eta = 0.5*(c_sec - c_tan);
913  c0 = c_sec - eta;
914  c1 = c1 / r;
915  return std::make_tuple( c0, c1, eta );
916 }
917 
919 template <class T>
920 inline
921 typename EllImg<T>::lin_param
922 EllImg<T>::_cmodel_linear
923 ( univariate_function f, const T& domain )
924 {
925  // (re)initialise Chebyshev model if it hasnt been used
926  // or is of different order
927  if( !_CMpt ) _CMpt = new CModel<T>( 1, options.CHEBORDER );
928  else if( _CMpt->nord() != options.CHEBORDER )
929  { delete _CMpt; _CMpt = new CModel<T>( 1, options.CHEBORDER ); }
930 
931  CVar<T> CVX( _CMpt, 0 , domain );
932  CVar<T> CVF = f( CVX );
933  double c0 = CVF.C().constant();
934  double c1 = CVF.linear( 0 , true );
935  double eta = 0.5 * Op<T>::diam(CVF.B());
936  return std::make_tuple( c0, c1, eta );
937 }
938 
939 template <class T>
940 inline
941 typename EllImg<T>::lin_param
942 EllImg<T>::_cmodel_linear
943 ( const int n, const T& domain )
944 {
945  // (re)initialise Chebyshev model if it hasnt been used
946  // or is of different order
947  if( !_CMpt ) _CMpt = new CModel<T>( 1, options.CHEBORDER );
948  else if( _CMpt->nord() != options.CHEBORDER )
949  { delete _CMpt; _CMpt = new CModel<T>( 1, options.CHEBORDER ); }
950 
951  CVar<T> CVX( _CMpt, 0 , domain );
952  CVar<T> CVF = pow( CVX, n);
953  double c0 = CVF.C().constant();
954  double c1 = CVF.linear( 0 , true );
955  double eta = 0.5 * Op<T>::diam(CVF.B());
956  return std::make_tuple( c0, c1, eta );
957 }
958 
959 template <class T>
960 inline
961 void
962 EllImg<T>::_minksum
963 ( const EllVar<T>& EllVar1, double rad )
964 {
965  long i = EllVar1._RowInd;
966  _minksum( i, rad );
967 }
968 
969 template <class T>
970 inline
971 void
972 EllImg<T>::_minksum
973 ( const long i, const double rad )
974 {
975  #ifdef MC__ELLIMAGE_DEBUG
976  _dbugout << std::scientific << std::setprecision(3) << std::right;
977  _dbugout << "Minkowski sum starts: i= " << i <<std::endl;
978  _dbugout << "q \n" ;
979  _dbugout << _q <<std::endl;
980  _dbugout << "Q \n" ;
981  _dbugout << _Q <<std::endl;
982  #endif
983  double TOL = 1e-8, EPS = machprec(), strQ = 0.0;
984 
985  for( long j=0; j<=i ; ++j ){
986  if( _Q.isListed(j,j) ) strQ += _Q(j,j)/(_Q(j,j)+TOL); // for some reason this loops modifies the diagonal elements of the product block if the isListed is not used ...
987  }
988  strQ = std::sqrt(strQ);
989  double sqrR = rad/std::sqrt(_Q(i,i)+TOL);
990  double kappa = strQ + sqrR + EPS;
991  _Q *= (kappa/(strQ+EPS));
992  _Q(i,i) += (std::pow(rad,2)*kappa)/(sqrR+EPS);
993 
1002 }
1003 
1004 template <class T>
1005 inline
1006 double
1007 EllImg<T>::_trQ
1008 ()
1009 {
1010  if( !_Q.n ) return 0.;
1011  double tr(_Q(0,0));
1012  for( unsigned int i=1; i<_Q.n; i++ ) tr += _Q(i,i);
1013  return tr;
1014 }
1015 
1017 
1018 template <class T>
1019 inline
1021 ( ) :
1022  _EI ( NULL ) ,
1023  _RowInd ( -1 ) ,
1024  _is_constant( false ) ,
1025  _const_val ( 0 ) ,
1026  _Range ( T(0) )
1027 {}
1028 
1029 template <class T>
1030 inline
1032 ( const EllVar<T>& EllVar1 ) :
1033  _EI ( EllVar1._EI ) ,
1034  _RowInd ( EllVar1._RowInd ) ,
1035  _is_constant( EllVar1._is_constant ) ,
1036  _const_val ( EllVar1._const_val ) ,
1037  _Range ( EllVar1._Range )
1038 { }
1039 
1040 template <class T>
1041 inline
1043 ( const double d ) :
1044  _EI ( NULL ) , // a "double" EllVar lives outside the EllImg
1045  _RowInd ( -1 ) , // it is also a constant and has a "trivial"
1046  _is_constant( true ) , // range. Test to identify it
1047  _const_val ( d ) , // if( _EI == NULL && _is_constant ) .
1048  _Range ( T(d) ) // Range should not be accessed.
1049 { }
1050 
1051 template <class T>
1052 inline
1054 ( const T& B ) :
1055  _EI ( NULL ) , // an "interval" EllVar lives outside the Ellimg
1056  _RowInd ( -1 ) , // it is NOT a constant, has a trivial constant
1057  _is_constant( false ) , // constant value and a nontrivial range. Test
1058  _const_val ( 0. ) , // to identify it is
1059  _Range ( B ) // if( _EI == NULL && !_is_constant ) .
1060 { }
1061 
1062 template <class T>
1063 inline
1065 ( const double l, const double u ) :
1066  _EI ( NULL ) , // an "interval" EllVar lives outside the Ellimg
1067  _RowInd ( -1 ) , // it is NOT a constant, has a trivial constant
1068  _is_constant( false ) , // constant value and a nontrivial range. Test
1069  _const_val ( 0. ) , // to identify it is
1070  _Range ( l, u ) // if( _EI == NULL && !_is_constant ) .
1071 { }
1072 
1073 template <class T>
1074 inline
1076 ( EllImg<T>& EI, const unsigned i )
1077 {
1078  _set( EI, i );
1079 }
1080 
1081 template <class T>
1082 inline
1084 ( EllImg<T>& EI, const unsigned i, const T& Irange )
1085 {
1086  _set( EI, i, Irange );
1087 }
1088 
1089 template <class T>
1090 inline
1092 ( EllImg<T>* EI ,
1093  long RowInd ) :
1094  _EI ( EI ) ,
1095  _RowInd ( RowInd ) ,
1096  _is_constant( false ) ,
1097  _const_val ( 0. ) ,
1098  _Range ( T() )
1099 {
1100  if( !_EI ) throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INIT );
1101  // The ellipsoid is lifted if it has not been initialised with a dependecy map
1102  if( ! EI->_depmap_flag )
1103  {
1104  // Checks if preallocation is needed
1105  if( EI->options.PREALLOC && RowInd >= EI->_Q.n )
1106  {
1107  long dim = EI->options.PREALLOC;
1108  EI->_Q.stretch( dim );
1109  EI->_q.stretch( dim );
1110  }
1111  else if( !EI->options.PREALLOC && RowInd >= EI->_Q.n )
1112  {
1113  EI->_Q.stretch( 1 );
1114  EI->_q.stretch( 1 );
1115  }
1116  }
1117  EI->_current_row++;
1118 }
1119 
1120 template <class T>
1121 inline
1123 ( EllImg<T>* EI ,
1124  long RowInd ,
1125  long current_row ) :
1126  _EI ( EI ) ,
1127  _RowInd ( RowInd ) ,
1128  _is_constant( false ) ,
1129  _const_val ( 0. ) ,
1130  _Range ( T() )
1131 {
1132  if( !_EI ) throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INIT );
1133  // The ellipsoid is lifted if it has not been initialised with a dependecy map
1134  if( ! EI->_depmap_flag )
1135  {
1136  // Checks if preallocation is needed
1137  if( EI->options.PREALLOC && RowInd >= EI->_Q.n )
1138  {
1139  long dim = EI->options.PREALLOC;
1140  EI->_Q.stretch( dim );
1141  EI->_q.stretch( dim );
1142  }
1143  else if( !EI->options.PREALLOC && RowInd >= EI->_Q.n )
1144  {
1145  EI->_Q.stretch( 1 );
1146  EI->_q.stretch( 1 );
1147  }
1148  }
1149  EI->_current_row = current_row;
1150 }
1151 
1152 template <class T>
1153 inline
1154 EllVar<T>&
1155 EllVar<T>::_set
1156 ( EllImg<T>& EI, const unsigned i )
1157 {
1158  if( i >= EI._nx )
1159  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INIT );
1160  _EI = &EI;
1161  _RowInd = i;
1162  _is_constant = false;
1163  _const_val = 0.;
1164  _Range = EI._q(i) + std::sqrt(EI._Q( i,i )) * T(-1.,1.);
1165  return *this;
1166 }
1167 
1168 template <class T>
1169 inline
1170 EllVar<T>&
1171 EllVar<T>::_set
1172 ( EllImg<T>& EI, const unsigned i, const T& Irange )
1173 {
1174  if( i >= EI._nx )
1175  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INIT );
1176  _EI = &EI;
1177  _RowInd = i;
1178  _is_constant = false;
1179  _const_val = 0.;
1180  if( !Op<T>::inter( _Range, EI._q(i) + std::sqrt(EI._Q( i,i )) * T(-1.,1.), Irange ) )
1181  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INIT );
1182  return *this;
1183 }
1184 
1185 template <class T>
1186 inline
1187 EllVar<T>&
1188 EllVar<T>::operator=
1189 ( const EllVar<T>& EllVar1 )
1190 {
1191  _EI = EllVar1._EI ;
1192  _RowInd = EllVar1._RowInd ;
1193  _is_constant = EllVar1._is_constant ;
1194  _const_val = EllVar1._const_val ;
1195  _Range = EllVar1._Range ;
1196  return *this;
1197 }
1198 
1199 template <class T>
1200 inline
1201 EllVar<T>&
1202 EllVar<T>::operator=
1203 ( const double d )
1204 {
1205  _EI = NULL ;
1206  _RowInd = -1 ;
1207  _is_constant = true ;
1208  _const_val = d ;
1209  _Range = T(d) ;
1210  return *this;
1211 }
1212 
1213 template <class T>
1214 inline
1215 EllVar<T>&
1216 EllVar<T>::operator=
1217 ( const T& B )
1218 {
1219  _EI = NULL ;
1220  _RowInd = -1 ;
1221  _is_constant = false ;
1222  _const_val = 0 ;
1223  _Range = B ;
1224  return *this;
1225 }
1226 
1227 template <typename T> inline EllVar<T>&
1228 EllVar<T>::operator +=
1229 ( const EllVar<T>&E1 )
1230 {
1231  EllVar<T> E2( *this );
1232  *this = E2 + E1;
1233  return *this;
1234 }
1235 
1236 template <typename T> inline EllVar<T>&
1237 EllVar<T>::operator -=
1238 ( const EllVar<T>&E1 )
1239 {
1240  EllVar<T> E2( *this );
1241  *this = E2 - E1;
1242  return *this;
1243 }
1244 
1245 template <typename T> inline EllVar<T>&
1246 EllVar<T>::operator *=
1247 ( const EllVar<T>&E1 )
1248 {
1249  EllVar<T> E2( *this );
1250  *this = E2 * E1;
1251  return *this;
1252 }
1253 
1254 template <typename T> inline EllVar<T>&
1255 EllVar<T>::operator /=
1256 ( const EllVar<T>&E1 )
1257 {
1258  EllVar<T> E2( *this );
1259  *this = E2 / E1;
1260  return *this;
1261 }
1262 
1264 
1265 template <class T>
1266 inline
1267 EllVar<T>
1268 operator+
1269 ( const EllVar<T>& EllVar1 )
1270 {
1271  return EllVar1;
1272 }
1273 
1274 template <class T>
1275 inline
1276 EllVar<T>
1277 operator+
1278 ( const EllVar<T>& EllVar1 ,
1279  const EllVar<T>& EllVar2 )
1280 {
1281  // The left operand is not an ellipsoidal variables
1282  if( !EllVar1._EI ){
1283  if( EllVar1._is_constant ) return EllVar2 + EllVar1._const_val;
1284  return EllVar2 + EllVar1._Range;
1285  }
1286  // The right operand is not an ellipsoidal variables
1287  if( !EllVar2._EI ){
1288  if( EllVar2._is_constant ) return EllVar1 + EllVar2._const_val;
1289  return EllVar1 + EllVar2._Range;
1290  }
1291  // The operands correspond to different ellipsoids
1292  if( EllVar1._EI != EllVar2._EI )
1293  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::EIMG );
1294 
1295  EllImg<T>* EI = EllVar1._EI;
1296  long i = EI->_current_row;
1297  long k = EllVar1._RowInd;
1298  long l = EllVar2._RowInd;
1299  // Construct Evar3 to return (increases _current_row)
1300  EllVar<T> EllVar3( EI, i );
1301 #ifdef MC__ELLIMAGE_DEBUG
1302  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1303  EI->_dbugout << "+ starts: i= " << i <<" k= "<< k <<" l= "<< l <<std::endl;
1304  EI->_dbugout << "q \n" ;
1305  EI->_dbugout << EI->_q <<std::endl;
1306  EI->_dbugout << "Q \n" ;
1307  EI->_dbugout << EI->_Q <<std::endl;
1308 #endif
1309  // Update Centre
1310  EI->_q( i ) = EI->_q(k) + EI->_q(l);
1311 
1312  // Update matrix when the shape matrix has been initialised with a dependency map
1313  if( EI-> _depmap_flag ){
1314  // Update current row in the Shape matrix
1315  for ( long j = 0; j < i ; ++j )
1316  if( EI->_depmap.isListed(i,j) ) EI->_Q.put( i,j, EI->_Q(k,j) + EI->_Q(l,j) );
1317  // Update Diagonal element
1318  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) + 2.*(EI->_Q(l,k)) + EI->_Q(l,l) );
1319  }
1320 
1321  // No dependency map available
1322  else{
1323  // Update current row in the Shape matrix
1324  for ( long j = 0; j < i ; ++j )
1325  if( EI->_Q.isListed(k,j) || EI->_Q.isListed(l,j) ) EI->_Q.put( i,j, EI->_Q(k,j) + EI->_Q(l,j) );
1326  // Update Diagonal element
1327  EI->_Q.put( i,i, EI->_Q(k,k) + 2.*(EI->_Q(l,k)) + EI->_Q(l,l) );
1328  }
1329 
1330  // Save range of Variable
1331  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1332  EllVar3._range() = Range;
1333 #ifdef MC__ELLIMAGE_DEBUG
1334  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1335  EI->_dbugout << "+ ends: i= " << i <<" k= "<< k <<" l= "<< l <<std::endl;
1336  EI->_dbugout << "q \n" ;
1337  EI->_dbugout << EI->_q <<std::endl;
1338  EI->_dbugout << "Q \n" ;
1339  EI->_dbugout << EI->_Q <<std::endl;
1340 #endif
1341 
1342  return EllVar3;
1343 }
1344 
1345 template <class T>
1346 inline
1347 EllVar<T>
1348 operator+
1349 ( const EllVar<T>& EllVar1 ,
1350  const double DVal )
1351 {
1352  // Neither of the operands are ellipsoidal variables
1353  if( !EllVar1._EI ){
1354  if( EllVar1._is_constant ) return DVal + EllVar1._const_val;
1355  return DVal + EllVar1._Range;
1356  }
1357 
1358  EllImg<T>* EI = EllVar1._EI;
1359  long i = EI->_current_row;
1360  long k = EllVar1._RowInd;
1361  // Construct Evar3 to return (increases _current_row)
1362  EllVar<T> EllVar3( EI, i );
1363  // Update Centre
1364  EI->_q( i ) = EI->_q(k) + DVal;
1365  // Update matrix when the shape matrix has been initialised with a dependency map
1366  if( EI-> _depmap_flag )
1367  {
1368  // Update current row in the Shape matrix
1369  for ( long j = 0; j < i ; ++j )
1370  {
1371  if( EI->_depmap.isListed(i,j) ) EI->_Q.put(i,j, EI->_Q(k,j) );
1372  }
1373  // Update Diagonal element
1374  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) );
1375  }
1376  else // No dependency map available
1377  {
1378  // Update current row in the Shape matrix
1379  for ( long j = 0; j < i ; ++j )
1380  {
1381  if( EI->_Q.isListed(k,j) ) EI->_Q.put(i,j, EI->_Q(k,j) );
1382  }
1383  // Update Diagonal element
1384  EI->_Q.put( i,i, EI->_Q(k,k) );
1385  }
1386  // Save range of Variable
1387  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1388  EllVar3._range() = Range;
1389 
1390  return EllVar3;
1391  }
1392 
1393 template <class T>
1394 inline
1395 EllVar<T>
1396 operator+
1397 ( const double DVal,
1398  const EllVar<T>& EllVar1 )
1399 {
1400  return EllVar1 + DVal;
1401 }
1402 
1403 template <class T>
1404 inline
1405 EllVar<T>
1406 operator+
1407 ( const EllVar<T>& EllVar1 ,
1408  const T& IVal )
1409 {
1410  // Neither of the operands are ellipsoidal variables
1411  if( !EllVar1._EI ){
1412  if( EllVar1._is_constant ) return IVal + EllVar1._const_val;
1413  return IVal + EllVar1._Range;
1414  }
1415 
1416  EllImg<T>* EI = EllVar1._EI;
1417  long i = EI->_current_row;
1418  long k = EllVar1._RowInd;
1419  // Construct Evar3 to return (increases _current_row)
1420  EllVar<T> EllVar3( EI, i );
1421  // Update Centre
1422  EI->_q( i ) = EI->_q(k) + Op<T>::mid(IVal) ; // Offset by the midpoint of the interval
1423  // Update matrix when the shape matrix has been initialised with a dependency map
1424  if( EI-> _depmap_flag )
1425  {
1426  EI->_minksum( i , 0.5*Op<T>::diam(IVal) );
1427  }
1428  else // No dependency map available
1429  {
1430  EI->_minksum( i , 0.5*Op<T>::diam(IVal) );
1431  }
1432  // Save range of Variable
1433  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1434  EllVar3._range() = Range;
1435 
1436  return EllVar3;
1437 }
1438 
1439 template <class T>
1440 inline
1441 EllVar<T>
1442 operator+
1443 ( const T& IVal ,
1444  const EllVar<T>& EllVar1 )
1445 {
1446  return EllVar1 + IVal ;
1447 }
1448 
1449 template <class T>
1450 inline
1451 EllVar<T>
1452 operator-
1453 ( const EllVar<T>& EllVar1 )
1454 {
1455  // The operand is not an ellipsoidal variable
1456  if( !EllVar1._EI ){
1457  if( EllVar1._is_constant ) return -EllVar1._const_val;
1458  return -EllVar1._Range;
1459  }
1460 
1461  EllImg<T>* EI = EllVar1._EI;
1462  long i = EI->_current_row;
1463  long k = EllVar1._RowInd;
1464  // Construct Evar3 to return (increases _current_row)
1465  EllVar<T> EllVar3( EI, i );
1466  // Update Centre
1467  EI->_q( i ) = - EI->_q(k) ;
1468  // Update matrix when the shape matrix has been initialised with a dependency map
1469  if( EI-> _depmap_flag )
1470  {
1471  // Update current row in the Shape matrix
1472  for ( long j = 0; j < i ; ++j )
1473  {
1474  if( EI->_depmap.isListed(i,j) ) EI->_Q.put( i,j, - EI->_Q(k,j) );
1475  }
1476  // Update Diagonal element
1477  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) );
1478  }
1479  else // No dependency map available
1480  {
1481  // Update current row in the Shape matrix
1482  for ( long j = 0; j < i ; ++j )
1483  {
1484  if( EI->_Q.isListed(k,j) ) EI->_Q.put( i,j, - EI->_Q(k,j) );
1485  }
1486  // Update Diagonal element
1487  EI->_Q.put( i,i, EI->_Q(k,k) );
1488  }
1489  // Save range of Variable
1490  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1491  EllVar3._range() = Range;
1492 
1493  return EllVar3;
1494 }
1495 
1496 template <class T>
1497 inline
1498 EllVar<T>
1499 operator-
1500 ( const EllVar<T>& EllVar1 ,
1501  const EllVar<T>& EllVar2 )
1502 {
1503  if( EllVar1._EI == NULL && EllVar1._is_constant &&
1504  EllVar2._EI == NULL && EllVar2._is_constant ) // Both EllVar1 and EllVar2 are doubles
1505  {
1506  return EllVar1._const_val - EllVar2._const_val;
1507  }
1508  else if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
1509  {
1510  return EllVar1._const_val - EllVar2 ;
1511  }
1512  else if( EllVar2._EI == NULL && EllVar2._is_constant ) // EllVar2 is a double
1513  {
1514  return EllVar1 - EllVar2._const_val ;
1515  }
1516  else if( EllVar1._EI == NULL && ! EllVar1._is_constant &&
1517  EllVar2._EI == NULL && ! EllVar2._is_constant ) // Both EllVar1 and EllVar2 are intervals
1518  {
1519  return EllVar1._Range - EllVar2._Range; // Computes interval and calls constructor EllVar<T>( const T& )
1520  }
1521  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
1522  {
1523  return EllVar1._Range - EllVar2 ;
1524  }
1525  else if( EllVar2._EI == NULL && ! EllVar2._is_constant ) // EllVar2 is an interval
1526  {
1527  return EllVar1 + (-1.*EllVar2._Range);
1528  }
1529  else if( EllVar1._EI != EllVar2._EI ) // EllVar1 and EllVar2 are in different ellipsoids
1530  {
1531  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::EIMG );
1532  }
1533  else //EllVar1 and EllVar2 are 'common' EllVar<T>s
1534  {
1535  EllImg<T>* EI = EllVar1._EI;
1536  long i = EI->_current_row;
1537  long k = EllVar1._RowInd;
1538  long l = EllVar2._RowInd;
1539  // Construct Evar3 to return (increases _current_row)
1540  EllVar<T> EllVar3( EI, i );
1541  // Update Centre
1542  EI->_q( i ) = EI->_q(k) - EI->_q(l);
1543  // Update matrix when the shape matrix has been initialised with a dependency map
1544  if( EI-> _depmap_flag )
1545  {
1546  // Update current row in the Shape matrix
1547  for ( long j = 0; j < i ; ++j )
1548  {
1549  if( EI->_depmap.isListed(i,j) ) EI->_Q.put(i,j, EI->_Q(k,j) - EI->_Q(l,j) );
1550  }
1551  // Update Diagonal element
1552  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) - 2.*(EI->_Q(l,k)) + EI->_Q(l,l) );
1553  }
1554  else // No dependency map available
1555  {
1556  // Update current row in the Shape matrix
1557  for ( long j = 0; j < i ; ++j )
1558  {
1559  if( EI->_Q.isListed(k,j) || EI->_Q.isListed(l,j) ) EI->_Q.put(i,j, EI->_Q(k,j) - EI->_Q(l,j) );
1560  }
1561  // Update Diagonal element
1562  EI->_Q.put( i,i, EI->_Q(k,k) - 2.*(EI->_Q(l,k)) + EI->_Q(l,l) );
1563  }
1564  // Save range of Variable
1565  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1566  EllVar3._range() = Range;
1567 
1568  return EllVar3;
1569  }
1570 }
1571 
1572 template <class T>
1573 inline
1574 EllVar<T>
1575 operator-
1576 ( const EllVar<T>& EllVar1 ,
1577  const double DVal )
1578 {
1579  // Neither of the operands are ellipsoidal variables
1580  if( !EllVar1._EI ){
1581  if( EllVar1._is_constant ) return EllVar1._const_val - DVal;
1582  return EllVar1._Range - DVal;
1583  }
1584 
1585  EllImg<T>* EI = EllVar1._EI;
1586  long i = EI->_current_row;
1587  long k = EllVar1._RowInd;
1588  // Construct Evar3 to return (increases _current_row)
1589  EllVar<T> EllVar3( EI, i );
1590  // Update Centre
1591  EI->_q( i ) = EI->_q(k) - DVal;
1592  // Update matrix when the shape matrix has been initialised with a dependency map
1593  if( EI-> _depmap_flag )
1594  {
1595  // Update current row in the Shape matrix
1596  for ( long j = 0; j < i ; ++j )
1597  {
1598  if( EI->_depmap.isListed(i,j) ) EI->_Q.put(i,j, EI->_Q(k,j) );
1599  }
1600  // Update Diagonal element
1601  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) );
1602  }
1603  else // No dependency map available
1604  {
1605  // Update current row in the Shape matrix
1606  for ( long j = 0; j < i ; ++j )
1607  {
1608  if( EI->_Q.isListed(k,j) ) EI->_Q.put(i,j, EI->_Q(k,j) );
1609  }
1610  // Update Diagonal element
1611  EI->_Q.put( i,i, EI->_Q(k,k) );
1612  }
1613  // Save range of Variable
1614  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1615  EllVar3._range() = Range;
1616 
1617  return EllVar3;
1618 }
1619 
1620 template <class T>
1621 inline
1622 EllVar<T>
1623 operator-
1624 ( const double DVal,
1625  const EllVar<T>& EllVar1 )
1626 {
1627  // Neither of the operands are ellipsoidal variables
1628  if( !EllVar1._EI ){
1629  if( EllVar1._is_constant ) return DVal - EllVar1._const_val;
1630  return DVal - EllVar1._Range;
1631  }
1632 
1633  EllImg<T>* EI = EllVar1._EI;
1634  long i = EI->_current_row;
1635  long k = EllVar1._RowInd;
1636  // Construct Evar3 to return (increases _current_row)
1637  EllVar<T> EllVar3( EI, i );
1638  // Update Centre
1639  EI->_q( i ) = DVal - EI->_q(k) ;
1640  // Update matrix when the shape matrix has been initialised with a dependency map
1641  if( EI-> _depmap_flag )
1642  {
1643  // Update current row in the Shape matrix
1644  for ( long j = 0; j < i ; ++j )
1645  {
1646  if( EI->_depmap.isListed(i,j) ) EI->_Q.put(i,j, - EI->_Q(k,j) );
1647  }
1648  // Update Diagonal element
1649  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q(k,k) );
1650  }
1651  else // No dependency map available
1652  {
1653  // Update current row in the Shape matrix
1654  for ( long j = 0; j < i ; ++j )
1655  {
1656  if( EI->_Q.isListed(k,j) ) EI->_Q.put(i,j, - EI->_Q(k,j) );
1657  }
1658  // Update Diagonal element
1659  EI->_Q.put( i,i, EI->_Q(k,k) );
1660  }
1661  // Save range of Variable
1662  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1663  EllVar3._range() = Range;
1664 
1665  return EllVar3;
1666 }
1667 
1668 template <class T>
1669 inline
1670 EllVar<T>
1671 operator-
1672 ( const EllVar<T>& EllVar1 ,
1673  const T& IVal )
1674 {
1675  // Neither of the operands are ellipsoidal variables
1676  if( !EllVar1._EI ){
1677  if( EllVar1._is_constant ) return EllVar1._const_val - IVal;
1678  return EllVar1._Range - IVal;
1679  }
1680 
1681  EllImg<T>* EI = EllVar1._EI;
1682  long i = EI->_current_row;
1683  long k = EllVar1._RowInd;
1684 
1685  // Construct Evar3 to return (increases _current_row)
1686  EllVar<T> EllVar3( EI, i );
1687  // Update Centre
1688  EI->_q( i ) = EI->_q(k) + Op<T>::mid( -1.*IVal ) ; // shift by the center of the interval // Update matrix when the shape matrixhas been initialised with a dependency map
1689  if( EI-> _depmap_flag )
1690  {
1691  EI->_minksum( i , 0.5*Op<T>::diam( -1.*IVal ) ) ;
1692  }
1693  else // No dependency map available
1694  {
1695  EI->_minksum( i , 0.5*Op<T>::diam( -1.*IVal ) ) ;
1696  }
1697  // Save range of Variable
1698  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1699  EllVar3._range() = Range;
1700 
1701  return EllVar3;
1702 }
1703 
1704 template <class T>
1705 inline
1706 EllVar<T>
1707 operator-
1708 ( const T& IVal,
1709  const EllVar<T>& EllVar1 )
1710 {
1711  // Neither of the operands are ellipsoidal variables
1712  if( !EllVar1._EI ){
1713  if( EllVar1._is_constant ) return IVal - EllVar1._const_val;
1714  return IVal - EllVar1._Range;
1715  }
1716 
1717  EllImg<T>* EI = EllVar1._EI;
1718  long i = EI->_current_row;
1719  long k = EllVar1._RowInd;
1720 
1721  // Construct Evar3 to return (increases _current_row)
1722  EllVar<T> EllVar3( EI, i );
1723  // Update Centre
1724  EI->_q( i ) = Op<T>::mid( IVal ) + EI->_q(k) ; // shift by the center of the interval
1725  // Update matrix when the shape matrixhas been initialised with a dependency map
1726  if( EI-> _depmap_flag )
1727  {
1728  EI->_minksum( i , 0.5*Op<T>::diam( IVal ) ) ;
1729  }
1730  else // No dependency map available
1731  {
1732  EI->_minksum( i , 0.5*Op<T>::diam( IVal ) ) ;
1733  }
1734  // Save range of Variable
1735  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
1736  EllVar3._range() = Range;
1737 
1738  return EllVar3;
1739 }
1740 
1741 template <class T>
1742 inline
1743 EllVar<T>
1744 operator*
1745 ( const EllVar<T>& EllVar0 ,
1746  const EllVar<T>& EllVar1 )
1747 {
1748  if( EllVar0._EI == NULL && EllVar0._is_constant &&
1749  EllVar1._EI == NULL && EllVar1._is_constant ) // Both EllVar0 and EllVar1 are doubles
1750  {
1751  return EllVar0._const_val * EllVar1._const_val;
1752  }
1753  else if( EllVar0._EI == NULL && EllVar0._is_constant ) // EllVar0 is a double
1754  {
1755  return EllVar0._const_val * EllVar1 ;
1756  }
1757  else if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
1758  {
1759  return EllVar0 * EllVar1._const_val ;
1760  }
1761  else if( EllVar0._EI == NULL && ! EllVar0._is_constant &&
1762  EllVar1._EI == NULL && ! EllVar1._is_constant ) // Both EllVar0 and EllVar1 are intervals
1763  {
1764  return EllVar0._Range * EllVar1._Range; // Computes interval and calls constructor EllVar<T>( const T& )
1765  }
1766  else if( EllVar0._EI == NULL && ! EllVar0._is_constant ) // EllVar0 is an interval
1767  {
1768  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF);
1769  }
1770  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
1771  {
1772  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF );
1773  }
1774  else if( EllVar0._EI != EllVar1._EI ) // EllVar1 and EllVar2 are in different ellipsoids
1775  {
1776  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::EIMG );
1777  }
1778  else //EllVar1 and EllVar2 are 'common' EllVar<T>s
1779  {
1780  EllImg<T>* EI = EllVar0._EI;
1781  long i;
1782  long k = EllVar0._RowInd;
1783  long l = EllVar1._RowInd;
1784  T domain_EllVar0 = EI->_q( k ) + std::sqrt( EI->_Q(k,k) ) *T(-1.,1);
1785  T domain_EllVar1 = EI->_q( l ) + std::sqrt( EI->_Q(l,l) ) *T(-1.,1);
1786  if( EI->_ip == -1 )
1787  {
1788  EI->_ip = EI->_current_row ; // The product block starts at the current_row
1789  if( ! EI->_depmap_flag && EI->_ip + 7 > EI->_Q.n ) // If there are not at least 7 more rows
1790  { // to accomodate the product block
1791  EI->_Q.stretch( 7 ) ; // Stretch to make space for the product block
1792  EI->_q.stretch( 7 ) ; // in every row, updates are performed until i (i,i) is the diagonal element
1793  for( long j = EI->_current_row ; j < EI->_current_row + 6 ; ++j ) EI->_q(j) = 0.;
1794  }
1795  i = EI->_current_row + 6 ; // Index for product result is the last row created
1796  }
1797  else i = EI->_current_row;
1798  long ii = EI->_ip ; // internal row counter for product block
1799  long kk = ii ; // internal counter for argument in univariate operations;
1800  long ll ; // internal counter for 2nd argument
1801  double result;
1802  // Construct EllVar
1803  EllVar<T> EllVar3( EI, i , i+1 );
1863  #ifdef MC__ELLIMAGE_DEBUG
1864  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1865  EI->_dbugout << "Product starts: i= " << i <<" k= "<< k << " l= " << l <<std::endl;
1866  EI->_dbugout << "Product block starts: " << EI->_ip << std::endl;
1867  EI->_dbugout << " _q =\n" ;
1868  EI->_dbugout << EI->_q << std::endl;
1869  EI->_dbugout << " _Q =\n" ;
1870  EI->_dbugout << EI->_Q << std::endl;
1871  #endif
1872  // compute v2 = ( v0 + v1 )
1873 // if( EI->_depmap_flag )
1874 // {
1875 // for( long j = 0 ; j <= i ; ++j )
1876 // {
1877 // if( EI->_depmap.isListed(ii,j) ) EI->_Q.put( ii,j, EI->_Q( k,j ) + EI->_Q( l,j ) );
1878 // }
1879 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii, EI->_Q( k,k ) + 2.* EI->_Q( l,k ) + EI->_Q( l,l ) );
1880 // }
1881 // else
1882 // {
1883  for( long j = 0 ; j <= i ; ++j )
1884  {
1885  if( EI->_Q.isListed(k,j) || EI->_Q.isListed(l,j) )
1886  {
1887  result = EI->_Q( k,j ) + EI->_Q( l,j );
1888  if( ! isequal(result,0.) ) EI->_Q.put( ii,j, result );
1889  }
1890  }
1891  result = EI->_Q( k,k ) + 2.* EI->_Q( l,k ) + EI->_Q( l,l ); // Diagonal
1892  if( ! isequal(result,0.) ) EI->_Q.put( ii,ii, result );
1893 // }
1894  EI->_q( ii ) = EI->_q( k ) + EI->_q( l );
1895  ii += 1; // increase row counter for product block
1896  #ifdef MC__ELLIMAGE_DEBUG
1897  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1898  EI->_dbugout << " After v2 : \n" ;
1899  EI->_dbugout << " _q =\n" ;
1900  EI->_dbugout << EI->_q << std::endl;
1901  EI->_dbugout << " _Q =\n" ;
1902  EI->_dbugout << EI->_Q << std::endl;
1903  #endif
1904  // compute v3 = ( v0 - v1 )
1905 // if( EI->_depmap_flag )
1906 // {
1907 // for( long j = 0 ; j <= i ; ++j ) if( EI->_depmap.isListed(ii,j) ) EI->_Q.put( ii,j, EI->_Q( k,j ) - EI->_Q( l,j ) );
1908 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii, EI->_Q( k,k ) - 2.* EI->_Q( l,k ) + EI->_Q( l,l ) );
1909 // }
1910 // else
1911 // {
1912  for( long j = 0 ; j <= i ; ++j )
1913  {
1914  if( EI->_Q.isListed(k,j) || EI->_Q.isListed(l,j) )
1915  {
1916  double result = EI->_Q( k,j ) - EI->_Q( l,j ) ;
1917  if( ! isequal(result,0.) ) EI->_Q.put( ii,j, result );
1918  }
1919  }
1920  result = EI->_Q( k,k ) - 2.* EI->_Q( l,k ) + EI->_Q( l,l ); //Diagonal
1921  if( ! isequal(result,0.) ) EI->_Q.put( ii,ii,result );
1922 // }
1923  EI->_q( ii ) = EI->_q( k ) - EI->_q( l );
1924  T domainv3 = EI->_q( ii ) + std::sqrt( EI->_Q( ii , ii ) ) * T(-1.,1.); // Compute domain for v5 before Msum (in v4)
1925  ii += 1; // increase row counter for product block
1926  #ifdef MC__ELLIMAGE_DEBUG
1927  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1928  EI->_dbugout << " After v3 : \n" ;
1929  EI->_dbugout << " _q =\n" ;
1930  EI->_dbugout << EI->_q << std::endl;
1931  EI->_dbugout << " _Q =\n" ;
1932  EI->_dbugout << EI->_Q << std::endl;
1933  #endif
1934  // compute v4 = ( v2 )^2
1935  T domain = EI->_q( kk ) + std::sqrt( EI->_Q(kk,kk) )*T(-1.,1.);
1936  double c_0, c_1, eta;
1937  std::tie( c_0, c_1, eta ) = EI->_linearize_sqr( domain );
1938 // if( EI->_depmap_flag )
1939 // {
1940 // for( long j = 0 ; j <= i ; ++j ) if( EI->_depmap.isListed(ii,j) )EI->_Q.put( ii,j, c_1*EI->_Q( kk ,j ) );
1941 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii, std::pow(c_1,2)*EI->_Q(kk,kk) );
1942 // }
1943 // else
1944 // {
1945  for( long j = 0 ; j <= i ; ++j )
1946  {
1947  if( EI->_Q.isListed( kk ,j ) )
1948  {
1949  result = c_1*EI->_Q( kk ,j );
1950  if(! isequal(result,0.) ) EI->_Q.put( ii,j, result );
1951  }
1952  }
1953  result = std::pow(c_1,2)*EI->_Q(kk,kk);
1954  if(! isequal(result,0.) ) EI->_Q.put( ii,ii, result );
1955 // }
1956  EI->_q( ii ) = c_0;
1957  EI->_minksum( ii, eta );
1958  ii += 1; // increase row counter for product block
1959  kk += 1; // increase counter for argument
1960  #ifdef MC__ELLIMAGE_DEBUG
1961  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1962  EI->_dbugout << " After v4 : \n" ;
1963  EI->_dbugout << " _q =\n" ;
1964  EI->_dbugout << EI->_q << std::endl;
1965  EI->_dbugout << " _Q =\n" ;
1966  EI->_dbugout << EI->_Q << std::endl;
1967  #endif
1968  // compute v5 = ( v3 )^2
1969  std::tie( c_0, c_1, eta ) = EI->_linearize_sqr( domainv3 );
1970 // if( EI->_depmap_flag )
1971 // {
1972 // for( long j = 0 ; j <= i ; ++j ) if( EI->_depmap.isListed(ii,j) ) EI->_Q.put( ii,j, c_1*EI->_Q( kk ,j ) );
1973 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii, std::pow(c_1,2)*EI->_Q(kk,kk) );
1974 // }
1975 // else
1976 // {
1977  for( long j = 0 ; j <= i ; ++j )
1978  {
1979  if( EI->_Q.isListed( kk ,j ) )
1980  {
1981  result = c_1*EI->_Q( kk ,j );
1982  if(! isequal(result,0.) ) EI->_Q.put( ii,j, result );
1983  }
1984  }
1985  result = std::pow(c_1,2)*EI->_Q(kk,kk);
1986  if(! isequal(result,0.) ) EI->_Q.put( ii,ii, result );
1987 // }
1988  EI->_q( ii ) = c_0;
1989  EI->_minksum( ii, eta );
1990  ii += 1; // increase row counter for product block
1991  kk += 1; // increase counter for argument
1992  #ifdef MC__ELLIMAGE_DEBUG
1993  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
1994  EI->_dbugout << " After v5 : \n" ;
1995  EI->_dbugout << " _q =\n" ;
1996  EI->_dbugout << EI->_q << std::endl;
1997  EI->_dbugout << " _Q =\n" ;
1998  EI->_dbugout << EI->_Q << std::endl;
1999  #endif
2000  // compute v6 = (1/4)*( v4 )
2001 // if( EI->_depmap_flag )
2002 // {
2003 // for( long j = 0 ; j <= i ; ++j ) if( EI->_depmap.isListed(ii,j) ) EI->_Q.put( ii,j, (1./4.)*EI->_Q( kk ,j ) );
2004 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii,(1./16.)*EI->_Q(kk,kk) );
2005 // }
2006 // else
2007 // {
2008  for( long j = 0 ; j <= i ; ++j )
2009  {
2010  if( EI->_Q.isListed( kk,j ) )
2011  {
2012  result = (1./4.)*EI->_Q( kk ,j ) ;
2013  if( ! isequal(result,0.) ) EI->_Q.put( ii,j, result );
2014  }
2015  }
2016  result = (1./16.)*EI->_Q(kk,kk);
2017  if( ! isequal(result,0.) ) EI->_Q.put( ii,ii,result );
2018 // }
2019  EI->_q( ii ) = (1./4.)*EI->_q( kk );
2020  ii += 1; // increase row counter for product block
2021  kk += 1; // increase counter for argument
2022  #ifdef MC__ELLIMAGE_DEBUG
2023  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2024  EI->_dbugout << " After v6 : \n" ;
2025  EI->_dbugout << " _q =\n" ;
2026  EI->_dbugout << EI->_q << std::endl;
2027  EI->_dbugout << " _Q =\n" ;
2028  EI->_dbugout << EI->_Q << std::endl;
2029  #endif
2030  // compute v7 = (1/4)*( v5 )
2031 // if( EI->_depmap_flag )
2032 // {
2033 // for( long j = 0 ; j <= i ; ++j ) if( EI->_depmap.isListed(ii,j) ) EI->_Q.put( ii,j, (1./4.)*EI->_Q( kk ,j ) );
2034 // if( EI->_depmap.isListed(ii,ii) ) EI->_Q.put( ii,ii,(1./16.)*EI->_Q(kk,kk) );
2035 // }
2036 // else
2037 // {
2038  for( long j = 0 ; j <= i ; ++j )
2039  {
2040  if( EI->_Q.isListed( kk ,j ) )
2041  {
2042  result = (1./4.)*EI->_Q( kk ,j );
2043  if( ! isequal( result, 0.) ) EI->_Q.put( ii,j, result );
2044  }
2045  }
2046  result = (1./16.)*EI->_Q(kk,kk);
2047  if( ! isequal( result, 0.) ) EI->_Q.put( ii,ii, result );
2048 // }
2049  EI->_q( ii ) = (1./4.)*EI->_q( kk );
2050  kk += 1;
2051  ll = kk+1;
2052  #ifdef MC__ELLIMAGE_DEBUG
2053  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2054  EI->_dbugout << " After v7 : \n" ;
2055  EI->_dbugout << " _q =\n" ;
2056  EI->_dbugout << EI->_q << std::endl;
2057  EI->_dbugout << " _Q =\n" ;
2058  EI->_dbugout << EI->_Q << std::endl;
2059  #endif
2060  // compute v8 = ( v6 - v7 )
2061  if( EI->_depmap_flag )
2062  {
2063  for( long j = 0 ; j < i ; ++j ) if( EI->_depmap.isListed(i,j) ) EI->_Q.put( i,j, EI->_Q( kk,j ) - EI->_Q( ll,j ) );
2064  if( EI->_depmap.isListed(i,i) ) EI->_Q.put( i,i, EI->_Q( kk,kk ) - 2.* EI->_Q( ll,kk ) + EI->_Q( ll,ll ) );
2065  }
2066  else
2067  {
2068  for( long j = 0 ; j < i ; ++j )
2069  {
2070  if( EI->_Q.isListed( kk,j ) || EI->_Q.isListed( ll,j ) )
2071  {
2072  result = EI->_Q( kk,j ) - EI->_Q( ll,j ) ;
2073  if( ! isequal(result,0.) ) EI->_Q.put( i,j, result );
2074  }
2075  }
2076  result = EI->_Q( kk,kk ) - 2.* EI->_Q( ll,kk ) + EI->_Q( ll,ll );
2077  if( ! isequal(result,0.) ) EI->_Q.put( i,i, result );
2078  }
2079  EI->_q( i ) = EI->_q( kk ) - EI->_q( ll );
2080  #ifdef MC__ELLIMAGE_DEBUG
2081  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2082  EI->_dbugout << " After v8 : \n" ;
2083  EI->_dbugout << " _q =\n" ;
2084  EI->_dbugout << EI->_q << std::endl;
2085  EI->_dbugout << " _Q =\n" ;
2086  EI->_dbugout << EI->_Q << std::endl;
2087  #endif
2088  //cleanup the product block
2089  for (long ipp= EI->_ip ; ipp <= ii ; ++ipp )
2090  {
2091  for (long jp= 0 ; jp <= i ; ++jp )
2092  {
2093  EI -> _Q.del( ipp , jp ) ;
2094 
2095  }
2096  EI->_Q.del( ipp,ipp );
2097  }
2098 // if( EI->_depmap_flag )
2099 // {
2100 // for (long ipp= EI->_ip ; ipp <= ii ; ++ipp )
2101 // {
2102 // for (long jp= 0 ; jp <= i ; ++jp )
2103 // {
2104 // EI -> _depmap.del( ipp , jp ) ;
2105 //
2106 // }
2107 // EI->_depmap.del( ipp,ipp );
2108 // }
2109 // }
2110 // std::cout << " DEPMAP After : \n";
2111 // std::cout << EI->_depmap << std::endl;
2112 
2113  //save bound the product
2114  T Range ;
2115  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), domain_EllVar0 * domain_EllVar1 );
2116  EllVar3._range() = Range;
2117 #ifdef MC__ELLIMAGE_DEBUG
2118  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2119  EI->_dbugout << "Product ends: i= " << i <<" k= "<< k << " l= " << l <<std::endl;
2120  EI->_dbugout << "Product block starts: " << EI->_ip << std::endl;
2121  EI->_dbugout << " _q =\n" ;
2122  EI->_dbugout << EI->_q << std::endl;
2123  EI->_dbugout << " _Q =\n" ;
2124  EI->_dbugout << EI->_Q << std::endl;
2125 #endif
2126 
2127  return EllVar3;
2128  }
2129 }
2130 
2131 template <class T>
2132 inline
2133 EllVar<T>
2134 operator*
2135 ( const EllVar<T>& EllVar1 ,
2136  const double DVal )
2137 {
2138  // Neither of the operands are ellipsoidal variables
2139  if( !EllVar1._EI ){
2140  if( EllVar1._is_constant ) return EllVar1._const_val * DVal;
2141  return EllVar1._Range * DVal;
2142  }
2143 
2144  EllImg<T>* EI = EllVar1._EI;
2145  long i = EI->_current_row;
2146  long k = EllVar1._RowInd;
2147  // Construct Evar3 to return (increases _current_row)
2148  EllVar<T> EllVar3( EI, i );
2149  // Update Centre
2150  EI->_q( i ) = EI->_q(k) * DVal;
2151  // Update matrix when the shape matrix has been initialised with a dependency map
2152  if( EI-> _depmap_flag )
2153  {
2154  // Update current row in the Shape matrix
2155  for ( long j = 0; j < i ; ++j )
2156  {
2157  if( EI->_depmap.isListed(i,j) ) EI->_Q(i,j) = DVal * EI->_Q(k,j) ;
2158  }
2159  // Update Diagonal element
2160  EI->_Q(i,i) = DVal*DVal*EI->_Q(k,k) ;
2161  }
2162  else // No dependency map available
2163  {
2164  // Update current row in the Shape matrix
2165  for ( long j = 0; j < i ; ++j )
2166  {
2167  EI->_Q.put(i, j, DVal*EI->_Q(k,j) );
2168  }
2169  // Update Diagonal element
2170  EI->_Q.put( i, i, DVal*DVal*EI->_Q(k,k) );
2171  }
2172  // Save range of Variable
2173  T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
2174  EllVar3._range() = Range;
2175 
2176  return EllVar3;
2177 }
2178 
2179 template <class T>
2180 inline
2181 EllVar<T>
2182 operator*
2183 ( const double DVal,
2184  const EllVar<T>& EllVar1 )
2185 {
2186  return EllVar1 * DVal;
2187 }
2188 
2189 template <class T>
2190 inline
2191 EllVar<T>
2192 operator*
2193 ( const EllVar<T>& EllVar1 ,
2194  const T& IVal )
2195 {
2196  // Neither of the operands are ellipsoidal variables
2197  if( !EllVar1._EI ){
2198  if( EllVar1._is_constant ) return IVal * EllVar1._const_val;
2199  return IVal * EllVar1._Range;
2200  }
2201 
2202  EllImg<T>* EI = EllVar1._EI;
2203  long i = EI->_current_row;
2204  long k = EllVar1._RowInd;
2205  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF );
2206 // // Construct Evar3 to return (increases _current_row)
2207 // EllVar<T> EllVar3( EI, i );
2208 // // Update Centre
2209 // EI->_q( i ) = EI->_q(k) * DVal;
2210 // // Update matrix when the shape matrix has been initialised with a dependency map
2211 // if( EI-> _depmap_flag )
2212 // {
2213 
2214 // }
2215 // else // No dependency map available
2216 // {
2217 
2218 // }
2219 // // Save range of Variable
2220 // T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
2221 // EllVar3._range() = Range;
2222 //
2223 // return EllVar3;
2224 }
2225 
2226 template <class T>
2227 inline
2228 EllVar<T>
2229 operator*
2230 ( const T& IVal ,
2231  const EllVar<T>& EllVar1 )
2232 {
2233  // Neither of the operands are ellipsoidal variables
2234  if( !EllVar1._EI ){
2235  if( EllVar1._is_constant ) return IVal * EllVar1._const_val;
2236  return IVal * EllVar1._Range;
2237  }
2238 
2239  EllImg<T>* EI = EllVar1._EI;
2240  long i = EI->_current_row;
2241  long k = EllVar1._RowInd;
2242  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF );
2243 // // Construct Evar3 to return (increases _current_row)
2244 // EllVar<T> EllVar3( EI, i );
2245 // // Update Centre
2246 // EI->_q( i ) = EI->_q(k) * DVal;
2247 // // Update matrix when the shape matrix has been initialised with a dependency map
2248 // if( EI-> _depmap_flag )
2249 // {
2250 
2251 // }
2252 // else // No dependency map available
2253 // {
2254 
2255 // }
2256 // // Save range of Variable
2257 // T Range = EI->_q(i) + std::sqrt(EI->_Q(i,i))*T(-1.,1.);
2258 // EllVar3._range() = Range;
2259 //
2260 // return EllVar3;
2261 }
2262 
2263 template <class T>
2264 inline
2265 EllVar<T>
2266 operator/
2267 ( const EllVar<T>& EllVar1,
2268  const EllVar<T>& EllVar2 )
2269 {
2270  if( EllVar1._EI == NULL && EllVar1._is_constant &&
2271  EllVar2._EI == NULL && EllVar2._is_constant ) // Both EllVar1 and EllVar2 are doubles
2272  {
2273  return EllVar1._const_val / EllVar2._const_val;
2274  }
2275  else if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2276  {
2277  return EllVar1._const_val * inv(EllVar2) ;
2278  }
2279  else if( EllVar2._EI == NULL && EllVar2._is_constant ) // EllVar2 is a double
2280  {
2281  return (1./EllVar2._const_val) * EllVar1 ;
2282  }
2283  else if( EllVar1._EI == NULL && ! EllVar1._is_constant &&
2284  EllVar2._EI == NULL && ! EllVar2._is_constant ) // Both EllVar1 and EllVar2 are intervals
2285  {
2286  return EllVar1._Range / EllVar2._Range; // Computes interval and calls constructor EllVar<T>( const T& )
2287  }
2288  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2289  {
2290  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF);
2291  }
2292  else if( EllVar2._EI == NULL && ! EllVar2._is_constant ) // EllVar2 is an interval
2293  {
2294  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF );
2295  }
2296  else if( EllVar1._EI != EllVar2._EI ) // EllVar1 and EllVar2 are in different ellipsoids
2297  {
2298  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::EIMG );
2299  }
2300  else //EllVar1 and EllVar2 are 'common' EllVar<T>s
2301  {
2302  return EllVar1 * inv( EllVar2 );
2303  }
2304 }
2305 
2306 template <class T>
2307 inline
2308 EllVar<T>
2309 operator/
2310 ( const EllVar<T>& EllVar1,
2311  const double DVal )
2312 {
2313  if( isequal( DVal, 0. ) )
2314  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::DIV );
2315  return ( 1./DVal ) * EllVar1;
2316 }
2317 
2318 template <class T>
2319 inline
2320 EllVar<T>
2321 operator/
2322 ( const double DVal,
2323  const EllVar<T>& EllVar1 )
2324 {
2325  return DVal * inv( EllVar1 );
2326 }
2327 
2328 template <class T>
2329 inline
2330 EllVar<T>
2331 operator/
2332 ( const EllVar<T>& EllVar1,
2333  const T& IVal )
2334 {
2335  return ( 1./IVal ) * EllVar1;
2336 }
2337 
2338 template <class T>
2339 inline
2340 EllVar<T>
2341 operator/
2342 ( const T& IVal ,
2343  const EllVar<T>& EllVar1 )
2344 {
2345  return IVal * inv( EllVar1 );
2346 }
2347 
2348 template <class T>
2349 inline
2350 EllVar<T>
2351 inv
2352 ( const EllVar<T>& EllVar1 )
2353 {
2354  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2355  {
2356  return 1./( EllVar1._const_val ) ;
2357  }
2358  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2359  {
2360  return inv( EllVar1._Range ) ;
2361  }
2362  else //EllVar1 is a 'common' EllVar<T>s
2363  {
2364  EllImg<T>* EI = EllVar1._EI;
2365  long i = EI->_current_row;
2366  long k = EllVar1._RowInd;
2367 
2368  // Construct Evar3 to return (increases _current_row)
2369  EllVar<T> EllVar3( EI, i );
2370  // bound the argument EllVar1 in the current ellipsoid
2371  T domain = EllVar1._range();
2372  if( Op<T>::l(domain) <= 0. && Op<T>::u(domain) >= 0. )
2373  {
2374  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::INV );
2375  }
2376  // Compute linear approximation of inv( m + r*x ) with x \in [-1,1] using Chebyshev models
2377  double c_0, c_1, eta;
2378  if( EI->options.CHEBUSE )
2379  {
2380  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( inv , domain );
2381  }
2382  else // Compute linear approximation of inv( m + r*x ) with x \in [-1,1] using minimax linearisation
2383  {
2384  double m = Op<T>::mid( domain );
2385  double r = 0.5 * Op<T>::diam( domain );
2386  double c_sec=0., x_tan=0., c_tan=0.;
2387  c_sec = m/(std::pow(m,2) - std::pow(r,2));
2388  c_1 = r/(std::pow(r,2) - std::pow(m,2));
2389  if ( m > 0 ) x_tan = (std::sqrt(-r/c_1)-m)/r;
2390  else x_tan = 1./((std::sqrt(-r/c_1)-m)/r);
2391  c_tan = 1./(m+r*x_tan)-c_1*x_tan;
2392  eta = (c_sec - c_tan)/2.;
2393  c_0 = c_sec - eta;
2394  c_1 = c_1/r;
2395  }
2396  // Update matrix
2397  EI->_univupdate( i , k , c_0 , c_1 , eta );
2398  // Save range of Variable
2399  T Range ;
2400  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), 1./(domain) );
2401  EllVar3._range() = Range;
2402 
2403  #ifdef MC__ELLIMAGE_DEBUG
2404  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2405  EI->_dbugout << "inv ends: i= " << i <<" k= "<< k <<std::endl;
2406  EI->_dbugout << "Range, q , Q\n" ;
2407  for( long i = 0 ; i < EI->_Q.n ; ++i )
2408  {
2409  EI->_dbugout << "\t" << EI->_q(i) << "\t" << EI->_Q.row(i);
2410  }
2411  EI->_dbugout << std::endl;
2412  #endif
2413  return EllVar3;
2414  }
2415 }
2416 
2417 template <class T>
2418 inline
2419 EllVar<T>
2420 exp
2421 ( const EllVar<T>& EllVar1 )
2422 {
2423  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2424  {
2425  return std::exp( EllVar1._const_val ) ;
2426  }
2427  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2428  {
2429  return exp( EllVar1._Range ) ;
2430  }
2431  else //EllVar1 is a 'common' EllVar<T>s
2432  {
2433  EllImg<T>* EI = EllVar1._EI;
2434  long i = EI->_current_row;
2435  long k = EllVar1._RowInd;
2436  // Construct Evar3 to return (increases _current_row)
2437  EllVar<T> EllVar3( EI, i );
2438  // bound the argument EllVar1 in the current ellipsoid
2439  T domain = EllVar1._range();
2440  // Compute linear approximation of exp( m + r*x ) with x \in [-1,1] using Chebyshev models
2441  double c_0, c_1, eta;
2442  if( EI->options.CHEBUSE )
2443  {
2444  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( exp , domain );
2445  }
2446  else // Compute linear approximation of exp( m + r*x ) with x \in [-1,1] using minimax linearisation
2447  {
2448  double m = Op<T>::mid( domain );
2449  double r = 0.5 * Op<T>::diam( domain );
2450  double c_sec=0., x_tan=0., c_tan=0.;
2451  c_sec = 0.5*(std::exp(m-r)+std::exp(m+r));
2452  c_1 = 0.5*(std::exp(m+r)-std::exp(m-r));
2453  x_tan = (std::log(c_1/r) - m)/r;
2454  c_tan = std::exp(m+r*x_tan)-c_1*x_tan;
2455  eta = (c_sec - c_tan)/2.0;
2456  c_0 = c_sec - eta;
2457  c_1 = c_1/r;
2458  }
2459  // Update matrix
2460  EI->_univupdate( i , k , c_0 , c_1 , eta );
2461  // Save range of Variable
2462  T Range ;
2463  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), exp(domain) );
2464  EllVar3._range() = Range;
2465 
2466  return EllVar3;
2467  }
2468 }
2469 
2470 template <class T>
2471 inline
2472 EllVar<T>
2473 log
2474 ( const EllVar<T>& EllVar1 )
2475 {
2476  // EllVar1 is double
2477  if( !EllVar1._EI && EllVar1._is_constant )
2478  return std::log( EllVar1._const_val );
2479 
2480  // EllVar1 is interval
2481  else if( !EllVar1._EI && !EllVar1._is_constant )
2482  return log( EllVar1._Range );
2483 
2484  // Check feasibility of operation
2485  T domain = EllVar1._range();
2486  if( Op<T>::l(domain) <= 0. )
2487  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::LOG );
2488 
2489  EllImg<T>* EI = EllVar1._EI;
2490  long i = EI->_current_row;
2491  long k = EllVar1._RowInd;
2492 #ifdef MC__ELLIMAGE_DEBUG
2493  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2494  EI->_dbugout << "log starts: i= " << i <<" k= "<< k << std::endl;
2495  EI->_dbugout << "q \n" << EI->_q << std::endl;
2496  EI->_dbugout << "Q \n" << EI->_Q << std::endl;
2497 #endif
2498 
2499  // Construct Evar3 to return (increases _current_row)
2500  EllVar<T> EllVar3( EI, i );
2501  double c_0, c_1, eta;
2502 
2503  // Compute linear approximation of log( m + r*x ) with x \in [-1,1] using Chebyshev models
2504  if( EI->options.CHEBUSE )
2505  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( log, domain );
2506 
2507  // Compute linear approximation of log( m + r*x ) with x \in [-1,1] using minimax linearisation
2508  else{
2509  double m = Op<T>::mid( domain );
2510  double r = 0.5 * Op<T>::diam( domain );
2511  double c_sec=0., x_tan=0., c_tan=0.;
2512  c_sec = (1./2.)*(std::log(m-r)+std::log(m+r));
2513  c_1 = (1./2.)*(std::log(m+r)-std::log(m-r));
2514  x_tan = (1./c_1)-(m/r);
2515  c_tan = std::log(m+r*x_tan)-c_1*x_tan;
2516  eta = std::fabs((c_sec - c_tan)/2.);
2517  c_0 = c_sec + eta;
2518  c_1 = c_1/r;
2519  }
2520 
2521  // Update matrix and variable
2522  EI->_univupdate( i, k, c_0, c_1, eta );
2523  Op<T>::inter( EllVar3._range(), EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1.), log(domain) );
2524 #ifdef MC__ELLIMAGE_DEBUG
2525  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2526  EI->_dbugout << "log ends: i= " << i <<" k= "<< k <<std::endl;
2527  EI->_dbugout << "q \n" ;
2528  EI->_dbugout << EI->_q <<std::endl;
2529  EI->_dbugout << "Q \n" ;
2530  EI->_dbugout << EI->_Q <<std::endl;
2531 #endif
2532 
2533  return EllVar3;
2534 }
2535 
2536 template <class T>
2537 inline
2538 EllVar<T>
2539 sqrt
2540 ( const EllVar<T>& EllVar1 )
2541 {
2542  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2543  {
2544  return std::sqrt( EllVar1._const_val ) ;
2545  }
2546  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2547  {
2548  return sqrt( EllVar1._Range ) ;
2549  }
2550  else //EllVar1 is a 'common' EllVar<T>s
2551  {
2552  EllImg<T>* EI = EllVar1._EI;
2553  long i = EI->_current_row;
2554  long k = EllVar1._RowInd;
2555 
2556  // Construct Evar3 to return (increases _current_row)
2557  EllVar<T> EllVar3( EI, i );
2558  // bound the argument EllVar1 in the current ellipsoid
2559  T domain = EllVar1._range();
2560  if( Op<T>::l(domain) < 0. )
2561  {
2562  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::SQRT );
2563  }
2564  // Compute linear approximation of sqrt( m + r*x ) with x \in [-1,1] using Chebyshev models
2565  double c_0, c_1, eta;
2566  if( EI->options.CHEBUSE )
2567  {
2568  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( sqrt , domain );
2569  }
2570  else // Compute linear approximation of sqrt( m + r*x ) with x \in [-1,1] using minimax linearisation
2571  {
2572  double m = Op<T>::mid( domain );
2573  double r = 0.5 * Op<T>::diam( domain );
2574  double c_sec=0., x_tan=0., c_tan=0.;
2575  c_sec = (0.5)*(std::sqrt(m-r)+std::sqrt(m+r));
2576  c_1 = (0.5)*(std::sqrt(m+r)-std::sqrt(m-r));
2577  x_tan = (std::pow(r,2) - 4.0*std::pow((c_1),2)*m )/(4.0*std::pow((c_1),2)*r);
2578  c_tan = std::sqrt(m+r*x_tan)-c_1*x_tan;
2579  eta = std::fabs((c_sec - c_tan)/2.0);
2580  c_0 = c_sec + eta;
2581  c_1 = c_1 / r ;
2582  }
2583  // Update matrix
2584  EI->_univupdate( i , k , c_0 , c_1 , eta );
2585  // Save range of Variable
2586  T Range ;
2587  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), sqrt(domain) );
2588  EllVar3._range() = Range;
2589 
2590  return EllVar3;
2591  }
2592 }
2593 
2594 template <class T>
2595 inline
2596 EllVar<T>
2597 sqr
2598 ( const EllVar<T>& EllVar1 )
2599 {
2600  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2601  {
2602  return std::pow( EllVar1._const_val ,2 ) ;
2603  }
2604  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2605  {
2606  return sqr( EllVar1._Range ) ;
2607  }
2608  else //EllVar1 is a 'common' EllVar<T>s
2609  {
2610  EllImg<T>* EI = EllVar1._EI;
2611  long i = EI->_current_row;
2612  long k = EllVar1._RowInd;
2613  // Construct Evar3 to return (increases _current_row)
2614  EllVar<T> EllVar3( EI, i );
2615  #ifdef MC__ELLIMAGE_DEBUG
2616  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2617  EI->_dbugout << "sqr starts: i= " << i <<" k= "<< k <<std::endl;
2618  EI->_dbugout << "q \n" ;
2619  EI->_dbugout << EI->_q <<std::endl;
2620  EI->_dbugout << "Q \n" ;
2621  EI->_dbugout << EI->_Q <<std::endl;
2622  #endif
2623  // bound the argument EllVar1 in the current ellipsoid
2624  T domain = EllVar1._range();
2625  // Compute linear approximation of sqr( m + r*x ) with x \in [-1,1] using Chebyshev models
2626  double c_0, c_1, eta;
2627  if( EI->options.CHEBUSE )
2628  {
2629  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( sqr , domain );
2630  }
2631  else // Compute linear approximation of sqr( m + r*x ) with x \in [-1,1] using minimax linearisation
2632  {
2633  double m = Op<T>::mid( domain );
2634  double r = 0.5 * Op<T>::diam( domain );
2635  double c_sec=0., x_tan=0., c_tan=0.;
2636  c_sec = std::pow(m,2)+std::pow(r,2);
2637  c_1 = 2.0*m*r;
2638  x_tan = (c_1-2.0*m*r)/(2.0*std::pow(r,2));
2639  c_tan = std::pow((m+r*x_tan),2)-c_1*x_tan;
2640  eta = (c_sec - c_tan)/2.0;
2641  c_0 = c_sec - eta;
2642  c_1 = c_1 / r;
2643  }
2644  // Update matrix
2645  EI->_univupdate( i , k , c_0 , c_1 , eta );
2646  // Save range of Variable
2647  T Range ;
2648  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), sqr(domain) );
2649  EllVar3._range() = Range;
2650  #ifdef MC__ELLIMAGE_DEBUG
2651  EI->_dbugout << std::scientific << std::setprecision(3) << std::right;
2652  EI->_dbugout << "sqr ends: i= " << i <<" k= "<< k <<std::endl;
2653  EI->_dbugout << "q \n" ;
2654  EI->_dbugout << EI->_q <<std::endl;
2655  EI->_dbugout << "Q \n" ;
2656  EI->_dbugout << EI->_Q <<std::endl;
2657  #endif
2658  return EllVar3;
2659  }
2660 }
2661 
2662 template <class T>
2663 inline
2664 EllVar<T>
2665 pow
2666 ( const EllVar<T>& EllVar1 , const int n )
2667 {
2668  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2669  {
2670  return std::pow( EllVar1._const_val , n ) ;
2671  }
2672  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2673  {
2674  return pow( EllVar1._Range , n ) ;
2675  }
2676  else //EllVar1 is a 'common' EllVar<T>s
2677  {
2678  EllImg<T>* EI = EllVar1._EI;
2679  long i = EI->_current_row;
2680  long k = EllVar1._RowInd;
2681  // Construct Evar3 to return (increases _current_row)
2682  EllVar<T> EllVar3( EI, i );
2683  // bound the argument EllVar1 in the current ellipsoid
2684  T domain = EllVar1._range();
2685  // Compute linear approximation of pow( m + r*x , n ) with x \in [-1,1] using Chebyshev models
2686  double c_0, c_1, eta;
2687  if( EI->options.CHEBUSE )
2688  {
2689  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( n , domain );
2690  }
2691  else // Compute linear approximation of log( m + r*x , n ) with x \in [-1,1] using minimax linearisation
2692  {
2693  double m = Op<T>::mid( domain );
2694  double r = 0.5 * Op<T>::diam( domain );
2695  double c_sec=0., x_tan=0., c_tan=0.;
2696  double x_tanL, x_tanU, c_tanL, c_tanU;
2697  if( n % 2 == 0 ) // even power
2698  {
2699  c_sec = (1./2.)*(std::pow((m+r),n)+std::pow((m-r),n));
2700  c_1 = (1./2.)*(std::pow((m+r),n)-std::pow((m-r),n));
2701  x_tan = (std::pow((c_1/(n*r)),1./(n-1))-m)/r;
2702  c_tan = std::pow((m+r*x_tan),n)-c_1*x_tan;
2703  eta = (c_sec - c_tan)/2.;
2704  c_0 = c_sec - eta;
2705  }
2706  else
2707  {
2708  if(Op<T>::l( domain ) >= 0 || Op<T>::u( domain ) <= 0)
2709  {
2710  c_1 = (1./2.)*(std::pow((m+r),n)-std::pow((m-r),n));
2711  c_sec = (1./2.)*(std::pow((m+r),n)+std::pow((m-r),n));
2712  x_tan = (sign(m)*std::pow((c_1/(n*r)),1./(n-1))-m)/r;
2713  c_tan = std::pow((m+r*x_tan),n)-c_1*x_tan;
2714  eta = (c_sec - c_tan)/2.;
2715  c_0 = c_sec - eta;
2716  }
2717  else
2718  {
2719  c_1 = (1./2.)*(std::pow((m+r),n)-std::pow((m-r),n));
2720  x_tanU = (std::pow((c_1/(n*r)),1./(n-1))-m)/r;
2721  x_tanL = (-1.0*std::pow((c_1/(n*r)),1./(n-1))-m)/r;
2722  c_tanU = std::pow((m+r*x_tanU),n)-c_1*x_tanU;
2723  c_tanL = std::pow((m+r*x_tanL),n)-c_1*x_tanL;
2724  eta = std::fabs((c_tanL - c_tanU)/2.);
2725  c_0 = std::fabs(c_tanL - eta);
2726  }
2727  }
2728  c_1 = c_1 / r;
2729  }
2730  // Update matrix
2731  EI->_univupdate( i , k , c_0 , c_1 , eta );
2732  // Save range of Variable
2733  T Range ;
2734  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), pow(domain,n) );
2735  EllVar3._range() = Range;
2736 
2737  return EllVar3;
2738  }
2739 }
2740 
2741 template <class T>
2742 inline
2743 EllVar<T>
2744 cos
2745 ( const EllVar<T>& EllVar1 )
2746 {
2747  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2748  {
2749  return std::cos( EllVar1._const_val ) ;
2750  }
2751  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2752  {
2753  return cos( EllVar1._Range ) ;
2754  }
2755  else //EllVar1 is a 'common' EllVar<T>s
2756  {
2757  EllImg<T>* EI = EllVar1._EI;
2758  long i = EI->_current_row;
2759  long k = EllVar1._RowInd;
2760  // Construct Evar3 to return (increases _current_row)
2761  EllVar<T> EllVar3( EI, i );
2762  // bound the argument EllVar1 in the current ellipsoid
2763  T domain = EllVar1._range();
2764  // Compute linear approximation of cos( m + r*x ) with x \in [-1,1] using Chebyshev models
2765  double c_0, c_1, eta;
2766  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( cos , domain );
2767  // Update matrix
2768  EI->_univupdate( i , k , c_0 , c_1 , eta );
2769  // Save range of Variable
2770  T Range ;
2771  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), cos(domain) );
2772  EllVar3._range() = Range;
2773 
2774  return EllVar3;
2775  }
2776 }
2777 
2778 template <class T>
2779 inline
2780 EllVar<T>
2781 sin
2782 ( const EllVar<T>& EllVar1 )
2783 {
2784  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2785  {
2786  return std::sin( EllVar1._const_val ) ;
2787  }
2788  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2789  {
2790  return sin( EllVar1._Range ) ;
2791  }
2792  else //EllVar1 is a 'common' EllVar<T>s
2793  {
2794  EllImg<T>* EI = EllVar1._EI;
2795  long i = EI->_current_row;
2796  long k = EllVar1._RowInd;
2797  // Construct Evar3 to return (increases _current_row)
2798  EllVar<T> EllVar3( EI, i );
2799  // bound the argument EllVar1 in the current ellipsoid
2800  T domain = EllVar1._range();
2801  // Compute linear approximation of sin( m + r*x ) with x \in [-1,1] using Chebyshev models
2802  double c_0, c_1, eta;
2803  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( sin , domain );
2804  // Update matrix
2805  EI->_univupdate( i , k , c_0 , c_1 , eta );
2806  // Save range of Variable
2807  T Range ;
2808  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), sin(domain) );
2809  EllVar3._range() = Range;
2810 
2811  return EllVar3;
2812  }
2813 }
2814 
2815 template <class T>
2816 inline
2817 EllVar<T>
2818 tan
2819 ( const EllVar<T>& EllVar1 )
2820 {
2821  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2822  {
2823  return std::tan( EllVar1._const_val ) ;
2824  }
2825  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2826  {
2827  return tan( EllVar1._Range ) ;
2828  }
2829  else //EllVar1 is a 'common' EllVar<T>s
2830  {
2831  EllImg<T>* EI = EllVar1._EI;
2832  long i = EI->_current_row;
2833  long k = EllVar1._RowInd;
2834  // Construct Evar3 to return (increases _current_row)
2835  EllVar<T> EllVar3( EI, i );
2836  // bound the argument EllVar1 in the current ellipsoid
2837  T domain = EllVar1._range();
2838  if( Op<T>::l(cos(domain)) <= 0. && Op<T>::u(cos(domain)) >= 0. )
2839  {
2840  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::TAN );
2841  }
2842  // Compute linear approximation of tan( m + r*x ) with x \in [-1,1] using Chebyshev models
2843  double c_0, c_1, eta;
2844  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( tan , domain );
2845  // Update matrix
2846  EI->_univupdate( i , k , c_0 , c_1 , eta );
2847  // Save range of Variable
2848  T Range ;
2849  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), tan(domain) );
2850  EllVar3._range() = Range;
2851 
2852  return EllVar3;
2853  }
2854 }
2855 
2856 template <class T>
2857 inline
2858 EllVar<T>
2859 acos
2860 ( const EllVar<T>& EllVar1 )
2861 {
2862  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2863  {
2864  return std::acos( EllVar1._const_val ) ;
2865  }
2866  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2867  {
2868  return acos( EllVar1._Range ) ;
2869  }
2870  else //EllVar1 is a 'common' EllVar<T>s
2871  {
2872  EllImg<T>* EI = EllVar1._EI;
2873  long i = EI->_current_row;
2874  long k = EllVar1._RowInd;
2875  // Construct Evar3 to return (increases _current_row)
2876  EllVar<T> EllVar3( EI, i );
2877  // bound the argument EllVar1 in the current ellipsoid
2878  T domain = EllVar1._range();
2879  if( Op<T>::l(domain) < -1. && Op<T>::u(domain) > 1. )
2880  {
2881  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::ACOS );
2882  }
2883  // Compute linear approximation of acos( m + r*x ) with x \in [-1,1] using Chebyshev models
2884  double c_0, c_1, eta;
2885  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( acos , domain );
2886  // Update matrix
2887  EI->_univupdate( i , k , c_0 , c_1 , eta );
2888  // Save range of Variable
2889  T Range ;
2890  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), acos(domain) );
2891  EllVar3._range() = Range;
2892 
2893  return EllVar3;
2894  }
2895 }
2896 
2897 template <class T>
2898 inline
2899 EllVar<T>
2900 asin
2901 ( const EllVar<T>& EllVar1 )
2902 {
2903  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2904  {
2905  return std::asin( EllVar1._const_val ) ;
2906  }
2907  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2908  {
2909  return asin( EllVar1._Range ) ;
2910  }
2911  else //EllVar1 is a 'common' EllVar<T>s
2912  {
2913  EllImg<T>* EI = EllVar1._EI;
2914  long i = EI->_current_row;
2915  long k = EllVar1._RowInd;
2916  // Construct Evar3 to return (increases _current_row)
2917  EllVar<T> EllVar3( EI, i );
2918  // bound the argument EllVar1 in the current ellipsoid
2919  T domain = EllVar1._range();
2920  if( Op<T>::l(domain) < -1. && Op<T>::u(domain) > 1. )
2921  {
2922  throw typename EllImg<T>::Exceptions( EllImg<T>::Exceptions::ACOS );
2923  }
2924  // Compute linear approximation of asin( m + r*x ) with x \in [-1,1] using Chebyshev models
2925  double c_0, c_1, eta;
2926  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( asin , domain );
2927  // Update matrix
2928  EI->_univupdate( i , k , c_0 , c_1 , eta );
2929  // Save range of Variable
2930  T Range ;
2931  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), asin(domain) );
2932  EllVar3._range() = Range;
2933 
2934  return EllVar3;
2935  }
2936 }
2937 
2938 template <class T>
2939 inline
2940 EllVar<T>
2941 atan
2942 ( const EllVar<T>& EllVar1 )
2943 {
2944  if( EllVar1._EI == NULL && EllVar1._is_constant ) // EllVar1 is a double
2945  {
2946  return std::atan( EllVar1._const_val ) ;
2947  }
2948  else if( EllVar1._EI == NULL && ! EllVar1._is_constant ) // EllVar1 is an interval
2949  {
2950  return atan( EllVar1._Range ) ;
2951  }
2952  else //EllVar1 is a 'common' EllVar<T>s
2953  {
2954  EllImg<T>* EI = EllVar1._EI;
2955  long i = EI->_current_row;
2956  long k = EllVar1._RowInd;
2957  // Construct Evar3 to return (increases _current_row)
2958  EllVar<T> EllVar3( EI, i );
2959  // bound the argument EllVar1 in the current ellipsoid
2960  T domain = EllVar1._range();
2961  // Compute linear approximation of acos( m + r*x ) with x \in [-1,1] using Chebyshev models
2962  double c_0, c_1, eta;
2963  std::tie( c_0, c_1, eta ) = EI->_cmodel_linear( atan , domain );
2964  // Update matrix
2965  EI->_univupdate( i , k , c_0 , c_1 , eta );
2966  // Save range of Variable
2967  T Range ;
2968  Op<T>::inter( Range, EI->_q(i)+std::sqrt(EI->_Q( i,i ))*T(-1.,1. ), atan(domain) );
2969  EllVar3._range() = Range;
2970 
2971  return EllVar3;
2972  }
2973 }
2974 
2975 template <typename T> inline std::ostream&
2976 operator<<
2977 ( std::ostream&out, const EllVar<T>&EllVar )
2978 {
2979  return out << std::scientific << EllVar.range() << "(index: " << EllVar.index() << ")";
2980 }
2981 
2982 template <class T>
2983 inline std::ostream&
2984 operator<<
2985 ( std::ostream&out, const EllImg<T>&E )
2986 {
2987  return out << static_cast<const Ellipsoid&>( E );
2988 }
2989 
2990 } // namespace mc
2991 
2992 namespace mc
2993 {
2994 
2996 template <> template<typename T> struct Op< mc::EllVar<T> >
2997 {
2998  typedef mc::EllVar<T> EV;
2999  static EV point( const double c ) { return EV( c ); }
3000  static EV zeroone() { return EV( mc::Op<T>::zeroone() ); } // ??
3001  static void I(EV& x, const EV&y) { x = y; } // ??
3002  static double l(const EV& x) { return mc::Op<T>::l(x.range()); }
3003  static double u(const EV& x) { return mc::Op<T>::u(x.range()); }
3004  static double abs (const EV& x) { return mc::Op<T>::abs(x.range()); }
3005  static double mid (const EV& x) { return mc::Op<T>::mid(x.range()); }
3006  static double diam(const EV& x) { return mc::Op<T>::diam(x.range()); }
3007  static EV inv (const EV& x) { return mc::inv(x); }
3008  static EV sqr (const EV& x) { return mc::sqr(x); }
3009  static EV sqrt(const EV& x) { return mc::sqrt(x); }
3010  static EV log (const EV& x) { return mc::log(x); }
3011  static EV xlog(const EV& x) { return x*mc::log(x); }
3012  static EV fabs(const EV& x) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3013  static EV exp (const EV& x) { return mc::exp(x); }
3014  static EV sin (const EV& x) { return mc::sin(x); }
3015  static EV cos (const EV& x) { return mc::cos(x); }
3016  static EV tan (const EV& x) { return mc::tan(x); }
3017  static EV asin(const EV& x) { return mc::asin(x); }
3018  static EV acos(const EV& x) { return mc::acos(x); }
3019  static EV atan(const EV& x) { return mc::atan(x); }
3020  static EV arh (const EV& x, const double k) { return mc::exp(-k/x); }
3021  static EV erf (const EV& x) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3022  static EV erfc(const EV& x) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3023  static EV fstep(const EV& x) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3024  static EV bstep(const EV& x) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3025  static EV hull(const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3026  static EV min (const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3027  static EV max (const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3028  template <typename X, typename Y> static EV pow(const X& x, const Y& y) { return mc::pow(x,y); }
3029  static EV monomial (const unsigned int n, const EV* x, const int* k) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3030  static bool inter(EV& xIy, const EV& x, const EV& y) { return false; }
3031  static bool eq(const EV& x, const EV& y) { return x.env() == y.env() && x.index() == y.index() && x.range() == y.range(); }
3032  static bool ne(const EV& x, const EV& y) { return !eq( x, y ); }
3033  static bool lt(const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3034  static bool le(const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3035  static bool gt(const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3036  static bool ge(const EV& x, const EV& y) { throw typename mc::EllImg<T>::Exceptions( EllImg<T>::Exceptions::UNDEF ); }
3037 };
3038 
3039 } // namespace mc
3040 
3041 #endif
double r(const unsigned int i) const
Return maximum radius for for index .
Definition: ellipsoid.hpp:568
const CPPL::dsymatrix & Q() const
Return shape matrix of ellipsoid.
Definition: ellipsoid.hpp:415
EllVar< T > & set(EllImg< T > &EI, const unsigned i, const T &Irange)
set variable in ellipsoidal image environment and tailored range
Definition: ellimage.hpp:626
EllImg< T > & set(const EllImg< T > &E)
Set an ellipsoid identical to E
Definition: ellimage.hpp:464
Structure containing the options for EllImg.
Definition: ellimage.hpp:387
long index() const
get pointer to row index
Definition: ellimage.hpp:636
C++ class for ellipsoidal arithmetic - Ellipsoidal image propagation.
Definition: ellimage.hpp:288
int ierr()
Error flag.
Definition: ellimage.hpp:365
CPPL::dcovector c_lift()
Returns the centre of the lifted Ellipsoid.
Definition: ellimage.hpp:434
const CPPL::dcovector & c() const
Return center of ellipsoid.
Definition: ellipsoid.hpp:396
C++ class for ellipsoidal arithmetic - Ellipsoidal image environment.
Definition: ellimage.hpp:301
std::ostream & output(std::ostream &os=std::cout)
Output lifted ellipsoid to os
Definition: ellimage.hpp:805
EllVar< T > & set(EllImg< T > &EI, const unsigned i)
set variable the ellipsoidal image environment
Definition: ellimage.hpp:623
Square-root operation with negative numbers in domain.
Definition: ellimage.hpp:355
unsigned CHEBORDER
Order of the Chebyshev model used for the linearisation of univariate functions – Used only if CHEBUS...
Definition: ellimage.hpp:398
Ellipsoid options.
Definition: ellipsoid.hpp:130
EllVar()
Default constructor.
Definition: ellimage.hpp:1021
CPPL::dssmatrix Q_lift()
Returns the shape matrix of the lifted Ellipsoid.
Definition: ellimage.hpp:430
C++ class for the computation of Chebyshev models of factorable function - Chebyshev model environmen...
Definition: cmodel.hpp:218
Tangent operation with zero in domain of cosine, tan(x) = sin(x)/cos(x)
Definition: ellimage.hpp:356
T range() const
get variable range
Definition: ellimage.hpp:630
Failed to construct ellipsoidal variable EllVar.
Definition: ellimage.hpp:358
EllImg()
Default constructor.
Definition: ellimage.hpp:675
Feature not yet implemented in mc::EllImg.
Definition: ellimage.hpp:360
Options()
Constructor of mc::EllImg<>::Options.
Definition: ellimage.hpp:390
Exceptions of mc::EllImg.
Definition: ellimage.hpp:348
virtual ~EllVar()
Destructor.
Definition: ellimage.hpp:620
EllImg< T > * image() const
get pointer to ellipsoidal image
Definition: ellimage.hpp:633
C++ class for ellipsoidal calculus.
Definition: ellipsoid.hpp:37
Inverse operation with zero in domain.
Definition: ellimage.hpp:353
Sine/Cosine inverse operation with domain outside [-1,1].
Definition: ellimage.hpp:357
TYPE
Enumeration type for EllImg exception handling.
Definition: ellimage.hpp:351
Ellipsoid & set(const CPPL::dsymatrix &Q=CPPL::dsymatrix(), const CPPL::dcovector &c=CPPL::dcovector())
Define ellipsoid of dimension with center and shape matrix .
Definition: ellipsoid.hpp:267
EllImg< T > & reset()
Reset ellipsoidal image to underlying defining ellipsoid.
Definition: ellimage.hpp:486
std::string what()
Error description.
Definition: ellimage.hpp:367
bool CHEBUSE
Whether to use Chebyshev models to obtain the linearisation of univariate functions.
Definition: ellimage.hpp:396
Operation between ellipsoidal variables EllVar linked to different ellipsoidal images EllImg...
Definition: ellimage.hpp:359
unsigned int n() const
Return dimension of ellipsoid.
Definition: ellipsoid.hpp:391
virtual ~EllImg()
Destructor.
Definition: ellimage.hpp:734
Log operation with non-positive numbers in domain.
Definition: ellimage.hpp:354
long PREALLOC
Sets number of rows to preallocate in the shape matrix and center vector.
Definition: ellimage.hpp:394
Exceptions(TYPE ierr)
Constructor for error ierr
Definition: ellimage.hpp:363
Division by zero scalar.
Definition: ellimage.hpp:352
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