* Copyright (c) 1982 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)natof.c 5.1 (Berkeley) %G%";
Bignum
bigatof(str
, radix
)
int radix
; /* TYPF ... TYPH */
reg chptr temp
; /* r10 */
reg u_int quotient
; /* r9 */ /* must be here */
reg u_int remainder
; /* r8 */ /* must be here */
reg
int dividend
; /* for doing division */
short *sptr
; /* for doing division */
int dexponent
; /* decimal exponent */
int bexponent
; /* binary exponent */
for(; isdigit(ch
); ch
= *str
++){
assert(((acc
[HOC
] & SIGNBIT
) == 0), "Negative HOC");
if (acc
[HOC
] < MAXINT_10
){
ovf
= numshift(3, temp
, acc
);
ovf
|= numshift(1, acc
, acc
);
ovf
|= numaddv(acc
, temp
, acc
);
ovf
|= numaddd(acc
, acc
, ch
- '0');
assert(ovf
== 0, "Overflow building mantissa");
* Then, the number is too large anyway
* only 'e' and 'E' are recognized by atof()
* we include the remainder for compatability with as formats
* in as, the radix actual paramater agrees with the character
* we expect; consequently, no checking is done.
for(; isdigit(ch
); ch
= *str
++){
* outrageously large exponent
* There should be a range check on dexponent here
* The number has now been reduced to a mantissa
* The mantissa is an n bit number (to the precision
* of the extended words) in the acc.
* The exponent is a signed power of 10 in dexponent.
* msign is on if the resulting number will eventually
* We now must convert the number to standard format floating
* number, which will be done by accumulating
* a binary exponent in bexponent, as we gradually
* drive dexponent towards zero, one count at a time.
* We must divide acc by 10 as many times as needed.
for (; dexponent
< 0; dexponent
++){
* Align the number so that the most significant
* bits are aligned in the most significant
* bits of the accumulator, adjusting the
* binary exponent as we shift.
* The goal is to get the high order bit (NOT the
assert(((acc
[HOC
] & SIGNBIT
) == 0), "Negative HOC");
for (j
= 5; j
>= 1; --j
){
i
= 1 << (j
- 1); /* 16, 8, 4, 2, 1 */
quotient
<<= (CH_BITS
- 1) - i
;
while((acc
[HOC
] & quotient
) == 0){
ovf
|= numshift((int)i
, acc
, acc
);
* Add 2 to the accumulator to effect rounding,
* and get set up to divide by 5.
ovf
= numaddd(acc
, acc
, 2);
assert(ovf
== 0, "Carry out of left rounding up by 2");
* Divide the high order chunks by 5;
* The last chunk will be divided by 10,
* (to see what the remainder is, also to effect rounding)
* and then multipiled by 2 to effect division by 5.
for (i
= (CH_N
* 2 - 1); i
>= 1; --i
){
* Divide (remainder:16).(acc[i]:16)
* by 5, putting the quotient back
* into acc[i]:16, and save the remainder
* for the next iteration.
dividend
= (remainder
<< 16) | (sptr
[i
] & ONES(16));
assert(dividend
>= 0, "dividend < 0");
remainder
= dividend
- (quotient
* 5);
* Divide the lowest order chunk by 10,
* saving the remainder to decide how to round.
* Then, multiply by 2, making it look as
* This multiply fills in a 0 on the least sig bit.
dividend
= (remainder
<< 16) | (sptr
[0] & ONES(16));
assert(dividend
>= 0, "dividend < 0");
quotient
= dividend
/ 10;
remainder
= dividend
- (quotient
* 10);
sptr
[0] = quotient
+ quotient
;
ovf
= numaddd(acc
, acc
, 1);
* Now, divide by 2, effecting division by 10,
* merely by adjusting the binary exponent.
* Scale the number up by multiplying by 10 as
* many times as necessary
for (; dexponent
> 0; dexponent
--){
* Compare high word to (2**31)/5,
while ( ((unsigned)acc
[HOC
]) > MAXINT_5
){
(void)numshift(-1, acc
, acc
);
* multiply the mantissa by 5,
* and scale the binary exponent by 2
ovf
= numshift(2, temp
, acc
);
ovf
|= numaddv(acc
, acc
, temp
);
assert(ovf
== 0, "Scaling * 10 of manitissa");
* a CH_N chunk length binary integer, right
* justified (in native format).
* Now, we treat this large integer as an octa word
* number, and unpack it into standard unpacked
* format. That unpacking will give us yet
* another binary exponent, which we adjust with
* the accumulated binary exponent.
printf("Octal number: ");
Acc
= bignumunpack(Acc
, &ovf
);
printf("Unpacked octal number: ");
printf("bexponent == %d\n", bexponent
);
Acc
.num_exponent
+= bexponent
;
assert(Acc
.num_sign
== 0, "unpacked integer is < 0");
* We now pack the number back into a radix format number.
* This checks for overflow, underflow,
Acc
= bignumpack(Acc
, radix
, &ovf
);
printf("packed number: ");
* Unfortunately, one can't use the ediv instruction to do
* division on numbers with > 64 bits.
* This is because ediv returns signed quantities;
* if the quotient is an unsigned number > 2^31,
* ediv sets integer overflow.
unsigned int ediv(high
, low
, divisor
, qp
, i
)
register unsigned int high
; /* r11 */
register unsigned int low
; /* r10 */
register unsigned int divisor
; /* r9 */
register unsigned int remainder
; /* r8 */
register unsigned int quotient
; /* r7 */
asm("ediv r9, r10, r7, r8 # Divide. q->r7, r->r8 (discarded)");