我在 c ++ 中使用此包装函数,用于 gsl ,这是我在其他解决方案中看到的
gsl_function_pp Fp( std::bind(&Class::member_function, &(*this), std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);
它说 int status = gsl_function .. 。 将给出错误代码。但是我无法弄清楚如何使用上面的包装函数获取状态。
**************************更新1
所以我用这个函数来解决fzero问题
double gsl_root(gsl_function *F, double x_lo, double x_hi) {
const gsl_root_fsolver_type *T;
gsl_root_fsolver *s;
T = gsl_root_fsolver_brent;
s = gsl_root_fsolver_alloc (T);
gsl_root_fsolver_set (s, F, x_lo, x_hi);
int status;
do {
status = gsl_root_fsolver_iterate(s);
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);
} while(status == GSL_CONTINUE);
gsl_root_fsolver_free(s);
return 0.5*(x_lo + x_hi);
}
如何获取上述功能的状态输出,我尝试迭代和间隔功能但没有工作,我已经不知道了,想了解为什么&amp;如何。
例如,当GSl没有解决方案时,我会收到错误,例如:
gsl: brent.c:74: ERROR: endpoints do not straddle y=0
Default GSL error handler invoked.
这就是我想要的。我只是想处理这个案子。抱歉混淆,希望现在问题更明确。
答案 0 :(得分:1)
我认为我的评论解决了这个问题,但我会在这里总结一下这个问题。 GSL函数只是以下c-struct
的typedefstruct gsl_function_struct
{
double (* function) (double x, void * params);
void * params;
};
typedef struct gsl_function_struct gsl_function ;
然后,显然gsl_function不是例程,例如&#34; int gsl_fft_complex_radix2_forward(...)&#34;例如,执行某些操作并返回一个错误状态的整数。
更新1:我仍然不明白错误状态和包装器之间的关系。那么让我展示一个几乎完整的例子(gsl集成)
// 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
使用fft函数,你应该做一些非常相似的事情int status = ....; if(status) {cout << std::string( gsl_strerror (status) ) << std::endl; exit(1); // or throw an exception}
更新2:我希望现在很清楚错误句柄与C ++包装器无关。
首先:当你设置gsl_set_error_handler_off()
时,你有责任检查gsl调用的错误。然后你必须将当前的代码替换为这样的代码
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;
第二:如果您检查GSL源代码,您将看到消息
gsl:brent.c:74:错误:端点不跨越y = 0
写在函数
上 static int brent_init (void * vstate, gsl_function * f, double * root, double x_lower, double x_upper)
此外,函数set
只是指向特定情况下brent_init
的指针
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};
然后,您无法检测到错误,因为您错过了以下呼叫的状态
status = gsl_root_fsolver_set (s, F, x_lo, x_hi);
if(status) std::cout << std::string( gsl_strerror (status) ) << std::endl;
最后,在发生类似情况时检查GSL源代码非常重要。错误消息显示发生错误的文件名和行号。因此,享受GSL是一个开源代码,并检查那里发生了什么!此外,GSL源代码组织严密,简洁易懂。