Conversion fixes arithmetic
authorLubomir Nerad <lubomir.nerad@oracle.com>
Wed, 27 Feb 2013 16:24:42 +0100
brancharithmetic
changeset 7786f8683517f1f
parent 774 42bc1e89134d
child 783 8264f07b1f46
Conversion fixes
rt/emul/mini/src/main/java/java/io/DataInputStream.java
rt/emul/mini/src/main/java/java/lang/Double.java
rt/emul/mini/src/main/java/java/lang/Float.java
rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js
rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java
     1.1 --- a/rt/emul/mini/src/main/java/java/io/DataInputStream.java	Wed Feb 27 11:24:58 2013 +0100
     1.2 +++ b/rt/emul/mini/src/main/java/java/io/DataInputStream.java	Wed Feb 27 16:24:42 2013 +0100
     1.3 @@ -468,42 +468,8 @@
     1.4       * @see        java.lang.Double#longBitsToDouble(long)
     1.5       */
     1.6      public final double readDouble() throws IOException {
     1.7 -        int hi = readInt();
     1.8 -        int low = readInt();
     1.9 -        return toDouble(hi, low);
    1.10 -    }
    1.11 -    
    1.12 -    @JavaScriptBody(args={ "hi", "low" },
    1.13 -        body=
    1.14 -          "if (low == 0) {\n"
    1.15 -        + "  if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n"
    1.16 -        + "  if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n"
    1.17 -        + "}\n"
    1.18 -        + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n"
    1.19 -        + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n"
    1.20 -        + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n"
    1.21 -        + "var e = (hi >> 20) & 0x7ff;\n"
    1.22 -        + "var to32 = low >> 0;\n"
    1.23 -        + "if (e === 0) {\n"
    1.24 -        + "  if (to32 & 0x80000000) {\n"
    1.25 -        + "    hi = hi << 1 + 1; low = low << 1;\n"
    1.26 -        + "  } else {\n"
    1.27 -        + "    hi = hi << 1; low = low << 1;\n"
    1.28 -        + "  }\n" 
    1.29 -        + "} else {\n"
    1.30 -        + "    hi = (hi & 0xfffff) | 0x100000;\n"
    1.31 -        + "}\n"
    1.32 -        + "to32 = low >> 0;\n"
    1.33 -        + "var m = Math.pow(2.0, 32) * hi + to32;\n"
    1.34 -        + "var r = s * m * Math.pow(2.0, e - 1075);\n"
    1.35 -        + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n"
    1.36 -        + "return r;\n"
    1.37 -    )
    1.38 -    private static double toDouble(int hi, int low) {
    1.39 -        long both = hi;
    1.40 -        both = (both << 32) & low;
    1.41 -        return Double.doubleToLongBits(both);
    1.42 -    }
    1.43 +        return Double.longBitsToDouble(readLong());
    1.44 +    }    
    1.45  
    1.46      private char lineBuffer[];
    1.47  
     2.1 --- a/rt/emul/mini/src/main/java/java/lang/Double.java	Wed Feb 27 11:24:58 2013 +0100
     2.2 +++ b/rt/emul/mini/src/main/java/java/lang/Double.java	Wed Feb 27 16:24:42 2013 +0100
     2.3 @@ -920,6 +920,26 @@
     2.4       * @return  the {@code double} floating-point value with the same
     2.5       *          bit pattern.
     2.6       */
     2.7 +    @JavaScriptBody(args={ "bits" },
     2.8 +        body=
     2.9 +          "var hi = bits.high32();\n"
    2.10 +        + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n"
    2.11 +        + "var e = (hi >> 20) & 0x7ff;\n"
    2.12 +        + "if (e === 0x7ff) {\n"
    2.13 +        + "  if ((bits == 0) && ((hi & 0xfffff) === 0)) {\n"
    2.14 +        + "    return (s > 0) ? Number.POSITIVE_INFINITY"
    2.15 +                          + " : Number.NEGATIVE_INFINITY;\n"
    2.16 +        + "  }\n"
    2.17 +        + "  return Number.NaN;\n"
    2.18 +        + "}\n"
    2.19 +        + "var m = (hi & 0xfffff).next32(bits);\n"
    2.20 +        + "if (e === 0) {\n"
    2.21 +        + "  m = m.shl64(1);\n"
    2.22 +        + "} else {\n"
    2.23 +        + "  m.hi = m.high32() | 0x100000;\n"
    2.24 +        + "}\n"
    2.25 +        + "return s * m.toFP() * Math.pow(2.0, e - 1075);\n"
    2.26 +    )
    2.27      public static native double longBitsToDouble(long bits);
    2.28  
    2.29      /**
     3.1 --- a/rt/emul/mini/src/main/java/java/lang/Float.java	Wed Feb 27 11:24:58 2013 +0100
     3.2 +++ b/rt/emul/mini/src/main/java/java/lang/Float.java	Wed Feb 27 16:24:42 2013 +0100
     3.3 @@ -822,13 +822,13 @@
     3.4            "var s = ((bits >> 31) == 0) ? 1 : -1;\n"
     3.5          + "var e = ((bits >> 23) & 0xff);\n"
     3.6          + "if (e === 0xff) {\n"
     3.7 -        + "    if ((bits & 0x7fffff) === 0) {\n"
     3.8 -        + "        return (s > 0) ? Number.POSITIVE_INFINITY"
     3.9 -                              + " : Number.NEGATIVE_INFINITY;\n"
    3.10 -        + "    }\n"
    3.11 -        + "    return Number.NaN;\n"
    3.12 +        + "  if ((bits & 0x7fffff) === 0) {\n"
    3.13 +        + "    return (s > 0) ? Number.POSITIVE_INFINITY"
    3.14 +                          + " : Number.NEGATIVE_INFINITY;\n"
    3.15 +        + "  }\n"
    3.16 +        + "  return Number.NaN;\n"
    3.17          + "}\n"
    3.18 -        + "var m = (e == 0) ?\n"
    3.19 +        + "var m = (e === 0) ?\n"
    3.20          + "  (bits & 0x7fffff) << 1 :\n"
    3.21          + "  (bits & 0x7fffff) | 0x800000;\n"
    3.22          + "return s * m * Math.pow(2.0, e - 150);\n"
     4.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Wed Feb 27 11:24:58 2013 +0100
     4.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Wed Feb 27 16:24:42 2013 +0100
     4.3 @@ -28,8 +28,17 @@
     4.4      return this.hi ? this.hi * (__m32+1) + this : this;
     4.5  };
     4.6  Number.prototype.toLong = function() {
     4.7 -    var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
     4.8 -    return hi.next32(Math.floor(this % (__m32+1)));
     4.9 +    var hi = (this / (__m32+1)) | 0;
    4.10 +    var low = (this % (__m32+1)) | 0;
    4.11 +    if (low < 0) {
    4.12 +        low += __m32+1;
    4.13 +    }
    4.14 +        
    4.15 +    if (this < 0) {
    4.16 +        hi -= 1;
    4.17 +    }
    4.18 +
    4.19 +    return hi.next32(low);
    4.20  };
    4.21  
    4.22  Number.prototype.toExactString = function() {
    4.23 @@ -481,7 +490,7 @@
    4.24              v = x;
    4.25          }
    4.26  
    4.27 -        if ((v === 0) && (v.high32() === 0)) {
    4.28 +        if ((v == 0) && (v.high32() === 0)) {
    4.29              __handleDivByZero();
    4.30          }
    4.31  
    4.32 @@ -522,7 +531,7 @@
    4.33              v = x;
    4.34          }
    4.35  
    4.36 -        if ((v === 0) && (v.high32() === 0)) {
    4.37 +        if ((v == 0) && (v.high32() === 0)) {
    4.38              __handleDivByZero();
    4.39          }
    4.40  
     5.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Feb 27 11:24:58 2013 +0100
     5.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Feb 27 16:24:42 2013 +0100
     5.3 @@ -691,19 +691,19 @@
     5.4                      emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
     5.5                      break;
     5.6                  case opc_f2i:
     5.7 -                    emit(out, "var @2 = Math.floor(@1).toInt32();",
     5.8 +                    emit(out, "var @2 = @1.toInt32();",
     5.9                           smapper.popF(), smapper.pushI());
    5.10                      break;
    5.11                  case opc_f2l:
    5.12 -                    emit(out, "var @2 = Math.floor(@1).toLong();",
    5.13 +                    emit(out, "var @2 = @1.toLong();",
    5.14                           smapper.popF(), smapper.pushL());
    5.15                      break;
    5.16                  case opc_d2i:
    5.17 -                    emit(out, "var @2 = Math.floor(@1).toInt32();",
    5.18 +                    emit(out, "var @2 = @1.toInt32();",
    5.19                           smapper.popD(), smapper.pushI());
    5.20                      break;
    5.21                  case opc_d2l:
    5.22 -                    emit(out, "var @2 = Math.floor(@1).toLong();",
    5.23 +                    emit(out, "var @2 = @1.toLong();",
    5.24                           smapper.popD(), smapper.pushL());
    5.25                      break;
    5.26                  case opc_i2b:
     6.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java	Wed Feb 27 11:24:58 2013 +0100
     6.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java	Wed Feb 27 16:24:42 2013 +0100
     6.3 @@ -50,6 +50,14 @@
     6.4      private static int neg(int x) {
     6.5          return (-x);
     6.6      }
     6.7 +
     6.8 +    private static float fadd(float x, float y) {
     6.9 +        return x + y;
    6.10 +    }
    6.11 +
    6.12 +    private static double dadd(double x, double y) {
    6.13 +        return x + y;
    6.14 +    }
    6.15      
    6.16      @Compare public int addOverflow() {
    6.17          return add(Integer.MAX_VALUE, 1);
    6.18 @@ -90,7 +98,7 @@
    6.19      @Compare public int division() {
    6.20          return div(1, 2);
    6.21      }
    6.22 -    
    6.23 +
    6.24      @Compare public int divisionReminder() {
    6.25          return mod(1, 2);
    6.26      }
    6.27 @@ -103,6 +111,14 @@
    6.28          return mod(-7, 3);
    6.29      }
    6.30  
    6.31 +    @Compare public int conversionFromFloat() {
    6.32 +        return (int) fadd(-2, -0.6f);
    6.33 +    }
    6.34 +
    6.35 +    @Compare public int conversionFromDouble() {
    6.36 +        return (int) dadd(-2, -0.6);
    6.37 +    }
    6.38 +
    6.39      @Compare public boolean divByZeroThrowsArithmeticException() {
    6.40          try {
    6.41              div(1, 0);
     7.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Wed Feb 27 11:24:58 2013 +0100
     7.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Wed Feb 27 16:24:42 2013 +0100
     7.3 @@ -26,55 +26,63 @@
     7.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
     7.5   */
     7.6  public class LongArithmeticTest {
     7.7 -    
     7.8 +
     7.9      private static long add(long x, long y) {
    7.10          return (x + y);
    7.11      }
    7.12 -    
    7.13 +
    7.14      private static long sub(long x, long y) {
    7.15          return (x - y);
    7.16      }
    7.17 -    
    7.18 +
    7.19      private static long mul(long x, long y) {
    7.20          return (x * y);
    7.21      }
    7.22 -    
    7.23 +
    7.24      private static long div(long x, long y) {
    7.25          return (x / y);
    7.26      }
    7.27 -    
    7.28 +
    7.29      private static long mod(long x, long y) {
    7.30          return (x % y);
    7.31      }
    7.32 -    
    7.33 +
    7.34      private static long neg(long x) {
    7.35          return (-x);
    7.36      }
    7.37 -    
    7.38 +
    7.39      private static long shl(long x, int b) {
    7.40          return (x << b);
    7.41      }
    7.42 -    
    7.43 +
    7.44      private static long shr(long x, int b) {
    7.45          return (x >> b);
    7.46      }
    7.47 -    
    7.48 +
    7.49      private static long ushr(long x, int b) {
    7.50          return (x >>> b);
    7.51      }
    7.52 -    
    7.53 +
    7.54      private static long and(long x, long y) {
    7.55          return (x & y);
    7.56      }
    7.57 -    
    7.58 +
    7.59      private static long or(long x, long y) {
    7.60          return (x | y);
    7.61      }
    7.62 -    
    7.63 +
    7.64      private static long xor(long x, long y) {
    7.65          return (x ^ y);
    7.66      }
    7.67 -    
    7.68 +
    7.69 +    private static float fadd(float x, float y) {
    7.70 +        return x + y;
    7.71 +    }
    7.72 +
    7.73 +    private static double dadd(double x, double y) {
    7.74 +        return x + y;
    7.75 +    }
    7.76 +
    7.77      public static int compare(long x, long y, int zero) {
    7.78          final int xyResult = compareL(x, y, zero);
    7.79          final int yxResult = compareL(y, x, zero);
    7.80 @@ -106,15 +114,15 @@
    7.81  
    7.82          return (trueCount == 1) ? result : -2;
    7.83      }
    7.84 -    
    7.85 +
    7.86      @Compare public long conversion() {
    7.87          return Long.MAX_VALUE;
    7.88      }
    7.89 -    
    7.90 +
    7.91      @Compare public long negate1() {
    7.92          return neg(0x00fa37d7763e0ca1l);
    7.93      }
    7.94 -    
    7.95 +
    7.96      @Compare public long negate2() {
    7.97          return neg(0x80fa37d7763e0ca1l);
    7.98      }
    7.99 @@ -134,11 +142,11 @@
   7.100      @Compare public long addMaxLongAndMaxLong() {
   7.101          return add(Long.MAX_VALUE, Long.MAX_VALUE);
   7.102      }
   7.103 -    
   7.104 +
   7.105      @Compare public long subMinLongAndMinLong() {
   7.106          return sub(Long.MIN_VALUE, Long.MIN_VALUE);
   7.107      }
   7.108 -    
   7.109 +
   7.110      @Compare public long subMinLongAndMaxLong() {
   7.111          return sub(Long.MIN_VALUE, Long.MAX_VALUE);
   7.112      }
   7.113 @@ -146,23 +154,23 @@
   7.114      @Compare public long multiplyMaxLong() {
   7.115          return mul(Long.MAX_VALUE, 2l);
   7.116      }
   7.117 -    
   7.118 +
   7.119      @Compare public long multiplyMaxLongAndMaxLong() {
   7.120          return mul(Long.MAX_VALUE, Long.MAX_VALUE);
   7.121      }
   7.122 -    
   7.123 +
   7.124      @Compare public long multiplyMinLong() {
   7.125          return mul(Long.MIN_VALUE, 2l);
   7.126      }
   7.127 -    
   7.128 +
   7.129      @Compare public long multiplyMinLongAndMinLong() {
   7.130          return mul(Long.MIN_VALUE, Long.MIN_VALUE);
   7.131      }
   7.132 -    
   7.133 +
   7.134      @Compare public long multiplyPrecision() {
   7.135          return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
   7.136      }
   7.137 -    
   7.138 +
   7.139      @Compare public long divideSmallPositiveNumbers() {
   7.140          return div(0xabcdef, 0x123);
   7.141      }
   7.142 @@ -251,6 +259,22 @@
   7.143          return mod(0x7fff800000000000l, 0x800000000001l);
   7.144      }
   7.145  
   7.146 +    @Compare public long conversionFromFloatPositive() {
   7.147 +        return (long) fadd(2, 0.6f);
   7.148 +    }
   7.149 +
   7.150 +    @Compare public long conversionFromFloatNegative() {
   7.151 +        return (long) fadd(-2, -0.6f);
   7.152 +    }
   7.153 +
   7.154 +    @Compare public long conversionFromDoublePositive() {
   7.155 +        return (long) dadd(0x20ffff0000L, 0.6);
   7.156 +    }
   7.157 +
   7.158 +    @Compare public long conversionFromDoubleNegative() {
   7.159 +        return (long) dadd(-0x20ffff0000L, -0.6);
   7.160 +    }
   7.161 +
   7.162      @Compare public boolean divByZeroThrowsArithmeticException() {
   7.163          try {
   7.164              div(1, 0);
   7.165 @@ -272,63 +296,63 @@
   7.166      @Compare public long shiftL1() {
   7.167          return shl(0x00fa37d7763e0ca1l, 5);
   7.168      }
   7.169 -    
   7.170 +
   7.171      @Compare public long shiftL2() {
   7.172          return shl(0x00fa37d7763e0ca1l, 32);
   7.173      }
   7.174 -    
   7.175 +
   7.176      @Compare public long shiftL3() {
   7.177          return shl(0x00fa37d7763e0ca1l, 45);
   7.178      }
   7.179 -    
   7.180 +
   7.181      @Compare public long shiftR1() {
   7.182          return shr(0x00fa37d7763e0ca1l, 5);
   7.183      }
   7.184 -    
   7.185 +
   7.186      @Compare public long shiftR2() {
   7.187          return shr(0x00fa37d7763e0ca1l, 32);
   7.188      }
   7.189 -    
   7.190 +
   7.191      @Compare public long shiftR3() {
   7.192          return shr(0x00fa37d7763e0ca1l, 45);
   7.193      }
   7.194 -    
   7.195 +
   7.196      @Compare public long uShiftR1() {
   7.197          return ushr(0x00fa37d7763e0ca1l, 5);
   7.198      }
   7.199 -    
   7.200 +
   7.201      @Compare public long uShiftR2() {
   7.202          return ushr(0x00fa37d7763e0ca1l, 45);
   7.203      }
   7.204 -    
   7.205 +
   7.206      @Compare public long uShiftR3() {
   7.207          return ushr(0xf0fa37d7763e0ca1l, 5);
   7.208      }
   7.209 -    
   7.210 +
   7.211      @Compare public long uShiftR4() {
   7.212          return ushr(0xf0fa37d7763e0ca1l, 45);
   7.213      }
   7.214 -    
   7.215 +
   7.216      @Compare public long and1() {
   7.217          return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
   7.218      }
   7.219 -    
   7.220 +
   7.221      @Compare public long or1() {
   7.222          return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
   7.223      }
   7.224 -    
   7.225 +
   7.226      @Compare public long xor1() {
   7.227          return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
   7.228      }
   7.229 -    
   7.230 +
   7.231      @Compare public long xor2() {
   7.232          return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
   7.233      }
   7.234 -    
   7.235 +
   7.236      @Compare public long xor3() {
   7.237          return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
   7.238      }
   7.239 -    
   7.240 +
   7.241      @Compare public int compareSameNumbers() {
   7.242          return compare(0x0000000000000000l, 0x0000000000000000l, 0);
   7.243      }