diff -r -U3 ../Src5.1.7-orig/main.c ./main.c
--- ../Src5.1.7-orig/main.c	2008-02-18 14:30:42.000000000 -0500
+++ ./main.c	2009-03-05 22:22:20.000000000 -0500
@@ -83,7 +83,7 @@
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 #define CPP	"cpp"
 #else
-#define CPP	"/lib/cpp"	/* classic Unix systems */
+#define CPP	"/usr/bin/cpp"	/* classic Unix systems */
 #endif
 #endif
 #endif
diff -r -U3 ../Src5.1.7-orig/pangen1.h ./pangen1.h
--- ../Src5.1.7-orig/pangen1.h	2008-09-03 18:09:22.000000000 -0400
+++ ./pangen1.h	2009-03-16 15:36:19.000000000 -0400
@@ -30,30 +30,88 @@
 	"#ifdef BITSTATE",
 #ifndef POWOW
 	"	if (udmem)",
-	"	{	udmem *= 1024L*1024L;",
+	"	{	log2udmem = 0;",
+	"		while ((1L << log2udmem) < udmem) log2udmem++;",
+	"		if ((1L << log2udmem) == udmem) {",
+	"			ssize = 23 + log2udmem;",
+	"			udmem = 0;",
+	"			goto pow2;",
+	"		}",
+	"		addr_factor = (double)udmem / (double)(1L << log2udmem);",
+	"		udmem *= 1024L*1024L;",
+	"		log2udmem += 23;",
 	"	#if NCORE>1",
 	"		if (!readtrail)",
 	"		{	void init_SS(unsigned long);",
 	"			init_SS((unsigned long) udmem);",
 	"		} else",
 	"	#endif",
+	"#ifdef CLEARY",
+	"		CT = emalloc(udmem + 1);", /* one extra for final k=2 bloom */
+	"		bstore = bstore_cleary_mod;",
+	"		ct_bytes = udmem;",
+	"		set_cleary_fn_ptrs_64();",
+	"		addr_max = (ct_bytes >> 3) - 1;",
+	"		addr_bits = log2udmem - 6;",
+/*	"		set_cleary_fn_ptrs_32();",
+	"		addr_max = (ct_bytes >> 2) - 1;",
+	"		addr_bits = log2udmem - 5;", */
+/*	"		set_cleary_fn_ptrs_final();",
+	"		addr_max = ct_bytes - 1;",
+	"		addr_bits = log2udmem - 3;", */
+	"",
+	"		max_occ = (uintptr_t)((addr_max - 1) * max_occ_prop);",
+	"		occ = 0;",
+	"#endif",
+	"#ifdef BLOOM",
 	"		SS = (uchar *) emalloc(udmem);",
 	"		bstore = bstore_mod;",
-	"	} else",
+	"#endif",
+	"#if defined(BLOOM) && defined(CLEARY)",
+	"		bstore = bstore_both_mod;",
+	"#endif",
+	"	} else { ",
 #endif
+	"	    pow2:",
 	"	#if NCORE>1",
 	"		{ void init_SS(unsigned long);",
 	"		  init_SS(ONE_L<<(ssize-3));",
 	"		}",
 	"	#else",
+	"#ifdef CLEARY",
+	"		ct_bytes = (ONE_L<<(ssize-3));",
+	"		CT = emalloc(ct_bytes + 1);",
+	"		bstore = bstore_cleary_reg;",
+	"		set_cleary_fn_ptrs_64();",
+	"		addr_bits = ssize - 6;",
+/*	"		set_cleary_fn_ptrs_32();",
+	"		addr_bits = ssize - 5;",*/
+/*	"		set_cleary_fn_ptrs_final();",
+	"		addr_bits = ssize - 3;",*/
+	"",
+	"		addr_max = (ONE_L << addr_bits) - 1;",
+	"		max_occ = (uintptr_t)((addr_max - 1) * max_occ_prop);",
+	"		occ = 0;",
+	"#endif",
+	"#ifdef BLOOM",
 	"		SS = (uchar *) emalloc(ONE_L<<(ssize-3));",
+	"		bstore = bstore_reg;",
+	"#endif",
+	"#if defined(BLOOM) && defined(CLEARY)",
+	"		bstore = bstore_both_reg;",
+	"#endif",
 	"	#endif",
+	"	}",
 	"#else",	/* if not BITSTATE */
 	"	hinit();",
 	"#endif",
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
 	"	onstack_init();",
 	"#endif",
+	"#ifdef TABLESTACK",
+	"	TS = (tsptr_t *) emalloc((ts_mask + 1) * sizeof(tsptr_t));",
+	"	{ int i; for (i = 0; i <= ts_mask; i++) TS[i] = BEYONDMAXDEPTH; }",
+	"#endif",
 	"#if defined(CNTRSTACK) && !defined(BFS)",
 	"	LL = (uchar *) emalloc(ONE_L<<(ssize-3));",
 	"#endif",
@@ -82,11 +140,44 @@
 	"#endif",
 	"	do_the_search();",
 	"#ifdef BITSTATE",
-	"	if (--Nrun > 0 && HASH_CONST[++HASH_NR])",
-	"	{	printf(\"Run %%d:\\n\", HASH_NR);",
+	"	if (--Nrun > 0)",
+	"	{	printf(\"Run %%d:\\n\", ++HASH_NR);",
+	"#if defined(HASH64) || defined(WIN64)",
+	"		hashseed = 1234567891234567897LL;",
+	"#else",
+	"		hashseed = 1234567897;",
+	"#endif",
+	"		hashseed *= (HASH_NR + 1);",
 	"		wrap_stats();",
 	"		printf(\"\\n\");",
-	"		memset(SS, 0, ONE_L<<(ssize-3));",
+	"		if (udmem) {",
+	"#ifdef CLEARY",
+	"			memset(CT, 0, udmem);",
+	"			set_cleary_fn_ptrs_64();",
+	"			addr_bits = log2udmem - 6;",
+	"			addr_max = udmem >> 3;", /* already in bytes */
+	"			max_occ = (uintptr_t)((addr_max - 1) * max_occ_prop);",
+	"			occ = 0;",
+	"#endif",
+	"#ifdef BLOOM",
+	"			memset(SS, 0, udmem);",
+	"#endif",
+	"		} else {",
+	"#ifdef CLEARY",
+	"			memset(CT, 0, ONE_L<<(ssize-3));",
+	"			set_cleary_fn_ptrs_64();",
+	"			addr_bits = ssize - 6;",
+	"			addr_max = (ONE_L << addr_bits) - 1;",
+	"			max_occ = (uintptr_t)((addr_max - 1) * max_occ_prop);",
+	"			occ = 0;",
+	"#endif",
+	"#ifdef BLOOM",
+	"			memset(SS, 0, ONE_L<<(ssize-3));",
+	"#endif",
+	"		}",
+		"#ifdef TABLESTACK",
+	"		{ int i; for (i = 0; i <= ts_mask; i++) TS[i] = BEYONDMAXDEPTH; }",
+		"#endif",
 		"#ifdef CNTRSTACK",
 	"		memset(LL, 0, ONE_L<<(ssize-3));",
 		"#endif",
@@ -698,6 +789,47 @@
 	"#endif",
 	"",
 	"#ifdef BITSTATE",
+	"static inline double bf_rate(double m, double n, double k) {",
+	"	return pow(1.0 - exp(- n * k / m), k);",
+	"}",
+	"static double bf_exom(double m, double n, double k) {",
+	"	double v = 0.0;",
+	"	double exom = 0.0;",
+	"	for (; v - exom + 0.5 < n; v++) {",
+	"		exom += bf_rate(m,v,k);",
+	"	}",
+	"	return exom;",
+	"}",
+	"static double bf_exom_rough(double m, double n, double k) {",
+	"	return n * bf_rate(m,n,k) * 0.5;"
+	"}",
+	"static double compute_fp_exom(double m, double n) {",
+	"	if (n/m < 0.001) {",
+	"		/*over-approx:*/",
+	"		return n * n / 2.0 / (m - n);",
+	"	} else {",
+	"		return -n - m * log(1.0 - n/m);",
+	"	}",
+	"}",
+	"static double compute_bf_exom(double m, double n, double k) {",
+	"	if (k == 1.0) {",
+	"		return compute_fp_exom(m,n);",
+	"	}",
+	"	if (n < 8000.0) {",
+	"		return bf_exom(m, n, k);",
+	"	} else {",
+	"		double f = 4000.0 / n;",
+	"		return bf_exom(m * f, 4000.0, k) / f;",
+	"	}",
+	"}",
+	"static double compute_bf_exom_rough(double m, double n, double k) {",
+	"	if (k == 1.0) {",
+	"		return compute_fp_exom(m,n);",
+	"	}",
+	"	return bf_exom_rough(m, n, k);",
+	"}",
+	"",
+	"#ifdef BLOOM",
 #ifndef POWOW
 	"int",
 	"bstore_mod(char *v, int n)	/* hasharray size not a power of two */",
@@ -774,6 +906,970 @@
 	"	}",
 	"	return 0;",
 	"}",
