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