11 #include "gsl/gsl_errno.h"
12 #include "gsl/gsl_integration.h"
16 #include "GaudiKernel/GaudiException.h"
20 #include "GaudiMath/NumericalDefiniteIntegral.h"
21 #include "GaudiMath/NumericalDerivative.h"
32 #pragma warning(disable:1572)
38 #pragma warning(disable:4996)
43 namespace GaudiMathImplementation
47 { gsl_function*
fn ; };
107 ( const AbsFunction& function ,
113 const
double epsabs ,
114 const
double epsrel ,
116 : m_function ( function.clone () )
126 , m_epsabs ( epsabs )
127 , m_epsrel ( epsrel )
128 , m_result ( GSL_NEGINF )
129 , m_error ( GSL_POSINF )
134 if (
function.dimensionality() < 2 )
135 { Exception(
"::constructor: invalid dimensionality ") ; }
136 if ( m_index >=
function.dimensionality() )
137 { Exception(
"::constructor: invalid variable index") ; }
139 m_DIM =
function.dimensionality() - 1 ;
140 m_argument = Argument( m_DIM ) ;
141 m_argF = Argument( m_DIM + 1 ) ;
156 (
const AbsFunction&
function ,
161 const double epsabs ,
162 const double epsrel ,
164 : m_function (
function.clone() )
174 , m_points ( points )
175 , m_epsabs ( epsabs )
176 , m_epsrel ( epsrel )
178 , m_result ( GSL_NEGINF )
179 , m_error ( GSL_POSINF )
183 if (
function.dimensionality() < 2 )
184 { Exception(
"::constructor: invalid dimensionality ") ; }
185 if ( m_index >=
function.dimensionality() )
186 { Exception(
"::constructor: invalid variable index") ; }
188 m_DIM =
function.dimensionality() - 1 ;
189 m_argument = Argument( m_DIM ) ;
190 m_argF = Argument( m_DIM + 1 ) ;
192 const double l1 = std::min ( a , b ) ;
193 const double l2 = std::max ( a , b ) ;
194 m_points.push_back ( l1 ) ;
195 m_points.push_back ( l2 ) ;
197 std::sort ( m_points.begin() , m_points.end() ) ;
198 m_points.erase( std::unique( m_points.begin () , m_points.end () ) ,
201 auto lower = std::lower_bound ( m_points.begin () , m_points.end () , l1 ) ;
202 m_points.erase( m_points.begin () , lower ) ;
203 auto upper = std::upper_bound ( m_points.begin () , m_points.end () , l2 ) ;
204 m_points.erase( upper , m_points.end () ) ;
206 m_pdata.reset(
new double[ m_points.size() ] );
207 std::copy( m_points.begin() , m_points.end() , m_pdata.get() );
236 (
const AbsFunction&
function ,
240 const double epsabs ,
241 const double epsrel ,
243 : m_function (
function.clone() )
253 , m_epsabs ( epsabs )
254 , m_epsrel ( epsrel )
256 , m_result ( GSL_NEGINF )
257 , m_error ( GSL_POSINF )
261 if (
function.dimensionality() < 2 )
262 { Exception(
"::constructor: invalid dimensionality ") ; }
263 if ( m_index >=
function.dimensionality() )
264 { Exception(
"::constructor: invalid variable index") ; }
266 m_DIM =
function.dimensionality() - 1 ;
267 m_argument = Argument( m_DIM ) ;
268 m_argF = Argument( m_DIM + 1 ) ;
299 (
const AbsFunction&
function ,
303 const double epsabs ,
304 const double epsrel ,
306 : m_function (
function.clone() )
316 , m_epsabs ( epsabs )
317 , m_epsrel ( epsrel )
319 , m_result ( GSL_NEGINF )
320 , m_error ( GSL_POSINF )
324 if (
function.dimensionality() < 2 )
325 { Exception(
"::constructor: invalid dimensionality ") ; }
326 if ( m_index >=
function.dimensionality() )
327 { Exception(
"::constructor: invalid variable index") ; }
329 m_DIM =
function.dimensionality() - 1 ;
330 m_argument = Argument( m_DIM ) ;
331 m_argF = Argument( m_DIM + 1 ) ;
358 (
const AbsFunction&
function ,
364 , m_function (
function.clone() )
374 , m_epsabs ( epsabs )
375 , m_epsrel ( epsrel )
377 , m_result ( GSL_NEGINF )
378 , m_error ( GSL_POSINF )
382 if (
function.dimensionality() < 2 )
383 { Exception(
"::constructor: invalid dimensionality ") ; }
384 if ( m_index >=
function.dimensionality() )
385 { Exception(
"::constructor: invalid variable index") ; }
387 m_DIM =
function.dimensionality() - 1 ;
388 m_argument = Argument( m_DIM ) ;
389 m_argF = Argument( m_DIM + 1 ) ;
398 , m_DIM ( right.
m_DIM )
402 , m_ia ( right.
m_ia )
403 , m_ib ( right.
m_ib )
410 , m_result ( GSL_NEGINF )
411 , m_error ( GSL_POSINF )
418 m_pdata.reset(
new double[m_points.size()] );
419 std::copy( m_points.begin() , m_points.end() , m_pdata.get() );
427 (
const std::string& message ,
431 "*GaudiMath*" , sc ) ;
439 double NumericalDefiniteIntegral::operator()
440 (
const double argument )
const
443 m_result = GSL_NEGINF ;
444 m_error = GSL_POSINF ;
447 if( 1 != m_DIM ) { Exception (
"operator(): invalid argument size " ) ; };
449 m_argument[0] = argument ;
450 return (*
this) ( m_argument );
461 {
Exception (
"::partial(i): invalid variable index " ) ; };
464 return Genfun::FunctionNoop( &aux ) ;
472 double NumericalDefiniteIntegral::operator()
473 (
const Argument& argument )
const
476 m_result = GSL_NEGINF ;
477 m_error = GSL_POSINF ;
480 if( argument.dimension() != m_DIM )
481 { Exception (
"operator(): invalid argument size " ) ; };
485 for(
size_t i = 0 ;
i < m_DIM ; ++
i )
487 m_argument [
i] = argument [
i] ;
488 const size_t j =
i < m_index ?
i :
i + 1 ;
489 m_argF [j] = argument [
i] ;
493 GSL_Helper helper( *m_function , m_argF , m_index );
503 {
return QAGI ( &F1 ) ; }
507 m_result = 0 ; m_error = 0 ;
512 {
return QAGP ( &F1 ) ; }
515 {
return QNG ( &F1 ) ; }
517 {
return QAG ( &F1 ) ; }
519 {
return QAGS ( &F1 ) ; }
521 { Exception (
"::operator(): invalid type " ); }
523 { Exception (
"::operator(): invalid category " ); }
537 m_ws->ws = gsl_integration_workspace_alloc( size () );
538 if ( !
m_ws->ws ) {
Exception (
"allocate()::invalid workspace" ) ; };
550 if ( !F ) {
Exception(
"::QAGI: invalid function"); }
559 ierror = gsl_integration_qagi ( F->
fn ,
566 ierror = gsl_integration_qagil ( F->
fn ,
m_b ,
573 ierror = gsl_integration_qagiu ( F->
fn ,
m_a ,
579 {
Exception (
"::QAGI: invalid mode" ) ; };
581 if( ierror ) { gsl_error(
"NumericalDefiniteIntegral::QAGI" ,
582 __FILE__ , __LINE__ , ierror ) ;}
593 if( !F ) {
Exception(
"QAGP::invalid function") ; }
598 const size_t npts =
points().size();
602 gsl_integration_qagp ( F->
fn ,
608 if( ierror ) { gsl_error(
"NumericalDefiniteIntegral::QAGI " ,
609 __FILE__ , __LINE__ , ierror ) ; }
623 if( !F ) {
Exception(
"QNG::invalid function") ; }
626 const double low = std::min (
m_a ,
m_b ) ;
627 const double high = std::max (
m_a ,
m_b ) ;
631 gsl_integration_qng ( F->
fn ,
636 if( ierror ) { gsl_error(
"NumericalIndefiniteIntegral::QNG " ,
637 __FILE__ , __LINE__ , ierror ) ; }
652 if( !F ) {
Exception(
"QAG::invalid function") ; }
658 const double low = std::min (
m_a ,
m_b ) ;
659 const double high = std::max (
m_a ,
m_b ) ;
662 gsl_integration_qag ( F->
fn ,
665 size () , (
int)
rule() ,
ws ()->
ws ,
668 if( ierror ) { gsl_error(
"NumericalDefiniteIntegral::QAG " ,
669 __FILE__ , __LINE__ , ierror ) ; }
683 if( !F ) {
Exception(
"QAG::invalid function") ; }
696 const double low = std::min (
m_a ,
m_b ) ;
697 const double high = std::max (
m_a ,
m_b ) ;
700 gsl_integration_qags ( F->
fn ,
706 if( ierror ) { gsl_error(
"NumericalDefiniteIntegral::QAGS " ,
707 __FILE__ , __LINE__ , ierror ) ; }
StatusCode Exception(const std::string &message, const StatusCode &sc=StatusCode::FAILURE) const
Define general base for Gaudi exception.
std::unique_ptr< _Workspace, gsl_ws_deleter > m_ws
GaudiMath::Integration::Category m_category
NumericalDefiniteIntegral()
Genfun::GaudiMathImplementation::NumericalDerivative Derivative
GaudiMath::Integration::KronrodRule m_rule
This class is used for returning status codes from appropriate routines.
double QAG(_Function *fun) const
std::unique_ptr< const AbsFunction > m_function
double GSL_Adaptor(double x, void *params)
Numerical derivative (using GSL adaptive numerical differentiation)
_Workspace * allocate() const
allocate the integration workspace
GaudiMath::Integration::Type m_type
std::vector< double > Points
typedef for vector of singular points
const Points & points() const
known singularities
std::unique_ptr< double[]> m_pdata
virtual Genfun::Derivative partial(unsigned int index) const
Derivatives.
double QAGP(_Function *fun) const
GaudiMath.h GaudiMath/GaudiMath.h.
KronrodRule
integration rule
double QNG(_Function *fun) const
double QAGI(_Function *fun) const
gsl_integration_workspace * ws
the simple structure to be used for adaption interface Genfun::AbsFunction to gsl_function structure ...
Type
the list of available types for ntuples
GaudiMath::Integration::KronrodRule rule() const
integration rule
collection of common types for classes NumericalIndefiniteIntegral and NumericalDefiniteIntegral ...
double QAGS(_Function *fun) const
This class allows the numerical evaluation of the following functions: