xref: /csrg-svn/old/as.vax/natof.c (revision 5805)
1*5805Srrh /*
2*5805Srrh  *	Copyright (c) 1982 Regents of the University of California
3*5805Srrh  */
4*5805Srrh #ifndef lint
5*5805Srrh static char sccsid[] = "@(#)natof.c 4.1 02/14/82";
6*5805Srrh #endif not lint
7*5805Srrh 
8*5805Srrh #include <stdio.h>
9*5805Srrh #include <ctype.h>
10*5805Srrh #include <errno.h>
11*5805Srrh 
12*5805Srrh #include "as.h"
13*5805Srrh 
14*5805Srrh Bignum bigatof(str, radix)
15*5805Srrh 	reg	char	*str;		/* r11 */
16*5805Srrh 		int	radix;		/* TYPF ... TYPH */
17*5805Srrh {
18*5805Srrh 		int	msign;
19*5805Srrh 		int	esign;
20*5805Srrh 		int	decpt;
21*5805Srrh 	reg	chptr	temp;		/* r10 */
22*5805Srrh 	reg	u_int	quotient;	/* r9 */	/* must be here */
23*5805Srrh 	reg	u_int	remainder;	/* r8 */	/* must be here */
24*5805Srrh 	reg	chptr	acc;
25*5805Srrh 	reg	int	dividend;	/* for doing division */
26*5805Srrh 	reg	u_int	i;
27*5805Srrh 		short	*sptr;		/* for doing division */
28*5805Srrh 		int	ch;
29*5805Srrh 		int	dexponent;	/* decimal exponent */
30*5805Srrh 		int	bexponent;	/* binary exponent */
31*5805Srrh 		Bignum	Acc;
32*5805Srrh 		Bignum	Temp;
33*5805Srrh 	static	Bignum	znumber;
34*5805Srrh 		Ovf	ovf;
35*5805Srrh 		u_int	j;
36*5805Srrh 	extern	int	errno;
37*5805Srrh 		u_int	ediv();
38*5805Srrh 
39*5805Srrh #ifdef lint
40*5805Srrh 	quotient = 0;
41*5805Srrh 	remainder = 0;
42*5805Srrh #endif lint
43*5805Srrh 	msign = 0;
44*5805Srrh 	esign = 0;
45*5805Srrh 	decpt = 0;
46*5805Srrh 	dexponent = 0;
47*5805Srrh 	Acc = znumber;
48*5805Srrh 	Acc.num_tag = radix;
49*5805Srrh 	acc = CH_FIELD(Acc);
50*5805Srrh 	temp = CH_FIELD(Temp);
51*5805Srrh 
52*5805Srrh 	do{
53*5805Srrh 		ch = *str++;
54*5805Srrh 	} while(isspace(ch));
55*5805Srrh 
56*5805Srrh 	switch(ch){
57*5805Srrh 	case '-':
58*5805Srrh 		msign = -1;
59*5805Srrh 		/* FALLTHROUGH */
60*5805Srrh 	case '+':
61*5805Srrh 		ch = *str++;
62*5805Srrh 		break;
63*5805Srrh 	}
64*5805Srrh   dofract:
65*5805Srrh 	for(; isdigit(ch); ch = *str++){
66*5805Srrh 		assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
67*5805Srrh 		if (acc[HOC] < MAXINT_10){
68*5805Srrh 			ovf = numshift(3, temp, acc);
69*5805Srrh 			ovf |= numshift(1, acc, acc);
70*5805Srrh 			ovf |= numaddv(acc, temp, acc);
71*5805Srrh 			ovf |= numaddd(acc, acc, ch - '0');
72*5805Srrh 			assert(ovf == 0, "Overflow building mantissa");
73*5805Srrh 		} else {
74*5805Srrh 			/*
75*5805Srrh 			 *	Then, the number is too large anyway
76*5805Srrh 			 */
77*5805Srrh 			dexponent++;
78*5805Srrh 		}
79*5805Srrh 		if (decpt)
80*5805Srrh 			dexponent--;
81*5805Srrh 	}
82*5805Srrh 	switch(ch){
83*5805Srrh 	case '.':
84*5805Srrh 		if (decpt == 0){
85*5805Srrh 			decpt++;
86*5805Srrh 			ch = *str++;
87*5805Srrh 			goto dofract;
88*5805Srrh 		}
89*5805Srrh 		break;
90*5805Srrh 	/*
91*5805Srrh 	 *	only 'e' and 'E' are recognized by atof()
92*5805Srrh 	 */
93*5805Srrh 	case 'e':
94*5805Srrh 	case 'E':
95*5805Srrh 	/*
96*5805Srrh 	 *	we include the remainder for compatability with as formats
97*5805Srrh 	 *	in as, the radix actual paramater agrees with the character
98*5805Srrh 	 *	we expect; consequently, no checking is done.
99*5805Srrh 	 */
100*5805Srrh 	case 'd':
101*5805Srrh 	case 'D':
102*5805Srrh 	case 'g':
103*5805Srrh 	case 'G':
104*5805Srrh 	case 'h':
105*5805Srrh 	case 'H':
106*5805Srrh 		j = 0;
107*5805Srrh 		ch = *str++;
108*5805Srrh 		esign = 0;
109*5805Srrh 		switch(ch){
110*5805Srrh 		case '-':
111*5805Srrh 			esign = 1;
112*5805Srrh 			/* FALLTHROUGH */
113*5805Srrh 		case '+':
114*5805Srrh 			ch = *str++;
115*5805Srrh 		}
116*5805Srrh 		for(; isdigit(ch); ch = *str++){
117*5805Srrh 			if (j < MAXINT_10){
118*5805Srrh 				j *= 10;
119*5805Srrh 				j += ch - '0';
120*5805Srrh 			} else {
121*5805Srrh 				/*
122*5805Srrh 				 *	outrageously large exponent
123*5805Srrh 				 */
124*5805Srrh 				 /*VOID*/
125*5805Srrh 			}
126*5805Srrh 		}
127*5805Srrh 		if (esign)
128*5805Srrh 			dexponent -= j;
129*5805Srrh 		else
130*5805Srrh 			dexponent += j;
131*5805Srrh 		/*
132*5805Srrh 		 *	There should be a range check on dexponent here
133*5805Srrh 		 */
134*5805Srrh 	}
135*5805Srrh 	/*
136*5805Srrh 	 *	The number has now been reduced to a mantissa
137*5805Srrh 	 *	and an exponent.
138*5805Srrh 	 *	The mantissa is an n bit number (to the precision
139*5805Srrh 	 *	of the extended words) in the acc.
140*5805Srrh 	 *	The exponent is a signed power of 10 in dexponent.
141*5805Srrh 	 *	msign is on if the resulting number will eventually
142*5805Srrh 	 *	be negative.
143*5805Srrh 	 *
144*5805Srrh 	 *	We now must convert the number to standard format floating
145*5805Srrh 	 *	number, which will be done by accumulating
146*5805Srrh 	 *	a binary exponent in bexponent, as we gradually
147*5805Srrh 	 *	drive dexponent towards zero, one count at a time.
148*5805Srrh 	 */
149*5805Srrh 	if (isclear(acc)){
150*5805Srrh 		return(Acc);
151*5805Srrh 	}
152*5805Srrh 	bexponent = 0;
153*5805Srrh 
154*5805Srrh 	/*
155*5805Srrh 	 *	Scale the number down.
156*5805Srrh 	 *	We must divide acc by 10 as many times as needed.
157*5805Srrh 	 */
158*5805Srrh 	for (; dexponent < 0; dexponent++){
159*5805Srrh 		/*
160*5805Srrh 		 *	Align the number so that the most significant
161*5805Srrh 		 *	bits are aligned in the most significant
162*5805Srrh 		 *	bits of the accumulator, adjusting the
163*5805Srrh 		 *	binary exponent as we shift.
164*5805Srrh 		 *	The goal is to get the high order bit (NOT the
165*5805Srrh 		 *	sign bit) set.
166*5805Srrh 		 */
167*5805Srrh 		assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
168*5805Srrh 		ovf = 0;
169*5805Srrh 
170*5805Srrh 		for (j = 5; j >= 1; --j){
171*5805Srrh 			i = 1 << (j - 1); 		/* 16, 8, 4, 2, 1 */
172*5805Srrh 			quotient = ONES(i);
173*5805Srrh 			quotient <<= (CH_BITS - 1) - i;
174*5805Srrh 			while((acc[HOC] & quotient) == 0){
175*5805Srrh 				ovf |= numshift((int)i, acc, acc);
176*5805Srrh 				bexponent -= i;
177*5805Srrh 			}
178*5805Srrh 		}
179*5805Srrh 		/*
180*5805Srrh 		 *	Add 2 to the accumulator to effect rounding,
181*5805Srrh 		 *	and get set up to divide by 5.
182*5805Srrh 		 */
183*5805Srrh 		ovf = numaddd(acc, acc, 2);
184*5805Srrh 		assert(ovf == 0, "Carry out of left rounding up by 2");
185*5805Srrh 		/*
186*5805Srrh 		 *	Divide the high order chunks by 5;
187*5805Srrh 		 *	The last chunk will be divided by 10,
188*5805Srrh 		 *	(to see what the remainder is, also to effect rounding)
189*5805Srrh 		 *	and then multipiled by 2 to effect division by 5.
190*5805Srrh 		 */
191*5805Srrh 		remainder = 0;
192*5805Srrh #if DEBUGNATOF
193*5805Srrh 		printf("Dividing: ");
194*5805Srrh 		bignumprint(Acc);
195*5805Srrh 		printf("\n");
196*5805Srrh #endif DEBUGNATOF
197*5805Srrh 		sptr = (short *)acc;
198*5805Srrh 		for (i = (CH_N * 2 - 1); i >= 1; --i){
199*5805Srrh 			/*
200*5805Srrh 			 *	Divide (remainder:16).(acc[i]:16)
201*5805Srrh 			 *	by 5, putting the quotient back
202*5805Srrh 			 *	into acc[i]:16, and save the remainder
203*5805Srrh 			 *	for the next iteration.
204*5805Srrh 			 */
205*5805Srrh 			dividend = (remainder << 16) | (sptr[i] & ONES(16));
206*5805Srrh 			assert(dividend >= 0, "dividend < 0");
207*5805Srrh 			quotient = dividend / 5;
208*5805Srrh 			remainder = dividend - (quotient * 5);
209*5805Srrh 			sptr[i] = quotient;
210*5805Srrh 			remainder = remainder;
211*5805Srrh 		}
212*5805Srrh 		/*
213*5805Srrh 		 *	Divide the lowest order chunk by 10,
214*5805Srrh 		 *	saving the remainder to decide how to round.
215*5805Srrh 		 *	Then, multiply by 2, making it look as
216*5805Srrh 		 *	if we divided by 10.
217*5805Srrh 		 *	This multiply fills in a 0 on the least sig bit.
218*5805Srrh 		 */
219*5805Srrh 		dividend = (remainder << 16) | (sptr[0] & ONES(16));
220*5805Srrh 		assert(dividend >= 0, "dividend < 0");
221*5805Srrh 		quotient = dividend / 10;
222*5805Srrh 		remainder = dividend - (quotient * 10);
223*5805Srrh 		sptr[0] = quotient + quotient;
224*5805Srrh 
225*5805Srrh 		if (remainder >= 5)
226*5805Srrh 			ovf = numaddd(acc, acc, 1);
227*5805Srrh 		/*
228*5805Srrh 		 *	Now, divide by 2, effecting division by 10,
229*5805Srrh 		 *	merely by adjusting the binary exponent.
230*5805Srrh 		 */
231*5805Srrh 		bexponent--;
232*5805Srrh 	}
233*5805Srrh 	/*
234*5805Srrh 	 *	Scale the number up by multiplying by 10 as
235*5805Srrh 	 *	many times as necessary
236*5805Srrh 	 */
237*5805Srrh 	for (; dexponent > 0; dexponent--){
238*5805Srrh 		/*
239*5805Srrh 		 *	Compare high word to (2**31)/5,
240*5805Srrh 		 *	and scale accordingly
241*5805Srrh 		 */
242*5805Srrh 		while ( ((unsigned)acc[HOC]) > MAXINT_5){
243*5805Srrh 			(void)numshift(-1, acc, acc);
244*5805Srrh 			bexponent++;
245*5805Srrh 		}
246*5805Srrh 		/*
247*5805Srrh 		 *	multiply the mantissa by 5,
248*5805Srrh 		 *	and scale the binary exponent by 2
249*5805Srrh 		 */
250*5805Srrh 		ovf = numshift(2, temp, acc);
251*5805Srrh 		ovf |= numaddv(acc, acc, temp);
252*5805Srrh 		assert(ovf == 0, "Scaling * 10 of manitissa");
253*5805Srrh 		bexponent++;
254*5805Srrh 	}
255*5805Srrh 	/*
256*5805Srrh 	 *	We now have:
257*5805Srrh 	 *	a CH_N chunk length binary integer, right
258*5805Srrh 	 *		justified (in native format).
259*5805Srrh 	 *	a binary exponent.
260*5805Srrh 	 *
261*5805Srrh 	 *	Now, we treat this large integer as an octa word
262*5805Srrh 	 *	number, and unpack it into standard unpacked
263*5805Srrh 	 *	format.  That unpacking will give us yet
264*5805Srrh 	 *	another binary exponent, which we adjust with
265*5805Srrh 	 *	the accumulated binary exponent.
266*5805Srrh 	 */
267*5805Srrh 	Acc.num_tag = TYPO;
268*5805Srrh #if DEBUGNATOF
269*5805Srrh 	printf("Octal number: ");
270*5805Srrh 	bignumprint(Acc);
271*5805Srrh 	printf("\n");
272*5805Srrh #endif DEBUGNATOF
273*5805Srrh 	Acc = bignumunpack(Acc, &ovf);
274*5805Srrh 
275*5805Srrh 	if (ovf)
276*5805Srrh 		errno = ERANGE;
277*5805Srrh #if DEBUGNATOF
278*5805Srrh 	printf("Unpacked octal number: ");
279*5805Srrh 	bignumprint(Acc);
280*5805Srrh 	printf("bexponent == %d\n", bexponent);
281*5805Srrh #endif DEBUGNATOF
282*5805Srrh 	Acc.num_exponent += bexponent;
283*5805Srrh 	assert(Acc.num_sign == 0, "unpacked integer is < 0");
284*5805Srrh 	Acc.num_sign = msign;
285*5805Srrh 	/*
286*5805Srrh 	 *	We now pack the number back into a radix format number.
287*5805Srrh 	 *	This checks for overflow, underflow,
288*5805Srrh 	 *	and rounds by 1/2 ulp.
289*5805Srrh 	 */
290*5805Srrh 	ovf = 0;
291*5805Srrh 	Acc = bignumpack(Acc, radix, &ovf);
292*5805Srrh 	if (ovf)
293*5805Srrh 		errno = ERANGE;
294*5805Srrh #if DEBUGNATOF
295*5805Srrh 	printf("packed number: ");
296*5805Srrh 	bignumprint(Acc);
297*5805Srrh 	printf("\n");
298*5805Srrh #endif DEBUGNATOF
299*5805Srrh 	return(Acc);
300*5805Srrh }
301*5805Srrh #if 0
302*5805Srrh /*
303*5805Srrh  *	Unfortunately, one can't use the ediv instruction to do
304*5805Srrh  *	division on numbers with > 64 bits.
305*5805Srrh  *	This is because ediv returns signed quantities;
306*5805Srrh  *	if the quotient is an unsigned number > 2^31,
307*5805Srrh  *	ediv sets integer overflow.
308*5805Srrh  */
309*5805Srrh unsigned int ediv(high, low, divisor, qp, i)
310*5805Srrh 	register	unsigned int	high;		/* r11 */
311*5805Srrh 	register	unsigned int	low;		/* r10 */
312*5805Srrh 	register	unsigned int	divisor;	/* r9 */
313*5805Srrh 			unsigned int	*qp;
314*5805Srrh {
315*5805Srrh 	register	unsigned int	remainder;	/* r8 */
316*5805Srrh 	register	unsigned int	quotient;	/* r7 */
317*5805Srrh 
318*5805Srrh 	asm("ediv r9, r10, r7, r8	# Divide.  q->r7, r->r8 (discarded)");
319*5805Srrh 	*qp = quotient;
320*5805Srrh 	return(remainder);
321*5805Srrh }
322*5805Srrh #endif 0
323