Question

I'm using the Gnu Scientific Library to implement a module in my program that computes integrals numerically. The functions are based on the example that can be found on the GSL website in Numerical integration examples:

and here's my code (most of it is the same as in the example):

typedef map<float, float> SignalData;

double f (double x, void * params) {
      SignalData * alpha = static_cast<SignalData *>(params);
      double f =  InterpolatorGSL::interpolatedValueForTime(alpha, x);
      return f;
}


float IntegrationComparator::integral(SignalData * signalData){
       gsl_integration_workspace * w = gsl_integration_workspace_alloc (100000);
       double result, error;
       double expected = -4.0;
       SignalData * alpha = signalData;

       gsl_function F;
       F.function = &f;
       F.params = &alpha;

       gsl_integration_qags (&F, -3.36e-08, -2.36e-08 , 0, 1e-7, 100000,
                             w, &result, &error);

       printf ("result          = % .18f\n", result);
       printf ("exact result    = % .18f\n", expected);
       printf ("estimated error = % .18f\n", error);
       printf ("actual error    = % .18f\n", result - expected);
       printf ("intervals =  %d\n", w->size);

       gsl_integration_workspace_free (w);

}

The problem can be tracked to the following line:

SignalData * alpha = static_cast<SignalData *>(params);

The cast apparently does not work correctly: if I try to do anything with the SignalData object (that is to use any method that takes it as a parameter, ie. a method for printing it out) it produces Segmentation Violation error (it actually prints out 4 random numbers before the error). In the code that I pasted above, it's the interpolation method that uses this object and that's where the Segmentation Violations occurs:

InterpolatorGSL::interpolatedValueForTime(alpha, x);

But this is due to the faulty casting as well.

I don't have much experience with C++ and I've never used void pointers before, so excuse me if this is a stupid question, but what is the right way to pass my map<float, float> * as a void * parameter?

Was it helpful?

Solution

Let's look at Numerical integration example

   double f (double x, void * params) {
   double alpha = *(double *) params;
   double f = log(alpha*x) / sqrt(x);
   return f;
 }
 ...
   double alpha = 1.0;

   gsl_function F;
   F.function = &f;
   F.params = &alpha;

passed variable has type double * and casted to double * in f function

in your code

double f (double x, void * params) {
  SignalData * alpha = static_cast<SignalData *>(params);
  double f =  InterpolatorGSL::interpolatedValueForTime(alpha, x);
  return f;
}
...
   SignalData * alpha = signalData;

   gsl_function F;
   F.function = &f;
   F.params = &alpha;

you assign SignalData ** but casting it to SignalData *

Thus I would suggest remove one & symbol from your code as following

F.params = alpha;

OTHER TIPS

alpha is a local variable in the integral() method, and F.params gets the address of that local variable. I can't quite follow the logic here, but do be aware that when integral() returns, F.params will contain an invalid pointer, and anything -- including a seg fault -- can happen as a result if you try to use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top