mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
1640 lines
36 KiB
Java
1640 lines
36 KiB
Java
/*
|
|
* @(#) $(JCGO)/goclsp/vm/java/lang/VMDouble.java --
|
|
* VM specific methods for Java "Double" class.
|
|
**
|
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
|
* Copyright (C) 2001-2009 Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* All rights reserved.
|
|
**
|
|
* Class specification origin: GNU Classpath v0.93 vm/reference
|
|
*/
|
|
|
|
/*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
**
|
|
* This software is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License (GPL) for more details.
|
|
**
|
|
* Linking this library statically or dynamically with other modules is
|
|
* making a combined work based on this library. Thus, the terms and
|
|
* conditions of the GNU General Public License cover the whole
|
|
* combination.
|
|
**
|
|
* As a special exception, the copyright holders of this library give you
|
|
* permission to link this library with independent modules to produce an
|
|
* executable, regardless of the license terms of these independent
|
|
* modules, and to copy and distribute the resulting executable under
|
|
* terms of your choice, provided that you also meet, for each linked
|
|
* independent module, the terms and conditions of the license of that
|
|
* module. An independent module is a module which is not derived from
|
|
* or based on this library. If you modify this library, you may extend
|
|
* this exception to your version of the library, but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
package java.lang;
|
|
|
|
final class VMDouble
|
|
{
|
|
|
|
private static final class FDBigInt
|
|
{
|
|
|
|
private int nWords;
|
|
|
|
private int[] data;
|
|
|
|
FDBigInt(int v)
|
|
{
|
|
nWords = 1;
|
|
data = new int[1];
|
|
data[0] = v;
|
|
}
|
|
|
|
FDBigInt(long v)
|
|
{
|
|
data = new int[2];
|
|
data[0] = (int) v;
|
|
data[1] = (int) (v >>> 32);
|
|
nWords = data[1] != 0 ? 2 : 1;
|
|
}
|
|
|
|
FDBigInt(FDBigInt other)
|
|
{
|
|
nWords = other.nWords;
|
|
data = new int[nWords];
|
|
VMSystem.arraycopy(other.data, 0, data, 0, nWords);
|
|
}
|
|
|
|
FDBigInt(long l, char[] ac, int i, int j)
|
|
{
|
|
int k = (j + 8) / 9;
|
|
if (k < 2)
|
|
k = 2;
|
|
data = new int[k];
|
|
data[0] = (int) l;
|
|
data[1] = (int) (l >>> 32);
|
|
nWords = 1;
|
|
if (data[1] != 0)
|
|
nWords = 2;
|
|
int i1 = i;
|
|
int l1 = j - 5;
|
|
while (i1 < l1)
|
|
{
|
|
int i2 = i1 + 5;
|
|
int j1 = ac[i1++] - '0';
|
|
while (i1 < i2)
|
|
j1 = 10 * j1 + ac[i1++] - '0';
|
|
multaddMe(100000, j1);
|
|
}
|
|
int j2 = 1;
|
|
int k1 = 0;
|
|
while (i1 < j)
|
|
{
|
|
k1 = 10 * k1 + ac[i1++] - '0';
|
|
j2 *= 10;
|
|
}
|
|
if (j2 != 1)
|
|
multaddMe(j2, k1);
|
|
}
|
|
|
|
private FDBigInt(int[] ai, int i)
|
|
{
|
|
data = ai;
|
|
nWords = i;
|
|
}
|
|
|
|
void lshiftMe(int i)
|
|
throws IllegalArgumentException
|
|
{
|
|
if (i <= 0)
|
|
{
|
|
if (i == 0)
|
|
return;
|
|
throw new IllegalArgumentException("negative shift count");
|
|
}
|
|
int j = i >> 5;
|
|
int k = i & 0x1f;
|
|
int l = 32 - k;
|
|
int[] ai = data;
|
|
int[] ai1 = data;
|
|
if (nWords + j >= ai.length)
|
|
ai = new int[nWords + j + 1];
|
|
int i1 = nWords + j;
|
|
int j1 = nWords - 1;
|
|
if (k == 0)
|
|
{
|
|
VMSystem.arraycopy(ai1, 0, ai, j, nWords);
|
|
i1 = j - 1;
|
|
}
|
|
else
|
|
{
|
|
for (ai[i1--] = ai1[j1] >>> l; j1 >= 1; ai[i1--] |= ai1[--j1] >>> l)
|
|
ai[i1] = ai1[j1] << k;
|
|
ai[i1--] = ai1[j1] << k;
|
|
}
|
|
while (i1 >= 0)
|
|
ai[i1--] = 0;
|
|
data = ai;
|
|
nWords += j + 1;
|
|
while (nWords > 1 && data[nWords - 1] == 0)
|
|
nWords--;
|
|
}
|
|
|
|
int normalizeMe()
|
|
throws IllegalArgumentException
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
int k = 0;
|
|
int l;
|
|
for (l = nWords - 1; l >= 0 && (k = data[l]) == 0; l--)
|
|
i++;
|
|
if (l < 0)
|
|
throw new IllegalArgumentException("zero value");
|
|
nWords -= i;
|
|
if ((k & 0xf0000000) != 0)
|
|
{
|
|
for (j = 32; (k & 0xf0000000) != 0; j--)
|
|
k >>>= 1;
|
|
}
|
|
else
|
|
{
|
|
while (k <= 0xfffff)
|
|
{
|
|
k <<= 8;
|
|
j += 8;
|
|
}
|
|
while (k <= 0x7ffffff)
|
|
{
|
|
k <<= 1;
|
|
j++;
|
|
}
|
|
}
|
|
if (j != 0)
|
|
lshiftMe(j);
|
|
return j;
|
|
}
|
|
|
|
FDBigInt mult(int i)
|
|
{
|
|
long l = i;
|
|
int[] ai = new int[l * ((long) data[nWords - 1] & 0xffffffffL) >
|
|
0xfffffffL ? nWords + 1 : nWords];
|
|
long l1 = 0L;
|
|
for (int j = 0; j < nWords; l1 >>>= 32)
|
|
{
|
|
l1 += ((long) data[j] & 0xffffffffL) * l;
|
|
ai[j++] = (int) l1;
|
|
}
|
|
if (l1 == 0L)
|
|
return new FDBigInt(ai, nWords);
|
|
ai[nWords] = (int) l1;
|
|
return new FDBigInt(ai, nWords + 1);
|
|
}
|
|
|
|
private void multaddMe(int i, int j)
|
|
{
|
|
long l = i;
|
|
long l1 = ((long) data[0] & 0xffffffffL) * l + ((long) j & 0xffffffffL);
|
|
data[0] = (int) l1;
|
|
l1 >>>= 32;
|
|
for (int k = 1; k < nWords; l1 >>>= 32)
|
|
{
|
|
l1 += l * ((long) data[k] & 0xffffffffL);
|
|
data[k++] = (int) l1;
|
|
}
|
|
if (l1 != 0L)
|
|
data[nWords++] = (int) l1;
|
|
}
|
|
|
|
FDBigInt mult(FDBigInt other)
|
|
{
|
|
int[] ai = new int[nWords + other.nWords];
|
|
for (int i = 0; i < nWords; i++)
|
|
{
|
|
long l = (long) data[i] & 0xffffffffL;
|
|
long l1 = 0L;
|
|
int k;
|
|
for (k = 0; k < other.nWords; k++)
|
|
{
|
|
l1 += ((long) ai[i + k] & 0xffffffffL) +
|
|
((long) other.data[k] & 0xffffffffL) * l;
|
|
ai[i + k] = (int) l1;
|
|
l1 >>>= 32;
|
|
}
|
|
ai[i + k] = (int) l1;
|
|
}
|
|
int j = ai.length - 1;
|
|
while (j > 0 && ai[j] == 0)
|
|
j--;
|
|
return new FDBigInt(ai, j + 1);
|
|
}
|
|
|
|
FDBigInt add(FDBigInt other)
|
|
{
|
|
long l = 0L;
|
|
int[] ai;
|
|
int[] ai1;
|
|
int i;
|
|
int j;
|
|
if (nWords >= other.nWords)
|
|
{
|
|
ai = data;
|
|
i = nWords;
|
|
ai1 = other.data;
|
|
j = other.nWords;
|
|
}
|
|
else
|
|
{
|
|
ai = other.data;
|
|
i = other.nWords;
|
|
ai1 = data;
|
|
j = nWords;
|
|
}
|
|
int[] ai2 = new int[i];
|
|
int k;
|
|
for (k = 0; k < i; l >>= 32)
|
|
{
|
|
l += (long) ai[k] & 0xffffffffL;
|
|
if (k < j)
|
|
l += (long) ai1[k] & 0xffffffffL;
|
|
ai2[k++] = (int) l;
|
|
}
|
|
if (l != 0L)
|
|
{
|
|
int[] ai3 = new int[i + 1];
|
|
VMSystem.arraycopy(ai2, 0, ai3, 0, i);
|
|
ai3[k++] = (int) l;
|
|
ai2 = ai3;
|
|
}
|
|
return new FDBigInt(ai2, k);
|
|
}
|
|
|
|
FDBigInt sub(FDBigInt other)
|
|
{
|
|
int[] ai = new int[nWords];
|
|
int i = nWords;
|
|
int j = other.nWords;
|
|
int k = 0;
|
|
long l = 0L;
|
|
int i1;
|
|
for (i1 = 0; i1 < i; l >>= 32)
|
|
{
|
|
l += (long) data[i1] & 0xffffffffL;
|
|
if (i1 < j)
|
|
l -= (long) other.data[i1] & 0xffffffffL;
|
|
if ((ai[i1++] = (int) l) == 0)
|
|
k++;
|
|
else k = 0;
|
|
}
|
|
if (l != 0L)
|
|
throw new InternalError("FP assertion: borrow out of subtract");
|
|
while (i1 < j)
|
|
if (other.data[i1++] != 0)
|
|
throw new InternalError("FP assertion: negative result of subtract");
|
|
return new FDBigInt(ai, i - k);
|
|
}
|
|
|
|
int cmp(FDBigInt other)
|
|
{
|
|
int i;
|
|
if (nWords > other.nWords)
|
|
{
|
|
int j = other.nWords - 1;
|
|
for (i = nWords - 1; i > j; i--)
|
|
if (data[i] != 0)
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
if (nWords < other.nWords)
|
|
{
|
|
for (i = other.nWords - 1; i >= nWords; i--)
|
|
if (other.data[i] != 0)
|
|
return -1;
|
|
}
|
|
else i = nWords - 1;
|
|
}
|
|
while (i > 0 && data[i] == other.data[i])
|
|
i--;
|
|
int k = data[i];
|
|
int l = other.data[i];
|
|
return k < 0 ? (l < 0 ? k - l : 1) : l < 0 ? -1 : k - l;
|
|
}
|
|
|
|
int quoRemIteration(FDBigInt other)
|
|
throws IllegalArgumentException
|
|
{
|
|
if (nWords != other.nWords)
|
|
throw new IllegalArgumentException("disparate values");
|
|
int i = nWords - 1;
|
|
long l = ((long) data[i] & 0xffffffffL) / (long) other.data[i];
|
|
long l1 = 0L;
|
|
for (int j = 0; j <= i; l1 >>= 32)
|
|
{
|
|
l1 += ((long) data[j] & 0xffffffffL) -
|
|
l * ((long) other.data[j] & 0xffffffffL);
|
|
data[j++] = (int) l1;
|
|
}
|
|
long l3;
|
|
if (l1 != 0L)
|
|
do
|
|
{
|
|
l3 = 0L;
|
|
for (int k = 0; k <= i; l3 >>= 32)
|
|
{
|
|
l3 += ((long) data[k] & 0xffffffffL) +
|
|
((long) other.data[k] & 0xffffffffL);
|
|
data[k++] = (int) l3;
|
|
}
|
|
if (l3 != 0L && l3 != 1L)
|
|
throw new InternalError("FP assertion: ".concat(
|
|
Long.toString(l3)).concat(" carry out of division correction"));
|
|
l--;
|
|
} while (l3 == 0L);
|
|
l3 = 0L;
|
|
for (int i1 = 0; i1 <= i; l3 >>= 32)
|
|
{
|
|
l3 += ((long) data[i1] & 0xffffffffL) * 10L;
|
|
data[i1++] = (int) l3;
|
|
}
|
|
if (l3 != 0L)
|
|
throw new InternalError("FP assertion: carry out of *10");
|
|
return (int) l;
|
|
}
|
|
}
|
|
|
|
private static final class FloatingDecimal
|
|
{
|
|
|
|
private static final long signMask = 0x8000000000000000L;
|
|
|
|
private static final long expMask = 0x7ff0000000000000L;
|
|
|
|
private static final long fractMask = 0xfffffffffffffL;
|
|
|
|
private static final int expShift = 52;
|
|
|
|
private static final int expBias = 0x3ff;
|
|
|
|
private static final long fractHOB = 0x10000000000000L;
|
|
|
|
private static final int maxSmallBinExp = 62;
|
|
|
|
private static final int minSmallBinExp = -(63 / 3);
|
|
|
|
private static final int maxDecimalDigits = 15;
|
|
|
|
private static final int maxDecimalExponent = 308;
|
|
|
|
private static final int minDecimalExponent = -324;
|
|
|
|
private static final int bigDecimalExponent = 324;
|
|
|
|
private static final int singleSignMask = 0x80000000;
|
|
|
|
private static final int singleExpMask = 0x7f800000;
|
|
|
|
private static final int singleFractMask = ~(singleSignMask | singleExpMask);
|
|
|
|
private static final int singleExpShift = 23;
|
|
|
|
private static final int singleFractHOB = 1 << singleExpShift;
|
|
|
|
private static final int singleExpBias = 127;
|
|
|
|
private static final int singleMaxDecimalDigits = 7;
|
|
|
|
private static final int singleMaxDecimalExponent = 38;
|
|
|
|
private static final int singleMinDecimalExponent = -45;
|
|
|
|
private static volatile FDBigInt[] b5p = new FDBigInt[8];
|
|
|
|
private static final char[] infinity =
|
|
{
|
|
'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'
|
|
};
|
|
|
|
private static final char[] notANumber =
|
|
{
|
|
'N', 'a', 'N'
|
|
};
|
|
|
|
private static final char[] zero =
|
|
{
|
|
'0', '0', '0', '0', '0', '0', '0', '0'
|
|
};
|
|
|
|
private static final double[] small10pow =
|
|
{
|
|
1.0, 10.0, 100.0, 1000.0, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
|
|
1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19,
|
|
1.0e20, 1.0e21, 1.0e22
|
|
};
|
|
|
|
private static final int maxSmallTen = 22 /* small10pow.length - 1 */;
|
|
|
|
private static final float[] singleSmall10pow =
|
|
{
|
|
1.0F, 10.0F, 100.0F, 1000.0F, 1.0e4F, 1.0e5F, 1.0e6F, 1.0e7F, 1.0e8F,
|
|
1.0e9F, 1.0e10F
|
|
};
|
|
|
|
private static final int singleMaxSmallTen =
|
|
10 /* singleSmall10pow.length - 1 */;
|
|
|
|
private static final double[] big10pow =
|
|
{
|
|
1e16, 1e32, 1e64, 1e128, 1e256
|
|
};
|
|
|
|
private static final double[] tiny10pow =
|
|
{
|
|
1e-16, 1e-32, 1e-64, 1e-128, 1e-256
|
|
};
|
|
|
|
private static final int[] n5bits =
|
|
{
|
|
0, 3, 5, 7, 10, 12, 14, 17, 19, 21, 24, 26, 28, 31, 33, 35, 38, 40, 42,
|
|
45, 47, 49, 52, 54, 56, 59, 61
|
|
};
|
|
|
|
private static final int[] small5pow =
|
|
{
|
|
1,
|
|
5,
|
|
5*5,
|
|
5*5*5,
|
|
5*5*5*5,
|
|
5*5*5*5*5,
|
|
5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5*5*5*5*5*5*5*5*5*5*5*5*5
|
|
};
|
|
|
|
private static final long[] long5pow =
|
|
{
|
|
1L,
|
|
5L,
|
|
5L*5,
|
|
5L*5*5,
|
|
5L*5*5*5,
|
|
5L*5*5*5*5,
|
|
5L*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
|
|
5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5
|
|
};
|
|
|
|
private boolean isExceptional;
|
|
|
|
private boolean isNegative;
|
|
|
|
private int decExponent;
|
|
|
|
private char[] digits;
|
|
|
|
private int nDigits;
|
|
|
|
private int bigIntExp;
|
|
|
|
private int bigIntNBits;
|
|
|
|
private boolean mustSetRoundDir;
|
|
|
|
private int roundDir;
|
|
|
|
FloatingDecimal(double d)
|
|
{
|
|
long l = doubleToRawLongBits(d);
|
|
if ((l & signMask) != 0L)
|
|
{
|
|
isNegative = true;
|
|
l ^= signMask;
|
|
}
|
|
else isNegative = false;
|
|
int i = (int) ((l & expMask) >> expShift);
|
|
long l1 = l & fractMask;
|
|
if (i == 0x7ff)
|
|
{
|
|
isExceptional = true;
|
|
if (l1 == 0L)
|
|
digits = infinity;
|
|
else
|
|
{
|
|
digits = notANumber;
|
|
isNegative = false;
|
|
}
|
|
nDigits = digits.length;
|
|
}
|
|
else
|
|
{
|
|
isExceptional = false;
|
|
int j;
|
|
if (i == 0)
|
|
{
|
|
if (l1 == 0L)
|
|
{
|
|
decExponent = 0;
|
|
digits = zero;
|
|
nDigits = 1;
|
|
return;
|
|
}
|
|
while ((~l1 & fractHOB) != 0L)
|
|
{
|
|
l1 <<= 1;
|
|
i--;
|
|
}
|
|
j = expShift + i + 1;
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
l1 |= fractHOB;
|
|
j = expShift + 1;
|
|
}
|
|
i -= expBias;
|
|
dtoa(i, l1, j);
|
|
}
|
|
}
|
|
|
|
FloatingDecimal(float f)
|
|
{
|
|
int i = VMFloat.floatToRawIntBits(f);
|
|
if ((i & singleSignMask) != 0)
|
|
{
|
|
isNegative = true;
|
|
i ^= singleSignMask;
|
|
}
|
|
else isNegative = false;
|
|
int j = (i & singleExpMask) >> singleExpShift;
|
|
int k = i & singleFractMask;
|
|
if (j == 0xff)
|
|
{
|
|
isExceptional = true;
|
|
if (k == 0)
|
|
digits = infinity;
|
|
else
|
|
{
|
|
digits = notANumber;
|
|
isNegative = false;
|
|
}
|
|
nDigits = digits.length;
|
|
}
|
|
else
|
|
{
|
|
isExceptional = false;
|
|
int l;
|
|
if (j == 0)
|
|
{
|
|
if (k == 0)
|
|
{
|
|
decExponent = 0;
|
|
digits = zero;
|
|
nDigits = 1;
|
|
return;
|
|
}
|
|
while ((~k & singleFractHOB) != 0)
|
|
{
|
|
k <<= 1;
|
|
j--;
|
|
}
|
|
l = singleExpShift + j + 1;
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
k |= singleFractHOB;
|
|
l = singleExpShift + 1;
|
|
}
|
|
j -= singleExpBias;
|
|
dtoa(j, (long) k << (expShift - singleExpShift), l);
|
|
}
|
|
}
|
|
|
|
private FloatingDecimal(boolean negSign, int i, char[] ac, int j,
|
|
boolean isExc)
|
|
{
|
|
isNegative = negSign;
|
|
decExponent = i;
|
|
digits = ac;
|
|
nDigits = j;
|
|
isExceptional = isExc;
|
|
}
|
|
|
|
private static int countBits(long l)
|
|
{
|
|
int i = 0;
|
|
if (l != 0L)
|
|
{
|
|
if (((int) l) == 0)
|
|
l >>= 32;
|
|
if (((short) l) == 0)
|
|
l >>= 16;
|
|
if (((byte) l) == 0)
|
|
l >>= 8;
|
|
while (((int) l & 1) == 0)
|
|
l >>= 1;
|
|
while ((l & 0xffL) != l)
|
|
{
|
|
l >>= 8;
|
|
i += 8;
|
|
}
|
|
int j = (int) l;
|
|
while (j != 0)
|
|
{
|
|
j >>= 1;
|
|
i++;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
private static FDBigInt big5pow(int i)
|
|
{
|
|
if (i < 0)
|
|
throw new InternalError("FP assertion: negative power of 5");
|
|
if (i < b5p.length && b5p[i] != null)
|
|
return b5p[i];
|
|
synchronized (FloatingDecimal.class)
|
|
{
|
|
if (b5p.length <= i)
|
|
{
|
|
FDBigInt[] afdbigint = new FDBigInt[(i >> 1) + i + 1];
|
|
VMSystem.arraycopy(b5p, 0, afdbigint, 0, b5p.length);
|
|
b5p = afdbigint;
|
|
}
|
|
if (b5p[i] != null)
|
|
return b5p[i];
|
|
if (i < small5pow.length)
|
|
return b5p[i] = new FDBigInt(small5pow[i]);
|
|
if (i < long5pow.length)
|
|
return b5p[i] = new FDBigInt(long5pow[i]);
|
|
int j = i >> 1;
|
|
int k = i - j;
|
|
FDBigInt fdbigint = b5p[j];
|
|
if (fdbigint == null)
|
|
fdbigint = big5pow(j);
|
|
if (k < small5pow.length)
|
|
return b5p[i] = fdbigint.mult(small5pow[k]);
|
|
FDBigInt fdbigint1 = b5p[k];
|
|
if (fdbigint1 == null)
|
|
fdbigint1 = big5pow(k);
|
|
return b5p[i] = fdbigint.mult(fdbigint1);
|
|
}
|
|
}
|
|
|
|
private static FDBigInt multPow52(FDBigInt fdbigint, int i, int j)
|
|
{
|
|
if (i != 0)
|
|
fdbigint = i < small5pow.length ? fdbigint.mult(small5pow[i]) :
|
|
fdbigint.mult(big5pow(i));
|
|
if (j != 0)
|
|
fdbigint.lshiftMe(j);
|
|
return fdbigint;
|
|
}
|
|
|
|
private static FDBigInt constructPow52(int i, int j)
|
|
{
|
|
FDBigInt fdbigint = new FDBigInt(big5pow(i));
|
|
if (j != 0)
|
|
fdbigint.lshiftMe(j);
|
|
return fdbigint;
|
|
}
|
|
|
|
private FDBigInt doubleToBigInt(double d)
|
|
{
|
|
long l = doubleToRawLongBits(d) & ~signMask;
|
|
int i = (int) (l >>> expShift);
|
|
l &= fractMask;
|
|
if (i > 0)
|
|
l |= fractHOB;
|
|
else
|
|
{
|
|
if (l == 0L)
|
|
throw new InternalError("FP assertion: doubleToBigInt(0)");
|
|
for (i++; (~l & fractHOB) != 0L; i--)
|
|
l <<= 1;
|
|
}
|
|
i -= expBias;
|
|
int j = countBits(l);
|
|
int k = expShift - j + 1;
|
|
bigIntExp = i - j + 1;
|
|
bigIntNBits = j;
|
|
return new FDBigInt(l >>> k);
|
|
}
|
|
|
|
private static double ulp(double d, boolean flag)
|
|
{
|
|
long l = doubleToRawLongBits(d) & ~signMask;
|
|
int i = (int) (l >>> expShift);
|
|
if (flag && i >= expShift && (l & fractMask) == 0L)
|
|
i--;
|
|
double d1 = i > expShift ?
|
|
longBitsToDouble((long) (i - expShift) << expShift) :
|
|
i != 0 ? longBitsToDouble(1L << (i - 1)) : Double.MIN_VALUE;
|
|
if (flag)
|
|
d1 = -d1;
|
|
return d1;
|
|
}
|
|
|
|
private float stickyRound(double d)
|
|
{
|
|
long l = doubleToRawLongBits(d);
|
|
long l1 = l & expMask;
|
|
return l1 == 0L || l1 == expMask ? (float) d :
|
|
(float) longBitsToDouble(l + (long) roundDir);
|
|
}
|
|
|
|
private void developLongDigits(int i, long l, long l1)
|
|
{
|
|
int j;
|
|
for (j = 0; l1 >= 10L; j++)
|
|
l1 /= 10L;
|
|
if (j != 0)
|
|
{
|
|
long l2 = long5pow[j] << j;
|
|
long l3 = l % l2;
|
|
l /= l2;
|
|
i += j;
|
|
if (l3 >= l2 >> 1)
|
|
l++;
|
|
}
|
|
char[] ac;
|
|
int k;
|
|
int i1;
|
|
if (l < 0x7fffffffL)
|
|
{
|
|
if (l <= 0L)
|
|
throw new InternalError("FP assertion: non-positive value ".concat(
|
|
Long.toString(l)));
|
|
int j1 = (int) l;
|
|
k = 10;
|
|
ac = new char[10];
|
|
i1 = k - 1;
|
|
int i2 = j1 % 10;
|
|
for (j1 /= 10; i2 == 0; i++)
|
|
{
|
|
i2 = j1 % 10;
|
|
j1 /= 10;
|
|
}
|
|
while (j1 != 0)
|
|
{
|
|
ac[i1--] = (char) (i2 + '0');
|
|
i++;
|
|
i2 = j1 % 10;
|
|
j1 /= 10;
|
|
}
|
|
ac[i1] = (char) (i2 + '0');
|
|
}
|
|
else
|
|
{
|
|
k = 20;
|
|
ac = new char[20];
|
|
i1 = k - 1;
|
|
int k1 = (int) (l % 10L);
|
|
for (l /= 10L; k1 == 0; i++)
|
|
{
|
|
k1 = (int) (l % 10L);
|
|
l /= 10L;
|
|
}
|
|
while (l != 0L)
|
|
{
|
|
ac[i1--] = (char) (k1 + '0');
|
|
i++;
|
|
k1 = (int) (l % 10L);
|
|
l /= 10L;
|
|
}
|
|
ac[i1] = (char) (k1 + '0');
|
|
}
|
|
k -= i1;
|
|
char[] ac1 = ac;
|
|
if (i1 != 0)
|
|
{
|
|
ac1 = new char[k];
|
|
VMSystem.arraycopy(ac, i1, ac1, 0, k);
|
|
}
|
|
digits = ac1;
|
|
decExponent = i + 1;
|
|
nDigits = k;
|
|
}
|
|
|
|
private void roundup()
|
|
{
|
|
int i = nDigits - 1;
|
|
char c = digits[i];
|
|
if (c == '9')
|
|
{
|
|
while (c == '9' && i > 0)
|
|
{
|
|
digits[i] = '0';
|
|
c = digits[--i];
|
|
}
|
|
if (c == '9')
|
|
{
|
|
decExponent++;
|
|
digits[0] = '1';
|
|
return;
|
|
}
|
|
}
|
|
digits[i] = (char) (c + 1);
|
|
}
|
|
|
|
private void dtoa(int i, long l, int j)
|
|
{
|
|
int k = countBits(l);
|
|
int i1 = k - i - 1;
|
|
if (i1 <= 0)
|
|
i1 = 0;
|
|
if (i <= maxSmallBinExp && i >= minSmallBinExp && i1 < long5pow.length &&
|
|
k + n5bits[i1] < 64 && i1 == 0)
|
|
{
|
|
long l1 = i > j ? 1L << (i - j - 1) : 0L;
|
|
if (i >= expShift)
|
|
l <<= i - expShift;
|
|
else l >>>= expShift - i;
|
|
developLongDigits(0, l, l1);
|
|
return;
|
|
}
|
|
int j1 = (int) (((((((l & ((1L << (expShift >> 1)) - 1L)) *
|
|
0x1287A762C9L) >>> (expShift >> 1)) + ((l & ~fractHOB) >>
|
|
(expShift >> 1)) * 0x1287A762C9L) >>> (64 - expShift)) +
|
|
(long) i * 0x4D104D427DE7EL + 0x8050250F0BBFL) >> expShift);
|
|
int k1 = -j1;
|
|
if (k1 <= 0)
|
|
k1 = 0;
|
|
int i2 = k1 + i1 + i;
|
|
int j2 = j1;
|
|
if (j2 <= 0)
|
|
j2 = 0;
|
|
int k2 = j2 + i1;
|
|
int l2 = k1;
|
|
int i3 = i2 - j;
|
|
l >>>= expShift - k + 1;
|
|
i2 -= k - 1;
|
|
int j3 = i2;
|
|
if (i2 >= k2)
|
|
j3 = k2;
|
|
i2 -= j3;
|
|
k2 -= j3;
|
|
i3 -= j3;
|
|
if (k == 1)
|
|
i3--;
|
|
if (i3 < 0)
|
|
{
|
|
i2 -= i3;
|
|
k2 -= i3;
|
|
i3 = 0;
|
|
}
|
|
char[] ac = new char[18];
|
|
int k3 = 0;
|
|
int l3 = (k1 < n5bits.length ? n5bits[k1] : k1 * 3) + k + i2;
|
|
int i4 = (j2 + 1 < n5bits.length ? n5bits[j2 + 1] : (j2 + 1) * 3) + k2 + 1;
|
|
digits = ac;
|
|
boolean flag;
|
|
boolean flag1;
|
|
long l4;
|
|
if (l3 < 64 && i4 < 64)
|
|
{
|
|
if (l3 < 32 && i4 < 32)
|
|
{
|
|
int j4 = ((int) l * small5pow[k1]) << i2;
|
|
int k4 = small5pow[j2] << k2;
|
|
int i5 = small5pow[l2] << i3;
|
|
int j5 = k4 * 10;
|
|
k3 = 0;
|
|
int i6 = j4 / k4;
|
|
j4 = 10 * (j4 % k4);
|
|
i5 *= 10;
|
|
flag = j4 < i5;
|
|
flag1 = j4 + i5 > j5;
|
|
if (i6 >= 10)
|
|
throw new InternalError("FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(i6)));
|
|
if (i6 == 0 && !flag1)
|
|
j1--;
|
|
else ac[k3++] = (char) (i6 + '0');
|
|
if (j1 <= -3 || j1 >= 8)
|
|
{
|
|
flag = false;
|
|
flag1 = false;
|
|
}
|
|
while (!flag && !flag1)
|
|
{
|
|
int j6 = j4 / k4;
|
|
j4 = 10 * (j4 % k4);
|
|
i5 *= 10;
|
|
if (j6 >= 10)
|
|
throw new InternalError("FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(j6)));
|
|
if (i5 > 0)
|
|
{
|
|
flag = j4 < i5;
|
|
flag1 = j4 + i5 > j5;
|
|
}
|
|
else
|
|
{
|
|
flag = true;
|
|
flag1 = true;
|
|
}
|
|
ac[k3++] = (char) (j6 + '0');
|
|
}
|
|
l4 = (j4 << 1) - j5;
|
|
}
|
|
else
|
|
{
|
|
long l5 = (l * long5pow[k1]) << i2;
|
|
long l6 = long5pow[j2] << k2;
|
|
long l7 = long5pow[l2] << i3;
|
|
long l8 = l6 * 10L;
|
|
k3 = 0;
|
|
int j7 = (int) (l5 / l6);
|
|
l5 = 10L * (l5 % l6);
|
|
l7 *= 10L;
|
|
flag = l5 < l7;
|
|
flag1 = l5 + l7 > l8;
|
|
if (j7 >= 10)
|
|
throw new InternalError("FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(j7)));
|
|
if (j7 == 0 && !flag1)
|
|
j1--;
|
|
else ac[k3++] = (char) (j7 + '0');
|
|
if (j1 <= -3 || j1 >= 8)
|
|
{
|
|
flag = false;
|
|
flag1 = false;
|
|
}
|
|
while (!flag && !flag1)
|
|
{
|
|
int k7 = (int) (l5 / l6);
|
|
l5 = 10L * (l5 % l6);
|
|
l7 *= 10L;
|
|
if (k7 >= 10)
|
|
throw new InternalError(
|
|
"FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(k7)));
|
|
if (l7 > 0L)
|
|
{
|
|
flag = l5 < l7;
|
|
flag1 = l5 + l7 > l8;
|
|
}
|
|
else
|
|
{
|
|
flag = true;
|
|
flag1 = true;
|
|
}
|
|
ac[k3++] = (char) (k7 + '0');
|
|
}
|
|
l4 = (l5 << 1) - l8;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FDBigInt fdbigint = multPow52(new FDBigInt(l), k1, i2);
|
|
FDBigInt fdbigint1 = constructPow52(j2, k2);
|
|
FDBigInt fdbigint2 = constructPow52(l2, i3);
|
|
int k5;
|
|
fdbigint.lshiftMe(k5 = fdbigint1.normalizeMe());
|
|
fdbigint2.lshiftMe(k5);
|
|
FDBigInt fdbigint3 = fdbigint1.mult(10);
|
|
k3 = 0;
|
|
int k6 = fdbigint.quoRemIteration(fdbigint1);
|
|
fdbigint2 = fdbigint2.mult(10);
|
|
flag = fdbigint.cmp(fdbigint2) < 0;
|
|
flag1 = fdbigint.add(fdbigint2).cmp(fdbigint3) > 0;
|
|
if (k6 >= 10)
|
|
throw new InternalError("FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(k6)));
|
|
if (k6 == 0 && !flag1)
|
|
j1--;
|
|
else ac[k3++] = (char) (k6 + '0');
|
|
if (j1 <= -3 || j1 >= 8)
|
|
{
|
|
flag = false;
|
|
flag1 = false;
|
|
}
|
|
while (!flag && !flag1)
|
|
{
|
|
int i7 = fdbigint.quoRemIteration(fdbigint1);
|
|
fdbigint2 = fdbigint2.mult(10);
|
|
if (i7 >= 10)
|
|
throw new InternalError("FP assertion: excessivly large digit ".concat(
|
|
String.valueOf(i7)));
|
|
flag = fdbigint.cmp(fdbigint2) < 0;
|
|
flag1 = fdbigint.add(fdbigint2).cmp(fdbigint3) > 0;
|
|
ac[k3++] = (char) (i7 + '0');
|
|
}
|
|
if (flag1 && flag)
|
|
{
|
|
fdbigint.lshiftMe(1);
|
|
l4 = fdbigint.cmp(fdbigint3);
|
|
}
|
|
else l4 = 0L;
|
|
}
|
|
decExponent = j1 + 1;
|
|
digits = ac;
|
|
nDigits = k3;
|
|
if (flag1)
|
|
{
|
|
if (flag)
|
|
{
|
|
if (l4 == 0L)
|
|
{
|
|
if ((ac[nDigits - 1] & 1) != 0)
|
|
roundup();
|
|
}
|
|
else
|
|
{
|
|
if (l4 > 0L)
|
|
roundup();
|
|
}
|
|
}
|
|
else roundup();
|
|
}
|
|
}
|
|
|
|
private static NumberFormatException numberFormatExceptionForInputString(
|
|
String s)
|
|
{
|
|
return new NumberFormatException("for input string: \"" + s + "\"");
|
|
}
|
|
|
|
String toJavaFormatString()
|
|
{
|
|
char[] ac = new char[nDigits + 10];
|
|
int i = 0;
|
|
if (isNegative)
|
|
{
|
|
ac[0] = '-';
|
|
i = 1;
|
|
}
|
|
if (isExceptional)
|
|
{
|
|
VMSystem.arraycopy(digits, 0, ac, i, nDigits);
|
|
i += nDigits;
|
|
}
|
|
else
|
|
{
|
|
if (decExponent > 0 && decExponent <= 7)
|
|
{
|
|
int j = nDigits;
|
|
if (j >= decExponent)
|
|
j = decExponent;
|
|
VMSystem.arraycopy(digits, 0, ac, i, j);
|
|
i += j;
|
|
if (j < decExponent)
|
|
{
|
|
j = decExponent - j;
|
|
VMSystem.arraycopy(zero, 0, ac, i, j);
|
|
i += j;
|
|
ac[i] = '.';
|
|
ac[i + 1] = '0';
|
|
i += 2;
|
|
}
|
|
else
|
|
{
|
|
ac[i++] = '.';
|
|
if (j < nDigits)
|
|
{
|
|
int l = nDigits - j;
|
|
VMSystem.arraycopy(digits, j, ac, i, l);
|
|
i += l;
|
|
}
|
|
else ac[i++] = '0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (decExponent <= 0 && decExponent >= -2)
|
|
{
|
|
ac[i] = '0';
|
|
ac[i + 1] = '.';
|
|
i += 2;
|
|
if (decExponent != 0)
|
|
{
|
|
VMSystem.arraycopy(zero, 0, ac, i, -decExponent);
|
|
i -= decExponent;
|
|
}
|
|
VMSystem.arraycopy(digits, 0, ac, i, nDigits);
|
|
i += nDigits;
|
|
if (nDigits > 1 && ac[i - 1] == '0')
|
|
i--;
|
|
}
|
|
else
|
|
{
|
|
ac[i] = digits[0];
|
|
ac[i + 1] = '.';
|
|
i += 2;
|
|
if (nDigits > 1)
|
|
{
|
|
VMSystem.arraycopy(digits, 1, ac, i, nDigits - 1);
|
|
i += nDigits - 1;
|
|
}
|
|
else ac[i++] = '0';
|
|
ac[i++] = 'E';
|
|
int k;
|
|
if (decExponent <= 0)
|
|
{
|
|
ac[i++] = '-';
|
|
k = 1 - decExponent;
|
|
}
|
|
else k = decExponent - 1;
|
|
if (k <= 9)
|
|
ac[i++] = (char) (k + '0');
|
|
else
|
|
{
|
|
if (k <= 99)
|
|
{
|
|
ac[i] = (char) (k / 10 + '0');
|
|
ac[i + 1] = (char) (k % 10 + '0');
|
|
i += 2;
|
|
}
|
|
else
|
|
{
|
|
ac[i++] = (char) (k / 100 + '0');
|
|
k %= 100;
|
|
ac[i] = (char) (k / 10 + '0');
|
|
ac[i + 1] = (char) (k % 10 + '0');
|
|
i += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new String(ac, 0, i);
|
|
}
|
|
|
|
static FloatingDecimal readJavaFormatString(String s)
|
|
throws NumberFormatException
|
|
{
|
|
boolean flag = false;
|
|
boolean flag1 = false;
|
|
try
|
|
{
|
|
s = s.trim();
|
|
int i = s.length();
|
|
if (i == 0)
|
|
throw numberFormatExceptionForInputString(s);
|
|
int j = 0;
|
|
char c;
|
|
if ((c = s.charAt(j)) == '+' || c == '-')
|
|
{
|
|
j++;
|
|
flag1 = true;
|
|
if (c == '-')
|
|
flag = true;
|
|
}
|
|
c = s.charAt(j);
|
|
if (c == 'N' || c == 'I')
|
|
{
|
|
boolean flag2 = false;
|
|
char[] ac1 = null;
|
|
if (c == 'N')
|
|
{
|
|
ac1 = notANumber;
|
|
flag2 = true;
|
|
}
|
|
else ac1 = infinity;
|
|
int l;
|
|
for (l = 0; j < i && l < ac1.length; l++)
|
|
if (s.charAt(j++) != ac1[l])
|
|
break;
|
|
if (l != ac1.length || j != i)
|
|
throw numberFormatExceptionForInputString(s);
|
|
return flag2 ? new FloatingDecimal(Double.NaN) :
|
|
new FloatingDecimal(flag ? -Double.POSITIVE_INFINITY :
|
|
Double.POSITIVE_INFINITY);
|
|
}
|
|
char[] ac = new char[i];
|
|
boolean flag3 = false;
|
|
int i1 = 0;
|
|
int j1 = 0;
|
|
int k1 = 0;
|
|
int k;
|
|
for (k = 0; j < i; j++)
|
|
{
|
|
if ((char) ((c = s.charAt(j)) - '1') <= (char) ('9' - '1'))
|
|
{
|
|
while (k1 > 0)
|
|
{
|
|
ac[k++] = '0';
|
|
k1--;
|
|
}
|
|
ac[k++] = c;
|
|
}
|
|
else
|
|
{
|
|
if (c == '0')
|
|
{
|
|
if (k > 0)
|
|
k1++;
|
|
else j1++;
|
|
}
|
|
else
|
|
{
|
|
if (c != '.')
|
|
break;
|
|
if (flag3)
|
|
throw numberFormatExceptionForInputString(s);
|
|
i1 = j;
|
|
if (flag1)
|
|
i1--;
|
|
flag3 = true;
|
|
}
|
|
}
|
|
}
|
|
if (k == 0)
|
|
{
|
|
ac = zero;
|
|
k = 1;
|
|
if (j1 == 0)
|
|
throw numberFormatExceptionForInputString(s);
|
|
}
|
|
int l1 = flag3 ? i1 - j1 : k + k1;
|
|
if (j < i && ((c = s.charAt(j)) == 'e' || c == 'E'))
|
|
{
|
|
int sign = 1;
|
|
int i2 = 0;
|
|
int j2 = 0xccccccc;
|
|
boolean flag4 = false;
|
|
char c2 = s.charAt(++j);
|
|
if (c2 == '-')
|
|
{
|
|
sign = -1;
|
|
j++;
|
|
}
|
|
if (c2 == '+')
|
|
j++;
|
|
int k2;
|
|
for (k2 = j; j < i; j++)
|
|
{
|
|
if (i2 >= j2)
|
|
flag4 = true;
|
|
char c1;
|
|
if ((char) ((c1 = s.charAt(j)) - '0') > (char) ('9' - '0'))
|
|
break;
|
|
i2 = i2 * 10 + c1 - '0';
|
|
}
|
|
if (j == k2)
|
|
throw numberFormatExceptionForInputString(s);
|
|
int l2 = bigDecimalExponent + k + k1;
|
|
l1 = flag4 || i2 > l2 ? sign * l2 : sign * i2 + l1;
|
|
}
|
|
char c3;
|
|
if (j >= i || (j == i - 1 && ((c3 = s.charAt(j)) == 'f' || c3 == 'F' ||
|
|
c3 == 'd' || c3 == 'D')))
|
|
return new FloatingDecimal(flag, l1, ac, k, false);
|
|
}
|
|
catch (StringIndexOutOfBoundsException e) {}
|
|
throw numberFormatExceptionForInputString(s);
|
|
}
|
|
|
|
float floatValue()
|
|
{
|
|
int i = nDigits;
|
|
if (i >= 8)
|
|
i = 8;
|
|
if (digits == infinity)
|
|
return isNegative ? -Float.POSITIVE_INFINITY : Float.POSITIVE_INFINITY;
|
|
if (digits == notANumber)
|
|
return Float.NaN;
|
|
int j = digits[0] - '0';
|
|
for (int k = 1; k < i; k++)
|
|
j = j * 10 + digits[k] - '0';
|
|
float f = j;
|
|
int l = decExponent - i;
|
|
if (nDigits <= singleMaxDecimalDigits)
|
|
{
|
|
if (l == 0 || f == 0.0F)
|
|
return isNegative ? -f : f;
|
|
if (l >= 0)
|
|
{
|
|
if (l <= singleMaxSmallTen)
|
|
{
|
|
f *= singleSmall10pow[l];
|
|
return isNegative ? -f : f;
|
|
}
|
|
int j1 = singleMaxDecimalDigits - i;
|
|
if (l <= singleMaxSmallTen + j1)
|
|
{
|
|
f = (f * singleSmall10pow[j1]) * singleSmall10pow[l - j1];
|
|
return isNegative ? -f : f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (l >= -singleMaxSmallTen)
|
|
{
|
|
f /= singleSmall10pow[-l];
|
|
return isNegative ? -f : f;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (decExponent >= nDigits && nDigits + decExponent <= maxDecimalDigits)
|
|
{
|
|
long l1 = (long) j;
|
|
for (int k1 = i; k1 < nDigits; k1++)
|
|
l1 = l1 * 10L + (long) (digits[k1] - '0');
|
|
float f1 = (float) ((double) l1 * small10pow[decExponent - nDigits]);
|
|
return isNegative ? -f1 : f1;
|
|
}
|
|
}
|
|
if (decExponent > singleMaxDecimalExponent + 1)
|
|
return isNegative ? -Float.POSITIVE_INFINITY : Float.POSITIVE_INFINITY;
|
|
if (decExponent < singleMinDecimalExponent - 1)
|
|
{
|
|
float f3 = 0.0F;
|
|
if (isNegative)
|
|
f3 = -f3;
|
|
return f3;
|
|
}
|
|
mustSetRoundDir = true;
|
|
return stickyRound(doubleValue());
|
|
}
|
|
|
|
double doubleValue()
|
|
{
|
|
int i = nDigits;
|
|
if (i >= 16)
|
|
i = 16;
|
|
if (digits == infinity)
|
|
return isNegative ? -Double.POSITIVE_INFINITY : Double.POSITIVE_INFINITY;
|
|
if (digits == notANumber)
|
|
return Double.NaN;
|
|
roundDir = 0;
|
|
int j = digits[0] - '0';
|
|
int k = i;
|
|
if (k >= 9)
|
|
k = 9;
|
|
for (int l = 1; l < k; l++)
|
|
j = (j * 10 + digits[l]) - '0';
|
|
long l1 = j;
|
|
for (int i1 = k; i1 < i; i1++)
|
|
l1 = l1 * 10L + (long) (digits[i1] - '0');
|
|
double d = l1;
|
|
int j1 = decExponent - i;
|
|
if (nDigits <= maxDecimalDigits)
|
|
{
|
|
if (j1 == 0 || d == 0.0)
|
|
return isNegative ? -d : d;
|
|
if (j1 >= 0)
|
|
{
|
|
if (j1 <= maxSmallTen)
|
|
{
|
|
double d1 = d * small10pow[j1];
|
|
if (mustSetRoundDir)
|
|
{
|
|
double d4 = d1 / small10pow[j1];
|
|
if (d4 != d)
|
|
roundDir = d4 >= d ? -1 : 1;
|
|
}
|
|
return isNegative ? -d1 : d1;
|
|
}
|
|
int k1 = maxDecimalDigits - i;
|
|
if (j1 <= maxSmallTen + k1)
|
|
{
|
|
d *= small10pow[k1];
|
|
double d4 = d * small10pow[j1 - k1];
|
|
if (mustSetRoundDir)
|
|
{
|
|
double d5 = d4 / small10pow[j1 - k1];
|
|
if (d5 != d)
|
|
roundDir = d5 >= d ? -1 : 1;
|
|
}
|
|
return isNegative ? -d4 : d4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j1 >= -maxSmallTen)
|
|
{
|
|
double d2 = d / small10pow[-j1];
|
|
double d6;
|
|
if (mustSetRoundDir && (d6 = d2 * small10pow[-j1]) != d)
|
|
roundDir = d6 >= d ? -1 : 1;
|
|
return isNegative ? -d2 : d2;
|
|
}
|
|
}
|
|
}
|
|
if (j1 > 0)
|
|
{
|
|
if (decExponent > maxDecimalExponent + 1)
|
|
return isNegative ? -Double.POSITIVE_INFINITY : Double.POSITIVE_INFINITY;
|
|
if ((j1 & 0xf) != 0)
|
|
d *= small10pow[j1 & 0xf];
|
|
if ((j1 >>= 4) != 0)
|
|
{
|
|
int i2;
|
|
for (i2 = 0; j1 > 1; j1 >>= 1)
|
|
{
|
|
if ((j1 & 1) != 0)
|
|
d *= big10pow[i2];
|
|
i2++;
|
|
}
|
|
double d5 = d * big10pow[i2];
|
|
if (d5 == Double.POSITIVE_INFINITY)
|
|
{
|
|
d5 = (d / 2.0) * big10pow[i2];
|
|
if (d5 == Double.POSITIVE_INFINITY)
|
|
return isNegative ? -d5 : d5;
|
|
d5 = Double.MAX_VALUE;
|
|
}
|
|
d = d5;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j1 < 0)
|
|
{
|
|
j1 = -j1;
|
|
if (decExponent < minDecimalExponent - 1)
|
|
{
|
|
double d3 = 0.0;
|
|
if (isNegative)
|
|
d3 = -d3;
|
|
return d3;
|
|
}
|
|
if ((j1 & 0xf) != 0)
|
|
d /= small10pow[j1 & 0xf];
|
|
if ((j1 >>= 4) != 0)
|
|
{
|
|
int j2;
|
|
for (j2 = 0; j1 > 1; j1 >>= 1)
|
|
{
|
|
if ((j1 & 1) != 0)
|
|
d *= tiny10pow[j2];
|
|
j2++;
|
|
}
|
|
double d6 = d * tiny10pow[j2];
|
|
if (d6 == 0.0)
|
|
{
|
|
d6 = d * 2.0;
|
|
d6 *= tiny10pow[j2];
|
|
if (d6 == 0.0)
|
|
{
|
|
double d8 = 0.0;
|
|
if (isNegative)
|
|
d8 = -d8;
|
|
return d8;
|
|
}
|
|
d6 = Double.MIN_VALUE;
|
|
}
|
|
d = d6;
|
|
}
|
|
}
|
|
}
|
|
FDBigInt fdbigint = new FDBigInt(l1, digits, i, nDigits);
|
|
j1 = decExponent - nDigits;
|
|
int k2 = 0;
|
|
do
|
|
{
|
|
FDBigInt fdbigint1 = doubleToBigInt(d);
|
|
int l2;
|
|
int i3;
|
|
int j3;
|
|
int k3;
|
|
if (j1 >= 0)
|
|
{
|
|
l2 = 0;
|
|
i3 = 0;
|
|
j3 = j1;
|
|
k3 = j1;
|
|
}
|
|
else
|
|
{
|
|
l2 = -j1;
|
|
j3 = 0;
|
|
i3 = l2;
|
|
k3 = 0;
|
|
}
|
|
if (bigIntExp >= 0)
|
|
l2 += bigIntExp;
|
|
else j3 -= bigIntExp;
|
|
int l3 = l2;
|
|
int i4 = bigIntExp + bigIntNBits <= -1022 ?
|
|
bigIntExp + expBias + expShift : 54 - bigIntNBits;
|
|
l2 += i4;
|
|
j3 += i4;
|
|
int j4 = l2;
|
|
if (l2 >= j3)
|
|
j4 = j3;
|
|
if (j4 >= l3)
|
|
j4 = l3;
|
|
l2 -= j4;
|
|
j3 -= j4;
|
|
l3 -= j4;
|
|
fdbigint1 = multPow52(fdbigint1, i3, l2);
|
|
FDBigInt fdbigint2 = multPow52(new FDBigInt(fdbigint), k3, j3);
|
|
FDBigInt fdbigint3;
|
|
int k4;
|
|
boolean flag;
|
|
if ((k4 = fdbigint1.cmp(fdbigint2)) > 0)
|
|
{
|
|
flag = true;
|
|
fdbigint3 = fdbigint1.sub(fdbigint2);
|
|
if (bigIntNBits == 1 && bigIntExp > -expBias && --l3 < 0)
|
|
{
|
|
l3 = 0;
|
|
fdbigint3.lshiftMe(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (k4 >= 0)
|
|
break;
|
|
flag = false;
|
|
fdbigint3 = fdbigint2.sub(fdbigint1);
|
|
}
|
|
FDBigInt fdbigint4 = constructPow52(i3, l3);
|
|
if ((k4 = fdbigint3.cmp(fdbigint4)) < 0)
|
|
{
|
|
roundDir = flag ? -1 : 1;
|
|
break;
|
|
}
|
|
if (k4 == 0)
|
|
{
|
|
d += ulp(d, flag) / 2.0;
|
|
roundDir = flag ? -1 : 1;
|
|
break;
|
|
}
|
|
d += ulp(d, flag);
|
|
} while (d != 0.0 && d != Double.POSITIVE_INFINITY && ++k2 < 64);
|
|
return isNegative ? -d : d;
|
|
}
|
|
}
|
|
|
|
private static final long NAN_BITS;
|
|
|
|
static
|
|
{
|
|
long bits = -1L;
|
|
bits >>>= 1; /* hack */
|
|
NAN_BITS = bits - (bits >> 12); /* hack */
|
|
}
|
|
|
|
private VMDouble() {}
|
|
|
|
static long doubleToLongBits(double value)
|
|
{
|
|
return value != value ? NAN_BITS : doubleToRawLongBits(value);
|
|
}
|
|
|
|
static native long doubleToRawLongBits(double value); /* JVM-core */
|
|
|
|
static native double longBitsToDouble(long bits); /* JVM-core */
|
|
|
|
static String toString(double d, boolean isFloat)
|
|
{
|
|
return (isFloat ? new FloatingDecimal((float) d) :
|
|
new FloatingDecimal(d)).toJavaFormatString();
|
|
}
|
|
|
|
static double parseDouble(String str)
|
|
throws NumberFormatException
|
|
{
|
|
if (str == null) /* hack */
|
|
throw new NullPointerException();
|
|
return FloatingDecimal.readJavaFormatString(str).doubleValue();
|
|
}
|
|
|
|
static float parseFloat(String str)
|
|
throws NumberFormatException
|
|
{ /* used by VM classes only */
|
|
if (str == null) /* hack */
|
|
throw new NullPointerException();
|
|
return FloatingDecimal.readJavaFormatString(str).floatValue();
|
|
}
|
|
}
|