/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\struct random_t
\brief Структура параметров датчиков псевдослучайных чисел.

Структура хранит инициализацию и текущие регистры различных датчиков 
псевдослучайных чисел. В библиотеке используются следующие датчики: 
\li MRG32K3A -- 32 битный датчик разработан Пьером Лекуэром [1]. 
\li MT19937-64 -- 64-битный датчик 
    <a href = "https://en.wikipedia.org/wiki/Mersenne_Twister">
	Вихрь Мерсенна 
	</a> [2, 3]. 

\note
[1] Pierre L'Ecuyer, (1999) Good Parameters and Implementations for Combined 
    Multiple Recursive Random Number Generators. Operations Research 
	47(1):159-164. https://doi.org/10.1287/opre.47.1.159 \n\n
[2] T. Nishimura, ``Tables of 64-bit Mersenne Twisters // ACM Transactions
    on Modeling and Computer Simulation 10. (2000) 348--357. \n\n
[3] M. Matsumoto and T. Nishimura  Mersenne Twister: a 623-dimensionally
    equidistributed uniform pseudorandom number generator // ACM Transactions
    on Modeling and Computer Simulation 8. (Jan. 1998) 3--30.  \n\n

\param  mrg32k3a_seed
Начальная инициализация датчика MRG32K3A. \n \n


\param  mrg32k3a_x
Первый вектор состояния рекурсивного датчика MRG32K3A. \n \n

\param  mrg32k3a_y
Второй вектор состояния рекурсивного датчика MRG32K3A. \n \n

\param  mt19937_mt
Первый вектор состояния рекурсивного датчика MT19937-64. \n \n

\param  mt19937_mti
Текущий индекс в векторе состояния датчика MT19937-64. \n \n

Параметры данной структуры заполняются автоматически функцией `random_init` 
и используются функциями генерации псевдослучайных векторов. 

\author
Бахурин Сергей.
www.dsplib.org 
***************************************************************************** */






/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int random_init(random_t* prnd, int type, void* seed)
\brief 
Инициализация датчиков псевдослучайных чисел. 

\param[in,out]  prnd
Указатель на структуру параметров и векторов состояния 
датчиков псевдослучайных чисел, которая будет инициализирована. \n\n

\param[in]  type
Тип датчика псевдослучайных чисел:
\verbatim
RAND_TYPE_MRG32K3A - 32-битный датчик MRG32K3A
RAND_TYPE_MT19937  - 64-битный датчик MT19937-64
\endverbatim

\param[in]  seed
Указатель на начальную инициализацию датчика. \n
Данный указатель имеет тип `void*`, поскольку параметр инициализации
зависит от типа датчика. Например если инициализируем датчик MRG32K3A,
т.е. параметр `type` задан как `RAND_TYPE_MRG32K3A`, то данный указатель 
приводится к типу `double`:
\code
  random_t rnd = {0};
  double seed = 1234.0;
  random_init(&rnd, RAND_TYPE_MRG32K3A, (void*)&seed);
\endcode
Если же используется 64-битный датчик Вихрь Мерсенна 
(`type` задан как `RAND_TYPE_MT19937`), то `seed` приводится к типу 
`unsigned long long`:
\code
  random_t rnd = {0};
  unsigned long long seed = 1234353456;
  random_init(&rnd, RAND_TYPE_MT19937, (void*)&seed);
\endcode
При фиксированном начальном значении датчика, псевдослучайные числа будут
повторяться при каждом запуске программы. \n
Указатель `seed` может быть `NULL`. В этом случае начальная инициализация 
датчиков будет задаваться случайными значениями и генерируемые псевдослучайные 
числа будут различными при каждом запуске программы.

\author
Бахурин Сергей.
www.dsplib.org
****************************************************************************  */




/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int randb(double* x, int n, random_t* prnd)
\brief 
Генерация бинарного униполярного [0, 1] псевдослучайного вектора 

Функция генерирует униполярный псевдослучайный вектор, 
каждый элемент которого принимает равновероятное значение 0 или 1. 

