/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 | } |