Boost logo

Boost :

From: Eric Ford (eford_at_[hidden])
Date: 2001-09-07 03:33:05


I thought a little bit about this and made up a straw man interface.
Comments are invited. Code can be found at
http://www.astro.princeton.edu/~eford/math/interface/

Basically, I identified the things that I thought should be accessible
to every (mathematical) function:
1. return value(s) type
2. argument(s) type
3. means to specify/ensure accuracey requirements
4. means to specify/ensure domain checking
5. means of error handeling

Some functions will also need additional parameters, which I'll add as
[0. function parameter(s) type ] (not all functions will have this)
I labeled this as 0, indicating that when used the function
parameter(s) parameter would come before the return value.

I treat each as a template parameter. I know 5 or 6 parameters is a
lot, but 2-5 can use default types and default constructors. (For
several functions even a default return value might make some sense.)
Paramters 0-2 are pretty much unavoidable for mathematical functions.
 
(I forsee dealing with multiple parameters, return values, or
arguments using the tuple library.)

In principle, the accuracey parameter allows users to specify the
accuracey they need and an algorithm or number of iterations could be
chosen to meet this need. By making the class that does this a
template parameter, users who just want the fastest answer can use
something like my accuracey_check_dont_bother which doesn't do any
checking and would signify to the class to chose a fast algorithm.

The domain checking parameter allows users to specify what checking is
done. For users desiring speed, a class such as my
domain_check_dont_bother can be used which eliminates such checks.
Users needing only to check if arguments are in a constant domain can
use something like my class domain_check_std. Users needing more
complicated checks can supply their own domain checking class. For
example, the domain could in principle have several regions or depend
on the function parameters (not to be confused with the template
parameters).

WRT the error handeling parameter... Again, some users want speed
with no error messages, others want messages, exceptions to be thrown,
etc. By having a template parameter provide error handeling functions
all these can be accomodated. An additional advantage is that some
functions could ignore errors, while others could throw. I've made
some basic error handeling functions (e.g.
error_handeler_cerr_and_throw) and derived some execption classes from
the std exceptions (well, the ones that I know of), adding the ability
to store a value.

Well, bring on the suggestions.
 
Eric

P.S. If you like to get some idea of what such functions would look
like, here's an example function that squares a number.
(function_base provides several typedef's and one member function for
each of the last three template parameters.)

template <class RetT, class ArgT = RetT,
  class AccuraceyCheckerT = accuracey_check_dont_bother<RetT,ArgT>,
  class DomainCheckerT = domain_check_dont_bother<ArgT>,
  class ErrorHandelerT = error_handeler_default >
  class square : public function_base<RetT, ArgT, AccuraceyCheckerT,
DomainCheckerT, ErrorHandelerT>
    {
      typedef function_base<RetT, ArgT, AccuraceyCheckerT,
DomainCheckerT, ErrorHandelerT> base_type;
      public:
      square(accuracey_checker_type AC = accuracey_checker_type(),
domain_checker_type DC=domain_checker_type(), error_handeler_type
EH=error_handeler_type() ) : base_type(AC,DC,EH) {};

      return_type operator()(const arg_type x) const
      {
        CheckInDomain(x);
        return_type y = x*x;
     if(!CheckOkAccuracey(numeric_limits<return_type>::epsilon(),y,x))
          error_handeler().inaccuracey_error(string("in
square(x)"),x);
        return y;
      };
    };

then in a program...

square<T> sq;
cout << "x = " << x << " sq(x) = " << sq(x) << endl;


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