Using boost::bind to bind member-function to boost::bisect?
Asked Answered
J

2

1

I've had problems with this before but now it's somehow working.

Now I've following problem. I need to bind values into member-function before I call boost::bisect with the same function. I found pretty good tutorial and I've followed it but it seems that I'm still doing something wrong.

At first I created test class where I got following working:

std::pair<double, double> result = bisect(&Func, 0.0, 1.0, TerminationCondition());
            double root = (result.first + result.second) / 2;

After that I added binding "on the fly as I thought it could work"

 std::pair<double, double> result = bisect(boost::bind(&CLASS::Function,this, _1), 0.0, 1.000000, TerminationCondition());

Result of that was an error. error: terminate called after throwing an instance of 'boost::exception_detail::clone_impl >' what(): Error in function boost::math::tools::bisect: No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = -0.0032916729090909091).

Anyway here is class::function which doesn't work as member function with binding for some reason. I tested it as non-member and it works

double CLASS::Function(double c)
{
/* values: m_a, m_b, m_c, m_d, and m_minus are located in .h file */

normal norm;
double temp = m_d*sqrt(c);

double total = ((1-boost::math::pdf(norm,(m_a*c+m_b)/temp))-(1 - m_c)+boost::math::pdf(norm,(m_a*c+m_b)/temp));

return (total - m_minus); 
}
Julieannjulien answered 28/11, 2011 at 16:39 Comment(0)
C
1

If I read the tutorial correctly, it should be:

std::pair<double, double> result =
    bisect(boost::bind(&CLASS::Function, this, _1, _2, _3),
        0.0, 1.000000, TerminationCondition());

I.e. the parameters to boost::bind() are:

  1. The name of the function (object) to bind to
  2. the arguments to pass to that, as the function expects them

For your case, a CLASS::memberFunc(), that'd be a CLASS * (possibly this but any CLASS * is ok) as the first, which you literally state as such, followed by the parameters later passed to the bound object.

These "futures" are designated by _1, _2 and so on, depending on their position at invocation time.

Example:

class addthree {
private:
    int second;
public:
    addthree(int term2nd = 0) : second(term2nd) {}
    void addto(int &term1st, const int constval) {
        term1st += (term2nd + constval);
    }
}

int a;
addthree aa;
boost::function<void(int)> add_to_a = boost::bind(&addthree::addto, &aa, a, _1);
boost::function<void(void)> inc_a = boost::bind(&addthree::addto, &aa, a, 1);

a = 0 ; add_to_a(2); std::cout << a << std::endl;
a = 10; add_to_a(a); std::cout << a << std::endl;
a = 0 ; inc_a(); std::cout << a << std::endl;
[ ... ]
Credendum answered 28/11, 2011 at 17:56 Comment(0)
E
1

This code:

std::pair<double, double> result = bisect(boost::bind(&CLASS::Function,this, _1), 0.0, 1.000000, TerminationCondition());

is correct. The error you get means that what CLASS::Function returns is invalid. bisect is complaining about multiple roots (or possibly no roots) in the given interval [0; 1]. How does CLASS::Function look like?

Emelina answered 28/11, 2011 at 21:41 Comment(7)
Can you just set a breakpoint into CLASS::Function and see if it gets the correct input numbers?Emelina
Please post your real CLASS::Function. The one you posted above has unpaired brackets, blank (...) spots and uses undefined variable var3. It's really hard to guess what's wrong. You can edit your answer so that the code is nicely formatted.Emelina
Added the function code. So the function gets correct values and it calculates total as it should but somehow it still says it can't find max or it finds multiple roots. So is the problem with binding ? I hope I don't need to bind items inside of normal dist?Julieannjulien
The function in your question can produce various values depending on the constants. Are you sure that there is a root in the interval [0; 1]?Emelina
It seems that there is a problem with the values what I get from header. When I hard coded the values in my function it gave me the root.Julieannjulien
Yes, at first I thought that was the issue because I got a root a couple of times when I did hard code the values. Anyway I must have had a typo at that time. I still get multiple roots and the problem is double temp = m_d*sqrt(c); because it seems to be 0 after bisect call so then there will be dividing by zero. So the error doesn't seem to be related to any the values what I use ?Julieannjulien
Of course, at the left side you start with c = 0.0, sqrt(c) = 0 and thus temp = 0 and you get division by zero. Adjust the interval according to your function :)Emelina

© 2022 - 2024 — McMap. All rights reserved.