1

我正在尝试创建一个通用的 Lanczos 算法,该算法接受一个运算符(函数指针)并从 C 中的该运算符打印一定数量的特征值。我正在使用 GNU 科学库来处理向量和矩阵。具体来说,有问题的运算符接受一些输入向量,并通过引用输出一个向量。所以,我希望 Lanczos 方法的函数原型至少看起来像,

void Lanczos( void (*operator) (gsl_vector_complex *,gsl_vector_complex *) , int k    );

其中 k 将是我想要打印的特征值的数量。问题是,我立即有兴趣为其查找特征值的相关操作员需要使用我在之前的模拟中生成的大量外部数据。具体来说,我感兴趣的运算符可以原型为

void WDoperator(gsl_vector_complex * input, gsl_vector_complex * output, lattice * L)

在我的程序的其他地方,我将latticeandsite结构定义为

typedef struct lattice{
  site * R[10*10*10*10];
}lattice;
typedef struct site{
  gsl_matrix_complex * link[4];
}site;

但是,当然,它的编写方式我无法将看起来像我的函数指针传递WDoperatorLanczos. 我解决这个问题的想法是只使用一个全局lattice指针来保存我的模拟结果,而不是将其WDoperator作为参数传递。然而,在研究 stackoverflow 时,似乎普遍的共识是不使用全局变量,尤其是不使用全局指针。那么,有没有我没有想到的更好的方法呢?有没有办法“抑制”函数的参数,使其适合我的函数指针Lanczos例行公事会接受吗?如果全局指针是解决这个问题的方法,是否有使用它们的最佳实践,这样我就不会创建内存泄漏怪物?特别是考虑到将存储在晶格中的数据的大小(现在有 40,000 个矩阵,但是一旦我开始工作,我想扩大它的规模,使其大约为 200k 矩阵)。如果之前在这里有类似的问题,我深表歉意,但我已尽力在论坛范围内寻找类似的问题。

4

2 回答 2

0

有没有办法“抑制”函数的参数,使其适合我的 Lanczos 例程将接受的函数指针?

当您不想使用 的附加参数时,您可以使用条件编译语句并为宏常量赋予不同的值lattice * L

#define CD 1

void WDoperator(gsl_vector_complex * input, gsl_vector_complex * output
#if CD 1
, lattice * L
#endif
);

void Lanczos( void (*operator) (int *,double *) 
#if CD 1
, lattice* L
#endif 
) int k);

您必须在使用指针的每个函数和每个函数内部的算法定义处应用相同的参数列表lattice

抱歉,如果这不是您想要的,但我认为它可以帮助您。

于 2020-04-08T18:07:48.507 回答
0

一种普遍接受的机制是提供一个匿名的上下文参数,该参数通过以下方式传递:

void Lanczos( void (*operator) (gsl_vector_complex *,gsl_vector_complex *) , int k, void *ctx)
void WDoperator(gsl_vector_complex * input, gsl_vector_complex * output, void * ctx) {
   Lattice *L = ctx;

...

如果你想对错误检查更严格一点,你可以想出类似的东西:

struct L_ctx {
    int type;
    void *arg;
};
enum {
    L_NoType,
    L_Lattice,
    L_ComplexLattice,
    ...
};

然后检查是否传入了适当的类型。不太容易出错,但与像 Golang 这样的体面的类型系统不匹配。

于 2020-04-08T18:16:20.847 回答