Using params from gsl function in integration routine

Click For Summary

Discussion Overview

The discussion revolves around the challenges of passing parameters to a GSL (GNU Scientific Library) integration routine in C/C++. Participants are examining a code snippet that attempts to integrate a function while using a structure to hold parameters. The focus is on debugging the integration routine and understanding the correct usage of pointers and references in this context.

Discussion Character

  • Technical explanation
  • Debugging assistance
  • Conceptual clarification
  • Debate/contested

Main Points Raised

  • One participant describes an issue with the integration routine not returning correct values, suggesting a potential problem with how parameters are passed.
  • Another participant advises using a debugger to step through the code to identify issues.
  • Concerns are raised about the syntax used to reference the structure, with some suggesting it may be incorrect.
  • Some participants propose that the way parameters are cast and dereferenced could lead to errors, and they suggest alternative methods for accessing the structure's members.
  • A participant mentions that the debugger shows unexpected values being returned, raising questions about uninitialized variables and memory states.
  • There is a discussion about the differences between using references and pointers in C++, with some advocating for a more conventional approach using pointers.
  • One participant points to a GSL example that suggests a different way to set up the function and parameters, indicating that using pointers may be more appropriate.

Areas of Agreement / Disagreement

Participants express differing opinions on the correct method for passing parameters and the implications of using pointers versus references. There is no consensus on the best approach, and the discussion remains unresolved regarding the optimal solution to the integration issue.

Contextual Notes

Participants note potential limitations in understanding how the GSL library expects parameters to be structured and passed, as well as the importance of ensuring consistent compilation flags between user code and library code.

CAF123
Gold Member
Messages
2,918
Reaction score
87
I'm trying to pass through some parameters of a function to the gsl integration routine but my code is currently not returning correct values. I attach a version of my code using dummy example functions and names.

C:
struct myStruct_t {
           double a;
 };

double func(double z, void* params)  {
        myStruct_t &myStruct = *(myStruct_t *)(params);

        double res = pow(z*myStruct.a,2);

       return res;
}
     
int main() {
    double result, error;
    myStruct_t myStruct;
    gsl_integration_workspace * w = gsl_integration_workspace_alloc(1000);

    gsl_function F;
    F.params = (void*)(&myStruct);
    F.function = func;

    for(int i = 0; i < 10; i++) {
   
        double b = pow(2,i);
        double a = 2*b;

        myStruct.a = a;
        gsl_integration_qags(&F, 0, 1, 1e-3, 1e-3, 1000, w, &result, &error);
        std::count << b << result << std::endl;
    }

}
I believe the issue is with the myStruct.a parameter in ``func and somehow it is not being passed through the integration routine properly. The code does not return an error but yields values ~10^(129) suggesting something is not quite right. I have tested this by simply hardcoding ten values of a one at a time in func instead of using a for loop and seeing if the code returns sensible results which it does so. Do you see immediately any error in what I have written? Thanks in advance!
 
Last edited by a moderator:
Technology news on Phys.org
Use a debugger and step through your code. The effort to learn how to use the debugger will definitely payoff in the long run.
 
Last edited:
CAF123 said:
myStruct_t &myStruct = *(myStruct_t *)(params);
I may be wrong (I haven't analysed C code since 2010), but I think the quoted part is subtly wrong. Going from right to left:
  • (myStruct_t *)(params) casts the typeless params to be a pointer to a myStruct_t
  • *(myStruct_t *)(params) dereferences that pointer (in other words it fetches the value that params is pointing to)
On the left side:
  • myStruct_t &myStruct is a pointer
So what you are doing is assigning a value (the contents of a struct) to a pointer

My standard advice to all C programmers: Run the code through lint repeatedly until no more comments appear.
 
Svein said:
myStruct_t &myStruct = *(myStruct_t *)(params);
[...]
On the left side:
  • myStruct_t &myStruct is a pointer
The syntax on the left side of the line you quoted means that myStruct is declared as a myStruct_t reference, not a pointer, and in the given context it does appears to be correct.

I would also recommend using a debugger to verify if the params parameter really is pointing to the myStruct instance or not. If it doesn't then I guess it requires some gsl specific knowledge or documentation to figure out why not.
 
Dear all, Thanks for your comments! Actually I am using the lldb debugger inbuilt into xcode on a macos. The program builds but there is 'no debug session' initiated in the IDE interface.

I had looked here at the first example
https://www.gnu.org/software/gsl/doc/html/integration.html

It's not immediately helpful because alpha is declared as a double dereferenced from pointer but then in the actual int main alpha is just set as 1.0.

Maybe @DrClaude can help, I recall I had discussed gsl with him/her before.
 
With an IDE debugger, you run the code in debug mode. However, prior to running in debug mode, you must set a breakpoint on the line of interest or the line before.
 
jedishrfu said:
With an IDE debugger, you run the code in debug mode. However, prior to running in debug mode, you must set a breakpoint on the line of interest or the line before.
Thanks, I see, putting the breakpoint after the return res in double func in my actual code says that the res is returning a value of around -1e+126. But I haven't declared any value for
Code:
 a
yet (that comes later in the for loop) so how can it resume this value? Is it just like some temporary memory value or something?
 
We think your problem is in how you're referencing the mystruct variable so that means stepping into the function and looking at what it thinks the arguments are. Sometimes these types of errors are more complex than you can imagine.

I had an issue across the calling boundary where data was getting corrupted. It turned out the library code I was calling was compiled with different flags from my code where the library code expected argument data to be placed at 8 byte boundaries instead of 4 byte.
 
Last edited:
Filip Larsen said:
The syntax on the left side of the line you quoted means that myStruct is declared as a myStruct_t reference, not a pointer, and in the given context it does appears to be correct.
OK. I am no expert on C++ (on the other hand I have been programming in C for 25years), but I still do not see why you would want to do it this way. In C, the obvious way would be:
C:
double func(double z, void* params)  {
        myStruct_t myStruct = *(myStruct_t *)(params);

        double res = pow(z*myStruct.a,2);

       return res;
}
The difference being that you now create a local myStruct and copy the given values to it.

BTW - this video () lists void * as one of the 10 "forbidden" C++ constructs.
 
  • #10
Last edited:
  • #11
params is being passed as a pointer of type void and you simply want to recast it into a pointer of type myStruct_t. The elements of the struct can then be accessed using -> instead of .

C:
struct myStruct_t {
           double a;
};

double func(double z, void* params)  {
       // myStruct_t &myStruct = *(myStruct_t *)(params);
        myStruct_t *myStruct = (myStruct_t *)(params);
        double res = pow(z*myStruct->a,2);

       return res;
}

CAF123 said:
Maybe @DrClaude can help, I recall I had discussed gsl with him/her before.
I use GSL in my teaching, so don't hesitate to tag me when you have such questions.
 
  • #12
Svein said:
I am no expert on C++ (on the other hand I have been programming in C for 25years), but I still do not see why you would want to do it this way.
It is mostly a matter of style and convention. In order not to derail this thread let me just refer to this Pointer vs Reference in C++ page for details. In context of this thread my point was that both approaches will work equally well inside the func function, even so much as to produce the same compiled code.

Granted, if one is using a C++ library that has a C-flavored API and examples, then it certainly may be a good idea to follow the "library style" when in doubt.
 

Similar threads

  • · Replies 7 ·
Replies
7
Views
2K
Replies
6
Views
2K
  • · Replies 21 ·
Replies
21
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 6 ·
Replies
6
Views
12K
  • · Replies 39 ·
2
Replies
39
Views
5K
Replies
3
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
Replies
10
Views
2K
Replies
20
Views
2K