summaryrefslogtreecommitdiff
path: root/src/common/pg_prng.c
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2024-03-27 10:12:39 +0000
committerDean Rasheed <dean.a.rasheed@gmail.com>2024-03-27 10:12:39 +0000
commite6341323a8da64b18e9af3e75a4578230702d61c (patch)
treef04f8e7fa84af4b569e58c85d2a7d98f65f45303 /src/common/pg_prng.c
parent818861eb578663a0d4d8d7dc4e18c96a148b3c75 (diff)
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
Diffstat (limited to 'src/common/pg_prng.c')
-rw-r--r--src/common/pg_prng.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/common/pg_prng.c b/src/common/pg_prng.c
index c1714a02bd9..15b39411a9b 100644
--- a/src/common/pg_prng.c
+++ b/src/common/pg_prng.c
@@ -185,6 +185,42 @@ pg_prng_int64p(pg_prng_state *state)
}
/*
+ * Select a random int64 uniformly from the range [rmin, rmax].
+ * If the range is empty, rmin is always produced.
+ */
+int64
+pg_prng_int64_range(pg_prng_state *state, int64 rmin, int64 rmax)
+{
+ int64 val;
+
+ if (likely(rmax > rmin))
+ {
+ uint64 uval;
+
+ /*
+ * Use pg_prng_uint64_range(). Can't simply pass it rmin and rmax,
+ * since (uint64) rmin will be larger than (uint64) rmax if rmin < 0.
+ */
+ uval = (uint64) rmin +
+ pg_prng_uint64_range(state, 0, (uint64) rmax - (uint64) rmin);
+
+ /*
+ * Safely convert back to int64, avoiding implementation-defined
+ * behavior for values larger than PG_INT64_MAX. Modern compilers
+ * will reduce this to a simple assignment.
+ */
+ if (uval > PG_INT64_MAX)
+ val = (int64) (uval - PG_INT64_MIN) + PG_INT64_MIN;
+ else
+ val = (int64) uval;
+ }
+ else
+ val = rmin;
+
+ return val;
+}
+
+/*
* Select a random uint32 uniformly from the range [0, PG_UINT32_MAX].
*/
uint32