Design of C++ Mathematical Libraries
Introduction
These library written in C++ provide the mathematical functionality required by the LHC experiments. Background information is the inventory of mathematical functions
Requirements
Main user of this software will be :
- software developers of LHC experiments writing simulation, reconstruction or event analysis applications. They will use the libraries together with the experiment framework
- Any physicists performing data analysis using a C++ program without any link to a particular analysis tools or framework
- Users of the ROOT Analysis framework working both in C++ or interactively using Cint
- Users working interactively in Python in connection with the available analysis and numerical tools provided with the language and by other LCG projects.
- Developers and user of any other analysis tools who uses the library through interfaces provided by the tool itself. An example is a user performing a fit using Minuit inside HippoDraw
General requirements
- Modularity, software should be composed from a set of components with as little couplings as possible
- ....
MathLib Components
We have identified the following components according to the functionality. A component a priori is not a priori relflects in a unique library. See packaging for library organization and distribution
- Mathematical functions: library of special functions and statistical functions
needed for HEP.
- C++ Function classes: library of classes describing generic functions, parametric
functions or probability density functions.
- Numerical algorithms: library containing the methods for numerical integration,
differentiation, function minimization, root finders, interpolators, etc..
- Linear algebra: library with vector and matrix classes and their operations.
- Random number generator: library with collections of generators and methods for generating
random numbers according to distributions.
Mathematical Functions
This library contains free functions in the namespace mathlib.
At the beginning will consist of only one library containing the most used functions. If the size of this library will become too large, functions which will be used less will be demoted to an additional library.
Library content
These functions are special functions and statistical functions. The functions we propose for the first version of the library are the following
Special functions
- Bessel functions, all cylindrical types (J,I,K) for fractional order and spherical (j,i) for interger order
- Error functions
- Exponential integrals
- Hypergeometric functions
- Beta function
- Zeta function
-
Statistical functions
This functions include probability density functions and corresponding cumulative distributions (integrals of the pdf)
- Gaussian
- Breit Wigner
- Landau
- Gamma
- Chi2-
- Lognormal
- F distribution
- Student t distribution
- Poisson
- Binomial
- Multinomial
- Kolgomorov
-
-
Others
Polynomial (evaluation)
Detailed Design
Following the C++ proposal, the library consists of free functions in a namespace.
We will have one (or more) header files defining the functions with no reference to the implementation.
As first choice we prefer to hide the implementation, therefore the functions will not be inlined. This will cause a small performance penalty, which is negligible for computational expensive functions.
Here is the effect on performances on a function evaluating a polynomial as function of order.
Here is example for Bessel function :
SpecFunc.h
namespace mathlib {
double cyl_bessel_j(double nu, double x);
double cyl_bessel_i(double nu, double x);
....
double erfc (double x);
}
Implementation based on GSL
SpecFunc.cpp
#include "MathFunc/SpecFunc.h"
#include "gsl/gsl_sf.h"
mathlib::cyl_bessel_j( double nu, double x) {
return gsl_sf_bessel_Jnu (nu, x);
}
Error Handling
In the shown example no error handling is provided. In reality we want to handle them and the proposed approach is to use the Exception classes from the standard library.
Errors that can occur in functions are:
- Domain Error when an input argument is in a domain where the function is not defined.
- Range error, used when the result is not representable (example when Nan is produced)
C++ Function Classes
This library contains the interface and classes to describe generic functions. These are needed to have a uniform
way of using the numerical algorithms. Therefore with same function object, the user can evaluate its integral numerically, can used to fit his data or can compose it with other function objects. In addition, either using the same interfaces of through simple adapters the function objects can be passed to tools like ROOT to be displayed.
The ideas here are inspired by the Generic functions of
CLHEP and it is adapted to our needs.
We provide the following classes and interfaces:
Interfaces:
-
IGenFunction
defines generic interface for single dimensional functions. Provides function value and optionally gradient. A providesGradient() method is needed at run-time to query whether the function provides it and algorithms which makes use of the gradient can be used. An alternative solution would have been to have a separate interface for functions providing gradient, having the advantages of using types for distinguishing between algorithms. However, we pay in flexibilities, and we might need to relying on the type information provided at run time.
virtual double operator() (double x) = 0;
virtual double gradient( double x) = 0;
virtual bool providesGradient() const = 0;
-
IMDGenFunction
Multidimensional generic function. Defines:
virtual double operator() (const std::vector & x) = 0;
virtual const std::vector<double> & gradient ( const std::vector<double> & x) = 0;
virtual bool providesGradient() const = 0;
-
IParamFunction
Interface describing functions with parameters. It inherits from IGenFunction and defines in addition methods to set and retrieve the parameters:
virtual void setParameters(const std::vector<double> & p) = 0;
virtual const std::vector<double> & parameters() = 0;
virtual const std::vector<double> & parameterGradient( double x) = 0;
-
IMDParamFunction
Parameteric function interface for multi-dimensions
Base Classes:
Concrete Classes
Here are classes representing the various type of functions (especially statistical one), such as Gaussian, Exponential, etc...., inheriting either from ParamFunction or from PdfFunction. A typical use-case for this functions is in fitting, the user, compose in a trivial way it's own model functions using the provided functions from the library.
Numerical Algorithms
This library will contain the various algorithms. We describe here their design and how the make use of the C++ Function library. The basic idea here is to separate as much as possible the interface of the numerical algorithm to the underlying implementation of the algorithm.
We plan to have a core numerical algorithms library which we'll have the algorithm interfaces and concrete classes with default implementations, which in the majority of the cases will be based for the moment on GSL. Addition implementation of the algorithms which can be present in a different library will be able to be added and used with a plug-in manager. The plugin-manager will reside in a separate library.
Numerical Integration
We will have an interface Integrator. This interface will define a method to set and retrieve control parameters, like tolerance, number of points, etc.., then the following method to perform the integration will be present:
double eval(const IGenFunction & f, double a, double b);
The concrete class implementing the Integrator interfaces, would have in addition the following method based on a generic (templated) function class :
template <class UserFunc>
double eval(const UserFunc & f, double a, double b);
Having a templated method taking a function, which needs just to implement the operator(), gives the advantage of avoid virtual calls, when evaluating the function values inside the algorithm. Since templated member function cannot be virtual, this method can be present only in the concrete class and not in the interface.
We plan to have the first integrator implementations based on GSL. In this case, in addition to the template method, the class will have also the following method based on function pointers, for users which do not want to use our function interfaces and want to call the integrator class directly using a free C function, avoiding the use of adapters.
We use the same signature for the function pointer as GSL.
typedef double ( * FuncPointer ) ( double, void * );
double eval( FuncPointer f, double a, double b);
In GSL, there are various numerical integration algorithms. We plan to include these algorithms:
- Finite intervals algorithms
- Non adaptive (fixed) Gauss-Kronrod integration (QNG)
- Adaptive Gauss-Kronrod integration (QAG) for finite intervals. In this case the user can specify the integration rule (15, 21, 31, 41, 51, or 61 point GK rule)
- Adapative integration with singularity (QAGS). The rule used is 21 point
- Adapative integration with singularity at known points (QAGP). The algorithms takes account of the user supplied points.
- Integration on infinite intervals
- Adaptive integration over the interval (-inf, + inf). Used QAGS with 15 rule
- Integration between (a, + inf)
- Integration between (-inf, b)
- Integrations with weight functions
-
Other algorithms exist in GSL, for Cauchy principal values (QAWC) , for log singularities (QAWS), for oscillatory functions (QAWO) anf Foutier integrals (QAWF). These algorithms will for the moment not implemented in the core library.
We have two possibility for implementing these algorithms. One is having a common class and choosing the type of algorithms using a string (or an enumeration parameters) in the constructor. The second possibility is having a different class for each type of algorithm. In this case would be convenient to present to the user a common base class inheriting from the Integrator interface which creates the different class representing each algorithm behind.
Numerical Differentiation
This algorithm provides differentiation by finite difference. It will consists of a set of functions in a Differentiator class.
Required methods for the interface, would be:
double eval( const IGenFunction & f, double x);
// in case of singularity or if f is defined only for values greater than x
double evalForward( const IGenFunction & f, double x);
// in case of singularity or if f is defined only for values smaller than x
double evalBackward( const IGenFunction & f, double x);
In addition, we will have like in the Integrator class, the template methods and those based on the free function pointer, double ( * ) (double, void *)
template <class UserFunc>
double eval(const UserFunc & f, double x);
typedef double ( * FuncPointer ) ( double, void * );
double eval( FuncPointer f, double x);
Root Finders
We'll have here algorithms to find the root of a function in one or multi-dimensions. Interfaces will exist in both case, using function classes of type IGenFunction or IMDGenFunction.
In addition exist algorithms which needs the function gradient.
A Root Finder base class is created taking as argument the algorithm type.
The proposed methods for the are:
double
Interpolation
Random numbers
The random number library will be implemented according to the design proposed for the C++ Standard library (see proposal document). This library will provide a palette of random number generators and possibility of generating random numbers according to pre-defined distributions.
The development of this library has a lower priority, since very good solution exist, like CLHEP, which is widely used by our community.
Linear Algebra
Also for the linear algebra, various library already exist, and before developing any new one, we evaluate the exist ones.
Library packaging
We expect to have this libraries:
- Core Mathematical functions (size exp. 0.5-1 MB)
- Function Classes (exp size approx 1 MB)
- Basic Numerical Algorithms (exp size 1-2 MB)
- Additional functions (really needed ? , size probably not more 1MB)
- Extension Algorithms (including additional minimization algorithms)
- Fitting Libraries (by default based on Minuit) (size approx 1 MB)
- Minuit (size approx 1 MB)
Contact:
Lorenzo Moneta
last update: 30 August 2004