Browse Source

added Output.writeDouble and Input.readDouble (closed issue #209)

Simon Krajewski 13 years ago
parent
commit
a530afe11d
3 changed files with 86 additions and 14 deletions
  1. 44 4
      std/haxe/io/Input.hx
  2. 30 2
      std/haxe/io/Output.hx
  3. 12 8
      tests/unit/TestIO.hx

+ 44 - 4
std/haxe/io/Input.hx

@@ -159,7 +159,7 @@ class Input {
 			var sig = ((bytes[1] & 0x7F) << 16) | (bytes[2] << 8) | bytes[3];
 			if (sig == 0 && exp == -127)
 				return 0.0;
-			return sign*(1 + Math.pow(2, -23)*sig)*Math.pow(2, exp);
+			return sign*(1 + Math.pow(2, -23)*sig) * Math.pow(2, exp);
 		#end
 	}
 
@@ -171,9 +171,28 @@ class Input {
 		#elseif php
 			var a = untyped __call__('unpack', 'd', readString(8));
 			return a[1];
-		#else
-			throw "Not implemented";
+		#elseif (flash || js)
+		var bytes = [];
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		bytes.push(readByte());
+		if (bigEndian)
+			bytes.reverse();
+			
+		var sign = 1 - ((bytes[0] >> 7) << 1); // sign = bit 0
+		var exp = (((bytes[0] << 4) & 0x7FF) | (bytes[1] >> 4)) - 1023; // exponent = bits 1..11
+		var sig = getDoubleSig(bytes);
+		if (sig == 0 && exp == -1023)
 			return 0.0;
+		return sign * (1.0 + Math.pow(2, -52) * sig) * Math.pow(2, exp);
+		#else
+		throw "not implemented";
+		return 0.0;
 		#end
 	}
 
@@ -278,4 +297,25 @@ class Input {
 	static var _double_of_bytes = cpp.Lib.load("std","double_of_bytes",2);
 #end
 
-}
+#if flash
+	function getDoubleSig(bytes:Array<Int>) : Int
+    {
+        return untyped 
+        {
+            Std.int(((((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * Math.pow(2, 32))) +
+            Std.int(((bytes[4] >> 7) * Math.pow(2,31))) +
+            Std.int((((bytes[4]&0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]));
+        };
+    }
+#elseif js
+	function getDoubleSig(bytes:Array<Int>) : Int
+    {
+        return untyped 
+        {
+            Std.parseInt(((((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * Math.pow(2, 32)).toString()) +
+            Std.parseInt(((bytes[4] >> 7) * Math.pow(2,31)).toString()) +
+            Std.parseInt((((bytes[4]&0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]).toString());
+        };
+    }	
+#end
+}

+ 30 - 2
std/haxe/io/Output.hx

@@ -103,7 +103,7 @@ class Output {
 		#else
 		if (x == 0.0)
 		{
-			writeByte(0); writeByte(0);	writeByte(0); writeByte(0);
+			writeByte(0); writeByte(0); writeByte(0); writeByte(0);
 			return;
 		}
 		var exp = Math.floor(Math.log(Math.abs(x)) / LN2);
@@ -131,7 +131,35 @@ class Output {
 		#elseif php
 		write(untyped Bytes.ofString(__call__('pack', 'd', x)));
 		#else
-		throw "Not implemented";
+		if (x == 0.0) 
+		{
+			writeByte(0); writeByte(0); writeByte(0); writeByte(0);
+			writeByte(0); writeByte(0); writeByte(0); writeByte(0);
+			return;
+		}
+        
+		var exp = Math.floor(Math.log(Math.abs(x)) / LN2);
+		var sig : Int = Math.floor(Math.abs(x) / Math.pow(2, exp) * Math.pow(2, 52));
+		var sig_h = (sig & cast 34359738367);
+		var sig_l = Math.floor((sig / Math.pow(2,32)));
+		var b1 = (exp + 0x3FF) >> 4 | (exp>0 ? ((x<0) ? 1<<7 : 1<<6) : ((x<0) ? 1<<7 : 0)),
+			b2 = (exp + 0x3FF) << 4 & 0xFF | (sig_l >> 16 & 0xF),
+			b3 = (sig_l >> 8) & 0xFF,
+			b4 = sig_l & 0xFF,
+			b5 = (sig_h >> 24) & 0xFF,
+			b6 = (sig_h >> 16) & 0xFF,
+			b7 = (sig_h >> 8) & 0xFF,
+			b8 = sig_h & 0xFF;
+		if (bigEndian)
+		{
+			writeByte(b8); writeByte(b7); writeByte(b6); writeByte(b5);
+			writeByte(b4); writeByte(b3); writeByte(b2); writeByte(b1);
+		}
+		else
+		{
+			writeByte(b1); writeByte(b2); writeByte(b3); writeByte(b4);
+			writeByte(b5); writeByte(b6); writeByte(b7); writeByte(b8);
+		}
 		#end
 	}
 

+ 12 - 8
tests/unit/TestIO.hx

@@ -43,10 +43,14 @@ class TestIO extends Test {
 		excv(function() o.writeBytes(b,3,20),OutsideBounds);
 
 		o.writeByte(98);
-		#if (neko || flash9 || php || cpp)
 		o.writeDouble(1.23);
-		#end
+		o.writeDouble(-1.23);
+		o.writeDouble(0.0);
+		o.writeDouble(-0.0);
 		o.writeFloat(1.2e10);
+		o.writeFloat(-1.2e10);
+		o.writeFloat(0.0);
+		o.writeFloat(-0.0);
 		o.writeByte(99);
 
 		var str = "Héllo World !";
@@ -91,14 +95,14 @@ class TestIO extends Test {
 		eq( i.read(5).compare(b.sub(3,5)), 0 );
 
 		eq( i.readByte(), 98 );
-		#if (neko || flash9 || php || cpp)
 		eq( i.readDouble(), 1.23 );
-		#else
-		// these two are not implemented
-		exc(function() i.readDouble());
-		//exc(function() i.readFloat());
-		#end
+		eq( i.readDouble(), -1.23 );
+		eq( i.readDouble(), 0.0 );
+		eq( i.readDouble(), -0.0 );
 		eq( i.readFloat(), 1.2e10 );
+		eq( i.readFloat(), -1.2e10 );
+		eq( i.readFloat(), 0.0 );
+		eq( i.readFloat(), -0.0 );
 		eq( i.readByte(), 99 );
 
 		eq( i.readString(haxe.io.Bytes.ofString(str).length), str );