4-Word [pseudo] Random Generator

Generator uses only shifts and xor so it should be fast.

Math design by George Marsaglia, Professor Emeritus, Florida State University. See http://www.jstatsoft.org/v08/i14/xorshift.pdf. From Journal of Statistical Software http://www.jstatsoft.org/.

Thanks to David Sexton for posting a link in news:sci.crypt.random-numbers Message ID: 1ac1d2b9.0310251435.43d3ca44@posting.google.com

This specific generator has a period of (2^128)-1. All items are unsigned 32-bit words.

unsigned int rand32(void)
{
  temp = x ^ (x << 15);
  x = y;
  y = z;
  z = w;
  w = w ^ (w >> 21) ^ temp ^ (temp >> 4);
  return w;
}


In his paper. Dr. Marsaglia mentions 4 triples that work.  The presenter of these pages can only quote values given in the paper:

[23, 24, 3]
[ 5, 14, 1]
[ 5, 12, 29]<-- this triple is used in randomFill
[15, 4, 21] <-- this example is used in his text and rand32()

An efficient random fill follows.  Note that it calls rand32 [up to 4 times] then uses a different set of values to propagate the first 4 words.  See code for details.  And just in case it's not 100% clear if you use the following code (or, for that matter any code off a web page) that proper functionality is 100% in your hands.  I disclaim any responsibility for any faults.  Note that the 4 seed words should be ordered w, z, y, x for memcpy to work properly at the top of this function.

// Thanks to SM Ryan who provided the LV macro in news:comp.lang.c
// As given, the macro name was lvaluecast
// Message-ID: <10imenhfni9tb62@corp.supernews.com>
#define LV(type,lvalue) (*((type*)((void*)(&(lvalue)))))

void randomFill(void* dest, int len)
{
  UINT32 temp;
  if (len <= 0) return; // ie if (stupid arg) return;
  int firstLen = len;
  if (len > 16) firstLen = 16;

///////////////////////////////////////////////
// fill the first 16 bytes...
///////////////////////////////////////////////

  for(temp=(firstLen+3)>>2; temp; temp--)
  {
    rand32();
  }
  memcpy(dest, &w, firstLen);
  LV(int, dest) += firstLen;
  len -= firstLen;

///////////////////////////////////////////////
// fill whole words after the first 16 bytes
///////////////////////////////////////////////

  while (len > 3)
  {
// Notice how LV(int*,dest)[-4] is used where x is used in random()
// and pDest[-1] is used in place of w
//
// Then notice that LV(int*,dest)++ takes the place of x=y etc
//
// NB: uning [5, 12, 29] here is important because we don't want
// to fill with values that follow the future returns from rand32()
//
  temp = LV(int*,dest)[-4] ^ (LV(int*,dest)[-4] << 5);
  *LV(int*,dest)++ =
  LV(int*,dest)[-1] ^ (LV(int*,dest)[-1] >> 29) ^ temp ^ (temp >> 12);
  len -= 4;
  }
  if (len <= 0) return;

/////////////////////////////////////////////
// fill any tail
/////////////////////////////////////////////
  rand32();
  memcpy(dest, &w, len);
}

Next Topic (Lagged Fibonacci Generator)
Previous Topic
Return to Index