Reimplementing readDouble to not depend on too high longs javap
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 18 Nov 2012 19:01:38 +0100
branchjavap
changeset 185d441042e6c11
parent 184 03be8510007c
child 186 123ba97c3718
Reimplementing readDouble to not depend on too high longs
emul/src/main/java/java/io/DataInputStream.java
vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java
vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java
     1.1 --- a/emul/src/main/java/java/io/DataInputStream.java	Sun Nov 18 16:45:50 2012 +0100
     1.2 +++ b/emul/src/main/java/java/io/DataInputStream.java	Sun Nov 18 19:01:38 2012 +0100
     1.3 @@ -25,6 +25,8 @@
     1.4  
     1.5  package java.io;
     1.6  
     1.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     1.8 +
     1.9  /**
    1.10   * A data input stream lets an application read primitive Java data
    1.11   * types from an underlying input stream in a machine-independent
    1.12 @@ -465,7 +467,41 @@
    1.13       * @see        java.lang.Double#longBitsToDouble(long)
    1.14       */
    1.15      public final double readDouble() throws IOException {
    1.16 -        return Double.longBitsToDouble(readLong());
    1.17 +        int hi = readInt();
    1.18 +        int low = readInt();
    1.19 +        return toDouble(hi, low);
    1.20 +    }
    1.21 +    
    1.22 +    @JavaScriptBody(args={ "hi", "low" },
    1.23 +        body=
    1.24 +          "if (low == 0) {\n"
    1.25 +        + "  if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n"
    1.26 +        + "  if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n"
    1.27 +        + "}\n"
    1.28 +        + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n"
    1.29 +        + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n"
    1.30 +        + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n"
    1.31 +        + "var e = (hi >> 20) & 0x7ff;\n"
    1.32 +        + "var to32 = low >> 0;\n"
    1.33 +        + "if (e === 0) {\n"
    1.34 +        + "  if (to32 & 0x80000000) {\n"
    1.35 +        + "    hi = hi << 1 + 1; low = low << 1;\n"
    1.36 +        + "  } else {\n"
    1.37 +        + "    hi = hi << 1; low = low << 1;\n"
    1.38 +        + "  }\n" 
    1.39 +        + "} else {\n"
    1.40 +        + "    hi = (hi & 0xfffff) | 0x100000;\n"
    1.41 +        + "}\n"
    1.42 +        + "to32 = low >> 0;\n"
    1.43 +        + "var m = Math.pow(2.0, 32) * hi + to32;\n"
    1.44 +        + "var r = s * m * Math.pow(2.0, e - 1075);\n"
    1.45 +        + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n"
    1.46 +        + "return r;\n"
    1.47 +    )
    1.48 +    private static double toDouble(int hi, int low) {
    1.49 +        long both = hi;
    1.50 +        both = (both << 32) & low;
    1.51 +        return Double.doubleToLongBits(both);
    1.52      }
    1.53  
    1.54      private char lineBuffer[];
     2.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Sun Nov 18 16:45:50 2012 +0100
     2.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Sun Nov 18 19:01:38 2012 +0100
     2.3 @@ -17,6 +17,11 @@
     2.4   */
     2.5  package org.apidesign.vm4brwsr;
     2.6  
     2.7 +import java.io.ByteArrayInputStream;
     2.8 +import java.io.ByteArrayOutputStream;
     2.9 +import java.io.DataInputStream;
    2.10 +import java.io.DataOutputStream;
    2.11 +import java.io.IOException;
    2.12  import javax.script.Invocable;
    2.13  import javax.script.ScriptException;
    2.14  import static org.testng.Assert.*;
    2.15 @@ -71,6 +76,23 @@
    2.16              Double.valueOf(exp)
    2.17          );
    2.18      }
    2.19 +
    2.20 +    @Test public void deserializeSimpleLong() throws Exception {
    2.21 +        assertExec("Should be 3454", "org_apidesign_vm4brwsr_Numbers_deserLongJAB", 
    2.22 +            Double.valueOf(3454), 
    2.23 +            new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)13, (byte)126 }
    2.24 +        );
    2.25 +    }
    2.26 +    /* XXX: JavaScript cannot represent as big longs as Java. 
    2.27 +    @Test public void deserializeLargeLong() throws Exception {
    2.28 +        final byte[] arr = new byte[] {
    2.29 +            (byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0
    2.30 +        };
    2.31 +        long exp = Numbers.deserLong(arr);
    2.32 +        assertExec("Should be " + exp, "org_apidesign_vm4brwsr_Numbers_deserLongJAB", 
    2.33 +            Double.valueOf(exp), arr);
    2.34 +    }
    2.35 +    */
    2.36      
    2.37      @Test public void deserializeFloatInJava() throws Exception {
    2.38          float f = 54324.32423f;
    2.39 @@ -85,7 +107,32 @@
    2.40          );
    2.41      }
    2.42  
    2.43 +    @Test public void deserializeDoubleInJava() throws Exception {
    2.44 +        double f = 3.0;
    2.45 +        double r = Numbers.deserDouble();
    2.46 +        assertEquals(r, f, 0.001, "Doubles are the same");
    2.47 +    }
    2.48      
    2.49 +    @Test public void deserializeDoubleInJS() throws Exception {
    2.50 +        double f = 3.0;
    2.51 +        assertExec("Should be the same", "org_apidesign_vm4brwsr_Numbers_deserDoubleD", f);
    2.52 +    }
    2.53 +    /*
    2.54 +    @Test public void serDouble() throws IOException {
    2.55 +        double f = 3.0;
    2.56 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
    2.57 +        DataOutputStream d = new DataOutputStream(os);
    2.58 +        d.writeLong(3454);
    2.59 +        d.close();
    2.60 +        
    2.61 +        StringBuilder sb = new StringBuilder();
    2.62 +        byte[] arr = os.toByteArray();
    2.63 +        for (int i = 0; i < arr.length; i++) {
    2.64 +            sb.append("(byte)").append(arr[i]).append(", ");
    2.65 +        }
    2.66 +        fail("" + sb);
    2.67 +    }
    2.68 +*/    
    2.69      private static CharSequence codeSeq;
    2.70      private static Invocable code;
    2.71  
     3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Sun Nov 18 16:45:50 2012 +0100
     3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Sun Nov 18 19:01:38 2012 +0100
     3.3 @@ -43,6 +43,17 @@
     3.4          float r = dis.readFloat();
     3.5          return r;
     3.6      }
     3.7 +    static double deserDouble() throws IOException {
     3.8 +        byte[] arr = {(byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0};
     3.9 +        ByteArrayInputStream is = new ByteArrayInputStream(arr);
    3.10 +        DataInputStream dis = new DataInputStream(is);
    3.11 +        return dis.readDouble();
    3.12 +    }
    3.13 +    static long deserLong(byte[] arr) throws IOException {
    3.14 +        ByteArrayInputStream is = new ByteArrayInputStream(arr);
    3.15 +        DataInputStream dis = new DataInputStream(is);
    3.16 +        return dis.readLong();
    3.17 +    }
    3.18      static int deserInt() throws IOException {
    3.19          byte[] arr = {(byte) 71, (byte) 84, (byte) 52, (byte) 83};
    3.20          ByteArrayInputStream is = new ByteArrayInputStream(arr);