BignumDigit DestructiveScaleDown(BignumDigit denominator) { BignumDigit numerator; BignumDigit remainder = (BignumDigit)0L; BignumDigit twoDigits; int start = 0; int scan = start + this.Length; while (start < scan) { twoDigits = this [--scan]; numerator = new BignumDigit(remainder.ToLong(), twoDigits.High); remainder = (BignumDigit)(numerator.ToLong() / denominator.ToLong()); numerator = new BignumDigit(numerator.ToLong() % denominator.ToLong(), twoDigits.Low); this [scan] = new BignumDigit(remainder.ToLong(), numerator.ToLong() / denominator.ToLong()); remainder = (BignumDigit)(numerator.ToLong() % denominator.ToLong()); } return(remainder); }
BignumDigit DestructiveScaleDown (BignumDigit denominator) { BignumDigit numerator; BignumDigit remainder = (BignumDigit) 0L; BignumDigit twoDigits; int start = 0; int scan = start + this.Length; while (start < scan) { twoDigits = this [--scan]; numerator = new BignumDigit (remainder.ToLong (), twoDigits.High); remainder = (BignumDigit) (numerator.ToLong () / denominator.ToLong ()); numerator = new BignumDigit (numerator.ToLong () % denominator.ToLong (), twoDigits.Low); this [scan] = new BignumDigit (remainder.ToLong (), numerator.ToLong () / denominator.ToLong ()); remainder = (BignumDigit) (numerator.ToLong () % denominator.ToLong ()); } return remainder; }
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); } }