xref: /freebsd/contrib/bc/include/rand.h (revision 44d4804d1945435745518cd09eb8ae6ab22ecef4)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
4252884aeSStefan Eßer  * Parts of this code are adapted from the following:
5252884aeSStefan Eßer  *
6252884aeSStefan Eßer  * PCG, A Family of Better Random Number Generators.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * You can find the original source code at:
9252884aeSStefan Eßer  *   https://github.com/imneme/pcg-c
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * -----------------------------------------------------------------------------
12252884aeSStefan Eßer  *
1310328f8bSStefan Eßer  * This code is under the following license:
14252884aeSStefan Eßer  *
15252884aeSStefan Eßer  * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
1610328f8bSStefan Eßer  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * Permission is hereby granted, free of charge, to any person obtaining a copy
19252884aeSStefan Eßer  * of this software and associated documentation files (the "Software"), to deal
20252884aeSStefan Eßer  * in the Software without restriction, including without limitation the rights
21252884aeSStefan Eßer  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22252884aeSStefan Eßer  * copies of the Software, and to permit persons to whom the Software is
23252884aeSStefan Eßer  * furnished to do so, subject to the following conditions:
24252884aeSStefan Eßer  *
25252884aeSStefan Eßer  * The above copyright notice and this permission notice shall be included in
26252884aeSStefan Eßer  * all copies or substantial portions of the Software.
27252884aeSStefan Eßer  *
28252884aeSStefan Eßer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29252884aeSStefan Eßer  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30252884aeSStefan Eßer  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31252884aeSStefan Eßer  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32252884aeSStefan Eßer  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33252884aeSStefan Eßer  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34252884aeSStefan Eßer  * SOFTWARE.
35252884aeSStefan Eßer  *
36252884aeSStefan Eßer  * *****************************************************************************
37252884aeSStefan Eßer  *
38252884aeSStefan Eßer  * Definitions for the RNG.
39252884aeSStefan Eßer  *
40252884aeSStefan Eßer  */
41252884aeSStefan Eßer 
42252884aeSStefan Eßer #ifndef BC_RAND_H
43252884aeSStefan Eßer #define BC_RAND_H
44252884aeSStefan Eßer 
45252884aeSStefan Eßer #include <stdint.h>
46252884aeSStefan Eßer #include <inttypes.h>
47252884aeSStefan Eßer 
48252884aeSStefan Eßer #include <vector.h>
49252884aeSStefan Eßer #include <num.h>
50252884aeSStefan Eßer 
513aa99676SStefan Eßer #if BC_ENABLE_EXTRA_MATH
523aa99676SStefan Eßer 
53*44d4804dSStefan Eßer #if BC_ENABLE_LIBRARY
54*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (1)
55*44d4804dSStefan Eßer #else // BC_ENABLE_LIBRARY
56*44d4804dSStefan Eßer #ifndef NDEBUG
57*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (1)
58*44d4804dSStefan Eßer #else // NDEBUG
59*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (0)
60*44d4804dSStefan Eßer #endif // NDEBUG
61*44d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY
623aa99676SStefan Eßer 
63*44d4804dSStefan Eßer /**
64*44d4804dSStefan Eßer  * A function to return a random unsigned long.
65*44d4804dSStefan Eßer  * @param ptr  A void ptr to some data that will help generate the random ulong.
66*44d4804dSStefan Eßer  * @return     The random ulong.
67*44d4804dSStefan Eßer  */
68*44d4804dSStefan Eßer typedef ulong (*BcRandUlong)(void *ptr);
69252884aeSStefan Eßer 
70252884aeSStefan Eßer #if BC_LONG_BIT >= 64
71252884aeSStefan Eßer 
72*44d4804dSStefan Eßer // If longs are 64 bits, we have the option of 128-bit integers on some
73*44d4804dSStefan Eßer // compilers. These two sections test that.
74252884aeSStefan Eßer #ifdef BC_RAND_BUILTIN
75252884aeSStefan Eßer #if BC_RAND_BUILTIN
76252884aeSStefan Eßer #ifndef __SIZEOF_INT128__
77252884aeSStefan Eßer #undef BC_RAND_BUILTIN
78252884aeSStefan Eßer #define BC_RAND_BUILTIN (0)
79252884aeSStefan Eßer #endif // __SIZEOF_INT128__
80252884aeSStefan Eßer #endif // BC_RAND_BUILTIN
81252884aeSStefan Eßer #endif // BC_RAND_BUILTIN
82252884aeSStefan Eßer 
83252884aeSStefan Eßer #ifndef BC_RAND_BUILTIN
84252884aeSStefan Eßer #ifdef __SIZEOF_INT128__
85252884aeSStefan Eßer #define BC_RAND_BUILTIN (1)
86252884aeSStefan Eßer #else // __SIZEOF_INT128__
87252884aeSStefan Eßer #define BC_RAND_BUILTIN (0)
88252884aeSStefan Eßer #endif // __SIZEOF_INT128__
89252884aeSStefan Eßer #endif // BC_RAND_BUILTIN
90252884aeSStefan Eßer 
91*44d4804dSStefan Eßer /// The type for random integers.
92252884aeSStefan Eßer typedef uint64_t BcRand;
93252884aeSStefan Eßer 
94*44d4804dSStefan Eßer /// A constant defined by PCG.
95252884aeSStefan Eßer #define BC_RAND_ROTC (63)
96252884aeSStefan Eßer 
97252884aeSStefan Eßer #if BC_RAND_BUILTIN
98252884aeSStefan Eßer 
99*44d4804dSStefan Eßer /// A typedef for the PCG state.
100252884aeSStefan Eßer typedef __uint128_t BcRandState;
101252884aeSStefan Eßer 
102*44d4804dSStefan Eßer /**
103*44d4804dSStefan Eßer  * Multiply two integers, worrying about overflow.
104*44d4804dSStefan Eßer  * @param a  The first integer.
105*44d4804dSStefan Eßer  * @param b  The second integer.
106*44d4804dSStefan Eßer  * @return   The product of the PCG states.
107*44d4804dSStefan Eßer  */
108252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))
109*44d4804dSStefan Eßer 
110*44d4804dSStefan Eßer /**
111*44d4804dSStefan Eßer  * Add two integers, worrying about overflow.
112*44d4804dSStefan Eßer  * @param a  The first integer.
113*44d4804dSStefan Eßer  * @param b  The second integer.
114*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
115*44d4804dSStefan Eßer  */
116252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))
117252884aeSStefan Eßer 
118*44d4804dSStefan Eßer /**
119*44d4804dSStefan Eßer  * Multiply two PCG states.
120*44d4804dSStefan Eßer  * @param a  The first PCG state.
121*44d4804dSStefan Eßer  * @param b  The second PCG state.
122*44d4804dSStefan Eßer  * @return   The product of the PCG states.
123*44d4804dSStefan Eßer  */
124252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))
125*44d4804dSStefan Eßer 
126*44d4804dSStefan Eßer /**
127*44d4804dSStefan Eßer  * Add two PCG states.
128*44d4804dSStefan Eßer  * @param a  The first PCG state.
129*44d4804dSStefan Eßer  * @param b  The second PCG state.
130*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
131*44d4804dSStefan Eßer  */
132252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))
133252884aeSStefan Eßer 
134*44d4804dSStefan Eßer /**
135*44d4804dSStefan Eßer  * Figure out if the PRNG has been modified. Since the increment of the PRNG has
136*44d4804dSStefan Eßer  * to be odd, we use the extra bit to store whether it has been modified or not.
137*44d4804dSStefan Eßer  * @param r  The PRNG.
138*44d4804dSStefan Eßer  * @return   True if the PRNG has *not* been modified, false otherwise.
139*44d4804dSStefan Eßer  */
140252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0)
141*44d4804dSStefan Eßer 
142*44d4804dSStefan Eßer /**
143*44d4804dSStefan Eßer  * Return true if the PRNG has not been seeded yet.
144*44d4804dSStefan Eßer  * @param r  The PRNG.
145*44d4804dSStefan Eßer  * @return   True if the PRNG has not been seeded yet, false otherwise.
146*44d4804dSStefan Eßer  */
147252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state)
148252884aeSStefan Eßer 
149*44d4804dSStefan Eßer /**
150*44d4804dSStefan Eßer  * Returns a constant built from @a h and @a l.
151*44d4804dSStefan Eßer  * @param h  The high 64 bits.
152*44d4804dSStefan Eßer  * @param l  The low 64 bits.
153*44d4804dSStefan Eßer  * @return   The constant built from @a h and @a l.
154*44d4804dSStefan Eßer  */
155252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l))
156252884aeSStefan Eßer 
157*44d4804dSStefan Eßer /**
158*44d4804dSStefan Eßer  * Truncates a PCG state to the number of bits in a random integer.
159*44d4804dSStefan Eßer  * @param s  The state to truncate.
160*44d4804dSStefan Eßer  * @return   The truncated state.
161*44d4804dSStefan Eßer  */
162252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint64_t) (s))
163*44d4804dSStefan Eßer 
164*44d4804dSStefan Eßer /**
165*44d4804dSStefan Eßer  * Chops a PCG state in half and returns the top bits.
166*44d4804dSStefan Eßer  * @param s  The state to chop.
167*44d4804dSStefan Eßer  * @return   The chopped state's top bits.
168*44d4804dSStefan Eßer  */
169252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL))
170*44d4804dSStefan Eßer 
171*44d4804dSStefan Eßer /**
172*44d4804dSStefan Eßer  * Rotates a PCG state.
173*44d4804dSStefan Eßer  * @param s  The state to rotate.
174*44d4804dSStefan Eßer  * @return   The rotated state.
175*44d4804dSStefan Eßer  */
176252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL))
177252884aeSStefan Eßer 
178252884aeSStefan Eßer #else // BC_RAND_BUILTIN
179252884aeSStefan Eßer 
180*44d4804dSStefan Eßer /// A typedef for the PCG state.
181252884aeSStefan Eßer typedef struct BcRandState {
182252884aeSStefan Eßer 
183*44d4804dSStefan Eßer 	/// The low bits.
184252884aeSStefan Eßer 	uint_fast64_t lo;
185*44d4804dSStefan Eßer 
186*44d4804dSStefan Eßer 	/// The high bits.
187252884aeSStefan Eßer 	uint_fast64_t hi;
188252884aeSStefan Eßer 
189252884aeSStefan Eßer } BcRandState;
190252884aeSStefan Eßer 
191*44d4804dSStefan Eßer /**
192*44d4804dSStefan Eßer  * Multiply two integers, worrying about overflow.
193*44d4804dSStefan Eßer  * @param a  The first integer.
194*44d4804dSStefan Eßer  * @param b  The second integer.
195*44d4804dSStefan Eßer  * @return   The product of the PCG states.
196*44d4804dSStefan Eßer  */
197252884aeSStefan Eßer #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b)))
198*44d4804dSStefan Eßer 
199*44d4804dSStefan Eßer /**
200*44d4804dSStefan Eßer  * Add two integers, worrying about overflow.
201*44d4804dSStefan Eßer  * @param a  The first integer.
202*44d4804dSStefan Eßer  * @param b  The second integer.
203*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
204*44d4804dSStefan Eßer  */
205252884aeSStefan Eßer #define bc_rand_add(a, b) (bc_rand_addition((a), (b)))
206252884aeSStefan Eßer 
207*44d4804dSStefan Eßer /**
208*44d4804dSStefan Eßer  * Multiply two PCG states.
209*44d4804dSStefan Eßer  * @param a  The first PCG state.
210*44d4804dSStefan Eßer  * @param b  The second PCG state.
211*44d4804dSStefan Eßer  * @return   The product of the PCG states.
212*44d4804dSStefan Eßer  */
213252884aeSStefan Eßer #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b)))
214*44d4804dSStefan Eßer 
215*44d4804dSStefan Eßer /**
216*44d4804dSStefan Eßer  * Add two PCG states.
217*44d4804dSStefan Eßer  * @param a  The first PCG state.
218*44d4804dSStefan Eßer  * @param b  The second PCG state.
219*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
220*44d4804dSStefan Eßer  */
221252884aeSStefan Eßer #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b)))
222252884aeSStefan Eßer 
223*44d4804dSStefan Eßer /**
224*44d4804dSStefan Eßer  * Figure out if the PRNG has been modified. Since the increment of the PRNG has
225*44d4804dSStefan Eßer  * to be odd, we use the extra bit to store whether it has been modified or not.
226*44d4804dSStefan Eßer  * @param r  The PRNG.
227*44d4804dSStefan Eßer  * @return   True if the PRNG has *not* been modified, false otherwise.
228*44d4804dSStefan Eßer  */
229252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0)
230*44d4804dSStefan Eßer 
231*44d4804dSStefan Eßer /**
232*44d4804dSStefan Eßer  * Return true if the PRNG has not been seeded yet.
233*44d4804dSStefan Eßer  * @param r  The PRNG.
234*44d4804dSStefan Eßer  * @return   True if the PRNG has not been seeded yet, false otherwise.
235*44d4804dSStefan Eßer  */
236252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi)
237252884aeSStefan Eßer 
238*44d4804dSStefan Eßer /**
239*44d4804dSStefan Eßer  * Returns a constant built from @a h and @a l.
240*44d4804dSStefan Eßer  * @param h  The high 64 bits.
241*44d4804dSStefan Eßer  * @param l  The low 64 bits.
242*44d4804dSStefan Eßer  * @return   The constant built from @a h and @a l.
243*44d4804dSStefan Eßer  */
244252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) }
245252884aeSStefan Eßer 
246*44d4804dSStefan Eßer /**
247*44d4804dSStefan Eßer  * Truncates a PCG state to the number of bits in a random integer.
248*44d4804dSStefan Eßer  * @param s  The state to truncate.
249*44d4804dSStefan Eßer  * @return   The truncated state.
250*44d4804dSStefan Eßer  */
251252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((s).lo)
252*44d4804dSStefan Eßer 
253*44d4804dSStefan Eßer /**
254*44d4804dSStefan Eßer  * Chops a PCG state in half and returns the top bits.
255*44d4804dSStefan Eßer  * @param s  The state to chop.
256*44d4804dSStefan Eßer  * @return   The chopped state's top bits.
257*44d4804dSStefan Eßer  */
258252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((s).hi)
259*44d4804dSStefan Eßer 
260*44d4804dSStefan Eßer /**
261*44d4804dSStefan Eßer  * Returns the rotate amount for a PCG state.
262*44d4804dSStefan Eßer  * @param s  The state to rotate.
263*44d4804dSStefan Eßer  * @return   The semi-rotated state.
264*44d4804dSStefan Eßer  */
265252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL))
266252884aeSStefan Eßer 
267*44d4804dSStefan Eßer /// A 64-bit integer with the bottom 32 bits set.
268252884aeSStefan Eßer #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL))
269*44d4804dSStefan Eßer 
270*44d4804dSStefan Eßer /**
271*44d4804dSStefan Eßer  * Returns the 32-bit truncated value of @a n.
272*44d4804dSStefan Eßer  * @param n  The integer to truncate.
273*44d4804dSStefan Eßer  * @return   The bottom 32 bits of @a n.
274*44d4804dSStefan Eßer  */
275252884aeSStefan Eßer #define BC_RAND_TRUNC32(n) ((n) & BC_RAND_BOTTOM32)
276*44d4804dSStefan Eßer 
277*44d4804dSStefan Eßer /**
278*44d4804dSStefan Eßer  * Returns the second 32 bits of @a n.
279*44d4804dSStefan Eßer  * @param n  The integer to truncate.
280*44d4804dSStefan Eßer  * @return   The second 32 bits of @a n.
281*44d4804dSStefan Eßer  */
282252884aeSStefan Eßer #define BC_RAND_CHOP32(n) ((n) >> 32)
283252884aeSStefan Eßer 
284252884aeSStefan Eßer #endif // BC_RAND_BUILTIN
285252884aeSStefan Eßer 
286*44d4804dSStefan Eßer /// A constant defined by PCG.
287252884aeSStefan Eßer #define BC_RAND_MULTIPLIER \
288252884aeSStefan Eßer 	BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL)
289252884aeSStefan Eßer 
290*44d4804dSStefan Eßer /**
291*44d4804dSStefan Eßer  * Returns the result of a PCG fold.
292*44d4804dSStefan Eßer  * @param s  The state to fold.
293*44d4804dSStefan Eßer  * @return   The folded state.
294*44d4804dSStefan Eßer  */
295252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s)))
296252884aeSStefan Eßer 
297252884aeSStefan Eßer #else // BC_LONG_BIT >= 64
298252884aeSStefan Eßer 
299*44d4804dSStefan Eßer // If we are using 32-bit longs, we need to set these so.
300252884aeSStefan Eßer #undef BC_RAND_BUILTIN
301252884aeSStefan Eßer #define BC_RAND_BUILTIN (1)
302252884aeSStefan Eßer 
303*44d4804dSStefan Eßer /// The type for random integers.
304252884aeSStefan Eßer typedef uint32_t BcRand;
305252884aeSStefan Eßer 
306*44d4804dSStefan Eßer /// A constant defined by PCG.
307252884aeSStefan Eßer #define BC_RAND_ROTC (31)
308252884aeSStefan Eßer 
309*44d4804dSStefan Eßer /// A typedef for the PCG state.
310252884aeSStefan Eßer typedef uint_fast64_t BcRandState;
311252884aeSStefan Eßer 
312*44d4804dSStefan Eßer /**
313*44d4804dSStefan Eßer  * Multiply two integers, worrying about overflow.
314*44d4804dSStefan Eßer  * @param a  The first integer.
315*44d4804dSStefan Eßer  * @param b  The second integer.
316*44d4804dSStefan Eßer  * @return   The product of the PCG states.
317*44d4804dSStefan Eßer  */
318252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))
319*44d4804dSStefan Eßer 
320*44d4804dSStefan Eßer /**
321*44d4804dSStefan Eßer  * Add two integers, worrying about overflow.
322*44d4804dSStefan Eßer  * @param a  The first integer.
323*44d4804dSStefan Eßer  * @param b  The second integer.
324*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
325*44d4804dSStefan Eßer  */
326252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))
327252884aeSStefan Eßer 
328*44d4804dSStefan Eßer /**
329*44d4804dSStefan Eßer  * Multiply two PCG states.
330*44d4804dSStefan Eßer  * @param a  The first PCG state.
331*44d4804dSStefan Eßer  * @param b  The second PCG state.
332*44d4804dSStefan Eßer  * @return   The product of the PCG states.
333*44d4804dSStefan Eßer  */
334252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))
335*44d4804dSStefan Eßer 
336*44d4804dSStefan Eßer /**
337*44d4804dSStefan Eßer  * Add two PCG states.
338*44d4804dSStefan Eßer  * @param a  The first PCG state.
339*44d4804dSStefan Eßer  * @param b  The second PCG state.
340*44d4804dSStefan Eßer  * @return   The sum of the PCG states.
341*44d4804dSStefan Eßer  */
342252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))
343252884aeSStefan Eßer 
344*44d4804dSStefan Eßer /**
345*44d4804dSStefan Eßer  * Figure out if the PRNG has been modified. Since the increment of the PRNG has
346*44d4804dSStefan Eßer  * to be odd, we use the extra bit to store whether it has been modified or not.
347*44d4804dSStefan Eßer  * @param r  The PRNG.
348*44d4804dSStefan Eßer  * @return   True if the PRNG has *not* been modified, false otherwise.
349*44d4804dSStefan Eßer  */
350252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0)
351*44d4804dSStefan Eßer 
352*44d4804dSStefan Eßer /**
353*44d4804dSStefan Eßer  * Return true if the PRNG has not been seeded yet.
354*44d4804dSStefan Eßer  * @param r  The PRNG.
355*44d4804dSStefan Eßer  * @return   True if the PRNG has not been seeded yet, false otherwise.
356*44d4804dSStefan Eßer  */
357252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state)
358252884aeSStefan Eßer 
359*44d4804dSStefan Eßer /**
360*44d4804dSStefan Eßer  * Returns a constant built from a number.
361*44d4804dSStefan Eßer  * @param n  The number.
362*44d4804dSStefan Eßer  * @return   The constant built from @a n.
363*44d4804dSStefan Eßer  */
364*44d4804dSStefan Eßer #define BC_RAND_CONSTANT(n) UINT64_C(n)
365*44d4804dSStefan Eßer 
366*44d4804dSStefan Eßer /// A constant defined by PCG.
367252884aeSStefan Eßer #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005)
368252884aeSStefan Eßer 
369*44d4804dSStefan Eßer /**
370*44d4804dSStefan Eßer  * Truncates a PCG state to the number of bits in a random integer.
371*44d4804dSStefan Eßer  * @param s  The state to truncate.
372*44d4804dSStefan Eßer  * @return   The truncated state.
373*44d4804dSStefan Eßer  */
374252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint32_t) (s))
375*44d4804dSStefan Eßer 
376*44d4804dSStefan Eßer /**
377*44d4804dSStefan Eßer  * Chops a PCG state in half and returns the top bits.
378*44d4804dSStefan Eßer  * @param s  The state to chop.
379*44d4804dSStefan Eßer  * @return   The chopped state's top bits.
380*44d4804dSStefan Eßer  */
381252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL))
382*44d4804dSStefan Eßer 
383*44d4804dSStefan Eßer /**
384*44d4804dSStefan Eßer  * Returns the rotate amount for a PCG state.
385*44d4804dSStefan Eßer  * @param s  The state to rotate.
386*44d4804dSStefan Eßer  * @return   The semi-rotated state.
387*44d4804dSStefan Eßer  */
388252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL))
389252884aeSStefan Eßer 
390*44d4804dSStefan Eßer /**
391*44d4804dSStefan Eßer  * Returns the result of a PCG fold.
392*44d4804dSStefan Eßer  * @param s  The state to fold.
393*44d4804dSStefan Eßer  * @return   The folded state.
394*44d4804dSStefan Eßer  */
395252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U))
396252884aeSStefan Eßer 
397252884aeSStefan Eßer #endif // BC_LONG_BIT >= 64
398252884aeSStefan Eßer 
399*44d4804dSStefan Eßer /**
400*44d4804dSStefan Eßer  * Rotates @a v by @a r bits.
401*44d4804dSStefan Eßer  * @param v  The value to rotate.
402*44d4804dSStefan Eßer  * @param r  The amount to rotate by.
403*44d4804dSStefan Eßer  * @return   The rotated value.
404*44d4804dSStefan Eßer  */
405252884aeSStefan Eßer #define BC_RAND_ROT(v, r) \
406252884aeSStefan Eßer 	((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC))))
407252884aeSStefan Eßer 
408*44d4804dSStefan Eßer /// The number of bits in a random integer.
409252884aeSStefan Eßer #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT)
410*44d4804dSStefan Eßer 
411*44d4804dSStefan Eßer /// The number of bits in a PCG state.
412252884aeSStefan Eßer #define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT)
413252884aeSStefan Eßer 
414*44d4804dSStefan Eßer /// The size of a BcNum with the max random integer. This isn't exact; it's
415*44d4804dSStefan Eßer /// actually rather crude. But it's always enough.
416252884aeSStefan Eßer #define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2)
417252884aeSStefan Eßer 
418*44d4804dSStefan Eßer /// The mask for how many bits bc_rand_srand() can set per iteration.
419252884aeSStefan Eßer #define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1)
420252884aeSStefan Eßer 
421*44d4804dSStefan Eßer /// The actual RNG data. These are the actual PRNG's.
422252884aeSStefan Eßer typedef struct BcRNGData {
423252884aeSStefan Eßer 
424*44d4804dSStefan Eßer 	/// The state.
425252884aeSStefan Eßer 	BcRandState state;
426*44d4804dSStefan Eßer 
427*44d4804dSStefan Eßer 	/// The increment and the modified bit.
428252884aeSStefan Eßer 	BcRandState inc;
429252884aeSStefan Eßer 
430252884aeSStefan Eßer } BcRNGData;
431252884aeSStefan Eßer 
432*44d4804dSStefan Eßer /// The public PRNG. This is just a stack of PRNG's to maintain the globals
433*44d4804dSStefan Eßer /// stack illusion.
434252884aeSStefan Eßer typedef struct BcRNG {
435252884aeSStefan Eßer 
436*44d4804dSStefan Eßer 	/// The stack of PRNG's.
437252884aeSStefan Eßer 	BcVec v;
438252884aeSStefan Eßer 
439252884aeSStefan Eßer } BcRNG;
440252884aeSStefan Eßer 
441*44d4804dSStefan Eßer /**
442*44d4804dSStefan Eßer  * Initializes a BcRNG.
443*44d4804dSStefan Eßer  * @param r  The BcRNG to initialize.
444*44d4804dSStefan Eßer  */
445252884aeSStefan Eßer void bc_rand_init(BcRNG *r);
446252884aeSStefan Eßer 
447*44d4804dSStefan Eßer #if BC_RAND_USE_FREE
448*44d4804dSStefan Eßer 
449*44d4804dSStefan Eßer /**
450*44d4804dSStefan Eßer  * Frees a BcRNG. This is only in debug builds because it would only be freed on
451*44d4804dSStefan Eßer  * exit.
452*44d4804dSStefan Eßer  * @param r  The BcRNG to free.
453*44d4804dSStefan Eßer  */
454*44d4804dSStefan Eßer void bc_rand_free(BcRNG *r);
455*44d4804dSStefan Eßer 
456*44d4804dSStefan Eßer #endif // BC_RAND_USE_FREE
457*44d4804dSStefan Eßer 
458*44d4804dSStefan Eßer /**
459*44d4804dSStefan Eßer  * Returns a random integer from the PRNG.
460*44d4804dSStefan Eßer  * @param r  The PRNG.
461*44d4804dSStefan Eßer  * @return   A random integer.
462*44d4804dSStefan Eßer  */
463252884aeSStefan Eßer BcRand bc_rand_int(BcRNG *r);
464*44d4804dSStefan Eßer 
465*44d4804dSStefan Eßer /**
466*44d4804dSStefan Eßer  * Returns a random integer from the PRNG bounded by @a bound. Bias is
467*44d4804dSStefan Eßer  * eliminated.
468*44d4804dSStefan Eßer  * @param r      The PRNG.
469*44d4804dSStefan Eßer  * @param bound  The bound for the random integer.
470*44d4804dSStefan Eßer  * @return       A bounded random integer.
471*44d4804dSStefan Eßer  */
472252884aeSStefan Eßer BcRand bc_rand_bounded(BcRNG *r, BcRand bound);
473*44d4804dSStefan Eßer 
474*44d4804dSStefan Eßer /**
475*44d4804dSStefan Eßer  * Seed the PRNG with the state in two parts and the increment in two parts.
476*44d4804dSStefan Eßer  * @param r       The PRNG.
477*44d4804dSStefan Eßer  * @param state1  The first part of the state.
478*44d4804dSStefan Eßer  * @param state2  The second part of the state.
479*44d4804dSStefan Eßer  * @param inc1    The first part of the increment.
480*44d4804dSStefan Eßer  * @param inc2    The second part of the increment.
481*44d4804dSStefan Eßer  */
482252884aeSStefan Eßer void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2);
483*44d4804dSStefan Eßer 
484*44d4804dSStefan Eßer /**
485*44d4804dSStefan Eßer  * Pushes a new PRNG onto the PRNG stack.
486*44d4804dSStefan Eßer  * @param r  The PRNG.
487*44d4804dSStefan Eßer  */
488252884aeSStefan Eßer void bc_rand_push(BcRNG *r);
489*44d4804dSStefan Eßer 
490*44d4804dSStefan Eßer /**
491*44d4804dSStefan Eßer  * Pops one or all but one items off of the PRNG stack.
492*44d4804dSStefan Eßer  * @param r      The PRNG.
493*44d4804dSStefan Eßer  * @param reset  True if all but one PRNG should be popped off the stack, false
494*44d4804dSStefan Eßer  *               if only one should be popped.
495*44d4804dSStefan Eßer  */
496252884aeSStefan Eßer void bc_rand_pop(BcRNG *r, bool reset);
497*44d4804dSStefan Eßer 
498*44d4804dSStefan Eßer /**
499*44d4804dSStefan Eßer  * Returns, via pointers, the state of the PRNG in pieces.
500*44d4804dSStefan Eßer  * @param r   The PRNG.
501*44d4804dSStefan Eßer  * @param s1  The return value for the first part of the state.
502*44d4804dSStefan Eßer  * @param s2  The return value for the second part of the state.
503*44d4804dSStefan Eßer  * @param i1  The return value for the first part of the increment.
504*44d4804dSStefan Eßer  * @param i2  The return value for the second part of the increment.
505*44d4804dSStefan Eßer  */
506252884aeSStefan Eßer void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2);
507*44d4804dSStefan Eßer 
508*44d4804dSStefan Eßer /**
509*44d4804dSStefan Eßer  * Seed the PRNG with random data.
510*44d4804dSStefan Eßer  * @param rng  The PRNG.
511*44d4804dSStefan Eßer  */
51250696a6eSStefan Eßer void bc_rand_srand(BcRNGData *rng);
513252884aeSStefan Eßer 
514*44d4804dSStefan Eßer /// A reference to a constant multiplier.
515252884aeSStefan Eßer extern const BcRandState bc_rand_multiplier;
516252884aeSStefan Eßer 
517252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
518252884aeSStefan Eßer 
519252884aeSStefan Eßer #endif // BC_RAND_H
520