xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/isc/xoshiro128starstar.c (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
1 /*	$NetBSD: xoshiro128starstar.c,v 1.1 2024/02/18 20:57:51 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0.  If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*
17  * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
18  *
19  * To the extent possible under law, the author has dedicated all
20  * copyright and related and neighboring rights to this software to the
21  * public domain worldwide. This software is distributed without any
22  * warranty.
23  *
24  * See <http://creativecommons.org/publicdomain/zero/1.0/>.
25  */
26 
27 #include <inttypes.h>
28 
29 #include <isc/thread.h>
30 
31 /*
32  * This is xoshiro128** 1.0, our 32-bit all-purpose, rock-solid generator.
33  * It has excellent (sub-ns) speed, a state size (128 bits) that is large
34  * enough for mild parallelism, and it passes all tests we are aware of.
35  *
36  * For generating just single-precision (i.e., 32-bit) floating-point
37  * numbers, xoshiro128+ is even faster.
38  *
39  * The state must be seeded so that it is not everywhere zero.
40  */
41 ISC_THREAD_LOCAL uint32_t seed[4] = { 0 };
42 
43 static uint32_t
rotl(const uint32_t x,int k)44 rotl(const uint32_t x, int k) {
45 	return ((x << k) | (x >> (32 - k)));
46 }
47 
48 static uint32_t
next(void)49 next(void) {
50 	uint32_t result_starstar, t;
51 
52 	result_starstar = rotl(seed[0] * 5, 7) * 9;
53 	t = seed[1] << 9;
54 
55 	seed[2] ^= seed[0];
56 	seed[3] ^= seed[1];
57 	seed[1] ^= seed[2];
58 	seed[0] ^= seed[3];
59 
60 	seed[2] ^= t;
61 
62 	seed[3] = rotl(seed[3], 11);
63 
64 	return (result_starstar);
65 }
66