I think my comment solves the problem, but I will summarize it here to close the question. GSL function is just a typedef to the following c-struct
struct gsl_function_struct
{
double (* function) (double x, void * params);
void * params;
};
typedef struct gsl_function_struct gsl_function ;
Then, it is clear that gsl_function is not a routine, like "int gsl_fft_complex_radix2_forward(...)" for example, that performs some operation and returns an integer with the error status.
Update 1: I still don't understand what is the relation between error status and the wrapper. So let me show a nearly complete example (gsl integration)
// use smart pointers in c++
template< typename T > class deleter;
template<> class deleter< gsl_integration_workspace > {
public:
void operator()( gsl_integration_workspace* ptr ) {
gsl_integration_workspace_free(ptr);
return;
}
};
typedef std::unique_ptr< gsl_integration_workspace,
deleter< gsl_integration_workspace > > cpp_gsl_integration_workspace;
// main program
// TURN OFF GSL ERROR ERROR HANDLER (GSL JUST PRINT ERROR MESSAGE AND KILL THE PROGRAM IF FLAG IN ON)
gsl_set_error_handler_off();
auto ptr = [](double x)->double{ return x; };
std::function<double(const double)> F1( std::cref(ptr) );
gsl_function_pp F2(F1);
gsl_function *F = static_cast<gsl_function*>(&F2);
double result;
double error;
double lower_limit = 0;
double upper_limit = 1;
double abs_eps = 0;
double rel_eps= 1e3;
int size = 1000;
cpp_gsl_integration_workspace w( gsl_integration_workspace_alloc( size ) );
int status = gsl_integration_qag ( F, lower_limit, upper_limit, abs_eps, rel_eps,
2000, GSL_INTEG_GAUSS15, w.get(), result, error );
// check status and get error message if integration failed.
// Nothing to do with the use of the C++ wrapper
if ( status )
{
// gsl_strerror prints a message explaining the error
std::cout << "GSL FAIL: " << std::string( gsl_strerror (status) ) << std::endl;
exit(1);
}
std::cout << result << " " << error << std::endl
With the fft functions you should do something very similar int status = ....; if(status) {cout << std::string( gsl_strerror (status) ) << std::endl; exit(1); // or throw an exception}
Update 2: I hope it is now clear that error handle has nothing to do with the C++ wrapper.
First: when you set gsl_set_error_handler_off()
you are the responsible to check the error on gsl calls. Then you must replace your current code to something like this
int status;
// this will be the crucial line for my the answer to your problem, but it is important
// to stress all places where you must check the status of the gsl function calls.
status = gsl_root_fsolver_set (s, F, x_lo, x_hi);
if(status) std::cout << std::string( gsl_strerror (status) ) << std::endl;
do {
status = gsl_root_fsolver_iterate(s);
if(status) std::cout << std::string( gsl_strerror (status) ) << std::endl;
x_lo = gsl_root_fsolver_x_lower (s);
x_hi = gsl_root_fsolver_x_upper (s);
status = gsl_root_test_interval (x_lo, x_hi, 0, 1e-12);
if(status) std::cout << std::string( gsl_strerror (status) ) << std::endl;
} while(status == GSL_CONTINUE);
if(status != GSL_SUCCESS ) std::cout << std::string( gsl_strerror (status) ) << std::endl;
Second: if you check the GSL source code you will see that the message
gsl: brent.c:74: ERROR: endpoints do not straddle y=0
is written on function
static int brent_init (void * vstate, gsl_function * f, double * root, double x_lower, double x_upper)
Furthermore, the function set
is just a pointer to brent_init
in your particular case
typedef struct
{
const char *name;
size_t size;
int (*set) (void *state, gsl_function * f, double * root, double x_lower, double x_upper);
int (*iterate) (void *state, gsl_function * f, double * root, double * x_lower, double * x_upper);
}
gsl_root_fsolver_type;
static const gsl_root_fsolver_type brent_type =
{"brent", /* name */
sizeof (brent_state_t),
&brent_init,
&brent_iterate};
Then, you couldn't detect the error because you missed the status on the following call
status = gsl_root_fsolver_set (s, F, x_lo, x_hi);
if(status) std::cout << std::string( gsl_strerror (status) ) << std::endl;
Last, it is important to check the GSL source code when something like this happens. The error message shows the file name and line number where the error occurs. So enjoy that GSL is an open source code and check what is happening there! Besides, GSL source code is very well organized, clean and easy to understand.