diff lphobos/std/random.d @ 473:373489eeaf90

Applied downs' lphobos update
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 04 Aug 2008 19:28:49 +0200
parents
children 88e23f8c2354
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/random.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,161 @@
+/**
+ * Macros:
+ *	WIKI = Phobos/StdRandom
+ */
+
+// random.d
+// www.digitalmars.com
+
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, September 2007
+*/
+
+module std.random;
+
+// Segments of the code in this file Copyright (c) 1997 by Rick Booth
+// From "Inner Loops" by Rick Booth, Addison-Wesley
+
+version (Win32)
+{
+    extern(Windows) int QueryPerformanceCounter(ulong *count);
+}
+else version (Unix)
+{
+    version(linux) import std.c.linux.linux;
+    else private import std.c.unix.unix;
+}
+
+/* ===================== Random ========================= */
+
+// BUG: not multithreaded
+
+private uint seed;		// starting seed
+private uint index;		// ith random number
+
+/**
+ * The random number generator is seeded at program startup with a random value.
+ This ensures that each program generates a different sequence of random
+ numbers. To generate a repeatable sequence, use rand_seed() to start the
+ sequence. seed and index start it, and each successive value increments index.
+ This means that the $(I n)th random number of the sequence can be directly
+ generated
+ by passing index + $(I n) to rand_seed().
+
+ Note: This is more random, but slower, than C's rand() function.
+ To use C's rand() instead, import std.c.stdlib.
+ */
+
+void rand_seed(uint seed, uint index)
+{
+     .seed = seed;
+     .index = index;
+}
+
+/**
+ * Get the next random number in sequence.
+ * BUGS: shares a global single state, not multithreaded
+ */
+
+uint rand()
+{
+    static uint xormix1[20] =
+    [
+                0xbaa96887, 0x1e17d32c, 0x03bcdc3c, 0x0f33d1b2,
+                0x76a6491d, 0xc570d85d, 0xe382b1e3, 0x78db4362,
+                0x7439a9d4, 0x9cea8ac5, 0x89537c5c, 0x2588f55d,
+                0x415b5e1d, 0x216e3d95, 0x85c662e7, 0x5e8ab368,
+                0x3ea5cc8c, 0xd26a0f74, 0xf3a9222b, 0x48aad7e4
+    ];
+
+    static uint xormix2[20] =
+    [
+                0x4b0f3b58, 0xe874f0c3, 0x6955c5a6, 0x55a7ca46,
+                0x4d9a9d86, 0xfe28a195, 0xb1ca7865, 0x6b235751,
+                0x9a997a61, 0xaa6e95c8, 0xaaa98ee1, 0x5af9154c,
+                0xfc8e2263, 0x390f5e8c, 0x58ffd802, 0xac0a5eba,
+                0xac4874f6, 0xa9df0913, 0x86be4c74, 0xed2c123b
+    ];
+
+    uint hiword, loword, hihold, temp, itmpl, itmph, i;
+
+    loword = seed;
+    hiword = index++;
+    for (i = 0; i < 4; i++)		// loop limit can be 2..20, we choose 4
+    {
+        hihold  = hiword;                           // save hiword for later
+        temp    = hihold ^  xormix1[i];             // mix up bits of hiword
+        itmpl   = temp   &  0xffff;                 // decompose to hi & lo
+        itmph   = temp   >> 16;                     // 16-bit words
+        temp    = itmpl * itmpl + ~(itmph * itmph); // do a multiplicative mix
+        temp    = (temp >> 16) | (temp << 16);      // swap hi and lo halves
+        hiword  = loword ^ ((temp ^ xormix2[i]) + itmpl * itmph); //loword mix
+        loword  = hihold;                           // old hiword is loword
+    }
+    return hiword;
+}
+
+static this()
+{
+    ulong s;
+
+    version(Win32)
+    {
+	QueryPerformanceCounter(&s);
+    }
+    else version(Unix)
+    {
+	// time.h
+	// sys/time.h
+
+	timeval tv;
+
+	if (gettimeofday(&tv, null))
+	{   // Some error happened - try time() instead
+	    s = time(null);
+	}
+	else
+	{
+	    s = cast(ulong)((cast(long)tv.tv_sec << 32) + tv.tv_usec);
+	}
+    }
+    else version(NoSystem)
+    {
+	// nothing
+    }
+    else
+	static assert(false);
+    rand_seed(cast(uint) s, cast(uint)(s >> 32));
+}
+
+
+unittest
+{
+    static uint results[10] =
+    [
+	0x8c0188cb,
+	0xb161200c,
+	0xfc904ac5,
+	0x2702e049,
+	0x9705a923,
+	0x1c139d89,
+	0x346b6d1f,
+	0xf8c33e32,
+	0xdb9fef76,
+	0xa97fcb3f
+    ];
+    int i;
+    uint seedsave = seed;
+    uint indexsave = index;
+
+    rand_seed(1234, 5678);
+    for (i = 0; i < 10; i++)
+    {	uint r = rand();
+	//printf("0x%x,\n", rand());
+	assert(r == results[i]);
+    }
+
+    seed = seedsave;
+    index = indexsave;
+}