\param[in,out] x  
Указатель на вектор случайных бинарных чисел.  \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n\n

\param[in] n
Размер вектора `x`. \n\n

\param[in] prnd
Указатель на структуру `random_t` параметров датчиков
псевдослучайных чисел. \n
Структура должна быть предварительно заполнена функцией \ref random_init. \n
Данный указатель может быть `NULL`, тогда будет использоваться 
встроенный датчик, определенный стандартом языка Си. Однако для серьезных нужд, 
например в криптографии, данный режим использовать не рекомендуется. 
Нет гарантии в качестве произведенной случайной последовательности если 
параметр `prnd` задан как `NULL`. \n\n

\return
`RES_OK` --- вектор целых псевдослучайных чисел рассчитан успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки".

Пример использования функции:

\include randb_test.c

Программа рассчитывает униполярный [0, 1] и биполярный [-1, 1] бинарные
псевдослучайные векторы.

В результате выполнения программы можно увидеть график:
\image html randb_test.png

\author
Бахурин Сергей.
www.dsplib.org
***************************************************************************** */


/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int randb2(double* x, int n, random_t* prnd)
\brief 
Генерация бинарного биполярного [-1, 1] псевдослучайного вектора 

Функция генерирует биполярный псевдослучайный вектор, 
каждый элемент которого принимает равновероятное значение -1 или 1. 

\param[in,out] x  
Указатель на вектор случайных бинарных чисел.  \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n\n

\param[in] n
Размер вектора `x`. \n\n

\param[in] prnd
Указатель на структуру `random_t` параметров датчиков
псевдослучайных чисел. \n
Структура должна быть предварительно заполнена функцией \ref random_init. \n
Данный указатель может быть `NULL`, тогда будет использоваться 
встроенный датчик, определенный стандартом языка Си. Однако для серьезных нужд, 
например в криптографии, данный режим использовать не рекомендуется. 
Нет гарантии в качестве произведенной случайной последовательности если 
параметр `prnd` задан как `NULL`. \n\n

\return
`RES_OK` --- вектор целых псевдослучайных чисел рассчитан успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки".

Пример использования функции:

\include randb_test.c

Программа рассчитывает униполярный [0, 1] и биполярный [-1, 1] бинарные
псевдослучайные векторы.

В результате выполнения программы можно увидеть график:
\image html randb_test.png

\author
Бахурин Сергей.
www.dsplib.org
***************************************************************************** */


/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int randi(int* x, int n, int start, int stop, random_t* prnd)
\brief 
Генерация целочисленного вектора равномерно 
распределенных псевдослучайных чисел.

Функция генерирует псевдослучайный вектор целых чисел в диапазоне от `start`
до `stop` включительно. 

\param[in,out] x  
Указатель на вектор случайных чисел.  \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n\n

\param[in] n
Размер вектора `x`. \n\n

\param[in] start
Начало диапазона целых чисел. \n\n

\param[in] stop
Конец диапазона целых чисел. \n\n

\param[in] prnd
Указатель на структуру `random_t` параметров датчиков
псевдослучайных чисел. \n
Структура должна быть предварительно заполнена функцией \ref random_init. \n
Данный указатель может быть `NULL`, тогда будет использоваться 
встроенный датчик, определенный стандартом языка Си. Однако для серьезных нужд, 
например в криптографии, данный режим использовать не рекомендуется. 
Нет гарантии в качестве произведенной случайной последовательности если 
параметр `prnd` задан как `NULL`. \n\n

\return
`RES_OK` --- вектор целых псевдослучайных чисел рассчитан успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки".

Пример использования функции:

\include randi_test.c

Программа рассчитывает целочисленный вектор 
псевдослучайных чисел в диапазоне [-4, 3].

В результате выполнения программы можно увидеть график:
\image html randi_test.png


\author
Бахурин Сергей.
www.dsplib.org
***************************************************************************** */





/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int randn(double* x, int n, double mu, double sigma, random_t* prnd)
\brief 
Генерация вектора нормально распределенных псевдослучайных чисел.

