QGpCoreTools/RootSolver.h
Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 **  This file is part of QGpCoreTools.
00004 **
00005 **  This library is free software; you can redistribute it and/or
00006 **  modify it under the terms of the GNU Lesser General Public
00007 **  License as published by the Free Software Foundation; either
00008 **  version 2.1 of the License, or (at your option) any later version.
00009 **
00010 **  This file is distributed in the hope that it will be useful, but WITHOUT
00011 **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 **  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00013 **  License for more details.
00014 **
00015 **  You should have received a copy of the GNU Lesser General Public
00016 **  License along with this library; if not, write to the Free Software
00017 **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 **
00019 **  See http://www.geopsy.org for more information.
00020 **
00021 **  Created : 2004-04-28
00022 **  Authors :
00023 **    Marc Wathelet
00024 **    Marc Wathelet (ULg, Liège, Belgium)
00025 **    Marc Wathelet (LGIT, Grenoble, France)
00026 **
00027 ***************************************************************************/
00028 
00029 #ifndef ROOTSOLVER_H
00030 #define ROOTSOLVER_H
00031 
00032 #include "QGpCoreToolsDLLExport.h"
00033 #include "CoreApplication.h"
00034 
00035 namespace QGpCoreTools {
00036 
00037 #define ROOTSOLVER_MAX_ITERATIONS 500
00038 
00039 template <class RealType, class FunctionClass>
00040 class QGPCORETOOLS_EXPORT RootSolverTemplate
00041 {
00042 public:
00043   RootSolverTemplate(FunctionClass * values);
00044 
00045   FunctionClass * values() {return _values;}
00046 
00047   RealType searchStep() const {return _dx;}
00048   void setAbsoluteStep(RealType step) {_dx=fabs(step); _dxType=Absolute;}
00049   void setRelativeStep(RealType step) {_dx=fabs(step); _dxType=Relative;}
00050 
00051   void setPolarity(RealType x0);
00052   void inversePolarity() {_polarity=-_polarity;}
00053 
00054   RealType precision() const {return _precision;}
00055   void setPrecision(RealType prec) {_precision=prec;}
00056 
00057   inline bool searchUp(RealType from, RealType to);
00058   inline bool searchDown(RealType from, RealType to);
00059 
00060   inline bool searchUp(RealType from, RealType min, RealType max);
00061   inline bool searchDown(RealType from, RealType min, RealType max);
00062 
00063   inline bool searchUpSlope(RealType from, RealType min, RealType max);
00064   inline bool searchDownSlope(RealType from, RealType min, RealType max);
00065 
00066   bool setInterval(RealType min, RealType max);
00067 
00068   void halving();
00069   void newtonRaphson();
00070   void neville();
00071 
00072   RealType lower() const {return _x1<_x2 ? _x1 : _x2;}
00073   RealType upper() const {return _x1<_x2 ? _x2 : _x1;}
00074 private:
00075   FunctionClass * _values;
00076   RealType _x1, _x2, _y1, _y2;
00077 
00078   enum StepType {Absolute, Relative};
00079   StepType _dxType;
00080   RealType _dx;
00081   RealType _polarity;
00082   RealType _precision;
00083 
00084   template <class Iterator>
00085     bool search(RealType from, RealType to, const Iterator& it);
00086   template <class Iterator>
00087     bool search(RealType from, RealType min, RealType max, const Iterator& it);
00088   template <class Iterator>
00089     bool searchSlope(RealType from, RealType min, RealType max, const Iterator& it);
00090   static inline bool isFound(RealType y1, RealType y2);
00091 
00092   class AbsoluteUpIterator
00093   {
00094   public:
00095     AbsoluteUpIterator(RealType dx) {_dx=dx;}
00096     RealType next(RealType x) const {return x+_dx;}
00097     static bool atEnd(RealType x, RealType to) {return x >= to;}
00098     static bool atEnd(RealType x, RealType /*min*/, RealType max) {return x >= max;}
00099     static RealType begin(RealType min, RealType /*max*/ ) {return min;}
00100     static RealType end(RealType /*min*/, RealType max) {return max;}
00101   private:
00102     RealType _dx;
00103   };
00104 
00105   class AbsoluteDownIterator
00106   {
00107   public:
00108     AbsoluteDownIterator(RealType dx) {_dx=dx;}
00109     RealType next(RealType x) const {return x-_dx;}
00110     static bool atEnd(RealType x, RealType to) {return x <= to;}
00111     static bool atEnd(RealType x, RealType min, RealType /*max*/ ) {return x <= min;}
00112     static RealType begin(RealType /*min*/, RealType max) {return max;}
00113     static RealType end(RealType min, RealType /*max*/ ) {return min;}
00114   private:
00115     RealType _dx;
00116   };
00117 
00118   class RelativeUpIterator
00119   {
00120   public:
00121     RelativeUpIterator(RealType dx) {_dx=1.0+dx;}
00122     RealType next(RealType x) const {return x*_dx;}
00123     static bool atEnd(RealType x, RealType to) {return x >= to;}
00124     static bool atEnd(RealType x, RealType /*min*/, RealType max) {return x >= max;}
00125     static RealType begin(RealType min, RealType /*max*/ ) {return min;}
00126     static RealType end(RealType /*min*/, RealType max) {return max;}
00127   private:
00128     RealType _dx;
00129   };
00130 
00131   class RelativeDownIterator
00132   {
00133   public:
00134     RelativeDownIterator(RealType dx) {_dx=1.0-dx;}
00135     RealType next(RealType x) const {return x*_dx;}
00136     static bool atEnd(RealType x, RealType to) {return x <= to;}
00137     static bool atEnd(RealType x, RealType min, RealType /*max*/ ) {return x <= min;}
00138     static RealType begin(RealType /*min*/, RealType max) {return max;}
00139     static RealType end(RealType min, RealType /*max*/ ) {return min;}
00140   private:
00141     RealType _dx;
00142   };
00143 };
00144 
00145 template <class RealType, class FunctionClass>
00146 inline bool RootSolverTemplate<RealType, FunctionClass>
00147 ::searchDown(RealType from, RealType min, RealType max)
00148 {
00149   if(_dxType==Absolute) {
00150     AbsoluteDownIterator it(_dx);
00151     return search(from, min, max, it);
00152   } else {
00153     RelativeDownIterator it(_dx);
00154     return search(from, min, max, it);
00155   }
00156 }
00157 
00158 template <class RealType, class FunctionClass>
00159 inline bool RootSolverTemplate<RealType, FunctionClass>
00160 ::searchUp(RealType from, RealType min, RealType max)
00161 {
00162   if(_dxType==Absolute) {
00163     AbsoluteUpIterator it(_dx);
00164     return search(from, min, max, it);
00165   } else {
00166     RelativeUpIterator it(_dx);
00167     return search(from, min, max, it);
00168   }
00169 }
00170 
00171 template <class RealType, class FunctionClass>
00172 inline bool RootSolverTemplate<RealType, FunctionClass>
00173 ::searchDownSlope(RealType from, RealType min, RealType max)
00174 {
00175   if(_dxType==Absolute) {
00176     AbsoluteDownIterator it(_dx);
00177     return searchSlope(from, min, max, it);
00178   } else {
00179     RelativeDownIterator it(_dx);
00180     return searchSlope(from, min, max, it);
00181   }
00182 }
00183 
00184 template <class RealType, class FunctionClass>
00185 inline bool RootSolverTemplate<RealType, FunctionClass>
00186 ::searchUpSlope(RealType from, RealType min, RealType max)
00187 {
00188   if(_dxType==Absolute) {
00189     AbsoluteUpIterator it(_dx);
00190     return searchSlope(from, min, max, it);
00191   } else {
00192     RelativeUpIterator it(_dx);
00193     return searchSlope(from, min, max, it);
00194   }
00195 }
00196 
00197 template <class RealType, class FunctionClass>
00198 inline bool RootSolverTemplate<RealType, FunctionClass>
00199 ::searchUp(RealType from, RealType to)
00200 {
00201   if(from>to) return false;
00202   if(_dxType==Absolute) {
00203     AbsoluteUpIterator it(_dx);
00204     return search(from, to, it);
00205   } else {
00206     RelativeUpIterator it(_dx);
00207     return search(from, to, it);
00208   }
00209 }
00210 
00211 template <class RealType, class FunctionClass>
00212 inline bool RootSolverTemplate<RealType, FunctionClass>
00213 ::searchDown(RealType from, RealType to)
00214 {
00215   if(from>to) return false;
00216   if(_dxType==Absolute) {
00217     AbsoluteDownIterator it(_dx);
00218     return search(from, to, it);
00219   } else {
00220     RelativeDownIterator it(_dx);
00221     return search(from, to, it);
00222   }
00223 }
00224 
00225 template <class RealType, class FunctionClass>
00226 inline bool RootSolverTemplate<RealType, FunctionClass>::isFound(RealType y1, RealType y2)
00227 {
00228   return (y1<0.0 && y2>0.0) || (y1>0.0 && y2<0.0);
00229 }
00230 
00231 // Usual precision
00232 template <class FunctionClass>
00233 class QGPCORETOOLS_EXPORT RootSolver: public RootSolverTemplate<double, FunctionClass>
00234 {
00235 public:
00236   RootSolver(FunctionClass * values) :
00237     RootSolverTemplate<double, FunctionClass>(values) {}
00238 };
00239 
00240 #ifdef BIGNUM
00241 // Arbitrary precision for special cases or experimental purposes
00242 template <class FunctionClass>
00243 class QGPCORETOOLS_EXPORT RootSolverBigNum: public RootSolverTemplate<mp_real, FunctionClass>
00244 {
00245 public:
00246   RootSolverBigNum(FunctionClass * values) :
00247     RootSolverTemplate<mp_real, FunctionClass>(values) {}
00248 };
00249 #endif
00250 
00251 template <class RealType, class FunctionClass>
00252 RootSolverTemplate<RealType, FunctionClass>::
00253 RootSolverTemplate(FunctionClass * values)
00254 {
00255   _values=values;
00256   _dxType=Relative;
00257   _dx=0.1;
00258   _polarity=1.0;
00259   _precision=1e-7;
00260 }
00261 
00262 template <class RealType, class FunctionClass>
00263 void RootSolverTemplate<RealType, FunctionClass>::
00264 setPolarity(RealType x0)
00265 {
00266   _polarity=_values->y(x0);
00267 }
00268 
00269 template <class RealType, class FunctionClass> template <class Iterator>
00270 bool RootSolverTemplate<RealType, FunctionClass>::
00271 search(RealType from, RealType to, const Iterator& it)
00272 {
00273   //#define searchFromTo
00274 #ifdef searchFromTo
00275   printf( "RootSolverTemplate::searchFromTo\n" );
00276 #endif
00277   _x1=from;
00278   _y1=_values->y(_x1);
00279   _x2=it.next(_x1);
00280   while( ! it.atEnd(_x2, to)) {
00281     _y2=_values->y(_x2);
00282 #ifdef searchFromTo
00283     printSearchDebug();
00284 #endif
00285     if(isFound(_y1, _y2)) {
00286       return true;
00287     } else {
00288       _x1=_x2;
00289       _y1=_y2;
00290       _x2=it.next(_x1);
00291     }
00292   }
00293 
00294   // reaching the maximum slowness, tests if there's a last root
00295 #ifdef searchFromTo
00296   printSearchDebug();
00297 #endif
00298   if( ! it.atEnd(_x1, to)) {
00299     _x2=to;
00300     _y2=_values->y(_x2);
00301     if(isFound(_y1, _y2)) {
00302       return true;
00303     }
00304   }
00305   return false;
00306 }
00307 
00308 template <class RealType, class FunctionClass> template <class Iterator>
00309 bool RootSolverTemplate<RealType, FunctionClass>::
00310 search(RealType from, RealType min, RealType max, const Iterator& it)
00311 {
00312   //#define searchMinMax
00313 #ifdef searchMinMax
00314   printf( "RootSolverTemplate::searchMinMax\n" );
00315   printf( "Current polarity %lg\n", ::toDouble(_polarity));
00316 #endif
00317   // Find the search direction by looking at polarity
00318   _x1=from;
00319   _y1=_values->y(_x1);
00320   _y2=_polarity;
00321 
00322   if(isFound(_y1, _y2)) {
00323     // Root is situated between tail and max/min (down/up)
00324 #ifdef searchMinMax
00325     //printf("1/_x1=%.8lf _y1=%lg 1/_x2=%.8lf _y2=%lg\n",1/_x1,_y1,1/_x2,_y2);
00326     printf( "Root above _x1=%.8lf _y1=%lg _x2=%.8lf _y2=%lg\n", _x1, _y1, _x2, _y2);
00327 #endif
00328     if(it.atEnd(from, min, max)) {
00329       /* If _x1 reaches the min (there is necessarly a solution
00330          greater than min because signs are different), there is a lot of
00331          chance that a mode jumping occured. The only one solution is to
00332          reduce the step size and recalculating all the curve until not
00333          getting this condition. */
00334       App::stream() << "** Warning ** : directly at the end" << endl;
00335       return false;
00336     } else {
00337       _x2=_x1;
00338       _y2=_y1;
00339       _x1=it.begin(min, max);
00340       _y1=_polarity;
00341       return true;
00342     }
00343   } else {
00344     // Root is situated below x0, between _x1 and min, thus search by step
00345     _x2=it.next(_x1);
00346     while( ! it.atEnd(_x2, min, max)) {
00347       _y2=_values->y(_x2);
00348 #ifdef searchMinMax
00349       printSearchDebug()
00350 #endif
00351       if(isFound(_y1, _y2)) {
00352         return true;
00353       } else {
00354         _x1=_x2;
00355         _y1=_y2;
00356         _x2=it.next(_x1);
00357       }
00358     }
00359   }
00360   // reaching the minimum slowness, tests if there's a last root
00361   if( ! it.atEnd(_x1, min, max)) {
00362     _x2=it.end(min, max);
00363     _y2=_values->y(_x2);
00364     if(isFound(_y1, _y2)) {
00365       return true;
00366     }
00367   }
00368 #ifdef searchMinMax
00369   printf( "*** no root\n" );
00370 #endif
00371   // If x1 reaches the min/max (there is maybe a solution
00372   // greater/less than min/max, signs are equal), there is a lot of
00373   // chance that a mode jumping occured for fundamental mode. The only one solution is to
00374   // reduce the step size and recalculating all the curve until not
00375   // getting this condition. For higher modes this condition can occur.
00376   return false;
00377 }
00378 
00379 template <class RealType, class FunctionClass> template <class Iterator>
00380 bool RootSolverTemplate<RealType, FunctionClass>
00381 ::searchSlope(RealType from, RealType min, RealType max, const Iterator& it)
00382 {
00383   _x1=from;
00384   _y1=_values->y(_x1);
00385   _x2=it.next(_x1);
00386   RealType maxDiff;
00387   if(_dxType==Absolute) {
00388     maxDiff=1e-7*_dx;
00389   } else {
00390     maxDiff=0.5e-7*fabs(_x1 + _x2) * _dx;
00391   }
00392   while( ! it.atEnd(_x2, min, max)) {
00393     _y2=_values->y(_x2);
00394     if(isFound(_y1, _y2)) {
00395       return true;
00396     }
00397     // A third point to get the slopes
00398     RealType x3=0.5 * (_x1 + _x2);
00399     RealType y3=_values->y(x3);
00400     if(y3 < _y1 && y3 < _y2) {
00401       // Refine the minimum
00402       RealType x1=_x1;
00403       RealType y1=_y1;
00404       RealType x2=_x2;
00405       RealType y2=_y2;
00406       RealType x13, y13, x32, y32;
00407       while(fabs(x2 - x1) > maxDiff) {
00408         x13=0.5 * (x1 + x3);
00409         y13=_values->y(x13);
00410         x32=0.5 * (x3 + x2);
00411         y32=_values->y(x32);
00412         if(y3 < y13 && y3 < y32) {
00413           x1=x13;
00414           y1=y13;
00415           x2=x32;
00416           y2=y32;
00417         } else if(y13 < y32) {
00418           x2=x3;
00419           y2=y3;
00420           x3=x13;
00421           y3=y13;
00422         } else {
00423           x1=x13;
00424           y1=y13;
00425           x3=x32;
00426           y3=y32;
00427         }
00428       }
00429       if(isFound(y3, _y2)) {
00430         // two hidden roots are found, return the first one
00431         _x2=x3;
00432         _y2=y3;
00433         return true;
00434       }
00435       // minimum without root restore and go further
00436     } else if(y3 > _y1 && y3 >  _y2) {
00437       // Refine the maximum
00438       RealType x1=_x1;
00439       RealType y1=_y1;
00440       RealType x2=_x2;
00441       RealType y2=_y2;
00442       RealType x13, y13, x32, y32;
00443       while(fabs(x1 - x2) > maxDiff) {
00444         x13=0.5 * (x1 + x3);
00445         y13=_values->y(x13);
00446         x32=0.5 * (x3 + x2);
00447         y32=_values->y(x32);
00448         if(y3 > y13 && y3 > y32) {
00449           x1=x13;
00450           y1=y13;
00451           x2=x32;
00452           y2=y32;
00453         } else if(y13 > y32) {
00454           x2=x3;
00455           y2=y3;
00456           x3=x13;
00457           y3=y13;
00458         } else {
00459           x1=x13;
00460           y1=y13;
00461           x3=x32;
00462           y3=y32;
00463         }
00464       }
00465       if(isFound(y3, _y2)) {
00466         // two hidden roots are found, return the first one
00467         _x2=x3;
00468         _y2=y3;
00469         return true;
00470       }
00471       // maximum without root restore and go further
00472     }
00473     _x1=_x2;
00474     _y1=_y2;
00475     _x2=it.next(_x1);
00476   }
00477   // reaching the minimum slowness, tests if there's a last root
00478   if( ! it.atEnd(_x1, min, max)) {
00479     _x2=it.end(min, max);
00480     _y2=_values->y(_x2);
00481     if(isFound(_y1, _y2)) {
00482       return true;
00483     }
00484   }
00485   return false;
00486 }
00487 
00488 template <class RealType, class FunctionClass>
00489 bool RootSolverTemplate<RealType, FunctionClass>::setInterval(RealType min, RealType max)
00490 {
00491   _x1=min;
00492   _y1=_values->y(_x1);
00493   _x2=max;
00494   _y2=_values->y(_x2);
00495   return isFound(_y1, _y2);
00496 }
00497 
00498 template <class RealType, class FunctionClass>
00499 void RootSolverTemplate<RealType, FunctionClass>::halving()
00500 {
00501   // First halving
00502   RealType x3=0.5 * (_x1 + _x2);
00503   RealType y3=_values->y(x3);
00504   // Relative Convergence criteria
00505   RealType tmpAbs1;
00506   tmpAbs1=_x1 + _x2;
00507   if(tmpAbs1 < 0) tmpAbs1=-tmpAbs1;
00508   RealType maxDiff=tmpAbs1 * _precision;
00509   RealType minDiff=-maxDiff;
00510   for(register int i=1;i < ROOTSOLVER_MAX_ITERATIONS;i++ ) {
00511     if(y3==0.0) {
00512       // just move the X3 by one tenth of actuel range
00513       x3 -= (_x2 - _x1) * 0.1;
00514       // recalculate the Y3, it will always be different from 0
00515       y3=_values->y(x3);
00516     }
00517     if(isFound(_y1, y3)) {
00518       _x2=x3;
00519       _y2=y3;
00520     } else {
00521       _x1=x3;
00522       _y1=y3;
00523     }
00524     // Check for convergence with a relative criteria, if so exit
00525     RealType diff=_x1 - _x2;
00526     if(minDiff <= diff && diff <= maxDiff) {
00527       return;
00528     }
00529     x3=0.5 * (_x1 + _x2);
00530     y3=_values->y(x3);
00531   }
00532   App::stream() << "Halving maximum iteration reached" << endl;
00533 }
00534 
00535 template <class RealType, class FunctionClass>
00536 void RootSolverTemplate<RealType, FunctionClass>::neville()
00537 {
00538 //#define neville_DEBUG
00539 //#define neville_STAT
00540 #if defined(neville_DEBUG) || defined(neville_STAT)
00541   printf("RootSolverTemplate::neville() @ precision=%lg\n", _precision);
00542 #endif
00543   // Variables for polynomial fit of Neville
00544   int m=0;
00545   RealType p[ 20 ], nevY[ 20 ];
00546   // First halving
00547   RealType x3=0.5 * (_x1 + _x2);
00548   RealType y3=_values->y(x3);
00549   // Relative Convergence criteria
00550   RealType maxDiff=fabs(x3)*_precision;
00551   for (register int i=1; i<ROOTSOLVER_MAX_ITERATIONS; i++) {
00552     // define new bounds according to signs of y1 and y3
00553     // If y1 and y3 have different signs then the root is between
00554     // y1 and y3, thus forget (x2,y2) else forget (x1,y1).
00555     // this case is not implemented in Herrmann's code
00556     // In our case, it is very important to closely bracket the root
00557     // X1 and X2 must ALWAYS stay on the same sides of the root during all
00558     // Neville's iterations.
00559 #ifdef neville_DEBUG
00560     //printf("1/_x1=%.20lf _y1=%.20lg 1/_x2=%.20lf _y2=%.20lg\n",1/_x1,_y1,1/_x2,_y2);
00561     printf("_x1=%.20lf _y1=%.20lg _x2=%.20lf _y2=%.20lg x3=%.20lf y3=%.20lg diff=%.20lg\n", _x1, _y1, _x2, _y2, x3, y3, fabs(_x1-_x2));
00562 #endif
00563     if(y3==0.0) {
00564       // Move the x3 towards the furthest limit
00565       if(fabs(_x1-x3)>fabs(_x2-x3)) {
00566         x3=0.5*(_x1+x3);
00567       } else {
00568         x3=0.5*(_x2+x3);
00569       }
00570       // recalculate the Y3, it will always be different from 0
00571       y3=_values->y(x3);
00572 #ifdef neville_DEBUG
00573       printf("y3 is null: x3=%.20lf y3=%.20lg\n", x3, y3);
00574 #endif
00575     }
00576     if(isFound(_y1, y3)) {
00577       _x2=x3;
00578       _y2=y3;
00579     } else {
00580       _x1=x3;
00581       _y1=y3;
00582     }
00583     // Check for convergence with a relative criteria, if so exit
00584     if(fabs(_x1-_x2)<=maxDiff) {
00585 #if defined(neville_DEBUG) || defined(neville_STAT)
00586       printf( "Number of iterations=%i \n", i);
00587       printf( "Neville poly m=%i \n", m);
00588       printf( "Convergence achieved\n" );
00589 #endif
00590       return;
00591     }
00592     //  Check the slopes between x1,x3 and x3,x2
00593     //  If they are different, the function is strongly non linear,
00594     //  thus use only halving, not Neville
00595     if(isFound(_y1 - y3, y3 - _y2)) {
00596 #if defined(neville_DEBUG) || defined(neville_STAT)
00597       printf( "Neville poly m=%i \n", m);
00598       printf( "Inverse slopes: " );
00599 #endif
00600       x3=0.5* (_x1 + _x2);
00601       y3=_values->y(x3);
00602       m=0;
00603     } else {
00604       // Until 2009-02-03, this test was performed, found to be useless
00605       // If y1 and y2 differ by more than a factor of 100
00606       // use only halving to avoid poor behavior of polynomial fit
00607 
00608 #if 0
00609       RealType ay1=_y1;
00610       if(ay1 < 0) ay1=-ay1;
00611       RealType ay2=_y2;
00612       if(ay2 < 0) ay2=-ay2;
00613       if(ay1 > 100 * ay2 || ay2 > 100 * ay1) {
00614 #if defined(neville_DEBUG) || defined(neville_STAT)
00615         printf( "Neville poly m=%i \n", m);
00616         printf( "Factor of more than 100: " );
00617 #endif
00618         x3=0.5* (x1 + x2);
00619         y3=_values->y(x3);
00620         m=0;
00621       } else {
00622 #endif
00623 #ifdef neville_DEBUG
00624       printf( "Neville poly m=%i \n", m);
00625 #endif
00626       //    if(m>10) cout << "**** WARNING: m=" << m << endl;
00627       if(m>0) {
00628         p[ m + 1 ]=x3;
00629         nevY[ m + 1 ]=y3;
00630       } else {
00631         p[ 0 ]=_x1;
00632         nevY[ 0 ]=_y1;
00633         p[ 1 ]=_x2;
00634         nevY[ 1 ]=_y2;
00635       }
00636       // perform Neville iteration. Instead of generating y(x)
00637       // we interchange the x and y of formula to solve for x(y)
00638       // when y=0.
00639       // A new point is added to the pyramidal contruction.
00640       // The new point is always added at the base, adding a new
00641       // slice at each iteration, each time larger
00642       // As pyramide grows, the degree of the polynome increase
00643       // thus the number of point taken into account increase also.
00644       for(int j=m;j >= 0;j-- ) {
00645         RealType denom=nevY[ m + 1 ] - nevY[ j ];
00646         RealType tmpAbs1=nevY[ m + 1 ];
00647         if(tmpAbs1 < 0) tmpAbs1=-tmpAbs1;
00648         RealType tmpAbs2=denom;
00649         if(tmpAbs2 < 0) tmpAbs2=-tmpAbs2;
00650         if(tmpAbs2 < 1.0e-10 * tmpAbs1) {
00651 #if defined(neville_DEBUG) || defined(neville_STAT)
00652           printf( "Neville poly m=%i \n", m);
00653           printf( "Denom too small (%lf), halving\n", denom);
00654 #endif
00655           p[ 0 ]=0.5 * (_x1 + _x2);
00656           m=0;
00657           break;
00658         } else p[ j ]=(nevY[ m + 1 ] * p[ j ] - nevY[ j ] * p[ j + 1 ] )/denom;
00659       }
00660       x3=p[ 0 ];
00661       // Just move the X3 by one tenth of actual range towards the limit with the highest y
00662       RealType tmpAbs1=_y1<0 ? -_y1 : _y1;
00663       RealType tmpAbs2=_y2<0 ? -_y2 : _y2;
00664       if(tmpAbs1 > tmpAbs2)
00665         x3 -= 0.1 * (x3 - _x1);
00666       else
00667         x3 -= 0.1 * (x3 - _x2);
00668       //printf("Function estimation\n");
00669       m++;
00670       if(m > 18) m=1;
00671       // Make sure new estimate is inside the previous values
00672       // if not perform interval halving
00673       if(_x1 <= _x2) {
00674         if(x3 < _x1 || x3 > _x2) {
00675 #if defined(neville_DEBUG) || defined(neville_STAT)
00676           printf( "Neville poly m=%i \n", m);
00677           printf( "New estimate out of range, halving\n" );
00678 #endif
00679           x3=0.5* (_x1 + _x2);
00680           m=1;
00681         }
00682       } else {
00683         if(x3 < _x2 || x3 > _x1) {
00684 #if defined(neville_DEBUG) || defined(neville_STAT)
00685           printf( "Neville poly m=%i \n", m);
00686           printf( "New estimate out of range, halving\n" );
00687 #endif
00688           x3=0.5* (_x1 + _x2);
00689           m=1;
00690         }
00691       }
00692       y3=_values->y(x3);
00693     }
00694   }
00695   App::stream() << "Neville maximum iteration reached" << endl;
00696 }
00697 
00698 template <class RealType, class FunctionClass>
00699 void RootSolverTemplate<RealType, FunctionClass>::newtonRaphson()
00700 {
00701   // First halving
00702   RealType x3=0.5 * (_x1 + _x2);
00703   RealType y3=_values->y(x3);
00704   // Relative Convergence criteria
00705   RealType tmpAbs1;
00706   tmpAbs1=_x1 + _x2;
00707   if(tmpAbs1 < 0) tmpAbs1=-tmpAbs1;
00708   RealType maxDiff=tmpAbs1 * _precision;
00709   RealType minDiff=-maxDiff;
00710   for(register int i=1;i < ROOTSOLVER_MAX_ITERATIONS;i++ ) {
00711     if(y3==0.0) {
00712       // just move the X3 by one tenth of actuel range
00713       x3 -= (_x2 - _x1) * 0.1;
00714       // recalculate the Y3, it will always be different from 0
00715       y3=_values->y(x3);
00716     }
00717     if(isFound(_y1, y3)) {
00718       _x2=x3;
00719       _y2=y3;
00720     } else {
00721       _x1=x3;
00722       _y1=y3;
00723     }
00724     // Check for convergence with a relative criteria, if so exit
00725     RealType diff=_x1 - _x2;
00726     if(minDiff <= diff && diff <= maxDiff) {
00727       return;
00728     }
00729     // Compute the derivative estimation from the lowest y
00730     // Just move the X3 by one tenth of actual range towards the limit with the highest y
00731     RealType tmpAbs1=_y1<0 ? -_y1 : _y1;
00732     RealType tmpAbs2=_y2<0 ? -_y2 : _y2;
00733     if(tmpAbs1 > tmpAbs2) {
00734       x3=_x2 - _y2/_values->derivative(_x2);
00735       x3 -= 0.1 * (x3 - _x1);
00736     } else {
00737       x3=_x1 - _y1/_values->derivative(_x1);
00738       x3 -= 0.1 * (x3 - _x2);
00739     }
00740     // Make sure new estimate is inside the previous values
00741     // if not perform interval halving
00742     if(_x1 <= _x2) {
00743       if(x3 < _x1 || x3 > _x2) {
00744         x3=0.5* (_x1 + _x2);
00745       }
00746     } else {
00747       if(x3 < _x2 || x3 > _x1) {
00748         x3=0.5* (_x1 + _x2);
00749       }
00750     }
00751     y3=_values->y(x3);
00752   }
00753   App::stream() << "Newton-Raphson maximum iteration reached" << endl;
00754 }
00755 
00756 } // namespace QGpCoreTools
00757 
00758 #endif // ROOTSOLVER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines