[gegl] gegl_random: add manually unrolled 3-round version



commit 338d7d79dc4ea61a4c6052e812771d14ae0d5a84
Author: Øyvind Kolås <pippin gimp org>
Date:   Mon Jul 22 20:39:43 2013 +0100

    gegl_random: add manually unrolled 3-round version

 gegl/gegl-random.c |   42 ++++++++++++++++++++++++++++++------------
 1 files changed, 30 insertions(+), 12 deletions(-)
---
diff --git a/gegl/gegl-random.c b/gegl/gegl-random.c
index 347ff5f..2b0ccdc 100644
--- a/gegl/gegl-random.c
+++ b/gegl/gegl-random.c
@@ -26,8 +26,8 @@
  * The way it works is by xoring three lookup tables that are iterated
  * cyclically, each LUT has a prime number as a size, thus the combination
  * of the three values xored will have a period of prime1 * prime2 * prime3,
- * with the primes used this yields roughly 3TB of random data from ~300kb
- * of lookup data.
+ * with the primes used this yields roughly 3TB of random, non-repeating
+ * data from ~300kb of lookup data.
  *
  * The data for the LUTs is shared between different random seeds, it
  * is just the sizes of the LUTs that change, currently with 468 primes
@@ -122,20 +122,38 @@ _gegl_random_int (int seed,
   unsigned long idx = x * XPRIME + 
                       y * YPRIME * XPRIME + 
                       n * NPRIME * YPRIME * XPRIME;
-
-  gint64 ret = 0;
-  int i;
-  int offset = 0;
-  long * prime = &primes[(seed * 23) % ((G_N_ELEMENTS (primes) - 1))];
+#define ROUNDS 3
+    /* 3 rounds gives a reasonably high cycle for */
+                         /*   our synthesized larger random set. */
+  long * prime = &primes[seed % (G_N_ELEMENTS (primes) - 1 - ROUNDS)];
   random_init ();
+#define UNROLLED
+
+#ifdef UNROLLED
 
-  for (i = 0; i < 3; i++) /* 3 rounds gives a reasonably high cycle for */
-    {                     /*   our synthesized larger random set. */
+  {
+    int prime0 = prime[0],
+        prime1 = prime[1],
+        prime2 = prime[2];
+    return
+    random_data[idx % prime0] ^
+    random_data[prime0 + (idx % (prime1))] ^
+    random_data[prime0 + prime1 + (idx % (prime2))];
+  }
+#else
+  {
+    gint32 ret = 0;
+    int i;
+    int offset = 0;
+
+    for (i = 0; i < ROUNDS; i++) 
       ret ^= random_data[offset + (idx % (prime[i]))];
       offset += prime[i];
-    }
 
-  return ret;
+
+    return ret;
+  }
+#endif
 }
 
 guint32
@@ -157,7 +175,7 @@ gegl_random_int_range (int seed,
                        int min,
                        int max)
 {
-  guint64 ret = _gegl_random_int (seed, x, y, z, n);
+  guint32 ret = _gegl_random_int (seed, x, y, z, n);
   return (ret % (max-min)) + min;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]