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