mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Invent random_normal() to provide normally-distributed random numbers.
There is already a version of this in contrib/tablefunc, but it seems sufficiently widely useful to justify having it in core. Paul Ramsey Discussion: https://postgr.es/m/CACowWR0DqHAvOKUCNxTrASFkWsDLqKMd6WiXvVvaWg4pV1BMnQ@mail.gmail.com
This commit is contained in:
@@ -19,11 +19,17 @@
|
||||
|
||||
#include "c.h"
|
||||
|
||||
#include <math.h> /* for ldexp() */
|
||||
#include <math.h>
|
||||
|
||||
#include "common/pg_prng.h"
|
||||
#include "port/pg_bitutils.h"
|
||||
|
||||
/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
/* process-wide state vector */
|
||||
pg_prng_state pg_global_prng_state;
|
||||
|
||||
@@ -235,6 +241,35 @@ pg_prng_double(pg_prng_state *state)
|
||||
return ldexp((double) (v >> (64 - 52)), -52);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select a random double from the normal distribution with
|
||||
* mean = 0.0 and stddev = 1.0.
|
||||
*
|
||||
* To get a result from a different normal distribution use
|
||||
* STDDEV * pg_prng_double_normal() + MEAN
|
||||
*
|
||||
* Uses https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
|
||||
*/
|
||||
double
|
||||
pg_prng_double_normal(pg_prng_state *state)
|
||||
{
|
||||
double u1,
|
||||
u2,
|
||||
z0;
|
||||
|
||||
/*
|
||||
* pg_prng_double generates [0, 1), but for the basic version of the
|
||||
* Box-Muller transform the two uniformly distributed random numbers are
|
||||
* expected to be in (0, 1]; in particular we'd better not compute log(0).
|
||||
*/
|
||||
u1 = 1.0 - pg_prng_double(state);
|
||||
u2 = 1.0 - pg_prng_double(state);
|
||||
|
||||
/* Apply Box-Muller transform to get one normal-valued output */
|
||||
z0 = sqrt(-2.0 * log(u1)) * sin(2.0 * M_PI * u2);
|
||||
return z0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select a random boolean value.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user