From e6341323a8da64b18e9af3e75a4578230702d61c Mon Sep 17 00:00:00 2001 From: Dean Rasheed Date: Wed, 27 Mar 2024 10:12:39 +0000 Subject: Add functions to generate random numbers in a specified range. This adds 3 new variants of the random() function: random(min integer, max integer) returns integer random(min bigint, max bigint) returns bigint random(min numeric, max numeric) returns numeric Each returns a random number x in the range min <= x <= max. For the numeric function, the number of digits after the decimal point is equal to the number of digits that "min" or "max" has after the decimal point, whichever has more. The main entry points for these functions are in a new C source file. The existing random(), random_normal(), and setseed() functions are moved there too, so that they can all share the same PRNG state, which is kept private to that file. Dean Rasheed, reviewed by Jian He, David Zhang, Aleksander Alekseev, and Tomas Vondra. Discussion: https://postgr.es/m/CAEZATCV89Vxuq93xQdmc0t-0Y2zeeNQTdsjbmV7dyFBPykbV4Q@mail.gmail.com --- src/backend/utils/adt/float.c | 95 ------------------------------------------- 1 file changed, 95 deletions(-) (limited to 'src/backend/utils/adt/float.c') diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 901edcc8961..cbbb8aecafc 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -21,10 +21,8 @@ #include "catalog/pg_type.h" #include "common/int.h" -#include "common/pg_prng.h" #include "common/shortest_dec.h" #include "libpq/pqformat.h" -#include "miscadmin.h" #include "utils/array.h" #include "utils/float.h" #include "utils/fmgrprotos.h" @@ -64,10 +62,6 @@ float8 degree_c_sixty = 60.0; float8 degree_c_one_half = 0.5; float8 degree_c_one = 1.0; -/* State for drandom() and setseed() */ -static bool drandom_seed_set = false; -static pg_prng_state drandom_seed; - /* Local function prototypes */ static double sind_q1(double x); static double cosd_q1(double x); @@ -2785,95 +2779,6 @@ derfc(PG_FUNCTION_ARGS) } -/* ========== RANDOM FUNCTIONS ========== */ - - -/* - * initialize_drandom_seed - initialize drandom_seed if not yet done - */ -static void -initialize_drandom_seed(void) -{ - /* Initialize random seed, if not done yet in this process */ - if (unlikely(!drandom_seed_set)) - { - /* - * If possible, initialize the seed using high-quality random bits. - * Should that fail for some reason, we fall back on a lower-quality - * seed based on current time and PID. - */ - if (unlikely(!pg_prng_strong_seed(&drandom_seed))) - { - TimestampTz now = GetCurrentTimestamp(); - uint64 iseed; - - /* Mix the PID with the most predictable bits of the timestamp */ - iseed = (uint64) now ^ ((uint64) MyProcPid << 32); - pg_prng_seed(&drandom_seed, iseed); - } - drandom_seed_set = true; - } -} - -/* - * drandom - returns a random number - */ -Datum -drandom(PG_FUNCTION_ARGS) -{ - float8 result; - - initialize_drandom_seed(); - - /* pg_prng_double produces desired result range [0.0 - 1.0) */ - result = pg_prng_double(&drandom_seed); - - PG_RETURN_FLOAT8(result); -} - -/* - * drandom_normal - returns a random number from a normal distribution - */ -Datum -drandom_normal(PG_FUNCTION_ARGS) -{ - float8 mean = PG_GETARG_FLOAT8(0); - float8 stddev = PG_GETARG_FLOAT8(1); - float8 result, - z; - - initialize_drandom_seed(); - - /* Get random value from standard normal(mean = 0.0, stddev = 1.0) */ - z = pg_prng_double_normal(&drandom_seed); - /* Transform the normal standard variable (z) */ - /* using the target normal distribution parameters */ - result = (stddev * z) + mean; - - PG_RETURN_FLOAT8(result); -} - -/* - * setseed - set seed for the random number generator - */ -Datum -setseed(PG_FUNCTION_ARGS) -{ - float8 seed = PG_GETARG_FLOAT8(0); - - if (seed < -1 || seed > 1 || isnan(seed)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("setseed parameter %g is out of allowed range [-1,1]", - seed))); - - pg_prng_fseed(&drandom_seed, seed); - drandom_seed_set = true; - - PG_RETURN_VOID(); -} - - /* * ========================= -- cgit v1.2.3