Re: [PATCH 3/3] Handle (-1) + (1) and (-3) - (-2) with bigints
[Thread Prev] | [Thread Next]
- Subject: Re: [PATCH 3/3] Handle (-1) + (1) and (-3) - (-2) with bigints
- From: Ori Bernstein <ori@xxxxxxxxxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Tue, 19 Feb 2019 13:28:56 -0800
- To: myrddin-dev@xxxxxxxxxxxxxx
- Cc: "S. Gilles" <sgilles@xxxxxxxxxxxx>
Pushed, thanks!
On Tue, 19 Feb 2019 08:19:09 -0500
"S. Gilles" <sgilles@xxxxxxxxxxxx> wrote:
> ---
> lib/std/bigint.myr | 42 ++++++++++---
> lib/std/test/bigint.myr | 135 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 167 insertions(+), 10 deletions(-)
>
> diff --git a/lib/std/bigint.myr b/lib/std/bigint.myr
> index c13f0df9..7b0f4bc0 100644
> --- a/lib/std/bigint.myr
> +++ b/lib/std/bigint.myr
> @@ -40,6 +40,7 @@ pkg std =
> const bigiszero : (a : bigint# -> bool)
> const bigiseven : (a : bigint# -> bool)
> const bigcmp : (a : bigint#, b : bigint# -> order)
> + const bigcmpabs : (a : bigint#, b : bigint# -> order)
> generic bigcmpi : (a : bigint#, b : @a -> order) :: numeric,integral @a
>
> /* shorthand for comparisons */
> @@ -412,6 +413,23 @@ const bigcmp = {a, b
> -> `Equal
> }
>
> +const bigcmpabs = {a, b
> + if a.dig.len < b.dig.len
> + -> `Before
> + elif a.dig.len > b.dig.len
> + -> `After
> + else
> + for var i = a.dig.len; i > 0; i--
> + var da = (a.dig[i - 1] : int64)
> + var db = (b.dig[i - 1] : int64)
> + if da != db
> + -> signedorder(da - db)
> + ;;
> + ;;
> + ;;
> + -> `Equal
> +}
> +
> const signedorder = {sign
> if sign < 0
> -> `Before
> @@ -430,14 +448,16 @@ const bigadd = {a, b
> elif b.sign == 0
> -> a
> else
> - match bigcmp(a, b)
> - | `Before: /* a is negative */
> + match bigcmpabs(a, b)
> + | `Before: /* (1) + (-2) or (-1) + (2) */
> a.sign = b.sign
> - -> usub(b, a)
> - | `After: /* b is negative */
> + var r = bigdup(b)
> + usub(r, a)
> + -> bigsteal(a, r)
> + | `After: /* (2) + (-1) or (-2) + (1) */
> -> usub(a, b)
> | `Equal:
> - die("Impossible. Equal vals with different sign.")
> + -> bigclear(a)
> ;;
> ;;
> }
> @@ -482,11 +502,13 @@ const bigsub = {a, b
> elif a.sign != b.sign
> -> uadd(a, b)
> else
> - match bigcmp(a, b)
> - | `Before: /* a is negative */
> - a.sign = b.sign
> - -> usub(b, a)
> - | `After: /* b is negative */
> + match bigcmpabs(a, b)
> + | `Before: /* (-1) - (-2) or (1) - (2) */
> + var r = bigdup(b)
> + usub(r, a)
> + r.sign = -1 * b.sign
> + -> bigsteal(a, r)
> + | `After: /* (-2) - (-1) or (2) - (1) */
> -> usub(a, b)
> | `Equal:
> -> bigclear(a)
> diff --git a/lib/std/test/bigint.myr b/lib/std/test/bigint.myr
> index d312ce41..2467143c 100644
> --- a/lib/std/test/bigint.myr
> +++ b/lib/std/test/bigint.myr
> @@ -16,10 +16,13 @@ type cmd = union
> const main = {
> testr.run([
> [.name = "smoke-test", .fn = smoketest],
> + [.name = "matches-small", .fn = matchsmall],
> [.name = "comparisons", .fn = comparisons],
> [.name = "format-zero", .fn = fmtzero],
> [.name = "division", .fn = smokediv],
> [.name = "modulo", .fn = smokemod],
> + [.name = "add-negatives", .fn = addneg],
> + [.name = "sub-negatives", .fn = subneg],
> ][:])
> }
>
> @@ -49,6 +52,55 @@ const smoketest = {ct
> testr.check(ct, std.eq(buf[:n], "517347321949036993306"), "simple smoke test failed")
> }
>
> +const matchsmall = {c
> + var nums = [ -5, -3, -2, -1, 0, 1, 2, 4, 8, 10 ][:]
> + for a : nums
> + for b : nums
> + var p = std.mkbigint(a)
> + var q = std.mkbigint(b)
> +
> + var radd = std.mkbigint(a + b)
> + var sadd = std.bigdup(p)
> + std.bigadd(sadd, q)
> + testr.check(c, std.bigeq(radd, sadd), "{} + {} != {} (was {})", a, b, a + b, sadd)
> +
> + var rsub = std.mkbigint(a - b)
> + var ssub = std.bigdup(p)
> + std.bigsub(ssub, q)
> + testr.check(c, std.bigeq(rsub, ssub), "{} - {} != {} (was {})", a, b, a - b, ssub)
> +
> + var rmul = std.mkbigint(a * b)
> + var smul = std.bigdup(p)
> + std.bigmul(smul, q)
> + testr.check(c, std.bigeq(rmul, smul), "{} * {} != {} (was {})", a, b, a * b, smul)
> +
> +
> + if b != 0
> + if a > 0 && b > 0
> + var rmod = std.mkbigint(a % b)
> + var smod = std.bigdup(p)
> + std.bigmod(smod, q)
> + testr.check(c, std.bigeq(rmod, smod), "{} % {} != {} (was {})", a, b, a % b, smod)
> + std.bigfree(rmod)
> + ;;
> +
> + var rdiv = std.mkbigint(a / b)
> + var sdiv = std.bigdup(p)
> + std.bigdiv(sdiv, q)
> + testr.check(c, std.bigeq(rdiv, sdiv), "{} / {} != {} (was {})", a, b, a / b, sdiv)
> +
> + std.bigfree(rdiv)
> + ;;
> +
> + std.bigfree(p)
> + std.bigfree(q)
> + std.bigfree(radd)
> + std.bigfree(rsub)
> + std.bigfree(rmul)
> + ;;
> + ;;
> +}
> +
> const comparisons = {c
> /* some comparison tests */
> var a = try(std.bigparse("1234_5678_1234_6789_6666_7777_8888"))
> @@ -122,7 +174,90 @@ const smokemod = {c
> std.mk(`Val "755578"), \
> std.mk(`Val "75557863709417659441940"))), \
> "27076504425474791131220")
> +}
> +
> +const addneg = {c
> + run(c, std.mk(`Add (\
> + std.mk(`Val "-1"), \
> + std.mk(`Val "1"))), \
> + "0")
> +
> + run(c, std.mk(`Add (\
> + std.mk(`Val "4"), \
> + std.mk(`Val "-2"))), \
> + "2")
> +
> + run(c, std.mk(`Add (\
> + std.mk(`Val "3"), \
> + std.mk(`Val "-6"))), \
> + "-3")
>
> + run(c, std.mk(`Add (\
> + std.mk(`Val "-4"), \
> + std.mk(`Val "8"))), \
> + "4")
> +
> + run(c, std.mk(`Add (\
> + std.mk(`Val "-10"), \
> + std.mk(`Val "5"))), \
> + "-5")
> +
> + run(c, std.mk(`Add (\
> + std.mk(`Val "-6"), \
> + std.mk(`Val "-12"))), \
> + "-18")
> +
> + run(c, std.mk(`Add (\
> + std.mk(`Val "7"), \
> + std.mk(`Val "-7"))), \
> + "0")
> +}
> +
> +const subneg = {c
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-1"), \
> + std.mk(`Val "1"))), \
> + "-2")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "1"), \
> + std.mk(`Val "-1"))), \
> + "2")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "4"), \
> + std.mk(`Val "-2"))), \
> + "6")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "3"), \
> + std.mk(`Val "-6"))), \
> + "9")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-4"), \
> + std.mk(`Val "8"))), \
> + "-12")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-10"), \
> + std.mk(`Val "5"))), \
> + "-15")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-6"), \
> + std.mk(`Val "-12"))), \
> + "6")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-14"), \
> + std.mk(`Val "-7"))), \
> + "-7")
> +
> + run(c, std.mk(`Sub (\
> + std.mk(`Val "-8"), \
> + std.mk(`Val "-8"))), \
> + "0")
> }
>
> const run = {c : testr.ctx#, e : cmd#, res : byte[:]
> --
> 2.20.1
>
>
--
Ori Bernstein <ori@xxxxxxxxxxxxxx>
| [PATCH 0/3] Handle negatives in bigint arithmetic | "S. Gilles" <sgilles@xxxxxxxxxxxx> |
| [PATCH 3/3] Handle (-1) + (1) and (-3) - (-2) with bigints | "S. Gilles" <sgilles@xxxxxxxxxxxx> |
- Prev by Date: [PATCH 3/3] Handle (-1) + (1) and (-3) - (-2) with bigints
- Next by Date: __fini__
- Previous by thread: [PATCH 3/3] Handle (-1) + (1) and (-3) - (-2) with bigints
- Next by thread: __fini__
- Index(es):