// See comments for InitialScaledStartValues private static void InitialScaledStartValuesNegativeExponentNegativePower( double v, int estimated_power, bool need_boundary_deltas, Bignum numerator, Bignum denominator, Bignum delta_minus, Bignum delta_plus) { const ulong kMinimalNormalizedExponent = 0x0010000000000000; var bits = (ulong)BitConverter.DoubleToInt64Bits(v); ulong significand = DoubleHelper.Significand(bits); int exponent = DoubleHelper.Exponent(bits); // Instead of multiplying the denominator with 10^estimated_power we // multiply all values (numerator and deltas) by 10^-estimated_power. // Use numerator as temporary container for power_ten. Bignum power_ten = numerator; power_ten.AssignPowerUInt16(10, -estimated_power); if (need_boundary_deltas) { // Since power_ten == numerator we must make a copy of 10^estimated_power // before we complete the computation of the numerator. // delta_plus = delta_minus = 10^estimated_power delta_plus.AssignBignum(power_ten); delta_minus.AssignBignum(power_ten); } // numerator = significand * 2 * 10^-estimated_power // since v = significand * 2^exponent this is equivalent to // numerator = v * 10^-estimated_power * 2 * 2^-exponent. // Remember: numerator has been abused as power_ten. So no need to assign it // to itself. numerator.MultiplyByUInt64(significand); // denominator = 2 * 2^-exponent with exponent < 0. denominator.AssignUInt16(1); denominator.ShiftLeft(-exponent); if (need_boundary_deltas) { // Introduce a common denominator so that the deltas to the boundaries are // integers. numerator.ShiftLeft(1); denominator.ShiftLeft(1); // With this shift the boundaries have their correct value, since // delta_plus = 10^-estimated_power, and // delta_minus = 10^-estimated_power. // These assignments have been done earlier. // The special case where the lower boundary is twice as close. // This time we have to look out for the exception too. ulong v_bits = bits; if ((v_bits & DoubleHelper.KSignificandMask) == 0 && // The only exception where a significand == 0 has its boundaries at // "normal" distances: (v_bits & DoubleHelper.KExponentMask) != kMinimalNormalizedExponent) { numerator.ShiftLeft(1); // *2 denominator.ShiftLeft(1); // *2 delta_plus.ShiftLeft(1); // *2 } } }