RooImproperIntegrator1D.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooImproperIntegrator1D.cxx 36209 2010-10-08 21:37:36Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 // Special numeric integrator that can handle integrals over open domains.
00021 // To this end the range is cut in up three pieces: [-inf,-1],[-1,+1] and [+1,inf]
00022 // and the outer two pieces, if required are calculated using a 1/x transform
00023 // END_HTML
00024 //
00025 
00026 
00027 #include "RooFit.h"
00028 
00029 #include "RooImproperIntegrator1D.h"
00030 #include "RooImproperIntegrator1D.h"
00031 #include "RooIntegrator1D.h"
00032 #include "RooInvTransform.h"
00033 #include "RooNumber.h"
00034 #include "RooNumIntFactory.h"
00035 #include "RooArgSet.h"
00036 #include "RooMsgService.h"
00037 
00038 #include "Riostream.h"
00039 #include <math.h>
00040 #include "TClass.h"
00041 
00042 
00043 
00044 ClassImp(RooImproperIntegrator1D)
00045 ;
00046 
00047 // Register this class with RooNumIntConfig
00048 
00049 //_____________________________________________________________________________
00050 void RooImproperIntegrator1D::registerIntegrator(RooNumIntFactory& fact)
00051 {
00052   // Register RooImproperIntegrator1D, its parameters and capabilities with RooNumIntFactory
00053 
00054   RooImproperIntegrator1D* proto = new RooImproperIntegrator1D() ;
00055   fact.storeProtoIntegrator(proto,RooArgSet(),RooIntegrator1D::Class()->GetName()) ;
00056 }
00057 
00058 
00059 
00060 //_____________________________________________________________________________
00061 RooImproperIntegrator1D::RooImproperIntegrator1D() :  
00062   _case(ClosedBothEnds), _xmin(-10), _xmax(10), _useIntegrandLimits(kTRUE),
00063   _origFunc(0), _function(0), _integrator1(0), _integrator2(0), _integrator3(0)
00064 {
00065   // Default constructor
00066 }
00067 
00068 
00069 //_____________________________________________________________________________
00070 RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function) :
00071   RooAbsIntegrator(function),
00072   _useIntegrandLimits(kTRUE),
00073   _origFunc((RooAbsFunc*)&function),
00074   _function(0),
00075   _integrator1(0),
00076   _integrator2(0),
00077   _integrator3(0)
00078 {
00079   // Constructor with function binding. The integration range is taken from the
00080   // definition in the function binding
00081   initialize(&function) ;
00082 }
00083 
00084 
00085 
00086 //_____________________________________________________________________________
00087 RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function, const RooNumIntConfig& config) :
00088   RooAbsIntegrator(function),
00089   _useIntegrandLimits(kTRUE),
00090   _origFunc((RooAbsFunc*)&function),
00091   _function(0),
00092   _config(config),
00093   _integrator1(0),
00094   _integrator2(0),
00095   _integrator3(0)
00096 {
00097   // Constructor with function binding and configuration object. The integration range is taken
00098   // from the definition in the function binding
00099   initialize(&function) ;
00100 }
00101 
00102 
00103 
00104 //_____________________________________________________________________________
00105 RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function, Double_t xmin, Double_t xmax, const RooNumIntConfig& config) :
00106   RooAbsIntegrator(function),
00107   _xmin(xmin),
00108   _xmax(xmax),
00109   _useIntegrandLimits(kFALSE),
00110   _origFunc((RooAbsFunc*)&function),
00111   _function(0),
00112   _config(config),
00113   _integrator1(0),
00114   _integrator2(0),
00115   _integrator3(0)
00116 {
00117   // Constructor with function binding, definition of integration range and configuration object
00118   initialize(&function) ;
00119 }
00120 
00121 
00122 
00123 //_____________________________________________________________________________
00124 RooAbsIntegrator* RooImproperIntegrator1D::clone(const RooAbsFunc& function, const RooNumIntConfig& config) const
00125 {
00126   // Return clone of integrator with given function and configuration. Needed by RooNumIntFactory.
00127   return new RooImproperIntegrator1D(function,config) ;
00128 }
00129 
00130 
00131 
00132 //_____________________________________________________________________________
00133 void RooImproperIntegrator1D::initialize(const RooAbsFunc* function)
00134 {
00135   // Initialize the integrator, construct and initialize subintegrators
00136 
00137   if(!isValid()) {
00138     oocoutE((TObject*)0,Integration) << "RooImproperIntegrator: cannot integrate invalid function" << endl;
00139     return;
00140   }
00141   // Create a new function object that uses the change of vars: x -> 1/x
00142   if (function) {
00143     _function= new RooInvTransform(*function);
00144   } else {
00145     function = _origFunc ;
00146     if (_integrator1) {
00147       delete _integrator1 ; 
00148       _integrator1 = 0 ;
00149     }
00150     if (_integrator2) {
00151       delete _integrator2 ; 
00152       _integrator2 = 0 ;
00153     }
00154     if (_integrator3) {
00155       delete _integrator3 ; 
00156       _integrator3 = 0 ;
00157     }
00158   }
00159 
00160   // partition the integration range into subranges that can each be
00161   // handled by RooIntegrator1D
00162   switch(_case= limitsCase()) {
00163   case ClosedBothEnds:
00164     // both limits are finite: use the plain trapezoid integrator
00165     _integrator1= new RooIntegrator1D(*function,_xmin,_xmax,_config);
00166     break;
00167   case OpenBothEnds:
00168     // both limits are infinite: integrate over (-1,+1) using
00169     // the plain trapezoid integrator...
00170     _integrator1= new RooIntegrator1D(*function,-1,+1,RooIntegrator1D::Trapezoid);
00171     // ...and integrate the infinite tails using the midpoint integrator
00172     _integrator2= new RooIntegrator1D(*_function,-1,0,RooIntegrator1D::Midpoint);
00173     _integrator3= new RooIntegrator1D(*_function,0,+1,RooIntegrator1D::Midpoint);
00174     break;
00175   case OpenBelowSpansZero:
00176     // xmax >= 0 so integrate from (-inf,-1) and (-1,xmax)
00177     _integrator1= new RooIntegrator1D(*_function,-1,0,RooIntegrator1D::Midpoint);
00178     _integrator2= new RooIntegrator1D(*function,-1,_xmax,RooIntegrator1D::Trapezoid);
00179     break;
00180   case OpenBelow:
00181     // xmax < 0 so integrate from (-inf,xmax)
00182     _integrator1= new RooIntegrator1D(*_function,1/_xmax,0,RooIntegrator1D::Midpoint);
00183     break;
00184   case OpenAboveSpansZero:
00185     // xmin <= 0 so integrate from (xmin,+1) and (+1,+inf)
00186     _integrator1= new RooIntegrator1D(*_function,0,+1,RooIntegrator1D::Midpoint);
00187     _integrator2= new RooIntegrator1D(*function,_xmin,+1,RooIntegrator1D::Trapezoid);
00188     break;
00189   case OpenAbove:
00190     // xmin > 0 so integrate from (xmin,+inf)
00191     _integrator1= new RooIntegrator1D(*_function,0,1/_xmin,RooIntegrator1D::Midpoint);
00192     break;
00193   case Invalid:
00194   default:
00195     _valid= kFALSE;
00196   }
00197 }
00198 
00199 
00200 //_____________________________________________________________________________
00201 RooImproperIntegrator1D::~RooImproperIntegrator1D() 
00202 {
00203   // Destructor
00204 
00205   if(0 != _integrator1) delete _integrator1;
00206   if(0 != _integrator2) delete _integrator2;
00207   if(0 != _integrator3) delete _integrator3;
00208   if(0 != _function) delete _function;
00209 }
00210 
00211 
00212 //_____________________________________________________________________________
00213 Bool_t RooImproperIntegrator1D::setLimits(Double_t *xmin, Double_t *xmax) 
00214 {
00215   // Change our integration limits. Return kTRUE if the new limits are
00216   // ok, or otherwise kFALSE. Always returns kFALSE and does nothing
00217   // if this object was constructed to always use our integrand's limits.
00218 
00219   if(_useIntegrandLimits) {
00220     oocoutE((TObject*)0,Integration) << "RooIntegrator1D::setLimits: cannot override integrand's limits" << endl;
00221     return kFALSE;
00222   }
00223 
00224   _xmin= *xmin;
00225   _xmax= *xmax;
00226   return checkLimits();
00227 }
00228 
00229 
00230 //_____________________________________________________________________________
00231 Bool_t RooImproperIntegrator1D::checkLimits() const 
00232 {
00233   // Check if the limits are valid. For this integrator all limit configurations
00234   // are valid, but if the limits change between two calculate() calls it
00235   // may be necessary to reconfigure (e.g. if an open ended range becomes
00236   // a closed range
00237 
00238   // Has either limit changed?
00239   if (_useIntegrandLimits) {
00240     if(_xmin == integrand()->getMinLimit(0) &&
00241        _xmax == integrand()->getMaxLimit(0)) return kTRUE;
00242   }
00243 
00244   // The limits have changed: can we use the same strategy?
00245   if(limitsCase() != _case) {
00246     // Reinitialize embedded integrators, will automatically propagate new limits
00247     const_cast<RooImproperIntegrator1D*>(this)->initialize() ;
00248     return kTRUE ;
00249   }
00250 
00251   // Reuse our existing integrators by updating their limits
00252   switch(_case) {
00253   case ClosedBothEnds:
00254     _integrator1->setLimits(_xmin,_xmax);
00255     break;
00256   case OpenBothEnds:
00257     // nothing has changed
00258     break;
00259   case OpenBelowSpansZero:
00260     _integrator2->setLimits(-1,_xmax);
00261     break;
00262   case OpenBelow:
00263     _integrator1->setLimits(1/_xmax,0);
00264     break;
00265   case OpenAboveSpansZero:
00266     _integrator2->setLimits(_xmin,+1);
00267     break;
00268   case OpenAbove:
00269     _integrator1->setLimits(0,1/_xmin);
00270     break;
00271   case Invalid:
00272   default:
00273     return kFALSE;
00274   }
00275   return kTRUE;
00276 }
00277 
00278 
00279 //_____________________________________________________________________________
00280 RooImproperIntegrator1D::LimitsCase RooImproperIntegrator1D::limitsCase() const 
00281 {
00282   // Classify the type of limits we have: OpenBothEnds,ClosedBothEnds,OpenBelow or OpenAbove.
00283 
00284   // Analyze the specified limits to determine which case applies.
00285   if(0 == integrand() || !integrand()->isValid()) return Invalid;
00286 
00287   if (_useIntegrandLimits) {
00288     _xmin= integrand()->getMinLimit(0);
00289     _xmax= integrand()->getMaxLimit(0);
00290   }
00291 
00292   Bool_t inf1= RooNumber::isInfinite(_xmin);
00293   Bool_t inf2= RooNumber::isInfinite(_xmax);
00294   if(!inf1 && !inf2) {
00295     // both limits are finite
00296     return ClosedBothEnds;
00297   }
00298   else if(inf1 && inf2) {
00299     // both limits are infinite
00300     return OpenBothEnds;
00301   }
00302   else if(inf1) { // inf2==false
00303     if(_xmax >= 0) {
00304       return OpenBelowSpansZero;
00305     }
00306     else {
00307       return OpenBelow;
00308     }
00309   }
00310   else { // inf1==false && inf2==true
00311     if(_xmin <= 0) {
00312       return OpenAboveSpansZero;
00313     }
00314     else {
00315       return OpenAbove;
00316     }
00317   }
00318   // return Invalid; OSF-CC: Statement unreachable
00319 }
00320 
00321 
00322 //_____________________________________________________________________________
00323 Double_t RooImproperIntegrator1D::integral(const Double_t* yvec) 
00324 {
00325   // Calculate the integral at the given parameter values of the function binding
00326 
00327   Double_t result(0);
00328   if(0 != _integrator1) result+= _integrator1->integral(yvec);
00329   if(0 != _integrator2) result+= _integrator2->integral(yvec);
00330   if(0 != _integrator3) result+= _integrator3->integral(yvec);
00331   return result;  
00332 }

Generated on Tue Jul 5 15:06:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1