<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body><div class="auto-created-dir-div" dir="auto" style="unicode-bidi: embed;"><style>p{margin:0}</style><p>On Sun Nov 6 00:17:19 UTC 2022 Johannes Kuhn <info at j-kuhn.de> wrote:</p><p><br></p><p>>...</p><p>>In particular, I would love to see the following methods added*:</p><p>></p><p>>- double Double.fromUnsignedLong(long i)</p><p>>- long Double.toUnsignedLong(double d)</p><p>>- float Float.fromUnsignedLong(long i)</p><p>>- long Float.toUnsignedLong(float f)</p><p>>...</p><p><br></p><p>The methods suggested for double to unsigned long by David Lloyd and Remi Forax</p><p> differ from BigInteger.doubleValue() <span style="display: inline !important;">in a few cases because of rounding error.</span></p><p><span style="display: inline !important;"> They also fail some WebAssembly tests</span></p><p>(https://github.com/WebAssembly/testsuite/blob/main/conversions.wast).</p><p><br></p><p>The double to unsigned long method below agrees with BigInteger.doubleValue() on random tests and </p><p>passes the WebAssembly tests.</p><p><br></p><p><br></p><p>    // DOUBLE 1 11 52</p><p>    private static final int PHYSICAL_MANTISSA = 52;</p><p>    private static final int MANTISSA = PHYSICAL_MANTISSA + 1; // leading one bit not stored in normal numbers</p><p>    private static final int SHIFT_DOWN = 64 - MANTISSA;</p><p>    private static final long DIVISOR = 1L << SHIFT_DOWN;</p><p>    private static final long REMAINDER_MASK = DIVISOR - 1;</p><p>    private static final long HALF = DIVISOR >>> 1;</p><p>    private static final double MULTIPLIER = (double)DIVISOR;</p><p>    </p><p>    public static double doubleFromUnsignedLong(long value) {</p><p>        if (value >= 0) {</p><p>            return (double)value;</p><p>        }</p><p>        long mantissa = value >>> SHIFT_DOWN; // top bit of mantissa is 1 as value negative</p><p>        long remainder = value & REMAINDER_MASK;</p><p>        if (remainder > HALF || remainder == HALF && (mantissa & 1) != 0) { // round up (half to even) ?</p><p>            ++mantissa;</p><p>        }</p><p>        return MULTIPLIER * mantissa;</p><p>    }</p><p>    </p><p>    private final static double TWO63D = 0x1.0p63;</p><p>    private final static double TWO64D = 0x1.0p64;</p><p><br></p><p>    public static long doubleToUnsignedLongStrict(double x) {</p><p>        if (Double.isNaN(x)) {</p><p>            String msg = "INTEGER_CONVERSION";</p><p>            throw new ArithmeticException(msg);</p><p>        }</p><p>        if (x >= TWO64D || x <= -1.0) {</p><p>            String msg = "INTEGER_OVERFLOW";</p><p>            throw new ArithmeticException(msg);</p><p>        }</p><p>        if (x < TWO63D) {</p><p>            return (long)x;</p><p>        }</p><p>        // x is an integer in [0x1.0p63,0x1.0p64) and last 11 bits are zero</p><p>        double y = x/2;</p><p>        long yl = (long)y;</p><p>        return  yl << 1;</p><p>    }</p><p>    </p><p>    // FLOAT 1 8 23</p><p>    private static final int PHYSICAL_MANTISSA_F = 23;</p><p>    private static final int MANTISSA_F = PHYSICAL_MANTISSA_F + 1; // leading one bit not stored in normal numbers</p><p>    private static final int SHIFT_DOWN_F = 64 - MANTISSA_F;</p><p>    private static final long DIVISOR_F = 1L << SHIFT_DOWN_F;</p><p>    private static final long REMAINDER_MASK_F = DIVISOR_F - 1;</p><p>    private static final long HALF_F = DIVISOR_F >>> 1;</p><p>    private static final float MULTIPLIER_F = (float)DIVISOR_F;</p><p>    </p><p>    public static float floatFromUnsignedLong(long value) {</p><p>        if (value >= 0) {</p><p>            return (float)value;</p><p>        }</p><p>        long mantissa = value >>> SHIFT_DOWN_F; // top bit of mantissa is 1 as value negative</p><p>        long remainder = value & REMAINDER_MASK_F;</p><p>        if (remainder > HALF_F || remainder == HALF_F && (mantissa & 1) != 0) { // round up (half to even) ?</p><p>            ++mantissa;</p><p>        }</p><p>        return MULTIPLIER_F * mantissa;</p><p>    }</p><p>    </p><p>    private final static double TWO31D = 0x1.0p31;</p><p>    private final static double TWO32D = 0x1.0p32;</p><p><br></p><p>    public static int doubleToUnsignedIntStrict(double x) {</p><p>        if (Double.isNaN(x)) {</p><p>            String msg = "INTEGER_CONVERSION";</p><p>            throw new ArithmeticException(msg);</p><p>        }</p><p>        if (x >= TWO32D || x <= -1.0) {</p><p>            String msg = "INTEGER_OVERFLOW";</p><p>            throw new ArithmeticException(msg);</p><p>        }</p><p>        if (x < TWO31D) {</p><p>            return (int)x;</p><p>        }</p><p>        return (int)(long)x;</p><p>    }</p><div><br></div></div></body></html>