Xorshift

Last updated
Example random distribution of Xorshift128 Xorshift.png
Example random distribution of Xorshift128

Xorshift random number generators, also called shift-register generators, are a class of pseudorandom number generators that were invented by George Marsaglia. [1] They are a subset of linear-feedback shift registers (LFSRs) which allow a particularly efficient implementation in software without the excessive use of sparse polynomials. [2] They generate the next number in their sequence by repeatedly taking the exclusive or of a number with a bit-shifted version of itself. This makes execution extremely efficient on modern computer architectures, but it does not benefit efficiency in a hardware implementation. Like all LFSRs, the parameters have to be chosen very carefully in order to achieve a long period. [3]

Contents

For execution in software, xorshift generators are among the fastest PRNGs, requiring very small code and state. However, they do not pass every statistical test without further refinement. This weakness is amended by combining them with a non-linear function, as described in the original paper. Because plain xorshift generators (without a non-linear step) fail some statistical tests, they have been accused of being unreliable. [3] :360

Example implementation

A C version [lower-alpha 1] of three xorshift algorithms [1] :4,5 is given here. The first has one 32-bit word of state, and period 232−1. The second has one 64-bit word of state and period 264−1. The last one has four 32-bit words of state, and period 2128−1. The 128-bit algorithm passes the diehard tests. However, it fails the MatrixRank and LinearComp tests of the BigCrush test suite from the TestU01 framework.

All use three shifts and three or four exclusive-or operations:

#include<stdint.h>structxorshift32_state{uint32_ta;};/* The state must be initialized to non-zero */uint32_txorshift32(structxorshift32_state*state){/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */uint32_tx=state->a;x^=x<<13;x^=x>>17;x^=x<<5;returnstate->a=x;}structxorshift64_state{uint64_ta;};uint64_txorshift64(structxorshift64_state*state){uint64_tx=state->a;x^=x<<13;x^=x>>7;x^=x<<17;returnstate->a=x;}/* struct xorshift128_state can alternatively be defined as a pair   of uint64_t or a uint128_t where supported */structxorshift128_state{uint32_tx[4];};/* The state must be initialized to non-zero */uint32_txorshift128(structxorshift128_state*state){/* Algorithm "xor128" from p. 5 of Marsaglia, "Xorshift RNGs" */uint32_tt=state->x[3];uint32_ts=state->x[0];/* Perform a contrived 32-bit shift. */state->x[3]=state->x[2];state->x[2]=state->x[1];state->x[1]=s;t^=t<<11;t^=t>>8;returnstate->x[0]=t^s^(s>>19);}

In case of one 64-bit word of state, there exist parameters which hold period 264−1 with two pair of exclusive-or and shift. [4]

#include<stdint.h>structxorshift64_state{uint64_ta;};uint64_txorshift64(structxorshift64_state*state){uint64_tx=state->a;x^=x<<7;x^=x>>9;returnstate->a=x;}

Non-linear variations

All xorshift generators fail some tests in the BigCrush test suite. This is true for all generators based on linear recurrences, such as the Mersenne Twister or WELL. However, it is easy to scramble the output of such generators to improve their quality.

The scramblers known as + and * still leave weakness in the low bits, [5] so they are intended for floating point use, where the lowest bits of floating-point numbers have a smaller impact on the interpreted value. [6] For general purpose, the scrambler ** (pronounced starstar) makes the LFSR generators pass in all bits.

xorwow

