xref: /aosp_15_r20/external/bc/src/rand.c (revision 5a6e848804d15c18a0125914844ee4eb0bda4fcf)
1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker  *
4*5a6e8488SAndroid Build Coastguard Worker  * Parts of this code are adapted from the following:
5*5a6e8488SAndroid Build Coastguard Worker  *
6*5a6e8488SAndroid Build Coastguard Worker  * PCG, A Family of Better Random Number Generators.
7*5a6e8488SAndroid Build Coastguard Worker  *
8*5a6e8488SAndroid Build Coastguard Worker  * You can find the original source code at:
9*5a6e8488SAndroid Build Coastguard Worker  *   https://github.com/imneme/pcg-c
10*5a6e8488SAndroid Build Coastguard Worker  *
11*5a6e8488SAndroid Build Coastguard Worker  * -----------------------------------------------------------------------------
12*5a6e8488SAndroid Build Coastguard Worker  *
13*5a6e8488SAndroid Build Coastguard Worker  * This code is under the following license:
14*5a6e8488SAndroid Build Coastguard Worker  *
15*5a6e8488SAndroid Build Coastguard Worker  * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
16*5a6e8488SAndroid Build Coastguard Worker  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
17*5a6e8488SAndroid Build Coastguard Worker  *
18*5a6e8488SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
19*5a6e8488SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
20*5a6e8488SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
21*5a6e8488SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22*5a6e8488SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
23*5a6e8488SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
24*5a6e8488SAndroid Build Coastguard Worker  *
25*5a6e8488SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
26*5a6e8488SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
27*5a6e8488SAndroid Build Coastguard Worker  *
28*5a6e8488SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29*5a6e8488SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30*5a6e8488SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31*5a6e8488SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32*5a6e8488SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33*5a6e8488SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34*5a6e8488SAndroid Build Coastguard Worker  * SOFTWARE.
35*5a6e8488SAndroid Build Coastguard Worker  *
36*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
37*5a6e8488SAndroid Build Coastguard Worker  *
38*5a6e8488SAndroid Build Coastguard Worker  * Code for the RNG.
39*5a6e8488SAndroid Build Coastguard Worker  *
40*5a6e8488SAndroid Build Coastguard Worker  */
41*5a6e8488SAndroid Build Coastguard Worker 
42*5a6e8488SAndroid Build Coastguard Worker #include <assert.h>
43*5a6e8488SAndroid Build Coastguard Worker #include <stdlib.h>
44*5a6e8488SAndroid Build Coastguard Worker #include <string.h>
45*5a6e8488SAndroid Build Coastguard Worker #include <time.h>
46*5a6e8488SAndroid Build Coastguard Worker #include <fcntl.h>
47*5a6e8488SAndroid Build Coastguard Worker 
48*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
49*5a6e8488SAndroid Build Coastguard Worker #include <unistd.h>
50*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
51*5a6e8488SAndroid Build Coastguard Worker #include <Windows.h>
52*5a6e8488SAndroid Build Coastguard Worker #include <bcrypt.h>
53*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
54*5a6e8488SAndroid Build Coastguard Worker 
55*5a6e8488SAndroid Build Coastguard Worker #include <status.h>
56*5a6e8488SAndroid Build Coastguard Worker #include <rand.h>
57*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
58*5a6e8488SAndroid Build Coastguard Worker 
59*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
60*5a6e8488SAndroid Build Coastguard Worker 
61*5a6e8488SAndroid Build Coastguard Worker #if !BC_RAND_BUILTIN
62*5a6e8488SAndroid Build Coastguard Worker 
63*5a6e8488SAndroid Build Coastguard Worker /**
64*5a6e8488SAndroid Build Coastguard Worker  * Adds two 64-bit values and preserves the overflow.
65*5a6e8488SAndroid Build Coastguard Worker  * @param a  The first operand.
66*5a6e8488SAndroid Build Coastguard Worker  * @param b  The second operand.
67*5a6e8488SAndroid Build Coastguard Worker  * @return   The sum, including overflow.
68*5a6e8488SAndroid Build Coastguard Worker  */
69*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_addition(uint_fast64_t a,uint_fast64_t b)70*5a6e8488SAndroid Build Coastguard Worker bc_rand_addition(uint_fast64_t a, uint_fast64_t b)
71*5a6e8488SAndroid Build Coastguard Worker {
72*5a6e8488SAndroid Build Coastguard Worker 	BcRandState res;
73*5a6e8488SAndroid Build Coastguard Worker 
74*5a6e8488SAndroid Build Coastguard Worker 	res.lo = a + b;
75*5a6e8488SAndroid Build Coastguard Worker 	res.hi = (res.lo < a);
76*5a6e8488SAndroid Build Coastguard Worker 
77*5a6e8488SAndroid Build Coastguard Worker 	return res;
78*5a6e8488SAndroid Build Coastguard Worker }
79*5a6e8488SAndroid Build Coastguard Worker 
80*5a6e8488SAndroid Build Coastguard Worker /**
81*5a6e8488SAndroid Build Coastguard Worker  * Adds two 128-bit values and discards the overflow.
82*5a6e8488SAndroid Build Coastguard Worker  * @param a  The first operand.
83*5a6e8488SAndroid Build Coastguard Worker  * @param b  The second operand.
84*5a6e8488SAndroid Build Coastguard Worker  * @return   The sum, without overflow.
85*5a6e8488SAndroid Build Coastguard Worker  */
86*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_addition2(BcRandState a,BcRandState b)87*5a6e8488SAndroid Build Coastguard Worker bc_rand_addition2(BcRandState a, BcRandState b)
88*5a6e8488SAndroid Build Coastguard Worker {
89*5a6e8488SAndroid Build Coastguard Worker 	BcRandState temp, res;
90*5a6e8488SAndroid Build Coastguard Worker 
91*5a6e8488SAndroid Build Coastguard Worker 	res = bc_rand_addition(a.lo, b.lo);
92*5a6e8488SAndroid Build Coastguard Worker 	temp = bc_rand_addition(a.hi, b.hi);
93*5a6e8488SAndroid Build Coastguard Worker 	res.hi += temp.lo;
94*5a6e8488SAndroid Build Coastguard Worker 
95*5a6e8488SAndroid Build Coastguard Worker 	return res;
96*5a6e8488SAndroid Build Coastguard Worker }
97*5a6e8488SAndroid Build Coastguard Worker 
98*5a6e8488SAndroid Build Coastguard Worker /**
99*5a6e8488SAndroid Build Coastguard Worker  * Multiplies two 64-bit values and preserves the overflow.
100*5a6e8488SAndroid Build Coastguard Worker  * @param a  The first operand.
101*5a6e8488SAndroid Build Coastguard Worker  * @param b  The second operand.
102*5a6e8488SAndroid Build Coastguard Worker  * @return   The product, including overflow.
103*5a6e8488SAndroid Build Coastguard Worker  */
104*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_multiply(uint_fast64_t a,uint_fast64_t b)105*5a6e8488SAndroid Build Coastguard Worker bc_rand_multiply(uint_fast64_t a, uint_fast64_t b)
106*5a6e8488SAndroid Build Coastguard Worker {
107*5a6e8488SAndroid Build Coastguard Worker 	uint_fast64_t al, ah, bl, bh, c0, c1, c2, c3;
108*5a6e8488SAndroid Build Coastguard Worker 	BcRandState carry, res;
109*5a6e8488SAndroid Build Coastguard Worker 
110*5a6e8488SAndroid Build Coastguard Worker 	al = BC_RAND_TRUNC32(a);
111*5a6e8488SAndroid Build Coastguard Worker 	ah = BC_RAND_CHOP32(a);
112*5a6e8488SAndroid Build Coastguard Worker 	bl = BC_RAND_TRUNC32(b);
113*5a6e8488SAndroid Build Coastguard Worker 	bh = BC_RAND_CHOP32(b);
114*5a6e8488SAndroid Build Coastguard Worker 
115*5a6e8488SAndroid Build Coastguard Worker 	c0 = al * bl;
116*5a6e8488SAndroid Build Coastguard Worker 	c1 = al * bh;
117*5a6e8488SAndroid Build Coastguard Worker 	c2 = ah * bl;
118*5a6e8488SAndroid Build Coastguard Worker 	c3 = ah * bh;
119*5a6e8488SAndroid Build Coastguard Worker 
120*5a6e8488SAndroid Build Coastguard Worker 	carry = bc_rand_addition(c1, c2);
121*5a6e8488SAndroid Build Coastguard Worker 
122*5a6e8488SAndroid Build Coastguard Worker 	res = bc_rand_addition(c0, (BC_RAND_TRUNC32(carry.lo)) << 32);
123*5a6e8488SAndroid Build Coastguard Worker 	res.hi += BC_RAND_CHOP32(carry.lo) + c3 + (carry.hi << 32);
124*5a6e8488SAndroid Build Coastguard Worker 
125*5a6e8488SAndroid Build Coastguard Worker 	return res;
126*5a6e8488SAndroid Build Coastguard Worker }
127*5a6e8488SAndroid Build Coastguard Worker 
128*5a6e8488SAndroid Build Coastguard Worker /**
129*5a6e8488SAndroid Build Coastguard Worker  * Multiplies two 128-bit values and discards the overflow.
130*5a6e8488SAndroid Build Coastguard Worker  * @param a  The first operand.
131*5a6e8488SAndroid Build Coastguard Worker  * @param b  The second operand.
132*5a6e8488SAndroid Build Coastguard Worker  * @return   The product, without overflow.
133*5a6e8488SAndroid Build Coastguard Worker  */
134*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_multiply2(BcRandState a,BcRandState b)135*5a6e8488SAndroid Build Coastguard Worker bc_rand_multiply2(BcRandState a, BcRandState b)
136*5a6e8488SAndroid Build Coastguard Worker {
137*5a6e8488SAndroid Build Coastguard Worker 	BcRandState c0, c1, c2, carry;
138*5a6e8488SAndroid Build Coastguard Worker 
139*5a6e8488SAndroid Build Coastguard Worker 	c0 = bc_rand_multiply(a.lo, b.lo);
140*5a6e8488SAndroid Build Coastguard Worker 	c1 = bc_rand_multiply(a.lo, b.hi);
141*5a6e8488SAndroid Build Coastguard Worker 	c2 = bc_rand_multiply(a.hi, b.lo);
142*5a6e8488SAndroid Build Coastguard Worker 
143*5a6e8488SAndroid Build Coastguard Worker 	carry = bc_rand_addition2(c1, c2);
144*5a6e8488SAndroid Build Coastguard Worker 	carry.hi = carry.lo;
145*5a6e8488SAndroid Build Coastguard Worker 	carry.lo = 0;
146*5a6e8488SAndroid Build Coastguard Worker 
147*5a6e8488SAndroid Build Coastguard Worker 	return bc_rand_addition2(c0, carry);
148*5a6e8488SAndroid Build Coastguard Worker }
149*5a6e8488SAndroid Build Coastguard Worker 
150*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
151*5a6e8488SAndroid Build Coastguard Worker 
152*5a6e8488SAndroid Build Coastguard Worker /**
153*5a6e8488SAndroid Build Coastguard Worker  * Marks a PRNG as modified. This is important for properly maintaining the
154*5a6e8488SAndroid Build Coastguard Worker  * stack of PRNG's.
155*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG to mark as modified.
156*5a6e8488SAndroid Build Coastguard Worker  */
157*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_setModified(BcRNGData * r)158*5a6e8488SAndroid Build Coastguard Worker bc_rand_setModified(BcRNGData* r)
159*5a6e8488SAndroid Build Coastguard Worker {
160*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
161*5a6e8488SAndroid Build Coastguard Worker 	r->inc |= (BcRandState) 1UL;
162*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
163*5a6e8488SAndroid Build Coastguard Worker 	r->inc.lo |= (uint_fast64_t) 1UL;
164*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
165*5a6e8488SAndroid Build Coastguard Worker }
166*5a6e8488SAndroid Build Coastguard Worker 
167*5a6e8488SAndroid Build Coastguard Worker /**
168*5a6e8488SAndroid Build Coastguard Worker  * Marks a PRNG as not modified. This is important for properly maintaining the
169*5a6e8488SAndroid Build Coastguard Worker  * stack of PRNG's.
170*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG to mark as not modified.
171*5a6e8488SAndroid Build Coastguard Worker  */
172*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_clearModified(BcRNGData * r)173*5a6e8488SAndroid Build Coastguard Worker bc_rand_clearModified(BcRNGData* r)
174*5a6e8488SAndroid Build Coastguard Worker {
175*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
176*5a6e8488SAndroid Build Coastguard Worker 	r->inc &= ~((BcRandState) 1UL);
177*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
178*5a6e8488SAndroid Build Coastguard Worker 	r->inc.lo &= ~(1UL);
179*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
180*5a6e8488SAndroid Build Coastguard Worker }
181*5a6e8488SAndroid Build Coastguard Worker 
182*5a6e8488SAndroid Build Coastguard Worker /**
183*5a6e8488SAndroid Build Coastguard Worker  * Copies a PRNG to another and marks the copy as modified if it already was or
184*5a6e8488SAndroid Build Coastguard Worker  * marks it modified if it already was.
185*5a6e8488SAndroid Build Coastguard Worker  * @param d  The destination PRNG.
186*5a6e8488SAndroid Build Coastguard Worker  * @param s  The source PRNG.
187*5a6e8488SAndroid Build Coastguard Worker  */
188*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_copy(BcRNGData * d,BcRNGData * s)189*5a6e8488SAndroid Build Coastguard Worker bc_rand_copy(BcRNGData* d, BcRNGData* s)
190*5a6e8488SAndroid Build Coastguard Worker {
191*5a6e8488SAndroid Build Coastguard Worker 	bool unmod = BC_RAND_NOTMODIFIED(d);
192*5a6e8488SAndroid Build Coastguard Worker 
193*5a6e8488SAndroid Build Coastguard Worker 	// NOLINTNEXTLINE
194*5a6e8488SAndroid Build Coastguard Worker 	memcpy(d, s, sizeof(BcRNGData));
195*5a6e8488SAndroid Build Coastguard Worker 
196*5a6e8488SAndroid Build Coastguard Worker 	if (!unmod) bc_rand_setModified(d);
197*5a6e8488SAndroid Build Coastguard Worker 	else if (!BC_RAND_NOTMODIFIED(s)) bc_rand_clearModified(d);
198*5a6e8488SAndroid Build Coastguard Worker }
199*5a6e8488SAndroid Build Coastguard Worker 
200*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
201*5a6e8488SAndroid Build Coastguard Worker 
202*5a6e8488SAndroid Build Coastguard Worker /**
203*5a6e8488SAndroid Build Coastguard Worker  * Reads random data from a file.
204*5a6e8488SAndroid Build Coastguard Worker  * @param ptr  A pointer to the file, as a void pointer.
205*5a6e8488SAndroid Build Coastguard Worker  * @return     The random data as an unsigned long.
206*5a6e8488SAndroid Build Coastguard Worker  */
207*5a6e8488SAndroid Build Coastguard Worker static ulong
bc_rand_frand(void * ptr)208*5a6e8488SAndroid Build Coastguard Worker bc_rand_frand(void* ptr)
209*5a6e8488SAndroid Build Coastguard Worker {
210*5a6e8488SAndroid Build Coastguard Worker 	ulong buf[1];
211*5a6e8488SAndroid Build Coastguard Worker 	int fd;
212*5a6e8488SAndroid Build Coastguard Worker 	ssize_t nread;
213*5a6e8488SAndroid Build Coastguard Worker 
214*5a6e8488SAndroid Build Coastguard Worker 	assert(ptr != NULL);
215*5a6e8488SAndroid Build Coastguard Worker 
216*5a6e8488SAndroid Build Coastguard Worker 	fd = *((int*) ptr);
217*5a6e8488SAndroid Build Coastguard Worker 
218*5a6e8488SAndroid Build Coastguard Worker 	nread = read(fd, buf, sizeof(ulong));
219*5a6e8488SAndroid Build Coastguard Worker 
220*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(nread != sizeof(ulong))) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
221*5a6e8488SAndroid Build Coastguard Worker 
222*5a6e8488SAndroid Build Coastguard Worker 	return *((ulong*) buf);
223*5a6e8488SAndroid Build Coastguard Worker }
224*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
225*5a6e8488SAndroid Build Coastguard Worker 
226*5a6e8488SAndroid Build Coastguard Worker /**
227*5a6e8488SAndroid Build Coastguard Worker  * Reads random data from BCryptGenRandom().
228*5a6e8488SAndroid Build Coastguard Worker  * @param ptr  An unused parameter.
229*5a6e8488SAndroid Build Coastguard Worker  * @return     The random data as an unsigned long.
230*5a6e8488SAndroid Build Coastguard Worker  */
231*5a6e8488SAndroid Build Coastguard Worker static ulong
bc_rand_winrand(void * ptr)232*5a6e8488SAndroid Build Coastguard Worker bc_rand_winrand(void* ptr)
233*5a6e8488SAndroid Build Coastguard Worker {
234*5a6e8488SAndroid Build Coastguard Worker 	ulong buf[1];
235*5a6e8488SAndroid Build Coastguard Worker 	NTSTATUS s;
236*5a6e8488SAndroid Build Coastguard Worker 
237*5a6e8488SAndroid Build Coastguard Worker 	BC_UNUSED(ptr);
238*5a6e8488SAndroid Build Coastguard Worker 
239*5a6e8488SAndroid Build Coastguard Worker 	buf[0] = 0;
240*5a6e8488SAndroid Build Coastguard Worker 
241*5a6e8488SAndroid Build Coastguard Worker 	s = BCryptGenRandom(NULL, (char*) buf, sizeof(ulong),
242*5a6e8488SAndroid Build Coastguard Worker 	                    BCRYPT_USE_SYSTEM_PREFERRED_RNG);
243*5a6e8488SAndroid Build Coastguard Worker 
244*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!BCRYPT_SUCCESS(s))) buf[0] = 0;
245*5a6e8488SAndroid Build Coastguard Worker 
246*5a6e8488SAndroid Build Coastguard Worker 	return buf[0];
247*5a6e8488SAndroid Build Coastguard Worker }
248*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
249*5a6e8488SAndroid Build Coastguard Worker 
250*5a6e8488SAndroid Build Coastguard Worker /**
251*5a6e8488SAndroid Build Coastguard Worker  * Reads random data from rand(), byte-by-byte because rand() is only guaranteed
252*5a6e8488SAndroid Build Coastguard Worker  * to return 15 bits of random data. This is the final fallback and is not
253*5a6e8488SAndroid Build Coastguard Worker  * preferred as it is possible to access cryptographically-secure PRNG's on most
254*5a6e8488SAndroid Build Coastguard Worker  * systems.
255*5a6e8488SAndroid Build Coastguard Worker  * @param ptr  An unused parameter.
256*5a6e8488SAndroid Build Coastguard Worker  * @return     The random data as an unsigned long.
257*5a6e8488SAndroid Build Coastguard Worker  */
258*5a6e8488SAndroid Build Coastguard Worker static ulong
bc_rand_rand(void * ptr)259*5a6e8488SAndroid Build Coastguard Worker bc_rand_rand(void* ptr)
260*5a6e8488SAndroid Build Coastguard Worker {
261*5a6e8488SAndroid Build Coastguard Worker 	size_t i;
262*5a6e8488SAndroid Build Coastguard Worker 	ulong res = 0;
263*5a6e8488SAndroid Build Coastguard Worker 
264*5a6e8488SAndroid Build Coastguard Worker 	BC_UNUSED(ptr);
265*5a6e8488SAndroid Build Coastguard Worker 
266*5a6e8488SAndroid Build Coastguard Worker 	// Fill up the unsigned long byte-by-byte.
267*5a6e8488SAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(ulong); ++i)
268*5a6e8488SAndroid Build Coastguard Worker 	{
269*5a6e8488SAndroid Build Coastguard Worker 		res |= ((ulong) (rand() & BC_RAND_SRAND_BITS)) << (i * CHAR_BIT);
270*5a6e8488SAndroid Build Coastguard Worker 	}
271*5a6e8488SAndroid Build Coastguard Worker 
272*5a6e8488SAndroid Build Coastguard Worker 	return res;
273*5a6e8488SAndroid Build Coastguard Worker }
274*5a6e8488SAndroid Build Coastguard Worker 
275*5a6e8488SAndroid Build Coastguard Worker /**
276*5a6e8488SAndroid Build Coastguard Worker  * Returns the actual increment of the PRNG, including the required last odd
277*5a6e8488SAndroid Build Coastguard Worker  * bit.
278*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG.
279*5a6e8488SAndroid Build Coastguard Worker  * @return   The increment of the PRNG, including the last odd bit.
280*5a6e8488SAndroid Build Coastguard Worker  */
281*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_inc(BcRNGData * r)282*5a6e8488SAndroid Build Coastguard Worker bc_rand_inc(BcRNGData* r)
283*5a6e8488SAndroid Build Coastguard Worker {
284*5a6e8488SAndroid Build Coastguard Worker 	BcRandState inc;
285*5a6e8488SAndroid Build Coastguard Worker 
286*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
287*5a6e8488SAndroid Build Coastguard Worker 	inc = r->inc | 1;
288*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
289*5a6e8488SAndroid Build Coastguard Worker 	inc.lo = r->inc.lo | 1;
290*5a6e8488SAndroid Build Coastguard Worker 	inc.hi = r->inc.hi;
291*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
292*5a6e8488SAndroid Build Coastguard Worker 
293*5a6e8488SAndroid Build Coastguard Worker 	return inc;
294*5a6e8488SAndroid Build Coastguard Worker }
295*5a6e8488SAndroid Build Coastguard Worker 
296*5a6e8488SAndroid Build Coastguard Worker /**
297*5a6e8488SAndroid Build Coastguard Worker  * Sets up the increment for the PRNG.
298*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG whose increment will be set up.
299*5a6e8488SAndroid Build Coastguard Worker  */
300*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_setupInc(BcRNGData * r)301*5a6e8488SAndroid Build Coastguard Worker bc_rand_setupInc(BcRNGData* r)
302*5a6e8488SAndroid Build Coastguard Worker {
303*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
304*5a6e8488SAndroid Build Coastguard Worker 	r->inc <<= 1UL;
305*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
306*5a6e8488SAndroid Build Coastguard Worker 	r->inc.hi <<= 1UL;
307*5a6e8488SAndroid Build Coastguard Worker 	r->inc.hi |= (r->inc.lo & (1UL << (BC_LONG_BIT - 1))) >> (BC_LONG_BIT - 1);
308*5a6e8488SAndroid Build Coastguard Worker 	r->inc.lo <<= 1UL;
309*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
310*5a6e8488SAndroid Build Coastguard Worker }
311*5a6e8488SAndroid Build Coastguard Worker 
312*5a6e8488SAndroid Build Coastguard Worker /**
313*5a6e8488SAndroid Build Coastguard Worker  * Seeds the state of a PRNG.
314*5a6e8488SAndroid Build Coastguard Worker  * @param state  The return parameter; the state to seed.
315*5a6e8488SAndroid Build Coastguard Worker  * @param val1   The lower half of the state.
316*5a6e8488SAndroid Build Coastguard Worker  * @param val2   The upper half of the state.
317*5a6e8488SAndroid Build Coastguard Worker  */
318*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_seedState(BcRandState * state,ulong val1,ulong val2)319*5a6e8488SAndroid Build Coastguard Worker bc_rand_seedState(BcRandState* state, ulong val1, ulong val2)
320*5a6e8488SAndroid Build Coastguard Worker {
321*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
322*5a6e8488SAndroid Build Coastguard Worker 	*state = ((BcRandState) val1) | ((BcRandState) val2) << (BC_LONG_BIT);
323*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
324*5a6e8488SAndroid Build Coastguard Worker 	state->lo = val1;
325*5a6e8488SAndroid Build Coastguard Worker 	state->hi = val2;
326*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
327*5a6e8488SAndroid Build Coastguard Worker }
328*5a6e8488SAndroid Build Coastguard Worker 
329*5a6e8488SAndroid Build Coastguard Worker /**
330*5a6e8488SAndroid Build Coastguard Worker  * Seeds a PRNG.
331*5a6e8488SAndroid Build Coastguard Worker  * @param r       The return parameter; the PRNG to seed.
332*5a6e8488SAndroid Build Coastguard Worker  * @param state1  The lower half of the state.
333*5a6e8488SAndroid Build Coastguard Worker  * @param state2  The upper half of the state.
334*5a6e8488SAndroid Build Coastguard Worker  * @param inc1    The lower half of the increment.
335*5a6e8488SAndroid Build Coastguard Worker  * @param inc2    The upper half of the increment.
336*5a6e8488SAndroid Build Coastguard Worker  */
337*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_seedRNG(BcRNGData * r,ulong state1,ulong state2,ulong inc1,ulong inc2)338*5a6e8488SAndroid Build Coastguard Worker bc_rand_seedRNG(BcRNGData* r, ulong state1, ulong state2, ulong inc1,
339*5a6e8488SAndroid Build Coastguard Worker                 ulong inc2)
340*5a6e8488SAndroid Build Coastguard Worker {
341*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_seedState(&r->state, state1, state2);
342*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_seedState(&r->inc, inc1, inc2);
343*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_setupInc(r);
344*5a6e8488SAndroid Build Coastguard Worker }
345*5a6e8488SAndroid Build Coastguard Worker 
346*5a6e8488SAndroid Build Coastguard Worker /**
347*5a6e8488SAndroid Build Coastguard Worker  * Fills a PRNG with random data to seed it.
348*5a6e8488SAndroid Build Coastguard Worker  * @param r       The PRNG.
349*5a6e8488SAndroid Build Coastguard Worker  * @param fulong  The function to fill an unsigned long.
350*5a6e8488SAndroid Build Coastguard Worker  * @param ptr     The parameter to pass to @a fulong.
351*5a6e8488SAndroid Build Coastguard Worker  */
352*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_fill(BcRNGData * r,BcRandUlong fulong,void * ptr)353*5a6e8488SAndroid Build Coastguard Worker bc_rand_fill(BcRNGData* r, BcRandUlong fulong, void* ptr)
354*5a6e8488SAndroid Build Coastguard Worker {
355*5a6e8488SAndroid Build Coastguard Worker 	ulong state1, state2, inc1, inc2;
356*5a6e8488SAndroid Build Coastguard Worker 
357*5a6e8488SAndroid Build Coastguard Worker 	state1 = fulong(ptr);
358*5a6e8488SAndroid Build Coastguard Worker 	state2 = fulong(ptr);
359*5a6e8488SAndroid Build Coastguard Worker 
360*5a6e8488SAndroid Build Coastguard Worker 	inc1 = fulong(ptr);
361*5a6e8488SAndroid Build Coastguard Worker 	inc2 = fulong(ptr);
362*5a6e8488SAndroid Build Coastguard Worker 
363*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_seedRNG(r, state1, state2, inc1, inc2);
364*5a6e8488SAndroid Build Coastguard Worker }
365*5a6e8488SAndroid Build Coastguard Worker 
366*5a6e8488SAndroid Build Coastguard Worker /**
367*5a6e8488SAndroid Build Coastguard Worker  * Executes the "step" portion of a PCG udpate.
368*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG.
369*5a6e8488SAndroid Build Coastguard Worker  */
370*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_step(BcRNGData * r)371*5a6e8488SAndroid Build Coastguard Worker bc_rand_step(BcRNGData* r)
372*5a6e8488SAndroid Build Coastguard Worker {
373*5a6e8488SAndroid Build Coastguard Worker 	BcRandState temp = bc_rand_mul2(r->state, bc_rand_multiplier);
374*5a6e8488SAndroid Build Coastguard Worker 	r->state = bc_rand_add2(temp, bc_rand_inc(r));
375*5a6e8488SAndroid Build Coastguard Worker }
376*5a6e8488SAndroid Build Coastguard Worker 
377*5a6e8488SAndroid Build Coastguard Worker /**
378*5a6e8488SAndroid Build Coastguard Worker  * Returns the new output of PCG.
379*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG.
380*5a6e8488SAndroid Build Coastguard Worker  * @return   The new output from the PRNG.
381*5a6e8488SAndroid Build Coastguard Worker  */
382*5a6e8488SAndroid Build Coastguard Worker static BcRand
bc_rand_output(BcRNGData * r)383*5a6e8488SAndroid Build Coastguard Worker bc_rand_output(BcRNGData* r)
384*5a6e8488SAndroid Build Coastguard Worker {
385*5a6e8488SAndroid Build Coastguard Worker 	return BC_RAND_ROT(BC_RAND_FOLD(r->state), BC_RAND_ROTAMT(r->state));
386*5a6e8488SAndroid Build Coastguard Worker }
387*5a6e8488SAndroid Build Coastguard Worker 
388*5a6e8488SAndroid Build Coastguard Worker /**
389*5a6e8488SAndroid Build Coastguard Worker  * Seeds every PRNG on the PRNG stack between the top and @a idx that has not
390*5a6e8488SAndroid Build Coastguard Worker  * been seeded.
391*5a6e8488SAndroid Build Coastguard Worker  * @param r    The PRNG stack.
392*5a6e8488SAndroid Build Coastguard Worker  * @param rng  The PRNG on the top of the stack. Must have been seeded.
393*5a6e8488SAndroid Build Coastguard Worker  */
394*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_seedZeroes(BcRNG * r,BcRNGData * rng,size_t idx)395*5a6e8488SAndroid Build Coastguard Worker bc_rand_seedZeroes(BcRNG* r, BcRNGData* rng, size_t idx)
396*5a6e8488SAndroid Build Coastguard Worker {
397*5a6e8488SAndroid Build Coastguard Worker 	BcRNGData* rng2;
398*5a6e8488SAndroid Build Coastguard Worker 
399*5a6e8488SAndroid Build Coastguard Worker 	// Just return if there are none to do.
400*5a6e8488SAndroid Build Coastguard Worker 	if (r->v.len <= idx) return;
401*5a6e8488SAndroid Build Coastguard Worker 
402*5a6e8488SAndroid Build Coastguard Worker 	// Get the first PRNG that might need to be seeded.
403*5a6e8488SAndroid Build Coastguard Worker 	rng2 = bc_vec_item_rev(&r->v, idx);
404*5a6e8488SAndroid Build Coastguard Worker 
405*5a6e8488SAndroid Build Coastguard Worker 	// Does it need seeding? Then it, and maybe more, do.
406*5a6e8488SAndroid Build Coastguard Worker 	if (BC_RAND_ZERO(rng2))
407*5a6e8488SAndroid Build Coastguard Worker 	{
408*5a6e8488SAndroid Build Coastguard Worker 		size_t i;
409*5a6e8488SAndroid Build Coastguard Worker 
410*5a6e8488SAndroid Build Coastguard Worker 		// Seed the ones that need seeding.
411*5a6e8488SAndroid Build Coastguard Worker 		for (i = 1; i < r->v.len; ++i)
412*5a6e8488SAndroid Build Coastguard Worker 		{
413*5a6e8488SAndroid Build Coastguard Worker 			bc_rand_copy(bc_vec_item_rev(&r->v, i), rng);
414*5a6e8488SAndroid Build Coastguard Worker 		}
415*5a6e8488SAndroid Build Coastguard Worker 	}
416*5a6e8488SAndroid Build Coastguard Worker }
417*5a6e8488SAndroid Build Coastguard Worker 
418*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_srand(BcRNGData * rng)419*5a6e8488SAndroid Build Coastguard Worker bc_rand_srand(BcRNGData* rng)
420*5a6e8488SAndroid Build Coastguard Worker {
421*5a6e8488SAndroid Build Coastguard Worker 	int fd = 0;
422*5a6e8488SAndroid Build Coastguard Worker 
423*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_LOCK;
424*5a6e8488SAndroid Build Coastguard Worker 
425*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
426*5a6e8488SAndroid Build Coastguard Worker 
427*5a6e8488SAndroid Build Coastguard Worker 	// Try /dev/urandom first.
428*5a6e8488SAndroid Build Coastguard Worker 	fd = open("/dev/urandom", O_RDONLY);
429*5a6e8488SAndroid Build Coastguard Worker 
430*5a6e8488SAndroid Build Coastguard Worker 	if (BC_NO_ERR(fd >= 0))
431*5a6e8488SAndroid Build Coastguard Worker 	{
432*5a6e8488SAndroid Build Coastguard Worker 		bc_rand_fill(rng, bc_rand_frand, &fd);
433*5a6e8488SAndroid Build Coastguard Worker 		close(fd);
434*5a6e8488SAndroid Build Coastguard Worker 	}
435*5a6e8488SAndroid Build Coastguard Worker 	else
436*5a6e8488SAndroid Build Coastguard Worker 	{
437*5a6e8488SAndroid Build Coastguard Worker 		// Try /dev/random second.
438*5a6e8488SAndroid Build Coastguard Worker 		fd = open("/dev/random", O_RDONLY);
439*5a6e8488SAndroid Build Coastguard Worker 
440*5a6e8488SAndroid Build Coastguard Worker 		if (BC_NO_ERR(fd >= 0))
441*5a6e8488SAndroid Build Coastguard Worker 		{
442*5a6e8488SAndroid Build Coastguard Worker 			bc_rand_fill(rng, bc_rand_frand, &fd);
443*5a6e8488SAndroid Build Coastguard Worker 			close(fd);
444*5a6e8488SAndroid Build Coastguard Worker 		}
445*5a6e8488SAndroid Build Coastguard Worker 	}
446*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
447*5a6e8488SAndroid Build Coastguard Worker 	// Try BCryptGenRandom first.
448*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_fill(rng, bc_rand_winrand, NULL);
449*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
450*5a6e8488SAndroid Build Coastguard Worker 
451*5a6e8488SAndroid Build Coastguard Worker 	// Fallback to rand() until the thing is seeded.
452*5a6e8488SAndroid Build Coastguard Worker 	while (BC_ERR(BC_RAND_ZERO(rng)))
453*5a6e8488SAndroid Build Coastguard Worker 	{
454*5a6e8488SAndroid Build Coastguard Worker 		bc_rand_fill(rng, bc_rand_rand, NULL);
455*5a6e8488SAndroid Build Coastguard Worker 	}
456*5a6e8488SAndroid Build Coastguard Worker 
457*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_UNLOCK;
458*5a6e8488SAndroid Build Coastguard Worker }
459*5a6e8488SAndroid Build Coastguard Worker 
460*5a6e8488SAndroid Build Coastguard Worker /**
461*5a6e8488SAndroid Build Coastguard Worker  * Propagates a change to the PRNG to all PRNG's in the stack that should have
462*5a6e8488SAndroid Build Coastguard Worker  * it. The ones that should have it are laid out in the manpages.
463*5a6e8488SAndroid Build Coastguard Worker  * @param r    The PRNG stack.
464*5a6e8488SAndroid Build Coastguard Worker  * @param rng  The PRNG that will be used to seed the others.
465*5a6e8488SAndroid Build Coastguard Worker  */
466*5a6e8488SAndroid Build Coastguard Worker static void
bc_rand_propagate(BcRNG * r,BcRNGData * rng)467*5a6e8488SAndroid Build Coastguard Worker bc_rand_propagate(BcRNG* r, BcRNGData* rng)
468*5a6e8488SAndroid Build Coastguard Worker {
469*5a6e8488SAndroid Build Coastguard Worker 	// Just return if there are none to do.
470*5a6e8488SAndroid Build Coastguard Worker 	if (r->v.len <= 1) return;
471*5a6e8488SAndroid Build Coastguard Worker 
472*5a6e8488SAndroid Build Coastguard Worker 	// If the PRNG has not been modified...
473*5a6e8488SAndroid Build Coastguard Worker 	if (BC_RAND_NOTMODIFIED(rng))
474*5a6e8488SAndroid Build Coastguard Worker 	{
475*5a6e8488SAndroid Build Coastguard Worker 		size_t i;
476*5a6e8488SAndroid Build Coastguard Worker 		bool go = true;
477*5a6e8488SAndroid Build Coastguard Worker 
478*5a6e8488SAndroid Build Coastguard Worker 		// Find the first PRNG that is modified and seed the others.
479*5a6e8488SAndroid Build Coastguard Worker 		for (i = 1; go && i < r->v.len; ++i)
480*5a6e8488SAndroid Build Coastguard Worker 		{
481*5a6e8488SAndroid Build Coastguard Worker 			BcRNGData* rng2 = bc_vec_item_rev(&r->v, i);
482*5a6e8488SAndroid Build Coastguard Worker 
483*5a6e8488SAndroid Build Coastguard Worker 			go = BC_RAND_NOTMODIFIED(rng2);
484*5a6e8488SAndroid Build Coastguard Worker 
485*5a6e8488SAndroid Build Coastguard Worker 			bc_rand_copy(rng2, rng);
486*5a6e8488SAndroid Build Coastguard Worker 		}
487*5a6e8488SAndroid Build Coastguard Worker 
488*5a6e8488SAndroid Build Coastguard Worker 		// Seed everything else.
489*5a6e8488SAndroid Build Coastguard Worker 		bc_rand_seedZeroes(r, rng, i);
490*5a6e8488SAndroid Build Coastguard Worker 	}
491*5a6e8488SAndroid Build Coastguard Worker 	// Seed everything.
492*5a6e8488SAndroid Build Coastguard Worker 	else bc_rand_seedZeroes(r, rng, 1);
493*5a6e8488SAndroid Build Coastguard Worker }
494*5a6e8488SAndroid Build Coastguard Worker 
495*5a6e8488SAndroid Build Coastguard Worker BcRand
bc_rand_int(BcRNG * r)496*5a6e8488SAndroid Build Coastguard Worker bc_rand_int(BcRNG* r)
497*5a6e8488SAndroid Build Coastguard Worker {
498*5a6e8488SAndroid Build Coastguard Worker 	// Get the actual PRNG.
499*5a6e8488SAndroid Build Coastguard Worker 	BcRNGData* rng = bc_vec_top(&r->v);
500*5a6e8488SAndroid Build Coastguard Worker 	BcRand res;
501*5a6e8488SAndroid Build Coastguard Worker 
502*5a6e8488SAndroid Build Coastguard Worker 	// Make sure the PRNG is seeded.
503*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_srand(rng);
504*5a6e8488SAndroid Build Coastguard Worker 
505*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_LOCK;
506*5a6e8488SAndroid Build Coastguard Worker 
507*5a6e8488SAndroid Build Coastguard Worker 	// This is the important part of the PRNG. This is the stuff from PCG.
508*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_step(rng);
509*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_propagate(r, rng);
510*5a6e8488SAndroid Build Coastguard Worker 	res = bc_rand_output(rng);
511*5a6e8488SAndroid Build Coastguard Worker 
512*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_UNLOCK;
513*5a6e8488SAndroid Build Coastguard Worker 
514*5a6e8488SAndroid Build Coastguard Worker 	return res;
515*5a6e8488SAndroid Build Coastguard Worker }
516*5a6e8488SAndroid Build Coastguard Worker 
517*5a6e8488SAndroid Build Coastguard Worker BcRand
bc_rand_bounded(BcRNG * r,BcRand bound)518*5a6e8488SAndroid Build Coastguard Worker bc_rand_bounded(BcRNG* r, BcRand bound)
519*5a6e8488SAndroid Build Coastguard Worker {
520*5a6e8488SAndroid Build Coastguard Worker 	BcRand rand;
521*5a6e8488SAndroid Build Coastguard Worker 	BcRand threshold;
522*5a6e8488SAndroid Build Coastguard Worker 
523*5a6e8488SAndroid Build Coastguard Worker 	// Calculate the threshold below which we have to try again.
524*5a6e8488SAndroid Build Coastguard Worker 	threshold = (0 - bound) % bound;
525*5a6e8488SAndroid Build Coastguard Worker 
526*5a6e8488SAndroid Build Coastguard Worker 	do
527*5a6e8488SAndroid Build Coastguard Worker 	{
528*5a6e8488SAndroid Build Coastguard Worker 		rand = bc_rand_int(r);
529*5a6e8488SAndroid Build Coastguard Worker 	}
530*5a6e8488SAndroid Build Coastguard Worker 	while (rand < threshold);
531*5a6e8488SAndroid Build Coastguard Worker 
532*5a6e8488SAndroid Build Coastguard Worker 	return rand % bound;
533*5a6e8488SAndroid Build Coastguard Worker }
534*5a6e8488SAndroid Build Coastguard Worker 
535*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_seed(BcRNG * r,ulong state1,ulong state2,ulong inc1,ulong inc2)536*5a6e8488SAndroid Build Coastguard Worker bc_rand_seed(BcRNG* r, ulong state1, ulong state2, ulong inc1, ulong inc2)
537*5a6e8488SAndroid Build Coastguard Worker {
538*5a6e8488SAndroid Build Coastguard Worker 	// Get the actual PRNG.
539*5a6e8488SAndroid Build Coastguard Worker 	BcRNGData* rng = bc_vec_top(&r->v);
540*5a6e8488SAndroid Build Coastguard Worker 
541*5a6e8488SAndroid Build Coastguard Worker 	// Seed and set up the PRNG's increment.
542*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_seedState(&rng->inc, inc1, inc2);
543*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_setupInc(rng);
544*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_setModified(rng);
545*5a6e8488SAndroid Build Coastguard Worker 
546*5a6e8488SAndroid Build Coastguard Worker 	// If the state is 0, use the increment as the state. Otherwise, seed it
547*5a6e8488SAndroid Build Coastguard Worker 	// with the state.
548*5a6e8488SAndroid Build Coastguard Worker 	if (!state1 && !state2)
549*5a6e8488SAndroid Build Coastguard Worker 	{
550*5a6e8488SAndroid Build Coastguard Worker 		// NOLINTNEXTLINE
551*5a6e8488SAndroid Build Coastguard Worker 		memcpy(&rng->state, &rng->inc, sizeof(BcRandState));
552*5a6e8488SAndroid Build Coastguard Worker 		bc_rand_step(rng);
553*5a6e8488SAndroid Build Coastguard Worker 	}
554*5a6e8488SAndroid Build Coastguard Worker 	else bc_rand_seedState(&rng->state, state1, state2);
555*5a6e8488SAndroid Build Coastguard Worker 
556*5a6e8488SAndroid Build Coastguard Worker 	// Propagate the change to PRNG's that need it.
557*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_propagate(r, rng);
558*5a6e8488SAndroid Build Coastguard Worker }
559*5a6e8488SAndroid Build Coastguard Worker 
560*5a6e8488SAndroid Build Coastguard Worker /**
561*5a6e8488SAndroid Build Coastguard Worker  * Returns the increment in the PRNG *without* the odd bit and also with being
562*5a6e8488SAndroid Build Coastguard Worker  * shifted one bit down.
563*5a6e8488SAndroid Build Coastguard Worker  * @param r  The PRNG.
564*5a6e8488SAndroid Build Coastguard Worker  * @return   The increment without the odd bit and with being shifted one bit
565*5a6e8488SAndroid Build Coastguard Worker  *           down.
566*5a6e8488SAndroid Build Coastguard Worker  */
567*5a6e8488SAndroid Build Coastguard Worker static BcRandState
bc_rand_getInc(BcRNGData * r)568*5a6e8488SAndroid Build Coastguard Worker bc_rand_getInc(BcRNGData* r)
569*5a6e8488SAndroid Build Coastguard Worker {
570*5a6e8488SAndroid Build Coastguard Worker 	BcRandState res;
571*5a6e8488SAndroid Build Coastguard Worker 
572*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_BUILTIN
573*5a6e8488SAndroid Build Coastguard Worker 	res = r->inc >> 1;
574*5a6e8488SAndroid Build Coastguard Worker #else // BC_RAND_BUILTIN
575*5a6e8488SAndroid Build Coastguard Worker 	res = r->inc;
576*5a6e8488SAndroid Build Coastguard Worker 	res.lo >>= 1;
577*5a6e8488SAndroid Build Coastguard Worker 	res.lo |= (res.hi & 1) << (BC_LONG_BIT - 1);
578*5a6e8488SAndroid Build Coastguard Worker 	res.hi >>= 1;
579*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_BUILTIN
580*5a6e8488SAndroid Build Coastguard Worker 
581*5a6e8488SAndroid Build Coastguard Worker 	return res;
582*5a6e8488SAndroid Build Coastguard Worker }
583*5a6e8488SAndroid Build Coastguard Worker 
584*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_getRands(BcRNG * r,BcRand * s1,BcRand * s2,BcRand * i1,BcRand * i2)585*5a6e8488SAndroid Build Coastguard Worker bc_rand_getRands(BcRNG* r, BcRand* s1, BcRand* s2, BcRand* i1, BcRand* i2)
586*5a6e8488SAndroid Build Coastguard Worker {
587*5a6e8488SAndroid Build Coastguard Worker 	BcRandState inc;
588*5a6e8488SAndroid Build Coastguard Worker 	BcRNGData* rng = bc_vec_top(&r->v);
589*5a6e8488SAndroid Build Coastguard Worker 
590*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_srand(rng);
591*5a6e8488SAndroid Build Coastguard Worker 
592*5a6e8488SAndroid Build Coastguard Worker 	// Get the increment.
593*5a6e8488SAndroid Build Coastguard Worker 	inc = bc_rand_getInc(rng);
594*5a6e8488SAndroid Build Coastguard Worker 
595*5a6e8488SAndroid Build Coastguard Worker 	// Chop the state.
596*5a6e8488SAndroid Build Coastguard Worker 	*s1 = BC_RAND_TRUNC(rng->state);
597*5a6e8488SAndroid Build Coastguard Worker 	*s2 = BC_RAND_CHOP(rng->state);
598*5a6e8488SAndroid Build Coastguard Worker 
599*5a6e8488SAndroid Build Coastguard Worker 	// Chop the increment.
600*5a6e8488SAndroid Build Coastguard Worker 	*i1 = BC_RAND_TRUNC(inc);
601*5a6e8488SAndroid Build Coastguard Worker 	*i2 = BC_RAND_CHOP(inc);
602*5a6e8488SAndroid Build Coastguard Worker }
603*5a6e8488SAndroid Build Coastguard Worker 
604*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_push(BcRNG * r)605*5a6e8488SAndroid Build Coastguard Worker bc_rand_push(BcRNG* r)
606*5a6e8488SAndroid Build Coastguard Worker {
607*5a6e8488SAndroid Build Coastguard Worker 	BcRNGData* rng = bc_vec_pushEmpty(&r->v);
608*5a6e8488SAndroid Build Coastguard Worker 
609*5a6e8488SAndroid Build Coastguard Worker 	// Make sure the PRNG is properly zeroed because that marks it as needing to
610*5a6e8488SAndroid Build Coastguard Worker 	// be seeded.
611*5a6e8488SAndroid Build Coastguard Worker 	// NOLINTNEXTLINE
612*5a6e8488SAndroid Build Coastguard Worker 	memset(rng, 0, sizeof(BcRNGData));
613*5a6e8488SAndroid Build Coastguard Worker 
614*5a6e8488SAndroid Build Coastguard Worker 	// If there is another item, copy it too.
615*5a6e8488SAndroid Build Coastguard Worker 	if (r->v.len > 1) bc_rand_copy(rng, bc_vec_item_rev(&r->v, 1));
616*5a6e8488SAndroid Build Coastguard Worker }
617*5a6e8488SAndroid Build Coastguard Worker 
618*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_pop(BcRNG * r,bool reset)619*5a6e8488SAndroid Build Coastguard Worker bc_rand_pop(BcRNG* r, bool reset)
620*5a6e8488SAndroid Build Coastguard Worker {
621*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_npop(&r->v, reset ? r->v.len - 1 : 1);
622*5a6e8488SAndroid Build Coastguard Worker }
623*5a6e8488SAndroid Build Coastguard Worker 
624*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_init(BcRNG * r)625*5a6e8488SAndroid Build Coastguard Worker bc_rand_init(BcRNG* r)
626*5a6e8488SAndroid Build Coastguard Worker {
627*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_ASSERT_LOCKED;
628*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_init(&r->v, sizeof(BcRNGData), BC_DTOR_NONE);
629*5a6e8488SAndroid Build Coastguard Worker 	bc_rand_push(r);
630*5a6e8488SAndroid Build Coastguard Worker }
631*5a6e8488SAndroid Build Coastguard Worker 
632*5a6e8488SAndroid Build Coastguard Worker #if BC_RAND_USE_FREE
633*5a6e8488SAndroid Build Coastguard Worker void
bc_rand_free(BcRNG * r)634*5a6e8488SAndroid Build Coastguard Worker bc_rand_free(BcRNG* r)
635*5a6e8488SAndroid Build Coastguard Worker {
636*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_ASSERT_LOCKED;
637*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_free(&r->v);
638*5a6e8488SAndroid Build Coastguard Worker }
639*5a6e8488SAndroid Build Coastguard Worker #endif // BC_RAND_USE_FREE
640*5a6e8488SAndroid Build Coastguard Worker 
641*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
642