| Home | Libraries | People | FAQ | More

## Trading Accuracy for Performance

There are a number of Policies that can be used to trade accuracy for performance:

- Internal promotion: by default functions with `float` arguments are evaluated at `double` precision internally to ensure full precision in the result. Similarly `double` precision functions are evaluated at `long double` precision internally by default. Changing these defaults 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.
- Target accuracy: just because you choose to evaluate at `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 to evaluate `double` precision functions at `double` precision internally, you can change the global default by passing `-DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false` on the command line, or 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<false>()));

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 - this is the same as the default, unless
    // someone has changed the global defaults.
    //
    typedef boost::math::policies::policy<> 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 22.2. Distribution performance comparison for different performance options with GNU C++ version 9.2.1 20191008 on linux

Function | boost 1.73 | Boost promote_double<false> | Boost promote_double<false> digits10<10> | Boost float promote_float<false>
--- | --- | --- | --- | ---
ArcSine (CDF) | 1.75 (35ns) | 1.65 (33ns) | 1.65 (33ns) | 1.00 (20ns)
ArcSine (PDF) | 1.00 (5ns) | 1.00 (5ns) | 1.00 (5ns) | 1.20 (6ns)
ArcSine (quantile) | 1.04 (24ns) | 1.00 (23ns) | 1.04 (24ns) | 1.00 (23ns)
Beta (CDF) | 4.41 (437ns) | 1.40 (139ns) | 1.38 (137ns) | 1.00 (99ns)
Beta (PDF) | 4.29 (360ns) | 1.23 (103ns) | 1.24 (104ns) | 1.00 (84ns)
Beta (quantile) | 4.17 (2587ns) | 1.60 (991ns) | 1.44 (893ns) | 1.00 (620ns)
Binomial (CDF) | 3.97 (837ns) | 1.54 (324ns) | 1.26 (265ns) | 1.00 (211ns)
Binomial (PDF) | 2.90 (322ns) | 1.09 (121ns) | 1.09 (121ns) | 1.00 (111ns)
Binomial (quantile) | 3.88 (3917ns) | 1.53 (1548ns) | 1.26 (1273ns) | 1.00 (1009ns)
Cauchy (CDF) | 1.15 (23ns) | 1.15 (23ns) | 1.00 (20ns) | 1.00 (20ns)
Cauchy (PDF) | 1.00 (3ns) | 1.00 (3ns) | 1.00 (3ns) | 1.33 (4ns)
Cauchy (quantile) | 1.88 (45ns) | 2.00 (48ns) | 1.79 (43ns) | 1.00 (24ns)
ChiSquared (CDF) | 3.54 (1002ns) | 1.79 (506ns) | 1.40 (397ns) | 1.00 (283ns)
ChiSquared (PDF) | 4.84 (295ns) | 1.41 (86ns) | 1.38 (84ns) | 1.00 (61ns)
ChiSquared (quantile) | 3.76 (1664ns) | 1.84 (815ns) | 1.37 (609ns) | 1.00 (443ns)
Exponential (CDF) | 1.27 (19ns) | 1.87 (28ns) | 1.60 (24ns) | 1.00 (15ns)
Exponential (PDF) | 1.58 (30ns) | 1.84 (35ns) | 2.00 (38ns) | 1.00 (19ns)
Exponential (quantile) | 1.00 (23ns) | 1.13 (26ns) | 1.17 (27ns) | 1.04 (24ns)
ExtremeValue (CDF) | 1.78 (57ns) | 1.81 (58ns) | 1.81 (58ns) | 1.00 (32ns)
ExtremeValue (PDF) | 1.96 (90ns) | 1.85 (85ns) | 1.83 (84ns) | 1.00 (46ns)
ExtremeValue (quantile) | 1.43 (53ns) | 1.38 (51ns) | 1.43 (53ns) | 1.00 (37ns)
F (CDF) | 4.46 (817ns) | 1.58 (289ns) | 1.24 (227ns) | 1.00 (183ns)
F (PDF) | 3.37 (361ns) | 1.18 (126ns) | 1.12 (120ns) | 1.00 (107ns)
F (quantile) | 2.70 (2615ns) | 1.28 (1241ns) | 1.03 (995ns) | 1.00 (969ns)
Gamma (CDF) | 3.90 (714ns) | 1.46 (267ns) | 1.47 (269ns) | 1.00 (183ns)
Gamma (PDF) | 5.75 (437ns) | 1.49 (113ns) | 1.51 (115ns) | 1.00 (76ns)
Gamma (quantile) | 4.35 (1827ns) | 1.80 (755ns) | 1.22 (511ns) | 1.00 (420ns)
Geometric (CDF) | 1.00 (25ns) | 1.08 (27ns) | 1.08 (27ns) | 1.16 (29ns)
Geometric (PDF) | 1.44 (23ns) | 1.44 (23ns) | 1.56 (25ns) | 1.00 (16ns)
Geometric (quantile) | 1.00 (25ns) | 1.12 (28ns) | 1.04 (26ns) | 1.24 (31ns)
Hypergeometric (CDF) | 1.08 (66745ns) | 1.00 (61922ns) | 1.02 (62901ns) | 1.07 (66289ns)
Hypergeometric (PDF) | 1.16 (73824ns) | 1.00 (63790ns) | 1.02 (65130ns) | 1.09 (69844ns)
Hypergeometric (quantile) | 1.00 (131293ns) | 1.27 (166268ns) | 1.24 (163105ns) | 1.14 (149745ns)
InverseChiSquared (CDF) | 3.06 (1538ns) | 1.60 (803ns) | 1.31 (657ns) | 1.00 (502ns)
InverseChiSquared (PDF) | 4.42 (367ns) | 1.63 (135ns) | 1.52 (126ns) | 1.00 (83ns)
InverseChiSquared (quantile) | 2.92 (2328ns) | 1.66 (1322ns) | 1.21 (963ns) | 1.00 (797ns)
InverseGamma (CDF) | 3.17 (806ns) | 1.41 (359ns) | 1.18 (299ns) | 1.00 (254ns)
InverseGamma (PDF) | 5.26 (515ns) | 1.54 (151ns) | 1.49 (146ns) | 1.00 (98ns)
InverseGamma (quantile) | 4.02 (2187ns) | 1.69 (921ns) | 1.19 (645ns) | 1.00 (544ns)
InverseGaussian (CDF) | 1.89 (236ns) | 1.94 (242ns) | 1.99 (249ns) | 1.00 (125ns)
InverseGaussian (PDF) | 1.53 (23ns) | 1.53 (23ns) | 1.53 (23ns) | 1.00 (15ns)
InverseGaussian (quantile) | 2.09 (3530ns) | 2.26 (3823ns) | 2.14 (3611ns) | 1.00 (1688ns)
Laplace (CDF) | 1.58 (41ns) | 1.62 (42ns) | 1.62 (42ns) | 1.00 (26ns)
Laplace (PDF) | 1.56 (42ns) | 1.59 (43ns) | 1.59 (43ns) | 1.00 (27ns)
Laplace (quantile) | 1.39 (39ns) | 1.43 (40ns) | 1.36 (38ns) | 1.00 (28ns)
LogNormal (CDF) | 2.12 (225ns) | 1.33 (141ns) | 1.36 (144ns) | 1.00 (106ns)
LogNormal (PDF) | 1.68 (74ns) | 1.73 (76ns) | 1.70 (75ns) | 1.00 (44ns)
LogNormal (quantile) | 1.75 (105ns) | 1.68 (101ns) | 1.40 (84ns) | 1.00 (60ns)
Logistic (CDF) | 1.52 (41ns) | 1.52 (41ns) | 1.74 (47ns) | 1.00 (27ns)
Logistic (PDF) | 1.59 (43ns) | 1.59 (43ns) | 1.59 (43ns) | 1.00 (27ns)
Logistic (quantile) | 1.23 (37ns) | 1.23 (37ns) | 1.27 (38ns) | 1.00 (30ns)
NegativeBinomial (CDF) | 4.51 (1354ns) | 1.80 (540ns) | 1.37 (410ns) | 1.00 (300ns)
NegativeBinomial (PDF) | 3.62 (445ns) | 1.07 (131ns) | 1.07 (132ns) | 1.00 (123ns)
NegativeBinomial (quantile) | 3.26 (7468ns) | 1.27 (2918ns) | 1.00 (2294ns) | 1.15 (2649ns)
NonCentralBeta (CDF) | 4.88 (2083ns) | 1.80 (769ns) | 1.61 (689ns) | 1.00 (427ns)
NonCentralBeta (PDF) | 3.83 (1265ns) | 1.55 (511ns) | 1.42 (468ns) | 1.00 (330ns)
NonCentralBeta (quantile) | 7.51 (55809ns) | 2.59 (19273ns) | 2.26 (16812ns) | 1.00 (7433ns)
NonCentralChiSquared (CDF) | 2.90 (4498ns) | 1.82 (2821ns) | 1.43 (2220ns) | 1.00 (1552ns)
NonCentralChiSquared (PDF) | 3.52 (953ns) | 1.61 (436ns) | 1.54 (416ns) | 1.00 (271ns)
NonCentralChiSquared (quantile) | 4.15 (31465ns) | 2.33 (17712ns) | 1.56 (11870ns) | 1.00 (7586ns)
NonCentralF (CDF) | 4.26 (1828ns) | 1.55 (667ns) | 1.36 (584ns) | 1.00 (429ns)
NonCentralF (PDF) | 3.98 (1506ns) | 1.49 (564ns) | 1.29 (488ns) | 1.00 (378ns)
NonCentralF (quantile) | 4.52 (29414ns) | 1.57 (10228ns) | 1.31 (8543ns) | 1.00 (6504ns)
NonCentralT (CDF) | 3.79 (6416ns) | 1.72 (2907ns) | 1.52 (2572ns) | 1.00 (1691ns)
NonCentralT (PDF) | 3.41 (4034ns) | 1.93 (2284ns) | 1.75 (2065ns) | 1.00 (1182ns)
NonCentralT (quantile) | 5.06 (68590ns) | 2.17 (29386ns) | 1.65 (22334ns) | 1.00 (13546ns)
Normal (CDF) | 2.24 (150ns) | 1.34 (90ns) | 1.28 (86ns) | 1.00 (67ns)
Normal (PDF) | 1.55 (34ns) | 1.50 (33ns) | 1.59 (35ns) | 1.00 (22ns)
Normal (quantile) | 1.68 (57ns) | 1.18 (40ns) | 1.24 (42ns) | 1.00 (34ns)
Pareto (CDF) | 1.40 (49ns) | 1.46 (51ns) | 1.40 (49ns) | 1.00 (35ns)
Pareto (PDF) | 1.95 (86ns) | 1.95 (86ns) | 2.09 (92ns) | 1.00 (44ns)
Pareto (quantile) | 1.76 (51ns) | 1.79 (52ns) | 1.72 (50ns) | 1.00 (29ns)
Poisson (CDF) | 3.38 (264ns) | 1.56 (122ns) | 1.45 (113ns) | 1.00 (78ns)
Poisson (PDF) | 4.19 (218ns) | 1.54 (80ns) | 1.52 (79ns) | 1.00 (52ns)
Poisson (quantile) | 3.04 (1193ns) | 1.38 (540ns) | 1.35 (528ns) | 1.00 (392ns)
Rayleigh (CDF) | 1.35 (23ns) | 1.41 (24ns) | 1.41 (24ns) | 1.00 (17ns)
Rayleigh (PDF) | 1.68 (37ns) | 1.64 (36ns) | 1.64 (36ns) | 1.00 (22ns)
Rayleigh (quantile) | 1.04 (27ns) | 1.04 (27ns) | 1.00 (26ns) | 1.08 (28ns)
SkewNormal (CDF) | 1.43 (691ns) | 1.31 (633ns) | 1.31 (635ns) | 1.00 (483ns)
SkewNormal (PDF) | 2.07 (174ns) | 1.31 (110ns) | 1.29 (108ns) | 1.00 (84ns)
SkewNormal (quantile) | 2.16 (6788ns) | 1.85 (5813ns) | 1.31 (4118ns) | 1.00 (3143ns)
StudentsT (CDF) | 6.44 (1893ns) | 2.23 (656ns) | 2.21 (650ns) | 1.00 (294ns)
StudentsT (PDF) | 6.58 (724ns) | 1.60 (176ns) | 1.52 (167ns) | 1.00 (110ns)
StudentsT (quantile) | 5.79 (2959ns) | 1.87 (954ns) | 1.86 (951ns) | 1.00 (511ns)
Weibull (CDF) | 1.73 (69ns) | 1.73 (69ns) | 1.75 (70ns) | 1.00 (40ns)
Weibull (PDF) | 1.98 (117ns) | 1.98 (117ns) | 1.98 (117ns) | 1.00 (59ns)
Weibull (quantile) | 1.21 (69ns) | 1.21 (69ns) | 1.19 (68ns) | 1.00 (57ns)