YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/postgres/src/port/erand48.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * erand48.c
4
 *
5
 * This file supplies pg_erand48() and related functions, which except
6
 * for the names are just like the POSIX-standard erand48() family.
7
 * (We don't supply the full set though, only the ones we have found use
8
 * for in Postgres.  In particular, we do *not* implement lcong48(), so
9
 * that there is no need for the multiplier and addend to be variable.)
10
 *
11
 * We used to test for an operating system version rather than
12
 * unconditionally using our own, but (1) some versions of Cygwin have a
13
 * buggy erand48() that always returns zero and (2) as of 2011, glibc's
14
 * erand48() is strangely coded to be almost-but-not-quite thread-safe,
15
 * which doesn't matter for the backend but is important for pgbench.
16
 *
17
 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
18
 *
19
 * Portions Copyright (c) 1993 Martin Birgmeier
20
 * All rights reserved.
21
 *
22
 * You may redistribute unmodified or modified versions of this source
23
 * code provided that the above copyright notice and this and the
24
 * following conditions are retained.
25
 *
26
 * This software is provided ``as is'', and comes with no warranties
27
 * of any kind. I shall in no event be liable for anything that happens
28
 * to anyone/anything when using this software.
29
 *
30
 * IDENTIFICATION
31
 *    src/port/erand48.c
32
 *
33
 *-------------------------------------------------------------------------
34
 */
35
36
#include "c.h"
37
38
#include <math.h>
39
40
0
#define RAND48_SEED_0 (0x330e)
41
#define RAND48_SEED_1 (0xabcd)
42
#define RAND48_SEED_2 (0x1234)
43
0
#define RAND48_MULT_0 (0xe66d)
44
0
#define RAND48_MULT_1 (0xdeec)
45
0
#define RAND48_MULT_2 (0x0005)
46
0
#define RAND48_ADD    (0x000b)
47
48
static unsigned short _rand48_seed[3] = {
49
  RAND48_SEED_0,
50
  RAND48_SEED_1,
51
  RAND48_SEED_2
52
};
53
static unsigned short _rand48_mult[3] = {
54
  RAND48_MULT_0,
55
  RAND48_MULT_1,
56
  RAND48_MULT_2
57
};
58
static unsigned short _rand48_add = RAND48_ADD;
59
60
61
/*
62
 * Advance the 48-bit value stored in xseed[] to the next "random" number.
63
 */
64
static void
65
_dorand48(unsigned short xseed[3])
66
773
{
67
773
  unsigned long accu;
68
773
  unsigned short temp[2];
69
70
773
  accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
71
773
    (unsigned long) _rand48_add;
72
773
  temp[0] = (unsigned short) accu;  /* lower 16 bits */
73
773
  accu >>= sizeof(unsigned short) * 8;
74
773
  accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
75
773
    (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
76
773
  temp[1] = (unsigned short) accu;  /* middle 16 bits */
77
773
  accu >>= sizeof(unsigned short) * 8;
78
773
  accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
79
773
  xseed[0] = temp[0];
80
773
  xseed[1] = temp[1];
81
773
  xseed[2] = (unsigned short) accu;
82
773
}
83
84
85
/*
86
 * Generate a random floating-point value using caller-supplied state.
87
 * Values are uniformly distributed over the interval [0.0, 1.0).
88
 */
89
double
90
pg_erand48(unsigned short xseed[3])
91
773
{
92
773
  _dorand48(xseed);
93
773
  return ldexp((double) xseed[0], -48) +
94
773
    ldexp((double) xseed[1], -32) +
95
773
    ldexp((double) xseed[2], -16);
96
773
}
97
98
/*
99
 * Generate a random non-negative integral value using internal state.
100
 * Values are uniformly distributed over the interval [0, 2^31).
101
 */
102
long
103
pg_lrand48(void)
104
0
{
105
0
  _dorand48(_rand48_seed);
106
0
  return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
107
0
}
108
109
/*
110
 * Generate a random signed integral value using caller-supplied state.
111
 * Values are uniformly distributed over the interval [-2^31, 2^31).
112
 */
113
long
114
pg_jrand48(unsigned short xseed[3])
115
0
{
116
0
  _dorand48(xseed);
117
0
  return (int32) (((uint32) xseed[2] << 16) + (uint32) xseed[1]);
118
0
}
119
120
/*
121
 * Initialize the internal state using the given seed.
122
 *
123
 * Per POSIX, this uses only 32 bits from "seed" even if "long" is wider.
124
 * Hence, the set of possible seed values is smaller than it could be.
125
 * Better practice is to use caller-supplied state and initialize it with
126
 * random bits obtained from a high-quality source of random bits.
127
 *
128
 * Note: POSIX specifies a function seed48() that allows all 48 bits
129
 * of the internal state to be set, but we don't currently support that.
130
 */
131
void
132
pg_srand48(long seed)
133
0
{
134
0
  _rand48_seed[0] = RAND48_SEED_0;
135
0
  _rand48_seed[1] = (unsigned short) seed;
136
0
  _rand48_seed[2] = (unsigned short) (seed >> 16);
137
0
  _rand48_mult[0] = RAND48_MULT_0;
138
0
  _rand48_mult[1] = RAND48_MULT_1;
139
0
  _rand48_mult[2] = RAND48_MULT_2;
140
0
  _rand48_add = RAND48_ADD;
141
0
}