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