ref: 6507bf31d345f0046a1415088e42390c8befdd97
dir: /lib/std/test/bigint.myr/
use std
type cmd = union
`Add (cmd#, cmd#)
`Sub (cmd#, cmd#)
`Mul (cmd#, cmd#)
`Div (cmd#, cmd#)
`Mod (cmd#, cmd#)
`Shl (cmd#, cmd#)
`Shr (cmd#, cmd#)
`Modpow (cmd#, cmd#, cmd#)
`Val byte[:]
;;
const main = {
var a, b, c, d, e
var buf : byte[64], n
/* a few combined ops */
a = std.mkbigint(1234)
b = std.mkbigint(0x7fffffff)
c = std.mkbigint(7919)
d = std.mkbigint(113051)
e = std.mkbigint(11)
std.bigmul(a, b)
std.bigmul(a, b)
std.bigadd(a, c)
std.bigsub(a, d)
std.bigdiv(a, e)
std.bigfree(b)
std.bigfree(c)
std.bigfree(d)
std.bigfree(e)
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("{} == {}\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 */
run(std.mk(`Div (\
std.mk(`Val "1234_5678_1234_6789_6666_7777_8888"), \
std.mk(`Val "1234_5678_1234_6789_6666_7777"))), \
"10000")
run(std.mk(`Div (\
std.mk(`Val "0xffff_1234_1234_1234_1234"), \
std.mk(`Val "0xf010_1234_2314"))), \
"4580035496")
run(std.mk(`Div (\
std.mk(`Val "5192296858534810493479828944327220"), \
std.mk(`Val "75557863709417659441940"))), \
"68719476751")
run(std.mk(`Div (\
std.mk(`Val "75557863709417659441940"), \
std.mk(`Val "5192296858534810493479828944327220"))), \
"0")
/* smoke test for mod */
run(std.mk(`Mod (\
std.mk(`Val "5192296858534810493479828944327220"), \
std.mk(`Val "75557863709417659441940"))),\
"257025710597479990280")
run(std.mk(`Modpow (\
std.mk(`Val "1"), \
std.mk(`Val "3"), \
std.mk(`Val "2"))), \
"1")
run(std.mk(`Modpow (\
std.mk(`Val "5192296858534810493479828944327220"), \
std.mk(`Val "75557863709417659441940"), \
std.mk(`Val "755578"))), \
"49054")
run(std.mk(`Modpow (\
std.mk(`Val "7220"), \
std.mk(`Val "755578"), \
std.mk(`Val "75557863709417659441940"))), \
"27076504425474791131220")
}
const run = {e : cmd#, res : byte[:]
var buf : byte[4096]
var v, n
v = eval(e)
n = std.bigbfmt(buf[:], v, 0)
if !std.sleq(buf[:n], res)
std.fatal("%s != %s\n", buf[:n], res)
;;
}
const eval = {e : cmd#
var buf : byte[2048]
var a, b, c /* scratch vars */
var n /* buf len */
match e#
| `Add (x, y): -> binop("+", std.bigadd, x, y)
| `Sub (x, y): -> binop("-", std.bigsub, x, y)
| `Mul (x, y): -> binop("*", std.bigmul, x, y)
| `Div (x, y): -> binop("/", std.bigdiv, x, y)
| `Mod (x, y): -> binop("%", std.bigmod, x, y)
| `Shl (x, y): -> binop("<<", std.bigshl, x, y)
| `Shr (x, y): -> binop(">>", std.bigshr, x, y)
| `Val x:
a = try(std.bigparse(x))
n = std.bigbfmt(buf[:], a, 0)
-> a
| `Modpow (x, y, z):
a = eval(x)
b = eval(y)
c = eval(z)
-> std.bigmodpow(a, b, c)
;;
}
const binop = {name, op, x, y
var a, b
a = eval(x)
b = eval(y)
op(a, b)
std.bigfree(b)
-> a
}
generic try = {x : std.option(@a)
match x
| `std.Some v: -> v
| `std.None: std.die("failed to get val")
;;
}