Boost logo

Boost :

From: John Maddock (john_at_[hidden])
Date: 2007-06-12 05:37:38


Following the successful review of the math-toolkit of special functions and
statistical distributions the main feature request was for a better way of
customising the library: both for choosing between precision vs speed
tradeoffs, and for determining how errors are best handled. I've been
experimenting with various policy-based interfaced based on Boost.Parameter,
and I think I now have something useable, so I'd like to know what people
think:

Policy Defaults
~~~~~~~~~~~~~~~

The library will use a sensible set of defaults (throw on domain errors and
internal evaluation errors, favour accuracy over speed etc), which can be
changed via the usual macro mechanism, so adding:

#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error
#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignor_error

to a user-config header would do what they say to the default policies.

Add Hock Changes:
~~~~~~~~~~~~~~~~~

We can create an ad-hock policy change at the call site by using the
make_policy function, for example:

using namespace boost::math::policy;
using namespace boost::math;

quantile(
    poisson(100),
    0.05,
    make_policy(
        // 5 dicimal digits precision only
        digits10<10>(),
        // don't internally promote double->long double for extra precision:
        promote_double<false>(),
        // return integer result, immediately below the "real" value:
        discrete_quantile<integer_below>()
    ));

Which returns the lower 95% quantile (ie critical value) of a poisson
distribution with rate parameter of 100 event's per unit time. The result
is calculated using only 10 decimal digits internal precision, truncated to
the largest integer that gives a CDF less than 0.05.

Predefined Policies
~~~~~~~~~~~~~~~~~~~

Although ad-hock policies are useful for testing, I imagine most sites would
want a few carefully controlled (and tested) policies. To achieve that you
define a typedef of the policy class:

using namespace boost::math::policy;
typedef policy<
    // Set error handling:
    domain_error<throw_on_error>,
    pole_error<throw_on_error>,
    overflow_error<throw_on_error>,
    evaluation_error<throw_on_error>,
    denorm_error<ignor_error>,
    underflow_error<ignor_error>,
    // calculate to 8 decimal digits internally
    digits10<8>,
    // don't promote double->long double for accuracy
    promote_double<false>,
    // Integer quantiles return the "outside edge":
    // below the real value for lower critical values,
    // above it for upper critical values, so that the
    // area inside contains *at least* the requested coverage:
    discrete_quantile<integer_outside_edge>
> fast_quantile_policy;

static fast_quantile_policy fast_quantile;

Then we can just use:

quantile(
    poisson(100),
    0.05,
    fast_quantile);

In our actual code.

Currently this policy interface is vapourware: I have enough of a prototype
implemented to know that it's possible to achieve this syntax (this is
revision #3 already !), but there's a lot of hairy meta-programming to
convert that into something that the library's internals can make use of...
so I'd like to know what folks think before I invest too much time messing
about with MPL :-)

The main disadvantage I've noticed at present, is that the mangled names of
the policy class - and therefore all the special functions etc - are *very*
long. This has an impact on error messages: in particular we currently use
BOOST_CURRENT_FUNCTION to get a nice formatted name of a function that's
about to throw, but with function names a couple of pages long I don't think
that will be possible with this interface any more :-(

Thanks in advance, John Maddock.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk