Update xoroshiro128+ to 1.0 version

This commit is contained in:
Joris van Rantwijk 2020-08-11 18:13:48 +02:00
parent e92ed9ea54
commit 2085470db4
4 changed files with 64 additions and 35 deletions

View File

@ -25,13 +25,17 @@ NOTE: This library is not designed for cryptographic applications
------------------ ------------------
Xoroshiro128+ is an RNG algorithm developed in 2016 by David Blackman Xoroshiro128+ is an RNG algorithm developed in 2016 by David Blackman
and Sebastiano Vigna. It is a further development of the Xorshift algorithm and Sebastiano Vigna. The VHDL code matches an updated version of
invented by George Marsaglia the algorithm called "xoroshiro128+ 1.0", released in 2018.
The Xoroshiro algorithm is based on the Xorshift concept invented
by George Marsaglia.
See also http://xoroshiro.di.unimi.it/ See also http://prng.di.unimi.it/
This RNG passes many statistical tests. Its period, 2**128 - 1, is long This RNG passes many statistical tests, but the least significant
compared to a typical LFSR, but much shorter than the Mersenne Twister. output bits are known to be not fully random and fail certain tests.
The generator has a long period (2**128 - 1) compared to a typical LFSR,
but much shorter than the Mersenne Twister.
The output is 1-dimensionally equidistributed. The output is 1-dimensionally equidistributed.
The VHDL implementation produces 64 new random bits on every (enabled) The VHDL implementation produces 64 new random bits on every (enabled)
@ -43,7 +47,7 @@ Seed length: 128 bits
Period: 2**128 - 1 Period: 2**128 - 1
FPGA resources: general logic and 64-bit adder FPGA resources: general logic and 64-bit adder
Synthesis results: 194 LUTs, 192 registers on Spartan-6 Synthesis results: 198 LUTs, 193 registers on Spartan-6
Timing results: 333 MHz on Spartan-6 LX45-3 Timing results: 333 MHz on Spartan-6 LX45-3
@ -141,7 +145,7 @@ Timing results: 380 MHz on Spartan-6 LX45-3 (32 bits output)
License License
------- -------
Copyright (C) 2016 Joris van Rantwijk Copyright (C) 2016-2020 Joris van Rantwijk
This VHDL library is free software; you can redistribute it and/or This VHDL library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License modify it under the terms of the GNU Lesser General Public License

View File

@ -10,9 +10,9 @@ CFLAGS = -std=c11 -Wall -O2
CXXFLAGS = -std=c++11 -Wall -O2 CXXFLAGS = -std=c++11 -Wall -O2
.PHONY: all .PHONY: all
all: ref_xoroshiro ref_mt19937 ref_trivium all: ref_xoroshiro128plus ref_mt19937 ref_trivium
ref_xoroshiro: ref_xoroshiro.c ref_xoroshiro128plus: ref_xoroshiro128plus.c
ref_mt19937: ref_mt19937.cpp ref_mt19937: ref_mt19937.cpp
@ -20,5 +20,5 @@ ref_trivium: ref_trivium.cpp
.PHONY: clean .PHONY: clean
clean: clean:
$(RM) ref_xoroshiro ref_mt19937 ref_trivium $(RM) ref_xoroshiro128plus ref_mt19937 ref_trivium

View File

