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