summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/include/gnuradio/xoroshiro128p.h
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/include/gnuradio/xoroshiro128p.h')
-rw-r--r--gnuradio-runtime/include/gnuradio/xoroshiro128p.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/gnuradio-runtime/include/gnuradio/xoroshiro128p.h b/gnuradio-runtime/include/gnuradio/xoroshiro128p.h
new file mode 100644
index 0000000000..b3e6dcb12d
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/xoroshiro128p.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Built on XOROSHIRO128+ by David Blackman and Sebastiano Vigna who put this
+// under CC-0, colloquially known as "public domain (or as close you get to that
+// in your local legislation)" see
+// http://xoroshiro.di.unimi.it/xoroshiro128plus.c
+// Conversion to a local state (original used global state) done by Marcus
+// Müller, 2018.
+#ifndef INCLUDED_XOROSHIRO128P_H
+#define INCLUDED_XOROSHIRO128P_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/*! \brief rotating left shift helper
+ * According to the original authors, this will on most platforms reduce to a single instruction
+ */
+static inline uint64_t rotl(const uint64_t x, const int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+
+/*! \brief generate the next random number and update the state.
+ * This is the workhorse, here!
+ */
+static inline uint64_t xoroshiro128p_next(uint64_t *state) {
+ const uint64_t s0 = state[0];
+ uint64_t s1 = state[1];
+ const uint64_t result = s0 + s1;
+
+ s1 ^= s0;
+ state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
+ state[1] = rotl(s1, 36); // c
+
+ return result;
+}
+
+
+/*! \brief Advance the internal state by 2^64 steps; useful when coordinating multiple independent RNGs
+ This is the jump function for the generator. It is equivalent
+ to 2^64 calls to next(); it can be used to generate 2^64
+ non-overlapping subsequences for parallel computations. */
+static inline void xoroshiro128p_jump(uint64_t *state) {
+ static const uint64_t JUMP[] = { 0xbeac0467eba5facb, 0xd86b048b86aa9922 };
+
+ uint64_t s0 = 0;
+ uint64_t s1 = 0;
+ for(unsigned int i = 0; i < sizeof (JUMP) / sizeof (*JUMP); ++i) {
+ for(unsigned int b = 0; b < 64; ++b) {
+ if (JUMP[i] & UINT64_C(1) << b) {
+ s0 ^= state[0];
+ s1 ^= state[1];
+ }
+ xoroshiro128p_next(state);
+ }
+ }
+
+ state[0] = s0;
+ state[1] = s1;
+}
+
+/*! \brief step of the SPLITMIX64 RNG; only used internally for seeding
+ * This RNG isn't as good as XOROSHIRO128+, so it's only used to initialize a 128 bit state from a seed.
+ */
+static inline uint64_t splitmix64_next(uint64_t *state) {
+ uint64_t z = (*state += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
+
+/*! \brief Seed the 128 bit state from a 64 bit seed
+ */
+static inline void xoroshiro128p_seed(uint64_t *state, const uint64_t seed) {
+ state[0] = seed;
+ state[1] = splitmix64_next(state);
+ xoroshiro128p_jump(state);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif // Include guard