[Add] Documentation for random number generations.
This commit is contained in:
parent
8feb19e20c
commit
833283add0
87
src/rng.c
87
src/rng.c
@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @file rng.c
|
||||||
|
*
|
||||||
|
* @brief Handle all the random number logic.
|
||||||
|
*
|
||||||
|
* Random numbers are currently generated using the mersenne twister.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -12,9 +20,9 @@
|
|||||||
#include "lephisto.h"
|
#include "lephisto.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
|
||||||
static uint32_t MT[624];
|
static uint32_t MT[624]; /**< Mersenne twister state. */
|
||||||
static uint32_t mt_y;
|
static uint32_t mt_y; /**< Internal mersenne twister variable. */
|
||||||
static int mt_pos = 0; /* Current number. */
|
static int mt_pos = 0; /**< Current number being used. */
|
||||||
|
|
||||||
static uint32_t rng_timeEntropy(void);
|
static uint32_t rng_timeEntropy(void);
|
||||||
/* Mersenne twister. */
|
/* Mersenne twister. */
|
||||||
@ -22,6 +30,11 @@ static void mt_initArray(uint32_t seed);
|
|||||||
static void mt_genArray(void);
|
static void mt_genArray(void);
|
||||||
static uint32_t mt_getInt(void);
|
static uint32_t mt_getInt(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void rng_init(void)
|
||||||
|
*
|
||||||
|
* @brief Initialize the random subsystem.
|
||||||
|
*/
|
||||||
void rng_init(void) {
|
void rng_init(void) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int need_init;
|
int need_init;
|
||||||
@ -49,7 +62,12 @@ void rng_init(void) {
|
|||||||
mt_genArray();
|
mt_genArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the time as source of entropy. */
|
/**
|
||||||
|
* @fn static uint32_t rng_timeEntropy(void)
|
||||||
|
*
|
||||||
|
* @brief Use time as a source of entropy.
|
||||||
|
* @return A 4 byte entopy seed.
|
||||||
|
*/
|
||||||
static uint32_t rng_timeEntropy(void) {
|
static uint32_t rng_timeEntropy(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -65,7 +83,11 @@ static uint32_t rng_timeEntropy(void) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generates the initial mersenne twister based on seed. */
|
/**
|
||||||
|
* @fn static void mt_initArray(uint32_t seed)
|
||||||
|
*
|
||||||
|
* @brief Generate the initial mersenne twister based on seed.
|
||||||
|
*/
|
||||||
static void mt_initArray(uint32_t seed) {
|
static void mt_initArray(uint32_t seed) {
|
||||||
int i;
|
int i;
|
||||||
MT[0] = seed;
|
MT[0] = seed;
|
||||||
@ -74,7 +96,11 @@ static void mt_initArray(uint32_t seed) {
|
|||||||
mt_pos = 0;
|
mt_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate an array of numbers. */
|
/**
|
||||||
|
* @fn static void mt_genArray(void)
|
||||||
|
*
|
||||||
|
* @brief Generate a new set of random numbers for the mersenne twister.
|
||||||
|
*/
|
||||||
static void mt_genArray(void) {
|
static void mt_genArray(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < 624; i++) {
|
for(i = 0; i < 624; i++) {
|
||||||
@ -89,7 +115,10 @@ static void mt_genArray(void) {
|
|||||||
mt_pos = 0;
|
mt_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the next int. */
|
/**
|
||||||
|
* @fn static uint32_t mt_getInt(void)
|
||||||
|
* @return A random 4 byte number.
|
||||||
|
*/
|
||||||
static uint32_t mt_getInt(void) {
|
static uint32_t mt_getInt(void) {
|
||||||
if(mt_pos >= 624) mt_genArray();
|
if(mt_pos >= 624) mt_genArray();
|
||||||
|
|
||||||
@ -102,19 +131,33 @@ static uint32_t mt_getInt(void) {
|
|||||||
return mt_y;
|
return mt_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a random int. */
|
/**
|
||||||
|
* @fn unsigned int randint(void)
|
||||||
|
*
|
||||||
|
* @brief Get a random integer.
|
||||||
|
* @return A random integer.
|
||||||
|
*/
|
||||||
unsigned int randint(void) {
|
unsigned int randint(void) {
|
||||||
return mt_getInt();
|
return mt_getInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a random double. */
|
/**
|
||||||
static double m_div = (double)(0xFFFFFFFF);
|
* @fn double randfp(void)
|
||||||
|
*
|
||||||
|
* @brief Get a random float between 0 and 1 (inclusive).
|
||||||
|
* @return A random float between 0 and 1 (inclusive).
|
||||||
|
*/
|
||||||
|
static double m_div = (double)(0xFFFFFFFF); /**< Number to divide by. */
|
||||||
double randfp(void) {
|
double randfp(void) {
|
||||||
double m = (double)mt_getInt();
|
double m = (double)mt_getInt();
|
||||||
return m / m_div;
|
return m / m_div;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* @fn double Normal(double x)
|
||||||
|
*
|
||||||
|
* @brief Calculates the normal distribution.
|
||||||
|
*
|
||||||
* Calculate N(x) where N is the normal distribution.
|
* Calculate N(x) where N is the normal distribution.
|
||||||
*
|
*
|
||||||
* Approximates to a power series:
|
* Approximates to a power series:
|
||||||
@ -123,6 +166,9 @@ double randfp(void) {
|
|||||||
* where t = 1 / (1 + 0.2316419*x)
|
* where t = 1 / (1 + 0.2316419*x)
|
||||||
*
|
*
|
||||||
* Maximum absolute error is 7.5e^-8.
|
* Maximum absolute error is 7.5e^-8.
|
||||||
|
*
|
||||||
|
* @param x Value to calculate the normal of.
|
||||||
|
* @return The value of the Normal.
|
||||||
*/
|
*/
|
||||||
double Normal(double x) {
|
double Normal(double x) {
|
||||||
double t;
|
double t;
|
||||||
@ -142,7 +188,11 @@ double Normal(double x) {
|
|||||||
return (x > 0.) ? 1. - series : series;
|
return (x > 0.) ? 1. - series : series;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* @fn double NormalInverse(double p)
|
||||||
|
*
|
||||||
|
* @brief Calculate the inverse of the normal.
|
||||||
|
*
|
||||||
* Lower tail quantile for standard disribution function.
|
* Lower tail quantile for standard disribution function.
|
||||||
*
|
*
|
||||||
* This function returns an approximation of the inverse cumulative
|
* This function returns an approximation of the inverse cumulative
|
||||||
@ -162,7 +212,7 @@ static const double a[] = {
|
|||||||
1.383577518672690e+02,
|
1.383577518672690e+02,
|
||||||
-3.066479806614716e+01,
|
-3.066479806614716e+01,
|
||||||
2.506628277459239e+00
|
2.506628277459239e+00
|
||||||
};
|
}; /**< Inverse normal coefficients. */
|
||||||
|
|
||||||
static const double b[] = {
|
static const double b[] = {
|
||||||
-5.447609879822406e+01,
|
-5.447609879822406e+01,
|
||||||
@ -170,7 +220,7 @@ static const double b[] = {
|
|||||||
-1.556989798598866e+02,
|
-1.556989798598866e+02,
|
||||||
6.680131188771972e+01,
|
6.680131188771972e+01,
|
||||||
-1.328068155288572e+01
|
-1.328068155288572e+01
|
||||||
};
|
}; /**< Inverse normal coefficients. */
|
||||||
|
|
||||||
static const double c[] = {
|
static const double c[] = {
|
||||||
-7.784894002430293e-03,
|
-7.784894002430293e-03,
|
||||||
@ -179,17 +229,18 @@ static const double c[] = {
|
|||||||
-2.549732539343734e+00,
|
-2.549732539343734e+00,
|
||||||
4.374664141464968e+00,
|
4.374664141464968e+00,
|
||||||
2.938163982698783e+00
|
2.938163982698783e+00
|
||||||
};
|
}; /**< Inverse normal coefficients. */
|
||||||
|
|
||||||
static const double d[] = {
|
static const double d[] = {
|
||||||
7.784695709041462e-03,
|
7.784695709041462e-03,
|
||||||
3.224671290700398e-01,
|
3.224671290700398e-01,
|
||||||
2.445134137142996e+00,
|
2.445134137142996e+00,
|
||||||
3.754408661907416e+00
|
3.754408661907416e+00
|
||||||
};
|
}; /**< Inverse normal coefficients. */
|
||||||
|
|
||||||
#define LOW 0.02425
|
|
||||||
#define HIGH 0.97575
|
#define LOW 0.02425 /**< Low area threshold. */
|
||||||
|
#define HIGH 0.97575 /**< High area threshold. */
|
||||||
|
|
||||||
double NormalInverse( double p ) {
|
double NormalInverse( double p ) {
|
||||||
double x, e, u, q, r;
|
double x, e, u, q, r;
|
||||||
|
21
src/rng.h
21
src/rng.h
@ -1,7 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def RNG(L,H)
|
||||||
|
*
|
||||||
|
* @brief Get a random number between L and H (L <= RNG <= H).
|
||||||
|
*
|
||||||
|
* If L is bigger than H it inverts the roles.
|
||||||
|
*/
|
||||||
#define RNG(L,H) (((L)>(H)) ? RNG_SANE((H), (L)) : RNG_SANE((L),(H)))
|
#define RNG(L,H) (((L)>(H)) ? RNG_SANE((H), (L)) : RNG_SANE((L),(H)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def RNG_SANE(L,H)
|
||||||
|
*
|
||||||
|
* @brief Get a number between L and H (L <= RNG <= H).
|
||||||
|
*
|
||||||
|
* Result unspecified if L is bigger than H.
|
||||||
|
*/
|
||||||
#define RNG_SANE(L,H) ((int)L + (int)((double)(H-L+1) * randfp())) /* L <= RNG <= H */
|
#define RNG_SANE(L,H) ((int)L + (int)((double)(H-L+1) * randfp())) /* L <= RNG <= H */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def RNGF()
|
||||||
|
*
|
||||||
|
* @brief Get a random float between 0 and 1 (0. <= RNGF <= 1.).
|
||||||
|
*/
|
||||||
#define RNGF() (randfp()) /* 0. <= RNGF <= 1. */
|
#define RNGF() (randfp()) /* 0. <= RNGF <= 1. */
|
||||||
|
|
||||||
/* Init. */
|
/* Init. */
|
||||||
|
Loading…
Reference in New Issue
Block a user