public double ReadFlonum(FaslFile file, uint offset) { //EncodedObject header = this [arg0Offset]; byte b0 = ReadByte(offset + 4); byte b1 = ReadByte(offset + 5); byte b2 = ReadByte(offset + 6); byte b3 = ReadByte(offset + 7); byte b4 = ReadByte(offset + 8); byte b5 = ReadByte(offset + 9); byte b6 = ReadByte(offset + 10); byte b7 = ReadByte(offset + 11); if ((b0 == 0) && (b1 == 0) && (b2 == 0) && (b3 == 0) && (b4 == 0) && (b5 == 0) && (b6 == 0) && (b7 == 0)) { return(0.0); } int encodedExponent = (b7 & 0x7F) << 4; encodedExponent += (b6 & 0xF0) >> 4; long mantissa = (encodedExponent == 0) ? 0 : 1; mantissa *= 16; mantissa += b6 & 0x0F; mantissa *= 256; mantissa += b5; mantissa *= 256; mantissa += b4; mantissa *= 256; mantissa += b3; mantissa *= 256; mantissa += b2; mantissa *= 256; mantissa += b1; mantissa *= 256; mantissa += b0; int exponent = -(1024 + 51); exponent += encodedExponent; int sign = ((b7 & 0x80) == 0) ? 1 : -1; double answer = FloatArithmetic.EncodeFloat(sign, exponent, mantissa); return(answer); }
public double ToDouble() { if (this.IsZero) { return(0.0); } { int length = this.Length; int index = length - 1; int scale_words = length - 1; BignumDigit msd = this [index]; int bits_to_get = 53; //DBL_MANT_DIG; /* includes implicit 1 */ double value = 0; long mask = 0; long guard_bit_mask = BIGNUM_RADIX >> 1; long rounding_correction = 0; int current_digit_bit_count = 0; long w = msd.ToLong(); current_digit_bit_count = 0; while (w > 0xff) { current_digit_bit_count += 8; w >>= 8; } while (w > 0) { current_digit_bit_count += 1; w >>= 1; } mask = (1 << (current_digit_bit_count)) - 1; while (true) { if (current_digit_bit_count > bits_to_get) { guard_bit_mask = (1 << (current_digit_bit_count - bits_to_get - 1)); mask &= ~((guard_bit_mask << 1) - 1); current_digit_bit_count = bits_to_get; bits_to_get = 0; } else { bits_to_get -= current_digit_bit_count; } value = (value * BIGNUM_RADIX) + (this [index].ToLong() & mask); if (bits_to_get == 0) { scale_words = index; if (current_digit_bit_count == BIGNUM_DIGIT_LENGTH) { if (index == 0) /* there is no guard bit */ { goto finished; } guard_bit_mask = (1 << (BIGNUM_DIGIT_LENGTH - 1)); rounding_correction = 1; index -= 1; } else { rounding_correction = (guard_bit_mask << 1); } break; } if (index == 0) /* fewer than DBL_MANT_DIG bits */ { goto finished; } index -= 1; current_digit_bit_count = BIGNUM_DIGIT_LENGTH; mask = BIGNUM_DIGIT_MASK; } /* round-to-even depending on lsb, guard and following bits: lgfffff */ if ((this [index].ToLong() & guard_bit_mask) == 0) /* case x0xxxx */ { goto round_down; } if ((this [index].ToLong() & (guard_bit_mask - 1)) != 0) /* case x1xx1x */ { goto round_up; } /* cases 110000 and 1101xx: test "odd?", i.e. round-to-even rounds up */ if ((guard_bit_mask << 1) == BIGNUM_RADIX) { if ((this [index + 1].ToLong() & 1) != 0) /* "odd?" */ { goto round_up; } } else { if ((this [index].ToLong() & (guard_bit_mask << 1)) != 0) { goto round_up; } } if (index == 0) /* case 010000, no more words of following bits */ { goto finished; } { /* distinguish between cases 0100...00 and 0100..1xx, multiple words */ int index2 = index - 1; while (index2 >= 0) { if (this [index] != 0) { goto round_up; } index2--; } goto round_down; } round_up: value += rounding_correction; round_down: /* note, ldexp `sticks' at the maximal non-infinity value, which * is a reasonable compromise for numbers with DBL_MAX_EXP bits * that round up */ if (scale_words > 0) { value = FloatArithmetic.LdExp(value, scale_words * BIGNUM_DIGIT_LENGTH); } finished: return(this.IsNegative ? (-value) : value); } }