math/statistics policy-interface feedback requested.
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
on Tue Jun 12 2007, "John Maddock"
define a typedef of the policy class:
using namespace boost::math::policy; typedef policy< // Set error handling: domain_error
, pole_error , overflow_error , evaluation_error , denorm_error , underflow_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 > 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.
Why not make it allowable to use derivation:
struct fast_quantile_policy
: policy<
// Set error handling:
domain_error
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 :-(
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com
David Abrahams wrote:
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.
Why not make it allowable to use derivation:
struct fast_quantile_policy : policy< // Set error handling: domain_error
, pole_error , overflow_error , evaluation_error , denorm_error , underflow_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 > {}; ? That will keep your type names under control.
Interesting idea. Actually as far as the code internals are concerned the only thing that matters are the member typedefs of the policy class used, so this should "just work".... but one of things I was planning on doing is "normalising" the policy class passed to the function: basically decompose it and then recompose in a particular order: that way if the same function is called with different policy types that actually name the same policies, then internally only one template gets instantiated and we reduce code bloat. The same mechanism can stip out policies that have no relevence to the function being called, again potentially reducing code bloat. At present I don't see a way to combine that with your inheritance mechanism. I also need to be able to inject certain computed policies into the policy object when it get's normalised (basically a combination of the existing policy and it's combination with the actual real-number type being used for the computation). I do have a Boost.Format based mechanism to create nicely formatted function names though - and yes only invoked when needed - so I guess the question is whether these long mangled names have any other consequences: compile and or link time for example? Thanks, John.
participants (2)
-
David Abrahams
-
John Maddock