Как адаптировать движок случайных чисел в стиле C ++ для GSL (Научная библиотека GNU)? - PullRequest
0 голосов
/ 12 июня 2018

У меня есть PRNG, который удовлетворяет требованиям механизма случайных чисел C ++, как описано здесь .(Это из семейства PCG ).То есть экземпляр механизма может использоваться классами распространения стандартной библиотеки C ++ для генерации случайных чисел:

pcg_extras::seed_seq_from<std::random_device> seed_source;
pcg32 rng(seed_source);
std::uniform_real_distribution<double> uniformDist(0., 1.);
double randomNumber = uniformDist(rng);

Мне нужно сгенерировать выборки из распределения, не включенного в <random>, поэтому мне нужноиспользовать функцию из GSL.Как я могу использовать мой движок C ++ для этой цели?Все функции GSL rng требуют const gsl_rng * в качестве первого аргумента.

По умолчанию создание и использование gsl_rng выглядит следующим образом:

const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
double u = gsl_rng_uniform (r);

Чтобы использовать свой собственный движок, я считаю, что мне нужно будет определить gsl_rng_type, как определено в"gsl/gsl_rng.h":

typedef struct
  {
    const char *name;
    unsigned long int max;
    unsigned long int min;
    size_t size;
    void (*set) (void *state, unsigned long int seed);
    unsigned long int (*get) (void *state);
    double (*get_double) (void *state);
  }
gsl_rng_type;

Прав ли я в том, что, по моему мнению, необходимо?Существуют ли примеры того, как я могу определить пользовательский gsl_rng_type, особенно три необходимые функции-члена?Что может быть моим void *state?

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

В итоге я сделал следующее, чтобы все заработало.Обратите внимание, что мой механизм случайных чисел является глобальной переменной в моей программе: g_rng.

Необходимо создать структуру для хранения любого состояния, подходящего для ГСЧ.В моем случае я просто держу указатель на pcg32:

// In some header file, e.g. rng.h
typedef struct
{
    pcg32 *rng;
} gsl_pcg_state;

Должны быть определены три функции: «set», «get» и «get_double»:

// In some header file, e.g. rng.h
static void gsl_pcg_set(void *state, unsigned long int seed)
{
    ((gsl_pcg_state *)state)->rng = &g_rng;
    (void)seed;                 // unused
}

static unsigned long int gsl_pcg_get(void *state)
{
    return (*((gsl_pcg_state *)state)->rng)();
}

static double gsl_pcg_get_double(void *state)
{
    // Range [0, 1)
    return (*((gsl_pcg_state *)state)->rng)() / 4294967296.;
}

Таким образом, можно создать экземпляр gsl_rng_type:

static const gsl_rng_type gsl_rng_pcg = {
    "pcg",
    0xffffffffUL,
    0,
    sizeof(gsl_pcg_state),
    &gsl_pcg_set,
    &gsl_pcg_get,
    &gsl_pcg_get_double
};

Внутри основной программы вы получите ...

gsl_rng *r;
r = gsl_rng_alloc(&gsl_rng_pcg);
// one can now call various gsl_ran_[...] functions

gsl_rng_free(r);

Глядя на gsl_rng_alloc, как определено в rng.c из GSL подтверждает, что это правильная установка.

0 голосов
/ 13 июня 2018

Это правильно.Весь общедоступный интерфейс описан в https://github.com/LuaDist/gsl/blob/master/rng/gsl_rng.h

...