MC++
mccormick.h
00001 // Copyright (C) 2005-2012 Benoit Chachuat (b.chachuat@imperial.ac.uk)
00002 // All rights reserved.
00003 
00004 // This code is provided "as is", without any warranty of any kind,
00005 // either expressed or implied, including but not limited to, any implied
00006 // warranty of merchantibility or fitness for any purpose. In no event
00007 // will any party who distributed the code be liable for damages or for
00008 // any claim(s) by any other party, including but not limited to, any
00009 // lost profits, lost monies, lost data or data rendered inaccurate,
00010 // losses sustained by third parties, or any other special, incidental or
00011 // consequential damages arising out of the use or inability to use the
00012 // program, even if the possibility of such damages has been advised
00013 // against. The entire risk as to the quality, the performance, and the
00014 // fitness of the program for any particular purpose lies with the party
00015 // using the code.
00016 
00017 // This code, and any derivative of this code, may not be used in a
00018 // commercial package without the prior explicit written permission of
00019 // the authors. Verbatim copies of this code may be made and distributed
00020 // in any medium, provided that this copyright notice is not removed or
00021 // altered in any way. No fees may be charged for distribution of the
00022 // codes, other than a fee to cover the cost of the media and a
00023 // reasonable handling fee.
00024 
00025 // ***************************************************************
00026 // ANY USE OF THIS CODE CONSTITUTES ACCEPTANCE OF THE TERMS OF THE
00027 //                         COPYRIGHT NOTICE
00028 // ***************************************************************
00029 
00193 #ifndef MC__MCCORMICK_H
00194 #define MC__MCCORMICK_H
00195 
00196 #include <iostream>
00197 #include <iomanip>
00198 #include <stdarg.h>
00199 #include <cassert>
00200 #include "mcfunc.h"
00201 #include "mcop.h"
00202 
00203 namespace mc
00204 {
00213 template <typename T>
00214 class McCormick
00216 {
00217   // friends of class McCormick for constructor overloading
00218   template <typename U> friend class McCormick;
00219 
00220   // friends of class McCormick for operator overloading
00221   template <typename U> friend McCormick<U> operator+
00222     ( const McCormick<U>& );
00223   template <typename U> friend McCormick<U> operator+
00224     ( const McCormick<U>&, const McCormick<U>& );
00225   template <typename U> friend McCormick<U> operator+
00226     ( const double, const McCormick<U>& );
00227   template <typename U> friend McCormick<U> operator+
00228     ( const McCormick<U>&, const double );
00229   template <typename U> friend McCormick<U> operator-
00230     ( const McCormick<U>& );
00231   template <typename U> friend McCormick<U> operator-
00232     ( const McCormick<U>&, const McCormick<U>& );
00233   template <typename U> friend McCormick<U> operator-
00234     ( const double, const McCormick<U>& );
00235   template <typename U> friend McCormick<U> operator-
00236     ( const McCormick<U>&, const double );
00237   template <typename U> friend McCormick<U> operator*
00238     ( const McCormick<U>&, const McCormick<U>& );
00239   template <typename U> friend McCormick<U> operator*
00240     ( const double, const McCormick<U>& );
00241   template <typename U> friend McCormick<U> operator*
00242     ( const McCormick<U>&, const double );
00243   template <typename U> friend McCormick<U> operator/
00244     ( const McCormick<U>&, const McCormick<U>& );
00245   template <typename U> friend McCormick<U> operator/
00246     ( const double, const McCormick<U>& );
00247   template <typename U> friend McCormick<U> operator/
00248     ( const McCormick<U>&, const double );
00249   template <typename U> friend std::ostream& operator<<
00250     ( std::ostream&, const McCormick<U>& );
00251   template <typename U> friend bool operator==
00252     ( const McCormick<U>&, const McCormick<U>& );
00253   template <typename U> friend bool operator!=
00254     ( const McCormick<U>&, const McCormick<U>& );
00255   template <typename U> friend bool operator<=
00256     ( const McCormick<U>&, const McCormick<U>& );
00257   template <typename U> friend bool operator>=
00258     ( const McCormick<U>&, const McCormick<U>& );
00259   template <typename U> friend bool operator<
00260     ( const McCormick<U>&, const McCormick<U>& );
00261   template <typename U> friend bool operator>
00262     ( const McCormick<U>&, const McCormick<U>& );
00263 
00264   // friends of class McCormick for function overloading
00265   template <typename U> friend McCormick<U> inv
00266     ( const McCormick<U>& );
00267   template <typename U> friend McCormick<U> sqr
00268     ( const McCormick<U>& );
00269   template <typename U> friend McCormick<U> exp
00270     ( const McCormick<U>& );
00271   template <typename U> friend McCormick<U> log
00272     ( const McCormick<U>& );
00273   template <typename U> friend McCormick<U> cos
00274     ( const McCormick<U>& );
00275   template <typename U> friend McCormick<U> sin
00276     ( const McCormick<U>& );
00277   template <typename U> friend McCormick<U> tan
00278     ( const McCormick<U>& );
00279   template <typename U> friend McCormick<U> acos
00280     ( const McCormick<U>& );
00281   template <typename U> friend McCormick<U> asin
00282     ( const McCormick<U>& );
00283   template <typename U> friend McCormick<U> atan
00284     ( const McCormick<U>& );
00285   template <typename U> friend McCormick<U> fabs
00286     ( const McCormick<U>& );
00287   template <typename U> friend McCormick<U> sqrt
00288     ( const McCormick<U>& );
00289   template <typename U> friend McCormick<U> xlog
00290     ( const McCormick<U>& );
00291   template <typename U> friend McCormick<U> arh
00292     ( const McCormick<U>&, const double );
00293   template <typename U> friend McCormick<U> erf
00294     ( const McCormick<U>& );
00295   template <typename U> friend McCormick<U> erfc
00296     ( const McCormick<U>& );
00297   template <typename U> friend McCormick<U> fstep
00298     ( const McCormick<U>& );
00299   template <typename U> friend McCormick<U> bstep
00300     ( const McCormick<U>& );
00301   template <typename U> friend McCormick<U> pow
00302     ( const McCormick<U>&, const int );
00303   template <typename U> friend McCormick<U> pow
00304     ( const McCormick<U>&, const double );
00305   template <typename U> friend McCormick<U> pow
00306     ( const double, const McCormick<U>& );
00307   template <typename U> friend McCormick<U> pow
00308     ( const McCormick<U>&, const McCormick<U>& );
00309   template <typename U> friend McCormick<U> monomial
00310     ( const unsigned int, const McCormick<U>*, const int* );
00311   template <typename U> friend McCormick<U> min
00312     ( const McCormick<U>&, const McCormick<U>& );
00313   template <typename U> friend McCormick<U> max
00314     ( const McCormick<U>&, const McCormick<U>& );
00315   template <typename U> friend McCormick<U> min
00316     ( const unsigned int, const McCormick<U>* );
00317   template <typename U> friend McCormick<U> max
00318     ( const unsigned int, const McCormick<U>* );
00319   template <typename U> friend McCormick<U> ltcond
00320     ( const McCormick<U>&, const McCormick<U>&, const McCormick<U>& );
00321   template <typename U> friend McCormick<U> ltcond
00322     ( const U&, const McCormick<U>&, const McCormick<U>& );
00323   template <typename U> friend McCormick<U> gtcond
00324     ( const McCormick<U>&, const McCormick<U>&, const McCormick<U>& );
00325   template <typename U> friend McCormick<U> gtcond
00326     ( const U&, const McCormick<U>&, const McCormick<U>& );
00327   template <typename U> friend bool inter
00328     ( McCormick<U>&, const McCormick<U>&, const McCormick<U>& );
00329   template <typename U> friend McCormick<U> cut
00330     ( const McCormick<U>& );
00331 
00332 public:
00333 
00334   // other operator overloadings
00335   McCormick<T>& operator=
00336     ( const McCormick<T>& );
00337   McCormick<T>& operator=
00338     ( const T& );
00339   McCormick<T>& operator=
00340     ( const double );
00341   McCormick<T>& operator+=
00342     ( const McCormick<T>& );
00343   McCormick<T>& operator+=
00344     ( const double );
00345   McCormick<T>& operator-=
00346     ( const McCormick<T>& );
00347   McCormick<T>& operator-=
00348     ( const double );
00349   McCormick<T>& operator*=
00350     ( const McCormick<T>& );
00351   McCormick<T>& operator*=
00352     ( const double );
00353   McCormick<T>& operator/=
00354     ( const McCormick<T>& );
00355   McCormick<T>& operator/=
00356     ( const double );
00357 
00361 
00362   static struct Options
00363   {
00365     Options():
00366       NEWTON_USE(true), NEWTON_MAXIT(100), NEWTON_TOL(1e-10), MVCOMP_USE(false),
00367       MVCOMP_TOL(1e1*machprec())
00368       {}
00370     bool NEWTON_USE;
00372     unsigned int NEWTON_MAXIT;
00374     double NEWTON_TOL;
00376     bool MVCOMP_USE;
00378     double MVCOMP_TOL;
00379   } options;
00380 
00382   class Exceptions
00383   {
00384   public:
00386     enum TYPE{
00387       DIV=1,   
00388       INV,  
00389       LOG,  
00390       SQRT, 
00391       ASIN, 
00392       NEWTON,  
00393       MULTSUB, 
00394       SUB=-1,  
00395       UNDEF=-2    
00396     };
00398     Exceptions( TYPE ierr ) : _ierr( ierr ){}
00400     int ierr(){ return _ierr; }
00401 
00402   private:
00403     TYPE _ierr;
00404   };
00405 
00407   McCormick():
00408     _nsub(0), _cvsub(0), _ccsub(0), _const(true)
00409     {}
00411   McCormick
00412     ( const double c ):
00413     _nsub(0), _cv(c), _cc(c), _cvsub(0), _ccsub(0), _const(true)
00414     {
00415       Op<T>::I(_I,c);
00416     }
00418   McCormick
00419     ( const T&I ):
00420     _nsub(0), _cvsub(0), _ccsub(0), _const(true)
00421     {
00422       Op<T>::I(_I,I);
00423       _cv = Op<T>::l(I); _cc = Op<T>::u(I);
00424     }
00426   McCormick
00427     ( const T&I, const double c ):
00428     _nsub(0), _cv(c), _cc(c), _cvsub(0), _ccsub(0), _const(false)
00429     {
00430       Op<T>::I(_I,I);
00431     }
00433   McCormick
00434     ( const T&I, const double cv, const double cc ):
00435     _nsub(0), _cv(cv), _cc(cc), _cvsub(0), _ccsub(0), _const(false)
00436     {
00437       Op<T>::I(_I,I); cut();
00438     }
00440   McCormick
00441     ( const McCormick<T>&MC ):
00442     _nsub(MC._nsub), _cv(MC._cv), _cc(MC._cc),
00443     _cvsub(_nsub>0?new double[_nsub]:0), _ccsub(_nsub>0?new double[_nsub]:0),
00444     _const(MC._const)
00445     {
00446       Op<T>::I(_I,MC._I);
00447       for ( unsigned int ip=0; ip<_nsub; ip++ ){
00448         _cvsub[ip] = MC._cvsub[ip];
00449         _ccsub[ip] = MC._ccsub[ip];
00450       }
00451     }
00453   template <typename U> McCormick
00454     ( const McCormick<U>&MC ):
00455     _nsub(MC._nsub), _cv(MC._cv), _cc(MC._cc),
00456     _cvsub(_nsub>0?new double[_nsub]:0), _ccsub(_nsub>0?new double[_nsub]:0),
00457     _const(MC._const)
00458     {
00459       Op<T>::I(_I,MC._I);
00460       for ( unsigned int ip=0; ip<_nsub; ip++ ){
00461         _cvsub[ip] = MC._cvsub[ip];
00462         _ccsub[ip] = MC._ccsub[ip];
00463       }
00464     }
00465 
00467   ~McCormick()
00468     {
00469       delete [] _cvsub;
00470       delete [] _ccsub;
00471     }
00472 
00474   unsigned int& nsub()
00475     {
00476       return _nsub;
00477     }
00478   const unsigned int nsub() const
00479     {
00480       return _nsub;
00481     }
00483   T& I()
00484     {
00485       return _I;
00486     }
00487   const T& I() const
00488     {
00489       return _I;
00490     }
00492   const double l() const
00493     {
00494       return Op<T>::l(_I);
00495     }
00497   const double u() const
00498     {
00499       return Op<T>::u(_I);
00500     }
00502   double& cv()
00503     {
00504       return _cv;
00505     }
00506   const double cv() const
00507     {
00508       return _cv;
00509     }
00511   double& cc()
00512     {
00513       return _cc;
00514     }
00515   const double cc() const
00516     {
00517       return _cc;
00518     }
00520   double*& cvsub()
00521     {
00522       return _cvsub;
00523     }
00524   const double* cvsub() const
00525     {
00526       return _cvsub;
00527     }
00529   double*& ccsub()
00530     {
00531       return _ccsub;
00532     }
00533   const double* ccsub() const
00534     {
00535       return _ccsub;
00536     }
00538   double& cvsub
00539     ( const unsigned int i )
00540     {
00541       return _cvsub[i];
00542     }
00543   const double cvsub
00544     ( const unsigned int i ) const
00545     {
00546       return _cvsub[i];
00547     }
00549   double& ccsub
00550     ( const unsigned int i )
00551     {
00552       return _ccsub[i];
00553     }
00554   const double ccsub
00555     ( const unsigned int i ) const
00556     {
00557       return _ccsub[i];
00558     }
00559 
00561   void I
00562     ( const T& I )
00563     {
00564       Op<T>::I(_I,I);
00565     }
00567   void cv
00568     ( const double& cv )
00569     {
00570       _cv = cv;
00571       _const = false;
00572     }
00574   void cc
00575     ( const double& cc )
00576     {
00577       _cc = cc;
00578       _const = false;
00579     }
00581   void c
00582     ( const double& c )
00583     {
00584       _cv = _cc = c;
00585       _const = false;
00586     }
00587 
00589   McCormick<T>& sub
00590     ( const unsigned int nsub);
00592   McCormick<T>& sub
00593     ( const unsigned int nsub, const unsigned int isub );
00595   McCormick<T>& sub
00596     ( const unsigned int nsub, const double*cvsub, const double*ccsub );
00597 
00599   McCormick<T>& cut();
00601   double laff
00602     ( const double*p, const double*pref ) const;
00604   double laff
00605     ( const T*Ip, const double*pref ) const;
00607   double uaff
00608     ( const double*p, const double*pref ) const;
00610   double uaff
00611     ( const T*Ip, const double*pref ) const;
00612 //   //! @brief Calculates affine bounds based on the subgradient values.
00615 private:
00616 
00618   unsigned int _nsub;
00620   T _I;
00622   double _cv;
00624   double _cc;
00626   double *_cvsub;
00628   double *_ccsub;
00630   bool _const;
00631   
00633   void _sub
00634     ( const unsigned int nsub, const bool cst );
00636   void _sub_reset();
00638   void _sub_resize
00639     ( const unsigned int nsub );
00641   void _sub_copy
00642     ( const McCormick<T>&MC );
00643 
00645   McCormick<T>& _sum1
00646     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00648   McCormick<T>& _sum2
00649     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00650 
00652   McCormick<T>& _sub1
00653     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00655   McCormick<T>& _sub2
00656     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00658   McCormick<T>& _sub3
00659     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00660 
00662   McCormick<T>& _mul1_u1pos_u2pos
00663     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00665   McCormick<T>& _mul2_u1pos_u2pos
00666     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00668   McCormick<T>& _mul1_u1pos_u2mix
00669     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00671   McCormick<T>& _mul2_u1pos_u2mix
00672     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00674   McCormick<T>& _mul3_u1pos_u2mix
00675     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00677   McCormick<T>& _mul1_u1mix_u2mix
00678     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00680   McCormick<T>& _mul2_u1mix_u2mix
00681     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00683   McCormick<T>& _mulMV
00684     ( const McCormick<T>&MC1, const McCormick<T>&MC2 );
00685 
00687   typedef double (puniv)
00688     ( const double x, const double*rusr, const int*iusr );
00690   static double _newton
00691     ( const double x0, const double xL, const double xU, const puniv f,
00692       const puniv df, const double*rusr, const int*iusr=0 );
00694   static double _secant
00695     ( const double x0, const double x1, const double xL, const double xU,
00696       const puniv f, const double*rusr, const int*iusr );
00697 
00699   static double* _oddpowcv
00700     ( const double x, const int iexp, const double xL, const double xU );
00702   static double* _oddpowcc
00703     ( const double x, const int iexp, const double xL, const double xU );
00705   static double _oddpowenv_func
00706     ( const double x, const double*rusr, const int*iusr );
00708   static double _oddpowenv_dfunc
00709     ( const double x, const double*rusr, const int*iusr );
00710 
00712   static double* _erfcv
00713     ( const double x, const double xL, const double xU );
00715   static double* _erfcc
00716     ( const double x, const double xL, const double xU );
00718   static double _erfenv_func
00719     ( const double x, const double*rusr, const int*iusr );
00721   static double _erfenv_dfunc
00722     ( const double x, const double*rusr, const int*iusr );
00723 
00725   static double* _stepcv
00726     ( const double x, const double xL, const double xU );
00728   static double* _stepcc
00729     ( const double x, const double xL, const double xU );
00730 
00732   static double* _cosarg
00733     (  const double xL, const double xU );
00735   static double* _coscv
00736     ( const double x, const double xL, const double xU );
00738   static double* _coscc
00739     ( const double x, const double xL, const double xU );
00741   static double* _coscv2
00742     ( const double x, const double xL, const double xU );
00744   static double _cosenv_func
00745     ( const double x, const double*rusr, const int*iusr );
00747   static double _cosenv_dfunc
00748     ( const double x, const double*rusr, const int*iusr );
00749 
00751   static double* _asincv
00752     ( const double x, const double xL, const double xU );
00754   static double* _asincc
00755     ( const double x, const double xL, const double xU );
00757   static double _asinenv_func
00758     ( const double x, const double*rusr, const int*iusr );
00760   static double _asinenv_dfunc
00761     ( const double x, const double*rusr, const int*iusr );
00762 };
00763 
00765 
00766 template <typename T> inline void
00767 McCormick<T>::_sub_reset()
00768 {
00769   delete [] _cvsub;
00770   delete [] _ccsub;
00771   _cvsub = _ccsub = 0;
00772 }
00773 
00774 template <typename T> inline void
00775 McCormick<T>::_sub_resize
00776 ( const unsigned int nsub )
00777 {
00778   if( _nsub != nsub ){
00779     delete [] _cvsub;
00780     delete [] _ccsub;
00781     _nsub = nsub;
00782     if( _nsub > 0 ){
00783       _cvsub = new double[_nsub];
00784       _ccsub = new double[_nsub];
00785     }
00786     else{
00787       _cvsub = _ccsub = 0;
00788       return;
00789     }
00790   }
00791 }
00792 
00793 template <typename T> inline void
00794 McCormick<T>::_sub_copy
00795 ( const McCormick<T>&MC )
00796 {
00797   _sub_resize( MC._nsub );
00798   for ( unsigned int i=0; i<_nsub; i++ ){
00799     _cvsub[i] = MC._cvsub[i];
00800     _ccsub[i] = MC._ccsub[i];
00801   }
00802   return;
00803 }
00804 
00805 template <typename T> inline void
00806 McCormick<T>::_sub
00807 ( const unsigned int nsub, const bool cst )
00808 {
00809   _sub_resize( nsub );
00810   for ( unsigned int i=0; i<nsub; i++ ){
00811     _cvsub[i] = _ccsub[i] = 0.;
00812   }
00813   _const = cst;
00814 }
00815 
00816 template <typename T> inline McCormick<T>&
00817 McCormick<T>::sub
00818 ( const unsigned int nsub )
00819 {
00820   _sub( nsub, false );
00821   return *this;
00822 }
00823 
00824 template <typename T> inline McCormick<T>&
00825 McCormick<T>::sub
00826 ( const unsigned int nsub, const unsigned int isub )
00827 {
00828   if( isub >= nsub ) throw Exceptions( Exceptions::SUB );
00829   sub( nsub );
00830   _cvsub[isub] = _ccsub[isub] = 1.;
00831   return *this;
00832 }
00833 
00834 template <typename T> inline McCormick<T>&
00835 McCormick<T>::sub
00836 ( const unsigned int nsub, const double*cvsub, const double*ccsub )
00837 {
00838   if( nsub && !(cvsub && ccsub) ) throw Exceptions( Exceptions::SUB );
00839   sub( nsub );
00840   for ( unsigned int i=0; i<nsub; i++ ){
00841     _cvsub[i] = cvsub[i];
00842     _ccsub[i] = ccsub[i];
00843   }
00844   return *this;
00845 }
00846 
00847 template <typename T> inline McCormick<T>&
00848 McCormick<T>::cut()
00849 {
00850   if( _cv < Op<T>::l(_I) ){
00851     _cv = Op<T>::l(_I);
00852     for( unsigned int i=0; i<_nsub; i++ ) _cvsub[i] = 0.;
00853   }
00854   if( _cc > Op<T>::u(_I) ){
00855     _cc = Op<T>::u(_I);
00856     for( unsigned int i=0; i<_nsub; i++ ) _ccsub[i] = 0.;
00857   }
00858   return *this;
00859 }
00860 
00861 template <typename T> inline double
00862 McCormick<T>::laff
00863 ( const double*p, const double*pref ) const
00864 {
00865   double _laff = _cv;
00866   for( unsigned int i=0; i<_nsub; i++ ){
00867     _laff += _cvsub[i]*(p[i]-pref[i]);
00868   }
00869   return _laff;
00870 }
00871 
00872 template <typename T> inline double
00873 McCormick<T>::laff
00874 ( const T*Ip, const double*pref ) const
00875 {
00876   double _laff = _cv;
00877   for( unsigned int i=0; i<_nsub; i++ ){
00878     _laff += Op<T>::l(_cvsub[i]*(Ip[i]-pref[i]));
00879   }
00880   return _laff;
00881 }
00882 
00883 template <typename T> inline double
00884 McCormick<T>::uaff
00885 ( const double*p, const double*pref ) const
00886 {
00887   double _uaff = _cc;
00888   for( unsigned int i=0; i<_nsub; i++ ){
00889     _uaff += _ccsub[i]*(p[i]-pref[i]);
00890   }
00891   return _uaff;
00892 }
00893 
00894 template <typename T> inline double
00895 McCormick<T>::uaff
00896 ( const T*Ip, const double*pref ) const
00897 {
00898   double _uaff = _cc;
00899   for( unsigned int i=0; i<_nsub; i++ ){
00900     _uaff += Op<T>::u(_ccsub[i]*(Ip[i]-pref[i]));
00901   }
00902   return _uaff;
00903 }
00904 
00905 // template <typename T> template <typename U> inline U
00906 // McCormick<T>::affine
00907 // ( const U*Ip, const double*pref ) const
00908 // {
00909 //   double laff = _cv;
00910 //   double uaff = _cc;
00911 //   for( unsigned int i=0; i<_nsub; i++ ){
00912 //     laff += Op<U>::l(_cvsub[i]*(Ip[i]-pref[i]));
00913 //     uaff += Op<U>::u(_ccsub[i]*(Ip[i]-pref[i]));
00914 //   }
00915 //   return U(laff,uaff);
00916 // }
00917 
00918 template <typename T> inline McCormick<T>&
00919 McCormick<T>::operator=
00920 ( const double c )
00921 {
00922   _I = c;
00923   _cv = _cc = c;
00924   _sub_reset();  
00925   _nsub = 0;
00926   _const = true; 
00927   return *this;
00928 }
00929 
00930 template <typename T> inline McCormick<T>&
00931 McCormick<T>::operator=
00932 ( const T&I )
00933 {
00934   _I = I;
00935   _cv = Op<T>::l(I);
00936   _cc = Op<T>::u(I);
00937   _sub_reset();
00938   _nsub = 0;
00939   _const = true;
00940   return *this;
00941 }
00942 
00943 template <typename T> inline McCormick<T>&
00944 McCormick<T>::operator=
00945 ( const McCormick<T>&MC )
00946 {
00947   if( this == &MC ) return *this;
00948   _I = MC._I;
00949   _cv = MC._cv;
00950   _cc = MC._cc;
00951   _sub_copy( MC );
00952   _const = MC._const;
00953   return *this;
00954 }
00955 
00956 template <typename T> inline McCormick<T>&
00957 McCormick<T>::operator+=
00958 ( const double a )
00959 { 
00960   _I += a;
00961   _cv += a;
00962   _cc += a; 
00963   return *this;
00964 }
00965 
00966 template <typename T> inline McCormick<T>&
00967 McCormick<T>::operator+=
00968 ( const McCormick<T> &MC )
00969 {
00970   if( _const && !MC._const ) sub( MC._nsub );
00971   else if( !MC._const && _nsub != MC._nsub ) throw Exceptions( Exceptions::SUB );
00972   _I += MC._I;
00973   _cv += MC._cv;
00974   _cc += MC._cc;
00975   for( unsigned int i=0; i<_nsub && !MC._const; i++ ){
00976     _cvsub[i] += MC._cvsub[i];
00977     _ccsub[i] += MC._ccsub[i];
00978   }
00979   return *this;
00980 }
00981 
00982 template <typename T> inline McCormick<T>&
00983 McCormick<T>::_sum1
00984 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
00985 {
00986   _I = MC1._I + MC2._I;
00987   _cv = MC1._cv + MC2._cv;
00988   _cc = MC1._cc + MC2._cc;
00989   for( unsigned int i=0; i<_nsub; i++ ){
00990     _cvsub[i] = MC1._cvsub[i];
00991     _ccsub[i] = MC1._ccsub[i];
00992   }
00993   return *this;
00994 }
00995 
00996 template <typename T> inline McCormick<T>&
00997 McCormick<T>::_sum2
00998 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
00999 {
01000   _I = MC1._I + MC2._I;
01001   _cv = MC1._cv + MC2._cv;
01002   _cc = MC1._cc + MC2._cc;
01003   for( unsigned int i=0; i<_nsub; i++ ){
01004     _cvsub[i] = MC1._cvsub[i] + MC2._cvsub[i];
01005     _ccsub[i] = MC1._ccsub[i] + MC2._ccsub[i];
01006   }
01007   return *this;
01008 }
01009 
01010 template <typename T> inline McCormick<T>&
01011 McCormick<T>::operator-=
01012 ( const double a )
01013 { 
01014   _I -= a;
01015   _cv -= a;
01016   _cc -= a; 
01017   return *this;
01018 }
01019 
01020 template <typename T> inline McCormick<T>&
01021 McCormick<T>::operator-=
01022 ( const McCormick<T> &MC )
01023 {
01024   if( _const && !MC._const ) sub( MC._nsub );
01025   else if( !MC._const && _nsub != MC._nsub ) throw Exceptions( Exceptions::SUB );
01026   _I -= MC._I;
01027   double t_cv = MC._cv;
01028   _cv -= MC._cc;
01029   _cc -= t_cv;
01030   for( unsigned int i=0; i<_nsub && !MC._const; i++ ){
01031     double t_cvsub = MC._cvsub[i];
01032     _cvsub[i] -= MC._ccsub[i];
01033     _ccsub[i] -= t_cvsub;
01034   }
01035   return *this;
01036 }
01037 
01038 template <typename T> inline McCormick<T>&
01039 McCormick<T>::_sub1
01040 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01041 {
01042   _I = MC1._I - MC2._I;
01043   _cv = MC1._cv - MC2._cc;
01044   _cc = MC1._cc - MC2._cv;
01045   for( unsigned int i=0; i<_nsub; i++ ){
01046     _cvsub[i] = MC1._cvsub[i];
01047     _ccsub[i] = MC1._ccsub[i];
01048   }
01049   return *this;
01050 }
01051 
01052 template <typename T> inline McCormick<T>&
01053 McCormick<T>::_sub2
01054 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01055 {
01056   _I = MC1._I - MC2._I;
01057   _cv = MC1._cv - MC2._cc;
01058   _cc = MC1._cc - MC2._cv;
01059   for( unsigned int i=0; i<_nsub; i++ ){
01060     _cvsub[i] = -MC2._ccsub[i];
01061     _ccsub[i] = -MC2._cvsub[i];
01062   }
01063   return *this;
01064 }
01065 
01066 template <typename T> inline McCormick<T>&
01067 McCormick<T>::_sub3
01068 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01069 {
01070   _I = MC1._I - MC2._I;
01071   _cv = MC1._cv - MC2._cc;
01072   _cc = MC1._cc - MC2._cv;
01073   for( unsigned int i=0; i<_nsub; i++ ){
01074     _cvsub[i] = MC1._cvsub[i] - MC2._ccsub[i];
01075     _ccsub[i] = MC1._ccsub[i] - MC2._cvsub[i];
01076   }
01077   return *this;
01078 }
01079 
01080 template <typename T> inline McCormick<T>&
01081 McCormick<T>::operator*=
01082 ( const double a )
01083 {
01084   McCormick<T> MC2 = a * (*this);
01085   *this = MC2;
01086   return *this;
01087 }
01088 
01089 template <typename T> inline McCormick<T>&
01090 McCormick<T>::operator*=
01091 ( const McCormick<T>&MC )
01092 {
01093   if( _const && !MC._const ) sub( MC._nsub );
01094   McCormick<T> MC2 = MC * (*this);
01095   *this = MC2;
01096   return *this;
01097 }
01098 
01099 template <typename T> inline McCormick<T>&
01100 McCormick<T>::_mul1_u1pos_u2pos
01101 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01102 {
01103   _I = MC1._I * MC2._I;
01104 
01105   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01106     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01107   double cv2 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::l(MC1._I) * MC2._cv
01108     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01109   if ( cv1 > cv2 ){
01110     _cv = cv1;
01111     for( unsigned int i=0; i<_nsub; i++ )
01112       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i];
01113   }
01114   else{
01115     _cv = cv2;
01116     for( unsigned int i=0; i<_nsub; i++ )
01117       _cvsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i];
01118   }
01119 
01120   double cc1 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::u(MC1._I) * MC2._cc
01121     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01122   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01123     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01124   if ( cc1 < cc2 ){
01125     _cc = cc1;
01126     for( unsigned int i=0; i<_nsub; i++ )
01127       _ccsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i];
01128   }
01129   else{
01130     _cc = cc2;
01131     for( unsigned int i=0; i<_nsub; i++ )
01132       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i];
01133   }
01134   return *this;
01135 }
01136 
01137 template <typename T> inline McCormick<T>&
01138 McCormick<T>::_mul2_u1pos_u2pos
01139 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01140 {
01141   _I = MC1._I * MC2._I;
01142 
01143   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01144     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01145   double cv2 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::l(MC1._I) * MC2._cv
01146     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01147   if ( cv1 > cv2 ){
01148     _cv = cv1;
01149     for( unsigned int i=0; i<_nsub; i++ )
01150       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i] + Op<T>::u(MC1._I) * MC2._cvsub[i];
01151   }
01152   else{
01153     _cv = cv2;
01154     for( unsigned int i=0; i<_nsub; i++ )
01155       _cvsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i] + Op<T>::l(MC1._I) * MC2._cvsub[i];
01156   }
01157 
01158   double cc1 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::u(MC1._I) * MC2._cc
01159     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01160   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01161     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01162   if ( cc1 < cc2 ){
01163     _cc = cc1;
01164     for( unsigned int i=0; i<_nsub; i++ )
01165       _ccsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i] + Op<T>::u(MC1._I) * MC2._ccsub[i];
01166   }
01167   else{
01168     _cc = cc2;
01169     for( unsigned int i=0; i<_nsub; i++ )
01170       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i] + Op<T>::l(MC1._I) * MC2._ccsub[i];
01171   }
01172   return *this;
01173 }
01174 
01175 template <typename T> inline McCormick<T>&
01176 McCormick<T>::_mul1_u1pos_u2mix
01177 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01178 {
01179   _I = MC1._I * MC2._I;
01180 
01181   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01182     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01183   double cv2 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cv
01184     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01185   if ( cv1 > cv2 ){
01186     _cv = cv1;
01187     for( unsigned int i=0; i<_nsub; i++ )
01188       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i];
01189   }
01190   else{
01191     _cv = cv2;
01192     for( unsigned int i=0; i<_nsub; i++ )
01193       _cvsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i];
01194   }
01195 
01196   double cc1 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cc
01197     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01198   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01199     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01200   if ( cc1 < cc2 ){
01201     _cc = cc1;
01202     for( unsigned int i=0; i<_nsub; i++ )
01203       _ccsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i];
01204   }
01205   else{
01206     _cc = cc2;
01207     for( unsigned int i=0; i<_nsub; i++ )
01208       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i];
01209   }
01210   return *this;
01211 }
01212 
01213 template <typename T> inline McCormick<T>&
01214 McCormick<T>::_mul2_u1pos_u2mix
01215 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01216 {
01217   _I = MC1._I * MC2._I;
01218 
01219   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01220     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01221   double cv2 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cv
01222     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01223   if ( cv1 > cv2 ){
01224     _cv = cv1;
01225     for( unsigned int i=0; i<_nsub; i++ )
01226       _cvsub[i] = Op<T>::u(MC1._I) * MC2._cvsub[i];
01227   }
01228   else{
01229     _cv = cv2;
01230     for( unsigned int i=0; i<_nsub; i++ )
01231       _cvsub[i] = Op<T>::l(MC1._I) * MC2._cvsub[i];
01232   }
01233 
01234   double cc1 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cc
01235     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01236   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01237     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01238   if ( cc1 < cc2 ){
01239     _cc = cc1;
01240     for( unsigned int i=0; i<_nsub; i++ )
01241       _ccsub[i] = Op<T>::u(MC1._I) * MC2._ccsub[i];
01242   }
01243   else{
01244     _cc = cc2;
01245     for( unsigned int i=0; i<_nsub; i++ )
01246       _ccsub[i] = Op<T>::l(MC1._I) * MC2._ccsub[i];
01247   }
01248   return *this;
01249 }
01250 
01251 template <typename T> inline McCormick<T>&
01252 McCormick<T>::_mul3_u1pos_u2mix
01253 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01254 {
01255   _I = MC1._I * MC2._I;
01256 
01257   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01258     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01259   double cv2 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cv
01260     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01261   if ( cv1 > cv2 ){
01262     _cv = cv1;
01263     for( unsigned int i=0; i<_nsub; i++ )
01264       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i] + Op<T>::u(MC1._I) * MC2._cvsub[i];
01265   }
01266   else{
01267     _cv = cv2;
01268     for( unsigned int i=0; i<_nsub; i++ )
01269       _cvsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i] + Op<T>::l(MC1._I) * MC2._cvsub[i];
01270   }
01271 
01272   double cc1 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cc
01273     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01274   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01275     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01276   if ( cc1 < cc2 ){
01277     _cc = cc1;
01278     for( unsigned int i=0; i<_nsub; i++ )
01279       _ccsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i] + Op<T>::u(MC1._I) * MC2._ccsub[i];
01280   }
01281   else{
01282     _cc = cc2;
01283     for( unsigned int i=0; i<_nsub; i++ )
01284       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i] + Op<T>::l(MC1._I) * MC2._ccsub[i];
01285   }
01286   return *this;
01287 }
01288 
01289 template <typename T> inline McCormick<T>&
01290 McCormick<T>::_mul1_u1mix_u2mix
01291 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01292 {
01293   _I = MC1._I * MC2._I;
01294 
01295   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01296     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01297   double cv2 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01298     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01299   if ( cv1 > cv2 ){
01300     _cv = cv1;
01301     for( unsigned int i=0; i<_nsub; i++ )
01302       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i];
01303   }
01304   else{
01305     _cv = cv2;
01306     for( unsigned int i=0; i<_nsub; i++ )
01307       _cvsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i];
01308   }
01309 
01310   double cc1 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cc
01311     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01312   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cv
01313     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01314   if ( cc1 < cc2 ){
01315     _cc = cc1;
01316     for( unsigned int i=0; i<_nsub; i++ )
01317       _ccsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i];
01318   }
01319   else{
01320     _cc = cc2;
01321     for( unsigned int i=0; i<_nsub; i++ )
01322       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i];
01323   }
01324   return *this;
01325 }
01326 
01327 template <typename T> inline McCormick<T>&
01328 McCormick<T>::_mul2_u1mix_u2mix
01329 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01330 {
01331   _I = MC1._I * MC2._I;
01332 
01333   double cv1 = Op<T>::u(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cv
01334     - Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
01335   double cv2 = Op<T>::l(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cc
01336     - Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
01337   if ( cv1 > cv2 ){
01338     _cv = cv1;
01339     for( unsigned int i=0; i<_nsub; i++ )
01340       _cvsub[i] = Op<T>::u(MC2._I) * MC1._cvsub[i] + Op<T>::u(MC1._I) * MC2._cvsub[i];
01341   }
01342   else{
01343     _cv = cv2;
01344     for( unsigned int i=0; i<_nsub; i++ )
01345       _cvsub[i] = Op<T>::l(MC2._I) * MC1._ccsub[i] + Op<T>::l(MC1._I) * MC2._ccsub[i];
01346   }
01347 
01348   double cc1 = Op<T>::l(MC2._I) * MC1._cv + Op<T>::u(MC1._I) * MC2._cc
01349     - Op<T>::u(MC1._I) * Op<T>::l(MC2._I);
01350   double cc2 = Op<T>::u(MC2._I) * MC1._cc + Op<T>::l(MC1._I) * MC2._cv
01351     - Op<T>::l(MC1._I) * Op<T>::u(MC2._I);
01352   if ( cc1 < cc2 ){
01353     _cc = cc1;
01354     for( unsigned int i=0; i<_nsub; i++ )
01355       _ccsub[i] = Op<T>::l(MC2._I) * MC1._cvsub[i] + Op<T>::u(MC1._I) * MC2._ccsub[i];
01356   }
01357   else{
01358     _cc = cc2;
01359     for( unsigned int i=0; i<_nsub; i++ )
01360       _ccsub[i] = Op<T>::u(MC2._I) * MC1._ccsub[i] + Op<T>::l(MC1._I) * MC2._cvsub[i];
01361   }
01362   return *this;
01363 }
01364 
01365 template <typename T> inline McCormick<T>&
01366 McCormick<T>::_mulMV
01367 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01368 {
01369  // Convex underestimator part
01370  {const double k = - Op<T>::diam(MC2._I) / Op<T>::diam(MC1._I);
01371   const double z = ( Op<T>::u(MC1._I)*Op<T>::u(MC2._I)
01372                    - Op<T>::l(MC1._I)*Op<T>::l(MC2._I) )
01373                    / Op<T>::diam(MC1._I);
01374   struct fct{
01375     static double t1
01376       ( const double x1, const double x2, const McCormick<T>&MC1,
01377         const McCormick<T>&MC2 )
01378       { return Op<T>::u(MC2._I) * x1 + Op<T>::u(MC1._I) * x2
01379         - Op<T>::u(MC2._I) * Op<T>::u(MC1._I); }
01380     static double t2
01381       ( const double x1, const double x2, const McCormick<T>&MC1,
01382         const McCormick<T>&MC2 )
01383       { return Op<T>::l(MC2._I) * x1 + Op<T>::l(MC1._I) * x2
01384         - Op<T>::l(MC2._I) * Op<T>::l(MC1._I); }
01385     static double t
01386       ( const double x1, const double x2, const McCormick<T>&MC1,
01387         const McCormick<T>&MC2 )
01388       { return std::max( t1(x1,x2,MC1,MC2), t2(x1,x2,MC1,MC2) ); }
01389   };
01390 
01391   int imid[4] = { -1, -1, -1, -1 };
01392   const double x1t[4] = { MC1._cv, MC1._cc,
01393                           mid( MC1._cv, MC1._cc, (MC2._cv-z)/k, imid[0] ),
01394                 mid( MC1._cv, MC1._cc, (MC2._cc-z)/k, imid[1] ) };
01395   const double x2t[4] = { mid( MC2._cv, MC2._cc, k*MC1._cv+z, imid[2] ),
01396                 mid( MC2._cv, MC2._cc, k*MC1._cc+z, imid[3] ),
01397                           MC2._cv, MC2._cc };
01398   const double v[4] = { fct::t( x1t[0], x2t[0], MC1, MC2 ), fct::t( x1t[1], x2t[1], MC1, MC2 ),
01399                         fct::t( x1t[2], x2t[2], MC1, MC2 ), fct::t( x1t[3], x2t[3], MC1, MC2 ) };
01400   const unsigned int ndx = argmin( 4, v );
01401   _cv = v[ndx];
01402 
01403   if( _nsub ){
01404     double myalpha;
01405     if( isequal( fct::t1( x1t[ndx], x2t[ndx], MC1, MC2 ),
01406                  fct::t2( x1t[ndx], x2t[ndx], MC1, MC2 ),
01407        options.MVCOMP_TOL, options.MVCOMP_TOL ) ){
01408       std::pair<double,double> alpha( 0., 1. );
01409       if( x1t[ndx] > MC1._cv )
01410         alpha.second = std::min( alpha.second, -Op<T>::l(MC2._I)/Op<T>::diam(MC2._I) );
01411       if( x1t[ndx] < MC1._cc )
01412         alpha.first = std::max( alpha.first, -Op<T>::l(MC2._I)/Op<T>::diam(MC2._I) );
01413       if( x2t[ndx] > MC2._cv )
01414         alpha.second = std::min( alpha.second, -Op<T>::l(MC1._I)/Op<T>::diam(MC1._I) );
01415       if( x2t[ndx] < MC2._cc )
01416         alpha.first = std::max( alpha.first, -Op<T>::l(MC1._I)/Op<T>::diam(MC1._I) );
01417       if( alpha.first > alpha.second ){
01418         std::cout << "WARNING: alphaL= " << alpha.first << "  alphaU= " << alpha.second
01419              << std::endl;
01420         throw Exceptions( Exceptions::MULTSUB );
01421       }
01422       myalpha = 0.5*( alpha.first + alpha.second );
01423     }
01424     else if( fct::t1( x1t[ndx], x2t[ndx], MC1, MC2 ) > fct::t2( x1t[ndx], x2t[ndx], MC1, MC2 ) )
01425       myalpha = 1.;
01426     else
01427       myalpha = 0.;
01428     double sigma1cv = Op<T>::l(MC2._I) + myalpha * Op<T>::diam(MC2._I),
01429            sigma2cv = Op<T>::l(MC1._I) + myalpha * Op<T>::diam(MC1._I);
01430     for( unsigned int i=0; i<_nsub; i++ )
01431       _cvsub[i] = ( sigma1cv>=0? MC1._cvsub[i]: MC1._ccsub[i] ) * sigma1cv
01432                 + ( sigma2cv>=0? MC2._cvsub[i]: MC2._ccsub[i] ) * sigma2cv;
01433   }
01434  }
01435 
01436  // Concave overestimator part
01437  {const double k = Op<T>::diam(MC2._I) / Op<T>::diam(MC1._I);
01438   const double z = ( Op<T>::u(MC1._I)*Op<T>::l(MC2._I)
01439                    - Op<T>::l(MC1._I)*Op<T>::u(MC2._I) )
01440                    / Op<T>::diam(MC1._I);
01441   struct fct{
01442     static double t1
01443       ( const double x1, const double x2, const McCormick<T>&MC1,
01444         const McCormick<T>&MC2 )
01445       { return Op<T>::l(MC2._I) * x1 + Op<T>::u(MC1._I) * x2
01446         - Op<T>::l(MC2._I) * Op<T>::u(MC1._I); }
01447     static double t2
01448       ( const double x1, const double x2, const McCormick<T>&MC1,
01449         const McCormick<T>&MC2 )
01450       { return Op<T>::u(MC2._I) * x1 + Op<T>::l(MC1._I) * x2
01451         - Op<T>::u(MC2._I) * Op<T>::l(MC1._I); }
01452     static double t
01453       ( const double x1, const double x2, const McCormick<T>&MC1,
01454         const McCormick<T>&MC2 )
01455       { return std::min( t1(x1,x2,MC1,MC2), t2(x1,x2,MC1,MC2) ); }
01456   };
01457 
01458   int imid[4] = { -1, -1, -1, -1 };
01459   const double x1t[4] = { MC1._cv, MC1._cc,
01460                           mid( MC1._cv, MC1._cc, (MC2._cv-z)/k, imid[0] ),
01461                 mid( MC1._cv, MC1._cc, (MC2._cc-z)/k, imid[1] ) };
01462   const double x2t[4] = { mid( MC2._cv, MC2._cc, k*MC1._cv+z, imid[2] ),
01463                 mid( MC2._cv, MC2._cc, k*MC1._cc+z, imid[3] ),
01464            MC2._cv, MC2._cc };
01465   const double v[4] = { fct::t( x1t[0], x2t[0], MC1, MC2 ), fct::t( x1t[1], x2t[1], MC1, MC2 ),
01466                         fct::t( x1t[2], x2t[2], MC1, MC2 ), fct::t( x1t[3], x2t[3], MC1, MC2 ) };
01467   const unsigned int ndx = argmax( 4, v );
01468   _cc = v[ndx];
01469 
01470   if( _nsub ){
01471     double myalpha;
01472     if( isequal( fct::t1( x1t[ndx], x2t[ndx], MC1, MC2 ),
01473                  fct::t2( x1t[ndx], x2t[ndx], MC1, MC2 ),
01474        options.MVCOMP_TOL, options.MVCOMP_TOL ) ){
01475       std::pair<double,double> alpha( 0., 1. );
01476       if( x1t[ndx] > MC1._cv )
01477         alpha.first = std::max( alpha.first, -Op<T>::l(MC2._I)/Op<T>::diam(MC2._I) );
01478       if( x1t[ndx] < MC1._cc )
01479         alpha.second = std::min( alpha.second, -Op<T>::l(MC2._I)/Op<T>::diam(MC2._I) );
01480       if( x2t[ndx] > MC2._cv )
01481         alpha.second = std::min( alpha.second, Op<T>::u(MC1._I)/Op<T>::diam(MC1._I) );
01482       if( x2t[ndx] > MC2._cc )
01483         alpha.first = std::max( alpha.first, Op<T>::u(MC1._I)/Op<T>::diam(MC1._I) );
01484       if( alpha.first > alpha.second ){
01485         std::cout << "WARNING: alphaL= " << alpha.first << "  alphaU= " << alpha.second
01486              << std::endl;
01487         throw Exceptions( Exceptions::MULTSUB );
01488       }
01489       myalpha = 0.5*( alpha.first + alpha.second ); //alpha.second
01490     }
01491     else if( fct::t1( x1t[ndx], x2t[ndx], MC1, MC2 ) < fct::t2( x1t[ndx], x2t[ndx], MC1, MC2 ) )
01492       myalpha = 0.;
01493     else
01494       myalpha = 1.;
01495     double sigma1cc = Op<T>::l(MC2._I) + myalpha * Op<T>::diam(MC2._I),
01496            sigma2cc = Op<T>::u(MC1._I) - myalpha * Op<T>::diam(MC1._I);
01497     for( unsigned int i=0; i<_nsub; i++ )
01498       _ccsub[i] = ( sigma1cc>=0? MC1._ccsub[i]: MC1._cvsub[i] ) * sigma1cc
01499                 + ( sigma2cc>=0? MC2._ccsub[i]: MC2._cvsub[i] ) * sigma2cc;
01500   }
01501  }
01502 
01503   return *this;
01504 }
01505 
01506 template <typename T> inline McCormick<T>&
01507 McCormick<T>::operator/=
01508 ( const double a )
01509 {
01510   McCormick<T> MC2 = (*this) / a;
01511   *this = MC2;
01512   return *this;
01513 }
01514 
01515 template <typename T> inline McCormick<T>&
01516 McCormick<T>::operator/=
01517 ( const McCormick<T>&MC )
01518 {
01519   if( _const && !MC._const ) sub( MC._nsub );
01520   McCormick<T> MC2 = (*this) / MC;
01521   *this = MC2;
01522   return *this;
01523 }
01524 
01525 template <typename T> inline double*
01526 McCormick<T>::_erfcv
01527 ( const double x, const double xL, const double xU )
01528 {
01529   static double cv[2];
01530   if( xU <= 0. ){  // convex part
01531     cv[0] = ::erf(x), cv[1] = 2./std::sqrt(PI)*std::exp(-sqr(x));
01532     return cv;
01533   }
01534 
01535   if( xL >= 0. ){  // concave part
01536     double r = ( isequal( xL, xU )? 0.:(::erf(xU)-::erf(xL))/(xU-xL) );
01537     cv[0] = ::erf(xL)+r*(x-xL), cv[1] = r;
01538     return cv;
01539   }
01540     
01541   double xj = _newton( xL, xL, 0., _erfenv_func, _erfenv_dfunc, &xU );
01542   if( x <= xj ){   // convex part
01543     cv[0] = ::erf(x), cv[1] = 2./std::sqrt(PI)*std::exp(-sqr(x));
01544     return cv;
01545   }
01546   double r = ( isequal( xj, xU )? 0.:(::erf(xU)-::erf(xj))/(xU-xj) );
01547   cv[0] = ::erf(xU)+r*(x-xU), cv[1] = r;
01548   return cv;
01549 }
01550 
01551 template <typename T> inline double*
01552 McCormick<T>::_erfcc
01553 ( const double x, const double xL, const double xU )
01554 {
01555   static double cc[2];
01556   if( xU <= 0. ){  // convex part
01557     double r = ( isequal( xL, xU )? 0.:(::erf(xU)-::erf(xL))/(xU-xL) );
01558     cc[0] = ::erf(xL)+r*(x-xL), cc[1] = r;
01559     return cc;
01560   }
01561 
01562   if( xL >= 0. ){  // concave part
01563     cc[0] = ::erf(x), cc[1] = 2./std::sqrt(PI)*std::exp(-sqr(x));
01564     return cc;
01565   }
01566     
01567   double xj = _newton( xU, 0., xU, _erfenv_func, _erfenv_dfunc, &xL );
01568   if( x >= xj ){   // concave part
01569     cc[0] = ::erf(x), cc[1] = 2./std::sqrt(PI)*std::exp(-sqr(x));
01570     return cc;
01571   }
01572   double r = ( isequal( xj, xL )? 0.:(::erf(xL)-::erf(xj))/(xL-xj) );
01573   cc[0] = ::erf(xL)+r*(x-xL), cc[1] = r;
01574   return cc;
01575 }
01576 
01577 template <typename T> inline double
01578 McCormick<T>::_erfenv_func
01579 ( const double x, const double*rusr, const int*iusr )
01580 {
01581   // f(z) = 2/sqrt(pi)*(b-z)*exp(-z^2) + erf(z) - erf(b) = 0
01582   return 2./std::sqrt(PI)*(*rusr-x)*std::exp(-sqr(x)) + ::erf(x)
01583     - ::erf(*rusr);
01584 }
01585 
01586 template <typename T> inline double
01587 McCormick<T>::_erfenv_dfunc
01588 ( const double x, const double*rusr, const int*iusr )
01589 {
01590   // f'(z) = -4/sqrt(pi)*z*(b-z)*exp(-z^2)
01591   return -4./std::sqrt(PI)*x*(*rusr-x)*std::exp(-sqr(x));
01592 }
01593 
01594 template <typename T> inline double*
01595 McCormick<T>::_oddpowcv
01596 ( const double x, const int iexp, const double xL, const double xU )
01597 {
01598   static double cv[2];
01599   if( xL >= 0. ){  // convex part
01600     double v = std::pow(x,iexp-1);
01601     cv[0] = x*v, cv[1] = iexp*v;
01602     return cv;
01603   }
01604 
01605   if( xU <= 0. ){  // concave part
01606     double r = ( isequal( xL, xU )? 0.:
01607       (std::pow(xU,iexp)-std::pow(xL,iexp))/(xU-xL) );
01608     cv[0] = std::pow(xL,iexp)+r*(x-xL), cv[1] = r;
01609     return cv;
01610   }
01611     
01612   double xj = _newton( xU, 0., xU, _oddpowenv_func, _oddpowenv_dfunc,
01613     &xL, &iexp );
01614   if( x >= xj ){   // convex part
01615     double v = std::pow(x,iexp-1);
01616     cv[0] = x*v, cv[1] = iexp*v;
01617     return cv;
01618   }
01619   double r = ( isequal( xL, xj )? 0.:
01620     (std::pow(xj,iexp)-std::pow(xL,iexp))/(xj-xL) );
01621   cv[0] = std::pow(xL,iexp)+r*(x-xL), cv[1] = r;
01622   return cv;
01623 }
01624 
01625 template <typename T> inline double*
01626 McCormick<T>::_oddpowcc
01627 ( const double x, const int iexp, const double xL, const double xU )
01628 {
01629   static double cc[2];
01630   if( xL >= 0. ){  // convex part
01631     double r = ( isequal( xL, xU )? 0.:
01632       (std::pow(xU,iexp)-std::pow(xL,iexp))/(xU-xL) );
01633     cc[0] = std::pow(xL,iexp)+r*(x-xL), cc[1] = r;
01634     return cc;
01635   }
01636   if( xU <= 0. ){  // concave part
01637     double v = std::pow(x,iexp-1);
01638     cc[0] = x*v, cc[1] = iexp*v;
01639     return cc;
01640   }
01641 
01642   double xj = _newton( xL, xL, 0., _oddpowenv_func, _oddpowenv_dfunc,
01643     &xU, &iexp );
01644   if( x <= xj ){   // concave part
01645     double v = std::pow(x,iexp-1);
01646     cc[0] = x*v, cc[1] = iexp*v;
01647     return cc;
01648   }
01649   double r = ( isequal( xU, xj )? 0.:
01650     (std::pow(xj,iexp)-std::pow(xU,iexp))/(xj-xU) );
01651   cc[0] = std::pow(xU,iexp)+r*(x-xU), cc[1] = r;
01652   return cc;
01653 }
01654 
01655 template <typename T> inline double
01656 McCormick<T>::_oddpowenv_func
01657 ( const double x, const double*rusr, const int*iusr )
01658 {
01659   // f(z) = (p-1)*z^p - a*p*z^{p-1} + a^p = 0
01660   return ((*iusr-1)*x-(*rusr)*(*iusr))*std::pow(x,*iusr-1)
01661     + std::pow(*rusr,*iusr);
01662 }
01663 
01664 template <typename T> inline double
01665 McCormick<T>::_oddpowenv_dfunc
01666 ( const double x, const double*rusr, const int*iusr )
01667 {
01668   // f'(z) = p*(p-1)*z^{p-1} - a*p*(p-1)*z^{p-2}
01669   return ((*iusr)*(*iusr-1)*x-(*rusr)*(*iusr)*(*iusr-1))*std::pow(x,*iusr-2);
01670 }
01671 
01672 template <typename T> inline double*
01673 McCormick<T>::_stepcv
01674 ( const double x, const double xL, const double xU )
01675 {
01676   static double cv[2];
01677 
01678   if( x < 0. ){
01679     cv[0] = cv[1] = 0.;
01680     return cv;
01681   }
01682 
01683   if( xL >= 0. ){
01684     cv[0] = 1., cv[1] = 0.;
01685     return cv;
01686   }
01687 
01688   cv[0] = x/xU, cv[1] = 1./xU;
01689   return cv;
01690 }
01691 
01692 template <typename T> inline double*
01693 McCormick<T>::_stepcc
01694 ( const double x, const double xL, const double xU )
01695 {
01696   static double cc[2];
01697 
01698   if( x >= 0. ){
01699     cc[0] = 1., cc[1] = 0.;
01700     return cc;
01701   }
01702 
01703   else if( xU < 0. ){
01704     cc[0] = 0., cc[1] = 0.;
01705     return cc;
01706   }
01707 
01708   cc[0] = 1.-x/xL, cc[1] = -1./xL;
01709   return cc;
01710 }
01711 
01712 template <typename T> inline double*
01713 McCormick<T>::_cosarg
01714 ( const double xL, const double xU )
01715 {
01716   static double arg[2];
01717   const int kL = std::ceil(-(1.+xL/PI)/2.);
01718   const double xL1 = xL+2.*PI*kL, xU1 = xU+2.*PI*kL;
01719   assert( xL1 >= -PI && xL1 <= PI );
01720   if( xL1 <= 0 ){
01721     if( xU1 <= 0 ) arg[0] = xL, arg[1] = xU;
01722     else if( xU1 >= PI ) arg[0] = PI*(1.-2.*kL), arg[1] = -PI*2.*kL;
01723     else arg[0] = std::cos(xL1)<=std::cos(xU1)?xL:xU, arg[1] = -PI*2.*kL;
01724     return arg;
01725   }
01726   if( xU1 <= PI ) arg[0] = xU, arg[1] = xL;
01727   else if( xU1 >= 2.*PI ) arg[0] = PI*(1-2.*kL), arg[1] = 2.*PI*(1.-kL);
01728   else arg[0] = PI*(1.-2.*kL), arg[1] = std::cos(xL1)>=std::cos(xU1)?xL:xU;
01729   return arg;
01730 }
01731 
01732 template <typename T> inline double*
01733 McCormick<T>::_coscv
01734 ( const double x, const double xL, const double xU )
01735 {
01736   static double cv[2];
01737   const int kL = std::ceil(-(1.+xL/PI)/2.);
01738   if( x <= PI*(1-2*kL) ){
01739     const double xL1 = xL+2.*PI*kL;
01740     if( xL1 >= 0.5*PI ){
01741       cv[0] = std::cos(x), cv[1] = -std::sin(x);
01742       return cv;
01743     }
01744     const double xU1 = std::min(xU+2.*PI*kL,PI);
01745     if( xL1 >= -0.5*PI && xU1 <= 0.5*PI ){
01746       double r = ( isequal( xL, xU )? 0.: (std::cos(xU)-std::cos(xL))/(xU-xL) );
01747       cv[0] = std::cos(xL)+r*(x-xL), cv[1] = r;
01748       return cv;
01749     }
01750     return _coscv2( x+2.*PI*kL, xL1, xU1 );
01751   }
01752 
01753   const int kU = std::floor((1.-xU/PI)/2.);
01754   if( x >= PI*(-1-2*kU) ){
01755     const double xU2 = xU+2.*PI*kU;
01756     if( xU2 <= -0.5*PI ){
01757       cv[0] = std::cos(x), cv[1] = -std::sin(x);
01758       return cv;
01759     }
01760     return _coscv2( x+2.*PI*kU, std::max(xL+2.*PI*kU,-PI), xU2 );
01761   }
01762 
01763   cv[0] = -1., cv[1] = 0.;
01764   return cv;
01765 }
01766 
01767 template <typename T> inline double*
01768 McCormick<T>::_coscv2
01769 ( const double x, const double xL, const double xU )
01770 {
01771   bool left;
01772   double x0, xm;
01773   if( std::fabs(xL)<=std::fabs(xU) )
01774     left = false, x0 = xU, xm = xL;
01775   else
01776     left = true, x0 = xL, xm = xU;
01777   double xj = _newton( x0, xL, xU, _cosenv_func, _cosenv_dfunc, &xm, 0 );
01778 
01779   static double cv[2];
01780   if(( left && x<=xj ) || ( !left && x>=xj )){
01781     cv[0] = std::cos(x), cv[1] = -std::sin(x);
01782     return cv;
01783   }
01784   double r = ( isequal( xm, xj )? 0.: (std::cos(xm)-std::cos(xj))/(xm-xj) );
01785   cv[0] = std::cos(xm)+r*(x-xm), cv[1] = r;
01786   return cv;
01787 }
01788 
01789 template <typename T> inline double*
01790 McCormick<T>::_coscc
01791 ( const double x, const double xL, const double xU )
01792 {
01793   static double cc[2];
01794   const double*cvenv = _coscv( x-PI, xL-PI, xU-PI );
01795   cc[0] = -cvenv[0], cc[1] = -cvenv[1];
01796   return cc;
01797 }
01798 
01799 template <typename T> inline double
01800 McCormick<T>::_cosenv_func
01801 ( const double x, const double*rusr, const int*iusr )
01802 
01803 {
01804   // f(z) = (z-a)*sin(z)+cos(z)-cos(a) = 0
01805   return ((x-*rusr)*std::sin(x)+std::cos(x)-std::cos(*rusr));
01806 }
01807 
01808 template <typename T> inline double
01809 McCormick<T>::_cosenv_dfunc
01810 ( const double x, const double*rusr, const int*iusr )
01811 {
01812   // f'(z) = (z-a)*cos(z)
01813   return ((x-*rusr)*std::cos(x));
01814 }
01815 
01816 template <typename T> inline double*
01817 McCormick<T>::_asincv
01818 ( const double x, const double xL, const double xU )
01819 {
01820   static double cv[2];
01821   if( xL >= 0. ){  // convex part
01822     cv[0] = std::asin(x), cv[1] = 1./std::sqrt(1-x*x);
01823     return cv;
01824   }
01825   if( xU <= 0. ){  // concave part
01826     double r = ( isequal( xL, xU )? 0.: (std::asin(xU)-std::asin(xL))/(xU-xL));
01827     cv[0] = std::asin(xL)+r*(x-xL), cv[1] = r;
01828     return cv;
01829   }   
01830   double xj = _secant( 0., xU, 0., xU, _asinenv_func, &xL, 0 );
01831   //double xj = _newton( xU, 0., xU, _asinenv_func, _asinenv_dfunc, &xL, 0 );
01832   if( x >= xj ){   // convex part
01833     cv[0] = std::asin(x), cv[1] = 1./std::sqrt(1-x*x);
01834     return cv;
01835   }
01836   double r = ( isequal( xL, xj )? 0.: (std::asin(xj)-std::asin(xL))/(xj-xL));
01837   cv[0] = std::asin(xL)+r*(x-xL), cv[1] = r; // linear part
01838   return cv;
01839 }
01840 
01841 template <typename T> inline double*
01842 McCormick<T>::_asincc
01843 ( const double x, const double xL, const double xU )
01844 {
01845   static double cc[2];
01846   if( xL >= 0. ){  // convex part
01847     double r = ( isequal( xL, xU )? 0.: (std::asin(xU)-std::asin(xL))/(xU-xL));
01848     cc[0] = std::asin(xL)+r*(x-xL), cc[1] = r;
01849     return cc;
01850   }
01851   if( xU <= 0. ){  // concave part
01852     cc[0] = std::asin(x), cc[1] = 1./std::sqrt(1-x*x);
01853     return cc;
01854   }
01855   double xj = _secant( 0., xL, xL, 0., _asinenv_func, &xU, 0 );
01856   //double xj = _newton( xL, xL, 0., _asinenv_func, _asinenv_dfunc, &xU, 0 );
01857   if( x <= xj ){   // concave part
01858     cc[0] = std::asin(x), cc[1] = 1./std::sqrt(1-x*x);
01859     return cc;
01860   }
01861   double r = ( isequal( xU, xj )? 0.: (std::asin(xj)-std::asin(xU))/(xj-xU));
01862   cc[0] = std::asin(xU)+r*(x-xU), cc[1] = r; // linear part
01863   return cc;
01864 }
01865 
01866 template <typename T> inline double
01867 McCormick<T>::_asinenv_func
01868 ( const double x, const double*rusr, const int*iusr )
01869 {
01870   // f(z) = z-a-sqrt(1-z^2)*(asin(z)-asin(a)) = 0
01871   return x-(*rusr)-std::sqrt(1.-x*x)*(std::asin(x)-std::asin(*rusr));
01872 }
01873 
01874 template <typename T> inline double
01875 McCormick<T>::_asinenv_dfunc
01876 ( const double x, const double*rusr, const int*iusr )
01877 {
01878   // f'(z) = z/sqrt(1-z^2)*(asin(z)-asin(a))
01879   return x/std::sqrt(1.-x*x)*(std::asin(x)-std::asin(*rusr));
01880 }
01881 
01882 template <typename T> inline double
01883 McCormick<T>::_newton
01884 ( const double x0, const double xL, const double xU, const puniv f,
01885   const puniv df, const double*rusr, const int*iusr )
01886 {
01887   double xk = std::max(xL,std::min(xU,x0));
01888   double fk = f(xk,rusr,iusr);
01889   
01890   for( unsigned int it=0; it<options.NEWTON_MAXIT; it++ ){
01891     if( std::fabs(fk) < options.NEWTON_TOL ) return xk;
01892     double dfk = df(xk,rusr,iusr);
01893     if( dfk == 0 ) throw Exceptions( Exceptions::NEWTON );
01894     if( isequal(xk,xL) && fk/dfk>0 ) return xk;
01895     if( isequal(xk,xU) && fk/dfk<0 ) return xk;
01896     xk = std::max(xL,std::min(xU,xk-fk/dfk));
01897     fk = f(xk,rusr,iusr);
01898   }
01899 
01900   throw Exceptions( Exceptions::NEWTON );
01901 }
01902 
01903 template <typename T> inline double
01904 McCormick<T>::_secant
01905 ( const double x0, const double x1, const double xL, const double xU,
01906   const puniv f, const double*rusr, const int*iusr )
01907 {
01908   double xkm = std::max(xL,std::min(xU,x0));
01909   double fkm = f(xkm,rusr,iusr);
01910   double xk = std::max(xL,std::min(xU,x1));
01911   
01912   for( unsigned int it=0; it<options.NEWTON_MAXIT; it++ ){
01913     double fk = f(xk,rusr,iusr);
01914     if( std::fabs(fk) < options.NEWTON_TOL ) return xk;
01915     double Bk = (fk-fkm)/(xk-xkm);
01916     if( Bk == 0 ) throw Exceptions( Exceptions::NEWTON );
01917     if( isequal(xk,xL) && fk/Bk>0 ) return xk;
01918     if( isequal(xk,xU) && fk/Bk<0 ) return xk;
01919     xkm = xk;
01920     fkm = fk;
01921     xk = std::max(xL,std::min(xU,xk-fk/Bk));
01922   }
01923 
01924   throw Exceptions( Exceptions::NEWTON );
01925 }
01926 
01928 
01929 template <typename T> inline McCormick<T>
01930 cut
01931 ( const McCormick<T>&MC )
01932 {
01933   McCormick<T> MC2( MC );
01934   return MC2.cut();
01935 }
01936 
01937 template <typename T> inline McCormick<T>
01938 operator+
01939 ( const McCormick<T>&MC )
01940 {
01941   McCormick<T> MC2( MC );
01942   return MC2;
01943 }
01944 
01945 template <typename T> inline McCormick<T>
01946 operator+
01947 ( const double a, const McCormick<T>&MC )
01948 {
01949   McCormick<T> MC2;
01950   MC2._sub( MC._nsub, MC._const );
01951   MC2._I = a + MC._I;
01952   MC2._cv = a + MC._cv;
01953   MC2._cc = a + MC._cc;
01954   for( unsigned int i=0; i<MC2._nsub; i++ ){
01955     MC2._cvsub[i] = MC._cvsub[i];
01956     MC2._ccsub[i] = MC._ccsub[i];
01957   }
01958   return MC2;
01959 }
01960 
01961 template <typename T> inline McCormick<T>
01962 operator+
01963 ( const McCormick<T>&MC, const double a )
01964 {
01965   return a + MC;
01966 }
01967 
01968 template <typename T> inline McCormick<T>
01969 operator+
01970 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
01971 {
01972   if( MC2._const ){
01973     McCormick<T> MC3;
01974     MC3._sub( MC1._nsub, MC1._const );
01975     return MC3._sum1( MC1, MC2 );
01976   }
01977   if( MC1._const ){
01978     McCormick<T> MC3;
01979     MC3._sub( MC2._nsub, MC2._const );
01980     return MC3._sum1( MC2, MC1 );
01981   } 
01982   if( MC1._nsub != MC2._nsub )
01983     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
01984   McCormick<T> MC3;
01985   MC3._sub( MC1._nsub, MC1._const||MC2._const );
01986   return MC3._sum2( MC1, MC2 );
01987 }
01988 
01989 template <typename T> inline McCormick<T>
01990 operator-
01991 ( const McCormick<T>&MC )
01992 {
01993   McCormick<T> MC2;
01994   MC2._sub( MC._nsub, MC._const );
01995   MC2._I = -MC._I;
01996   MC2._cv = -MC._cc;
01997   MC2._cc = -MC._cv;
01998   for( unsigned int i=0; i<MC2._nsub; i++ ){
01999     MC2._cvsub[i] = -MC._ccsub[i];
02000     MC2._ccsub[i] = -MC._cvsub[i];
02001   }
02002   return MC2;
02003 }
02004 
02005 template <typename T> inline McCormick<T>
02006 operator-
02007 ( const McCormick<T>&MC, const double a )
02008 {
02009   return MC + (-a);
02010 }
02011 
02012 template <typename T> inline McCormick<T>
02013 operator-
02014 ( const double a, const McCormick<T>&MC )
02015 {
02016   McCormick<T> MC2;
02017   MC2._sub( MC._nsub, MC._const );
02018   MC2._I = a - MC._I;
02019   MC2._cv = a - MC._cc;
02020   MC2._cc = a - MC._cv;
02021   for( unsigned int i=0; i<MC2._nsub; i++ ){
02022     MC2._cvsub[i] = -MC._ccsub[i];
02023     MC2._ccsub[i] = -MC._cvsub[i];
02024   }
02025   return MC2;
02026 }
02027 
02028 template <typename T> inline McCormick<T>
02029 operator-
02030 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
02031 {
02032   if( &MC1 == &MC2 ) return 0;
02033 
02034   if( MC2._const ){
02035     McCormick<T> MC3;
02036     MC3._sub( MC1._nsub, MC1._const );
02037     return MC3._sub1( MC1, MC2 );  
02038   }
02039   if( MC1._const ){
02040     McCormick<T> MC3;
02041     MC3._sub( MC2._nsub, MC2._const );
02042     return MC3._sub2( MC1, MC2 );
02043   }
02044   if( MC1._nsub != MC2._nsub )
02045     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02046   McCormick<T> MC3;
02047   MC3._sub( MC1._nsub, MC1._const||MC2._const );
02048   return MC3._sub3( MC1, MC2 );
02049 }
02050 
02051 template <typename T> inline McCormick<T>
02052 operator*
02053 ( const double a, const McCormick<T>&MC )
02054 {
02055   McCormick<T> MC2;
02056   MC2._sub( MC._nsub, MC._const );
02057   MC2._I = a * MC._I;
02058   if ( a >= 0 ){
02059     MC2._cv = a * MC._cv;
02060     MC2._cc = a * MC._cc;
02061     for( unsigned int i=0; i<MC2._nsub; i++ ){
02062       MC2._cvsub[i] = a * MC._cvsub[i];
02063       MC2._ccsub[i] = a * MC._ccsub[i];
02064     }
02065   }
02066   else{
02067     MC2._cv = a * MC._cc;
02068     MC2._cc = a * MC._cv;
02069     for( unsigned int i=0; i<MC2._nsub; i++ ){
02070       MC2._cvsub[i] = a * MC._ccsub[i];
02071       MC2._ccsub[i] = a * MC._cvsub[i];
02072     }
02073   }
02074   return MC2;
02075 }
02076 
02077 template <typename T> inline McCormick<T>
02078 operator*
02079 ( const McCormick<T>&MC, const double a )
02080 {  
02081   return a * MC;
02082 }
02083 
02084 template <typename T> inline McCormick<T>
02085 operator*
02086 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
02087 {
02088   if( &MC1 == &MC2 ) return sqr(MC1);
02089 
02090   bool thin1 = isequal( Op<T>::diam(MC1._I), 0. );
02091   bool thin2 = isequal( Op<T>::diam(MC2._I), 0. );
02092 
02093   if ( McCormick<T>::options.MVCOMP_USE && !(thin1||thin2) ){
02094     McCormick<T> MC3;
02095     if( MC2._const )
02096       MC3._sub( MC1._nsub, MC1._const );
02097     else if( MC1._const )
02098       MC3._sub( MC2._nsub, MC2._const );
02099     else if( MC1._nsub != MC2._nsub )
02100       throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02101     else
02102       MC3._sub( MC1._nsub, MC1._const||MC2._const );
02103 
02104     MC3._I = MC1._I * MC2._I;
02105     return MC3._mulMV( MC1, MC2 ).cut();
02106     //return thin1? MC3._mulMV( MC2, MC1 ).cut(): MC3._mulMV( MC1, MC2 ).cut();
02107   }
02108 
02109   if ( Op<T>::l(MC1._I) >= 0. ){
02110     if ( Op<T>::l(MC2._I) >= 0. ){
02111       if( MC2._const ){
02112         McCormick<T> MC3;
02113         MC3._sub( MC1._nsub, MC1._const );
02114         return MC3._mul1_u1pos_u2pos( MC1, MC2 ).cut();
02115       }
02116       if( MC1._const ){
02117         McCormick<T> MC3;
02118         MC3._sub( MC2._nsub, MC2._const );
02119         return MC3._mul1_u1pos_u2pos( MC2, MC1 ).cut();
02120       }
02121       if( MC1._nsub != MC2._nsub )
02122         throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02123       McCormick<T> MC3;
02124       MC3._sub( MC1._nsub, MC1._const||MC2._const );
02125       return MC3._mul2_u1pos_u2pos( MC1, MC2 ).cut();
02126     }
02127     if ( Op<T>::u(MC2._I) <= 0. ){
02128       return -( MC1 * (-MC2) );
02129     }
02130     if( MC2._const ){
02131       McCormick<T> MC3;
02132       MC3._sub( MC1._nsub, MC1._const );
02133       return MC3._mul1_u1pos_u2mix( MC1, MC2 ).cut();
02134     }
02135     if( MC1._const ){
02136       McCormick<T> MC3;
02137       MC3._sub( MC2._nsub, MC2._const );
02138       return MC3._mul2_u1pos_u2mix( MC1, MC2 ).cut();
02139     }
02140     if( MC1._nsub != MC2._nsub )
02141       throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02142     McCormick<T> MC3;
02143     MC3._sub( MC1._nsub, MC1._const||MC2._const );
02144     return MC3._mul3_u1pos_u2mix( MC1, MC2 ).cut();
02145   }
02146 
02147   if ( Op<T>::u(MC1._I) <= 0. ){
02148     if ( Op<T>::l(MC2._I) >= 0. ){
02149       return -( (-MC1) * MC2);
02150     }
02151     if ( Op<T>::u(MC2._I) <= 0. ){
02152       return (-MC1) * (-MC2);
02153     }
02154     return -( MC2 * (-MC1) );
02155   }
02156 
02157   if ( Op<T>::l(MC2._I) >= 0. ){
02158     return MC2 * MC1;
02159   }
02160   if ( Op<T>::u(MC2._I) <= 0. ){
02161     return -( (-MC2) * MC1 );
02162   }
02163   if( MC2._const ){
02164     McCormick<T> MC3;
02165     MC3._sub( MC1._nsub, MC1._const );
02166     return MC3._mul1_u1mix_u2mix( MC1, MC2 ).cut();
02167   }
02168   if( MC1._const ){
02169     McCormick<T> MC3;
02170     MC3._sub( MC2._nsub, MC2._const );
02171     return MC3._mul1_u1mix_u2mix( MC2, MC1 ).cut();
02172   }
02173   if( MC1._nsub != MC2._nsub )
02174     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02175   McCormick<T> MC3;
02176   MC3._sub( MC1._nsub, MC1._const||MC2._const );
02177   return MC3._mul2_u1mix_u2mix( MC1, MC2 ).cut();
02178 }
02179 
02180 template <typename T> inline McCormick<T>
02181 operator/
02182 ( const McCormick<T>&MC, const double a )
02183 {
02184   if ( isequal( a, 0. ))
02185     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::DIV );
02186   return (1./a) * MC;
02187 }
02188 
02189 template <typename T> inline McCormick<T>
02190 operator/
02191 ( const double a, const McCormick<T>&MC )
02192 {
02193   return a * inv( MC );
02194 }
02195 
02196 template <typename T> inline McCormick<T>
02197 operator/
02198 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
02199 {
02200   if( &MC1 == &MC2 ) return 1.;
02201 
02202   bool posorthant = ( Op<T>::l(MC1._I) >= 0. && Op<T>::l(MC2._I) > 0. );
02203 
02204   if ( McCormick<T>::options.MVCOMP_USE && posorthant){
02205     McCormick<T> MC3;
02206     if( MC2._const )
02207       MC3._sub( MC1._nsub, MC1._const );
02208     else if( MC1._const )
02209       MC3._sub( MC2._nsub, MC2._const );
02210     else if( MC1._nsub != MC2._nsub )
02211       throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02212     else
02213       MC3._sub( MC1._nsub, MC1._const||MC2._const );
02214 
02215     MC3._I = MC1._I / MC2._I;
02216 
02217     int imidcv1 = -1, imidcv2 = -1;
02218     double fmidcv1 = ( mid(MC1._cv, MC1._cc, Op<T>::l(MC1._I), imidcv1)
02219       + std::sqrt(Op<T>::l(MC1._I) * Op<T>::u(MC1._I)) )
02220       / ( std::sqrt(Op<T>::l(MC1._I)) + std::sqrt(Op<T>::u(MC1._I)) );
02221     double fmidcv2 = mid(MC2._cv, MC2._cc, Op<T>::u(MC2._I), imidcv2);
02222     MC3._cv = sqr(fmidcv1) / fmidcv2;
02223     for( unsigned int i=0; i<MC3._nsub; i++ )
02224       MC3._cvsub[i] = 2. * fmidcv1 / fmidcv2
02225         / ( std::sqrt(Op<T>::l(MC1._I)) + std::sqrt(Op<T>::u(MC1._I)) )
02226         * (MC1._const? 0.: mid( MC1._cvsub, MC1._ccsub, i, imidcv1 ))
02227         - sqr( fmidcv1 / fmidcv2 )
02228         * (MC2._const? 0.: mid( MC2._cvsub, MC2._ccsub, i, imidcv2 ));
02229 
02230     int imidcc1 = -1, imidcc2 = -1;
02231     double fmidcc1 = mid(MC1._cv, MC1._cc, Op<T>::l(MC1._I), imidcc1);
02232     double fmidcc2 = mid(MC2._cv, MC2._cc, Op<T>::u(MC2._I), imidcc2);
02233     double gcc1 = Op<T>::u(MC2._I) * fmidcc1 - Op<T>::l(MC1._I) * fmidcc2
02234                  + Op<T>::l(MC1._I) * Op<T>::l(MC2._I);
02235     double gcc2 = Op<T>::l(MC2._I) * fmidcc1 - Op<T>::u(MC1._I) * fmidcc2
02236                  + Op<T>::u(MC1._I) * Op<T>::u(MC2._I);
02237     if( gcc1 <= gcc2 ){
02238       MC3._cc = gcc1 / ( Op<T>::l(MC2._I) * Op<T>::u(MC2._I) );
02239       for( unsigned int i=0; i<MC3._nsub; i++ )
02240         MC3._ccsub[i] = 1. / Op<T>::l(MC2._I)
02241           * (MC1._const? 0.: mid( MC1._cvsub, MC1._ccsub, i, imidcc1 ))
02242           - Op<T>::l(MC1._I) / ( Op<T>::l(MC2._I) * Op<T>::u(MC2._I) )
02243           * (MC2._const? 0.: mid( MC2._cvsub, MC2._ccsub, i, imidcc2 ));
02244     }
02245     else{
02246       MC3._cc = gcc2 / ( Op<T>::l(MC2._I) * Op<T>::u(MC2._I) );
02247       for( unsigned int i=0; i<MC3._nsub; i++ )
02248         MC3._ccsub[i] = 1. / Op<T>::u(MC2._I)
02249           * (MC1._const? 0.: mid( MC1._cvsub, MC1._ccsub, i, imidcc1 ))
02250           - Op<T>::u(MC1._I) / ( Op<T>::l(MC2._I) * Op<T>::u(MC2._I) )
02251           * (MC2._const? 0.: mid( MC2._cvsub, MC2._ccsub, i, imidcc2 ));
02252     }
02253     return MC3.cut();
02254   }
02255 
02256   return MC1 * inv( MC2 );
02257 }
02258 
02259 template <typename T> inline McCormick<T>
02260 inv
02261 ( const McCormick<T>&MC )
02262 {
02263   if ( Op<T>::l(MC._I) <= 0. && Op<T>::u(MC._I) >= 0. )
02264     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::INV );
02265   McCormick<T> MC2;
02266   MC2._sub( MC._nsub, MC._const );
02267   MC2._I = Op<T>::inv( MC._I );
02268 
02269   if ( Op<T>::l(MC._I) > 0. ){
02270     { int imid = -1;
02271       double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02272       MC2._cv = 1./vmid;
02273       for( unsigned int i=0; i<MC2._nsub; i++ )
02274         MC2._cvsub[i] = - mid( MC._cvsub, MC._ccsub, i, imid )
02275           / ( vmid * vmid );
02276     }
02277     { int imid = -1;
02278       MC2._cc = 1. / Op<T>::l(MC._I) + 1. / Op<T>::u(MC._I) - mid( MC._cv, MC._cc,
02279         Op<T>::l(MC._I), imid ) / ( Op<T>::l(MC._I) * Op<T>::u(MC._I) );
02280       for( unsigned int i=0; i<MC2._nsub; i++ )
02281         MC2._ccsub[i] = - mid( MC._cvsub, MC._ccsub, i, imid )
02282           / ( Op<T>::l(MC._I) * Op<T>::u(MC._I) );
02283     }
02284   }
02285 
02286   else{
02287     { int imid = -1;
02288       MC2._cv = 1. / Op<T>::l(MC._I) + 1. / Op<T>::u(MC._I) - mid( MC._cv, MC._cc,
02289         Op<T>::u(MC._I), imid ) / ( Op<T>::l(MC._I) * Op<T>::u(MC._I) );
02290       for( unsigned int i=0; i<MC2._nsub; i++ )
02291         MC2._cvsub[i] = - mid( MC._cvsub, MC._ccsub, i, imid )
02292           / ( Op<T>::l(MC._I) * Op<T>::u(MC._I) );
02293     }
02294     { int imid = -1;
02295       double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid);
02296       MC2._cc = 1. / vmid;
02297       for( unsigned int i=0; i<MC2._nsub; i++ )
02298         MC2._ccsub[i] = - mid( MC._cvsub, MC._ccsub, i, imid )
02299           / ( vmid * vmid );
02300     }
02301   }
02302   
02303   return MC2.cut();
02304 }
02305 
02306 template <typename T> inline McCormick<T>
02307 sqr
02308 ( const McCormick<T>&MC )
02309 {
02310   McCormick<T> MC2;
02311   MC2._sub( MC._nsub, MC._const );
02312   MC2._I = Op<T>::sqr( MC._I );
02313   { int imid = -1;
02314     double zmin = mid( Op<T>::l(MC._I), Op<T>::u(MC._I), 0., imid );
02315     imid = -1;
02316     MC2._cv = mc::sqr( mid( MC._cv, MC._cc, zmin, imid ) );
02317     for( unsigned int i=0; i<MC2._nsub; i++ )
02318       MC2._cvsub[i] = 2 * mid( MC._cvsub, MC._ccsub, i, imid )
02319         * mid( MC._cv, MC._cc, zmin, imid );
02320   }
02321 
02322   { int imid = -1;
02323     double zmax = (mc::sqr( Op<T>::l(MC._I) )>mc::sqr( Op<T>::u(MC._I) )?
02324       Op<T>::l(MC._I): Op<T>::u(MC._I));
02325     double r = ( isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) )? 0.:
02326       ( mc::sqr( Op<T>::u(MC._I) ) - mc::sqr( Op<T>::l(MC._I) ) )
02327       / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) ) );
02328     MC2._cc = mc::sqr( Op<T>::l(MC._I) ) + r * ( mid( MC._cv, MC._cc, zmax,
02329       imid ) - Op<T>::l(MC._I) );
02330     for( unsigned int i=0; i<MC2._nsub; i++ )
02331       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02332   }
02333 
02334   return MC2.cut();
02335 }
02336 
02337 template <typename T> inline McCormick<T>
02338 exp
02339 ( const McCormick<T>&MC )
02340 {
02341   McCormick<T> MC2;
02342   MC2._sub( MC._nsub, MC._const );
02343   MC2._I = Op<T>::exp( MC._I );
02344 
02345   { int imid = -1;
02346     MC2._cv = std::exp( mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid ));
02347     for( unsigned int i=0; i<MC2._nsub; i++ )
02348       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * MC2._cv;
02349   }
02350 
02351   { int imid = -1;
02352     double r = 0.;
02353     if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02354       r = ( std::exp( Op<T>::u(MC._I) ) - std::exp( Op<T>::l(MC._I) ) )
02355         / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02356     MC2._cc = std::exp( Op<T>::u(MC._I) ) + r * ( mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid )
02357       - Op<T>::u(MC._I) );
02358     for( unsigned int i=0; i<MC2._nsub; i++ )
02359       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02360   }
02361 
02362   return MC2.cut();
02363 }
02364 
02365 template <typename T> inline McCormick<T>
02366 arh
02367 ( const McCormick<T>&MC, const double k )
02368 {
02369   if( Op<T>::l(MC._I) <= 0. || k < 0. || ( Op<T>::u(MC._I) > 0.5*k && Op<T>::l(MC._I) >= 0.5*k ) ){
02370     return exp( - k * inv( MC ) );
02371   }
02372 
02373   McCormick<T> MC2;
02374   MC2._sub( MC._nsub, MC._const );
02375   MC2._I = Op<T>::arh( MC._I, k );
02376 
02377   if ( Op<T>::u(MC._I) <= 0.5*k ){
02378     { int imid = -1;
02379       double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid );
02380       MC2._cv = std::exp( - k / vmid );
02381       for( unsigned int i=0; i<MC2._nsub; i++ )
02382         MC2._cvsub[i] = k / ( vmid * vmid ) * MC2._cv
02383           * mid( MC._cvsub, MC._ccsub, i, imid );
02384     }
02385     { int imid = -1;
02386       double r = 0.;
02387       if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02388         r = ( mc::arh( Op<T>::u(MC._I) ) - mc::arh( Op<T>::l(MC._I) ) )
02389           / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02390       MC2._cc = mc::arh( Op<T>::l(MC._I) ) + r * ( mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid )
02391         - Op<T>::l(MC._I) );
02392       for( unsigned int i=0; i<MC2._nsub; i++ )
02393         MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02394     }
02395     return MC2.cut();
02396   }
02397 
02398   else if ( Op<T>::l(MC._I) >= 0.5*k ){
02399     { int imid = -1;
02400       double r = 0.;
02401       if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02402         r = ( mc::arh( Op<T>::u(MC._I) ) - mc::arh( Op<T>::l(MC._I) ) )
02403           / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02404       MC2._cv = mc::arh( Op<T>::l(MC._I) ) + r * ( mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid )
02405         - Op<T>::l(MC._I) );
02406       for( unsigned int i=0; i<MC2._nsub; i++ )
02407         MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02408     }
02409     { int imid = -1;
02410       double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02411       MC2._cc = std::exp( - k / vmid );
02412       for( unsigned int i=0; i<MC2._nsub; i++ )
02413         MC2._ccsub[i] = k / ( vmid * vmid ) * MC2._cc
02414           * mid( MC._cvsub, MC._ccsub, i, imid );
02415     }
02416     return MC2.cut();
02417   }
02418 }
02419 
02420 template <typename T> inline McCormick<T>
02421 log
02422 ( const McCormick<T>&MC )
02423 {
02424   if ( Op<T>::l(MC._I) <= 0. )
02425     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::LOG );
02426   McCormick<T> MC2;
02427   MC2._sub( MC._nsub, MC._const );
02428   MC2._I = Op<T>::log( MC._I );
02429 
02430   { int imid = -1;
02431     double scal = 0.;
02432     if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02433       scal = ( std::log( Op<T>::u(MC._I) ) - std::log( Op<T>::l(MC._I) ) )
02434         / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02435     MC2._cv = std::log( Op<T>::l(MC._I) ) + scal * ( mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid )
02436       - Op<T>::l(MC._I) );
02437     for( unsigned int i=0; i<MC2._nsub; i++ )
02438       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * scal;
02439   }
02440 
02441   { int imid = -1;
02442     double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02443     MC2._cc = std::log( vmid );
02444     for( unsigned int i=0; i<MC2._nsub; i++ )
02445       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) / vmid;
02446   }
02447 
02448   return MC2.cut();
02449 }
02450 
02451 template <typename T> inline McCormick<T>
02452 xlog
02453 ( const McCormick<T>&MC )
02454 {
02455   if ( Op<T>::l(MC._I) <= 0. )
02456     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::LOG );
02457   McCormick<T> MC2;
02458   MC2._sub( MC._nsub, MC._const );
02459   MC2._I = Op<T>::xlog( MC._I );
02460 
02461   { int imid = -1;
02462     double zmin = mid( Op<T>::l(MC._I), Op<T>::u(MC._I), std::exp(-1.), imid );
02463     imid = -1;
02464     double vmid = mid( MC._cv, MC._cc, zmin, imid );
02465     MC2._cv = xlog( vmid );
02466     for( unsigned int i=0; i<MC2._nsub; i++ )
02467       MC2._cvsub[i] = (std::log( vmid ) + 1.) * mid( MC._cvsub, MC._ccsub,
02468         i, imid );
02469   }
02470 
02471   { int imid = -1;
02472     double zmax = ( xlog(Op<T>::u(MC._I))>=xlog(Op<T>::l(MC._I))? Op<T>::u(MC._I): Op<T>::l(MC._I) );
02473     double r = 0.;
02474     if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02475       r = ( xlog(Op<T>::u(MC._I)) - xlog(Op<T>::l(MC._I)) )
02476         / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02477     imid = -1;
02478     MC2._cc = xlog(Op<T>::l(MC._I)) + r * ( mid( MC._cv, MC._cc, zmax, imid ) - Op<T>::l(MC._I) );
02479     for( unsigned int i=0; i<MC2._nsub; i++ )
02480       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02481   }
02482 
02483   return MC2.cut();
02484 }
02485 
02486 template <typename T> inline McCormick<T>
02487 sqrt
02488 ( const McCormick<T>&MC )
02489 {
02490   if ( Op<T>::l(MC._I) < 0. )
02491     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SQRT );
02492   McCormick<T> MC2;
02493   MC2._sub( MC._nsub, MC._const );
02494   MC2._I = Op<T>::sqrt( MC._I );
02495 
02496   { double r = 0.;
02497     if( !isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) ))
02498       r = ( std::sqrt( Op<T>::u(MC._I) ) - std::sqrt( Op<T>::l(MC._I) ) )
02499         / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) );
02500     int imid = -1;
02501     double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid );
02502     MC2._cv = std::sqrt( Op<T>::l(MC._I) ) + r * ( vmid - Op<T>::l(MC._I) );
02503     for( unsigned int i=0; i<MC2._nsub; i++ )
02504       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02505   }
02506 
02507   { int imid = -1;
02508     double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02509     MC2._cc = std::sqrt( vmid );
02510     for( unsigned int i=0; i<MC2._nsub; i++ )
02511       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) / (2.*MC2._cc);
02512   }
02513 
02514   return MC2.cut();
02515 }
02516 
02517 template <typename T> inline McCormick<T>
02518 erfc
02519 ( const McCormick<T> &MC )
02520 {
02521   return ( 1. - erf( MC ) );
02522 }
02523 
02524 template <typename T> inline McCormick<T>
02525 erf
02526 ( const McCormick<T>&MC )
02527 {
02528   McCormick<T> MC2;
02529   MC2._sub( MC._nsub, MC._const );
02530   MC2._I = Op<T>::erf( MC._I );
02531 
02532   if( !McCormick<T>::options.NEWTON_USE ){
02533      MC2._cv = Op<T>::l(MC2._I);
02534      MC2._cc = Op<T>::u(MC2._I);
02535     for( unsigned int i=0; i<MC2._nsub; i++ ){
02536       MC2._cvsub[i] = MC2._ccsub[i] = 0.;
02537     }
02538     return MC2;
02539   }
02540 
02541   { int imid = -1;
02542     const double* cvenv = McCormick<T>::_erfcv( mid( MC._cv,
02543       MC._cc, Op<T>::l(MC._I), imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
02544     MC2._cv = cvenv[0];
02545     for( unsigned int i=0; i<MC2._nsub; i++ ){
02546       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * cvenv[1];
02547     }
02548   }
02549   { int imid = -1;
02550     const double* ccenv = McCormick<T>::_erfcc( mid( MC._cv,
02551       MC._cc, Op<T>::u(MC._I), imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
02552     MC2._cc = ccenv[0];
02553     for( unsigned int i=0; i<MC2._nsub; i++ ){
02554       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * ccenv[1];
02555     }
02556   }
02557   return MC2.cut();
02558 }
02559 
02560 template <typename T> inline McCormick<T>
02561 pow
02562 ( const McCormick<T>&MC, const int n )
02563 {
02564   if( n == 0 ){
02565     return 1.;
02566   }
02567 
02568   if( n == 1 ){
02569     return MC;
02570   }
02571 
02572   if( n >= 2 && !(n%2) ){ 
02573     McCormick<T> MC2;
02574     MC2._sub( MC._nsub, MC._const );
02575     MC2._I = Op<T>::pow( MC._I, n );
02576     { int imid = -1;
02577       double zmin = mid( Op<T>::l(MC._I), Op<T>::u(MC._I), 0., imid );
02578       imid = -1;
02579       MC2._cv = std::pow( mid( MC._cv, MC._cc, zmin, imid ), n );
02580       for( unsigned int i=0; i<MC2._nsub; i++ )
02581         MC2._cvsub[i] = n * mid( MC._cvsub, MC._ccsub, i, imid )
02582           * std::pow( mid( MC._cv, MC._cc, zmin, imid ), n-1 );
02583     }
02584     { int imid = -1;
02585       double zmax = (std::pow( Op<T>::l(MC._I), n )>std::pow( Op<T>::u(MC._I), n )?
02586         Op<T>::l(MC._I): Op<T>::u(MC._I));
02587       double r = ( isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) )? 0.: ( std::pow( Op<T>::u(MC._I),
02588         n ) - std::pow( Op<T>::l(MC._I), n ) ) / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) ) );
02589       MC2._cc = std::pow( Op<T>::l(MC._I), n ) + r * ( mid( MC._cv, MC._cc, zmax,
02590         imid ) - Op<T>::l(MC._I) );
02591       for( unsigned int i=0; i<MC2._nsub; i++ )
02592         MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02593     }
02594     return MC2.cut();
02595   }
02596 
02597   if( n >= 3 && McCormick<T>::options.NEWTON_USE ){
02598     McCormick<T> MC2;
02599     MC2._sub( MC._nsub, MC._const );
02600     MC2._I = Op<T>::pow( MC._I, n );
02601     { int imid = -1;
02602       const double* cvenv = McCormick<T>::_oddpowcv( mid( MC._cv,
02603         MC._cc, Op<T>::l(MC._I), imid ), n, Op<T>::l(MC._I), Op<T>::u(MC._I) );
02604       MC2._cv = cvenv[0];
02605       for( unsigned int i=0; i<MC2._nsub; i++ ){
02606         MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * cvenv[1];
02607       }
02608     }
02609     { int imid = -1;
02610       const double* ccenv = McCormick<T>::_oddpowcc( mid( MC._cv,
02611         MC._cc, Op<T>::u(MC._I), imid ), n, Op<T>::l(MC._I), Op<T>::u(MC._I) );
02612       MC2._cc = ccenv[0];
02613       for( unsigned int i=0; i<MC2._nsub; i++ ){
02614         MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * ccenv[1];
02615       }
02616     }
02617     return MC2.cut();
02618   }
02619 
02620   if( n >= 3 ){
02621     return pow( MC, n-1 ) * MC;
02622   }
02623 
02624   if( n == -1 ){
02625     return inv( MC );
02626   }
02627 
02628   if ( Op<T>::l(MC._I) <= 0. && Op<T>::u(MC._I) >= 0. )
02629     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::INV );
02630   McCormick<T> MC2;
02631   MC2._sub( MC._nsub, MC._const );
02632   MC2._I = Op<T>::pow( MC._I, n );
02633 
02634   if ( Op<T>::l(MC._I) > 0. ){
02635     { int imid = -1;
02636       double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02637       MC2._cv = std::pow( vmid, n );
02638       for( unsigned int i=0; i<MC2._nsub; i++ )
02639         MC2._cvsub[i] = n* mid( MC._cvsub, MC._ccsub, i, imid ) * std::pow( vmid, n-1 );
02640     }
02641     { double r = std::pow( Op<T>::l(MC._I), -n-1 ) + std::pow( Op<T>::u(MC._I), -n-1 );
02642       for( int i=1; i<=-n-2; i++ )
02643          r += std::pow( Op<T>::l(MC._I), i ) * std::pow( Op<T>::u(MC._I), -n-1-i );
02644       r /= - std::pow( Op<T>::l(MC._I), -n ) * std::pow( Op<T>::u(MC._I), -n );
02645       int imid = -1;
02646       double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid );
02647       MC2._cc = std::pow( Op<T>::l(MC._I), n ) + r * ( vmid - Op<T>::l(MC._I) );
02648       for( unsigned int i=0; i<MC2._nsub; i++ )
02649         MC2._ccsub[i] = r * mid( MC._cvsub, MC._ccsub, i, imid );
02650     }
02651     return MC2.cut();
02652   }
02653 
02654   if( (-n)%2 ){
02655     { double r = std::pow( Op<T>::l(MC._I), -n-1 ) + std::pow( Op<T>::u(MC._I), -n-1 );
02656       for( int i=1; i<=-n-2; i++ )
02657          r += std::pow( Op<T>::l(MC._I), i ) * std::pow( Op<T>::u(MC._I), -n-1-i );
02658       r /= - std::pow( Op<T>::l(MC._I), -n ) * std::pow( Op<T>::u(MC._I), -n );
02659       int imid = -1;
02660       double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02661       MC2._cv = std::pow( Op<T>::l(MC._I), n ) + r * ( vmid - Op<T>::l(MC._I) );
02662       for( unsigned int i=0; i<MC2._nsub; i++ )
02663         MC2._cvsub[i] = r * mid( MC._cvsub, MC._ccsub, i, imid );
02664     }
02665     { int imid = -1;
02666       double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid );
02667       MC2._cc = std::pow( vmid, n );
02668       for( unsigned int i=0; i<MC2._nsub; i++ )
02669         MC2._ccsub[i] = n* mid( MC._cvsub, MC._ccsub, i, imid ) * std::pow( vmid, n-1 );
02670     }
02671     return MC2.cut();
02672   }
02673 
02674   { int imid = -1;
02675     double vmid = mid( MC._cv, MC._cc, Op<T>::l(MC._I), imid );
02676     MC2._cv = std::pow( vmid, n );
02677     for( unsigned int i=0; i<MC2._nsub; i++ )
02678       MC2._cvsub[i] = n* mid( MC._cvsub, MC._ccsub, i, imid ) * std::pow( vmid, n-1 );
02679   }
02680     { double r = std::pow( Op<T>::l(MC._I), -n-1 ) + std::pow( Op<T>::u(MC._I), -n-1 );
02681       for( int i=1; i<=-n-2; i++ )
02682          r += std::pow( Op<T>::l(MC._I), i ) * std::pow( Op<T>::u(MC._I), -n-1-i );
02683       r /= - std::pow( Op<T>::l(MC._I), -n ) * std::pow( Op<T>::u(MC._I), -n );
02684     int imid = -1;
02685     double vmid = mid( MC._cv, MC._cc, Op<T>::u(MC._I), imid );
02686     MC2._cc = std::pow( Op<T>::l(MC._I), n ) + r * ( vmid - Op<T>::l(MC._I) );
02687     for( unsigned int i=0; i<MC2._nsub; i++ )
02688       MC2._ccsub[i] = r * mid( MC._cvsub, MC._ccsub, i, imid );
02689   }
02690   return MC2.cut();
02691 }
02692 
02693 template <typename T> inline McCormick<T>
02694 pow
02695 ( const McCormick<T> &MC, const double a )
02696 {
02697   return exp( a * log( MC ) );
02698 }
02699 
02700 template <typename T> inline McCormick<T>
02701 pow
02702 ( const McCormick<T> &MC1, const McCormick<T> &MC2 )
02703 {
02704   return exp( MC2 * log( MC1 ) );
02705 }
02706 
02707 template <typename T> inline McCormick<T>
02708 pow
02709 ( const double a, const McCormick<T> &MC )
02710 {
02711   return exp( MC * std::log( a ) );
02712 }
02713 
02714 template <typename T> inline McCormick<T>
02715 monomial
02716 (const unsigned int n, const McCormick<T>*MC, const int*k)
02717 {
02718   if( n == 0 ){
02719     return 1.;
02720   }
02721   if( n == 1 ){
02722     return pow( MC[0], k[0] );
02723   }
02724   return pow( MC[0], k[0] ) * monomial( n-1, MC+1, k+1 );
02725 }
02726 
02727 template <typename T> inline McCormick<T>
02728 fabs
02729 ( const McCormick<T> &MC )
02730 {
02731   McCormick<T> MC2;
02732   MC2._sub( MC._nsub, MC._const );
02733   MC2._I = Op<T>::fabs( MC._I );
02734 
02735   { int imid = -1;
02736     double zmin = mid( Op<T>::l(MC._I), Op<T>::u(MC._I), 0., imid );
02737     imid = -1;
02738     double vmid = mid( MC._cv, MC._cc, zmin, imid );
02739     MC2._cv = std::fabs( vmid );
02740     if( vmid >= 0. )
02741       for( unsigned int i=0; i<MC2._nsub; i++ )
02742         MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid );
02743     else
02744       for( unsigned int i=0; i<MC2._nsub; i++ )
02745         MC2._cvsub[i] = - mid( MC._cvsub, MC._ccsub, i, imid );
02746   }
02747 
02748   { int imid = -1;
02749     double zmax = (std::fabs( Op<T>::l(MC._I) )>std::fabs( Op<T>::u(MC._I) )? Op<T>::l(MC._I):
02750       Op<T>::u(MC._I));
02751     double r = ( isequal( Op<T>::l(MC._I), Op<T>::u(MC._I) )? 0.: ( std::fabs( Op<T>::u(MC._I) )
02752       - std::fabs( Op<T>::l(MC._I) ) ) / ( Op<T>::u(MC._I) - Op<T>::l(MC._I) ) );
02753     MC2._cc = std::fabs( Op<T>::l(MC._I) ) + r * ( mid( MC._cv, MC._cc, zmax, imid )
02754       - Op<T>::l(MC._I) );
02755     for( unsigned int i=0; i<MC2._nsub; i++ )
02756       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * r;
02757   }
02758 
02759   return MC2.cut();
02760 }
02761 
02762 template <typename T> inline McCormick<T>
02763 min
02764 ( const McCormick<T> &MC1, const McCormick<T> &MC2 )
02765 {
02766   if( MC1._nsub != MC2._nsub )
02767     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02768 
02769   McCormick<T> MC3;
02770   if( MC2._const )
02771     MC3._sub( MC1._nsub, MC1._const );
02772   else if( MC1._const )
02773     MC3._sub( MC2._nsub, MC2._const );
02774   else if( MC1._nsub != MC2._nsub )
02775     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02776   else
02777     MC3._sub( MC1._nsub, MC1._const||MC2._const );
02778   MC3._I = Op<T>::min( MC1._I, MC2._I );
02779 
02780   if( Op<T>::u(MC1._I) <= Op<T>::l(MC2._I) ){
02781     MC3._cv = MC1._cv;
02782     for( unsigned int i=0; i< MC3._nsub; i++ )
02783       MC3._cvsub[i] = (MC1._const? 0.: MC1._cvsub[i]);
02784   }
02785   else if( Op<T>::u(MC2._I) <= Op<T>::l(MC1._I) ){
02786     MC3._cv = MC2._cv;
02787     for( unsigned int i=0; i< MC3._nsub; i++ )
02788       MC3._cvsub[i] = (MC2._const? 0.: MC2._cvsub[i]);
02789   }
02790   else if( McCormick<T>::options.MVCOMP_USE ){
02791      double minL1L2 = std::min( Op<T>::l(MC1._I), Op<T>::l(MC2._I) );
02792      double minL1U2 = std::min( Op<T>::l(MC1._I), Op<T>::u(MC2._I) );
02793      double minU1L2 = std::min( Op<T>::u(MC1._I), Op<T>::l(MC2._I) );
02794      double minU1U2 = std::min( Op<T>::u(MC1._I), Op<T>::u(MC2._I) );
02795 
02796      bool thin1 = isequal( Op<T>::diam(MC1._I), 0. );
02797      double r11 = ( thin1?  0.: ( minU1L2 - minL1L2 ) / Op<T>::diam(MC1._I) );
02798      double r21 = ( thin1?  0.: ( minL1U2 - minU1U2 ) / Op<T>::diam(MC1._I) );
02799 
02800      bool thin2 = isequal( Op<T>::diam(MC2._I), 0. );
02801      double r12 = ( thin2?  0.: ( minL1U2 - minL1L2 ) / Op<T>::diam(MC2._I) );
02802      double r22 = ( thin2?  0.: ( minU1L2 - minU1U2 ) / Op<T>::diam(MC2._I) );
02803 
02804      double g1cv = minL1L2 + r11 * ( MC1._cv - Op<T>::l(MC1._I) )
02805                            + r12 * ( MC2._cv - Op<T>::l(MC2._I) );
02806      double g2cv = minU1U2 - r21 * ( MC1._cv - Op<T>::u(MC1._I) )
02807                            - r22 * ( MC2._cv - Op<T>::u(MC2._I) );
02808      if( g1cv >= g2cv ){
02809        MC3._cv = g1cv;
02810       for( unsigned int i=0; i< MC3._nsub; i++ )
02811         MC3._cvsub[i] = (MC1._const? 0.: r11*MC1._cvsub[i])
02812                       + (MC2._const? 0.: r12*MC2._cvsub[i]);
02813      }
02814      else{
02815        MC3._cv = g2cv;
02816       for( unsigned int i=0; i< MC3._nsub; i++ )
02817         MC3._cvsub[i] = - (MC1._const? 0.: r21*MC1._cvsub[i])
02818                         - (MC2._const? 0.: r22*MC2._cvsub[i]);
02819      }
02820   }
02821   else{
02822     McCormick<T> MCMin = 0.5*( MC1 + MC2 - fabs( MC2 - MC1 ) );
02823     MC3._cv = MCMin._cv;
02824     for( unsigned int i=0; i< MC3._nsub; i++ )
02825       MC3._cvsub[i] = MCMin._cvsub[i];
02826   }
02827 
02828   MC3._cc = std::min( MC1._cc, MC2._cc );
02829   for( unsigned int i=0; i< MC3._nsub; i++ )
02830     MC3._ccsub[i] = ( MC1._cc<=MC2._cc? (MC1._const? 0.: MC1._ccsub[i])
02831                                       : (MC2._const? 0.: MC2._ccsub[i]) );
02832 
02833   return  MC3.cut();
02834 }
02835 
02836 template <typename T> inline McCormick<T>
02837 max
02838 ( const McCormick<T> &MC1, const McCormick<T> &MC2 )
02839 {
02840   if( MC1._nsub != MC2._nsub )
02841     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02842 
02843   McCormick<T> MC3;
02844   if( MC2._const )
02845     MC3._sub( MC1._nsub, MC1._const );
02846   else if( MC1._const )
02847     MC3._sub( MC2._nsub, MC2._const );
02848   else if( MC1._nsub != MC2._nsub )
02849     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02850   else
02851     MC3._sub( MC1._nsub, MC1._const||MC2._const );
02852   MC3._I = Op<T>::max( MC1._I, MC2._I );
02853 
02854   if( Op<T>::u(MC1._I) <= Op<T>::l(MC2._I) ){
02855     MC3._cc = MC1._cc;
02856     for( unsigned int i=0; i< MC3._nsub; i++ )
02857       MC3._ccsub[i] = (MC1._const? 0.: MC1._ccsub[i]);
02858   }
02859   else if( Op<T>::u(MC2._I) <= Op<T>::l(MC1._I) ){
02860     MC3._cc = MC2._cc;
02861     for( unsigned int i=0; i< MC3._nsub; i++ )
02862       MC3._ccsub[i] = (MC2._const? 0.: MC2._ccsub[i]);
02863   }
02864   else if ( McCormick<T>::options.MVCOMP_USE ){
02865      double maxL1L2 = std::max( Op<T>::l(MC1._I), Op<T>::l(MC2._I) );
02866      double maxL1U2 = std::max( Op<T>::l(MC1._I), Op<T>::u(MC2._I) );
02867      double maxU1L2 = std::max( Op<T>::u(MC1._I), Op<T>::l(MC2._I) );
02868      double maxU1U2 = std::max( Op<T>::u(MC1._I), Op<T>::u(MC2._I) );
02869 
02870      bool thin1 = isequal( Op<T>::diam(MC1._I), 0. );
02871      double r11 = ( thin1?  0.: ( maxU1L2 - maxL1L2 ) / Op<T>::diam(MC1._I) );
02872      double r21 = ( thin1?  0.: ( maxL1U2 - maxU1U2 ) / Op<T>::diam(MC1._I) );
02873 
02874      bool thin2 = isequal( Op<T>::diam(MC2._I), 0. );
02875      double r12 = ( thin2?  0.: ( maxL1U2 - maxL1L2 ) / Op<T>::diam(MC2._I) );
02876      double r22 = ( thin2?  0.: ( maxU1L2 - maxU1U2 ) / Op<T>::diam(MC2._I) );
02877 
02878      double g1cc = maxL1L2 + r11 * ( MC1._cc - Op<T>::l(MC1._I) )
02879                            + r12 * ( MC2._cc - Op<T>::l(MC2._I) );
02880      double g2cc = maxU1U2 - r21 * ( MC1._cc - Op<T>::u(MC1._I) )
02881                            - r22 * ( MC2._cc - Op<T>::u(MC2._I) );
02882      if( g1cc <= g2cc ){
02883        MC3._cc = g1cc;
02884       for( unsigned int i=0; i< MC3._nsub; i++ )
02885         MC3._ccsub[i] = (MC1._const? 0.: r11*MC1._ccsub[i])
02886                       + (MC2._const? 0.: r12*MC2._ccsub[i]);
02887      }
02888      else{
02889        MC3._cc = g2cc;
02890       for( unsigned int i=0; i< MC3._nsub; i++ )
02891         MC3._ccsub[i] = - (MC1._const? 0.: r21*MC1._ccsub[i])
02892                         - (MC2._const? 0.: r22*MC2._ccsub[i]);
02893      }
02894   }
02895   else{
02896     McCormick<T> MCMax = 0.5*( MC1 + MC2 + fabs( MC1 - MC2 ) );
02897     MC3._cc = MCMax._cc;
02898     for( unsigned int i=0; i< MC3._nsub; i++ )
02899       MC3._ccsub[i] = MCMax._ccsub[i];
02900   }
02901 
02902   MC3._cv = std::max( MC1._cv, MC2._cv );
02903   for( unsigned int i=0; i< MC3._nsub; i++ )
02904     MC3._cvsub[i] = ( MC1._cv>=MC2._cv? (MC1._const? 0.: MC1._cvsub[i])
02905                                       : (MC2._const? 0.: MC2._cvsub[i]) );
02906 
02907   return  MC3.cut();
02908 }
02909 
02910 template <typename T> inline McCormick<T>
02911 min
02912 ( const unsigned int n, const McCormick<T>*MC )
02913 {
02914   McCormick<T> MC2( n==0 || !MC ? 0.: MC[0] );
02915   for( unsigned int i=1; i<n; i++ ) MC2 = min( MC2, MC[i] );
02916   return MC2;
02917 }
02918 
02919 template <typename T> inline McCormick<T>
02920 max
02921 ( const unsigned int n, const McCormick<T>*MC )
02922 {
02923   McCormick<T> MC2( n==0 || !MC ? 0.: MC[0] );
02924   for( unsigned int i=1; i<n; i++ ) MC2 = max( MC2, MC[i] );
02925   return MC2;
02926 }
02927 
02928 template <typename T> inline McCormick<T>
02929 fstep
02930 ( const McCormick<T> &MC )
02931 {
02932   McCormick<T> MC2;
02933   MC2._sub( MC._nsub, MC._const );
02934   if( Op<T>::l( MC._I ) >= 0 )
02935     MC2._I = 1.;
02936   else if( Op<T>::u( MC._I ) < 0 )
02937     MC2._I = 0.;
02938   else
02939     MC2._I = Op<T>::zeroone();
02940   
02941   { int imid = -1;
02942     double zmin = Op<T>::l(MC._I);
02943     double vmid = mid( MC._cv, MC._cc, zmin, imid );
02944     const double* cvenv = McCormick<T>::_stepcv( vmid, Op<T>::l(MC._I),
02945       Op<T>::u(MC._I) );
02946     MC2._cv = cvenv[0];
02947     for( unsigned int i=0; i<MC2._nsub; i++ )
02948       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid )*cvenv[1];
02949   }
02950   
02951   { int imid = -1;
02952     double zmax = Op<T>::u(MC._I);
02953     double vmid = mid( MC._cv, MC._cc, zmax, imid );
02954     const double* ccenv = McCormick<T>::_stepcc( vmid, Op<T>::l(MC._I),
02955       Op<T>::u(MC._I) );
02956     MC2._cc = ccenv[0];
02957     for( unsigned int i=0; i<MC2._nsub; i++ )
02958       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid )*ccenv[1];
02959   }
02960 
02961   return  MC2.cut();
02962 }
02963 
02964 template <typename T> inline McCormick<T>
02965 bstep
02966 ( const McCormick<T> &MC )
02967 {
02968   return fstep( -MC );  
02969 }
02970 
02971 template <typename T> inline McCormick<T>
02972 ltcond
02973 ( const T &I0, const McCormick<T> &MC1, const McCormick<T> &MC2 )
02974 {
02975   if( Op<T>::u( I0 ) < 0. )       return MC1;
02976   else if( Op<T>::l( I0 ) >= 0. ) return MC2;
02977 
02978   McCormick<T> MC3;
02979   if( MC2._const )
02980     MC3._sub( MC1._nsub, MC1._const );
02981   else if( MC1._const )
02982     MC3._sub( MC2._nsub, MC2._const );
02983   else if( MC1._nsub != MC2._nsub )
02984     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
02985   else
02986     MC3._sub( MC1._nsub, MC1._const||MC2._const );
02987 
02988   MC3._I = Op<T>::hull( MC1._I, MC2._I );
02989   McCormick<T> MCMin  = 0.5*( MC1 + MC2 - fabs( MC2 - MC1 ) );
02990   McCormick<T> MCMax  = 0.5*( MC1 + MC2 + fabs( MC1 - MC2 ) );
02991   MC3._cv = MCMin._cv;
02992   MC3._cc = MCMax._cc;
02993   for( unsigned int i=0; i< MC3._nsub; i++ ){
02994     MC3._cvsub[i] = MCMin._cvsub[i];
02995     MC3._ccsub[i] = MCMax._ccsub[i];
02996   }    
02997   return  MC3.cut();
02998 }
02999 
03000 template <typename T> inline McCormick<T>
03001 ltcond
03002 ( const McCormick<T> &MC0, const McCormick<T> &MC1, const McCormick<T> &MC2 )
03003 {
03004   McCormick<T> MC3 = ltcond( MC0._I, MC1, MC2 );
03005   McCormick<T> MCStep = fstep(-MC0)*MC1 + fstep(MC0)*MC2;
03006   if( MCStep._cv > MC3._cv ){
03007     MC3._cv = MCStep._cv;
03008     for( unsigned int i=0; i< MC3._nsub; i++ )
03009       MC3._cvsub[i] = MCStep._cvsub[i];
03010   }    
03011   if( MCStep._cc < MC3._cc ){
03012     MC3._cc = MCStep._cc;
03013     for( unsigned int i=0; i< MC3._nsub; i++ )
03014       MC3._ccsub[i] = MCStep._ccsub[i];
03015   }    
03016   return  MC3.cut();
03017 }
03018 
03019 template <typename T> inline McCormick<T>
03020 gtcond
03021 ( const T &I0, const McCormick<T> &MC1, const McCormick<T> &MC2 )
03022 {
03023   return ltcond( -I0, MC1, MC2 );
03024 }
03025 template <typename T> inline McCormick<T>
03026 gtcond
03027 ( const McCormick<T> &MC0, const McCormick<T> &MC1, const McCormick<T> &MC2 )
03028 {
03029   return ltcond( -MC0, MC1, MC2 );
03030 }
03031 
03032 template <typename T> inline McCormick<T>
03033 cos
03034 ( const McCormick<T> &MC )
03035 {
03036   McCormick<T> MC2;
03037   MC2._sub( MC._nsub, MC._const );
03038   MC2._I = Op<T>::cos( MC._I );
03039 
03040   if( !McCormick<T>::options.NEWTON_USE ){
03041      MC2._cv = Op<T>::l(MC2._I);
03042      MC2._cc = Op<T>::u(MC2._I);
03043     for( unsigned int i=0; i<MC2._nsub; i++ ){
03044       MC2._cvsub[i] = MC2._ccsub[i] = 0.;
03045     }
03046     return MC2;
03047   }
03048   
03049   double*argbnd = McCormick<T>::_cosarg( Op<T>::l(MC._I), Op<T>::u(MC._I) );
03050   { int imid = -1;
03051     const double* cvenv = McCormick<T>::_coscv( mid( MC._cv,
03052       MC._cc, argbnd[0], imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
03053     std::cout << "imid: " << imid << "  " << MC._cv << "  " << MC._cc
03054               << "  " << argbnd[0] << std::endl;
03055     MC2._cv = cvenv[0];
03056     for( unsigned int i=0; i< MC2._nsub; i++ ){
03057        MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * cvenv[1];
03058     }
03059   }
03060   { int imid = -1;
03061     const double* ccenv = McCormick<T>::_coscc( mid( MC._cv,
03062       MC._cc, argbnd[1], imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
03063      MC2._cc = ccenv[0];
03064     for( unsigned int i=0; i< MC2._nsub; i++ ){
03065        MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * ccenv[1];
03066     }
03067   }
03068   return  MC2.cut();
03069 }
03070 
03071 template <typename T> inline McCormick<T>
03072 sin
03073 ( const McCormick<T> &MC )
03074 {
03075   return cos( MC - PI/2. );
03076 }
03077 
03078 template <typename T> inline McCormick<T>
03079 asin
03080 ( const McCormick<T> &MC )
03081 {
03082   if( !McCormick<T>::options.NEWTON_USE )
03083     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::ASIN );
03084   McCormick<T> MC2;
03085   MC2._sub( MC._nsub, MC._const );
03086   MC2._I = Op<T>::asin( MC._I );
03087   { int imid = -1;
03088     const double* cvenv = McCormick<T>::_asincv( mid( MC._cv,
03089       MC._cc, Op<T>::l(MC._I), imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
03090     MC2._cv = cvenv[0];
03091     for( unsigned int i=0; i<MC2._nsub; i++ ){
03092       MC2._cvsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * cvenv[1];
03093     }
03094   }
03095   { int imid = -1;
03096     const double* ccenv = McCormick<T>::_asincc( mid( MC._cv,
03097       MC._cc, Op<T>::u(MC._I), imid ), Op<T>::l(MC._I), Op<T>::u(MC._I) );
03098     MC2._cc = ccenv[0];
03099     for( unsigned int i=0; i<MC2._nsub; i++ ){
03100       MC2._ccsub[i] = mid( MC._cvsub, MC._ccsub, i, imid ) * ccenv[1];
03101     }
03102   }
03103   return MC2.cut();
03104 }
03105 
03106 template <typename T> inline McCormick<T>
03107 acos
03108 ( const McCormick<T> &MC )
03109 {
03110   return asin( -MC ) + PI/2.;
03111 }
03112 
03113 template <typename T> inline McCormick<T>
03114 tan
03115 ( const McCormick<T> &MC )
03116 {
03117   return sin(MC) / cos(MC);
03118 }
03119 
03120 template <typename T> inline McCormick<T>
03121 atan
03122 ( const McCormick<T> &MC )
03123 {
03124   return asin( MC / sqrt(1+sqr(MC)) );
03125 }
03126 
03127 template <typename T> inline std::ostream&
03128 operator<<
03129 ( std::ostream&out, const McCormick<T>&MC)
03130 {
03131   const int iprec = 5;
03132   out << std::scientific << std::setprecision(iprec) << std::right
03133       << "[ " << std::setw(iprec+7) << MC.l() << " : "
03134               << std::setw(iprec+7) << MC.u()
03135       << " ] [ "  << std::setw(iprec+7) << MC.cv() << " : "
03136                   << std::setw(iprec+7) << MC.cc() << " ]";
03137   if( MC._nsub ){
03138     out << " [ (";
03139     for( unsigned int i=0; i<MC._nsub-1; i++ )
03140       out << std::setw(iprec+7) << MC.cvsub(i) << ",";
03141     out << std::setw(iprec+7) << MC.cvsub(MC._nsub-1) << ") : (";
03142     for( unsigned int i=0; i<MC._nsub-1; i++ )
03143       out << std::setw(iprec+7) << MC.ccsub(i) << ",";
03144     out << std::setw(iprec+7) << MC.ccsub(MC._nsub-1) << ") ]";
03145   }
03146   return out;
03147 }
03148 
03149 template <typename T> inline bool
03150 inter
03151 ( McCormick<T>&XIY, const McCormick<T>&X, const McCormick<T>&Y )
03152 {
03153   if( !Op<T>::inter( XIY._I, X._I, Y._I ) ) return false;
03154   //if( X._cv > Y._cc || Y._cv > X._cc ) return false;
03155 
03156   if( !X._const && !Y._const && (X._nsub != Y._nsub) )
03157     throw typename McCormick<T>::Exceptions( McCormick<T>::Exceptions::SUB );
03158   else if( !X._const )
03159     XIY._sub( X._nsub, X._const );
03160   else
03161     XIY._sub( Y._nsub, Y._const );
03162 
03163   if( Y._cv > X._cv ){
03164     XIY._cv = Y._cv;
03165     for( unsigned int is=0; is<XIY._nsub; is++ )
03166       XIY._cvsub[is] = ( Y._const? 0.: Y._cvsub[is] );
03167   }
03168   else{
03169     XIY._cv = X._cv;
03170     for( unsigned int is=0; is<XIY._nsub; is++ )
03171       XIY._cvsub[is] = ( X._const? 0.: X._cvsub[is] );
03172   }
03173   if( Y._cc < X._cc ){
03174     XIY._cc = Y._cc;
03175     for( unsigned int is=0; is<XIY._nsub; is++ )
03176       XIY._ccsub[is] = ( Y._const? 0.: Y._ccsub[is] );
03177   }
03178   else{
03179     XIY._cc = X._cc;
03180     for( unsigned int is=0; is<XIY._nsub; is++ )
03181       XIY._ccsub[is] = ( X._const? 0.: X._ccsub[is] );
03182   }
03183   return true;
03184 }
03185 
03186 template <typename T> inline bool
03187 operator==
03188 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03189 {
03190   return( Op<T>::eq(MC1._I,MC2._I) && MC1._cv == MC2._cv && MC1._cc == MC2._cc );
03191 }
03192 
03193 template <typename T> inline bool
03194 operator!=
03195 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03196 {
03197   return( Op<T>::ne(MC1._I,MC2._I) || MC1._cv != MC2._cv || MC1._cc != MC2._cc );
03198 }
03199 
03200 template <typename T> inline bool
03201 operator<=
03202 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03203 {
03204   return( Op<T>::le(MC1._I,MC2._I) && MC1._cv >= MC2._cv && MC1._cc <= MC2._cc );
03205 }
03206 
03207 template <typename T> inline bool
03208 operator>=
03209 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03210 {
03211   return( Op<T>::ge(MC1._I,MC2._I) && MC1._cv <= MC2._cv && MC1._cc >= MC2._cc );
03212 }
03213 
03214 template <typename T> inline bool
03215 operator<
03216 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03217 {
03218   return( Op<T>::lt(MC1._I,MC2._I) && MC1._cv > MC2._cv && MC1._cc < MC2._cc );
03219 }
03220 
03221 template <typename T> inline bool
03222 operator>
03223 ( const McCormick<T>&MC1, const McCormick<T>&MC2 )
03224 {
03225   return( Op<T>::gt(MC1._I,MC2._I) && MC1._cv < MC2._cv && MC1._cc > MC2._cc );
03226 }
03227 
03228 template <typename T> typename McCormick<T>::Options McCormick<T>::options;
03229 
03230 } // namespace mc
03231 
03232 
03233 #include "mcop.h"
03234 
03235 namespace mc
03236 {
03237 
03239 template <> template<typename T> struct Op< mc::McCormick<T> >
03240 {
03241   typedef mc::McCormick<T> MC;
03242   static MC point( const double c ) { return MC(c); }
03243   static MC zeroone() { return MC( mc::Op<T>::zeroone() ); }
03244   static void I(MC& x, const MC&y) { x = y; }
03245   static double l(const MC& x) { return x.l(); }
03246   static double u(const MC& x) { return x.u(); }
03247   static double abs (const MC& x) { return mc::Op<T>::abs(x.I());  }
03248   static double mid (const MC& x) { return mc::Op<T>::mid(x.I());  }
03249   static double diam(const MC& x) { return mc::Op<T>::diam(x.I()); }
03250   static MC inv (const MC& x) { return mc::inv(x);  }
03251   static MC sqr (const MC& x) { return mc::sqr(x);  }
03252   static MC sqrt(const MC& x) { return mc::sqrt(x); }
03253   static MC log (const MC& x) { return mc::log(x);  }
03254   static MC xlog(const MC& x) { return mc::xlog(x); }
03255   static MC fabs(const MC& x) { return mc::fabs(x); }
03256   static MC exp (const MC& x) { return mc::exp(x);  }
03257   static MC sin (const MC& x) { return mc::sin(x);  }
03258   static MC cos (const MC& x) { return mc::cos(x);  }
03259   static MC tan (const MC& x) { return mc::tan(x);  }
03260   static MC asin(const MC& x) { return mc::asin(x); }
03261   static MC acos(const MC& x) { return mc::acos(x); }
03262   static MC atan(const MC& x) { return mc::atan(x); }
03263   static MC erf (const MC& x) { return mc::erf(x);  }
03264   static MC erfc(const MC& x) { return mc::erfc(x); }
03265   static MC hull(const MC& x, const MC& y) { return mc::Op<T>::hull(x.I(),y.I()); }
03266   static MC min (const MC& x, const MC& y) { return mc::min(x,y);  }
03267   static MC max (const MC& x, const MC& y) { return mc::max(x,y);  }
03268   static MC arh (const MC& x, const double k) { return mc::arh(x,k); }
03269   template <typename X, typename Y> static MC pow(const X& x, const Y& y) { return mc::pow(x,y); }
03270   static MC monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); }
03271   static bool inter(MC& xIy, const MC& x, const MC& y) { return mc::inter(xIy,x,y); }
03272   static bool eq(const MC& x, const MC& y) { return x==y; }
03273   static bool ne(const MC& x, const MC& y) { return x!=y; }
03274   static bool lt(const MC& x, const MC& y) { return x<y;  }
03275   static bool le(const MC& x, const MC& y) { return x<=y; }
03276   static bool gt(const MC& x, const MC& y) { return x>y;  }
03277   static bool ge(const MC& x, const MC& y) { return x>=y; }
03278 };
03279 
03280 } // namespace mc
03281 
03282 #endif