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