Question

I have a prototype code in Matlab, it's using fsolve and fzero in some calculations. In c++ I'm using GSL and trying to find the value x which is f(x)=0;

So for my example, in Matlab I do:

functionSolver= @(x) myFunction(x);
XSol = fsolve(functionSolver,0);

this one clearly solves the Matlab function which is:

function F = myFunction(x)
%% do something with x
F = x;
end

So then in C++, i have myFunction as;

double myClass::myFunction(double x){
//do something with x
return x;
}

In GSL documentation it's telling about root finding example however need some help. https://www.gnu.org/software/gsl/manual/html_node/Root-Finding-Examples.html#Root-Finding-Examples

There must be some clear ways to find 0 root(s) of given function. Even if you can provide me simple example I'll be so glad!

All best.

Was it helpful?

Solution

You can't cast class member functions into gsl_function without a wrapper. You must use global functions. In this case, the second example shown on the GSL documentation you linked is the standard way to use the library if you can't provide the function first derivative (otherwise check the first example). There is not much simplification left.

If you are willing to use a wrapper, however, there a many ways to simplify your life. For example, you can use a wrapper to enable c++11 features like lambdas!. In general, I don't recommend anyone to use third-party wrapper for GSL without a careful code check. You should first learn the standard way.

Another example: I developed a small wrapper that simplifies the GSL 1D Root Finder API. You can find the source code and a nice example in this link. I am NOT saying you should use my wrapper. In time, you will probably develop your own!

Update 1: There is also O2Scl which is the most developed C++ wrapper for gsl that I am aware of. It seems to have a very nice API. Again: you should use wrapper with great care.

Update 2: To answer a question raised in a comment: You can also create a global function and use it as a wrapper. Example:

double myFunction(double x, void* ptr) {
    myClass* ptr2 = static_cast<myClass*>(ptr);
    return ptr2->myFunction(x);
}

I don't like this solution in more complicated cases (but here is perfectly fine and probably the simpler option) because it is cumbersome if you want to send more parameters (example: you need 2 parameters: the class itself and an extra number - in this case you would need to create an extra struct to hold both!). Using the wrapper I linked you can easily send many parameters using lambdas! Example

double a = 1;
myClass m1 ....
gsl_function_pp Fp( [&](double x){return a * m1.myFunction(x);} ); 
gsl_function *F = static_cast<gsl_function*>(&Fp); 

Just for completion, here is the wrapper code

class gsl_function_pp : public gsl_function
{
   public:
   gsl_function_pp(std::function<double(double)> const& func) : _func(func){
   function=&gsl_function_pp::invoke;
   params=this;
   }     
   private:
   std::function<double(double)> _func;
   static double invoke(double x, void *params) {
   return static_cast<gsl_function_pp*>(params)->_func(x);
   }
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top