Support for Long multiplication + tests arithmetic
authorMartin Soch <Martin.Soch@oracle.com>
Mon, 04 Feb 2013 09:41:33 +0100
brancharithmetic
changeset 657b42bfe334128
parent 630 04e312a7887e
child 669 3754580b6c67
Support for Long multiplication + tests
emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java
vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java
     1.1 --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Fri Feb 01 09:00:30 2013 +0100
     1.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Feb 04 09:41:33 2013 +0100
     1.3 @@ -80,6 +80,32 @@
     1.4      return hi.next32(low);
     1.5  };
     1.6  
     1.7 +Number.prototype.mul64 = function(x) {
     1.8 +    var low = this.mul32(x);
     1.9 +    low += (low < 0) ? (__m32+1) : 0;
    1.10 +    // first count upper 32 bits of (this.low * x.low)
    1.11 +    var hi_hi = 0;
    1.12 +    var hi_low = 0;
    1.13 +    var m = 1;
    1.14 +    for (var i = 0; i < 32; i++) {
    1.15 +        if (x & m) {
    1.16 +            hi_hi += this >>> 16;
    1.17 +            hi_low += this & 0xFFFF
    1.18 +        }
    1.19 +        hi_low >>= 1;
    1.20 +        hi_low += (hi_hi & 1) ? 0x8000 : 0;
    1.21 +        hi_hi >>= 1;
    1.22 +        m <<= 1;
    1.23 +    }
    1.24 +    var hi = (hi_hi << 16) + hi_low;
    1.25 +    
    1.26 +    var m1 = this.high32().mul32(x);
    1.27 +    var m2 = this.mul32(x.high32());
    1.28 +    hi = hi.add32(m1).add32(m2);
    1.29 +    
    1.30 +    return hi.next32(low);
    1.31 +};
    1.32 +
    1.33  Number.prototype.div64 = function(x) {
    1.34      var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough
    1.35      if (low > __m32) {
     2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Feb 01 09:00:30 2013 +0100
     2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Feb 04 09:41:33 2013 +0100
     2.3 @@ -544,7 +544,7 @@
     2.4                      emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
     2.5                      break;
     2.6                  case opc_lmul:
     2.7 -                    emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
     2.8 +                    emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
     2.9                      break;
    2.10                  case opc_fmul:
    2.11                      emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
     3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Fri Feb 01 09:00:30 2013 +0100
     3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Mon Feb 04 09:41:33 2013 +0100
     3.3 @@ -219,6 +219,56 @@
     3.4          );
     3.5      }
     3.6      
     3.7 +    @Test public void longMultiplyMax() throws Exception {
     3.8 +        final long res = Long.MAX_VALUE * 2l;
     3.9 +        assertExec("Multiplication MAX*2",
    3.10 +            Numbers.class, "mulL__J_3B_3B",
    3.11 +            Double.valueOf(res),
    3.12 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
    3.13 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02 }
    3.14 +        );
    3.15 +    }
    3.16 +    
    3.17 +    @Test public void longMultiplyMaxAndMax() throws Exception {
    3.18 +        final long res = Long.MAX_VALUE * Long.MAX_VALUE;
    3.19 +        assertExec("Multiplication MAX*MAX",
    3.20 +            Numbers.class, "mulL__J_3B_3B",
    3.21 +            Double.valueOf(res),
    3.22 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
    3.23 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }
    3.24 +        );
    3.25 +    }
    3.26 +    
    3.27 +    @Test public void longMultiplyMin() throws Exception {
    3.28 +        final long res = Long.MIN_VALUE * 2l;
    3.29 +        assertExec("Multiplication MIN*2",
    3.30 +            Numbers.class, "mulL__J_3B_3B",
    3.31 +            Double.valueOf(res),
    3.32 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
    3.33 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02 }
    3.34 +        );
    3.35 +    }
    3.36 +    
    3.37 +    @Test public void longMultiplyMinAndMin() throws Exception {
    3.38 +        final long res = Long.MIN_VALUE * Long.MIN_VALUE;
    3.39 +        assertExec("Multiplication MIN*2",
    3.40 +            Numbers.class, "mulL__J_3B_3B",
    3.41 +            Double.valueOf(res),
    3.42 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
    3.43 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
    3.44 +        );
    3.45 +    }
    3.46 +    
    3.47 +    @Test public void longMultiplyPrecision() throws Exception {
    3.48 +        final long res = 0x00fa37d7763e0ca1l * 0xa7b3432fff00123el;
    3.49 +        assertExec("Multiplication",
    3.50 +            Numbers.class, "mulL__J_3B_3B",
    3.51 +            Double.valueOf(res),
    3.52 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
    3.53 +            new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
    3.54 +        );
    3.55 +    }
    3.56 +    
    3.57      @Test public void longShiftL1() throws Exception {
    3.58          final long res = 0x00fa37d7763e0ca1l << 5;
    3.59          assertExec("Long << 5",
     4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Fri Feb 01 09:00:30 2013 +0100
     4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Mon Feb 04 09:41:33 2013 +0100
     4.3 @@ -94,8 +94,12 @@
     4.4          return (disX.readLong() - disY.readLong());
     4.5      }
     4.6      
     4.7 -    public static long mulL(long x, long y) {
     4.8 -        return (x * y);
     4.9 +    public static long mulL(byte[] arrX, byte[] arrY) throws IOException {
    4.10 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    4.11 +        DataInputStream disX = new DataInputStream(isX);
    4.12 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    4.13 +        DataInputStream disY = new DataInputStream(isY);
    4.14 +        return (disX.readLong() * disY.readLong());
    4.15      }
    4.16      
    4.17      public static long divL(long x, long y) {