xref: /plan9-contrib/sys/src/cmd/ic/mul.c (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1*ce95e1b3SDavid du Colombier #include "gc.h"
2*ce95e1b3SDavid du Colombier 
3*ce95e1b3SDavid du Colombier /*
4*ce95e1b3SDavid du Colombier  * code sequences for multiply by constant.
5*ce95e1b3SDavid du Colombier  * [a-l][0-3]
6*ce95e1b3SDavid du Colombier  *	lsl	$(A-'a'),r0,r1
7*ce95e1b3SDavid du Colombier  * [+][0-7]
8*ce95e1b3SDavid du Colombier  *	add	r0,r1,r2
9*ce95e1b3SDavid du Colombier  * [-][0-7]
10*ce95e1b3SDavid du Colombier  *	sub	r0,r1,r2
11*ce95e1b3SDavid du Colombier  */
12*ce95e1b3SDavid du Colombier 
13*ce95e1b3SDavid du Colombier static	int	multabp;
14*ce95e1b3SDavid du Colombier static	long	mulval;
15*ce95e1b3SDavid du Colombier static	char*	mulcp;
16*ce95e1b3SDavid du Colombier static	long	valmax;
17*ce95e1b3SDavid du Colombier static	int	shmax;
18*ce95e1b3SDavid du Colombier 
19*ce95e1b3SDavid du Colombier static int	docode(char *hp, char *cp, int r0, int r1);
20*ce95e1b3SDavid du Colombier static int	gen1(int len);
21*ce95e1b3SDavid du Colombier static int	gen2(int len, long r1);
22*ce95e1b3SDavid du Colombier static int	gen3(int len, long r0, long r1, int flag);
23*ce95e1b3SDavid du Colombier enum
24*ce95e1b3SDavid du Colombier {
25*ce95e1b3SDavid du Colombier 	SR1	= 1<<0,		/* r1 has been shifted */
26*ce95e1b3SDavid du Colombier 	SR0	= 1<<1,		/* r0 has been shifted */
27*ce95e1b3SDavid du Colombier 	UR1	= 1<<2,		/* r1 has not been used */
28*ce95e1b3SDavid du Colombier 	UR0	= 1<<3,		/* r0 has not been used */
29*ce95e1b3SDavid du Colombier };
30*ce95e1b3SDavid du Colombier 
31*ce95e1b3SDavid du Colombier Multab*
mulcon0(long v)32*ce95e1b3SDavid du Colombier mulcon0(long v)
33*ce95e1b3SDavid du Colombier {
34*ce95e1b3SDavid du Colombier 	int a1, a2, g;
35*ce95e1b3SDavid du Colombier 	Multab *m, *m1;
36*ce95e1b3SDavid du Colombier 	char hint[10];
37*ce95e1b3SDavid du Colombier 
38*ce95e1b3SDavid du Colombier 	if(v < 0)
39*ce95e1b3SDavid du Colombier 		v = -v;
40*ce95e1b3SDavid du Colombier 
41*ce95e1b3SDavid du Colombier 	/*
42*ce95e1b3SDavid du Colombier 	 * look in cache
43*ce95e1b3SDavid du Colombier 	 */
44*ce95e1b3SDavid du Colombier 	m = multab;
45*ce95e1b3SDavid du Colombier 	for(g=0; g<nelem(multab); g++) {
46*ce95e1b3SDavid du Colombier 		if(m->val == v) {
47*ce95e1b3SDavid du Colombier 			if(m->code[0] == 0)
48*ce95e1b3SDavid du Colombier 				return 0;
49*ce95e1b3SDavid du Colombier 			return m;
50*ce95e1b3SDavid du Colombier 		}
51*ce95e1b3SDavid du Colombier 		m++;
52*ce95e1b3SDavid du Colombier 	}
53*ce95e1b3SDavid du Colombier 
54*ce95e1b3SDavid du Colombier 	/*
55*ce95e1b3SDavid du Colombier 	 * select a spot in cache to overwrite
56*ce95e1b3SDavid du Colombier 	 */
57*ce95e1b3SDavid du Colombier 	multabp++;
58*ce95e1b3SDavid du Colombier 	if(multabp < 0 || multabp >= nelem(multab))
59*ce95e1b3SDavid du Colombier 		multabp = 0;
60*ce95e1b3SDavid du Colombier 	m = multab+multabp;
61*ce95e1b3SDavid du Colombier 	m->val = v;
62*ce95e1b3SDavid du Colombier 	mulval = v;
63*ce95e1b3SDavid du Colombier 
64*ce95e1b3SDavid du Colombier 	/*
65*ce95e1b3SDavid du Colombier 	 * look in execption hint table
66*ce95e1b3SDavid du Colombier 	 */
67*ce95e1b3SDavid du Colombier 	a1 = 0;
68*ce95e1b3SDavid du Colombier 	a2 = hintabsize;
69*ce95e1b3SDavid du Colombier 	for(;;) {
70*ce95e1b3SDavid du Colombier 		if(a1 >= a2)
71*ce95e1b3SDavid du Colombier 			goto no;
72*ce95e1b3SDavid du Colombier 		g = (a2 + a1)/2;
73*ce95e1b3SDavid du Colombier 		if(v < hintab[g].val) {
74*ce95e1b3SDavid du Colombier 			a2 = g;
75*ce95e1b3SDavid du Colombier 			continue;
76*ce95e1b3SDavid du Colombier 		}
77*ce95e1b3SDavid du Colombier 		if(v > hintab[g].val) {
78*ce95e1b3SDavid du Colombier 			a1 = g+1;
79*ce95e1b3SDavid du Colombier 			continue;
80*ce95e1b3SDavid du Colombier 		}
81*ce95e1b3SDavid du Colombier 		break;
82*ce95e1b3SDavid du Colombier 	}
83*ce95e1b3SDavid du Colombier 
84*ce95e1b3SDavid du Colombier 	if(docode(hintab[g].hint, m->code, 1, 0))
85*ce95e1b3SDavid du Colombier 		return m;
86*ce95e1b3SDavid du Colombier 	print("multiply table failure %ld\n", v);
87*ce95e1b3SDavid du Colombier 	m->code[0] = 0;
88*ce95e1b3SDavid du Colombier 	return 0;
89*ce95e1b3SDavid du Colombier 
90*ce95e1b3SDavid du Colombier no:
91*ce95e1b3SDavid du Colombier 	/*
92*ce95e1b3SDavid du Colombier 	 * try to search
93*ce95e1b3SDavid du Colombier 	 */
94*ce95e1b3SDavid du Colombier 	hint[0] = 0;
95*ce95e1b3SDavid du Colombier 	for(g=1; g<=6; g++) {
96*ce95e1b3SDavid du Colombier 		if(g >= 6 && v >= 65535)
97*ce95e1b3SDavid du Colombier 			break;
98*ce95e1b3SDavid du Colombier 		mulcp = hint+g;
99*ce95e1b3SDavid du Colombier 		*mulcp = 0;
100*ce95e1b3SDavid du Colombier 		if(gen1(g)) {
101*ce95e1b3SDavid du Colombier 			if(docode(hint, m->code, 1, 0))
102*ce95e1b3SDavid du Colombier 				return m;
103*ce95e1b3SDavid du Colombier 			print("multiply table failure %ld\n", v);
104*ce95e1b3SDavid du Colombier 			break;
105*ce95e1b3SDavid du Colombier 		}
106*ce95e1b3SDavid du Colombier 	}
107*ce95e1b3SDavid du Colombier 
108*ce95e1b3SDavid du Colombier 	/*
109*ce95e1b3SDavid du Colombier 	 * try a recur followed by a shift
110*ce95e1b3SDavid du Colombier 	 */
111*ce95e1b3SDavid du Colombier 	g = 0;
112*ce95e1b3SDavid du Colombier 	while(!(v & 1)) {
113*ce95e1b3SDavid du Colombier 		g++;
114*ce95e1b3SDavid du Colombier 		v >>= 1;
115*ce95e1b3SDavid du Colombier 	}
116*ce95e1b3SDavid du Colombier 	if(g) {
117*ce95e1b3SDavid du Colombier 		m1 = mulcon0(v);
118*ce95e1b3SDavid du Colombier 		if(m1) {
119*ce95e1b3SDavid du Colombier 			strcpy(m->code, m1->code);
120*ce95e1b3SDavid du Colombier 			sprint(strchr(m->code, 0), "%c0", g+'a');
121*ce95e1b3SDavid du Colombier 			return m;
122*ce95e1b3SDavid du Colombier 		}
123*ce95e1b3SDavid du Colombier 	}
124*ce95e1b3SDavid du Colombier 	m->code[0] = 0;
125*ce95e1b3SDavid du Colombier 	return 0;
126*ce95e1b3SDavid du Colombier }
127*ce95e1b3SDavid du Colombier 
128*ce95e1b3SDavid du Colombier static int
docode(char * hp,char * cp,int r0,int r1)129*ce95e1b3SDavid du Colombier docode(char *hp, char *cp, int r0, int r1)
130*ce95e1b3SDavid du Colombier {
131*ce95e1b3SDavid du Colombier 	int c, i;
132*ce95e1b3SDavid du Colombier 
133*ce95e1b3SDavid du Colombier 	c = *hp++;
134*ce95e1b3SDavid du Colombier 	*cp = c;
135*ce95e1b3SDavid du Colombier 	cp += 2;
136*ce95e1b3SDavid du Colombier 	switch(c) {
137*ce95e1b3SDavid du Colombier 	default:
138*ce95e1b3SDavid du Colombier 		c -= 'a';
139*ce95e1b3SDavid du Colombier 		if(c < 1 || c >= 30)
140*ce95e1b3SDavid du Colombier 			break;
141*ce95e1b3SDavid du Colombier 		for(i=0; i<4; i++) {
142*ce95e1b3SDavid du Colombier 			switch(i) {
143*ce95e1b3SDavid du Colombier 			case 0:
144*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0<<c, r1))
145*ce95e1b3SDavid du Colombier 					goto out;
146*ce95e1b3SDavid du Colombier 				break;
147*ce95e1b3SDavid du Colombier 			case 1:
148*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r1<<c, r1))
149*ce95e1b3SDavid du Colombier 					goto out;
150*ce95e1b3SDavid du Colombier 				break;
151*ce95e1b3SDavid du Colombier 			case 2:
152*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0, r0<<c))
153*ce95e1b3SDavid du Colombier 					goto out;
154*ce95e1b3SDavid du Colombier 				break;
155*ce95e1b3SDavid du Colombier 			case 3:
156*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0, r1<<c))
157*ce95e1b3SDavid du Colombier 					goto out;
158*ce95e1b3SDavid du Colombier 				break;
159*ce95e1b3SDavid du Colombier 			}
160*ce95e1b3SDavid du Colombier 		}
161*ce95e1b3SDavid du Colombier 		break;
162*ce95e1b3SDavid du Colombier 
163*ce95e1b3SDavid du Colombier 	case '+':
164*ce95e1b3SDavid du Colombier 		for(i=0; i<8; i++) {
165*ce95e1b3SDavid du Colombier 			cp[-1] = i+'0';
166*ce95e1b3SDavid du Colombier 			switch(i) {
167*ce95e1b3SDavid du Colombier 			case 1:
168*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0+r1, r1))
169*ce95e1b3SDavid du Colombier 					goto out;
170*ce95e1b3SDavid du Colombier 				break;
171*ce95e1b3SDavid du Colombier 			case 5:
172*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0, r0+r1))
173*ce95e1b3SDavid du Colombier 					goto out;
174*ce95e1b3SDavid du Colombier 				break;
175*ce95e1b3SDavid du Colombier 			}
176*ce95e1b3SDavid du Colombier 		}
177*ce95e1b3SDavid du Colombier 		break;
178*ce95e1b3SDavid du Colombier 
179*ce95e1b3SDavid du Colombier 	case '-':
180*ce95e1b3SDavid du Colombier 		for(i=0; i<8; i++) {
181*ce95e1b3SDavid du Colombier 			cp[-1] = i+'0';
182*ce95e1b3SDavid du Colombier 			switch(i) {
183*ce95e1b3SDavid du Colombier 			case 1:
184*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0-r1, r1))
185*ce95e1b3SDavid du Colombier 					goto out;
186*ce95e1b3SDavid du Colombier 				break;
187*ce95e1b3SDavid du Colombier 			case 2:
188*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r1-r0, r1))
189*ce95e1b3SDavid du Colombier 					goto out;
190*ce95e1b3SDavid du Colombier 				break;
191*ce95e1b3SDavid du Colombier 			case 5:
192*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0, r0-r1))
193*ce95e1b3SDavid du Colombier 					goto out;
194*ce95e1b3SDavid du Colombier 				break;
195*ce95e1b3SDavid du Colombier 			case 6:
196*ce95e1b3SDavid du Colombier 				if(docode(hp, cp, r0, r1-r0))
197*ce95e1b3SDavid du Colombier 					goto out;
198*ce95e1b3SDavid du Colombier 				break;
199*ce95e1b3SDavid du Colombier 			}
200*ce95e1b3SDavid du Colombier 		}
201*ce95e1b3SDavid du Colombier 		break;
202*ce95e1b3SDavid du Colombier 
203*ce95e1b3SDavid du Colombier 	case 0:
204*ce95e1b3SDavid du Colombier 		if(r0 == mulval)
205*ce95e1b3SDavid du Colombier 			return 1;
206*ce95e1b3SDavid du Colombier 	}
207*ce95e1b3SDavid du Colombier 	return 0;
208*ce95e1b3SDavid du Colombier 
209*ce95e1b3SDavid du Colombier out:
210*ce95e1b3SDavid du Colombier 	cp[-1] = i+'0';
211*ce95e1b3SDavid du Colombier 	return 1;
212*ce95e1b3SDavid du Colombier }
213*ce95e1b3SDavid du Colombier 
214*ce95e1b3SDavid du Colombier static int
gen1(int len)215*ce95e1b3SDavid du Colombier gen1(int len)
216*ce95e1b3SDavid du Colombier {
217*ce95e1b3SDavid du Colombier 	int i;
218*ce95e1b3SDavid du Colombier 
219*ce95e1b3SDavid du Colombier 	for(shmax=1; shmax<30; shmax++) {
220*ce95e1b3SDavid du Colombier 		valmax = 1<<shmax;
221*ce95e1b3SDavid du Colombier 		if(valmax >= mulval)
222*ce95e1b3SDavid du Colombier 			break;
223*ce95e1b3SDavid du Colombier 	}
224*ce95e1b3SDavid du Colombier 	if(mulval == 1)
225*ce95e1b3SDavid du Colombier 		return 1;
226*ce95e1b3SDavid du Colombier 
227*ce95e1b3SDavid du Colombier 	len--;
228*ce95e1b3SDavid du Colombier 	for(i=1; i<=shmax; i++)
229*ce95e1b3SDavid du Colombier 		if(gen2(len, 1<<i)) {
230*ce95e1b3SDavid du Colombier 			*--mulcp = 'a'+i;
231*ce95e1b3SDavid du Colombier 			return 1;
232*ce95e1b3SDavid du Colombier 		}
233*ce95e1b3SDavid du Colombier 	return 0;
234*ce95e1b3SDavid du Colombier }
235*ce95e1b3SDavid du Colombier 
236*ce95e1b3SDavid du Colombier static int
gen2(int len,long r1)237*ce95e1b3SDavid du Colombier gen2(int len, long r1)
238*ce95e1b3SDavid du Colombier {
239*ce95e1b3SDavid du Colombier 	int i;
240*ce95e1b3SDavid du Colombier 
241*ce95e1b3SDavid du Colombier 	if(len <= 0) {
242*ce95e1b3SDavid du Colombier 		if(r1 == mulval)
243*ce95e1b3SDavid du Colombier 			return 1;
244*ce95e1b3SDavid du Colombier 		return 0;
245*ce95e1b3SDavid du Colombier 	}
246*ce95e1b3SDavid du Colombier 
247*ce95e1b3SDavid du Colombier 	len--;
248*ce95e1b3SDavid du Colombier 	if(len == 0)
249*ce95e1b3SDavid du Colombier 		goto calcr0;
250*ce95e1b3SDavid du Colombier 
251*ce95e1b3SDavid du Colombier 	if(gen3(len, r1, r1+1, UR1)) {
252*ce95e1b3SDavid du Colombier 		i = '+';
253*ce95e1b3SDavid du Colombier 		goto out;
254*ce95e1b3SDavid du Colombier 	}
255*ce95e1b3SDavid du Colombier 	if(gen3(len, r1-1, r1, UR0)) {
256*ce95e1b3SDavid du Colombier 		i = '-';
257*ce95e1b3SDavid du Colombier 		goto out;
258*ce95e1b3SDavid du Colombier 	}
259*ce95e1b3SDavid du Colombier 	if(gen3(len, 1, r1+1, UR1)) {
260*ce95e1b3SDavid du Colombier 		i = '+';
261*ce95e1b3SDavid du Colombier 		goto out;
262*ce95e1b3SDavid du Colombier 	}
263*ce95e1b3SDavid du Colombier 	if(gen3(len, 1, r1-1, UR1)) {
264*ce95e1b3SDavid du Colombier 		i = '-';
265*ce95e1b3SDavid du Colombier 		goto out;
266*ce95e1b3SDavid du Colombier 	}
267*ce95e1b3SDavid du Colombier 
268*ce95e1b3SDavid du Colombier 	return 0;
269*ce95e1b3SDavid du Colombier 
270*ce95e1b3SDavid du Colombier calcr0:
271*ce95e1b3SDavid du Colombier 	if(mulval == r1+1) {
272*ce95e1b3SDavid du Colombier 		i = '+';
273*ce95e1b3SDavid du Colombier 		goto out;
274*ce95e1b3SDavid du Colombier 	}
275*ce95e1b3SDavid du Colombier 	if(mulval == r1-1) {
276*ce95e1b3SDavid du Colombier 		i = '-';
277*ce95e1b3SDavid du Colombier 		goto out;
278*ce95e1b3SDavid du Colombier 	}
279*ce95e1b3SDavid du Colombier 	return 0;
280*ce95e1b3SDavid du Colombier 
281*ce95e1b3SDavid du Colombier out:
282*ce95e1b3SDavid du Colombier 	*--mulcp = i;
283*ce95e1b3SDavid du Colombier 	return 1;
284*ce95e1b3SDavid du Colombier }
285*ce95e1b3SDavid du Colombier 
286*ce95e1b3SDavid du Colombier static int
gen3(int len,long r0,long r1,int flag)287*ce95e1b3SDavid du Colombier gen3(int len, long r0, long r1, int flag)
288*ce95e1b3SDavid du Colombier {
289*ce95e1b3SDavid du Colombier 	int i, f1, f2;
290*ce95e1b3SDavid du Colombier 	long x;
291*ce95e1b3SDavid du Colombier 
292*ce95e1b3SDavid du Colombier 	if(r0 <= 0 ||
293*ce95e1b3SDavid du Colombier 	   r0 >= r1 ||
294*ce95e1b3SDavid du Colombier 	   r1 > valmax)
295*ce95e1b3SDavid du Colombier 		return 0;
296*ce95e1b3SDavid du Colombier 
297*ce95e1b3SDavid du Colombier 	len--;
298*ce95e1b3SDavid du Colombier 	if(len == 0)
299*ce95e1b3SDavid du Colombier 		goto calcr0;
300*ce95e1b3SDavid du Colombier 
301*ce95e1b3SDavid du Colombier 	if(!(flag & UR1)) {
302*ce95e1b3SDavid du Colombier 		f1 = UR1|SR1;
303*ce95e1b3SDavid du Colombier 		for(i=1; i<=shmax; i++) {
304*ce95e1b3SDavid du Colombier 			x = r0<<i;
305*ce95e1b3SDavid du Colombier 			if(x > valmax)
306*ce95e1b3SDavid du Colombier 				break;
307*ce95e1b3SDavid du Colombier 			if(gen3(len, r0, x, f1)) {
308*ce95e1b3SDavid du Colombier 				i += 'a';
309*ce95e1b3SDavid du Colombier 				goto out;
310*ce95e1b3SDavid du Colombier 			}
311*ce95e1b3SDavid du Colombier 		}
312*ce95e1b3SDavid du Colombier 	}
313*ce95e1b3SDavid du Colombier 
314*ce95e1b3SDavid du Colombier 	if(!(flag & UR0)) {
315*ce95e1b3SDavid du Colombier 		f1 = UR1|SR1;
316*ce95e1b3SDavid du Colombier 		for(i=1; i<=shmax; i++) {
317*ce95e1b3SDavid du Colombier 			x = r1<<i;
318*ce95e1b3SDavid du Colombier 			if(x > valmax)
319*ce95e1b3SDavid du Colombier 				break;
320*ce95e1b3SDavid du Colombier 			if(gen3(len, r1, x, f1)) {
321*ce95e1b3SDavid du Colombier 				i += 'a';
322*ce95e1b3SDavid du Colombier 				goto out;
323*ce95e1b3SDavid du Colombier 			}
324*ce95e1b3SDavid du Colombier 		}
325*ce95e1b3SDavid du Colombier 	}
326*ce95e1b3SDavid du Colombier 
327*ce95e1b3SDavid du Colombier 	if(!(flag & SR1)) {
328*ce95e1b3SDavid du Colombier 		f1 = UR1|SR1|(flag&UR0);
329*ce95e1b3SDavid du Colombier 		for(i=1; i<=shmax; i++) {
330*ce95e1b3SDavid du Colombier 			x = r1<<i;
331*ce95e1b3SDavid du Colombier 			if(x > valmax)
332*ce95e1b3SDavid du Colombier 				break;
333*ce95e1b3SDavid du Colombier 			if(gen3(len, r0, x, f1)) {
334*ce95e1b3SDavid du Colombier 				i += 'a';
335*ce95e1b3SDavid du Colombier 				goto out;
336*ce95e1b3SDavid du Colombier 			}
337*ce95e1b3SDavid du Colombier 		}
338*ce95e1b3SDavid du Colombier 	}
339*ce95e1b3SDavid du Colombier 
340*ce95e1b3SDavid du Colombier 	if(!(flag & SR0)) {
341*ce95e1b3SDavid du Colombier 		f1 = UR0|SR0|(flag&(SR1|UR1));
342*ce95e1b3SDavid du Colombier 
343*ce95e1b3SDavid du Colombier 		f2 = UR1|SR1;
344*ce95e1b3SDavid du Colombier 		if(flag & UR1)
345*ce95e1b3SDavid du Colombier 			f2 |= UR0;
346*ce95e1b3SDavid du Colombier 		if(flag & SR1)
347*ce95e1b3SDavid du Colombier 			f2 |= SR0;
348*ce95e1b3SDavid du Colombier 
349*ce95e1b3SDavid du Colombier 		for(i=1; i<=shmax; i++) {
350*ce95e1b3SDavid du Colombier 			x = r0<<i;
351*ce95e1b3SDavid du Colombier 			if(x > valmax)
352*ce95e1b3SDavid du Colombier 				break;
353*ce95e1b3SDavid du Colombier 			if(x > r1) {
354*ce95e1b3SDavid du Colombier 				if(gen3(len, r1, x, f2)) {
355*ce95e1b3SDavid du Colombier 					i += 'a';
356*ce95e1b3SDavid du Colombier 					goto out;
357*ce95e1b3SDavid du Colombier 				}
358*ce95e1b3SDavid du Colombier 			} else
359*ce95e1b3SDavid du Colombier 				if(gen3(len, x, r1, f1)) {
360*ce95e1b3SDavid du Colombier 					i += 'a';
361*ce95e1b3SDavid du Colombier 					goto out;
362*ce95e1b3SDavid du Colombier 				}
363*ce95e1b3SDavid du Colombier 		}
364*ce95e1b3SDavid du Colombier 	}
365*ce95e1b3SDavid du Colombier 
366*ce95e1b3SDavid du Colombier 	x = r1+r0;
367*ce95e1b3SDavid du Colombier 	if(gen3(len, r0, x, UR1)) {
368*ce95e1b3SDavid du Colombier 		i = '+';
369*ce95e1b3SDavid du Colombier 		goto out;
370*ce95e1b3SDavid du Colombier 	}
371*ce95e1b3SDavid du Colombier 
372*ce95e1b3SDavid du Colombier 	if(gen3(len, r1, x, UR1)) {
373*ce95e1b3SDavid du Colombier 		i = '+';
374*ce95e1b3SDavid du Colombier 		goto out;
375*ce95e1b3SDavid du Colombier 	}
376*ce95e1b3SDavid du Colombier 
377*ce95e1b3SDavid du Colombier 	x = r1-r0;
378*ce95e1b3SDavid du Colombier 	if(gen3(len, x, r1, UR0)) {
379*ce95e1b3SDavid du Colombier 		i = '-';
380*ce95e1b3SDavid du Colombier 		goto out;
381*ce95e1b3SDavid du Colombier 	}
382*ce95e1b3SDavid du Colombier 
383*ce95e1b3SDavid du Colombier 	if(x > r0) {
384*ce95e1b3SDavid du Colombier 		if(gen3(len, r0, x, UR1)) {
385*ce95e1b3SDavid du Colombier 			i = '-';
386*ce95e1b3SDavid du Colombier 			goto out;
387*ce95e1b3SDavid du Colombier 		}
388*ce95e1b3SDavid du Colombier 	} else
389*ce95e1b3SDavid du Colombier 		if(gen3(len, x, r0, UR0)) {
390*ce95e1b3SDavid du Colombier 			i = '-';
391*ce95e1b3SDavid du Colombier 			goto out;
392*ce95e1b3SDavid du Colombier 		}
393*ce95e1b3SDavid du Colombier 
394*ce95e1b3SDavid du Colombier 	return 0;
395*ce95e1b3SDavid du Colombier 
396*ce95e1b3SDavid du Colombier calcr0:
397*ce95e1b3SDavid du Colombier 	f1 = flag & (UR0|UR1);
398*ce95e1b3SDavid du Colombier 	if(f1 == UR1) {
399*ce95e1b3SDavid du Colombier 		for(i=1; i<=shmax; i++) {
400*ce95e1b3SDavid du Colombier 			x = r1<<i;
401*ce95e1b3SDavid du Colombier 			if(x >= mulval) {
402*ce95e1b3SDavid du Colombier 				if(x == mulval) {
403*ce95e1b3SDavid du Colombier 					i += 'a';
404*ce95e1b3SDavid du Colombier 					goto out;
405*ce95e1b3SDavid du Colombier 				}
406*ce95e1b3SDavid du Colombier 				break;
407*ce95e1b3SDavid du Colombier 			}
408*ce95e1b3SDavid du Colombier 		}
409*ce95e1b3SDavid du Colombier 	}
410*ce95e1b3SDavid du Colombier 
411*ce95e1b3SDavid du Colombier 	if(mulval == r1+r0) {
412*ce95e1b3SDavid du Colombier 		i = '+';
413*ce95e1b3SDavid du Colombier 		goto out;
414*ce95e1b3SDavid du Colombier 	}
415*ce95e1b3SDavid du Colombier 	if(mulval == r1-r0) {
416*ce95e1b3SDavid du Colombier 		i = '-';
417*ce95e1b3SDavid du Colombier 		goto out;
418*ce95e1b3SDavid du Colombier 	}
419*ce95e1b3SDavid du Colombier 
420*ce95e1b3SDavid du Colombier 	return 0;
421*ce95e1b3SDavid du Colombier 
422*ce95e1b3SDavid du Colombier out:
423*ce95e1b3SDavid du Colombier 	*--mulcp = i;
424*ce95e1b3SDavid du Colombier 	return 1;
425*ce95e1b3SDavid du Colombier }
426*ce95e1b3SDavid du Colombier 
427*ce95e1b3SDavid du Colombier /*
428*ce95e1b3SDavid du Colombier  * hint table has numbers that
429*ce95e1b3SDavid du Colombier  * the search algorithm fails on.
430*ce95e1b3SDavid du Colombier  * <1000:
431*ce95e1b3SDavid du Colombier  *	all numbers
432*ce95e1b3SDavid du Colombier  * <5000:
433*ce95e1b3SDavid du Colombier  * 	÷ by 5
434*ce95e1b3SDavid du Colombier  * <10000:
435*ce95e1b3SDavid du Colombier  * 	÷ by 50
436*ce95e1b3SDavid du Colombier  * <65536:
437*ce95e1b3SDavid du Colombier  * 	÷ by 250
438*ce95e1b3SDavid du Colombier  */
439*ce95e1b3SDavid du Colombier Hintab	hintab[] =
440*ce95e1b3SDavid du Colombier {
441*ce95e1b3SDavid du Colombier 	683,	"b++d+e+",
442*ce95e1b3SDavid du Colombier 	687,	"b+e++e-",
443*ce95e1b3SDavid du Colombier 	691,	"b++d+e+",
444*ce95e1b3SDavid du Colombier 	731,	"b++d+e+",
445*ce95e1b3SDavid du Colombier 	811,	"b++d+i+",
446*ce95e1b3SDavid du Colombier 	821,	"b++e+e+",
447*ce95e1b3SDavid du Colombier 	843,	"b+d++e+",
448*ce95e1b3SDavid du Colombier 	851,	"b+f-+e-",
449*ce95e1b3SDavid du Colombier 	853,	"b++e+e+",
450*ce95e1b3SDavid du Colombier 	877,	"c++++g-",
451*ce95e1b3SDavid du Colombier 	933,	"b+c++g-",
452*ce95e1b3SDavid du Colombier 	981,	"c-+e-d+",
453*ce95e1b3SDavid du Colombier 	1375,	"b+c+b+h-",
454*ce95e1b3SDavid du Colombier 	1675,	"d+b++h+",
455*ce95e1b3SDavid du Colombier 	2425,	"c++f-e+",
456*ce95e1b3SDavid du Colombier 	2675,	"c+d++f-",
457*ce95e1b3SDavid du Colombier 	2750,	"b+d-b+h-",
458*ce95e1b3SDavid du Colombier 	2775,	"c-+g-e-",
459*ce95e1b3SDavid du Colombier 	3125,	"b++e+g+",
460*ce95e1b3SDavid du Colombier 	3275,	"b+c+g+e+",
461*ce95e1b3SDavid du Colombier 	3350,	"c++++i+",
462*ce95e1b3SDavid du Colombier 	3475,	"c-+e-f-",
463*ce95e1b3SDavid du Colombier 	3525,	"c-+d+g-",
464*ce95e1b3SDavid du Colombier 	3625,	"c-+e-j+",
465*ce95e1b3SDavid du Colombier 	3675,	"b+d+d+e+",
466*ce95e1b3SDavid du Colombier 	3725,	"b+d-+h+",
467*ce95e1b3SDavid du Colombier 	3925,	"b+d+f-d-",
468*ce95e1b3SDavid du Colombier 	4275,	"b+g++e+",
469*ce95e1b3SDavid du Colombier 	4325,	"b+h-+d+",
470*ce95e1b3SDavid du Colombier 	4425,	"b+b+g-j-",
471*ce95e1b3SDavid du Colombier 	4525,	"b+d-d+f+",
472*ce95e1b3SDavid du Colombier 	4675,	"c++d-g+",
473*ce95e1b3SDavid du Colombier 	4775,	"b+d+b+g-",
474*ce95e1b3SDavid du Colombier 	4825,	"c+c-+i-",
475*ce95e1b3SDavid du Colombier 	4850,	"c++++i-",
476*ce95e1b3SDavid du Colombier 	4925,	"b++e-g-",
477*ce95e1b3SDavid du Colombier 	4975,	"c+f++e-",
478*ce95e1b3SDavid du Colombier 	5500,	"b+g-c+d+",
479*ce95e1b3SDavid du Colombier 	6700,	"d+b++i+",
480*ce95e1b3SDavid du Colombier 	9700,	"d++++j-",
481*ce95e1b3SDavid du Colombier 	11000,	"b+f-c-h-",
482*ce95e1b3SDavid du Colombier 	11750,	"b+d+g+j-",
483*ce95e1b3SDavid du Colombier 	12500,	"b+c+e-k+",
484*ce95e1b3SDavid du Colombier 	13250,	"b+d+e-f+",
485*ce95e1b3SDavid du Colombier 	13750,	"b+h-c-d+",
486*ce95e1b3SDavid du Colombier 	14250,	"b+g-c+e-",
487*ce95e1b3SDavid du Colombier 	14500,	"c+f+j-d-",
488*ce95e1b3SDavid du Colombier 	14750,	"d-g--f+",
489*ce95e1b3SDavid du Colombier 	16750,	"b+e-d-n+",
490*ce95e1b3SDavid du Colombier 	17750,	"c+h-b+e+",
491*ce95e1b3SDavid du Colombier 	18250,	"d+b+h-d+",
492*ce95e1b3SDavid du Colombier 	18750,	"b+g-++f+",
493*ce95e1b3SDavid du Colombier 	19250,	"b+e+b+h+",
494*ce95e1b3SDavid du Colombier 	19750,	"b++h--f-",
495*ce95e1b3SDavid du Colombier 	20250,	"b+e-l-c+",
496*ce95e1b3SDavid du Colombier 	20750,	"c++bi+e-",
497*ce95e1b3SDavid du Colombier 	21250,	"b+i+l+c+",
498*ce95e1b3SDavid du Colombier 	22000,	"b+e+d-g-",
499*ce95e1b3SDavid du Colombier 	22250,	"b+d-h+k-",
500*ce95e1b3SDavid du Colombier 	22750,	"b+d-e-g+",
501*ce95e1b3SDavid du Colombier 	23250,	"b+c+h+e-",
502*ce95e1b3SDavid du Colombier 	23500,	"b+g-c-g-",
503*ce95e1b3SDavid du Colombier 	23750,	"b+g-b+h-",
504*ce95e1b3SDavid du Colombier 	24250,	"c++g+m-",
505*ce95e1b3SDavid du Colombier 	24750,	"b+e+e+j-",
506*ce95e1b3SDavid du Colombier 	25000,	"b++dh+g+",
507*ce95e1b3SDavid du Colombier 	25250,	"b+e+d-g-",
508*ce95e1b3SDavid du Colombier 	25750,	"b+e+b+j+",
509*ce95e1b3SDavid du Colombier 	26250,	"b+h+c+e+",
510*ce95e1b3SDavid du Colombier 	26500,	"b+h+c+g+",
511*ce95e1b3SDavid du Colombier 	26750,	"b+d+e+g-",
512*ce95e1b3SDavid du Colombier 	27250,	"b+e+e+f+",
513*ce95e1b3SDavid du Colombier 	27500,	"c-i-c-d+",
514*ce95e1b3SDavid du Colombier 	27750,	"b+bd++j+",
515*ce95e1b3SDavid du Colombier 	28250,	"d-d-++i-",
516*ce95e1b3SDavid du Colombier 	28500,	"c+c-h-e-",
517*ce95e1b3SDavid du Colombier 	29000,	"b+g-d-f+",
518*ce95e1b3SDavid du Colombier 	29500,	"c+h+++e-",
519*ce95e1b3SDavid du Colombier 	29750,	"b+g+f-c+",
520*ce95e1b3SDavid du Colombier 	30250,	"b+f-g-c+",
521*ce95e1b3SDavid du Colombier 	33500,	"c-f-d-n+",
522*ce95e1b3SDavid du Colombier 	33750,	"b+d-b+j-",
523*ce95e1b3SDavid du Colombier 	34250,	"c+e+++i+",
524*ce95e1b3SDavid du Colombier 	35250,	"e+b+d+k+",
525*ce95e1b3SDavid du Colombier 	35500,	"c+e+d-g-",
526*ce95e1b3SDavid du Colombier 	35750,	"c+i-++e+",
527*ce95e1b3SDavid du Colombier 	36250,	"b+bh-d+e+",
528*ce95e1b3SDavid du Colombier 	36500,	"c+c-h-e-",
529*ce95e1b3SDavid du Colombier 	36750,	"d+e--i+",
530*ce95e1b3SDavid du Colombier 	37250,	"b+g+g+b+",
531*ce95e1b3SDavid du Colombier 	37500,	"b+h-b+f+",
532*ce95e1b3SDavid du Colombier 	37750,	"c+be++j-",
533*ce95e1b3SDavid du Colombier 	38500,	"b+e+b+i+",
534*ce95e1b3SDavid du Colombier 	38750,	"d+i-b+d+",
535*ce95e1b3SDavid du Colombier 	39250,	"b+g-l-+d+",
536*ce95e1b3SDavid du Colombier 	39500,	"b+g-c+g-",
537*ce95e1b3SDavid du Colombier 	39750,	"b+bh-c+f-",
538*ce95e1b3SDavid du Colombier 	40250,	"b+bf+d+g-",
539*ce95e1b3SDavid du Colombier 	40500,	"b+g-c+g+",
540*ce95e1b3SDavid du Colombier 	40750,	"c+b+i-e+",
541*ce95e1b3SDavid du Colombier 	41250,	"d++bf+h+",
542*ce95e1b3SDavid du Colombier 	41500,	"b+j+c+d-",
543*ce95e1b3SDavid du Colombier 	41750,	"c+f+b+h-",
544*ce95e1b3SDavid du Colombier 	42500,	"c+h++g+",
545*ce95e1b3SDavid du Colombier 	42750,	"b+g+d-f-",
546*ce95e1b3SDavid du Colombier 	43250,	"b+l-e+d-",
547*ce95e1b3SDavid du Colombier 	43750,	"c+bd+h+f-",
548*ce95e1b3SDavid du Colombier 	44000,	"b+f+g-d-",
549*ce95e1b3SDavid du Colombier 	44250,	"b+d-g--f+",
550*ce95e1b3SDavid du Colombier 	44500,	"c+e+c+h+",
551*ce95e1b3SDavid du Colombier 	44750,	"b+e+d-h-",
552*ce95e1b3SDavid du Colombier 	45250,	"b++g+j-g+",
553*ce95e1b3SDavid du Colombier 	45500,	"c+d+e-g+",
554*ce95e1b3SDavid du Colombier 	45750,	"b+d-h-e-",
555*ce95e1b3SDavid du Colombier 	46250,	"c+bd++j+",
556*ce95e1b3SDavid du Colombier 	46500,	"b+d-c-j-",
557*ce95e1b3SDavid du Colombier 	46750,	"e-e-b+g-",
558*ce95e1b3SDavid du Colombier 	47000,	"b+c+d-j-",
559*ce95e1b3SDavid du Colombier 	47250,	"b+e+e-g-",
560*ce95e1b3SDavid du Colombier 	47500,	"b+g-c-h-",
561*ce95e1b3SDavid du Colombier 	47750,	"b+f-c+h-",
562*ce95e1b3SDavid du Colombier 	48250,	"d--h+n-",
563*ce95e1b3SDavid du Colombier 	48500,	"b+c-g+m-",
564*ce95e1b3SDavid du Colombier 	48750,	"b+e+e-g+",
565*ce95e1b3SDavid du Colombier 	49500,	"c-f+e+j-",
566*ce95e1b3SDavid du Colombier 	49750,	"c+c+g++f-",
567*ce95e1b3SDavid du Colombier 	50000,	"b+e+e+k+",
568*ce95e1b3SDavid du Colombier 	50250,	"b++i++g+",
569*ce95e1b3SDavid du Colombier 	50500,	"c+g+f-i+",
570*ce95e1b3SDavid du Colombier 	50750,	"b+e+d+k-",
571*ce95e1b3SDavid du Colombier 	51500,	"b+i+c-f+",
572*ce95e1b3SDavid du Colombier 	51750,	"b+bd+g-e-",
573*ce95e1b3SDavid du Colombier 	52250,	"b+d+g-j+",
574*ce95e1b3SDavid du Colombier 	52500,	"c+c+f+g+",
575*ce95e1b3SDavid du Colombier 	52750,	"b+c+e+i+",
576*ce95e1b3SDavid du Colombier 	53000,	"b+i+c+g+",
577*ce95e1b3SDavid du Colombier 	53500,	"c+g+g-n+",
578*ce95e1b3SDavid du Colombier 	53750,	"b+j+d-c+",
579*ce95e1b3SDavid du Colombier 	54250,	"b+d-g-j-",
580*ce95e1b3SDavid du Colombier 	54500,	"c-f+e+f+",
581*ce95e1b3SDavid du Colombier 	54750,	"b+f-+c+g+",
582*ce95e1b3SDavid du Colombier 	55000,	"b+g-d-g-",
583*ce95e1b3SDavid du Colombier 	55250,	"b+e+e+g+",
584*ce95e1b3SDavid du Colombier 	55500,	"b+cd++j+",
585*ce95e1b3SDavid du Colombier 	55750,	"b+bh-d-f-",
586*ce95e1b3SDavid du Colombier 	56250,	"c+d-b+j-",
587*ce95e1b3SDavid du Colombier 	56500,	"c+d+c+i+",
588*ce95e1b3SDavid du Colombier 	56750,	"b+e+d++h-",
589*ce95e1b3SDavid du Colombier 	57000,	"b+d+g-f+",
590*ce95e1b3SDavid du Colombier 	57250,	"b+f-m+d-",
591*ce95e1b3SDavid du Colombier 	57750,	"b+i+c+e-",
592*ce95e1b3SDavid du Colombier 	58000,	"b+e+d+h+",
593*ce95e1b3SDavid du Colombier 	58250,	"c+b+g+g+",
594*ce95e1b3SDavid du Colombier 	58750,	"d-e-j--e+",
595*ce95e1b3SDavid du Colombier 	59000,	"d-i-+e+",
596*ce95e1b3SDavid du Colombier 	59250,	"e--h-m+",
597*ce95e1b3SDavid du Colombier 	59500,	"c+c-h+f-",
598*ce95e1b3SDavid du Colombier 	59750,	"b+bh-e+i-",
599*ce95e1b3SDavid du Colombier 	60250,	"b+bh-e-e-",
600*ce95e1b3SDavid du Colombier 	60500,	"c+c-g-g-",
601*ce95e1b3SDavid du Colombier 	60750,	"b+e-l-e-",
602*ce95e1b3SDavid du Colombier 	61250,	"b+g-g-c+",
603*ce95e1b3SDavid du Colombier 	61750,	"b+g-c+g+",
604*ce95e1b3SDavid du Colombier 	62250,	"f--+c-i-",
605*ce95e1b3SDavid du Colombier 	62750,	"e+f--+g+",
606*ce95e1b3SDavid du Colombier 	64750,	"b+f+d+p-",
607*ce95e1b3SDavid du Colombier };
608*ce95e1b3SDavid du Colombier int	hintabsize	= nelem(hintab);
609