Marsaglia suggested scrambling the output by combining it with a simple additive counter modulo 232 (which he calls a "Weyl sequence" after Weyl's equidistribution theorem). This also increases the period by a factor of 232, to 2192−232:

#include<stdint.h>structxorwow_state{uint32_tx[5];uint32_tcounter;};/* The state array must be initialized to not be all zero in the first four words */uint32_txorwow(structxorwow_state*state){/* Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs" */uint32_tt=state->x[4];uint32_ts=state->x[0];/* Perform a contrived 32-bit shift. */state->x[4]=state->x[3];state->x[3]=state->x[2];state->x[2]=state->x[1];state->x[1]=s;t^=t>>2;t^=t<<1;t^=s^(s<<4);state->x[0]=t;state->counter+=362437;returnt+state->counter;}

This performs well, but fails a few tests in BigCrush. [7] This generator is the default in Nvidia's CUDA toolkit. [8]

xorshift*

An xorshift* generator applies an invertible multiplication (modulo the word size) as a non-linear transformation to the output of an xorshift generator, as suggested by Marsaglia. [1] All xorshift* generators emit a sequence of values that is equidistributed in the maximum possible dimension (except that they will never output zero for 16 calls, i.e. 128 bytes, in a row). [9]

The following 64-bit generator has a maximal period of 264−1. [9]

#include<stdint.h>/* xorshift64s, variant A_1(12,25,27) with multiplier M_32 from line 3 of table 5 */uint64_txorshift64star(void){/* initial seed must be nonzero, don't use a static variable for the state if multithreaded */staticuint64_tx=1;x^=x>>12;x^=x<<25;x^=x>>27;returnx*0x2545F4914F6CDD1DULL;}

The generator fails only the MatrixRank test of BigCrush, however if the generator is modified to return only the high 32 bits, then it passes BigCrush with zero failures. [10] :7 In fact, a reduced version with only 40 bits of internal state passes the suite, suggesting a large safety margin. [10] :19 A similar generator suggested in Numerical Recipes [11] as RanQ1 also fails the BirthdaySpacings test.

Vigna [9] suggests the following xorshift1024* generator with 1024 bits of state and a maximal period of 21024−1; however, it does not always pass BigCrush. [5] xoshiro256** is therefore a much better option.

#include<stdint.h>/* The state must be seeded so that there is at least one non-zero element in array */structxorshift1024s_state{uint64_tx[16];intindex;};uint64_txorshift1024s(structxorshift1024s_state*state){intindex=state->index;uint64_tconsts=state->x[index++];uint64_tt=state->x[index&=15];t^=t<<31;// at^=t>>11;// b  -- Again, the shifts and the multipliers are tunablet^=s^(s>>30);// cstate->x[index]=t;state->index=index;returnt*1181783497276652981ULL;}

xorshift+

An xorshift+ generator can achieve an order of magnitude fewer failures than Mersenne Twister or WELL. A native C implementation of an xorshift+ generator that passes all tests from the BigCrush suite can typically generate a random number in fewer than 10 clock cycles on x86, thanks to instruction pipelining. [12]

Rather than using multiplication, it is possible to use addition as a faster non-linear transformation. The idea was first proposed by Saito and Matsumoto (also responsible for the Mersenne Twister) in the XSadd generator, which adds two consecutive outputs of an underlying xorshift generator based on 32-bit shifts. [13] However, one disadvantage of adding consecutive outputs is that, while the underlying xorshift128 generator is 2-dimensionally equidistributed, the xorshift128+ generator is only 1-dimensionally equidistributed. [14]

XSadd has some weakness in the low-order bits of its output; it fails several BigCrush tests when the output words are bit-reversed. To correct this problem, Vigna introduced the xorshift+ family, [14] based on 64-bit shifts. xorshift+ generators, even as large as xorshift1024+, exhibit some detectable linearity in the low-order bits of their output; [5] it passes BigCrush, but doesn't when the 32 lowest-order bits are used in reverse order from each 64-bit word. [5] This generator is one of the fastest generators passing BigCrush. [12]

The following xorshift128+ generator uses 128 bits of state and has a maximal period of 2128−1.

#include<stdint.h>structxorshift128p_state{uint64_tx[2];};/* The state must be seeded so that it is not all zero */uint64_txorshift128p(structxorshift128p_state*state){uint64_tt=state->x[0];uint64_tconsts=state->x[1];state->x[0]=s;t^=t<<23;// at^=t>>18;// b -- Again, the shifts and the multipliers are tunablet^=s^(s>>5);// cstate->x[1]=t;returnt+s;}

xoshiro

xoshiro (short for "xor, shift, rotate") and xoroshiro (short for "xor, rotate, shift, rotate") use rotations in addition to shifts. According to Vigna, they are faster and produce better quality output than xorshift. [15] [16]

This class of generator has variants for 32-bit and 64-bit integer and floating point output; for floating point, one takes the upper 53 bits (for binary64) or the upper 23 bits (for binary32), since the upper bits are of better quality than the lower bits in the floating point generators. The algorithms also include a jump function, which sets the state forward by some number of steps – usually a power of two that allows many threads of execution to start at distinct initial states.

For 32-bit output, xoshiro128** and xoshiro128+ are exactly equivalent to xoshiro256** and xoshiro256+, with uint32_t in place of uint64_t, and with different shift/rotate constants.

More recently, the xoshiro++ generators have been made as an alternative to the xoshiro** generators. They are used in some implementations of Fortran compilers such as GNU Fortran, Java, and Julia. [17]

xoshiro256**

xoshiro256** is the family's general-purpose random 64-bit number generator. It is used in GNU Fortran compiler, Lua (as of Lua 5.4), and the .NET framework (as of .NET 6.0). [17]

/*  Adapted from the code included on Sebastiano Vigna's website */#include<stdint.h>uint64_trol64(uint64_tx,intk){return(x<<k)|(x>>(64-k));}structxoshiro256ss_state{uint64_ts[4];};uint64_txoshiro256ss(structxoshiro256ss_state*state){uint64_t*s=state->s;uint64_tconstresult=rol64(s[1]*5,7)*9;uint64_tconstt=s[1]<<17;s[2]^=s[0];s[3]^=s[1];s[1]^=s[2];s[0]^=s[3];s[2]^=t;s[3]=rol64(s[3],45);returnresult;}

xoshiro256+

xoshiro256+ is approximately 15% faster than xoshiro256**, but the lowest three bits have low linear complexity; therefore, it should be used only for floating point results by extracting the upper 53 bits.

#include<stdint.h>uint64_trol64(uint64_tx,intk){return(x<<k)|(x>>(64-k));}structxoshiro256p_state{uint64_ts[4];};uint64_txoshiro256p(structxoshiro256p_state*state){uint64_t*s=state->s;uint64_tconstresult=s[0]+s[3];uint64_tconstt=s[1]<<17;s[2]^=s[0];s[3]^=s[1];s[1]^=s[2];s[0]^=s[3];s[2]^=t;s[3]=rol64(s[3],45);returnresult;}

xoroshiro

If space is at a premium, xoroshiro128** and xoroshiro128+ are equivalent to xoshiro256** and xoshiro256+. These have smaller state spaces, and thus are less useful for massively parallel programs. xoroshiro128+ also exhibits a mild dependency in the population count, generating a failure after 5  TB of output. The authors do not believe that this can be detected in real world programs.

xoroshiro64** and xoroshiro64* are equivalent to xoroshiro128** and xoroshiro128+. Unlike the xoshiro generators, they are not straightforward ports of their higher-precision counterparts.

Initialization

In the xoshiro paper, it is recommended to initialize the state of the generators using a generator which is radically different from the initialized generators, as well as one which will never give the "all-zero" state; for shift-register generators, this state is impossible to escape from. [16] [18] The authors specifically recommend using the SplitMix64 generator, from a 64-bit seed, as follows:

#include<stdint.h>structsplitmix64_state{uint64_ts;};uint64_tsplitmix64(structsplitmix64_state*state){uint64_tresult=(state->s+=0x9E3779B97f4A7C15);result=(result^(result>>30))*0xBF58476D1CE4E5B9;result=(result^(result>>27))*0x94D049BB133111EB;returnresult^(result>>31);}structxorshift128_state{uint32_tx[4];};// one could do the same for any of the other generatorsvoidxorshift128_init(structxorshift128_state*state,uint64_tseed){structsplitmix64_statesmstate={seed};uint64_ttmp=splitmix64(&smstate);state->x[0]=(uint32_t)tmp;state->x[1]=(uint32_t)(tmp>>32);tmp=splitmix64(&smstate);state->x[2]=(uint32_t)tmp;state->x[3]=(uint32_t)(tmp>>32);}

Notes

  1. In C and most other C-based languages, ^ represents bitwise XOR, and << and >> represent bitwise shifts.

Related Research Articles

A pseudorandom number generator (PRNG), also known as a deterministic random bit generator (DRBG), is an algorithm for generating a sequence of numbers whose properties approximate the properties of sequences of random numbers. The PRNG-generated sequence is not truly random, because it is completely determined by an initial value, called the PRNG's seed. Although sequences that are closer to truly random can be generated using hardware random number generators, pseudorandom number generators are important in practice for their speed in number generation and their reproducibility.

<span class="mw-page-title-main">Linear congruential generator</span> Algorithm for generating pseudo-randomized numbers

A linear congruential generator (LCG) is an algorithm that yields a sequence of pseudo-randomized numbers calculated with a discontinuous piecewise linear equation. The method represents one of the oldest and best-known pseudorandom number generator algorithms. The theory behind them is relatively easy to understand, and they are easily implemented and fast, especially on computer hardware which can provide modular arithmetic by storage-bit truncation.

The Mersenne Twister is a general-purpose pseudorandom number generator (PRNG) developed in 1997 by Makoto Matsumoto and Takuji Nishimura. Its name derives from the choice of a Mersenne prime as its period length.

A Lagged Fibonacci generator is an example of a pseudorandom number generator. This class of random number generator is aimed at being an improvement on the 'standard' linear congruential generator. These are based on a generalisation of the Fibonacci sequence.

In computing, a linear-feedback shift register (LFSR) is a shift register whose input bit is a linear function of its previous state.

<span class="mw-page-title-main">Serpent (cipher)</span>

Serpent is a symmetric key block cipher that was a finalist in the Advanced Encryption Standard (AES) contest, in which it ranked second to Rijndael. Serpent was designed by Ross Anderson, Eli Biham, and Lars Knudsen.

<span class="mw-page-title-main">Tiny Encryption Algorithm</span> Block cipher

In cryptography, the Tiny Encryption Algorithm (TEA) is a block cipher notable for its simplicity of description and implementation, typically a few lines of code. It was designed by David Wheeler and Roger Needham of the Cambridge Computer Laboratory; it was first presented at the Fast Software Encryption workshop in Leuven in 1994, and first published in the proceedings of that workshop.

<span class="mw-page-title-main">XTEA</span> Block cipher

In cryptography, XTEA is a block cipher designed to correct weaknesses in TEA. The cipher's designers were David Wheeler and Roger Needham of the Cambridge Computer Laboratory, and the algorithm was presented in an unpublished technical report in 1997. It is not subject to any patents.

Red Pike is a classified United Kingdom government encryption algorithm, proposed for use by the National Health Service by GCHQ, but designed for a "broad range of applications in the British government" Archived 2004-04-23 at the Wayback Machine. Little is publicly known about Red Pike, except that it is a block cipher with a 64-bit block size and 64-bit key length. According to the academic study of the cipher cited below and quoted in a paper by Ross Anderson and Markus Kuhn, it "uses the same basic operations as RC5" and "has no look-up tables, virtually no key schedule and requires only five lines of code"; "the influence of each key bit quickly cascades" and "each encryption involves of the order of 100 operations". 64 bits of key entropy are not considered secure anymore.

The Hamming weight of a string is the number of symbols that are different from the zero-symbol of the alphabet used. It is thus equivalent to the Hamming distance from the all-zero string of the same length. For the most typical case, a string of bits, this is the number of 1's in the string, or the digit sum of the binary representation of a given number and the ₁ norm of a bit vector. In this binary case, it is also called the population count, popcount, sideways sum, or bit summation.

The grid method of multiplication is an introductory approach to multi-digit multiplication calculations that involve numbers larger than ten. Because it is often taught in mathematics education at the level of primary school or elementary school, this algorithm is sometimes called the grammar school method.

In computer science, multiply-with-carry (MWC) is a method invented by George Marsaglia for generating sequences of random integers based on an initial set from two to many thousands of randomly chosen seed values. The main advantages of the MWC method are that it invokes simple computer integer arithmetic and leads to very fast generation of sequences of random numbers with immense periods, ranging from around to .

The Lehmer random number generator, sometimes also referred to as the Park–Miller random number generator, is a type of linear congruential generator (LCG) that operates in multiplicative group of integers modulo n. The general formula is

In the C programming language, operations can be performed on a bit level using bitwise operators.

TestU01 is a software library, implemented in the ANSI C language, that offers a collection of utilities for the empirical randomness testing of random number generators (RNGs). The library was first introduced in 2007 by Pierre L’Ecuyer and Richard Simard of the Université de Montréal.

<span class="mw-page-title-main">Spectral test</span>

The spectral test is a statistical test for the quality of a class of pseudorandom number generators (PRNGs), the linear congruential generators (LCGs). LCGs have a property that when plotted in 2 or more dimensions, lines or hyperplanes will form, on which all possible outputs can be found. The spectral test compares the distance between these planes; the further apart they are, the worse the generator is. As this test is devised to study the lattice structures of LCGs, it can not be applied to other families of PRNGs.

KISS (Keep it Simple Stupid) is a family of pseudorandom number generators introduced by George Marsaglia. Starting from 1998 Marsaglia posted on various newsgroups including sci.math, comp.lang.c, comp.lang.fortran and sci.stat.math several versions of the generators. All KISS generators combine three or four independent random number generators with a view to improving the quality of randomness. KISS generators produce 32-bit or 64-bit random integers, from which random floating-point numbers can be constructed if desired. The original 1993 generator is based on the combination of a linear congruential generator and of two linear feedback shift-register generators. It has a period 295, good speed and good statistical properties; however, it fails the LinearComplexity test in the Crush and BigCrush tests of the TestU01 suite. A newer version from 1999 is based on a linear congruential generator, a 3-shift linear feedback shift-register and two multiply-with-carry generators. It is 10–20% slower than the 1993 version but has a larger period 2123 and passes all tests in TestU01. In 2009 Marsaglia presented a version based on 64-bit integers (appropriate for 64-bit processors) which combines a multiply-with-carry generator, a Xorshift generator and a linear congruential generator. It has a period of around 2250 (around 1075).

xoroshiro128+ is a pseudorandom number generator intended as a successor to xorshift+. Instead of perpetuating Marsaglia's tradition of xorshift as a basic operation, xoroshiro128+ uses a shift/rotate-based linear transformation designed by Sebastiano Vigna in collaboration with David Blackman. The result is a significant improvement in speed and statistical quality.

A permuted congruential generator (PCG) is a pseudorandom number generation algorithm developed in 2014 by Dr. M.E. O'Neill which applies an output permutation function to improve the statistical properties of a modulo-2n linear congruential generator. It achieves excellent statistical performance with small and fast code, and small state size.

References

  1. 1 2 3 Marsaglia, George (July 2003). "Xorshift RNGs". Journal of Statistical Software . 8 (14). doi: 10.18637/jss.v008.i14 .
  2. Brent, Richard P. (August 2004). "Note on Marsaglia's Xorshift Random Number Generators". Journal of Statistical Software . 11 (5). doi: 10.18637/jss.v011.i05 . hdl: 1885/34049 .
  3. 1 2 Panneton, François; L'Ecuyer, Pierre (October 2005). "On the xorshift random number generators" (PDF). ACM Transactions on Modeling and Computer Simulation. 15 (4): 346–361. doi:10.1145/1113316.1113319. S2CID   11136098.
  4. 和田維作. "良い乱数・悪い乱数" . Retrieved 2023-08-28. The parameters are only (7,9) and (9.7).
  5. 1 2 3 4 Lemire, Daniel; O’Neill, Melissa E. (April 2019). "Xorshift1024*, Xorshift1024+, Xorshift128+ and Xoroshiro128+ Fail Statistical Tests for Linearity". Computational and Applied Mathematics. 350: 139–142. arXiv: 1810.05313 . doi:10.1016/j.cam.2018.10.019. S2CID   52983294. We report that these scrambled generators systematically fail Big Crush—specifically the linear-complexity and matrix-rank tests that detect linearity—when taking the 32 lowest-order bits in reverse order from each 64-bit word.
  6. "ISO/IEC 60559:2020". ISO.
  7. Le Floc'h, Fabien (12 January 2011). "XORWOW L'ecuyer TestU01 Results". Chase The Devil (blog). Retrieved 2017-11-02.
  8. "cuRAND Testing". Nvidia . Retrieved 2017-11-02.
  9. 1 2 3 Vigna, Sebastiano (July 2016). "An experimental exploration of Marsaglia's xorshift generators, scrambled" (PDF). ACM Transactions on Mathematical Software. 42 (4): 30. arXiv: 1402.6246 . doi:10.1145/2845077. S2CID   13936073. Proposes xorshift* generators, adding a final multiplication by a constant.
  10. 1 2 O'Neill, Melissa E. (5 September 2014). PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation (PDF) (Technical report). Harvey Mudd College. pp. 6–8. HMC-CS-2014-0905.
  11. Press, WH; Teukolsky, SA; Vetterling, WT; Flannery, BP (2007). "Section 7.1.2.A. 64-bit Xorshift Method". Numerical Recipes: The Art of Scientific Computing (3rd ed.). New York: Cambridge University Press. ISBN   978-0-521-88068-8.
  12. 1 2 Vigna, Sebastiano. "xorshift*/xorshift+ generators and the PRNG shootout" . Retrieved 2014-10-25.
  13. Saito, Mutsuo; Matsumoto, Makoto (2014). "XORSHIFT-ADD (XSadd): A variant of XORSHIFT" . Retrieved 2014-10-25.
  14. 1 2 Vigna, Sebastiano (May 2017). "Further scramblings of Marsaglia's xorshift generators" (PDF). Journal of Computational and Applied Mathematics. 315 (C): 175–181. arXiv: 1404.0390 . doi:10.1016/j.cam.2016.11.006. S2CID   6876444. Describes xorshift+ generators, a generalization of XSadd.
  15. Vigna, Sebastiano. "xoshiro/xoroshiro generators and the PRNG shootout" . Retrieved 2019-07-07.
  16. 1 2 Blackman, David; Vigna, Sebastiano (2018). "Scrambled Linear Pseudorandom Number Generators". Data Structures and Algorithms. arXiv: 1805.01407 .
  17. 1 2 "xoshiro / xoroshiro generators and the PRNG shootout" . Retrieved 2023-09-07.
  18. Matsumoto, Makoto; Wada, Isaku; Kuramoto, Ai; Ashihara, Hyo (September 2007). "Common defects in initialization of pseudorandom number generators". ACM Transactions on Modeling and Computer Simulation. 17 (4): 15–es. doi:10.1145/1276927.1276928. S2CID   1721554.

Further reading