+
+/* A test harness for visualizing different random number generators.
+ This doesn't really belong in lcdscrub, but it was a convenient
+ place to put it.
+ */
+#if 0 /* mwc1616 */
+
+static unsigned long mwc1616_x = 1;
+static unsigned long mwc1616_y = 2;
+
+static void
+mwc1616_srand (unsigned long seed)
+{
+ mwc1616_x = seed | 1;
+ mwc1616_y = seed | 2;
+}
+
+static unsigned long
+mwc1616 (void)
+{
+ mwc1616_x = 18000 * (mwc1616_x & 0xFFFF) + (mwc1616_x >> 16);
+ mwc1616_y = 30903 * (mwc1616_y & 0xFFFF) + (mwc1616_y >> 16);
+ return (mwc1616_x << 16) + (mwc1616_y & 0xFFFF);
+}
+
+# undef random
+# undef srand
+# define srand mwc1616_srand
+# define random() ((unsigned int) (mwc1616() & (unsigned int) (~0)))
+
+
+#elif 0 /* xorshift128plus */
+
+
+static uint64_t xo_state0 = 1;
+static uint64_t xo_state1 = 2;
+
+static void
+xorshift128plus_srand (unsigned long seed)
+{
+ xo_state0 = seed | 1;
+ xo_state1 = seed | 2;
+}
+
+static uint64_t
+xorshift128plus (void)
+{
+ register uint64_t s1 = xo_state0;
+ register uint64_t s0 = xo_state1;
+ xo_state0 = s0;
+ s1 ^= s1 << 23;
+ s1 ^= s1 >> 17;
+ s1 ^= s0;
+ s1 ^= s0 >> 26;
+ xo_state1 = s1;
+ return s1;
+}
+
+# undef random
+# undef srand
+# define srand xorshift128plus_srand
+# define random() ((unsigned int) (xorshift128plus() & (unsigned int) (~0)))
+
+
+#else /* ya_random */
+# undef srand
+# define srand(n)
+
+#endif /* ya_random */
+
+
+
+/* If you see patterns in this image, the PRNG sucks.
+ */
+static void
+lcdscrub_random (struct state *st)
+{
+ unsigned long steps_per_frame = 3000000;
+ unsigned long segments = 0x8000; /* 2^15 */
+
+ if (! st->collisions)
+ {
+ struct timeval tp;
+# if GETTIMEOFDAY_TWO_ARGS
+ gettimeofday (&tp, 0);
+# else
+ gettimeofday (&tp);
+# endif
+ srand ((unsigned int) (tp.tv_sec ^ tp.tv_usec));
+
+ st->collisions =
+ XCreateImage (st->dpy, st->xgwa.visual, 1, XYPixmap,
+ 0, NULL, segments, segments, 8, 0);
+ if (! st->collisions) abort();
+ st->collisions->data = (char *)
+ calloc (segments, st->collisions->bytes_per_line); /* 128 MB */
+ if (! st->collisions->data) abort();
+ }
+
+ while (--steps_per_frame)
+ {
+ unsigned long x = random() & (segments-1);
+ unsigned long y = random() & (segments-1);
+ unsigned long p = XGetPixel (st->collisions, x, y) ? 0 : 1;
+ XPutPixel (st->collisions, x, y, p);
+ st->ncollisions += (p ? 1 : -1);
+ }
+
+ {
+ int w, h;
+ Pixmap p;
+ GC gc;
+
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+ w = st->xgwa.width;
+ h = st->xgwa.height;
+
+ p = XCreatePixmap (st->dpy, st->window, w, h, 1);
+ gc = XCreateGC (st->dpy, p, 0, 0);
+ XSetBackground (st->dpy, gc, 0);
+ XSetForeground (st->dpy, gc, 1);
+ XPutImage (st->dpy, p, gc, st->collisions, 0, 0, 0, 0, w, h);
+ XFreeGC (st->dpy, gc);
+
+ gc = st->fg;
+ XClearWindow (st->dpy, st->window);
+ XSetClipMask (st->dpy, gc, p);
+ XFillRectangle (st->dpy, st->window, gc, 0, 0, w, h);
+ XFreePixmap (st->dpy, p);
+ }
+
+ /*
+ fprintf(stderr, "%.2f\n", st->ncollisions / (float) (segments*segments));
+ */
+}
+
+