testDerivation.cxx

Go to the documentation of this file.
00001 #include "Math/Polynomial.h"
00002 #include "Math/Derivator.h"
00003 #include "Math/IFunction.h"
00004 #include "Math/Functor.h"
00005 #include "Math/WrappedFunction.h"
00006 #include "Math/WrappedParamFunction.h"
00007 #include <iostream>
00008 #include <vector>
00009 #include <cassert>
00010 #include <cmath>
00011 
00012 #ifdef HAVE_ROOTLIBS
00013 
00014 #include "TStopwatch.h"
00015 #include "TF1.h"
00016 #include "Math/WrappedTF1.h"
00017 #include "Math/WrappedMultiTF1.h"
00018 #include "Math/DistFunc.h"
00019 
00020 #endif
00021 
00022 const double ERRORLIMIT = 1E-5;
00023 
00024 typedef double ( * FP ) ( double, void * ); 
00025 typedef double ( * FP2 ) ( double ); 
00026 
00027 
00028 double myfunc ( double x, void * ) { 
00029   
00030   return std::pow( x, 1.5); 
00031 }
00032 
00033 double myfunc2 ( double x) { 
00034   return std::pow( x, 1.5); 
00035 }
00036 
00037 int testDerivation() {
00038 
00039    int status = 0;
00040 
00041 
00042   // Derivative of an IGenFunction
00043   // Works when compiled c++, compiled ACLiC, interpreted by CINT
00044   ROOT::Math::Polynomial *f1 = new ROOT::Math::Polynomial(2);
00045 
00046   std::vector<double> p(3);
00047   p[0] = 2;
00048   p[1] = 3;
00049   p[2] = 4;
00050   f1->SetParameters(&p[0]);
00051 
00052   ROOT::Math::Derivator *der = new ROOT::Math::Derivator(*f1);
00053 
00054   double step = 1E-8;
00055   double x0 = 2;
00056 
00057   der->SetFunction(*f1);
00058   double result = der->Eval(x0);
00059   std::cout << "Derivative of function inheriting from IGenFunction f(x) = 2 + 3x + 4x^2 at x = 2" << std::endl;
00060   std::cout << "Return code:  " << der->Status() << std::endl;
00061   std::cout << "Result:       " << result << " +/- " << der->Error() << std::endl;
00062   std::cout << "Exact result: " << f1->Derivative(x0) << std::endl;
00063   std::cout << "EvalForward:  " << der->EvalForward(*f1, x0) << std::endl;
00064   std::cout << "EvalBackward: " << der->EvalBackward(x0, step) << std::endl << std::endl;;
00065   status += fabs(result-f1->Derivative(x0)) > ERRORLIMIT;
00066   
00067   
00068   // Derivative of a free function
00069   // Works when compiled c++, compiled ACLiC, does not work when interpreted by CINT  
00070   FP f2 = &myfunc;
00071   der->SetFunction(f2);
00072 
00073   std::cout << "Derivative of a free function f(x) = x^(3/2) at x = 2" << std::endl;
00074   std::cout << "EvalCentral:  " << der->EvalCentral(x0) << std::endl;
00075   std::cout << "EvalForward:  " << der->EvalForward(x0) << std::endl;
00076   std::cout << "EvalBackward: " << der->EvalBackward(x0) << std::endl;
00077 
00078   std::cout << "Exact result: " << 1.5*sqrt(x0) << std::endl << std::endl;
00079 
00080   status += fabs(der->EvalCentral(x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00081   status += fabs(der->EvalForward(x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00082   status += fabs(der->EvalBackward(x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00083 
00084   
00085   
00086   // Derivative of a free function wrapped in an IGenFunction
00087   // Works when compiled c++, compiled ACLiC, does not work when interpreted by CINT  
00088   ROOT::Math::Functor1D *f3 = new ROOT::Math::Functor1D (&myfunc2);
00089 
00090   std::cout << "Derivative of a free function wrapped in a Functor f(x) = x^(3/2) at x = 2" << std::endl;
00091   std::cout << "EvalCentral:  " << der->Eval( *f3, x0) << std::endl;
00092   der->SetFunction(*f3);
00093   std::cout << "EvalForward:  " << der->EvalForward(x0) << std::endl;
00094   std::cout << "EvalBackward: " << der->EvalBackward(x0) << std::endl;
00095   std::cout << "Exact result: " << 1.5*sqrt(x0) << std::endl << std::endl;
00096 
00097   status += fabs(der->Eval( *f3, x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00098   status += fabs(der->EvalForward(x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00099   status += fabs(der->EvalBackward(x0)-1.5*sqrt(x0)) > ERRORLIMIT;
00100 
00101 
00102   // tets case when an empty Derivator is used 
00103 
00104   ROOT::Math::Derivator der2;
00105   std::cout << "Tes a derivator without a function" << std::endl;
00106   std::cout << der2.Eval(1.0) << std::endl; 
00107   
00108   // Derivative of a multidim TF1 function
00109   
00110 // #ifdef LATER
00111 //   TF2 * f2d = new TF2("f2d","x*x + y*y",-10,10,-10,10);
00112 //   // find gradient at x={1,1}
00113 //   double vx[2] = {1.,2.}; 
00114 //   ROOT::Math::WrappedTF1 fx(*f2d); 
00115 
00116 //   std::cout << "Derivative of a  f(x,y) = x^2 + y^2 at x = 1,y=2" << std::endl;
00117 //   std::cout << "df/dx  = " << der->EvalCentral(fx,1.) << std::endl;
00118 //   WrappedFunc fy(*f2d,0,vx); 
00119 //   std::cout << "df/dy  = " << der->EvalCentral(fy,2.) << std::endl;
00120 // #endif
00121 
00122   return status;
00123 }
00124 
00125 
00126 #ifdef HAVE_ROOTLIBS
00127 
00128 void testDerivPerf() { 
00129 
00130 
00131    std::cout << "\n\n***************************************************************\n";
00132    std::cout << "Test derivation performances....\n\n";
00133 
00134   ROOT::Math::Polynomial f1(2); 
00135   double p[3] = {2,3,4};
00136   f1.SetParameters(p);
00137   
00138   TStopwatch timer; 
00139   int n = 1000000; 
00140   double x1 = 0; double x2 = 10; 
00141   double dx = (x2-x1)/double(n); 
00142 
00143   timer.Start(); 
00144   double s1 = 0; 
00145   ROOT::Math::Derivator der(f1);
00146   for (int i = 0; i < n; ++i) { 
00147      double x = x1 + dx*i; 
00148      s1+= der.EvalCentral(x);
00149   }
00150   timer.Stop(); 
00151   std::cout << "Time using ROOT::Math::Derivator :\t" << timer.RealTime() << std::endl; 
00152   int pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00153 
00154   timer.Start(); 
00155   s1 = 0; 
00156   for (int i = 0; i < n; ++i) { 
00157      ROOT::Math::Derivator der2(f1);
00158      double x = x1 + dx*i; 
00159      s1+= der2.EvalForward(x);
00160   }
00161   timer.Stop(); 
00162   std::cout << "Time using ROOT::Math::Derivator(2):\t" << timer.RealTime() << std::endl; 
00163   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00164 
00165   timer.Start(); 
00166   s1 = 0; 
00167   for (int i = 0; i < n; ++i) { 
00168      double x = x1 + dx*i; 
00169      s1+= ROOT::Math::Derivator::Eval(f1,x);
00170   }
00171   timer.Stop(); 
00172   std::cout << "Time using ROOT::Math::Derivator(3):\t" << timer.RealTime() << std::endl; 
00173   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00174 
00175 
00176   TF1 f2("pol","pol2",0,10);
00177   f2.SetParameters(p);
00178   
00179   timer.Start(); 
00180   double s2 = 0; 
00181   for (int i = 0; i < n; ++i) { 
00182      double x = x1 + dx*i; 
00183      s2+= f2.Derivative(x);
00184   }
00185   timer.Stop(); 
00186   std::cout << "Time using TF1::Derivative :\t\t" << timer.RealTime() << std::endl; 
00187   pr = std::cout.precision(18);
00188   std::cout << s2 << std::endl;
00189   std::cout.precision(pr);
00190 
00191 
00192 
00193 }
00194 
00195 double userFunc(const double *x, const double *  = 0) { 
00196    return std::exp(-x[0]); 
00197 }
00198 double userFunc1(double x) { return userFunc(&x); }
00199 
00200 double userFunc2(const double * x) { return userFunc(x); }
00201 
00202 void testDerivPerfUser() { 
00203 
00204 
00205    std::cout << "\n\n***************************************************************\n";
00206    std::cout << "Test derivation performances - using a User function\n\n";
00207 
00208   ROOT::Math::WrappedFunction<> f1(userFunc1); 
00209   
00210   TStopwatch timer; 
00211   int n = 1000000; 
00212   double x1 = 0; double x2 = 10; 
00213   double dx = (x2-x1)/double(n); 
00214 
00215   timer.Start(); 
00216   double s1 = 0; 
00217   ROOT::Math::Derivator der(f1);
00218   for (int i = 0; i < n; ++i) { 
00219      double x = x1 + dx*i; 
00220      s1+= der.EvalCentral(x);
00221   }
00222   timer.Stop(); 
00223   std::cout << "Time using ROOT::Math::Derivator :\t" << timer.RealTime() << std::endl; 
00224   int pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00225 
00226   timer.Start(); 
00227   s1 = 0; 
00228   for (int i = 0; i < n; ++i) { 
00229      ROOT::Math::Derivator der2(f1);
00230      double x = x1 + dx*i; 
00231      s1+= der2.EvalForward(x);
00232   }
00233   timer.Stop(); 
00234   std::cout << "Time using ROOT::Math::Derivator(2):\t" << timer.RealTime() << std::endl; 
00235   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00236 
00237   timer.Start(); 
00238   s1 = 0; 
00239   for (int i = 0; i < n; ++i) { 
00240      double x = x1 + dx*i; 
00241      s1+= ROOT::Math::Derivator::Eval(f1,x);
00242   }
00243   timer.Stop(); 
00244   std::cout << "Time using ROOT::Math::Derivator(3):\t" << timer.RealTime() << std::endl; 
00245   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00246 
00247 
00248   TF1 f2("uf",userFunc,0,10,0);
00249   
00250   timer.Start(); 
00251   double s2 = 0; 
00252   for (int i = 0; i < n; ++i) { 
00253      double x = x1 + dx*i; 
00254      s2+= f2.Derivative(x);
00255   }
00256   timer.Stop(); 
00257   std::cout << "Time using TF1::Derivative :\t\t" << timer.RealTime() << std::endl; 
00258   pr = std::cout.precision(18);
00259   std::cout << s2 << std::endl;
00260   std::cout.precision(pr);
00261 
00262   //typedef double( * FN ) (const double *, const double * ); 
00263   ROOT::Math::WrappedMultiFunction<> f3(userFunc2,1); 
00264   timer.Start(); 
00265   s1 = 0; 
00266   double xx[1]; 
00267   for (int i = 0; i < n; ++i) { 
00268      xx[0] = x1 + dx*i; 
00269      s1+= ROOT::Math::Derivator::Eval(f3,xx,0);
00270   }
00271   timer.Stop(); 
00272   std::cout << "Time using ROOT::Math::Derivator Multi:\t" << timer.RealTime() << std::endl; 
00273   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00274 
00275 
00276 
00277 }
00278 
00279 
00280 double gausFunc( const double * x, const double * p) { 
00281    return p[0] * ROOT::Math::normal_pdf(x[0], p[2], p[1] ); 
00282 }
00283 
00284 
00285 void testDerivPerfParam() { 
00286 
00287 
00288    std::cout << "\n\n***************************************************************\n";
00289    std::cout << "Test derivation performances - using a Gaussian Param function\n\n";
00290 
00291    //TF1 gaus("gaus","gaus",-10,10);
00292    TF1 gaus("gaus",gausFunc,-10,10,3);
00293   double params[3] = {10,1.,1.};
00294   gaus.SetParameters(params);
00295 
00296   ROOT::Math::WrappedTF1 f1(gaus); 
00297   
00298   TStopwatch timer; 
00299   int n = 300000; 
00300   double x1 = 0; double x2 = 10; 
00301   double dx = (x2-x1)/double(n); 
00302 
00303   timer.Start(); 
00304   double s1 = 0; 
00305   for (int i = 0; i < n; ++i) { 
00306      double x = x1 + dx*i; 
00307      // param derivatives
00308      s1 += ROOT::Math::Derivator::Eval(f1,x,params,0);
00309      s1 += ROOT::Math::Derivator::Eval(f1,x,params,1);
00310      s1 += ROOT::Math::Derivator::Eval(f1,x,params,2);
00311   }
00312   timer.Stop(); 
00313   std::cout << "Time using ROOT::Math::Derivator (1D) :\t" << timer.RealTime() << std::endl; 
00314   int pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00315 
00316   ROOT::Math::WrappedParamFunction<> f2(&gausFunc,1,params,params+3); 
00317   double xx[1]; 
00318 
00319   timer.Start(); 
00320   s1 = 0; 
00321   for (int i = 0; i < n; ++i) { 
00322      xx[0] = x1 + dx*i; 
00323      s1 += ROOT::Math::Derivator::Eval(f2,xx,params,0);
00324      s1 += ROOT::Math::Derivator::Eval(f2,xx,params,1);
00325      s1 += ROOT::Math::Derivator::Eval(f2,xx,params,2);
00326   }
00327   timer.Stop(); 
00328   std::cout << "Time using ROOT::Math::Derivator(ND):\t" << timer.RealTime() << std::endl; 
00329   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00330 
00331   // test that func parameters have not been changed 
00332   assert( std::fabs(params[0] - gaus.GetParameter(0)) < 1.E-15); 
00333   assert( std::fabs(params[1] - gaus.GetParameter(1)) < 1.E-15); 
00334   assert( std::fabs(params[2] - gaus.GetParameter(2)) < 1.E-15); 
00335 
00336   timer.Start(); 
00337   s1 = 0; 
00338   double g[3];
00339   for (int i = 0; i < n; ++i) { 
00340      xx[0] = x1 + dx*i; 
00341      gaus.GradientPar(xx,g,1E-8);
00342      s1 += g[0];
00343      s1 += g[1];
00344      s1 += g[2];
00345   }
00346   timer.Stop(); 
00347   std::cout << "Time using TF1::ParamGradient:\t\t" << timer.RealTime() << std::endl; 
00348   pr = std::cout.precision(18); std::cout << s1 << std::endl; std::cout.precision(pr);
00349 
00350 }
00351 
00352 #endif
00353 
00354 int main() {
00355 
00356   int status = 0;
00357 
00358   status += testDerivation();
00359 
00360 #ifdef HAVE_ROOTLIBS
00361   testDerivPerf();
00362   testDerivPerfUser();
00363   testDerivPerfParam();
00364 #endif
00365 
00366   return status;
00367 
00368 }

Generated on Tue Jul 5 14:34:58 2011 for ROOT_528-00b_version by  doxygen 1.5.1