Функция использует преобразование Бокса-Мюллера для приведения  
равномерно-распределенных псевдослучайных чисел к нормальному распределению 
с математическим ожиданием \f$\mu\f$ и средневадратическим 
отклонением \f$\sigma\f$.

\param[in,out] x  
Указатель на вектор случайных чисел.  \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n\n
      
\param[in] n
Размер вектора случайных чисел. \n\n

\param[in] mu
Математическое ожидание \f$\mu\f$. \n\n


\param[in] sigma
Cредневадратическое отклонение \f$\sigma\f$. \n
Дисперсия сгенерированных чисел равна \f$\sigma^2\f$. \n\n

\param[in] prnd
Указатель на структуру `random_t` параметров датчиков
псевдослучайных чисел. \n
Структура должна быть предварительно заполнена функцией \ref random_init. \n
Данный указатель может быть `NULL`, тогда будет использоваться 
встроенный датчик, определенный стандартом языка Си. Однако для серьезных нужд, 
например в криптографии, данный режим использовать не рекомендуется. 
Нет гарантии в качестве произведенной случайной последовательности если 
параметр `prnd` задан как `NULL`. \n\n

\return
`RES_OK` --- вектор нормально распределенных 
псевдослучайных чисел рассчитан успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки".

Пример использования функции:

\include randn_test.c

Программа рассчитывает независимые векторы нормально распределенных 
псевдослучайных чисел, \f$\mu = 0\f$ и \f$\sigma=1\f$.

В результате выполнения программы можно увидеть график:
\image html randn_test.png


\author
Бахурин Сергей.
www.dsplib.org
***************************************************************************** */






/*! ****************************************************************************
\ingroup SPEC_MATH_RAND_GEN_GROUP
\fn int randu(double* x, int n, random_t* prnd)
\brief 
Генерация вектора равномерно-распределенных в интервале 
от 0 до 1 псевдослучайных чисел.

\param[in,out] x  
Указатель на вектор случайных чисел.  \n
Размер вектора `[n x 1]`. \n
Память должна быть выделена. \n\n
      
\param[in] n
Размер вектора случайных чисел. \n\n

\param[in] prnd
Указатель на структуру `random_t` параметров датчиков
псевдослучайных чисел. \n
Структура должна быть предварительно заполнена функцией \ref random_init. \n
 Данный указатель может быть `NULL`, тогда будет использоваться 
встроенный датчик, определенный стандартом языка Си. Однако для серьезных нужд, 
например в криптографии, данный режим использовать не рекомендуется. 
Нет гарантии в качестве произведенной случайной последовательности если 
параметр `prnd` задан как `NULL`. \n\n

\return
`RES_OK` --- вектор равномерно-распределенных 
псевдослучайных чисел рассчитан успешно. \n
В противном случае \ref ERROR_CODE_GROUP "код ошибки".

Пример использования функции с различными датчиками псевдослучайных чисел
приведен в следующем листинге:

\include randu_test.c

Программа рассчитывает независимые векторы равномерно-распределенных 
от 0 до 1 псевдослучайных чисел и выводит их на график для трех различных 
датчиков: MRG32K3A, MT19937-64 и встроенный датчик, определенный 
стандартом языка Си.

В результате выполнения программы можно увидеть график:

\image html randu_test.png

Однако при детальном исследовании датчиков, можно обнаружить, что встроенный 
датчик, определенный стандартом языка Си, 
выдает значения на фиксированной сетке. 

Чтобы проверить это можно выполнить следующую программу:

\include randu_accuracy_test.c

Данная программа аккумулирует только значения датчиков в интервале 
от 0 до 0.001 и выводит их на график:

\image html randu_acc_test.png

Из графика хорошо видно, что данные встроенного датчика выдаются на 
равноотстоящей сетке значений, в отличии от датчиков MRG32K3A и MT19937-64,
которые сохранили псевдослучайный характер.


\author
Бахурин Сергей.
www.dsplib.org
***************************************************************************** */


