+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# define TARGET(c) ((c)->back_buf ? (c)->back_buf : \
+ (c)->pix_buf ? (c)->pix_buf : (c)->win)
+#else /* HAVE_DOUBLE_BUFFER_EXTENSION */
+# define TARGET(c) ((c)->pix_buf ? (c)->pix_buf : (c)->win)
+#endif /* !HAVE_DOUBLE_BUFFER_EXTENSION */
+
+#ifdef USE_FAST_SQRT_HACKISH
+/* Based loosely on code from Wikipedia:
+ * https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Approximations_that_depend_on_IEEE_representation
+ */
+
+/* FAST_SQRT_EXTRA_BITS = 3: Smallest useful value
+ * = 5/6: A little bit of banding, wave_height table is on par with regular
+ * sqrt() code.
+ * = 7: No apparent difference with original @ radius = 800.
+ * = 8: One more just to be comfortable.
+ */
+
+# define FAST_SQRT_EXTRA_BITS 8
+
+union int_float
+{
+ uint32_t i;
+ float f;
+};
+
+static unsigned fast_log2(unsigned x)
+{
+ union int_float u;
+ if(!x)
+ return x;
+ u.f = x;
+ return ((u.i - 0x3f800000) >> (23 - FAST_SQRT_EXTRA_BITS)) + 1;
+}
+
+static float fast_inv_log2(unsigned x)
+{
+ union int_float u;
+ if(!x)
+ return 0.0f;
+ u.i = ((x - 1) << (23 - FAST_SQRT_EXTRA_BITS)) + 0x3f800000;
+ return u.f;
+}
+
+#endif
+
+#ifdef USE_FAST_SQRT_BIGTABLE2
+
+/* I eyeballed these figures. They could be improved. - D.O. */
+
+# define FAST_SQRT_DISCARD_BITS1 4
+/* = 5: Dot in center is almost invisible at radius = 800. */
+/* = 4: Dot in center looks OK at radius = 50. */
+
+/* 156/2740/9029 */
+/* # define FAST_SQRT_DISCARD_BITS2 8 */
+/* # define FAST_SQRT_CUTOFF 64 * 64 */
+
+/* 156/2242/5386 */
+# define FAST_SQRT_DISCARD_BITS2 9
+# define FAST_SQRT_CUTOFF 128 * 128
+
+/*
+ * This is a little faster:
+ * 44.5 FPS, 19/5000/17578
+ *
+ * # define FAST_SQRT_DISCARD_BITS1 7
+ * # define FAST_SQRT_DISCARD_BITS2 7
+ * # define FAST_SQRT_CUTOFF 0
+ *
+ * For radius = 800, FAST_SQRT_DISCARD_BITS2 =
+ * = 9/10: Approximately the original table size, some banding near origins.
+ * = 7: wave_height is 20 KB, and just fits inside a 32K L1 cache.
+ * = 6: Nearly indistinguishable from original
+ */
+
+/*
+ FAST_TABLE(x) is equivalent to, but slightly faster than:
+ x < FAST_SQRT_CUTOFF ?
+ (x >> FAST_SQRT_DISCARD_BITS1) :
+ ((x - FAST_SQRT_CUTOFF) >> FAST_SQRT_DISCARD_BITS2) +
+ (FAST_SQRT_CUTOFF >> FAST_SQRT_DISCARD_BITS1);
+*/
+
+#define FAST_TABLE(x) \
+ ((x) < FAST_SQRT_CUTOFF ? \
+ ((x) >> FAST_SQRT_DISCARD_BITS1) : \
+ (((x) + \
+ ((FAST_SQRT_CUTOFF << (FAST_SQRT_DISCARD_BITS2 - \
+ FAST_SQRT_DISCARD_BITS1)) - FAST_SQRT_CUTOFF)) >> \
+ FAST_SQRT_DISCARD_BITS2))
+
+static double fast_inv_table(unsigned x)
+{
+ return x < (FAST_SQRT_CUTOFF >> FAST_SQRT_DISCARD_BITS1) ?
+ (x << FAST_SQRT_DISCARD_BITS1) :
+ ((x - (FAST_SQRT_CUTOFF >> FAST_SQRT_DISCARD_BITS1)) <<
+ FAST_SQRT_DISCARD_BITS2) + FAST_SQRT_CUTOFF;
+}
+
+#endif
+
+/* Also destroys c->row. */
+static void destroy_image(Display* dpy, struct inter_context* c)
+{
+#ifdef USE_XIMAGE
+ if(c->ximage) {
+# ifdef HAVE_XSHM_EXTENSION
+ if(c->use_shm) {
+ destroy_xshm_image(dpy, c->ximage, &c->shm_info);
+ } else
+# endif
+ {
+ /* Also frees c->ximage->data, which isn't allocated by XCreateImage. */
+ XDestroyImage(c->ximage);
+ }
+ }
+
+ free(c->row);
+#endif
+}
+
+static void inter_free(Display* dpy, struct inter_context* c)
+{
+#ifndef USE_XIMAGE
+ unsigned i;
+#endif
+
+ if(c->pix_buf)
+ XFreePixmap(dpy, c->pix_buf);
+
+ if(c->copy_gc)
+ XFreeGC(dpy, c->copy_gc);
+
+ destroy_image(dpy, c);
+
+ if(c->colors <= 2)
+ free(c->pal);
+ else
+ free_colors(c->screen, c->cmap, c->pal, c->colors);
+
+#ifndef USE_XIMAGE
+ for(i = 0; i != c->colors; ++i)
+ XFreeGC(dpy, c->gcs[i]);
+ free(c->gcs);
+#endif
+
+ free(c->wave_height);
+ free(c->source);
+}
+
+static void abort_no_mem(void)
+{
+ fprintf(stderr, "interference: %s\n", strerror(ENOMEM));
+ exit(1);
+}
+
+static void check_no_mem(Display* dpy, struct inter_context* c, void* ptr)
+{
+ if(!ptr) {
+ inter_free(dpy, c);
+ abort_no_mem();
+ }
+}