website statistics

Xorshift RNGs for small systemsΒΆ

“Xorshift RNGs” by George Marsaglia describes a very efficient system for generating high-quality random numbers using very little compute and storage.

For a simple random number generator running on an embedded CPU we’re unlikely to be very concerned with cycle lengths – a cycle of 232-1 is perfectly acceptable. Marsaglia suggests coefficients (13, 17, 5) for a 32-bit generator. So we have C code:

uint32_t seed = 7;  // 100% random seed value

static uint32_t random()
{
  seed ^= seed << 13;
  seed ^= seed >> 17;
  seed ^= seed << 5;
  return seed;
}

This is simple enough to give excellent performance on an 8-bit CPU. Note that seed never reaches zero; in fact if seed is zero then random() returns zero every time.

This 32-bit ANS Forth implementation also has a setseed function which can be safely called with any 32-bit integer. setseed handles the problem value of 0 by mapping it to -1.

variable seed
7 seed !

: random    ( -- x )  \ return a 32-bit random number x
    seed @
    dup 13 lshift xor
    dup 17 rshift xor
    dup 5  lshift xor
    dup seed !
;

: setseed   ( x -- )  \ seed the RNG with x
    dup 0= or         \ map 0 to -1
    seed !
;

As a quick trial, plotting 65536 random pixels in a 256x256 grid on a Gameduino 2 gives no obvious patterns:

_images/xorshift.png