@ -13,14 +13,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
/* ========== BEGIN of reference implementation of xoroshiro128+ ========== /* ========== BEGIN of reference implementation of xoroshiro128+ ==========
* Source: http://xoroshiro.di.unimi.it/ * Source: http://prng.di.unimi.it/
*/ */
/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) /* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain and related and neighboring rights to this software to the public domain
@ -28,22 +27,48 @@ worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */ See <http://creativecommons.org/publicdomain/zero/1.0/>. */
int64_t s[2]; #include <stdint.h>
/* This is xoroshiro128+ 1.0, our best and fastest small-state generator
for floating-point numbers. We suggest to use its upper bits for
floating-point generation, as it is slightly faster than
xoroshiro128++/xoroshiro128**. It passes all tests we are aware of
except for the four lower bits, which might fail linearity tests (and
just those), so if low linear complexity is not considered an issue (as
it is usually the case) it can be used to generate 64-bit outputs, too;
moreover, this generator has a very mild Hamming-weight dependency
making our test (http://prng.di.unimi.it/hwd.php) fail after 5 TB of
output; we believe this slight bias cannot affect any application. If
you are concerned, use xoroshiro128++, xoroshiro128** or xoshiro256+.
We suggest to use a sign test to extract a random Boolean value, and
right shifts to extract subsets of bits.
The state must be seeded so that it is not everywhere zero. If you have
a 64-bit seed, we suggest to seed a splitmix64 generator and use its
output to fill s.
NOTE: the parameters (a=24, b=16, b=37) of this version give slightly
better results in our test than the 2016 version (a=55, b=14, c=36).
*/
static inline uint64_t rotl(const uint64_t x, int k) { static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
static uint64_t s[2];
uint64_t next(void) { uint64_t next(void) {
const uint64_t s0 = s[0]; const uint64_t s0 = s[0];
uint64_t s1 = s[1]; uint64_t s1 = s[1];
const uint64_t result = s0 + s1; const uint64_t result = s0 + s1;
s1 ^= s0; s1 ^= s0;
s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
s[1] = rotl(s1, 36); // c s[1] = rotl(s1, 37); // c
return result; return result;
} }
/* ========== END of reference implementation of xoroshiro128+ ========== */ /* ========== END of reference implementation of xoroshiro128+ ========== */
@ -58,12 +83,12 @@ int main(int argc, const char **argv)
if (argc != 4) { if (argc != 4) {
fprintf(stderr, "Reference implementation of RNG xoroshiro128+\n"); fprintf(stderr, "Reference implementation of RNG xoroshiro128+\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Usage: ref_xoroshiro SEED0 SEED1 NUMVALUE\n"); fprintf(stderr, "Usage: ref_xoroshiro128plus SEED0 SEED1 NUMVALUE\n");
fprintf(stderr, " SEED0 seed value in range 0 .. (2**64-1)\n"); fprintf(stderr, " SEED0 seed value in range 0 .. (2**64-1)\n");
fprintf(stderr, " SEED1 seed value in range 0 .. (2**64-1)\n"); fprintf(stderr, " SEED1 seed value in range 0 .. (2**64-1)\n");
fprintf(stderr, " NUMVALUE number of values to get from generator\n"); fprintf(stderr, " NUMVALUE number of values to get from generator\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Example: ref_xoroshiro 0x3141592653589793 " fprintf(stderr, "Example: ref_xoroshiro128plus 0x3141592653589793 "
"0x0123456789abcdef 100\n"); "0x0123456789abcdef 100\n");
exit(1); exit(1);
} }

View File

@ -1,5 +1,5 @@
-- --
-- Pseudo Random Number Generator "xoroshiro128+". -- Pseudo Random Number Generator "xoroshiro128+ 1.0".
-- --
-- Author: Joris van Rantwijk <joris@jorisvr.nl> -- Author: Joris van Rantwijk <joris@jorisvr.nl>
-- --
@ -7,9 +7,9 @@
-- The generator can produce 64 new random bits on every clock cycle. -- The generator can produce 64 new random bits on every clock cycle.
-- --
-- The algorithm "xoroshiro128+" is by David Blackman and Sebastiano Vigna. -- The algorithm "xoroshiro128+" is by David Blackman and Sebastiano Vigna.
-- See also http://xoroshiro.di.unimi.it/ -- See also http://prng.di.unimi.it/
-- --
-- The generator requires a 128-bit seed value, not equal to zero. -- The generator requires a 128-bit seed value, not equal to all zeros.
-- A default seed must be supplied at compile time and will be used -- A default seed must be supplied at compile time and will be used
-- to initialize the generator at reset. The generator also supports -- to initialize the generator at reset. The generator also supports
-- re-seeding at run time. -- re-seeding at run time.
@ -19,12 +19,12 @@
-- --
-- NOTE: This is not a cryptographic random number generator. -- NOTE: This is not a cryptographic random number generator.
-- --
-- NOTE: The least significant output bit is less random than -- NOTE: The least significant output bits are not fully random and
-- all other output bits. -- fail certain statistical tests.
-- --
-- --
-- Copyright (C) 2016 Joris van Rantwijk -- Copyright (C) 2016-2020 Joris van Rantwijk
-- --
-- This code is free software; you can redistribute it and/or -- This code is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public -- modify it under the terms of the GNU Lesser General Public
@ -131,12 +131,12 @@ begin
-- Update internal state. -- Update internal state.
reg_state_s0 <= reg_state_s0 xor reg_state_s0 <= reg_state_s0 xor
reg_state_s1 xor reg_state_s1 xor
shiftl(reg_state_s0, 14) xor rotl(reg_state_s0, 24) xor
shiftl(reg_state_s1, 14) xor shiftl(reg_state_s0, 16) xor
rotl(reg_state_s0, 55); shiftl(reg_state_s1, 16);
reg_state_s1 <= rotl(reg_state_s0, 36) xor reg_state_s1 <= rotl(reg_state_s0, 37) xor
rotl(reg_state_s1, 36); rotl(reg_state_s1, 37);
end if; end if;