Boost logo

Boost Users :

Subject: Re: [Boost-users] Extending boost::function for mathematics?
From: jesseperla (jesseperla_at_[hidden])
Date: 2009-01-25 15:32:06


> Do you require that a math_function object be callable?

It is a good question, and one I have wrestled with. The short answer
is that the algorithms you might use it with are for these is in
scientific processing with an incredibly high number of executions.
So for the same reason you might want to write function objects that
directly implement operator() and have typedef result_type for
adaptation, you would want a similar option when designing generic
algorithms. If you don't use math_function, you can inline.. if you
do, then it will use boost::function dispatching for its underlying
object.

I think that part of the design question here is whether this is a
(type erasure) wrapper class that implements the concept of a
differentiable function, and what that concept looks like. For
example, here is what I am thinking for a root finder:

template <class F>
double find_root(F f, double initial_value)
{
     //implement newton's method executing f(x) and f.gradient(x) to
find the zero
    //This might want to do a dynamic or static assertion that the
function has some sort of single_crossing trait associated with
it.... For later, but this is why I think those traits are useful.
}

struct square {double operator()(double x){return x*x;} double
gradient(double x){return 2 * x;} }; //quadratic differentiable
function
struct scaled_square {double operator()(double x, double a){a * x *
x;} double gradient(double x, double a){return 2 * a * x;} }; //
scaled quadratic
double zero= find_root(square(), .1); //inlines everything.
double zero = find_root(math_bind(scaled_square, _1, 1.0)); //Would
uses the dynamic dispatching in boost::function since the math_bind
creates a math_function object which has a boost::function
double zero = find_root(math_function<double (double)>(_1 * _1, 2 *
_1)); //constructs a new math_function... similar to previous line.

Alternatively, if it is in a class:
template <class F = math_function<double (double)> >
class newton_root_finder
{
     F f_;

     template<class G>
     newton_root_finder(const G& f) : f_(f) //Here it will construct
the underlying object as required.

     double solve() { implement newton's method using f() and
f.gradient() }
};


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net