![]() |
Home | Libraries | People | FAQ | More |
There are a number of Policies that can be used to trade accuracy for performance:
float
arguments are evaluated at double
precision internally to ensure full precision in the result. double precision functions are evaluated
at double precision by default
(older releases promoted them to long
double, which is slow on x86 and
very slow where long double
is software emulated). Changing the float
default can have a significant speed advantage at the expense of accuracy,
note also that evaluating using float
internally may result in numerical instability for some of the more complex
algorithms, we suggest you use this option with care. Defining BOOST_MATH_PROMOTE_DOUBLE_POLICY as
true turns promotion of double on again for the extra accuracy.
double
precision doesn't mean you necessarily want to target full 16-digit accuracy,
if you wish you can change the default (full machine precision) to whatever
is "good enough" for your particular use case.
For example, suppose you want float
precision functions to be evaluated at float
precision internally, you can change the global default by passing -DBOOST_MATH_PROMOTE_FLOAT_POLICY=false on the
command line. Likewise, to get the extra accuracy of long
double for double
functions, pass -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=true. Either
can also be selected at the point of call via something like this:
double val = boost::math::erf(my_argument, boost::math::policies::make_policy(boost::math::policies::promote_double<true>()));
However, an easier option might be:
#include <boost/math/special_functions.hpp> // Or any individual special function header namespace math{ namespace precise{ // // Define a Policy for accurate evaluation - double is evaluated internally at // long double precision (the default evaluates double at double precision): // typedef boost::math::policies::policy<boost::math::policies::promote_double<true> > accurate_policy; // // Invoke BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS to declare // functions that use the above policy. Note no trailing // ";" required on the macro call: // BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(accurate_policy) } namespace fast{ // // Define a Policy for fast evaluation: // using namespace boost::math::policies; typedef policy<promote_double<false> > fast_policy; // // Invoke BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS: // BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(fast_policy) } }
And now one can call:
math::accurate::tgamma(x);
For the "accurate" version of tgamma, and:
math::fast::tgamma(x);
For the faster version.
Had we wished to change the target precision (to 9 decimal places) as well as the evaluation type used, we might have done:
namespace math{ namespace fast{ // // Define a Policy for fast evaluation: // using namespace boost::math::policies; typedef policy<promote_double<false>, digits10<9> > fast_policy; // // Invoke BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS: // BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(fast_policy) } }
One can do a similar thing with the distribution classes:
#include <boost/math/distributions.hpp> // or any individual distribution header namespace math{ namespace fast{ // // Define a policy for fastest possible evaluation: // using namespace boost::math::policies; typedef policy<promote_float<false> > fast_float_policy; // // Invoke BOOST_MATH_DECLARE_DISTRIBUTIONS // BOOST_MATH_DECLARE_DISTRIBUTIONS(float, fast_float_policy) }} // namespaces // // And use: // float p_val = cdf(math::fast::normal(1.0f, 3.0f), 0.25f);
Here's how these options change the relative performance of the distributions on Linux:
Table 24.2. Distribution performance comparison for different performance options with GNU C++ version 9.2.1 20191008 on linux
|
Function |
boost 1.73 |
Boost |
Boost |
Boost |
|---|---|---|---|---|
|
ArcSine (CDF) |
1.75 |
1.65 |
1.65 |
1.00 |
|
ArcSine (PDF) |
1.00 |
1.00 |
1.00 |
1.20 |
|
ArcSine (quantile) |
1.04 |
1.00 |
1.04 |
1.00 |
|
Beta (CDF) |
4.41 |
1.40 |
1.38 |
1.00 |
|
Beta (PDF) |
4.29 |
1.23 |
1.24 |
1.00 |
|
Beta (quantile) |
4.17 |
1.60 |
1.44 |
1.00 |
|
Binomial (CDF) |
3.97 |
1.54 |
1.26 |
1.00 |
|
Binomial (PDF) |
2.90 |
1.09 |
1.09 |
1.00 |
|
Binomial (quantile) |
3.88 |
1.53 |
1.26 |
1.00 |
|
Cauchy (CDF) |
1.15 |
1.15 |
1.00 |
1.00 |
|
Cauchy (PDF) |
1.00 |
1.00 |
1.00 |
1.33 |
|
Cauchy (quantile) |
1.88 |
2.00 |
1.79 |
1.00 |
|
ChiSquared (CDF) |
3.54 |
1.79 |
1.40 |
1.00 |
|
ChiSquared (PDF) |
4.84 |
1.41 |
1.38 |
1.00 |
|
ChiSquared (quantile) |
3.76 |
1.84 |
1.37 |
1.00 |
|
Exponential (CDF) |
1.27 |
1.87 |
1.60 |
1.00 |
|
Exponential (PDF) |
1.58 |
1.84 |
2.00 |
1.00 |
|
Exponential (quantile) |
1.00 |
1.13 |
1.17 |
1.04 |
|
ExtremeValue (CDF) |
1.78 |
1.81 |
1.81 |
1.00 |
|
ExtremeValue (PDF) |
1.96 |
1.85 |
1.83 |
1.00 |
|
ExtremeValue (quantile) |
1.43 |
1.38 |
1.43 |
1.00 |
|
F (CDF) |
4.46 |
1.58 |
1.24 |
1.00 |
|
F (PDF) |
3.37 |
1.18 |
1.12 |
1.00 |
|
F (quantile) |
2.70 |
1.28 |
1.03 |
1.00 |
|
Gamma (CDF) |
3.90 |
1.46 |
1.47 |
1.00 |
|
Gamma (PDF) |
5.75 |
1.49 |
1.51 |
1.00 |
|
Gamma (quantile) |
4.35 |
1.80 |
1.22 |
1.00 |
|
Geometric (CDF) |
1.00 |
1.08 |
1.08 |
1.16 |
|
Geometric (PDF) |
1.44 |
1.44 |
1.56 |
1.00 |
|
Geometric (quantile) |
1.00 |
1.12 |
1.04 |
1.24 |
|
Hypergeometric (CDF) |
1.08 |
1.00 |
1.02 |
1.07 |
|
Hypergeometric (PDF) |
1.16 |
1.00 |
1.02 |
1.09 |
|
Hypergeometric (quantile) |
1.00 |
1.27 |
1.24 |
1.14 |
|
InverseChiSquared (CDF) |
3.06 |
1.60 |
1.31 |
1.00 |
|
InverseChiSquared (PDF) |
4.42 |
1.63 |
1.52 |
1.00 |
|
InverseChiSquared (quantile) |
2.92 |
1.66 |
1.21 |
1.00 |
|
InverseGamma (CDF) |
3.17 |
1.41 |
1.18 |
1.00 |
|
InverseGamma (PDF) |
5.26 |
1.54 |
1.49 |
1.00 |
|
InverseGamma (quantile) |
4.02 |
1.69 |
1.19 |
1.00 |
|
InverseGaussian (CDF) |
1.89 |
1.94 |
1.99 |
1.00 |
|
InverseGaussian (PDF) |
1.53 |
1.53 |
1.53 |
1.00 |
|
InverseGaussian (quantile) |
2.09 |
2.26 |
2.14 |
1.00 |
|
Laplace (CDF) |
1.58 |
1.62 |
1.62 |
1.00 |
|
Laplace (PDF) |
1.56 |
1.59 |
1.59 |
1.00 |
|
Laplace (quantile) |
1.39 |
1.43 |
1.36 |
1.00 |
|
LogNormal (CDF) |
2.12 |
1.33 |
1.36 |
1.00 |
|
LogNormal (PDF) |
1.68 |
1.73 |
1.70 |
1.00 |
|
LogNormal (quantile) |
1.75 |
1.68 |
1.40 |
1.00 |
|
Logistic (CDF) |
1.52 |
1.52 |
1.74 |
1.00 |
|
Logistic (PDF) |
1.59 |
1.59 |
1.59 |
1.00 |
|
Logistic (quantile) |
1.23 |
1.23 |
1.27 |
1.00 |
|
NegativeBinomial (CDF) |
4.51 |
1.80 |
1.37 |
1.00 |
|
NegativeBinomial (PDF) |
3.62 |
1.07 |
1.07 |
1.00 |
|
NegativeBinomial (quantile) |
3.26 |
1.27 |
1.00 |
1.15 |
|
NonCentralBeta (CDF) |
4.88 |
1.80 |
1.61 |
1.00 |
|
NonCentralBeta (PDF) |
3.83 |
1.55 |
1.42 |
1.00 |
|
NonCentralBeta (quantile) |
7.51 |
2.59 |
2.26 |
1.00 |
|
NonCentralChiSquared (CDF) |
2.90 |
1.82 |
1.43 |
1.00 |
|
NonCentralChiSquared (PDF) |
3.52 |
1.61 |
1.54 |
1.00 |
|
NonCentralChiSquared (quantile) |
4.15 |
2.33 |
1.56 |
1.00 |
|
NonCentralF (CDF) |
4.26 |
1.55 |
1.36 |
1.00 |
|
NonCentralF (PDF) |
3.98 |
1.49 |
1.29 |
1.00 |
|
NonCentralF (quantile) |
4.52 |
1.57 |
1.31 |
1.00 |
|
NonCentralT (CDF) |
3.79 |
1.72 |
1.52 |
1.00 |
|
NonCentralT (PDF) |
3.41 |
1.93 |
1.75 |
1.00 |
|
NonCentralT (quantile) |
5.06 |
2.17 |
1.65 |
1.00 |
|
Normal (CDF) |
2.24 |
1.34 |
1.28 |
1.00 |
|
Normal (PDF) |
1.55 |
1.50 |
1.59 |
1.00 |
|
Normal (quantile) |
1.68 |
1.18 |
1.24 |
1.00 |
|
Pareto (CDF) |
1.40 |
1.46 |
1.40 |
1.00 |
|
Pareto (PDF) |
1.95 |
1.95 |
2.09 |
1.00 |
|
Pareto (quantile) |
1.76 |
1.79 |
1.72 |
1.00 |
|
Poisson (CDF) |
3.38 |
1.56 |
1.45 |
1.00 |
|
Poisson (PDF) |
4.19 |
1.54 |
1.52 |
1.00 |
|
Poisson (quantile) |
3.04 |
1.38 |
1.35 |
1.00 |
|
Rayleigh (CDF) |
1.35 |
1.41 |
1.41 |
1.00 |
|
Rayleigh (PDF) |
1.68 |
1.64 |
1.64 |
1.00 |
|
Rayleigh (quantile) |
1.04 |
1.04 |
1.00 |
1.08 |
|
SkewNormal (CDF) |
1.43 |
1.31 |
1.31 |
1.00 |
|
SkewNormal (PDF) |
2.07 |
1.31 |
1.29 |
1.00 |
|
SkewNormal (quantile) |
2.16 |
1.85 |
1.31 |
1.00 |
|
StudentsT (CDF) |
6.44 |
2.23 |
2.21 |
1.00 |
|
StudentsT (PDF) |
6.58 |
1.60 |
1.52 |
1.00 |
|
StudentsT (quantile) |
5.79 |
1.87 |
1.86 |
1.00 |
|
Weibull (CDF) |
1.73 |
1.73 |
1.75 |
1.00 |
|
Weibull (PDF) |
1.98 |
1.98 |
1.98 |
1.00 |
|
Weibull (quantile) |
1.21 |
1.21 |
1.19 |
1.00 |