Unsigned long to double and back
david32768@btinternet.com david32768@btinternet.com
david32768 at btinternet.com
Thu Dec 1 13:12:53 UTC 2022
On Sun Nov 6 00:17:19 UTC 2022 Johannes Kuhn <info at j-kuhn.de> wrote:
> ...
> In particular, I would love to see the following methods added*:
>
> - double Double.fromUnsignedLong(long i)
> - long Double.toUnsignedLong(double d)
> - float Float.fromUnsignedLong(long i)
> - long Float.toUnsignedLong(float f)
> ...
The methods suggested for double to unsigned long by David Lloyd and
Remi Forax
differ from BigInteger.doubleValue() in a few cases because of
rounding error.
They also fail some WebAssembly tests
(https://github.com/WebAssembly/testsuite/blob/main/conversions.wast).
The double to unsigned long method below agrees with
BigInteger.doubleValue() on random tests and
passes the WebAssembly tests.
// DOUBLE 1 11 52
private static final int PHYSICAL_MANTISSA = 52;
private static final int MANTISSA = PHYSICAL_MANTISSA + 1; //
leading one bit not stored in normal numbers
private static final int SHIFT_DOWN = 64 - MANTISSA;
private static final long DIVISOR = 1L << SHIFT_DOWN;
private static final long REMAINDER_MASK = DIVISOR - 1;
private static final long HALF = DIVISOR >>> 1;
private static final double MULTIPLIER = (double)DIVISOR;
public static double doubleFromUnsignedLong(long value) {
if (value >= 0) {
return (double)value;
}
long mantissa = value >>> SHIFT_DOWN; // top bit of mantissa is
1 as value negative
long remainder = value & REMAINDER_MASK;
if (remainder > HALF || remainder == HALF && (mantissa & 1) !=
0) { // round up (half to even) ?
++mantissa;
}
return MULTIPLIER * mantissa;
}
private final static double TWO63D = 0x1.0p63;
private final static double TWO64D = 0x1.0p64;
public static long doubleToUnsignedLongStrict(double x) {
if (Double.isNaN(x)) {
String msg = "INTEGER_CONVERSION";
throw new ArithmeticException(msg);
}
if (x >= TWO64D || x <= -1.0) {
String msg = "INTEGER_OVERFLOW";
throw new ArithmeticException(msg);
}
if (x < TWO63D) {
return (long)x;
}
// x is an integer in [0x1.0p63,0x1.0p64) and last 11 bits are
zero
double y = x/2;
long yl = (long)y;
return yl << 1;
}
// FLOAT 1 8 23
private static final int PHYSICAL_MANTISSA_F = 23;
private static final int MANTISSA_F = PHYSICAL_MANTISSA_F + 1; //
leading one bit not stored in normal numbers
private static final int SHIFT_DOWN_F = 64 - MANTISSA_F;
private static final long DIVISOR_F = 1L << SHIFT_DOWN_F;
private static final long REMAINDER_MASK_F = DIVISOR_F - 1;
private static final long HALF_F = DIVISOR_F >>> 1;
private static final float MULTIPLIER_F = (float)DIVISOR_F;
public static float floatFromUnsignedLong(long value) {
if (value >= 0) {
return (float)value;
}
long mantissa = value >>> SHIFT_DOWN_F; // top bit of mantissa
is 1 as value negative
long remainder = value & REMAINDER_MASK_F;
if (remainder > HALF_F || remainder == HALF_F && (mantissa & 1)
!= 0) { // round up (half to even) ?
++mantissa;
}
return MULTIPLIER_F * mantissa;
}
private final static double TWO31D = 0x1.0p31;
private final static double TWO32D = 0x1.0p32;
public static int doubleToUnsignedIntStrict(double x) {
if (Double.isNaN(x)) {
String msg = "INTEGER_CONVERSION";
throw new ArithmeticException(msg);
}
if (x >= TWO32D || x <= -1.0) {
String msg = "INTEGER_OVERFLOW";
throw new ArithmeticException(msg);
}
if (x < TWO31D) {
return (int)x;
}
return (int)(long)x;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20221201/9660ae2c/attachment-0001.htm>
More information about the core-libs-dev
mailing list