00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "Math/GSLIntegrator.h"
00033
00034 #include "gsl/gsl_integration.h"
00035
00036 #include "Math/IFunction.h"
00037 #include "GSLIntegrationWorkspace.h"
00038 #include "GSLFunctionWrapper.h"
00039
00040
00041 #include <algorithm>
00042 #include <functional>
00043 #include <ctype.h>
00044
00045
00046 #include <iostream>
00047
00048
00049
00050 namespace ROOT {
00051 namespace Math {
00052
00053
00054
00055
00056 GSLIntegrator::GSLIntegrator(const Integration::Type type , const Integration::GKRule rule, double absTol, double relTol, size_t size) :
00057 fType(type),
00058 fRule(rule),
00059 fAbsTol(absTol),
00060 fRelTol(relTol),
00061 fSize(size),
00062 fMaxIntervals(size),
00063 fResult(0),fError(0),fStatus(-1),fNEval(-1),
00064 fFunction(0),
00065 fWorkspace(0)
00066 {
00067
00068
00069 if (type != Integration::kNONADAPTIVE)
00070 fWorkspace = new GSLIntegrationWorkspace( fSize);
00071
00072
00073 }
00074
00075
00076
00077 GSLIntegrator::GSLIntegrator(double absTol, double relTol, size_t size) :
00078 fType(Integration::kADAPTIVESINGULAR),
00079 fRule(Integration::kGAUSS31),
00080 fAbsTol(absTol),
00081 fRelTol(relTol),
00082 fSize(size),
00083 fMaxIntervals(size),
00084 fResult(0),fError(0),fStatus(-1),fNEval(-1),
00085 fFunction(0),
00086 fWorkspace(0)
00087 {
00088
00089 fWorkspace = new GSLIntegrationWorkspace( fSize);
00090
00091 }
00092
00093
00094
00095 GSLIntegrator::GSLIntegrator(const Integration::Type type , double absTol, double relTol, size_t size) :
00096 fType(type),
00097 fRule(Integration::kGAUSS31),
00098 fAbsTol(absTol),
00099 fRelTol(relTol),
00100 fSize(size),
00101 fMaxIntervals(size),
00102 fResult(0),fError(0),fStatus(-1),fNEval(-1),
00103 fFunction(0),
00104 fWorkspace(0)
00105 {
00106
00107
00108
00109 if (type != Integration::kNONADAPTIVE)
00110 fWorkspace = new GSLIntegrationWorkspace( fSize);
00111
00112 }
00113
00114 GSLIntegrator::GSLIntegrator(const char * type , int rule, double absTol, double relTol, size_t size) :
00115 fRule(Integration::kGAUSS31),
00116 fAbsTol(absTol),
00117 fRelTol(relTol),
00118 fSize(size),
00119 fMaxIntervals(size),
00120 fResult(0),fError(0),fStatus(-1),fNEval(-1),
00121 fFunction(0),
00122 fWorkspace(0)
00123 {
00124
00125
00126 fType = Integration::kADAPTIVESINGULAR;
00127 if (type != 0) {
00128 std::string typeName(type);
00129 std::transform(typeName.begin(), typeName.end(), typeName.begin(), (int(*)(int)) toupper );
00130 if (typeName == "NONADAPTIVE")
00131 fType = Integration::kNONADAPTIVE;
00132 else if (typeName == "ADAPTIVE")
00133 fType = Integration::kADAPTIVE;
00134 else {
00135 if (typeName != "ADAPTIVESINGULAR")
00136 MATH_WARN_MSG("GSLIntegrator","Use default type: AdaptiveSingular");
00137 }
00138 }
00139
00140
00141
00142
00143 if (fType != Integration::kNONADAPTIVE)
00144 fWorkspace = new GSLIntegrationWorkspace( fSize);
00145
00146 if (rule >= Integration::kGAUSS15 && rule <= Integration::kGAUSS61) SetIntegrationRule((Integration::GKRule) rule);
00147
00148 }
00149
00150
00151 GSLIntegrator::~GSLIntegrator()
00152 {
00153
00154 if (fFunction) delete fFunction;
00155 if (fWorkspace) delete fWorkspace;
00156 }
00157
00158 GSLIntegrator::GSLIntegrator(const GSLIntegrator &) :
00159 VirtualIntegratorOneDim()
00160 {
00161
00162 }
00163
00164 GSLIntegrator & GSLIntegrator::operator = (const GSLIntegrator &rhs)
00165 {
00166
00167 if (this == &rhs) return *this;
00168
00169 return *this;
00170 }
00171
00172
00173
00174
00175 void GSLIntegrator::SetFunction( GSLFuncPointer fp, void * p) {
00176
00177 if (fFunction ==0) fFunction = new GSLFunctionWrapper();
00178 fFunction->SetFuncPointer( fp );
00179 fFunction->SetParams ( p );
00180 }
00181
00182 void GSLIntegrator::SetFunction(const IGenFunction &f ) {
00183
00184 if (fFunction ==0) fFunction = new GSLFunctionWrapper();
00185 fFunction->SetFunction(f);
00186 }
00187
00188
00189
00190 double GSLIntegrator::Integral(double a, double b) {
00191
00192
00193
00194
00195 if (!CheckFunction()) return 0;
00196
00197 if ( fType == Integration::kNONADAPTIVE) {
00198 size_t neval = 0;
00199 fStatus = gsl_integration_qng( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, &fResult, &fError, &neval);
00200 fNEval = neval;
00201 }
00202 else if (fType == Integration::kADAPTIVE) {
00203 fStatus = gsl_integration_qag( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fRule, fWorkspace->GetWS(), &fResult, &fError);
00204 const int npts[6] = {15,21,31,41,51,61};
00205 assert(fRule>=1 && fRule <=6);
00206 fNEval = (fWorkspace->GetWS()->size)*npts[fRule-1];
00207 }
00208 else if (fType == Integration::kADAPTIVESINGULAR) {
00209
00210
00211
00212
00213 fStatus = gsl_integration_qags( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00214 fNEval = (fWorkspace->GetWS()->size) * 21;
00215 }
00216 else {
00217
00218 fResult = 0;
00219 fError = 0;
00220 fStatus = -1;
00221 std::cerr << "GSLIntegrator - Error: Unknown integration type" << std::endl;
00222 throw std::exception();
00223 }
00224
00225 return fResult;
00226
00227 }
00228
00229
00230 double GSLIntegrator::IntegralCauchy(double a, double b, double c) {
00231
00232 if (!CheckFunction()) return 0;
00233
00234 fStatus = gsl_integration_qawc( fFunction->GetFunc(), a, b , c, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00235 fNEval = (fWorkspace->GetWS()->size) * 15;
00236
00237 return fResult;
00238
00239 }
00240
00241 double GSLIntegrator::IntegralCauchy(const IGenFunction & f, double a, double b, double c) {
00242
00243
00244 if (!CheckFunction()) return 0;
00245 SetFunction(f);
00246 return IntegralCauchy(a, b, c);
00247
00248 }
00249
00250
00251
00252 double GSLIntegrator::Integral( const std::vector<double> & pts) {
00253
00254
00255 if (!CheckFunction()) return 0;
00256
00257 if (fType == Integration::kADAPTIVESINGULAR && pts.size() >= 2 ) {
00258
00259 double * p = const_cast<double *>(&pts.front() );
00260 fStatus = gsl_integration_qagp( fFunction->GetFunc(), p, pts.size() , fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00261 fNEval = (fWorkspace->GetWS()->size) * 15;
00262 }
00263 else {
00264 fResult = 0;
00265 fError = 0;
00266 fStatus = -1;
00267 std::cerr << "GSLIntegrator - Error: Unknown integration type or not enough singular points defined" << std::endl;
00268 return 0;
00269 }
00270 return fResult;
00271 }
00272
00273
00274 double GSLIntegrator::Integral( ) {
00275
00276
00277
00278 if (!CheckFunction()) return 0;
00279
00280 if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00281
00282 fStatus = gsl_integration_qagi( fFunction->GetFunc(), fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00283 fNEval = (fWorkspace->GetWS()->size) * 15;
00284
00285 return fResult;
00286 }
00287
00288
00289
00290 double GSLIntegrator::IntegralUp( double a ) {
00291
00292
00293
00294 if (!CheckFunction()) return 0;
00295
00296 if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00297
00298 fStatus = gsl_integration_qagiu( fFunction->GetFunc(), a, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00299 fNEval = (fWorkspace->GetWS()->size) * 21;
00300
00301 return fResult;
00302 }
00303
00304
00305
00306 double GSLIntegrator::IntegralLow( double b ) {
00307
00308
00309
00310 if (!CheckFunction()) return 0;
00311
00312 if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00313
00314 fStatus = gsl_integration_qagil( fFunction->GetFunc(), b, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00315 fNEval = (fWorkspace->GetWS()->size) * 21;
00316
00317 return fResult;
00318 }
00319
00320
00321
00322
00323 double GSLIntegrator::Integral(const IGenFunction & f, double a, double b) {
00324
00325 SetFunction(f);
00326 return Integral(a,b);
00327 }
00328
00329 double GSLIntegrator::Integral(const IGenFunction & f ) {
00330
00331 SetFunction(f);
00332 return Integral();
00333 }
00334
00335 double GSLIntegrator::IntegralUp(const IGenFunction & f, double a) {
00336
00337 SetFunction(f);
00338 return IntegralUp(a);
00339 }
00340
00341 double GSLIntegrator::IntegralLow(const IGenFunction & f, double b) {
00342
00343 SetFunction(f);
00344 return IntegralLow(b);
00345 }
00346
00347 double GSLIntegrator::Integral(const IGenFunction & f, const std::vector<double> & pts) {
00348
00349 SetFunction(f);
00350 return Integral(pts);
00351 }
00352
00353
00354
00355
00356 double GSLIntegrator::Integral( GSLFuncPointer f , void * p, double a, double b) {
00357
00358 SetFunction( f, p);
00359 return Integral(a,b);
00360 }
00361
00362 double GSLIntegrator::Integral( GSLFuncPointer f, void * p ) {
00363
00364 SetFunction( f, p);
00365 return Integral();
00366 }
00367
00368 double GSLIntegrator::IntegralUp( GSLFuncPointer f, void * p, double a ) {
00369
00370 SetFunction( f, p);
00371 return IntegralUp(a);
00372 }
00373
00374 double GSLIntegrator::IntegralLow( GSLFuncPointer f, void * p, double b ) {
00375
00376 SetFunction( f, p);
00377 return IntegralLow(b);
00378 }
00379
00380 double GSLIntegrator::Integral( GSLFuncPointer f, void * p, const std::vector<double> & pts ) {
00381
00382 SetFunction( f, p);
00383 return Integral(pts);
00384 }
00385
00386
00387
00388 double GSLIntegrator::Result() const { return fResult; }
00389
00390 double GSLIntegrator::Error() const { return fError; }
00391
00392 int GSLIntegrator::Status() const { return fStatus; }
00393
00394
00395
00396
00397
00398
00399 void GSLIntegrator::SetAbsTolerance(double absTol){ this->fAbsTol = absTol; }
00400
00401
00402
00403 void GSLIntegrator::SetRelTolerance(double relTol){ this->fRelTol = relTol; }
00404
00405
00406 void GSLIntegrator::SetIntegrationRule(Integration::GKRule rule){ this->fRule = rule; }
00407
00408 bool GSLIntegrator::CheckFunction() {
00409
00410 if (fFunction->IsValid()) return true;
00411 fStatus = -1; fResult = 0; fError = 0;
00412 std::cerr << "GSLIntegrator - Error : Function has not been specified " << std::endl;
00413 return false;
00414 }
00415
00416 void GSLIntegrator::SetOptions(const ROOT::Math::IntegratorOneDimOptions & opt)
00417 {
00418
00419 fType = opt.IntegratorType();
00420 if (fType == IntegrationOneDim::kDEFAULT) fType = IntegrationOneDim::kADAPTIVESINGULAR;
00421 if (fType != IntegrationOneDim::kADAPTIVE &&
00422 fType != IntegrationOneDim::kADAPTIVESINGULAR &&
00423 fType != IntegrationOneDim::kNONADAPTIVE ) {
00424 MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default ADAPTIVESINGULAR");
00425 fType = IntegrationOneDim::kADAPTIVESINGULAR;
00426 }
00427 SetAbsTolerance( opt.AbsTolerance() );
00428 SetRelTolerance( opt.RelTolerance() );
00429 fSize = opt.WKSize();
00430 fMaxIntervals = fSize;
00431 if (fType == Integration::kADAPTIVE) {
00432 int npts = opt.NPoints();
00433 if ( npts >= Integration::kGAUSS15 && npts <= Integration::kGAUSS61)
00434 fRule = (Integration::GKRule) npts;
00435 else {
00436 MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default GAUSS31");
00437 fRule = Integration::kGAUSS31;
00438 }
00439 }
00440 }
00441
00442 ROOT::Math::IntegratorOneDimOptions GSLIntegrator::Options() const {
00443 ROOT::Math::IntegratorOneDimOptions opt;
00444 opt.SetAbsTolerance(fAbsTol);
00445 opt.SetRelTolerance(fRelTol);
00446 opt.SetWKSize(fSize);
00447 opt.SetIntegrator(GetTypeName() );
00448
00449 if (fType == IntegrationOneDim::kADAPTIVE)
00450 opt.SetNPoints(fRule);
00451 else if (fType == IntegrationOneDim::kADAPTIVESINGULAR)
00452 opt.SetNPoints( Integration::kGAUSS31 );
00453 else
00454 opt.SetNPoints( 0 );
00455
00456 return opt;
00457 }
00458
00459 const char * GSLIntegrator::GetTypeName() const {
00460 if (fType == IntegrationOneDim::kADAPTIVE) return "Adaptive";
00461 if (fType == IntegrationOneDim::kADAPTIVESINGULAR) return "AdaptiveSingular";
00462 if (fType == IntegrationOneDim::kNONADAPTIVE) return "NonAdaptive";
00463 return "Undefined";
00464 }
00465
00466
00467 }
00468 }