xref: /csrg-svn/old/as.tahoe/bignum.c (revision 40599)
1*40599Sbostic /*
2*40599Sbostic  *	Copyright (c) 1982 Regents of the University of California
3*40599Sbostic  */
4*40599Sbostic #ifndef lint
5*40599Sbostic static char sccsid[] = "@(#)bignum1.c 4.4 6/30/83";
6*40599Sbostic #endif not lint
7*40599Sbostic 
8*40599Sbostic #include <errno.h>
9*40599Sbostic #include <stdio.h>
10*40599Sbostic #include "as.h"
11*40599Sbostic 
12*40599Sbostic Bignum	Znumber;
13*40599Sbostic 
14*40599Sbostic /*
15*40599Sbostic  *	Construct an integer.
16*40599Sbostic  */
17*40599Sbostic 
as_atoi(ccp,radix,ovfp)18*40599Sbostic Bignum as_atoi(ccp, radix, ovfp)
19*40599Sbostic 	reg	char	*ccp;		/* character cp */
20*40599Sbostic 		int	radix;
21*40599Sbostic 		Ovf	*ovfp;
22*40599Sbostic {
23*40599Sbostic 	reg	chptr	bcp;
24*40599Sbostic 		chptr	tcp;
25*40599Sbostic 	reg	int	i;
26*40599Sbostic 		int	val;
27*40599Sbostic 		Bignum	n_n;
28*40599Sbostic 		Bignum	t_n;
29*40599Sbostic 		int	sign;
30*40599Sbostic 		Ovf	ovf;
31*40599Sbostic 
32*40599Sbostic 	ovf = 0;
33*40599Sbostic 	sign = 0;
34*40599Sbostic 	for (; *ccp; ccp++){
35*40599Sbostic 		switch(*ccp){
36*40599Sbostic 		case '0':
37*40599Sbostic 		case '+':	continue;
38*40599Sbostic 		case '-':	sign ^= 1;
39*40599Sbostic 				continue;
40*40599Sbostic 		}
41*40599Sbostic 		break;
42*40599Sbostic 	}
43*40599Sbostic 
44*40599Sbostic 	n_n = Znumber;
45*40599Sbostic 	t_n = Znumber;
46*40599Sbostic 	bcp = CH_FIELD(n_n); (void)numclear(bcp);
47*40599Sbostic 	tcp = CH_FIELD(t_n); (void)numclear(tcp);
48*40599Sbostic 	for (; *ccp; ccp++){
49*40599Sbostic 		switch(*ccp){
50*40599Sbostic 		case '8': case '9':
51*40599Sbostic 			if (radix < 10)
52*40599Sbostic 				goto done;
53*40599Sbostic 			/*FALLTHROUGH*/
54*40599Sbostic 		case '0': case '1': case '2': case '3': case '4':
55*40599Sbostic 		case '5': case '6': case '7':
56*40599Sbostic 			val = *ccp - '0';
57*40599Sbostic 			break;
58*40599Sbostic 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
59*40599Sbostic 			if (radix < 16)
60*40599Sbostic 				goto done;
61*40599Sbostic 			val = *ccp - 'A' + 10;
62*40599Sbostic 			break;
63*40599Sbostic 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
64*40599Sbostic 			if (radix < 16)
65*40599Sbostic 				goto done;
66*40599Sbostic 			val = *ccp - 'a' + 10;
67*40599Sbostic 			break;
68*40599Sbostic 		default:
69*40599Sbostic 			goto done;
70*40599Sbostic 		}
71*40599Sbostic 		switch(radix){
72*40599Sbostic 		case 8:
73*40599Sbostic 			ovf |= numshift(3, bcp, bcp);
74*40599Sbostic 			break;
75*40599Sbostic 		case 16:
76*40599Sbostic 			ovf |= numshift(4, bcp, bcp);
77*40599Sbostic 			break;
78*40599Sbostic 		case 10:
79*40599Sbostic 			ovf |= numshift(1, tcp, bcp);
80*40599Sbostic 			ovf |= numshift(3, bcp, bcp);
81*40599Sbostic 			ovf |= numaddv(bcp, tcp, bcp);
82*40599Sbostic 			break;
83*40599Sbostic 		}
84*40599Sbostic 		ovf |= numaddd(bcp, bcp, val);
85*40599Sbostic 	}
86*40599Sbostic   done: ;
87*40599Sbostic 	ovf |= posovf(bcp);
88*40599Sbostic 	if (sign){
89*40599Sbostic 		if (ovf & OVF_MAXINT) {
90*40599Sbostic 			ovf &= ~(OVF_MAXINT | OVF_POSOVF);
91*40599Sbostic 		} else {
92*40599Sbostic 			ovf |= numnegate(bcp, bcp);
93*40599Sbostic 		}
94*40599Sbostic 	}
95*40599Sbostic 	/*
96*40599Sbostic 	 *	find the highest set unit of the number
97*40599Sbostic 	 */
98*40599Sbostic 	val = sign ? -1 : 0;
99*40599Sbostic 	for (i = 0; i < CH_N; i++){
100*40599Sbostic 		if (bcp[i] == val)
101*40599Sbostic 			break;
102*40599Sbostic 	}
103*40599Sbostic 	{
104*40599Sbostic 		static u_char tagtab[4][8] = {
105*40599Sbostic 		{	TYPB,
106*40599Sbostic 			TYPW,
107*40599Sbostic 			TYPL, TYPL,
108*40599Sbostic 			TYPQ, TYPQ, TYPQ, TYPQ },
109*40599Sbostic 		{	TYPW,
110*40599Sbostic 			TYPL,
111*40599Sbostic 			TYPQ, TYPQ },
112*40599Sbostic 		{   0   },
113*40599Sbostic 		{	TYPL,
114*40599Sbostic 			TYPQ }
115*40599Sbostic 		};
116*40599Sbostic 		/*
117*40599Sbostic 		 *	i indexes to the null chunk; make it point to the
118*40599Sbostic 		 *	last non null chunk
119*40599Sbostic 		 */
120*40599Sbostic 		i -= 1;
121*40599Sbostic 		if (i < 0)
122*40599Sbostic 			i = 0;
123*40599Sbostic 		n_n.num_tag = tagtab[HOC][i];
124*40599Sbostic 		assert(n_n.num_tag != 0, " Botch width computation");
125*40599Sbostic 	}
126*40599Sbostic 	*ovfp = ovf;
127*40599Sbostic 	return(n_n);
128*40599Sbostic }
129*40599Sbostic 
as_atof(numbuf,radix)130*40599Sbostic Bignum as_atof (numbuf, radix)
131*40599Sbostic 	char *numbuf;
132*40599Sbostic {
133*40599Sbostic 	double atof ();
134*40599Sbostic 	Bignum number;
135*40599Sbostic 
136*40599Sbostic 	number = Znumber;
137*40599Sbostic 	number.num_tag = radix;
138*40599Sbostic 	switch (radix)
139*40599Sbostic 	{
140*40599Sbostic 	   case TYPD:
141*40599Sbostic 		number.num_num.numFd_float.Fd_value = atof (numbuf);
142*40599Sbostic 		break;
143*40599Sbostic 	   case TYPF:
144*40599Sbostic 		number.num_num.numFf_float.Ff_value = atof (numbuf);
145*40599Sbostic 		break;
146*40599Sbostic 	}
147*40599Sbostic 
148*40599Sbostic 	return (number);
149*40599Sbostic }
150*40599Sbostic 
posovf(src)151*40599Sbostic Ovf posovf(src)
152*40599Sbostic 	reg	chptr	src;
153*40599Sbostic {
154*40599Sbostic 	reg	int	i;
155*40599Sbostic 	Ovf	overflow = 0;
156*40599Sbostic 
157*40599Sbostic 	if (src[HOC] & SIGNBIT)
158*40599Sbostic 		overflow = OVF_POSOVF;
159*40599Sbostic 	if (src[HOC] == SIGNBIT){
160*40599Sbostic 		for (i = HOC - 1; i >= 0; --i){
161*40599Sbostic 			if (src[i] != 0)
162*40599Sbostic 				return(overflow);
163*40599Sbostic 		}
164*40599Sbostic 		overflow |= OVF_MAXINT;
165*40599Sbostic 	}
166*40599Sbostic 	return(overflow);
167*40599Sbostic }
168*40599Sbostic 
169*40599Sbostic /*
170*40599Sbostic  *	check if the number is clear
171*40599Sbostic  */
isclear(dst)172*40599Sbostic int isclear(dst)
173*40599Sbostic 	reg	chptr	dst;
174*40599Sbostic {
175*40599Sbostic 	return(!isunequal(dst, CH_FIELD(Znumber)));
176*40599Sbostic }
177*40599Sbostic 
isunequal(src1,src2)178*40599Sbostic int isunequal(src1, src2)
179*40599Sbostic 	reg	chptr	src1, src2;
180*40599Sbostic {
181*40599Sbostic 	reg	int	i;
182*40599Sbostic 
183*40599Sbostic 	i = CH_N;
184*40599Sbostic 	do{
185*40599Sbostic 		if (*src1++ != *src2++)
186*40599Sbostic 			return(i);
187*40599Sbostic 	}while(--i);
188*40599Sbostic 	return(0);
189*40599Sbostic }
190*40599Sbostic 
numclear(dst)191*40599Sbostic Ovf numclear(dst)
192*40599Sbostic 	reg	chptr	dst;
193*40599Sbostic {
194*40599Sbostic 	reg	int	i;
195*40599Sbostic 	i = CH_N;
196*40599Sbostic 	do{
197*40599Sbostic 		*dst++ = 0;
198*40599Sbostic 	}while(--i);
199*40599Sbostic 	return(0);
200*40599Sbostic }
201*40599Sbostic 
numshift(n,dst,src)202*40599Sbostic Ovf numshift(n, dst, src)
203*40599Sbostic 		int	n;
204*40599Sbostic 	reg	chptr	dst, src;
205*40599Sbostic {
206*40599Sbostic 	reg	int	i;
207*40599Sbostic 	reg	u_int	carryi, carryo;
208*40599Sbostic 	reg	u_int	mask;
209*40599Sbostic 	reg	u_int	value;
210*40599Sbostic 
211*40599Sbostic 	i = CH_N;
212*40599Sbostic 	if (n == 0){
213*40599Sbostic 		do{
214*40599Sbostic 			*dst++ = *src++;
215*40599Sbostic 		} while(--i);
216*40599Sbostic 		return(0);
217*40599Sbostic 	}
218*40599Sbostic 
219*40599Sbostic 	carryi = 0;
220*40599Sbostic 	mask = ONES(n);
221*40599Sbostic 
222*40599Sbostic 	if (n > 0){
223*40599Sbostic 		do{
224*40599Sbostic 			value = *src++;
225*40599Sbostic 			carryo = (value >> (CH_BITS - n)) & mask;
226*40599Sbostic 			value <<= n;
227*40599Sbostic 			value &= ~mask;
228*40599Sbostic 			*dst++ = value | carryi;
229*40599Sbostic 			carryi = carryo;
230*40599Sbostic 		} while (--i);
231*40599Sbostic 		return(carryi ? OVF_LSHIFT : 0);
232*40599Sbostic 	} else {
233*40599Sbostic 		n = -n;
234*40599Sbostic 		src += CH_N;
235*40599Sbostic 		dst += CH_N;
236*40599Sbostic 		do{
237*40599Sbostic 			value = *--src;
238*40599Sbostic 			carryo = value & mask;
239*40599Sbostic 			value >>= n;
240*40599Sbostic 			value &= ONES(CH_BITS - n);
241*40599Sbostic 			*--dst = value | carryi;
242*40599Sbostic 			carryi = carryo << (CH_BITS - n);
243*40599Sbostic 		} while (--i);
244*40599Sbostic 		return(carryi ? OVF_LSHIFT : 0);
245*40599Sbostic 	}
246*40599Sbostic }
247*40599Sbostic 
numaddd(dst,src1,val)248*40599Sbostic Ovf numaddd(dst, src1, val)
249*40599Sbostic 	chptr	dst, src1;
250*40599Sbostic 	int	val;
251*40599Sbostic {
252*40599Sbostic 	static	Bignum	work;
253*40599Sbostic 
254*40599Sbostic 	work.num_uchar[3] = val;
255*40599Sbostic 	return (numaddv(dst, src1, CH_FIELD(work)));
256*40599Sbostic }
257*40599Sbostic 
numaddv(dst,src1,src2)258*40599Sbostic Ovf numaddv(dst, src1, src2)
259*40599Sbostic 	reg	chptr	dst, src1, src2;
260*40599Sbostic {
261*40599Sbostic 	reg	int	i;
262*40599Sbostic 	reg	int	carry;
263*40599Sbostic 	reg	u_int	A,B,value;
264*40599Sbostic 
265*40599Sbostic 	carry = 0;
266*40599Sbostic 	i = CH_N;
267*40599Sbostic 	do{
268*40599Sbostic 		A = *src1++;
269*40599Sbostic 		B = *src2++;
270*40599Sbostic 		value = A + B + carry;
271*40599Sbostic 		*dst++ = value;
272*40599Sbostic 		carry = 0;
273*40599Sbostic 		if (value < A || value < B)
274*40599Sbostic 			carry = 1;
275*40599Sbostic 	} while (--i);
276*40599Sbostic 	return(carry ? OVF_ADDV : 0);
277*40599Sbostic }
278*40599Sbostic 
numnegate(dst,src)279*40599Sbostic Ovf numnegate(dst, src)
280*40599Sbostic 	chptr	dst, src;
281*40599Sbostic {
282*40599Sbostic 	Ovf	ovf;
283*40599Sbostic 
284*40599Sbostic 	ovf = num1comp(dst, src) ;
285*40599Sbostic 	ovf |= numaddd(dst, dst, 1);
286*40599Sbostic 	return(ovf);
287*40599Sbostic }
288*40599Sbostic 
num1comp(dst,src)289*40599Sbostic Ovf num1comp(dst, src)
290*40599Sbostic 	reg	chptr	dst, src;
291*40599Sbostic {
292*40599Sbostic 	reg	int	i;
293*40599Sbostic 	i = CH_N;
294*40599Sbostic 	do{
295*40599Sbostic 		*dst++ = ~ *src++;
296*40599Sbostic 	}while (--i);
297*40599Sbostic 	return(0);
298*40599Sbostic }
299*40599Sbostic 
bignumprint(number)300*40599Sbostic bignumprint(number)
301*40599Sbostic 	Bignum	number;		/* number presented */
302*40599Sbostic {
303*40599Sbostic 	switch (num_type)
304*40599Sbostic 	{
305*40599Sbostic 		case TYPQ:
306*40599Sbostic 			printf ("val[msd] = 0x%x, val[lsd] = 0x%x.",
307*40599Sbostic 			number.num_num.numIq_int.Iq_ulong[1],
308*40599Sbostic 			number.num_num.numIq_int.Iq_ulong[0]);
309*40599Sbostic 			break;
310*40599Sbostic 		case TYPF:
311*40599Sbostic 			printf ("value %20.17f",
312*40599Sbostic 			number.num_num.numFf_float.Ff_value);
313*40599Sbostic 			break;
314*40599Sbostic 		case TYPD:
315*40599Sbostic 			printf ("value %20.17f",
316*40599Sbostic 			number.num_num.numFd_float.Fd_value);
317*40599Sbostic 			break;
318*40599Sbostic 		default:
319*40599Sbostic 			break;
320*40599Sbostic 	}
321*40599Sbostic }
322*40599Sbostic 
323