我正在用C ++编写一些代码,用于科学计算。我选择使用的线性代数库是Armadillo。我的问题是Armadillo使用简单的rand()函数或Mersenne Twister rng,而我需要更好的质量数字,例如ranlux。 GSL提供了ranulx的实现,而Armadillo通过定义预处理器宏ARMA_RNG_ALT并编写适当的头文件(称为arma_rng_alt.hpp)来允许外部rng。
现在,我不是C ++向导,但是我设法通过复制或粘贴现有标头arma_rng_cxx98.hpp和arma_rng_cxx11.hpp来做到这一点。我的解决方案可能不是最漂亮的,但我认为它可以正常工作。这是我的标头的一部分:
#if defined(ARMA_RNG_ALT)
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#define RNG_TYPE gsl_rng_ranlxd1
class arma_rng_alt
{
public:
typedef unsigned long int seed_type;
inline void set_seed(const seed_type val);
arma_inline int randi_val();
arma_inline double randu_val();
arma_inline double randn_val();
private:
gsl_rng* engine;
};
inline
void
arma_rng_alt::set_seed(const arma_rng_alt::seed_type val)
{
engine = gsl_rng_alloc(RNG_TYPE);
gsl_rng_set(engine, val);
}
arma_inline
int
arma_rng_alt::randi_val()
{
return gsl_rng_get(engine);
}
arma_inline
double
arma_rng_alt::randu_val()
{
return gsl_rng_uniform(engine);
}
arma_inline
double
arma_rng_alt::randn_val()
{
return gsl_ran_gaussian_ziggurat(engine, 1.);
}
#endif
现在,如果该外部rng被armadillo视为没有私有变量的类(例如,在arma_rng_cxx98.hpp标头中,使用rand()且不需要分配引擎),那将是可以的。相反,我需要分配引擎并每次都调用它,因此我需要实例化该类,否则会出现“没有对象就无法调用成员函数”错误。因此,我实际上需要修改Armadillo库本身的标头,即arma_rng.hpp。 为了使事情更清楚,这是原始arma_rng.hpp中用于生成随机整数的典型块的样子:
template<typename eT>
struct arma_rng::randi
{
arma_inline
operator eT ()
{
#if defined(ARMA_RNG_ALT)
{
return eT( arma_rng_alt::randi_val() );
}
#elif defined(ARMA_USE_EXTERN_CXX11_RNG)
{
return eT( arma_rng_cxx11_instance.randi_val() );
}
#else
{
return eT( arma_rng_cxx98::randi_val() );
}
#endif
}
如您所见,如果使用cxx98或alt,则仅调用randi_val函数,而如果使用cxx11,则在calss arma_rng_cxx11(在标头中较早声明的线程局部变量)的实际实例上调用randi_val。 。我需要的是类似于cxx11的东西,因此这是我修改此特定示例的库标头arma_rng.hpp的方式:
template<typename eT>
struct arma_rng::randi
{
arma_inline
operator eT ()
{
#if defined(ARMA_RNG_ALT)
{
return eT( arma_rng_alt_instance.randi_val() );
}
#elif defined(ARMA_USE_EXTERN_CXX11_RNG)
{
return eT( arma_rng_cxx11_instance.randi_val() );
}
#else
{
return eT( arma_rng_cxx98::randi_val() );
}
#endif
}
在声明我自己创建的类arma_rng_alt的线程本地实例之后。
运作起来很吸引人,但是要注意的是,现在我需要在HPC集群上运行代码,并且虽然可以创建自己的arma_rng_alt.hpp,但不能修改库头文件arma_rng.hpp本身。因此,我需要一种使原始标头正常工作的方法(因此无需实例化该类)。您对此有任何想法吗?坦率地说,我的C ++专业知识已达到极限。
谢谢