xref: /plan9/sys/src/cmd/5c/mul.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier /*
47dd7cddfSDavid du Colombier  * code sequences for multiply by constant.
57dd7cddfSDavid du Colombier  * [a-l][0-3]
67dd7cddfSDavid du Colombier  *	lsl	$(A-'a'),r0,r1
77dd7cddfSDavid du Colombier  * [+][0-7]
87dd7cddfSDavid du Colombier  *	add	r0,r1,r2
97dd7cddfSDavid du Colombier  * [-][0-7]
107dd7cddfSDavid du Colombier  *	sub	r0,r1,r2
117dd7cddfSDavid du Colombier  */
127dd7cddfSDavid du Colombier 
13*59cc4ca5SDavid du Colombier static  int	maxmulops = 3;	/* max # of ops to replace mul with */
147dd7cddfSDavid du Colombier static	int	multabp;
157dd7cddfSDavid du Colombier static	long	mulval;
167dd7cddfSDavid du Colombier static	char*	mulcp;
177dd7cddfSDavid du Colombier static	long	valmax;
187dd7cddfSDavid du Colombier static	int	shmax;
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier static int	docode(char *hp, char *cp, int r0, int r1);
217dd7cddfSDavid du Colombier static int	gen1(int len);
227dd7cddfSDavid du Colombier static int	gen2(int len, long r1);
237dd7cddfSDavid du Colombier static int	gen3(int len, long r0, long r1, int flag);
247dd7cddfSDavid du Colombier enum
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier 	SR1	= 1<<0,		/* r1 has been shifted */
277dd7cddfSDavid du Colombier 	SR0	= 1<<1,		/* r0 has been shifted */
287dd7cddfSDavid du Colombier 	UR1	= 1<<2,		/* r1 has not been used */
297dd7cddfSDavid du Colombier 	UR0	= 1<<3,		/* r0 has not been used */
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier Multab*
mulcon0(long v)337dd7cddfSDavid du Colombier mulcon0(long v)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier 	int a1, a2, g;
367dd7cddfSDavid du Colombier 	Multab *m, *m1;
377dd7cddfSDavid du Colombier 	char hint[10];
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	if(v < 0)
407dd7cddfSDavid du Colombier 		v = -v;
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 	/*
437dd7cddfSDavid du Colombier 	 * look in cache
447dd7cddfSDavid du Colombier 	 */
457dd7cddfSDavid du Colombier 	m = multab;
467dd7cddfSDavid du Colombier 	for(g=0; g<nelem(multab); g++) {
477dd7cddfSDavid du Colombier 		if(m->val == v) {
487dd7cddfSDavid du Colombier 			if(m->code[0] == 0)
497dd7cddfSDavid du Colombier 				return 0;
507dd7cddfSDavid du Colombier 			return m;
517dd7cddfSDavid du Colombier 		}
527dd7cddfSDavid du Colombier 		m++;
537dd7cddfSDavid du Colombier 	}
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	/*
567dd7cddfSDavid du Colombier 	 * select a spot in cache to overwrite
577dd7cddfSDavid du Colombier 	 */
587dd7cddfSDavid du Colombier 	multabp++;
597dd7cddfSDavid du Colombier 	if(multabp < 0 || multabp >= nelem(multab))
607dd7cddfSDavid du Colombier 		multabp = 0;
617dd7cddfSDavid du Colombier 	m = multab+multabp;
627dd7cddfSDavid du Colombier 	m->val = v;
637dd7cddfSDavid du Colombier 	mulval = v;
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	/*
667dd7cddfSDavid du Colombier 	 * look in execption hint table
677dd7cddfSDavid du Colombier 	 */
687dd7cddfSDavid du Colombier 	a1 = 0;
697dd7cddfSDavid du Colombier 	a2 = hintabsize;
707dd7cddfSDavid du Colombier 	for(;;) {
717dd7cddfSDavid du Colombier 		if(a1 >= a2)
727dd7cddfSDavid du Colombier 			goto no;
737dd7cddfSDavid du Colombier 		g = (a2 + a1)/2;
747dd7cddfSDavid du Colombier 		if(v < hintab[g].val) {
757dd7cddfSDavid du Colombier 			a2 = g;
767dd7cddfSDavid du Colombier 			continue;
777dd7cddfSDavid du Colombier 		}
787dd7cddfSDavid du Colombier 		if(v > hintab[g].val) {
797dd7cddfSDavid du Colombier 			a1 = g+1;
807dd7cddfSDavid du Colombier 			continue;
817dd7cddfSDavid du Colombier 		}
827dd7cddfSDavid du Colombier 		break;
837dd7cddfSDavid du Colombier 	}
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier 	if(docode(hintab[g].hint, m->code, 1, 0))
867dd7cddfSDavid du Colombier 		return m;
877dd7cddfSDavid du Colombier 	print("multiply table failure %ld\n", v);
887dd7cddfSDavid du Colombier 	m->code[0] = 0;
897dd7cddfSDavid du Colombier 	return 0;
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier no:
927dd7cddfSDavid du Colombier 	/*
937dd7cddfSDavid du Colombier 	 * try to search
947dd7cddfSDavid du Colombier 	 */
957dd7cddfSDavid du Colombier 	hint[0] = 0;
96*59cc4ca5SDavid du Colombier 	for(g=1; g<=maxmulops; g++) {
97*59cc4ca5SDavid du Colombier 		if(g >= maxmulops && v >= 65535)
987dd7cddfSDavid du Colombier 			break;
997dd7cddfSDavid du Colombier 		mulcp = hint+g;
1007dd7cddfSDavid du Colombier 		*mulcp = 0;
1017dd7cddfSDavid du Colombier 		if(gen1(g)) {
1027dd7cddfSDavid du Colombier 			if(docode(hint, m->code, 1, 0))
1037dd7cddfSDavid du Colombier 				return m;
1047dd7cddfSDavid du Colombier 			print("multiply table failure %ld\n", v);
1057dd7cddfSDavid du Colombier 			break;
1067dd7cddfSDavid du Colombier 		}
1077dd7cddfSDavid du Colombier 	}
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	/*
1107dd7cddfSDavid du Colombier 	 * try a recur followed by a shift
1117dd7cddfSDavid du Colombier 	 */
1127dd7cddfSDavid du Colombier 	g = 0;
1137dd7cddfSDavid du Colombier 	while(!(v & 1)) {
1147dd7cddfSDavid du Colombier 		g++;
1157dd7cddfSDavid du Colombier 		v >>= 1;
1167dd7cddfSDavid du Colombier 	}
1177dd7cddfSDavid du Colombier 	if(g) {
1187dd7cddfSDavid du Colombier 		m1 = mulcon0(v);
1197dd7cddfSDavid du Colombier 		if(m1) {
1207dd7cddfSDavid du Colombier 			strcpy(m->code, m1->code);
1217dd7cddfSDavid du Colombier 			sprint(strchr(m->code, 0), "%c0", g+'a');
1227dd7cddfSDavid du Colombier 			return m;
1237dd7cddfSDavid du Colombier 		}
1247dd7cddfSDavid du Colombier 	}
1257dd7cddfSDavid du Colombier 	m->code[0] = 0;
1267dd7cddfSDavid du Colombier 	return 0;
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier static int
docode(char * hp,char * cp,int r0,int r1)1307dd7cddfSDavid du Colombier docode(char *hp, char *cp, int r0, int r1)
1317dd7cddfSDavid du Colombier {
1327dd7cddfSDavid du Colombier 	int c, i;
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 	c = *hp++;
1357dd7cddfSDavid du Colombier 	*cp = c;
1367dd7cddfSDavid du Colombier 	cp += 2;
1377dd7cddfSDavid du Colombier 	switch(c) {
1387dd7cddfSDavid du Colombier 	default:
1397dd7cddfSDavid du Colombier 		c -= 'a';
1407dd7cddfSDavid du Colombier 		if(c < 1 || c >= 30)
1417dd7cddfSDavid du Colombier 			break;
1427dd7cddfSDavid du Colombier 		for(i=0; i<4; i++) {
1437dd7cddfSDavid du Colombier 			switch(i) {
1447dd7cddfSDavid du Colombier 			case 0:
1457dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0<<c, r1))
1467dd7cddfSDavid du Colombier 					goto out;
1477dd7cddfSDavid du Colombier 				break;
1487dd7cddfSDavid du Colombier 			case 1:
1497dd7cddfSDavid du Colombier 				if(docode(hp, cp, r1<<c, r1))
1507dd7cddfSDavid du Colombier 					goto out;
1517dd7cddfSDavid du Colombier 				break;
1527dd7cddfSDavid du Colombier 			case 2:
1537dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0, r0<<c))
1547dd7cddfSDavid du Colombier 					goto out;
1557dd7cddfSDavid du Colombier 				break;
1567dd7cddfSDavid du Colombier 			case 3:
1577dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0, r1<<c))
1587dd7cddfSDavid du Colombier 					goto out;
1597dd7cddfSDavid du Colombier 				break;
1607dd7cddfSDavid du Colombier 			}
1617dd7cddfSDavid du Colombier 		}
1627dd7cddfSDavid du Colombier 		break;
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier 	case '+':
1657dd7cddfSDavid du Colombier 		for(i=0; i<8; i++) {
1667dd7cddfSDavid du Colombier 			cp[-1] = i+'0';
1677dd7cddfSDavid du Colombier 			switch(i) {
1687dd7cddfSDavid du Colombier 			case 1:
1697dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0+r1, r1))
1707dd7cddfSDavid du Colombier 					goto out;
1717dd7cddfSDavid du Colombier 				break;
1727dd7cddfSDavid du Colombier 			case 5:
1737dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0, r0+r1))
1747dd7cddfSDavid du Colombier 					goto out;
1757dd7cddfSDavid du Colombier 				break;
1767dd7cddfSDavid du Colombier 			}
1777dd7cddfSDavid du Colombier 		}
1787dd7cddfSDavid du Colombier 		break;
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier 	case '-':
1817dd7cddfSDavid du Colombier 		for(i=0; i<8; i++) {
1827dd7cddfSDavid du Colombier 			cp[-1] = i+'0';
1837dd7cddfSDavid du Colombier 			switch(i) {
1847dd7cddfSDavid du Colombier 			case 1:
1857dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0-r1, r1))
1867dd7cddfSDavid du Colombier 					goto out;
1877dd7cddfSDavid du Colombier 				break;
1887dd7cddfSDavid du Colombier 			case 2:
1897dd7cddfSDavid du Colombier 				if(docode(hp, cp, r1-r0, r1))
1907dd7cddfSDavid du Colombier 					goto out;
1917dd7cddfSDavid du Colombier 				break;
1927dd7cddfSDavid du Colombier 			case 5:
1937dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0, r0-r1))
1947dd7cddfSDavid du Colombier 					goto out;
1957dd7cddfSDavid du Colombier 				break;
1967dd7cddfSDavid du Colombier 			case 6:
1977dd7cddfSDavid du Colombier 				if(docode(hp, cp, r0, r1-r0))
1987dd7cddfSDavid du Colombier 					goto out;
1997dd7cddfSDavid du Colombier 				break;
2007dd7cddfSDavid du Colombier 			}
2017dd7cddfSDavid du Colombier 		}
2027dd7cddfSDavid du Colombier 		break;
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier 	case 0:
2057dd7cddfSDavid du Colombier 		if(r0 == mulval)
2067dd7cddfSDavid du Colombier 			return 1;
2077dd7cddfSDavid du Colombier 	}
2087dd7cddfSDavid du Colombier 	return 0;
2097dd7cddfSDavid du Colombier 
2107dd7cddfSDavid du Colombier out:
2117dd7cddfSDavid du Colombier 	cp[-1] = i+'0';
2127dd7cddfSDavid du Colombier 	return 1;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier static int
gen1(int len)2167dd7cddfSDavid du Colombier gen1(int len)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier 	int i;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier 	for(shmax=1; shmax<30; shmax++) {
2217dd7cddfSDavid du Colombier 		valmax = 1<<shmax;
2227dd7cddfSDavid du Colombier 		if(valmax >= mulval)
2237dd7cddfSDavid du Colombier 			break;
2247dd7cddfSDavid du Colombier 	}
2257dd7cddfSDavid du Colombier 	if(mulval == 1)
2267dd7cddfSDavid du Colombier 		return 1;
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier 	len--;
2297dd7cddfSDavid du Colombier 	for(i=1; i<=shmax; i++)
2307dd7cddfSDavid du Colombier 		if(gen2(len, 1<<i)) {
2317dd7cddfSDavid du Colombier 			*--mulcp = 'a'+i;
2327dd7cddfSDavid du Colombier 			return 1;
2337dd7cddfSDavid du Colombier 		}
2347dd7cddfSDavid du Colombier 	return 0;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier static int
gen2(int len,long r1)2387dd7cddfSDavid du Colombier gen2(int len, long r1)
2397dd7cddfSDavid du Colombier {
2407dd7cddfSDavid du Colombier 	int i;
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier 	if(len <= 0) {
2437dd7cddfSDavid du Colombier 		if(r1 == mulval)
2447dd7cddfSDavid du Colombier 			return 1;
2457dd7cddfSDavid du Colombier 		return 0;
2467dd7cddfSDavid du Colombier 	}
2477dd7cddfSDavid du Colombier 
2487dd7cddfSDavid du Colombier 	len--;
2497dd7cddfSDavid du Colombier 	if(len == 0)
2507dd7cddfSDavid du Colombier 		goto calcr0;
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier 	if(gen3(len, r1, r1+1, UR1)) {
2537dd7cddfSDavid du Colombier 		i = '+';
2547dd7cddfSDavid du Colombier 		goto out;
2557dd7cddfSDavid du Colombier 	}
2567dd7cddfSDavid du Colombier 	if(gen3(len, r1-1, r1, UR0)) {
2577dd7cddfSDavid du Colombier 		i = '-';
2587dd7cddfSDavid du Colombier 		goto out;
2597dd7cddfSDavid du Colombier 	}
2607dd7cddfSDavid du Colombier 	if(gen3(len, 1, r1+1, UR1)) {
2617dd7cddfSDavid du Colombier 		i = '+';
2627dd7cddfSDavid du Colombier 		goto out;
2637dd7cddfSDavid du Colombier 	}
2647dd7cddfSDavid du Colombier 	if(gen3(len, 1, r1-1, UR1)) {
2657dd7cddfSDavid du Colombier 		i = '-';
2667dd7cddfSDavid du Colombier 		goto out;
2677dd7cddfSDavid du Colombier 	}
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier 	return 0;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier calcr0:
2727dd7cddfSDavid du Colombier 	if(mulval == r1+1) {
2737dd7cddfSDavid du Colombier 		i = '+';
2747dd7cddfSDavid du Colombier 		goto out;
2757dd7cddfSDavid du Colombier 	}
2767dd7cddfSDavid du Colombier 	if(mulval == r1-1) {
2777dd7cddfSDavid du Colombier 		i = '-';
2787dd7cddfSDavid du Colombier 		goto out;
2797dd7cddfSDavid du Colombier 	}
2807dd7cddfSDavid du Colombier 	return 0;
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier out:
2837dd7cddfSDavid du Colombier 	*--mulcp = i;
2847dd7cddfSDavid du Colombier 	return 1;
2857dd7cddfSDavid du Colombier }
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier static int
gen3(int len,long r0,long r1,int flag)2887dd7cddfSDavid du Colombier gen3(int len, long r0, long r1, int flag)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier 	int i, f1, f2;
2917dd7cddfSDavid du Colombier 	long x;
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier 	if(r0 <= 0 ||
2947dd7cddfSDavid du Colombier 	   r0 >= r1 ||
2957dd7cddfSDavid du Colombier 	   r1 > valmax)
2967dd7cddfSDavid du Colombier 		return 0;
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier 	len--;
2997dd7cddfSDavid du Colombier 	if(len == 0)
3007dd7cddfSDavid du Colombier 		goto calcr0;
3017dd7cddfSDavid du Colombier 
3027dd7cddfSDavid du Colombier 	if(!(flag & UR1)) {
3037dd7cddfSDavid du Colombier 		f1 = UR1|SR1;
3047dd7cddfSDavid du Colombier 		for(i=1; i<=shmax; i++) {
3057dd7cddfSDavid du Colombier 			x = r0<<i;
3067dd7cddfSDavid du Colombier 			if(x > valmax)
3077dd7cddfSDavid du Colombier 				break;
3087dd7cddfSDavid du Colombier 			if(gen3(len, r0, x, f1)) {
3097dd7cddfSDavid du Colombier 				i += 'a';
3107dd7cddfSDavid du Colombier 				goto out;
3117dd7cddfSDavid du Colombier 			}
3127dd7cddfSDavid du Colombier 		}
3137dd7cddfSDavid du Colombier 	}
3147dd7cddfSDavid du Colombier 
3157dd7cddfSDavid du Colombier 	if(!(flag & UR0)) {
3167dd7cddfSDavid du Colombier 		f1 = UR1|SR1;
3177dd7cddfSDavid du Colombier 		for(i=1; i<=shmax; i++) {
3187dd7cddfSDavid du Colombier 			x = r1<<i;
3197dd7cddfSDavid du Colombier 			if(x > valmax)
3207dd7cddfSDavid du Colombier 				break;
3217dd7cddfSDavid du Colombier 			if(gen3(len, r1, x, f1)) {
3227dd7cddfSDavid du Colombier 				i += 'a';
3237dd7cddfSDavid du Colombier 				goto out;
3247dd7cddfSDavid du Colombier 			}
3257dd7cddfSDavid du Colombier 		}
3267dd7cddfSDavid du Colombier 	}
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 	if(!(flag & SR1)) {
3297dd7cddfSDavid du Colombier 		f1 = UR1|SR1|(flag&UR0);
3307dd7cddfSDavid du Colombier 		for(i=1; i<=shmax; i++) {
3317dd7cddfSDavid du Colombier 			x = r1<<i;
3327dd7cddfSDavid du Colombier 			if(x > valmax)
3337dd7cddfSDavid du Colombier 				break;
3347dd7cddfSDavid du Colombier 			if(gen3(len, r0, x, f1)) {
3357dd7cddfSDavid du Colombier 				i += 'a';
3367dd7cddfSDavid du Colombier 				goto out;
3377dd7cddfSDavid du Colombier 			}
3387dd7cddfSDavid du Colombier 		}
3397dd7cddfSDavid du Colombier 	}
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	if(!(flag & SR0)) {
3427dd7cddfSDavid du Colombier 		f1 = UR0|SR0|(flag&(SR1|UR1));
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier 		f2 = UR1|SR1;
3457dd7cddfSDavid du Colombier 		if(flag & UR1)
3467dd7cddfSDavid du Colombier 			f2 |= UR0;
3477dd7cddfSDavid du Colombier 		if(flag & SR1)
3487dd7cddfSDavid du Colombier 			f2 |= SR0;
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier 		for(i=1; i<=shmax; i++) {
3517dd7cddfSDavid du Colombier 			x = r0<<i;
3527dd7cddfSDavid du Colombier 			if(x > valmax)
3537dd7cddfSDavid du Colombier 				break;
3547dd7cddfSDavid du Colombier 			if(x > r1) {
3557dd7cddfSDavid du Colombier 				if(gen3(len, r1, x, f2)) {
3567dd7cddfSDavid du Colombier 					i += 'a';
3577dd7cddfSDavid du Colombier 					goto out;
3587dd7cddfSDavid du Colombier 				}
3597dd7cddfSDavid du Colombier 			} else
3607dd7cddfSDavid du Colombier 				if(gen3(len, x, r1, f1)) {
3617dd7cddfSDavid du Colombier 					i += 'a';
3627dd7cddfSDavid du Colombier 					goto out;
3637dd7cddfSDavid du Colombier 				}
3647dd7cddfSDavid du Colombier 		}
3657dd7cddfSDavid du Colombier 	}
3667dd7cddfSDavid du Colombier 
3677dd7cddfSDavid du Colombier 	x = r1+r0;
3687dd7cddfSDavid du Colombier 	if(gen3(len, r0, x, UR1)) {
3697dd7cddfSDavid du Colombier 		i = '+';
3707dd7cddfSDavid du Colombier 		goto out;
3717dd7cddfSDavid du Colombier 	}
3727dd7cddfSDavid du Colombier 
3737dd7cddfSDavid du Colombier 	if(gen3(len, r1, x, UR1)) {
3747dd7cddfSDavid du Colombier 		i = '+';
3757dd7cddfSDavid du Colombier 		goto out;
3767dd7cddfSDavid du Colombier 	}
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier 	x = r1-r0;
3797dd7cddfSDavid du Colombier 	if(gen3(len, x, r1, UR0)) {
3807dd7cddfSDavid du Colombier 		i = '-';
3817dd7cddfSDavid du Colombier 		goto out;
3827dd7cddfSDavid du Colombier 	}
3837dd7cddfSDavid du Colombier 
3847dd7cddfSDavid du Colombier 	if(x > r0) {
3857dd7cddfSDavid du Colombier 		if(gen3(len, r0, x, UR1)) {
3867dd7cddfSDavid du Colombier 			i = '-';
3877dd7cddfSDavid du Colombier 			goto out;
3887dd7cddfSDavid du Colombier 		}
3897dd7cddfSDavid du Colombier 	} else
3907dd7cddfSDavid du Colombier 		if(gen3(len, x, r0, UR0)) {
3917dd7cddfSDavid du Colombier 			i = '-';
3927dd7cddfSDavid du Colombier 			goto out;
3937dd7cddfSDavid du Colombier 		}
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier 	return 0;
3967dd7cddfSDavid du Colombier 
3977dd7cddfSDavid du Colombier calcr0:
3987dd7cddfSDavid du Colombier 	f1 = flag & (UR0|UR1);
3997dd7cddfSDavid du Colombier 	if(f1 == UR1) {
4007dd7cddfSDavid du Colombier 		for(i=1; i<=shmax; i++) {
4017dd7cddfSDavid du Colombier 			x = r1<<i;
4027dd7cddfSDavid du Colombier 			if(x >= mulval) {
4037dd7cddfSDavid du Colombier 				if(x == mulval) {
4047dd7cddfSDavid du Colombier 					i += 'a';
4057dd7cddfSDavid du Colombier 					goto out;
4067dd7cddfSDavid du Colombier 				}
4077dd7cddfSDavid du Colombier 				break;
4087dd7cddfSDavid du Colombier 			}
4097dd7cddfSDavid du Colombier 		}
4107dd7cddfSDavid du Colombier 	}
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier 	if(mulval == r1+r0) {
4137dd7cddfSDavid du Colombier 		i = '+';
4147dd7cddfSDavid du Colombier 		goto out;
4157dd7cddfSDavid du Colombier 	}
4167dd7cddfSDavid du Colombier 	if(mulval == r1-r0) {
4177dd7cddfSDavid du Colombier 		i = '-';
4187dd7cddfSDavid du Colombier 		goto out;
4197dd7cddfSDavid du Colombier 	}
4207dd7cddfSDavid du Colombier 
4217dd7cddfSDavid du Colombier 	return 0;
4227dd7cddfSDavid du Colombier 
4237dd7cddfSDavid du Colombier out:
4247dd7cddfSDavid du Colombier 	*--mulcp = i;
4257dd7cddfSDavid du Colombier 	return 1;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier /*
4297dd7cddfSDavid du Colombier  * hint table has numbers that
4307dd7cddfSDavid du Colombier  * the search algorithm fails on.
4317dd7cddfSDavid du Colombier  * <1000:
4327dd7cddfSDavid du Colombier  *	all numbers
4337dd7cddfSDavid du Colombier  * <5000:
4347dd7cddfSDavid du Colombier  * 	÷ by 5
4357dd7cddfSDavid du Colombier  * <10000:
4367dd7cddfSDavid du Colombier  * 	÷ by 50
4377dd7cddfSDavid du Colombier  * <65536:
4387dd7cddfSDavid du Colombier  * 	÷ by 250
4397dd7cddfSDavid du Colombier  */
4407dd7cddfSDavid du Colombier Hintab	hintab[] =
4417dd7cddfSDavid du Colombier {
4427dd7cddfSDavid du Colombier 	683,	"b++d+e+",
4437dd7cddfSDavid du Colombier 	687,	"b+e++e-",
4447dd7cddfSDavid du Colombier 	691,	"b++d+e+",
4457dd7cddfSDavid du Colombier 	731,	"b++d+e+",
4467dd7cddfSDavid du Colombier 	811,	"b++d+i+",
4477dd7cddfSDavid du Colombier 	821,	"b++e+e+",
4487dd7cddfSDavid du Colombier 	843,	"b+d++e+",
4497dd7cddfSDavid du Colombier 	851,	"b+f-+e-",
4507dd7cddfSDavid du Colombier 	853,	"b++e+e+",
4517dd7cddfSDavid du Colombier 	877,	"c++++g-",
4527dd7cddfSDavid du Colombier 	933,	"b+c++g-",
4537dd7cddfSDavid du Colombier 	981,	"c-+e-d+",
4547dd7cddfSDavid du Colombier 	1375,	"b+c+b+h-",
4557dd7cddfSDavid du Colombier 	1675,	"d+b++h+",
4567dd7cddfSDavid du Colombier 	2425,	"c++f-e+",
4577dd7cddfSDavid du Colombier 	2675,	"c+d++f-",
4587dd7cddfSDavid du Colombier 	2750,	"b+d-b+h-",
4597dd7cddfSDavid du Colombier 	2775,	"c-+g-e-",
4607dd7cddfSDavid du Colombier 	3125,	"b++e+g+",
4617dd7cddfSDavid du Colombier 	3275,	"b+c+g+e+",
4627dd7cddfSDavid du Colombier 	3350,	"c++++i+",
4637dd7cddfSDavid du Colombier 	3475,	"c-+e-f-",
4647dd7cddfSDavid du Colombier 	3525,	"c-+d+g-",
4657dd7cddfSDavid du Colombier 	3625,	"c-+e-j+",
4667dd7cddfSDavid du Colombier 	3675,	"b+d+d+e+",
4677dd7cddfSDavid du Colombier 	3725,	"b+d-+h+",
4687dd7cddfSDavid du Colombier 	3925,	"b+d+f-d-",
4697dd7cddfSDavid du Colombier 	4275,	"b+g++e+",
4707dd7cddfSDavid du Colombier 	4325,	"b+h-+d+",
4717dd7cddfSDavid du Colombier 	4425,	"b+b+g-j-",
4727dd7cddfSDavid du Colombier 	4525,	"b+d-d+f+",
4737dd7cddfSDavid du Colombier 	4675,	"c++d-g+",
4747dd7cddfSDavid du Colombier 	4775,	"b+d+b+g-",
4757dd7cddfSDavid du Colombier 	4825,	"c+c-+i-",
4767dd7cddfSDavid du Colombier 	4850,	"c++++i-",
4777dd7cddfSDavid du Colombier 	4925,	"b++e-g-",
4787dd7cddfSDavid du Colombier 	4975,	"c+f++e-",
4797dd7cddfSDavid du Colombier 	5500,	"b+g-c+d+",
4807dd7cddfSDavid du Colombier 	6700,	"d+b++i+",
4817dd7cddfSDavid du Colombier 	9700,	"d++++j-",
4827dd7cddfSDavid du Colombier 	11000,	"b+f-c-h-",
4837dd7cddfSDavid du Colombier 	11750,	"b+d+g+j-",
4847dd7cddfSDavid du Colombier 	12500,	"b+c+e-k+",
4857dd7cddfSDavid du Colombier 	13250,	"b+d+e-f+",
4867dd7cddfSDavid du Colombier 	13750,	"b+h-c-d+",
4877dd7cddfSDavid du Colombier 	14250,	"b+g-c+e-",
4887dd7cddfSDavid du Colombier 	14500,	"c+f+j-d-",
4897dd7cddfSDavid du Colombier 	14750,	"d-g--f+",
4907dd7cddfSDavid du Colombier 	16750,	"b+e-d-n+",
4917dd7cddfSDavid du Colombier 	17750,	"c+h-b+e+",
4927dd7cddfSDavid du Colombier 	18250,	"d+b+h-d+",
4937dd7cddfSDavid du Colombier 	18750,	"b+g-++f+",
4947dd7cddfSDavid du Colombier 	19250,	"b+e+b+h+",
4957dd7cddfSDavid du Colombier 	19750,	"b++h--f-",
4967dd7cddfSDavid du Colombier 	20250,	"b+e-l-c+",
4977dd7cddfSDavid du Colombier 	20750,	"c++bi+e-",
4987dd7cddfSDavid du Colombier 	21250,	"b+i+l+c+",
4997dd7cddfSDavid du Colombier 	22000,	"b+e+d-g-",
5007dd7cddfSDavid du Colombier 	22250,	"b+d-h+k-",
5017dd7cddfSDavid du Colombier 	22750,	"b+d-e-g+",
5027dd7cddfSDavid du Colombier 	23250,	"b+c+h+e-",
5037dd7cddfSDavid du Colombier 	23500,	"b+g-c-g-",
5047dd7cddfSDavid du Colombier 	23750,	"b+g-b+h-",
5057dd7cddfSDavid du Colombier 	24250,	"c++g+m-",
5067dd7cddfSDavid du Colombier 	24750,	"b+e+e+j-",
5077dd7cddfSDavid du Colombier 	25000,	"b++dh+g+",
5087dd7cddfSDavid du Colombier 	25250,	"b+e+d-g-",
5097dd7cddfSDavid du Colombier 	25750,	"b+e+b+j+",
5107dd7cddfSDavid du Colombier 	26250,	"b+h+c+e+",
5117dd7cddfSDavid du Colombier 	26500,	"b+h+c+g+",
5127dd7cddfSDavid du Colombier 	26750,	"b+d+e+g-",
5137dd7cddfSDavid du Colombier 	27250,	"b+e+e+f+",
5147dd7cddfSDavid du Colombier 	27500,	"c-i-c-d+",
5157dd7cddfSDavid du Colombier 	27750,	"b+bd++j+",
5167dd7cddfSDavid du Colombier 	28250,	"d-d-++i-",
5177dd7cddfSDavid du Colombier 	28500,	"c+c-h-e-",
5187dd7cddfSDavid du Colombier 	29000,	"b+g-d-f+",
5197dd7cddfSDavid du Colombier 	29500,	"c+h+++e-",
5207dd7cddfSDavid du Colombier 	29750,	"b+g+f-c+",
5217dd7cddfSDavid du Colombier 	30250,	"b+f-g-c+",
5227dd7cddfSDavid du Colombier 	33500,	"c-f-d-n+",
5237dd7cddfSDavid du Colombier 	33750,	"b+d-b+j-",
5247dd7cddfSDavid du Colombier 	34250,	"c+e+++i+",
5257dd7cddfSDavid du Colombier 	35250,	"e+b+d+k+",
5267dd7cddfSDavid du Colombier 	35500,	"c+e+d-g-",
5277dd7cddfSDavid du Colombier 	35750,	"c+i-++e+",
5287dd7cddfSDavid du Colombier 	36250,	"b+bh-d+e+",
5297dd7cddfSDavid du Colombier 	36500,	"c+c-h-e-",
5307dd7cddfSDavid du Colombier 	36750,	"d+e--i+",
5317dd7cddfSDavid du Colombier 	37250,	"b+g+g+b+",
5327dd7cddfSDavid du Colombier 	37500,	"b+h-b+f+",
5337dd7cddfSDavid du Colombier 	37750,	"c+be++j-",
5347dd7cddfSDavid du Colombier 	38500,	"b+e+b+i+",
5357dd7cddfSDavid du Colombier 	38750,	"d+i-b+d+",
5367dd7cddfSDavid du Colombier 	39250,	"b+g-l-+d+",
5377dd7cddfSDavid du Colombier 	39500,	"b+g-c+g-",
5387dd7cddfSDavid du Colombier 	39750,	"b+bh-c+f-",
5397dd7cddfSDavid du Colombier 	40250,	"b+bf+d+g-",
5407dd7cddfSDavid du Colombier 	40500,	"b+g-c+g+",
5417dd7cddfSDavid du Colombier 	40750,	"c+b+i-e+",
5427dd7cddfSDavid du Colombier 	41250,	"d++bf+h+",
5437dd7cddfSDavid du Colombier 	41500,	"b+j+c+d-",
5447dd7cddfSDavid du Colombier 	41750,	"c+f+b+h-",
5457dd7cddfSDavid du Colombier 	42500,	"c+h++g+",
5467dd7cddfSDavid du Colombier 	42750,	"b+g+d-f-",
5477dd7cddfSDavid du Colombier 	43250,	"b+l-e+d-",
5487dd7cddfSDavid du Colombier 	43750,	"c+bd+h+f-",
5497dd7cddfSDavid du Colombier 	44000,	"b+f+g-d-",
5507dd7cddfSDavid du Colombier 	44250,	"b+d-g--f+",
5517dd7cddfSDavid du Colombier 	44500,	"c+e+c+h+",
5527dd7cddfSDavid du Colombier 	44750,	"b+e+d-h-",
5537dd7cddfSDavid du Colombier 	45250,	"b++g+j-g+",
5547dd7cddfSDavid du Colombier 	45500,	"c+d+e-g+",
5557dd7cddfSDavid du Colombier 	45750,	"b+d-h-e-",
5567dd7cddfSDavid du Colombier 	46250,	"c+bd++j+",
5577dd7cddfSDavid du Colombier 	46500,	"b+d-c-j-",
5587dd7cddfSDavid du Colombier 	46750,	"e-e-b+g-",
5597dd7cddfSDavid du Colombier 	47000,	"b+c+d-j-",
5607dd7cddfSDavid du Colombier 	47250,	"b+e+e-g-",
5617dd7cddfSDavid du Colombier 	47500,	"b+g-c-h-",
5627dd7cddfSDavid du Colombier 	47750,	"b+f-c+h-",
5637dd7cddfSDavid du Colombier 	48250,	"d--h+n-",
5647dd7cddfSDavid du Colombier 	48500,	"b+c-g+m-",
5657dd7cddfSDavid du Colombier 	48750,	"b+e+e-g+",
5667dd7cddfSDavid du Colombier 	49500,	"c-f+e+j-",
5677dd7cddfSDavid du Colombier 	49750,	"c+c+g++f-",
5687dd7cddfSDavid du Colombier 	50000,	"b+e+e+k+",
5697dd7cddfSDavid du Colombier 	50250,	"b++i++g+",
5707dd7cddfSDavid du Colombier 	50500,	"c+g+f-i+",
5717dd7cddfSDavid du Colombier 	50750,	"b+e+d+k-",
5727dd7cddfSDavid du Colombier 	51500,	"b+i+c-f+",
5737dd7cddfSDavid du Colombier 	51750,	"b+bd+g-e-",
5747dd7cddfSDavid du Colombier 	52250,	"b+d+g-j+",
5757dd7cddfSDavid du Colombier 	52500,	"c+c+f+g+",
5767dd7cddfSDavid du Colombier 	52750,	"b+c+e+i+",
5777dd7cddfSDavid du Colombier 	53000,	"b+i+c+g+",
5787dd7cddfSDavid du Colombier 	53500,	"c+g+g-n+",
5797dd7cddfSDavid du Colombier 	53750,	"b+j+d-c+",
5807dd7cddfSDavid du Colombier 	54250,	"b+d-g-j-",
5817dd7cddfSDavid du Colombier 	54500,	"c-f+e+f+",
5827dd7cddfSDavid du Colombier 	54750,	"b+f-+c+g+",
5837dd7cddfSDavid du Colombier 	55000,	"b+g-d-g-",
5847dd7cddfSDavid du Colombier 	55250,	"b+e+e+g+",
5857dd7cddfSDavid du Colombier 	55500,	"b+cd++j+",
5867dd7cddfSDavid du Colombier 	55750,	"b+bh-d-f-",
5877dd7cddfSDavid du Colombier 	56250,	"c+d-b+j-",
5887dd7cddfSDavid du Colombier 	56500,	"c+d+c+i+",
5897dd7cddfSDavid du Colombier 	56750,	"b+e+d++h-",
5907dd7cddfSDavid du Colombier 	57000,	"b+d+g-f+",
5917dd7cddfSDavid du Colombier 	57250,	"b+f-m+d-",
5927dd7cddfSDavid du Colombier 	57750,	"b+i+c+e-",
5937dd7cddfSDavid du Colombier 	58000,	"b+e+d+h+",
5947dd7cddfSDavid du Colombier 	58250,	"c+b+g+g+",
5957dd7cddfSDavid du Colombier 	58750,	"d-e-j--e+",
5967dd7cddfSDavid du Colombier 	59000,	"d-i-+e+",
5977dd7cddfSDavid du Colombier 	59250,	"e--h-m+",
5987dd7cddfSDavid du Colombier 	59500,	"c+c-h+f-",
5997dd7cddfSDavid du Colombier 	59750,	"b+bh-e+i-",
6007dd7cddfSDavid du Colombier 	60250,	"b+bh-e-e-",
6017dd7cddfSDavid du Colombier 	60500,	"c+c-g-g-",
6027dd7cddfSDavid du Colombier 	60750,	"b+e-l-e-",
6037dd7cddfSDavid du Colombier 	61250,	"b+g-g-c+",
6047dd7cddfSDavid du Colombier 	61750,	"b+g-c+g+",
6057dd7cddfSDavid du Colombier 	62250,	"f--+c-i-",
6067dd7cddfSDavid du Colombier 	62750,	"e+f--+g+",
6077dd7cddfSDavid du Colombier 	64750,	"b+f+d+p-",
6087dd7cddfSDavid du Colombier };
6097dd7cddfSDavid du Colombier int	hintabsize	= nelem(hintab);
610