11

I would like to use GSL within a c++ class without declaring member functions as static. The reason for this is because I don't know them too well and I'm not sure about thread safety. From what I read, std::function might be a solution but I'm not sure how to use it.

My question comes down to how can I remove static in declaration of g?

#include<iostream>
#include <functional>
#include <stdlib.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_monte.h>
#include <gsl/gsl_monte_plain.h>
#include <gsl/gsl_monte_miser.h>
#include <gsl/gsl_monte_vegas.h>


using namespace std;

class A {
public:
  static double g (double *k, size_t dim, void *params)
  {
    double A = 1.0 / (M_PI * M_PI * M_PI);
    return A / (1.0 - cos (k[0]) * cos (k[1]) * cos (k[2]));
  }
  double result() {
    double res, err;

    double xl[3] = { 0, 0, 0 };
    double xu[3] = { M_PI, M_PI, M_PI };

    const gsl_rng_type *T;
    gsl_rng *r;

    ////// the following 3 lines didn't work ///////
    //function<double(A,double*, size_t, void*)> fg;
    //fg = &A::g;
    //gsl_monte_function G = { &fg, 3, 0 };
    gsl_monte_function G = { &g, 3, 0 };

    size_t calls = 500000;

    gsl_rng_env_setup ();

    T = gsl_rng_default;
    r = gsl_rng_alloc (T);

    {
      gsl_monte_plain_state *s = gsl_monte_plain_alloc (3);
      gsl_monte_plain_integrate (&G, xl, xu, 3, calls, r, s, &res, &err);
      gsl_monte_plain_free (s);
    }

    gsl_rng_free (r);
    return res;
  }
};

main() {
  A a;
  cout <<"gsl mc result is " << a.result() <<"\n";
}

Update (1):

I tried changing gsl_monte_function G = { &g, 3, 0 }; to gsl_monte_function G = { bind(&A::g, this,_1,_2,_3), 3, 0 }; but it didn't work

Update (2): I tried using assigning std::function to a member function but it didn't work either.

Update (3) in the end I wrote a non-member function:

double gmf (double *k, size_t dim, void *params) {
  auto *mf = static_cast<A*>(params);
  return abs(mf->g(k,dim,params));
  //return 1.0;
};

It worked but it's a messy solution because I needed to write a helper function. With lambdas,function and bind, there should be a way to have everything logical within the class.

Community
  • 1
  • 1
kirill_igum
  • 3,703
  • 5
  • 37
  • 68
  • I know that my answer came quite late, but I hope that wrap class can help you in the future. This wrap is quite handy because it also allows you to integrate lambda functions or to bind functions with more than one parameter (if you want to integrate f(x, a) = a x where a is a parameter for example). – Vivian Miranda Aug 31 '13 at 00:40

4 Answers4

9

You can easily wrap member functions using the following code (which is a well known solution)

 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);
   }
};

Then you can use std::bind to wrap the member function in a std::function. Example:

gsl_function_pp Fp( std::bind(&Class::member_function, &(*this),  std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);     

However, you should be aware about the performance penalties of std::function before wrapping member functions inside gsl integration routine. See template vs std::function . To avoid this performance hit (which may or may not be critical for you), you should use templates as shown below

template< typename F >
  class gsl_function_pp : public gsl_function {
  public:
  gsl_function_pp(const F& func) : _func(func) {
    function = &gsl_function_pp::invoke;
    params=this;
  }
  private:
  const F& _func;
  static double invoke(double x, void *params) {
    return static_cast<gsl_function_pp*>(params)->_func(x);
  }
};

In this case, to call a member function you need the following

 Class* ptr2 = this;
 auto ptr = [=](double x)->double{return ptr2->foo(x);};
 gsl_function_pp<decltype(ptr)> Fp(ptr);     
 gsl_function *F = static_cast<gsl_function*>(&Fp);   

PS: the link template vs std::function explains that compiler usually has an easier time optimizing templates than std::function (which is critical for performance if your code is doing heavy numerical calculation). So even tough the workaround in the second example seems more cumbersome, I would prefer templates than std::function.

Community
  • 1
  • 1
Vivian Miranda
  • 2,276
  • 1
  • 13
  • 26
  • It's a good solution but it still uses static member functions. anyway, i mark it as answered to close the question. i drifted away from gsl and use odeint now so i didn't test it. – kirill_igum Sep 01 '13 at 02:22
1

GSL takes a C-type functions “int (*)(char,float)” rather than C++-type “int (Fred::*)(char,float)”. To convert a member function to the C-type function, you need to add static.

see Is the type of “pointer-to-member-function” different from “pointer-to-function”?

kirill_igum
  • 3,703
  • 5
  • 37
  • 68
0

Why are you worried about the static function in this case? Variables and/or objects declared in a static function are not shared between different threads unless they are static themselves (which in your case they are not).

Is your code failing to do something?

krolth
  • 982
  • 7
  • 12
  • not right now but it's a part of a bigger code that I will continue to expand. I'm using static for now but I would rather have a non-static solution. another benefit would be to understand `bind` and `function` – kirill_igum Oct 29 '12 at 04:45
0

Sorry, but what you're trying to do doesn't make any sense. Whatever thread safety issues you're worried about, they won't be solved by adding or removing the static keyword.

The only reason why you would make g non-static would be if an instance of A was somehow required for g's operation. And g's current implementation doesn't require such an instance.

Note you can also make g a global function, without the static keyword. There would be no visible difference in your case. However it's better style in your case to have g in the class which makes use of it, as a static function.

Also, Here is some related material about pointers to (static/non-static) member functions.

Danra
  • 8,833
  • 4
  • 49
  • 113
  • in my full code, the `g` function depends on `std::function` member. I get an error if I make g static `invalid use of member ... in static member function`. then I have to make that `std::function` static but then I have a problem assigning a function to it from another class. – kirill_igum Oct 29 '12 at 21:04