# HG changeset patch # User Jaroslav Tulach # Date 1353261698 -3600 # Node ID d441042e6c11124095dfe8ad33abc2cc18a6259f # Parent 03be8510007ce03e1856434393f4ca11df0ab79b Reimplementing readDouble to not depend on too high longs diff -r 03be8510007c -r d441042e6c11 emul/src/main/java/java/io/DataInputStream.java --- a/emul/src/main/java/java/io/DataInputStream.java Sun Nov 18 16:45:50 2012 +0100 +++ b/emul/src/main/java/java/io/DataInputStream.java Sun Nov 18 19:01:38 2012 +0100 @@ -25,6 +25,8 @@ package java.io; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * A data input stream lets an application read primitive Java data * types from an underlying input stream in a machine-independent @@ -465,7 +467,41 @@ * @see java.lang.Double#longBitsToDouble(long) */ public final double readDouble() throws IOException { - return Double.longBitsToDouble(readLong()); + int hi = readInt(); + int low = readInt(); + return toDouble(hi, low); + } + + @JavaScriptBody(args={ "hi", "low" }, + body= + "if (low == 0) {\n" + + " if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n" + + " if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n" + + "}\n" + + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n" + + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n" + + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n" + + "var e = (hi >> 20) & 0x7ff;\n" + + "var to32 = low >> 0;\n" + + "if (e === 0) {\n" + + " if (to32 & 0x80000000) {\n" + + " hi = hi << 1 + 1; low = low << 1;\n" + + " } else {\n" + + " hi = hi << 1; low = low << 1;\n" + + " }\n" + + "} else {\n" + + " hi = (hi & 0xfffff) | 0x100000;\n" + + "}\n" + + "to32 = low >> 0;\n" + + "var m = Math.pow(2.0, 32) * hi + to32;\n" + + "var r = s * m * Math.pow(2.0, e - 1075);\n" + + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n" + + "return r;\n" + ) + private static double toDouble(int hi, int low) { + long both = hi; + both = (both << 32) & low; + return Double.doubleToLongBits(both); } private char lineBuffer[]; diff -r 03be8510007c -r d441042e6c11 vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Sun Nov 18 16:45:50 2012 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Sun Nov 18 19:01:38 2012 +0100 @@ -17,6 +17,11 @@ */ package org.apidesign.vm4brwsr; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import javax.script.Invocable; import javax.script.ScriptException; import static org.testng.Assert.*; @@ -71,6 +76,23 @@ Double.valueOf(exp) ); } + + @Test public void deserializeSimpleLong() throws Exception { + assertExec("Should be 3454", "org_apidesign_vm4brwsr_Numbers_deserLongJAB", + Double.valueOf(3454), + new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)13, (byte)126 } + ); + } + /* XXX: JavaScript cannot represent as big longs as Java. + @Test public void deserializeLargeLong() throws Exception { + final byte[] arr = new byte[] { + (byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 + }; + long exp = Numbers.deserLong(arr); + assertExec("Should be " + exp, "org_apidesign_vm4brwsr_Numbers_deserLongJAB", + Double.valueOf(exp), arr); + } + */ @Test public void deserializeFloatInJava() throws Exception { float f = 54324.32423f; @@ -85,7 +107,32 @@ ); } + @Test public void deserializeDoubleInJava() throws Exception { + double f = 3.0; + double r = Numbers.deserDouble(); + assertEquals(r, f, 0.001, "Doubles are the same"); + } + @Test public void deserializeDoubleInJS() throws Exception { + double f = 3.0; + assertExec("Should be the same", "org_apidesign_vm4brwsr_Numbers_deserDoubleD", f); + } + /* + @Test public void serDouble() throws IOException { + double f = 3.0; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DataOutputStream d = new DataOutputStream(os); + d.writeLong(3454); + d.close(); + + StringBuilder sb = new StringBuilder(); + byte[] arr = os.toByteArray(); + for (int i = 0; i < arr.length; i++) { + sb.append("(byte)").append(arr[i]).append(", "); + } + fail("" + sb); + } +*/ private static CharSequence codeSeq; private static Invocable code; diff -r 03be8510007c -r d441042e6c11 vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Sun Nov 18 16:45:50 2012 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Sun Nov 18 19:01:38 2012 +0100 @@ -43,6 +43,17 @@ float r = dis.readFloat(); return r; } + static double deserDouble() throws IOException { + byte[] arr = {(byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0}; + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + return dis.readDouble(); + } + static long deserLong(byte[] arr) throws IOException { + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + return dis.readLong(); + } static int deserInt() throws IOException { byte[] arr = {(byte) 71, (byte) 84, (byte) 52, (byte) 83}; ByteArrayInputStream is = new ByteArrayInputStream(arr);