+	"",
+	"double compute_ex_hashom() {",
+	"	double m;",
+	"	if (udmem) m = udmem * 8.0; else m = pow(2.0,ssize);",
+	"	return compute_bf_exom(m, nstates, hfns);",
+	"}",
+	"#endif", /* BLOOM */
+	"",
+	"#ifdef CLEARY",
+	"#define CLEARYDEBUG 0", /* 1 -> some good checks, 2 -> lots of checks */
+	"#ifdef CLEARYSTACK",
+	    "#define METABITS 3",
+	    "",
+	    "static uintptr_t last_cleary_addr;",
+	    "#define STACK_CLEARY_DEFS(bits,typ_t) \\",
+	    "uintptr_t start_occ_##bits = 0;\\",
+	    "uintptr_t final_occ_##bits = 0;\\",
+	    "int cstore_##bits(uintptr_t addr, uint64_t hashv);\\",
+	    "static inline void clear_remember_stack_bit_##bits(typ_t *vect, uintptr_t addr) {\\",
+	    "   last_cleary_addr = addr;\\",
+	    "	vect[last_cleary_addr] &= ~((typ_t)4);\\",
+	    "}\\",
+	    "static inline int get_remember_stack_bit_##bits(typ_t *vect, uintptr_t addr) {\\",
+	    "   last_cleary_addr = addr;\\",
+	    "	return (vect[addr] >> 2) & 1;\\",
+	    "}\\",
+	    "static inline int_fast16_t get_stack_bit_##bits(typ_t *vect, uintptr_t addr) {\\",
+	    "	return vect[addr] & 4;\\",
+	    "}\\",
+	    "static inline void put_stack_bit_##bits(typ_t *vect, uintptr_t addr, int_fast16_t val) {\\",
+	    "	vect[addr] = (vect[addr] & ~((typ_t)4)) | (typ_t)val;\\",
+	    "}\\",
+	    "static void onstack_put_##bits();\\",
+	    "static void onstack_zap_##bits();\\",
+	    "static void set_cleary_fn_ptrs_##bits() {\\",
+	    "   cstore = cstore_##bits;\\",
+	    "	start_occ_##bits = occ;\\",
+	    "	final_occ_##bits = occ;\\",
+	    "	onstack_put = onstack_put_##bits;\\",
+	    "	onstack_zap = onstack_zap_##bits;\\",
+	    "}\\",
+	    "",
+	    "#define STACK_CLEARY_DEFS2(bits,typ_t) \\",
+	    "static void onstack_put_##bits() {\\",
+	    "	typ_t *vect = (typ_t *)CT;\\",
+/*		"printf(\"Stack put %%lx\\n\", (long) K3);\\",*/
+/*		"printf(\"Stack put\\n\");\\",*/
+		"if (CLEARYDEBUG && K3 != trpt->k3) abort();\\",/**/
+	    "	vect[last_cleary_addr] |= (typ_t)4;\\",
+	    "}\\",
+	    "static void onstack_zap_##bits() {\\",
+	    "	uintptr_t addr;\\",
+	    "	uint64_t h;\\",
+	    "	int result;\\",
+	    "	uint32_t preh;\\",
+	    "	typ_t v1, v2; uintptr_t curEntry, curHome;\\",
+	    "	typ_t *vect = (typ_t *)CT;\\",
+/*	    "   K3 = trpt->k3;\\",*/
+/*		"printf(\"Stack zap %%lx\\n\", (long) trpt->k3);\\",*/
+/*		"printf(\"Stack zap\\n\");\\",*/
+	    "	if (udmem) {\\",
+	    "		preh = (uint32_t)((uint32_t)trpt->k3 * addr_factor) ^ (trpt->k1 & 0xfff);\\",
+	    "	} else {\\",
+	    "		preh = trpt->k3;\\",
+	    "	}\\",
+	    "	h = ((uint64_t) preh << 32) ^ (uint64_t) trpt->k2;\\",
+	    "	addr = (uintptr_t)(h >> (64 - addr_bits));\\",
+	    "	h = (h << addr_bits) ^ ((uint64_t) trpt->k1 >> (32 - addr_bits));\\",
+	    "	result = cstore(addr, h);\\",
+		"if (CLEARYDEBUG && result == 0) { printf(\"0 result\\n\"); abort(); }\\",
+	    	/* check if removal needed, before clearing stack bit */
+	    "	curEntry = last_cleary_addr;\\",
+	    "	if (!get_change_##bits(vect, curEntry)) {\\",
+	    "		v1 = get_entry_##bits(vect, curEntry);\\",
+	    "		v2 = get_entry_##bits(vect, curEntry-1);\\",
+	    "		if (v1 == v2) {\\",
+	    "			curEntry--;\\",
+	    "			goto remove;\\",
+	    "		}\\",
+	    "	}\\",
+	    "	if (curEntry < addr_max && get_occupied_##bits(vect, curEntry+1) && !get_change_##bits(vect, curEntry+1)) {\\",
+	    "		v1 = get_entry_##bits(vect, curEntry);\\",
+	    "		v2 = get_entry_##bits(vect, curEntry+1);\\",
+	    "		if (v1 == v2) goto remove;\\",
+	    "	}\\",
+	    "	vect[last_cleary_addr] &= ~((typ_t)4);\\",
+	    "	return;\\", /* removal not needed; done */
+	    "remove:\\",
+	    /* removing, and dup is to the right. */
+	    /*"printf(\"Removing entry @ %%u (home %%u)\\n\", (unsigned) curEntry, (unsigned) curHome);\\",*/
+	    /*"dump_cleary_table_##bits(vect, curEntry - 10, curEntry + 10);\\",*/
+	    "	curHome = addr;\\",
+	    "	if (curHome <= curEntry) {\\", /* shift left */
+	    "		if (get_change_##bits(vect, curEntry)) {\\",
+	    "if (CLEARYDEBUG && !get_occupied_##bits(vect, curEntry+1)) { printf(\"missing another element in chain\\n\"); abort(); }\\",
+	    "			copy_but_mapped_##bits(vect,curEntry+1,curEntry);\\",
+	    "if (CLEARYDEBUG && get_change_##bits(vect, curEntry)) { printf(\"missing another element in chain2\\n\"); abort(); }\\",
+	    "			set_change_##bits(vect,curEntry);\\",
+	    "			curEntry++;\\",
+	    "		}\\",
+	    "		for (;;) {\\",
+	    "			if (curEntry >= addr_max || !get_occupied_##bits(vect,curEntry+1)) goto clear_and_return;\\",
+	    "			if (get_change_##bits(vect,curEntry+1)) {\\",
+	    "				for (;;) {\\",
+	    "					curHome++;\\",
+	    "					if (curHome >= curEntry + 1) goto clear_and_return;\\",
+	    "					if (get_mapped_##bits(vect,curHome)) break;\\",
+	    "				}\\",
+	    "			}\\",
+	    "			copy_but_mapped_##bits(vect,curEntry+1,curEntry);\\", 
+	    "			curEntry++;\\",
+	    "		}\\",
+	    "	} else {\\", /* shift right */
+	    "		if (get_change_##bits(vect, curEntry)) {\\",
+	    "if (CLEARYDEBUG && !get_occupied_##bits(vect, curEntry+1)) { printf(\"missing another element in chain\\n\"); abort(); }\\",
+	    "if (CLEARYDEBUG && get_change_##bits(vect, curEntry+1)) { printf(\"missing another element in chain4\\n\"); abort(); }\\",
+	    "			set_change_##bits(vect,curEntry+1);\\",
+	    "			for (;;) {\\",
+	    "				curHome--;\\",
+	    "				if (curHome < curEntry) goto clear_and_return;\\",
+	    "				if (get_mapped_##bits(vect,curHome)) break;\\",
+	    "			}\\",
+	    "		}\\",
+	    "		for (;;) {\\",
+	    "			if (curEntry < 1 || !get_occupied_##bits(vect,curEntry-1)) goto clear_and_return;\\",
+	    "			copy_but_mapped_##bits(vect,curEntry-1,curEntry);\\", 
+	    "			curEntry--;\\",
+	    "			if (get_change_##bits(vect,curEntry)) {\\",
+	    "				for (;;) {\\",
+	    "					curHome--;\\",
+	    "					if (curHome < curEntry) goto clear_and_return;\\",
+	    "					if (get_mapped_##bits(vect,curHome)) break;\\",
+	    "				}\\",
+	    "			}\\",
+	    "		}\\",
+	    "	}\\",
+	    "clear_and_return:\\",
+	    "if (CLEARYDEBUG && get_mapped_##bits(vect, curEntry)) { printf(\"cleared mapped\\n\"); abort(); }\\",
+	    "	clear_all_##bits(vect, curEntry);\\",
+	    "}\\",
+	    "",
+	"#else",
+	    "#define METABITS 2",
+	    "",
+	    "#define STACK_CLEARY_DEFS(bits,typ_t) \\",
+	    "uintptr_t start_occ_##bits = 0;\\",
+	    "uintptr_t final_occ_##bits = 0;\\",
+	    "int cstore_##bits(uintptr_t addr, uint64_t hashv);\\",
+	    "static inline void clear_remember_stack_bit_##bits(typ_t *vect, uintptr_t addr) { }\\",
+	    "static inline int get_remember_stack_bit_##bits(typ_t *vect, uintptr_t addr) {\\",
+	    "	return 0;\\",
+	    "}\\",
+	    "static void set_cleary_fn_ptrs_##bits() {\\",
+	    "   cstore = cstore_##bits;\\",
+	    "	start_occ_##bits = occ;\\",
+	    "	final_occ_##bits = occ;\\",
+	    "}\\",
+	    "static inline int_fast16_t get_stack_bit_##bits(typ_t *vect, uintptr_t addr) {\\",
+	    "	return 0;\\",
+	    "}\\",
+	    "static inline void put_stack_bit_##bits(typ_t *vect, uintptr_t addr, int_fast16_t val) { }\\",
+	    "",
+	    "#define STACK_CLEARY_DEFS2(bits,typ_t) \\",
+	    "",
+	"#endif",
+	"",
+	"#define SIMPLE_CLEARY_DEFS(bits,typ_t) \\",
+	"static inline uintptr_t find_empty_##bits(typ_t *vect, uintptr_t start)\\",
+	"{\\",
+	"	uintptr_t left = start;\\",
+	"	uintptr_t right = start + 1;\\",
+	"	for (;;) {\\",
+	"		if (vect[left] == 0) return left;\\",
+	"		if (left == 0) goto right_only;\\",
+	"		left--;\\",
+	"		if (right > addr_max) goto left_only;\\",
+	"		if (vect[right] == 0) return right;\\",
+	"		right++;\\",
+	"	}\\",
+	"    left_only:\\",
+	"	while (vect[left] != 0) left--;\\",
+	"	return left;\\",
+	"    right_only:\\",
+	"	while (vect[right] != 0) right++;\\",
+	"	return right;\\",
+	"}\\",
+	"\\",
+	"static inline typ_t get_occupied_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	return vect[addr];\\",
+	"}\\",
+	"\\",
+	"static inline typ_t get_occupied2_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	return vect[addr] >> 1;\\", /* for use during conversion */
+	"}\\",
+	"\\",
+	"static inline int_fast16_t get_mapped_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	return (int_fast16_t)(vect[addr] & 1);\\",
+	"}\\",
+	"\\",
+	"static inline void set_mapped_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] |= 1;\\",
+	"}\\",
+	"\\",
+	"static inline void clear_mapped_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] &= ~((typ_t) 1);\\",
+	"}\\",
+	"\\",
+	"static inline int_fast16_t get_change_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	return (int_fast16_t)(vect[addr] & 2);\\",
+	"}\\",
+	"\\",
+	"static inline void set_change_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] |= 2;\\",
+	"}\\",
+	"\\",
+	"static inline void clear_change_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] &= ~((typ_t) 2);\\",
+	"}\\",
+	"\\",
+	"static inline typ_t get_entry_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	return vect[addr] >> METABITS;\\",
+	"}\\",
+	"\\",
+	"static inline void put_entry_##bits(typ_t *vect, uintptr_t addr, typ_t v) {\\",
+	"	vect[addr] = (v << METABITS) | (vect[addr] & (((typ_t)1 << METABITS) - 1));\\",
+	"}\\",
+	"\\",
+	"static inline void copy_but_mapped_##bits(typ_t *vect, uintptr_t src, uintptr_t dst) {\\",
+	"	vect[dst] = (vect[src] & ~((typ_t)1)) | (vect[dst] & 1);\\",
+	"}\\",
+	"\\",
+	"static inline void clear_but_mapped_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] &= ((typ_t) 1);\\",
+	"}\\",
+	"\\",
+	"static inline void clear_all_##bits(typ_t *vect, uintptr_t addr) {\\",
+	"	vect[addr] = ((typ_t) 0);\\",
+	"}\\",
+	"\\",
+	/* debugging: */
+	"void dump_cleary_table_##bits(typ_t *vect, uintptr_t start, uintptr_t after) {\\",
+	"	for (; start < after; start++) {\\",
+	"		printf(\"[%%lu] %%c%%c%%c \", start, get_mapped_##bits(vect,start) ? 'M' : '_', get_change_##bits(vect,start) ? 'C' : '_', get_stack_bit_##bits(vect,start) ? 'S' : (METABITS == 3 ? '_' : ' '));\\",
+	"		{ int i; typ_t val;\\",
+	"		  val = get_entry_##bits(vect, start);\\",
+	"		  for (i = bits - METABITS - 1; i >= 0; i--) {\\",
+	"			putchar((char)((val >> i) & 1) + '0');\\",
+	"		  }\\",
+	"		}\\",
+	"		putchar('\\n');\\",
+	"	}\\",
+	"}\\",
+	/* end of debugging */
+	"\\",
+	"int cstore_##bits(uintptr_t addr, uint64_t hashv) {\\",
+	"	uintptr_t emptyAddr;\\",
+	"	typ_t *vect = (typ_t *)CT;\\",
+	"	typ_t h = (typ_t)(hashv >> (64 - bits + METABITS));\\", /* clear bottom two bits for metadata */
+	"\\",
+/*	"printf(\"Cstore %%llx @ %%lx\\n\", (long long) hashv, (long)addr);\\",*/
+	"	emptyAddr = find_empty_##bits(vect, addr);\\",
+	"	if (emptyAddr > addr) {\\",
+	"		int keepChangeBit;\\",
+	"		uintptr_t curAddr = emptyAddr;\\",
+	"		uintptr_t curHomeAddr = emptyAddr;\\",
+	"		if (get_mapped_##bits(vect, addr)) {\\",
+	"\\",			/* have to search before we commit to making room */
+	"			if (curHomeAddr > addr) {\\",
+	"				curHomeAddr++;\\",
+	"				for (;;) {\\",
+	"					do {\\",
+	"						curHomeAddr--;\\",
+	"					} while (curHomeAddr > addr && !get_mapped_##bits(vect,curHomeAddr));\\",
+	"					if (curHomeAddr == addr) break;\\",
+	"					do {\\",
+	"						curAddr--;\\",
+	"					} while (!get_change_##bits(vect,curAddr));\\",
+	"				}\\",
+	"			}\\", /* that got us to immediately *after* the chain we're interested in */
+	"			for (;;) {\\", /* now we can search backward through the chain */
+	"				typ_t v;\\",
+	"				v = get_entry_##bits(vect, curAddr - 1);\\",
+	"				if (h > v) {\\",
+	"					keepChangeBit = 0;  break;\\",
+	"				} else if (h == v) {\\",
+	"					return 1 + get_remember_stack_bit_##bits(vect, curAddr - 1);\\",
+	"				}\\",
+	"\\",				/* keep searching */
+	"				curAddr--;\\",
+	"				if (get_change_##bits(vect, curAddr)) {\\",
+	"					keepChangeBit = 1;  break;\\",
+	"				}\\",
+	"			}\\",
+	"\\",			/* if we get here, not found */
+	"			while (emptyAddr > curAddr) {\\",
+	"				copy_but_mapped_##bits(vect, emptyAddr - 1, emptyAddr);\\",
+	"				emptyAddr--;\\",
+	"			}\\",
+	"			if (keepChangeBit) {\\",
+	"				clear_change_##bits(vect, curAddr+1);\\",
+	"			} else {\\",
+	"				clear_change_##bits(vect, curAddr);\\",
+	"			}\\",
+	"			put_entry_##bits(vect, curAddr, h);\\",
+	"			clear_remember_stack_bit_##bits(vect, curAddr);\\",
+	"			final_occ_##bits++; occ++;  return 0;\\",
+	"		} else {\\",  /* mapped bit not set */
+	"\\",			/* we know it's not there, so we can start shifting */
+	"			if (curHomeAddr > addr) {\\",
+	"				curHomeAddr++;\\",
+	"				for (;;) {\\",
+	"					do {\\",
+	"						curHomeAddr--;\\",
+	"					} while (curHomeAddr > addr && !get_mapped_##bits(vect, curHomeAddr));\\",
+	"					if (curHomeAddr == addr) break;\\",
+	"					do {\\",
+	"						copy_but_mapped_##bits(vect, curAddr-1, curAddr);\\",
+	"						curAddr--;\\",
+	"					} while (!get_change_##bits(vect, curAddr));\\",
+	"				}\\",
+	"			}\\",
+	"			set_mapped_##bits(vect, addr);\\",
+	"			set_change_##bits(vect, curAddr);\\",
+	"			put_entry_##bits(vect, curAddr, h);\\",
+	"			clear_remember_stack_bit_##bits(vect, curAddr);\\",
+	"			final_occ_##bits++; occ++; return 0;\\",
+	"		}\\",
+	"	} else if (emptyAddr < addr) {\\",
+	"		int keepChangeBit;\\",
+	"		uintptr_t curAddr = emptyAddr;\\",
+	"		uintptr_t curHomeAddr = emptyAddr;\\",
+	"		if (get_mapped_##bits(vect, addr)) {\\",
+	"\\",			/* have to search before we commit to making room */
+	"			for (;;) {\\",
+	"				do {\\",
+	"					curHomeAddr++;\\",
+	"				} while (curHomeAddr < addr && !get_mapped_##bits(vect, curHomeAddr));\\",
+	"				do {\\",
+	"					curAddr++;\\",
+	"				} while (!get_change_##bits(vect, curAddr));\\",
+	"				if (curHomeAddr == addr) break;\\",
+	"			}\\", /* that got us to the beginning of the right chain */
+	"			for (;;) {\\", /* now we search through that chain */
+	"				typ_t v;\\",
+	"				v = get_entry_##bits(vect, curAddr);\\",
+	"				if (h < v) {\\",
+	"					keepChangeBit = 0;  break;\\",
+	"				} else if (h == v) {\\",
+	"					return 1 + get_remember_stack_bit_##bits(vect, curAddr);\\",
+	"				}\\",
+	"\\",				/* keep searching */
+	"				curAddr++;\\",
+	"				if (curAddr > addr_max || get_change_##bits(vect, curAddr) || !get_occupied_##bits(vect, curAddr)) {\\",
+	"					keepChangeBit = 1;  break;\\",
+	"				}\\",
+	"			}\\",
+	"\\",			/* if we get here, not found */
+	"			while (emptyAddr + 1 < curAddr) {\\",
+	"				copy_but_mapped_##bits(vect, emptyAddr + 1, emptyAddr);\\",
+	"				emptyAddr++;\\",
+	"			}\\",
+	"			if (!keepChangeBit) {\\",
+	"				if (get_change_##bits(vect, curAddr)) {\\",
+	"					set_change_##bits(vect, emptyAddr);\\",
+	"				} else {\\",
+	"					clear_change_##bits(vect, emptyAddr);\\",
+	"				}\\",
+	"				clear_change_##bits(vect, curAddr);\\",
+	"			} else {\\",
+	"				clear_change_##bits(vect, emptyAddr);\\",
+	"			}\\",
+	"			put_entry_##bits(vect, emptyAddr, h);\\",
+	"			clear_remember_stack_bit_##bits(vect, emptyAddr);\\",
+	"			final_occ_##bits++; occ++; return 0;\\",
+	"		} else {\\", /* mapped bit not set */
+	"\\",			/* go ahead and start shifting */
+	"			for (;;) {\\",
+	"				do {\\",
+	"					curHomeAddr++;\\",
+	"				} while (curHomeAddr < addr && !get_mapped_##bits(vect, curHomeAddr));\\",
+	"				if (curHomeAddr == addr) break;\\",
+	"				do {\\",
+	"					copy_but_mapped_##bits(vect, curAddr + 1, curAddr);\\",
+	"					curAddr++;\\",
+	"				} while (curAddr + 1 <= addr_max && !get_change_##bits(vect, curAddr + 1) && get_occupied_##bits(vect, curAddr + 1));\\",
+	"			}\\",
+	"			set_mapped_##bits(vect, addr);\\",
+	"			set_change_##bits(vect, curAddr);\\",
+	"			put_entry_##bits(vect, curAddr, h);\\",
+	"			clear_remember_stack_bit_##bits(vect, curAddr);\\",
+	"			final_occ_##bits++; occ++; return 0;\\",
+	"		}\\",
+	"	} else {\\", /* emptyAddr == addr */
+	"		set_mapped_##bits(vect, addr);\\",
+	"		set_change_##bits(vect, addr);\\",
+	"		put_entry_##bits(vect, addr, h);\\",
+	"		clear_remember_stack_bit_##bits(vect, addr);\\", /* needed to save location */
+	"		final_occ_##bits++; occ++; return 0;\\",
+	"	}\\",
+	"}",
+	"",
+	"",
+	"#define CLEARY_CCONVERT_DEF(frombits,tobits,fromtyp_t,totyp_t) \\",
+	"void cconvert_##frombits##_##tobits() {\\",
+	"	fromtyp_t *fromvect = (fromtyp_t *)CT;\\",
+	"	totyp_t *tovect = (totyp_t *)CT;\\",
+	"	uintptr_t colldup = 0;\\",
+	"	uintptr_t stackdup = 0;\\",
+	"	uintptr_t topAddr;\\",
+	"	uintptr_t curEntry;\\",
+	"	uintptr_t curHome;\\",
+	"	uintptr_t pivotAddr;\\",
+	"	uintptr_t newEntry, newHome, prevNewHome;\\",
+	"	fromtyp_t fromv;\\",
+	"	totyp_t tov, prevv;\\",
+	"	int_fast16_t highbit;\\",
+	"	int_fast16_t changebit;\\",
+	"	int_fast16_t stackbit;\\",
+	"	const totyp_t tov_mask = (totyp_t)((totyp_t) 0 - (totyp_t) 1) >> METABITS;\\",
+	/*"	printf(\"tov_mask = %%u\\n\", (unsigned)tov_mask);\\",*/
+	/*"	dump_cleary_table_##frombits(fromvect, 0, addr_max+1);\\",*/
+	"	for (topAddr = 0; topAddr <= addr_max;) {\\",
+	"		if (!get_occupied_##frombits(fromvect, topAddr)) {\\",
+	"			topAddr++;\\",
+	"			continue;\\",
+	"		}\\",
+	"if (CLEARYDEBUG > 1 && !get_change_##frombits(fromvect, topAddr)) { printf(\"cconvert A\\n\"); abort(); }\\",
+	"		curEntry = topAddr; curHome = topAddr;\\",
+	"		for (;;) {\\",
+	"			while (!get_mapped_##frombits(fromvect, curHome)) {\\",
+	"				curHome++;\\",
+	"if (CLEARYDEBUG && curHome > addr_max) { printf(\"cconvert B\\n\"); abort(); }\\",
+	"			}\\",
+	"			\\", /* here home matches entry, start of chain*/
+	"			for (;;) {\\",
+	"				if (curEntry == curHome) goto pivot_found;\\",
+	"				\\", /* curEntry < curHome */
+	"				curEntry++;\\",
+	"				if (get_change_##frombits(fromvect, curEntry)) break;\\",
+	"if (CLEARYDEBUG > 1 && !get_occupied2_##frombits(fromvect, curEntry)) { printf(\"cconvert C\\n\"); abort(); }\\",
+	"			}\\",
+	"			curHome++;\\",
+	"if (CLEARYDEBUG && curHome > addr_max) { printf(\"cconvert D\\n\"); abort(); }\\",
+	"		}\\",
+	"	    pivot_found:\\",
+	"		pivotAddr = curEntry;\\",
+	"		curHome = pivotAddr;\\",
+	"		fromv = get_entry_##frombits(fromvect, curEntry);\\",
+	"		stackbit = get_stack_bit_##frombits(fromvect, curEntry);\\",
+	"		changebit = get_change_##frombits(fromvect, curEntry);\\",
+	"		highbit = (fromv >> (frombits - (METABITS+1)));\\",
+	"		clear_all_##frombits(fromvect, curEntry);\\",
+	"		newHome = (curHome << 1) + highbit;\\",
+	"		newEntry = newHome;\\",
+	"		tov = (fromv >> (tobits - 1)) & tov_mask;\\",
+	"if (CLEARYDEBUG > 1 && get_mapped_##tobits(tovect, newHome)) { printf(\"cconvert E\\n\"); abort(); }\\",
+	"		set_mapped_##tobits(tovect, newHome);\\",
+	"if (CLEARYDEBUG > 1 && get_occupied2_##tobits(tovect, newEntry)) { printf(\"cconvert F\\n\"); abort(); }\\",
+	"		put_entry_##tobits(tovect, newEntry, tov);\\",
+	"		put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"		for (;;) {\\",
+	"			prevv = tov; prevNewHome = newHome;\\",
+	"			if (changebit) {\\",
+	"				if (curEntry == topAddr) {\\",
+	"if (CLEARYDEBUG > 1 && get_change_##tobits(tovect, newEntry)) { printf(\"cconvert G\\n\"); abort(); }\\",
+	"					set_change_##tobits(tovect, newEntry);\\",
+	"					break;\\",
+	"				}\\",
+	"				do curHome--; while (!get_mapped_##frombits(fromvect, curHome));\\",
+	"				clear_mapped_##frombits(fromvect, curHome);\\",
+	"			}\\",
+	"			curEntry--; newEntry--;\\",
+	"if (CLEARYDEBUG > 1 && curHome <= curEntry) { printf(\"cconvert H\\n\"); abort(); }\\",
+	"			fromv = get_entry_##frombits(fromvect, curEntry);\\",
+	"			stackbit = get_stack_bit_##frombits(fromvect, curEntry);\\",
+	"			changebit = get_change_##frombits(fromvect, curEntry);\\",
+	"			highbit = (fromv >> (frombits - (METABITS+1)));\\",
+	"if (CLEARYDEBUG > 1 && highbit > 1) { printf(\"cconvert I\\n\"); abort(); }\\",
+	"			clear_but_mapped_##frombits(fromvect, curEntry);\\",
+	"			newHome = (curHome << 1) + highbit;\\",
+	"			tov = (fromv >> (tobits - 1)) & tov_mask;\\",
+	"			if (prevNewHome != newHome) {\\",
+	"if (CLEARYDEBUG > 1 && get_change_##tobits(tovect, newEntry+1)) { printf(\"cconvert K\\n\"); abort(); }\\",
+	"				set_change_##tobits(tovect, newEntry+1);\\",
+	"				if (newHome < newEntry) newEntry = newHome;\\",
+	"if (CLEARYDEBUG > 1 && get_mapped_##tobits(tovect, newHome)) { printf(\"cconvert L\\n\"); abort(); }\\",
+	"				set_mapped_##tobits(tovect, newHome);\\",
+	"if (CLEARYDEBUG > 1 && get_occupied2_##tobits(tovect, newEntry)) { printf(\"cconvert M\\n\"); abort(); }\\",
+	"				put_entry_##tobits(tovect, newEntry, tov);\\",
+	"				put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"			} else if (tov == prevv) {\\",
+	"				if (stackbit) {\\",
+	"					if (get_stack_bit_##tobits(tovect, newEntry+1)) {\\",
+	"						stackdup++;\\",
+	"						put_entry_##tobits(tovect, newEntry, tov);\\",
+	"						put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"					} else {\\",
+	"						newEntry++;\\",
+	"						put_stack_bit_##tobits(tovect,newEntry,stackbit);\\",
+	"						occ--;\\",
+	"						colldup++;\\",
+	"					}\\",
+	"				} else {\\",
+	"					newEntry++;\\",
+	"					occ--;\\",
+	"					colldup++;\\",
+	"				}\\",
+	"			} else {\\",
+	"if (CLEARYDEBUG > 1 && get_occupied2_##tobits(tovect, newEntry)) { printf(\"cconvert N\\n\"); abort(); }\\",
+	"				put_entry_##tobits(tovect, newEntry, tov);\\",
+	"				put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"			}\\",
+	"		}\\",
+	"		curEntry = pivotAddr + 1; curHome = pivotAddr;\\",
+	"		if (curEntry > addr_max || !get_occupied_##frombits(fromvect, curEntry)) goto done_with_top;\\",
+	"		newEntry = (pivotAddr << 1) + 1;\\",
+	"		if (get_occupied_##tobits(tovect, newEntry)) newEntry++;\\",
+	"		newHome = newEntry - 1;  tov = get_entry_##tobits(tovect, newEntry - 1);\\",
+/*	"printf(\"Start %%d %%d\\n\", (int)newHome, (int)tov);\\",*/
+	"		for (;;) {\\",
+	"			changebit = get_change_##frombits(fromvect, curEntry);\\",
+	"			if (changebit) {\\",
+	"				for (;;) {\\",
+	"					curHome++;\\",
+	"					if (curHome == curEntry) goto done_with_top;\\",
+	"					if (get_mapped_##frombits(fromvect, curHome)) break;\\",
+	"				}\\",
+	"if (CLEARYDEBUG && curHome >= curEntry) { printf(\"cconvert O\\n\"); abort(); }\\",
+	"				clear_mapped_##frombits(fromvect, curHome);\\",
+	"			}\\",
+	"			prevv = tov; prevNewHome = newHome;\\",
+	"			fromv = get_entry_##frombits(fromvect, curEntry);\\",
+/*	"printf(\"@ %%d\\n\", (int)curEntry);\\",*/
+/*	"printf(\"@ %%d is %%d\\n\", (int)curEntry, (int)fromv);\\",*/
+	"			stackbit = get_stack_bit_##frombits(fromvect, curEntry);\\",
+	"			highbit = (fromv >> (frombits - (METABITS+1)));\\",
+	"			clear_but_mapped_##frombits(fromvect, curEntry);\\",
+	"			tov = (fromv >> (tobits - 1)) & tov_mask;\\",
+	"			newHome = (curHome << 1) + highbit;\\",
+/*	"printf(\"next  %%d %%d (%%d %%d)\\n\", (int)newHome, (int)tov, (int)curEntry, (int) curHome);\\",*/
+	"			if (newHome != prevNewHome) {\\",
+	"				if (newHome > newEntry) newEntry = newHome;\\",
+	"if (CLEARYDEBUG > 1 && get_occupied2_##tobits(tovect, newEntry)) { printf(\"cconvert P\\n\"); abort(); }\\",
+	"if (CLEARYDEBUG > 1 && get_change_##tobits(tovect, newEntry)) { printf(\"cconvert Q\\n\"); abort(); }\\",
+	"				set_change_##tobits(tovect, newEntry);\\",
+	"if (CLEARYDEBUG > 1 && get_mapped_##tobits(tovect, newHome)) { printf(\"cconvert R\\n\"); abort(); }\\",
+	"				set_mapped_##tobits(tovect, newHome);\\",
+	"				put_entry_##tobits(tovect, newEntry, tov);\\",
+	"				put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"			} else if (tov == prevv) {\\",
+	"				if (stackbit) {\\",
+	"					if (get_stack_bit_##tobits(tovect, newEntry - 1)) {\\",
+	"						stackdup++;\\",
+	"						put_entry_##tobits(tovect, newEntry, tov);\\",
+	"						put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"					} else {\\",
+	"						newEntry--;\\",
+	"						put_stack_bit_##tobits(tovect,newEntry,stackbit);\\",
+	"						occ--;\\",
+	"						colldup++;\\",
+	"					}\\",
+	"				} else {\\",
+	"					newEntry--;\\",
+	"					occ--;\\",
+	"					colldup++;\\",
+	"				}\\",
+	"			} else {\\",
+	"if (CLEARYDEBUG > 1 && get_occupied2_##tobits(tovect, newEntry)) { printf(\"cconvert S\\n\"); abort(); }\\",
+	"if (CLEARYDEBUG > 1 && get_change_##tobits(tovect, newEntry)) { printf(\"cconvert T\\n\"); abort(); }\\",
+	"				put_entry_##tobits(tovect, newEntry, tov);\\",
+	"				put_stack_bit_##tobits(tovect, newEntry, stackbit);\\",
+	"			}\\",
+	"			curEntry++; newEntry++;\\",
+	"			if (curEntry > addr_max || !get_occupied_##frombits(fromvect, curEntry)) goto done_with_top;\\",
+	"		}\\",
+	"	    done_with_top:\\",
+	"\\", /* do some checking */
+	"if (CLEARYDEBUG > 1) {\\",
+	"newEntry = topAddr << 1;\\",
+	"newHome  = newEntry - 1;\\",
+	"while (newEntry < (curEntry << 1)) {\\",
+	"	while (newEntry < (curEntry << 1) && !get_occupied2_##tobits(tovect, newEntry)) newEntry++;\\",
+	"	if (newEntry >= (curEntry << 1)) break;\\",
+	"	if (!get_change_##tobits(tovect, newEntry)) { printf(\"cconvert U\\n\"); dump_cleary_table_##tobits(tovect, topAddr << 1, curEntry << 1); abort(); }\\",
+	"	do newHome++; while (newHome < (curEntry << 1) && !get_mapped_##tobits(tovect, newHome));\\",
+	"	if (newHome >= (curEntry << 1)) { printf(\"cconvert V\\n\"); abort(); }\\",
+	"	if (!get_occupied2_##tobits(tovect, newHome)) { printf(\"cconvert W\\n\"); abort(); }\\",
+	"	do newEntry++; while (newEntry < (curEntry << 1) && get_occupied_##tobits(tovect, newEntry) && !get_change_##tobits(tovect, newEntry));\\",
+	"}\\",
+	"do newHome++; while (newHome < (curEntry << 1) && !get_mapped_##tobits(tovect, newHome));\\",
+	"if (newHome < (curEntry << 1)) { printf(\"cconvert X\\n\"); abort(); }\\",
+	"}\\",
+	"\\", /* done with checking */
+	"		topAddr = curEntry;\\",
+	"	}\\",
+/*	"	printf(\"Occ = %%lu; newOcc = %%lu\\n\" , (long)occ, (long)newOcc);\\",*/
+	"	printf(\"New dups collapsed: %%lu  Not collapsed (both on stack): %%lu\\n\", (long)colldup, (long) stackdup);\\",
+	"	set_cleary_fn_ptrs_##tobits();\\",
+	"	addr_bits++;\\",
+	"	addr_max = (addr_max << 1) + 1;\\",
+	"	max_occ = (uintptr_t)((addr_max - 1) * max_occ_prop);\\",
+	"}",
+	"",
+	"STACK_CLEARY_DEFS(64,uint64_t)",
+	"STACK_CLEARY_DEFS(32,uint32_t)",
+	"STACK_CLEARY_DEFS(16,uint16_t)",
+	"STACK_CLEARY_DEFS( 8,uint8_t)",
+	"",
+	"SIMPLE_CLEARY_DEFS(64,uint64_t)",
+	"SIMPLE_CLEARY_DEFS(32,uint32_t)",
+	"SIMPLE_CLEARY_DEFS(16,uint16_t)",
+	"SIMPLE_CLEARY_DEFS( 8,uint8_t)",
+	"",
+	"CLEARY_CCONVERT_DEF(64,32,uint64_t,uint32_t)",
+	"CLEARY_CCONVERT_DEF(32,16,uint32_t,uint16_t)",
+	"CLEARY_CCONVERT_DEF(16, 8,uint16_t,uint8_t)",
+	"",
+	"STACK_CLEARY_DEFS2(64,uint64_t)",
+	"STACK_CLEARY_DEFS2(32,uint32_t)",
+	"STACK_CLEARY_DEFS2(16,uint16_t)",
+	"STACK_CLEARY_DEFS2( 8,uint8_t)",
+	"",
+	"",
+	"#ifdef CLEARYSTACK",
+	"#define FINALBITSPERBYTE 6",
+	"uint8_t bit1idxs[32] = { 0, 1, 2, 3, 4, 5,",
+	"                         0, 1, 2, 3, 4, 5,",
+	"                         0, 1, 2, 3, 4, 5,",
+	"                         0, 1, 2, 3, 4, 5,",
+	"                         0, 1, 2, 3, 4, 5,",
+	"                         0, 1 };",
+	"uint8_t bit2idxs[32] = { 0, 0, 0, 0, 0,",
+	"                         1, 1, 1, 1, 1,",
+	"                         2, 2, 2, 2, 2, 2,",
+	"                         3, 3, 3, 3, 3, 3,",
+	"                         4, 4, 4, 4, 4,",
+	"                         5, 5, 5, 5, 5 };",
+	"#define GETBIT1IDX(v) (bit1idxs[v])",
+	"#define GETBIT2IDX(v) (bit2idxs[v])",
+	"#else",
+	"#define FINALBITSPERBYTE 8",
+	"#define GETBIT1IDX(v) ((v) & 7)",
+	"#define GETBIT2IDX(v) ((v) >> 3)",
+	"#endif",
+	"",
+	"uintptr_t start_occ_final = 0;",
+	"uintptr_t final_occ_final = 0;",
+	"",
+	"static inline void inc_sb_final(uint8_t *vect, uintptr_t addr) {",
+	"#ifdef CLEARYSTACK",
+	"if (CLEARYDEBUG > 1 && ((vect[addr] >> 6) & 3) == 3) printf(\"stack counter overflow @ %%lu\\n\", (unsigned long) addr);",
+	"	vect[addr] += 64;",
+	"#endif",
+	"}",
+	"static inline void dec_sb_final(uint8_t *vect, uintptr_t addr) {",
+	"#ifdef CLEARYSTACK",
+	"if (CLEARYDEBUG > 1 && ((vect[addr] >> 6) & 3) == 0) printf(\"stack counter underflow @ %%lu\\n\", (unsigned long) addr);",
+	"	vect[addr] -= 64;",
+	"#endif",
+	"}",
+	"static inline int_fast16_t get_sb_final(uint8_t *vect, uintptr_t addr) {",
+	"#ifdef CLEARYSTACK",
+	"	return ((vect[addr] >> 6) | (vect[addr] >> 7)) & 1;",
+	"#else",
+	"	return 0;",
+	"#endif",
+	"}",
+	"",
+	"#ifdef CLEARYSTACK",
+	"static void onstack_put_final() {",
+	"	uint8_t *vect = (uint8_t *)CT;",
+/*	"printf(\"Stack put %%lx\\n\", (long) K3);",*/
+/*	"printf(\"Stack put\\n\");",*/
+	"if (CLEARYDEBUG && K3 != trpt->k3) abort();",
+	"	inc_sb_final(vect,last_cleary_addr);",
+	"}",
+	"static void onstack_zap_final() {",
+	"	uintptr_t addr;",
+	"	uint64_t h;",
+	"	uint32_t preh;",
+	"	uint8_t *vect = (uint8_t *)CT;",
+/*	"printf(\"Stack zap %%lx\\n\", (long) trpt->k3);",*/
+/*	"printf(\"Stack zap\\n\");",*/
+	"	if (udmem) {",
+	"		preh = (uint32_t)((uint32_t)trpt->k3 * addr_factor) ^ (trpt->k1 & 0xfff);",
+	"	} else {",
+	"		preh = trpt->k3;",
+	"	}",
+	"	h = ((uint64_t) preh << 32) ^ (uint64_t) trpt->k2;",
+	"	addr = (uintptr_t)(h >> (64 - addr_bits));",
+	"	dec_sb_final(vect,addr);",
+	"if (CLEARYDEBUG && 0) {", /* broken? */
+	"		h = (h << addr_bits) ^ ((uint64_t) trpt->k1 >> (32 - addr_bits));",
+	"		preh = h >> (64 - 8 + METABITS);",
+	"		if (preh >= 32) { printf(\"Bad bitspre (zap) (%%u)\\n\", (unsigned) preh); abort(); }",
+	"		if (((vect[addr] >> GETBIT1IDX(preh)) & (vect[addr+1] >> GETBIT2IDX(preh)) & 1) == 0) { printf(\"0 result\\n\"); abort(); }",
+	"	}",
+	"}",
+	"#endif",
+	"",
+	"int cstore_final(uintptr_t addr, uint64_t hashv) {",
+	"	int_fast16_t bitspre, bit1;",
+	"#ifndef SINGLEBLOOMFINAL",
+	"	int_fast16_t bit2;",
+	"#endif",
+	"	uint8_t *vect = (uint8_t *)CT;",
+	"#ifdef CLEARYSTACK",
+	"	last_cleary_addr = addr;",
+	"#endif",
+	"	bitspre = hashv >> (64 - 8 + METABITS);",
+	"if (CLEARYDEBUG && (bitspre < 0 || bitspre >= 32)) { printf(\"Bad bitspre (cstore) (%%u)\\n\", (unsigned) bitspre); abort(); }",
+	"	bit1 = GETBIT1IDX(bitspre);",
+	"#ifndef SINGLEBLOOMFINAL",
+	"	bit2 = GETBIT2IDX(bitspre);",
+	"#endif",
+	"	int result = (vect[addr] >> bit1) &",
+	"#ifndef SINGLEBLOOMFINAL",
+	"		     (vect[addr+1] >> bit2) &",
+	"#endif",
+	"		     1;",
+	"	if (result) {",
+	"		return 1 + get_sb_final(vect, addr);",
+	"	} else {",
+	"		vect[addr] |= (1 << bit1);",
+	"#ifndef SINGLEBLOOMFINAL",
+	"		vect[addr+1] |= (1 << bit2);",
+	"#endif",
+	"		final_occ_final++;",
+	"		occ++;",
+	"		return 0;",
+	"	}",
+	"}",
+	"static void set_cleary_fn_ptrs_final() {",
+	"	cstore = cstore_final;",
+	"	start_occ_final = occ;",
+	"	final_occ_final = occ;",
+	"#ifdef CLEARYSTACK",
+	"	onstack_put = onstack_put_final;",
+	"	onstack_zap = onstack_zap_final;",
+	"#endif",
+	"}",
+	"",
+	"static void cconvert_8_final() {",
+	"	uint8_t *vect = (uint8_t *)CT;",
+	"	uintptr_t topAddr;",
+	"	uintptr_t curEntry, curHome;",
+	"	uintptr_t pivotAddr;",
+	"#ifndef SINGLEBLOOMFINAL",
+	"	uintptr_t prevHome;",
+	"	uint8_t nextByte;",
+	"	uint8_t postPivotByte;",
+	"	uint8_t prevTopByte;",
+	"#endif",
+	"	uint8_t v;",
+	"	int_fast16_t changebit;",
+	"	int_fast16_t stackbit;",
+	"	prevTopByte = 0;",
+	"	for (topAddr = 0; topAddr <= addr_max;) {",
+	"		if (!get_occupied_8(vect, topAddr)) {",
+	"#ifndef SINGLEBLOOMFINAL",
+	"			vect[topAddr] |= prevTopByte;",
+	"			prevTopByte = 0;",
+	"#endif",
+	"			topAddr++;",
+	"			continue;",
+	"		}",
+	"if (CLEARYDEBUG && !get_change_8(vect, topAddr)) { printf(\"cconvert a\\n\"); abort(); }",
+	"		curEntry = topAddr; curHome = topAddr;",
+	"		for (;;) {",
+	"			while (!get_mapped_8(vect, curHome)) {",
+	"				curHome++;",
+	"if (CLEARYDEBUG && !get_occupied2_8(vect, curHome)) {  printf(\"cconvert b\\n\"); abort(); }",
+	"			}",
+	"			", /* here home matches entry, start of chain*/
+	"			for (;;) {",
+	"				if (curEntry == curHome) goto pivot_found;",
+	"				", /* curEntry < curHome */
+	"				curEntry++;",
+	"				if (get_change_8(vect, curEntry)) break;",
+	"if (CLEARYDEBUG && !get_occupied2_8(vect, curEntry)) { printf(\"cconvert c\\n\"); abort(); }",
+	"			}",
+	"			curHome++;",
+	"if (CLEARYDEBUG && !get_occupied2_8(vect, curHome)) { printf(\"cconvert d\\n\"); abort(); }",
+	"		}",
+	"	    pivot_found:",
+	"		pivotAddr = curEntry;",
+	"		curHome = curEntry;",
+	"		clear_mapped_8(vect, curEntry);",
+	"#ifndef SINGLEBLOOMFINAL",
+	"		nextByte = 0;",
+	"#endif",
+	"		for (;;) {",
+	"			v = get_entry_8(vect, curEntry);",
+	"			stackbit = get_stack_bit_8(vect, curEntry);",
+	"			changebit = get_change_8(vect, curEntry);",
+	"			clear_but_mapped_8(vect, curEntry);",
+	"if (CLEARYDEBUG && v >= 32) { printf(\"Bad bitspre (cconvert) (%%u)\\n\", (unsigned) v); abort(); }",
+	"			vect[curHome] |= (1 << GETBIT1IDX(v));",
+	"#ifndef SINGLEBLOOMFINAL",
+	"			nextByte |= (1 << GETBIT2IDX(v));",
+	"#endif",
+	"			if (stackbit) inc_sb_final(vect, curHome);",
+	"			if (changebit) {",
+	"#ifndef SINGLEBLOOMFINAL",
+	"				if (curHome == pivotAddr) {",
+	"					postPivotByte = nextByte;",
+	"				} else {",
+	"					vect[curHome+1] |= nextByte;",
+	"				}",
+	"				nextByte = 0;",
+	"#endif",
+	"				if (curEntry == topAddr) {",
+	"					break;",
+	"				}",
+	"				do curHome--; while (!get_mapped_8(vect, curHome));",
+	"				clear_mapped_8(vect, curHome);",
+	"			}",
+	"else if (CLEARYDEBUG && curEntry == topAddr) { printf(\"e\\n\"); abort(); }",
+	"			curEntry--;",
+	"if (CLEARYDEBUG && curHome <= curEntry) { printf(\"f\\n\"); abort(); }",
+	"		}",
+	"		curEntry = pivotAddr + 1; curHome = pivotAddr;",
+	"#ifndef SINGLEBLOOMFINAL",
+	"		vect[topAddr] |= prevTopByte;",
+	"		nextByte = postPivotByte;",
+	"		prevHome = curHome;",
+	"#endif",
+	"		if (curEntry > addr_max || !get_occupied_8(vect, curEntry)) goto done_with_top;",
+	"		for (;;) {",
+	"			changebit = get_change_8(vect, curEntry);",
+	"			if (changebit) {",
+	"#ifndef SINGLEBLOOMFINAL",
+	"				prevHome = curHome;",
+	"#endif",
+	"				for (;;) {",
+	"					curHome++;",
+	"					if (curHome == curEntry) goto done_with_top;",
+	"					if (get_mapped_8(vect, curHome)) break;",
+	"				}",
+	"if (CLEARYDEBUG && curHome >= curEntry) { printf(\"g\\n\"); abort(); }",
+	"				clear_mapped_8(vect, curHome);",
+	"#ifndef SINGLEBLOOMFINAL",
+	"				vect[prevHome+1] |= nextByte;",
+	"				nextByte = 0;",
+	"#endif",
+	"			}",
+	"			stackbit = get_stack_bit_8(vect, curEntry);",
+	"			v = get_entry_8(vect, curEntry);",
+	"			clear_but_mapped_8(vect, curEntry);",
+	"if (CLEARYDEBUG && v >= 32) { printf(\"Bad bitspre (cconvert) (%%u)\\n\", (unsigned) v); abort(); }",
+	"			vect[curHome] |= (1 << GETBIT1IDX(v));",
+	"#ifndef SINGLEBLOOMFINAL",
+	"			nextByte |= (1 << GETBIT2IDX(v));",
+	"#endif",
+	"			if (stackbit) inc_sb_final(vect, curHome);",
+	"			curEntry++;",
+	"			if (curEntry > addr_max || !get_occupied_8(vect, curEntry)) goto done_with_top;",
+	"		}",
+	"	    done_with_top:",
+	"#ifndef SINGLEBLOOMFINAL",
+	"		if (prevHome + 1 == curEntry) {",
+	"			prevTopByte = nextByte;",
+	"		} else {",
+	"			vect[prevHome+1] |= nextByte;",
+	"			prevTopByte = 0;",
+	"		}",
+	"#endif",
+	"		topAddr = curEntry;",
+	"	}",
+	"	set_cleary_fn_ptrs_final();",
+		/* addr_bits and addr_max will stay the same */
+	"	occ = 0;", /* not tracked */
+	"	max_occ = addr_max * 8;", /* probably not used */
+	"}",
+	"",
+	"",
+	"void cconvert() {",
+	"	clock_t start_time, stop_time;",
+	"	struct tms start_tm, stop_tm;",
+	"	if (cstore == cstore_64) {",
+	"		start_time = times(&start_tm);",
+	"		printf(\"Converting from 64-bit to 32-bit Cleary...\\n\");",
+	"		cconvert_64_32();",
+	"		stop_time = times(&stop_tm);",
+	"		printf(\"... Done (%%g sec)\\n\",((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK)));",
+	"	} else if (cstore == cstore_32) {",
+	"		start_time = times(&start_tm);",
+	"		printf(\"Converting from 32-bit to 16-bit Cleary...\\n\");",
+	"		cconvert_32_16();",
+	"		stop_time = times(&stop_tm);",
+	"		printf(\"... Done (%%g sec)\\n\",((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK)));",
+	"	} else if (cstore == cstore_16) {",
+	"		start_time = times(&start_tm);",
+	"		printf(\"Converting from 16-bit to 8-bit Cleary...\\n\");",
+	"		cconvert_16_8();",
+	"		stop_time = times(&stop_tm);",
+	"		printf(\"... Done (%%g sec)\\n\",((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK)));",
+	"	} else if (cstore == cstore_8) {",
+	"		start_time = times(&start_tm);",
+	"#ifdef SINGLEBLOOMFINAL",
+	"		printf(\"Converting from 8-bit Cleary to single-bit Bloom...\\n\");",
+	"#else",
+	"		printf(\"Converting from 8-bit Cleary to two-bit Bloom...\\n\");",
+	"#endif",
+	"		cconvert_8_final();",
+	"		stop_time = times(&stop_tm);",
+	"		printf(\"... Done (%%g sec)\\n\",((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK)));",
+	"	}",
+	"}",
+	"",
+	"int bstore_cleary_mod(char *v, int n) {",
+	"	uintptr_t addr;",
+	"	uint32_t preh;",
+	"	uint64_t h;",
+	"	",
+	"	if (occ >= max_occ) {",
+	"		cconvert();",
+	"	}",
+	"	d_hash((uchar *) v, n); /* sets K1-K3 */",
+	"	preh = (uint32_t)((uint32_t)K3 * addr_factor) ^ (K1 & 0xfff);",
+	"	h = ((uint64_t) preh << 32) ^ (uint64_t) K2;",
+	"	addr = (uintptr_t)(h >> (64 - addr_bits));",
+	"	h = (h << addr_bits) ^ ((uint64_t) K1 >> (32 - addr_bits));",
+	"	return cstore(addr, h);",
+	"}",
+	"",
+	"int bstore_cleary_reg(char *v, int n) {",
+	"	uintptr_t addr;",
+	"	uint64_t h;",
+	"	",
+	"	if (occ >= max_occ) {",
+	"		cconvert();",
+	"	}",
+	"	d_hash((uchar *) v, n); /* sets K1-K3 */",
+	"	h = ((uint64_t) K3 << 32) ^ (uint64_t) K2;",
+	"	addr = (uintptr_t)(h >> (64 - addr_bits));",
+	"	h = (h << addr_bits) ^ ((uint64_t) K1 >> (32 - addr_bits));",
+	"	return cstore(addr, h);",
+	"}",
+	"",
+	"double compute_ex_hashom_cleary() {",
+	"	double exom = 0.0;",
+	"	double m;",
+	"	m = pow(2.0, 64 - METABITS) * (ct_bytes >> 3);",
+	"	exom += compute_fp_exom(m, final_occ_64) - compute_fp_exom(m, start_occ_64);",
+	"	m = pow(2.0, 32 - METABITS) * (ct_bytes >> 2);",
+	"	exom += compute_fp_exom(m, final_occ_32) - compute_fp_exom(m, start_occ_32);",
+	"	m = pow(2.0, 16 - METABITS) * (ct_bytes >> 1);",
+	"	exom += compute_fp_exom(m, final_occ_16) - compute_fp_exom(m, start_occ_16);",
+	"	m = pow(2.0, 8 - METABITS) * ct_bytes;",
+	"	exom += compute_fp_exom(m, final_occ_8) - compute_fp_exom(m, start_occ_8);",
+	"#ifndef SINGLEBLOOMFINAL",
+	/* fingerprint collisions in final BF: */
+	"	exom += compute_fp_exom(m, final_occ_final) - compute_fp_exom(m, start_occ_final);",
+	"	m = (double)FINALBITSPERBYTE * (double)ct_bytes;",
+	"	exom += compute_bf_exom_rough(m, final_occ_final, 2) - compute_bf_exom_rough(m, start_occ_final, 2);",
+	"#else",
+	"	m = (double)FINALBITSPERBYTE * (double)ct_bytes;",
+	"	exom += compute_bf_exom_rough(m, final_occ_final, 1) - compute_bf_exom_rough(m, start_occ_final, 1);",
+	"#endif",
+	"	return exom;",
+	"}",
+	"",
+	"#endif", /* CLEARY */
 	"#endif", /* BITSTATE */
 	"unsigned long TMODE = 0666; /* file permission bits for trail files */",
 	"",
@@ -2009,11 +3105,11 @@
 	"	enter_critical(GLOBAL_LOCK);	/* snapshot */",
 	"	printf(\"cpu%%d: \", core_id);",
 	"#endif",
-	"	printf(\"Depth= %%7ld States= %%8.3g \",",
+	"	printf(\"Depth= %%lu/%%7ld States= %%8.3g \",",
 	"#if NCORE>1",
 	"		(long) (nr_handoffs * z_handoff) +",
 	"#endif",
-	"		mreached, nstates);",
+	"		depth, mreached, nstates);",
 	"	printf(\"Transitions= %%8.3g \", nstates+truncs);",
 	"#ifdef MA",
 	"	printf(\"Nodes= %%7d \", nr_states);",
@@ -2114,6 +3210,49 @@
 	"}",
 	"#endif",
 	"",
+	"#ifdef TABLESTACK",
+	"static inline int onstack_now_table() {",
+	"	unsigned loc = trpt->k3 & ts_mask;",
+	"	loc = TS[loc];",
+	"	for (;;) {",
+	"		if (loc == BEYONDMAXDEPTH) return 0;",
+	/*"if (loc > maxdepth) abort();",*/
+	"		if (trail[loc].k2 == trpt->k2 && trail[loc].k3 == trpt->k3) return 1;",
+	"		loc = trail[loc].ts_next;",
+	"	}",
+	"}",
+	"static inline void onstack_put_table() {",
+	"	unsigned stateloc = depth;",
+	/*"if (stateloc != trpt - trail) abort();",*/
+	"	unsigned loc = trpt->k3 & ts_mask;",
+/*		"printf(\"Stack put %%lx\\n\", (long) trpt->k3);",*/
+	"	trpt->ts_next = TS[loc];",
+	"	TS[loc] = (tsptr_t) stateloc;",
+	"}",
+	"static inline void onstack_zap_table() {",
+	"	unsigned loc = trpt->k3 & ts_mask;",
+	/*"if (TS[loc] != depth) abort();",*/ /* it's FIFO! */
+/*		"printf(\"Stack zap %%lx\\n\", (long) trpt->k3);",*/
+	"	TS[loc] = trpt->ts_next;",
+	"}",
+	"#ifdef CNTRSTACK",
+	"static inline int onstack_now_both() {",
+	"	int tblresult, cntrresult;",
+	"	tblresult = onstack_now_table();",
+	"	cntrresult = onstack_now_cntr();",
+	"	if (tblresult && !cntrresult) stack_false_negatives++;",
+	"	else if (!tblresult && cntrresult) stack_false_positives++;",
+	"	return tblresult;",
+	"}",
+	"static inline void onstack_put_both() {",
+	"	onstack_put_cntr(); onstack_put_table();",
+	"}",
+	"static inline void onstack_zap_both() {",
+	"	onstack_zap_cntr(); onstack_zap_table();",
+	"}",
+	"#endif",
+	"#endif",
+	"",
 	"void",
 	"new_state(void)",
 	"{	Trans *t;",
@@ -2248,10 +3387,20 @@
 	"		if (!(trpt->tau&8)) /* if no atomic move */",
 	"		{",
 	"#ifdef BITSTATE",
-		"#ifdef CNTRSTACK",	/* -> bitstate, reduced, safety */
+		"#if defined(CNTRSTACK) || defined(TABLESTACK) || defined(CLEARYSTACK)",
 	"			II = bstore((char *)&now, vsize);",
+			"#ifdef CNTRSTACK",	/* -> bitstate, reduced, safety */
 	"			trpt->j6 = j1; trpt->j7 = j2;",
-	"			JJ = LL[j1] && LL[j2];",
+			"#endif",
+			"#ifdef TABLESTACK",
+	"			trpt->k2 = K2; trpt->k3 = K3;",
+			"#endif",
+			"#ifdef CLEARYSTACK",
+	"			trpt->k1 = K1; trpt->k2 = K2; trpt->k3 = K3;",
+	"			JJ = (II == 2) ? 1 : 0;",
+			"#else",
+	"			JJ = onstack_now();",
+			"#endif",
 		"#else",
 			"#ifdef FULLSTACK",
 	"			JJ = onstack_now();",		    /* sets j1 */
@@ -2430,7 +3579,7 @@
 	"#endif",
 	"			}",
 
-	"#if defined(FULLSTACK) || defined(CNTRSTACK)",
+	"#if defined(FULLSTACK) || defined(CNTRSTACK) || defined(TABLESTACK) || defined(CLEARYSTACK)",
 	"			onstack_put();",
 		"#ifdef DEBUG2",
 		"#if defined(FULLSTACK) && !defined(MA)",
@@ -3391,7 +4540,7 @@
 	"		}",
 	"#endif",
 "#ifndef MA",
-	"#if defined(FULLSTACK) || defined(CNTRSTACK)",
+	"#if defined(FULLSTACK) || defined(CNTRSTACK) || defined(TABLESTACK) || defined(CLEARYSTACK)",
 	"#ifdef VERI",
 	"		if (boq == -1",
 	"		&&  (((trpt->tau&4) && !(trpt->tau&128))",
@@ -3518,7 +4667,13 @@
 	"	else",
 	"	printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
 	"		(double)(1<<(ssize-8)) / (double) nstates * 256.0);",
+	"#ifdef BLOOM",
 	"       printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);",
+	"       printf(\"expected hash omissions (BF): %%g\\n\", compute_ex_hashom());",
+	"#endif",
+	"#ifdef CLEARY",
+	"       printf(\"expected hash omissions (CT): %%g\\n\", compute_ex_hashom_cleary());",
+	"#endif",
 	"	#if 0",
 #ifndef POWOW
 	"	if (udmem)",
@@ -3611,14 +4766,24 @@
 	"	printf(\"	  Restarted from checkpoint %%s.xpt\\n\", PanSource);",
 	"  #endif",
 	"#endif",
-	"#ifdef CHECK",
+	/*"#ifdef CHECK",*/
 	"  #ifdef FULLSTACK",
 	"	printf(\"	+ FullStack Matching\\n\");",
 	"  #endif",
+	"  #ifdef CLEARYSTACK",
+	"	printf(\"	+ ClearyStack Matching\\n\");",
+	"  #endif",
+	"  #ifdef TABLESTACK",
+	"	printf(\"	+ TableStack Matching\\n\");",
+	"  #endif",
 	"  #ifdef CNTRSTACK",
+	"  #ifdef TABLESTACK",
+	"	printf(\"	+ CntrStack Matching (%%u fp, %%u fn)\\n\", stack_false_positives, stack_false_negatives);",
+	"  #else",
 	"	printf(\"	+ CntrStack Matching\\n\");",
 	"  #endif",
-	"#endif",
+	"  #endif",
+	/*"#endif",*/
 	"#ifdef BITSTATE",
 	"	printf(\"\\nBit statespace search for:\\n\");",
 	"#else",
@@ -3730,10 +4895,13 @@
 #endif
 	"	nr3 = (double) (ONE_L<<(ssize-3));",
 			"#ifdef CNTRSTACK",
-	"	nr5 = (double) (ONE_L<<(ssize-3));",
+	"	nr5 += (double) (ONE_L<<(ssize-3));",
+			"#endif",
+			"#ifdef TABLESTACK",
+	"	nr5 += (double) ((ts_mask+1) * sizeof(tsptr_t));",
 			"#endif",
 			"#ifdef FULLSTACK",
-	"	nr5 = (double) (maxdepth*sizeof(struct H_el *));",
+	"	nr5 += (double) (maxdepth*sizeof(struct H_el *));",
 			"#endif",
 		"#endif",
 	"	nr4 = (double) (svmax * (sizeof(Svtack) + hmax))",
@@ -4005,7 +5173,7 @@
 	"		case 0: break;",
 	"	}	}",
 	"#if defined(HASH64) || defined(WIN64)",
-	"	b = HASH_CONST[HASH_NR];",
+	"	b = hashseed;",
 	"	c = 0x9e3779b97f4a7c13LL; /* arbitrary value */",
 	"	while (n >= 3)",
 	"	{	a += k[0];",
@@ -4024,7 +5192,7 @@
 	"	mix(a,b,c);",
 	"#else", /* 32 bit version: */
 	"	a = c = 0xdeadbeef + (n<<2);",
-	"	b = HASH_CONST[HASH_NR];",
+	"	b = hashseed;",
 	"	while (n > 3)",
 	"	{	a += k[0];",
 	"		b += k[1];",
@@ -4041,9 +5209,9 @@
 	"	}",
 	"	final(a,b,c);",
 	"#endif",
+	"	K1 = c; K2 = b; K3 = a;",
 	"	j1 = c&nmask; j3 = a&7;      /* 1st bit */",
 	"	j2 = b&nmask; j4 = (a>>3)&7; /* 2nd bit */",
-	"	K1 = c; K2 = b;",
 	"}",
 	"",
 	"void",
@@ -4173,9 +5341,6 @@
 	"main(int argc, char *argv[])",
 	"{	void to_compile(void);\n",
 	"	efd = stderr;	/* default */",
-	"#ifdef BITSTATE",
-	"	bstore = bstore_reg; /* default */",
-	"#endif",
 	"#if NCORE>1",
 	"	{	int i, j;",
 	"		strcpy(o_cmdline, \"\");",
@@ -4219,7 +5384,8 @@
 	"		case 'g': gui = 1; goto samething;",
 	"#endif",
 	"		case 'h': if (!argv[1][2]) usage(efd); else",
-	"			  HASH_NR = atoi(&argv[1][2])%%33; break;",
+	"			  HASH_NR = atoi(&argv[1][2]);",
+	"			  hashseed *= HASH_NR; break;",
 	"		case 'I': iterative = 2; every_error = 1; break;",
 	"		case 'i': iterative = 1; every_error = 1; break;",
 	"		case 'J': like_java = 1; break; /* Klaus Havelund */",
@@ -4249,6 +5415,12 @@
 #endif
 	"		case 'm': maxdepth = atoi(&argv[1][2]); break;",
 	"		case 'n': no_rck = 1; break;",
+	"#ifdef CLEARY",
+        "               case 'o': max_occ_prop = (double) atoi(&argv[1][2]) / 100.0;",
+        "                         if (max_occ_prop < 0.01) max_occ_prop = 0.01;",
+        "                         if (max_occ_prop > 0.99) max_occ_prop = 0.99;",
+        "                         break;",
+	"#endif",
 	"		case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]);",
 	"			  if (argv[2][0] != '-') /* check next arg */",
 	"			  {	trailfilename = argv[2];",
@@ -4363,7 +5535,18 @@
 	"	}",
 	"#endif",
 	"	omaxdepth = maxdepth;",
+	"#ifdef TABLESTACK",
+	"	if (maxdepth >= BEYONDMAXDEPTH) {",
+	"		fprintf(efd, \"error: maxdepth greater than TABLESTACK max of %%u\\n\", (unsigned) BEYONDMAXDEPTH-1);",
+	"		pan_exit(1);",
+	"	}",
+	"	ts_mask = 1;",
+	"	while (ts_mask < (maxdepth + (maxdepth >> 1))) ts_mask = (ts_mask << 1) + 1;",
+	"#endif",
 	"#ifdef BITSTATE",
+	"#ifdef CNTRSTACK",
+	"	if (!udmem) ssize--;", /* to account for memory usage by cbf */
+	"#endif",
 	"	if (WS == 4 && ssize > 34)",	/* 32-bit word size */
 	"	{	ssize = 34;",
 	"		fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);",
@@ -4485,7 +5668,7 @@
 	"#ifndef BITSTATE",
 	"	if (Nrun > 1) HASH_NR = Nrun - 1;",
 	"#endif",
-	"	if (Nrun < 1 || Nrun > 32)",
+	"	if (Nrun < 1)",
 	"	{	fprintf(efd, \"error: invalid arg for -R\\n\");",
 	"		usage(efd);",
 	"	}",
@@ -4541,6 +5724,18 @@
 	"#if defined(MA) && defined(REACH)",
 	"	#warning -DREACH is voided by -DMA",
 	"#endif",
+	"#if defined(FULLSTACK) && defined(CLEARYSTACK)",
+	"	#error cannot combine -DFULLSTACK and -DCLEARYSTACK",
+	"#endif",
+	"#if defined(TABLESTACK) && defined(CLEARYSTACK)",
+	"	#error cannot combine -DTABLESTACK and -DCLEARYSTACK",
+	"#endif",
+	"#if defined(CNTRSTACK) && defined(CLEARYSTACK)",
+	"	#error cannot combine -DCNTRSTACK and -DCLEARYSTACK",
+	"#endif",
+	"#if defined(FULLSTACK) && defined(TABLESTACK)",
+	"	#error cannot combine -DFULLSTACK and -DTABLESTACK",
+	"#endif",
 	"#if defined(FULLSTACK) && defined(CNTRSTACK)",
 	"	#error cannot combine -DFULLSTACK and -DCNTRSTACK",
 	"#endif",
diff -r -U3 ../Src5.1.7-orig/pangen2.h ./pangen2.h
--- ../Src5.1.7-orig/pangen2.h	2008-04-25 13:51:26.000000000 -0400
+++ ./pangen2.h	2009-03-08 23:44:16.000000000 -0400
@@ -31,6 +31,10 @@
 	"#include <stdio.h>",
 	"#include <signal.h>",
 	"#include <stdlib.h>",
+	"#include <stdint.h>",
+	"extern double pow(double, double);",
+	"extern double exp(double);",
+	"extern double log(double);",
 	"#include <stdarg.h>",
 	"#include <string.h>",
 	"#include <ctype.h>",
@@ -57,10 +61,48 @@
 
 static char *Preamble[] = {
 
+	"#ifdef TABLESTACK",
+	"#if TABLESTACK==16",
+	"typedef uint16_t tsptr_t;",
+	"#define BEYONDMAXDEPTH UINT16_MAX", /* for null ptr */
+	"#else",
+	"typedef uint32_t tsptr_t;",
+	"#define BEYONDMAXDEPTH UINT32_MAX", /* for null ptr */
+	"#endif",
+/*	"int onstack_now_table();",
+	"void onstack_put_table();",
+	"void onstack_zap_table();",*/
+	"#endif",
+	"#ifdef CNTRSTACK",
+	"#define onstack_now_cntr()	(LL[trpt->j6] && LL[trpt->j7])",
+	"#define onstack_put_cntr()	 LL[trpt->j6]++; LL[trpt->j7]++",
+	"#define onstack_zap_cntr()	 LL[trpt->j6]--; LL[trpt->j7]--",
+	"#endif",
 	"#ifdef CNTRSTACK",
-	"#define onstack_now()	(LL[trpt->j6] && LL[trpt->j7])",
-	"#define onstack_put()	 LL[trpt->j6]++; LL[trpt->j7]++",
-	"#define onstack_zap()	 LL[trpt->j6]--; LL[trpt->j7]--",
+	"#ifdef TABLESTACK",
+	"unsigned stack_false_positives = 0;",
+	"unsigned stack_false_negatives = 0;",
+/*	"int onstack_now_both();",
+	"void onstack_put_both();",
+	"void onstack_zap_both();",*/
+	"#define onstack_now() onstack_now_both()",
+	"#define onstack_put() onstack_put_both()",
+	"#define onstack_zap() onstack_zap_both()",
+	"#else",
+	"#define onstack_now() onstack_now_cntr()",
+	"#define onstack_put() onstack_put_cntr()",
+	"#define onstack_zap() onstack_zap_cntr()",
+	"#endif",
+	"#else",
+	"#ifdef TABLESTACK",
+	"#define onstack_now() onstack_now_table()",
+	"#define onstack_put() onstack_put_table()",
+	"#define onstack_zap() onstack_zap_table()",
+	"#endif",
+	"#endif",
+	"#ifdef CLEARYSTACK",
+	"void (*onstack_put)();",
+	"void (*onstack_zap)();",
 	"#endif",
 
 	"#if !defined(SAFETY) && !defined(NOCOMP)",
@@ -191,6 +233,13 @@
 	"#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS) || (NCORE>1)",
 	"	struct H_el *ostate;	/* pointer to stored state */",
 	"#endif",
+	"#ifdef TABLESTACK",
+	"	tsptr_t ts_next;  /* for linked list */",
+	"	uint32_t k2, k3;  /* to store hash value */",
+	"#endif",
+	"#ifdef CLEARYSTACK",
+	"	uint32_t k1, k2, k3;  /* to store hash value */",
+	"#endif",
 	/* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY, uses LL[] */
 	"#if defined(CNTRSTACK) && !defined(BFS)",
 	"	long	j6, j7;",
@@ -233,7 +282,25 @@
 	"char	*stackfile;",
  	"#endif",
 	"uchar	*SS, *LL;",
+	"#ifdef CLEARY",
+	"static void *CT;",
+	"static uintptr_t addr_bits;",
+	"static uintptr_t addr_max;",
+	"static uintptr_t ct_bytes;",
+	"static uintptr_t occ;",
+	"static uintptr_t max_occ;",
+	"static double max_occ_prop = 0.85;",
+	"#endif",
+	"#ifdef TABLESTACK",
+	"tsptr_t *TS;",
+	"uint32_t ts_mask;",
+	"#endif",
 	"uchar	HASH_NR = 0;",
+	"#if defined(HASH64) || defined(WIN64)",
+	"uint64_t hashseed = 1234567891234567897LL;",
+	"#else",
+	"uint32_t hashseed = 1234567897;",
+	"#endif",
 	"",
 	"double memcnt = (double) 0;",
 	"double memlim = (double) (1<<30); /* 1 GB */",
@@ -341,11 +408,13 @@
 	"static unsigned int hfns = 3;	/* new default */",
 	"#endif",
 	"static unsigned long j1;",
-	"static unsigned long K1, K2;",
+	"static uint32_t K1, K2, K3;",
 	"static unsigned long j2, j3, j4;",
 	"#ifdef BITSTATE",
 #ifndef POWOW
-	"static long udmem;",
+	"static double addr_factor;",
+	"static uintptr_t log2udmem;",
+	"static uintptr_t udmem;",
 #endif
 	"#endif",
 	"static long	A_depth = 0;",
@@ -369,11 +438,25 @@
 	"#endif\n",
 	"#ifdef BITSTATE",
 	"int (*bstore)(char *, int);",
+	"#ifdef BLOOM",
 	"int bstore_reg(char *, int);",
 #ifndef POWOW
 	"int bstore_mod(char *, int);",
 #endif
 	"#endif",
+	"#ifdef CLEARY",
+	"static void set_cleary_fn_ptrs_64();",
+	"static void set_cleary_fn_ptrs_32();",
+	"static void set_cleary_fn_ptrs_16();",
+	"static void set_cleary_fn_ptrs_8();",
+	"static void set_cleary_fn_ptrs_final();",
+	"static int (*cstore)(uintptr_t, uint64_t);",
+	"int bstore_cleary_reg(char *, int);",
+#ifndef POWOW
+	"int bstore_cleary_mod(char *, int);",
+#endif
+	"#endif",
+	"#endif",
 	"void active_procs(void);",
 	"void cleanup(void);",
 	"void do_the_search(void);",
diff -r -U3 ../Src5.1.7-orig/pangen3.h ./pangen3.h
--- ../Src5.1.7-orig/pangen3.h	2008-04-18 13:39:48.000000000 -0400
+++ ./pangen3.h	2009-03-03 16:17:59.000000000 -0500
@@ -64,6 +64,9 @@
 			"#define NOFAIR",
 		"#endif",
 	"#endif",
+	"#if (defined(CLEARY) || defined(BLOOM)) && !defined(BITSTATE)",
+	"#define BITSTATE",
+	"#endif",
 	"#ifdef NOREDUCE",
 		"#ifndef XUSAFE",
 		"#define XUSAFE",
@@ -73,8 +76,10 @@
 		"#endif",
 	"#else",
 		"#ifdef BITSTATE",
-			"#if defined(SAFETY) && !defined(HASH64)",
-				"#define CNTRSTACK",
+			"#ifdef SAFETY",
+				"#if !defined(CNTRSTACK) && !defined(TABLESTACK) && !defined(FULLSTACK) && !defined(CLEARYSTACK)",
+					"#error Please define either CNTRSTACK, TABLESTACK, FULLSTACK, or CLEARYSTACK",
+				"#endif",
 			"#else",
 				"#define FULLSTACK",
 			"#endif",
@@ -82,7 +87,24 @@
 			"#define FULLSTACK",
 		"#endif",
 	"#endif",
+	"#ifdef CLEARYSTACK",
+	"#ifndef CLEARY",
+	"#error CLEARYSTACK depends on CLEARY",
+	"#endif",
+	"#endif",
+	"#ifdef TABLESTACK",
+	"#ifdef SC",
+	"#error Cannot combine TABLESTACK and SC",
+	"#endif",
+	"#endif",
 	"#ifdef BITSTATE",
+		"#ifdef CLEARY",
+			"#if NCORE>1",
+			"#error Cleary table not yet supported for multicore",
+			"#endif",
+		"#else",
+			"#define BLOOM",
+		"#endif",
 		"#ifndef NOCOMP",
 		"#define NOCOMP",
 		"#endif",
