shithub: mc

Download patch

ref: 6235cb639285f9ff5a7fc483a1950a8cd42f9aa9
parent: 88df32c77ff6806dee396803b8a9145f53c04ae3
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 19 20:29:46 EDT 2015

Fix floating point formatting.

--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -266,7 +266,9 @@
 		for var i = a.dig.len; i > 0; i--
 			da = a.dig[i - 1] castto(int64)
 			db = b.dig[i - 1] castto(int64)
-			-> signedorder(sa * (da - db))
+			if da != db
+				-> signedorder(sa * (da - db))
+			;;
 		;;
 	;;
 	-> `Equal
--- a/lib/std/fltfmt.myr
+++ b/lib/std/fltfmt.myr
@@ -19,11 +19,17 @@
 
 const Dblbias = 1023
 const Fltbias = 127
+const Dblminmant	= 1 << 52	/* the minimum mantissa for a normal float. */
 
 const flt64bfmt = {sb, val, mode, precision
 	var isneg, exp, mant
 
 	(isneg, mant, exp) = flt64explode(val)
+	/* adjust for denormals */
+	while mant < Dblminmant
+		mant <<= 1
+		exp--
+	;;
 	dragon4(sb, isneg, mant, (exp - 52) castto(int64), Dblbias, mode, precision)
 }
 
@@ -163,6 +169,7 @@
 	;;
 	while true
 		k--
+
 		bigmuli(r, 10)
 		u = bigdup(r);
 		bigdiv(u, s)
@@ -179,16 +186,20 @@
 		| _:
 		;;
 		bigfree(t)
-		
+
+		/* v = 2*r */
 		v = bigdup(r)
 		bigshli(v, 1)
+
+		/* t = 2*s - mp */
 		t = bigdup(s)
 		bigshli(t, 1)
 		bigsub(t, mp)
+
 		match bigcmp(v, t)
-		| `After: high = true
-		| `Equal: high = roundup
-		| `Before: high = false
+		| `Before: high = false;
+		| `Equal: high = roundup;
+		| `After: high = true;
 		;;
 		bigfree(v)
 		bigfree(t)
--- a/lib/std/test/bigint.myr
+++ b/lib/std/test/bigint.myr
@@ -37,6 +37,27 @@
 	n = std.bigbfmt(buf[:], a, 0)
 	std.assert(std.sleq(buf[:n], "517347321949036993306"), "simple smoke test failed")
 
+	/* some comparison tests */
+	a = try(std.bigparse("1234_5678_1234_6789_6666_7777_8888"))
+	b = try(std.bigparse("2234_5678_1234_6789_6666_7777_8888"))
+	match std.bigcmp(a, b)
+	| `std.Before:	/* everything is as it should be */
+	| `std.Equal:	std.fatal("lies: {} == {}\n", a, b)
+	| `std.After:	std.fatal("lies: {} > {}\n", a, b)
+	;;
+	std.bigfree(a)
+	std.bigfree(b)
+
+	a = try(std.bigparse("36028797018963964"))
+	b = try(std.bigparse("36028797018963958"))
+	match std.bigcmp(a, b)
+	| `std.Before:	std.fatal("lies: {} < {}\n", a, b)
+	| `std.Equal:	std.fatal("lies: {} == {}\n", a, b)
+	| `std.After:	/* everything is as it should be */
+	;;
+	std.bigfree(a)
+	std.bigfree(b)
+
 	/* make sure we format '0' correctly */
 	run(std.mk(`Val "0"), "0")
 	/* smoke test for division */