shithub: mc

Download patch

ref: c98dd1239d76a56d36ce6511239ccfce2b5c6e43
parent: 33191432d1d295d78a1c5638de7a9d9fc0ea97e4
author: Ori Bernstein <[email protected]>
date: Wed Jan 22 21:52:56 EST 2014

Handle zeros correctly in bigint.myr

--- a/libstd/bigint.myr
+++ b/libstd/bigint.myr
@@ -23,6 +23,7 @@
 	const mkbigint	: (v : int32 -> bigint#)
 	const bigfree	: (a : bigint# -> void)
 	const bigdup	: (a : bigint# -> bigint#)
+	const bigassign	: (d : bigint#, s : bigint# -> bigint#)
 	const bigparse	: (s : byte[:] -> option(bigint#))
 	const bigfmt	: (b : byte[:], a : bigint# -> size)
 
@@ -70,14 +71,17 @@
 }
 
 const bigdup = {a
-	var v
+	-> bigassign(zalloc(), a)
+}
 
-	v = zalloc()
-	v.dig = sldup(a.dig)
-	v.sign = a.sign
-	-> v
+const bigassign = {d, s
+	slfree(d.dig)
+	d.dig = sldup(s.dig)
+	d.sign = s.sign
+	-> d
 }
 
+
 /* for now, just dump out something for debugging... */
 const bigfmt = {buf, val
 	const digitchars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
@@ -173,14 +177,14 @@
 	else
 		/* the one with more digits has greater magnitude */
 		if a.dig.len > b.dig.len
-			-> signedmagorder(a.sign)
+			-> signedorder(a.sign)
 		;;
 		/* otherwise, the one with the first larger digit is bigger */
 		for i = a.dig.len; i > 0; i--
 			if a.dig[i - 1] > b.dig[i - 1]
-				-> signedmagorder(a.sign)
+				-> signedorder(a.sign)
 			elif b.dig[i - 1] > a.dig[i - 1]
-				-> signedmagorder(a.sign)
+				-> signedorder(a.sign)
 			;;
 		;;
 	;;
@@ -187,9 +191,9 @@
 	-> `Equal
 }
 
-const signedmagorder = {sign
+const signedorder = {sign
 	if sign < 0
-		-> `Before
+		-> `Before 
 	else
 		-> `After
 	;;
@@ -240,7 +244,15 @@
 
 /* a -= b */
 const bigsub = {a, b
-	if a.sign != b.sign
+	/* 0 - x = -x */
+	if a.sign == 0
+		bigassign(a, b)
+		a.sign = -b.sign
+		-> a
+	/* x - 0 = x */
+	elif b.sign == 0
+		-> a
+	elif a.sign != b.sign
 		-> uadd(a, b)
 	else
 		match bigcmp(a, b)
@@ -281,8 +293,12 @@
 	var carry, t
 	var w
 
-	/* trim() will take care of the zero case */
-	if a.sign != b.sign
+	if a.sign == 0 || b.sign == 0
+		a.sign = 0
+		slfree(a.dig)
+		a.dig = [][:]
+		-> a
+	elif a.sign != b.sign
 		a.sign = -1
 	else
 		a.sign = 1