1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-27 00:12:01 +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:
Tom Lane
2023-01-09 12:44:00 -05:00
parent 2673ebf49a
commit 38d81760c4
10 changed files with 164 additions and 29 deletions

View File

@@ -1136,8 +1136,8 @@ getGaussianRand(pg_prng_state *state, int64 min, int64 max,
Assert(parameter >= MIN_GAUSSIAN_PARAM);
/*
* Get user specified random number from this loop, with -parameter <
* stdev <= parameter
* Get normally-distributed random number in the range -parameter <= stdev
* < parameter.
*
* This loop is executed until the number is in the expected range.
*
@@ -1149,25 +1149,7 @@ getGaussianRand(pg_prng_state *state, int64 min, int64 max,
*/
do
{
/*
* 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] (see
* https://en.wikipedia.org/wiki/Box-Muller_transform)
*/
double rand1 = 1.0 - pg_prng_double(state);
double rand2 = 1.0 - pg_prng_double(state);
/* Box-Muller basic form transform */
double var_sqrt = sqrt(-2.0 * log(rand1));
stdev = var_sqrt * sin(2.0 * M_PI * rand2);
/*
* we may try with cos, but there may be a bias induced if the
* previous value fails the test. To be on the safe side, let us try
* over.
*/
stdev = pg_prng_double_normal(state);
}
while (stdev < -parameter || stdev >= parameter);