Как передать большой набор данных в функцию без аргумента в C - PullRequest
1 голос
/ 08 апреля 2020

Я пытаюсь создать общий алгоритм Ланцоша, который принимает оператор (указатель на функцию) и печатает определенное количество собственных значений этого оператора в C. Я использую библиотеку GNU Scientifi c для обработки векторов и матриц. В частности, рассматриваемый оператор получает некоторый входной вектор и посредством ссылки выводит вектор. Итак, я бы ожидал, что прототип функции для метода Ланцоша будет минимально выглядеть примерно так:

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)

в другом месте моей программы, у меня есть структуры lattice и site, определенные как

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

Но, конечно, при написании я не могу передать указатель на функцию, похожую на мой WDoperator, в Lanczos. Моя идея решить эту проблему состояла в том, чтобы просто иметь глобальный указатель lattice, который содержит мои результаты моделирования, вместо того, чтобы передавать его в WDoperator в качестве аргумента. Тем не менее, при копании в стеке, кажется, что общий консенсус заключается в том, чтобы не использовать глобальные переменные и особенно не глобальные указатели. Итак, есть ли лучший способ сделать это, о котором я не думаю? Есть ли способ «подавить» аргумент функции, чтобы он вписался в указатель на функцию, которую примет моя подпрограмма Lanczos? Если глобальные указатели являются способом go с этим, есть ли лучшие практики по их использованию, чтобы я не создавал монстра с утечкой памяти? Особенно с учетом размера данных, которые будут храниться в решетке (прямо сейчас 40000 матриц, но как только я получу это, я бы хотел увеличить их до порядка 200 тыс. Матриц). Я прошу прощения, если здесь уже был похожий вопрос, но я сделал все возможное, чтобы расширить форум для подобных запросов.

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Общепринятым механизмом является предоставление анонимного параметра контекста, который передается через:

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.

0 голосов
/ 08 апреля 2020

Есть ли способ "подавить" аргумент функции, чтобы он вписывался в указатель функции, который будет принимать моя подпрограмма 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.

Извините, если это не то, что вы ищете, но я думаю, что это может помочь вам.

...