decouple-drandom-from-other-random-calls-1.patch
text/x-diff
Filename: decouple-drandom-from-other-random-calls-1.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 0 | 0 |
| src/backend/utils/adt/float.c | 0 | 0 |
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 3786099..1df4356 100644
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 1136,1146 ****
</table>
<para>
! The characteristics of the values returned by
! <literal><function>random()</function></literal> depend
! on the system implementation. It is not suitable for cryptographic
! applications; see <xref linkend="pgcrypto"/> module for an alternative.
! </para>
<para>
Finally, <xref linkend="functions-math-trig-table"/> shows the
--- 1136,1150 ----
</table>
<para>
! The <function>random()</function> function uses a simple linear
! congruential algorithm. It is fast but not suitable for cryptographic
! applications; see the <xref linkend="pgcrypto"/> module for an
! alternative.
! If <function>setseed()</function> is called, the results of
! subsequent <function>random()</function> calls in the current session are
! repeatable by re-issuing <function>setseed()</function> with the same
! argument.
! </para>
<para>
Finally, <xref linkend="functions-math-trig-table"/> shows the
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index cf9327f..add099e 100644
*** a/src/backend/utils/adt/float.c
--- b/src/backend/utils/adt/float.c
***************
*** 22,31 ****
--- 22,34 ----
#include "catalog/pg_type.h"
#include "common/int.h"
#include "libpq/pqformat.h"
+ #include "miscadmin.h"
#include "utils/array.h"
+ #include "utils/backend_random.h"
#include "utils/float.h"
#include "utils/fmgrprotos.h"
#include "utils/sortsupport.h"
+ #include "utils/timestamp.h"
/* Configurable GUC parameter */
*************** float8 degree_c_sixty = 60.0;
*** 53,58 ****
--- 56,65 ----
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 unsigned short drandom_seed[3] = {0, 0, 0};
+
/* Local function prototypes */
static double sind_q1(double x);
static double cosd_q1(double x);
*************** drandom(PG_FUNCTION_ARGS)
*** 2378,2385 ****
{
float8 result;
! /* result [0.0 - 1.0) */
! result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
PG_RETURN_FLOAT8(result);
}
--- 2385,2414 ----
{
float8 result;
! /* 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 (!pg_backend_random((char *) drandom_seed, sizeof(drandom_seed)))
! {
! TimestampTz now = GetCurrentTimestamp();
! uint64 iseed;
!
! /* Mix the PID with the most predictable bits of the timestamp */
! iseed = (uint64) now ^ ((uint64) MyProcPid << 32);
! drandom_seed[0] = (unsigned short) iseed;
! drandom_seed[1] = (unsigned short) (iseed >> 16);
! drandom_seed[2] = (unsigned short) (iseed >> 32);
! }
! drandom_seed_set = true;
! }
!
! /* pg_erand48 produces desired result range [0.0 - 1.0) */
! result = pg_erand48(drandom_seed);
PG_RETURN_FLOAT8(result);
}
*************** Datum
*** 2392,2404 ****
setseed(PG_FUNCTION_ARGS)
{
float8 seed = PG_GETARG_FLOAT8(0);
! int iseed;
! if (seed < -1 || seed > 1)
! elog(ERROR, "setseed parameter %f out of range [-1,1]", seed);
! iseed = (int) (seed * MAX_RANDOM_VALUE);
! srandom((unsigned int) iseed);
PG_RETURN_VOID();
}
--- 2421,2440 ----
setseed(PG_FUNCTION_ARGS)
{
float8 seed = PG_GETARG_FLOAT8(0);
! uint64 iseed;
! 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)));
! /* Use sign bit + 47 fractional bits to fill drandom_seed[] */
! iseed = (int64) (seed * (float8) UINT64CONST(0x7FFFFFFFFFFF));
! drandom_seed[0] = (unsigned short) iseed;
! drandom_seed[1] = (unsigned short) (iseed >> 16);
! drandom_seed[2] = (unsigned short) (iseed >> 32);
! drandom_seed_set = true;
PG_RETURN_VOID();
}