private void Init (string format, double value, int defPrecision)
{
Init (format);
_defPrecision = defPrecision;
long bits = BitConverter.DoubleToInt64Bits (value);
_positive = bits >= 0;
bits &= Int64.MaxValue;
if (bits == 0) {
_decPointPos = 1;
_digitsLen = 0;
_positive = true;
return;
}
int e = (int)(bits >> DoubleBitsExponentShift);
long m = bits & DoubleBitsMantissaMask;
if (e == DoubleBitsExponentMask) {
_NaN = m != 0;
_infinity = m == 0;
return;
}
int expAdjust = 0;
if (e == 0) {
// We need 'm' to be large enough so we won't lose precision.
e = 1;
int scale = ScaleOrder (m);
if (scale < DoubleDefPrecision) {
expAdjust = scale - DoubleDefPrecision;
m *= GetTenPowerOf (-expAdjust);
}
}
else {
m = (m + DoubleBitsMantissaMask + 1) * 10;
expAdjust = -1;
}
// multiply the mantissa by 10 ^ N
ulong lo = (uint)m;
ulong hi = (ulong)m >> 32;
ulong lo2 = MantissaBitsTable [e];
ulong hi2 = lo2 >> 32;
lo2 = (uint)lo2;
ulong mm = hi * lo2 + lo * hi2 + ((lo * lo2) >> 32);
long res = (long)(hi * hi2 + (mm >> 32));
while (res < SeventeenDigitsThreshold) {
mm = (mm & UInt32.MaxValue) * 10;
res = res * 10 + (long)(mm >> 32);
expAdjust--;
}
if ((mm & 0x80000000) != 0)
res++;
int order = DoubleDefPrecision + 2;
_decPointPos = TensExponentTable [e] + expAdjust + order;
// Rescale 'res' to the initial precision (15-17 for doubles).
int initialPrecision = InitialFloatingPrecision ();
if (order > initialPrecision) {
long val = GetTenPowerOf (order - initialPrecision);
res = (res + (val >> 1)) / val;
order = initialPrecision;
}
if (res >= GetTenPowerOf (order)) {
order++;
_decPointPos++;
}
InitDecHexDigits ((ulong)res);
_offset = CountTrailingZeros ();
_digitsLen = order - _offset;
}