PostgreSQL Source Code git master
pseudorandomfuncs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pseudorandomfuncs.c
4 * Functions giving SQL access to a pseudorandom number generator.
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/pseudorandomfuncs.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include <math.h>
17
18#include "common/pg_prng.h"
19#include "miscadmin.h"
20#include "utils/fmgrprotos.h"
21#include "utils/numeric.h"
22#include "utils/timestamp.h"
23
24/* Shared PRNG state used by all the random functions */
26static bool prng_seed_set = false;
27
28/*
29 * initialize_prng() -
30 *
31 * Initialize (seed) the PRNG, if not done yet in this process.
32 */
33static void
35{
37 {
38 /*
39 * If possible, seed the PRNG using high-quality random bits. Should
40 * that fail for some reason, we fall back on a lower-quality seed
41 * based on current time and PID.
42 */
44 {
46 uint64 iseed;
47
48 /* Mix the PID with the most predictable bits of the timestamp */
49 iseed = (uint64) now ^ ((uint64) MyProcPid << 32);
50 pg_prng_seed(&prng_state, iseed);
51 }
52 prng_seed_set = true;
53 }
54}
55
56/*
57 * setseed() -
58 *
59 * Seed the PRNG from a specified value in the range [-1.0, 1.0].
60 */
63{
64 float8 seed = PG_GETARG_FLOAT8(0);
65
66 if (seed < -1 || seed > 1 || isnan(seed))
68 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
69 errmsg("setseed parameter %g is out of allowed range [-1,1]",
70 seed));
71
73 prng_seed_set = true;
74
76}
77
78/*
79 * drandom() -
80 *
81 * Returns a random number chosen uniformly in the range [0.0, 1.0).
82 */
85{
86 float8 result;
87
89
90 /* pg_prng_double produces desired result range [0.0, 1.0) */
91 result = pg_prng_double(&prng_state);
92
93 PG_RETURN_FLOAT8(result);
94}
95
96/*
97 * drandom_normal() -
98 *
99 * Returns a random number from a normal distribution.
100 */
101Datum
103{
104 float8 mean = PG_GETARG_FLOAT8(0);
105 float8 stddev = PG_GETARG_FLOAT8(1);
106 float8 result,
107 z;
108
110
111 /* Get random value from standard normal(mean = 0.0, stddev = 1.0) */
113 /* Transform the normal standard variable (z) */
114 /* using the target normal distribution parameters */
115 result = (stddev * z) + mean;
116
117 PG_RETURN_FLOAT8(result);
118}
119
120/*
121 * int4random() -
122 *
123 * Returns a random 32-bit integer chosen uniformly in the specified range.
124 */
125Datum
127{
128 int32 rmin = PG_GETARG_INT32(0);
129 int32 rmax = PG_GETARG_INT32(1);
130 int32 result;
131
132 if (rmin > rmax)
134 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135 errmsg("lower bound must be less than or equal to upper bound"));
136
138
139 result = (int32) pg_prng_int64_range(&prng_state, rmin, rmax);
140
141 PG_RETURN_INT32(result);
142}
143
144/*
145 * int8random() -
146 *
147 * Returns a random 64-bit integer chosen uniformly in the specified range.
148 */
149Datum
151{
152 int64 rmin = PG_GETARG_INT64(0);
153 int64 rmax = PG_GETARG_INT64(1);
154 int64 result;
155
156 if (rmin > rmax)
158 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
159 errmsg("lower bound must be less than or equal to upper bound"));
160
162
163 result = pg_prng_int64_range(&prng_state, rmin, rmax);
164
165 PG_RETURN_INT64(result);
166}
167
168/*
169 * numeric_random() -
170 *
171 * Returns a random numeric value chosen uniformly in the specified range.
172 */
173Datum
175{
176 Numeric rmin = PG_GETARG_NUMERIC(0);
177 Numeric rmax = PG_GETARG_NUMERIC(1);
178 Numeric result;
179
181
182 result = random_numeric(&prng_state, rmin, rmax);
183
184 PG_RETURN_NUMERIC(result);
185}
Numeric random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
Definition: numeric.c:4346
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
int64_t int64
Definition: c.h:485
double float8
Definition: c.h:587
int32_t int32
Definition: c.h:484
uint64_t uint64
Definition: c.h:489
#define unlikely(x)
Definition: c.h:333
int64 TimestampTz
Definition: timestamp.h:39
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
int MyProcPid
Definition: globals.c:46
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:78
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
int64 pg_prng_int64_range(pg_prng_state *state, int64 rmin, int64 rmax)
Definition: pg_prng.c:192
double pg_prng_double(pg_prng_state *state)
Definition: pg_prng.c:268
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
double pg_prng_double_normal(pg_prng_state *state)
Definition: pg_prng.c:290
void pg_prng_fseed(pg_prng_state *state, double fseed)
Definition: pg_prng.c:102
#define pg_prng_strong_seed(state)
Definition: pg_prng.h:46
uintptr_t Datum
Definition: postgres.h:69
static void initialize_prng(void)
Datum numeric_random(PG_FUNCTION_ARGS)
static pg_prng_state prng_state
Datum int4random(PG_FUNCTION_ARGS)
Datum setseed(PG_FUNCTION_ARGS)
static bool prng_seed_set
Datum drandom(PG_FUNCTION_ARGS)
Datum drandom_normal(PG_FUNCTION_ARGS)
Datum int8random(PG_FUNCTION_ARGS)