in kotlin-native/runtime/src/main/cpp/dtoa/dblparse.cpp [458:640]
KDouble doubleAlgorithm (U_64 * f, IDATA length, KInt e, KDouble z)
{
U_64 m;
IDATA k, comparison, comparison2;
U_64 *x, *y, *D, *D2;
IDATA xLength, yLength, DLength, D2Length, decApproxCount, incApproxCount;
//PORT_ACCESS_FROM_ENV (env);
x = y = D = D2 = 0;
xLength = yLength = DLength = D2Length = 0;
decApproxCount = incApproxCount = 0;
do
{
m = doubleMantissa (z);
k = doubleExponent (z);
if (x && x != f)
//jclmem_free_memory (env, x);
release(x);
release (y);
release (D);
release (D2);
if (e >= 0 && k >= 0)
{
xLength = sizeOfTenToTheE (e) + length;
allocateU64 (x, xLength);
memset (x + length, 0, sizeof (U_64) * (xLength - length));
memcpy (x, f, sizeof (U_64) * length);
timesTenToTheEHighPrecision (x, xLength, e);
yLength = (k >> 6) + 2;
allocateU64 (y, yLength);
memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
*y = m;
simpleShiftLeftHighPrecision (y, yLength, k);
}
else if (e >= 0)
{
xLength = sizeOfTenToTheE (e) + length + ((-k) >> 6) + 1;
allocateU64 (x, xLength);
memset (x + length, 0, sizeof (U_64) * (xLength - length));
memcpy (x, f, sizeof (U_64) * length);
timesTenToTheEHighPrecision (x, xLength, e);
simpleShiftLeftHighPrecision (x, xLength, -k);
yLength = 1;
allocateU64 (y, 1);
*y = m;
}
else if (k >= 0)
{
xLength = length;
x = f;
yLength = sizeOfTenToTheE (-e) + 2 + (k >> 6);
allocateU64 (y, yLength);
memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
*y = m;
timesTenToTheEHighPrecision (y, yLength, -e);
simpleShiftLeftHighPrecision (y, yLength, k);
}
else
{
xLength = length + ((-k) >> 6) + 1;
allocateU64 (x, xLength);
memset (x + length, 0, sizeof (U_64) * (xLength - length));
memcpy (x, f, sizeof (U_64) * length);
simpleShiftLeftHighPrecision (x, xLength, -k);
yLength = sizeOfTenToTheE (-e) + 1;
allocateU64 (y, yLength);
memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
*y = m;
timesTenToTheEHighPrecision (y, yLength, -e);
}
comparison = compareHighPrecision (x, xLength, y, yLength);
if (comparison > 0)
{ /* x > y */
DLength = xLength;
allocateU64 (D, DLength);
memcpy (D, x, DLength * sizeof (U_64));
subtractHighPrecision (D, DLength, y, yLength);
}
else if (comparison)
{ /* y > x */
DLength = yLength;
allocateU64 (D, DLength);
memcpy (D, y, DLength * sizeof (U_64));
subtractHighPrecision (D, DLength, x, xLength);
}
else
{ /* y == x */
DLength = 1;
allocateU64 (D, 1);
*D = 0;
}
D2Length = DLength + 1;
allocateU64 (D2, D2Length);
m <<= 1;
multiplyHighPrecision (D, DLength, &m, 1, D2, D2Length);
m >>= 1;
comparison2 = compareHighPrecision (D2, D2Length, y, yLength);
if (comparison2 < 0)
{
if (comparison < 0 && m == NORMAL_MASK)
{
simpleShiftLeftHighPrecision (D2, D2Length, 1);
if (compareHighPrecision (D2, D2Length, y, yLength) > 0)
{
DECREMENT_DOUBLE (z, decApproxCount, incApproxCount);
}
else
{
break;
}
}
else
{
break;
}
}
else if (comparison2 == 0)
{
if ((LOW_U32_FROM_VAR (m) & 1) == 0)
{
if (comparison < 0 && m == NORMAL_MASK)
{
DECREMENT_DOUBLE (z, decApproxCount, incApproxCount);
}
else
{
break;
}
}
else if (comparison < 0)
{
DECREMENT_DOUBLE (z, decApproxCount, incApproxCount);
break;
}
else
{
INCREMENT_DOUBLE (z, decApproxCount, incApproxCount);
break;
}
}
else if (comparison < 0)
{
DECREMENT_DOUBLE (z, decApproxCount, incApproxCount);
}
else
{
if (DOUBLE_TO_LONGBITS (z) == INFINITE_LONGBITS)
break;
INCREMENT_DOUBLE (z, decApproxCount, incApproxCount);
}
}
while (1);
if (x && x != f)
//jclmem_free_memory (env, x);
release(x);
release (y);
release (D);
release (D2);
return z;
OutOfMemory:
if (x && x != f)
//jclmem_free_memory (env, x);
release(x);
release (y);
release (D);
release (D2);
DOUBLE_TO_LONGBITS (z) = -2;
return z;
}