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