ref: 6d707df71c0fe11da7dd53bf36eb3d3fadb8ec9b
dir: /lib/std/test/bigint.myr/
use std use testr 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 = { 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], [.name = "bigdivmod", .fn = somebigdivmod], ][:]) } const smoketest = {ct var a, b, c, d, e, f 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) f = std.mkbigint((4294967296 : int64)) 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) testr.check(ct, std.eq(buf[:n], "517347321949036993306"), "simple smoke test failed") n = std.bigbfmt(buf[:], f, 0) testr.check(ct, std.eq(buf[:n], "4294967296"), "smoke test failed for 2^32 case") } 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")) var b = try(std.bigparse("2234_5678_1234_6789_6666_7777_8888")) testr.check(c, std.bigcmp(a, b) == `std.Before, "{} should be < {}", a, b) std.bigfree(a) std.bigfree(b) a = try(std.bigparse("36028797018963964")) b = try(std.bigparse("36028797018963958")) testr.check(c, std.bigcmp(a, b) == `std.After, "{} should be > {}", a, b) std.bigfree(a) std.bigfree(b) } const fmtzero = {c /* make sure we format '0' correctly */ run(c, std.mk(`Val "0"), "0") } const smokediv = {c /* smoke test for division */ run(c, std.mk(`Div (\ std.mk(`Val "1234_5678_1234_6789_6666_7777_8888"), \ std.mk(`Val "1234_5678_1234_6789_6666_7777"))), \ "10000") run(c, std.mk(`Div (\ std.mk(`Val "0xffff_1234_1234_1234_1234"), \ std.mk(`Val "0xf010_1234_2314"))), \ "4580035496") run(c, std.mk(`Div (\ std.mk(`Val "5192296858534810493479828944327220"), \ std.mk(`Val "75557863709417659441940"))), \ "68719476751") run(c, std.mk(`Div (\ std.mk(`Val "75557863709417659441940"), \ std.mk(`Val "5192296858534810493479828944327220"))), \ "0") } const smokemod = {c /* smoke test for mod */ run(c, std.mk(`Mod (\ std.mk(`Val "5192296858534810493479828944327220"), \ std.mk(`Val "75557863709417659441940"))),\ "257025710597479990280") run(c, std.mk(`Modpow (\ std.mk(`Val "1"), \ std.mk(`Val "3"), \ std.mk(`Val "2"))), \ "1") run(c, std.mk(`Modpow (\ std.mk(`Val "5192296858534810493479828944327220"), \ std.mk(`Val "75557863709417659441940"), \ std.mk(`Val "755578"))), \ "49054") run(c, std.mk(`Modpow (\ std.mk(`Val "2393"), \ std.mk(`Val "2"), \ std.mk(`Val "6737"))), \ "6736") run(c, std.mk(`Modpow (\ std.mk(`Val "6193257528475266832463188301662235"), \ std.mk(`Val "6157075615645799356061575607567581"), \ std.mk(`Val "12314151231291598712123151215135163"))), \ "1540381241336817586803754632242117") run(c, std.mk(`Modpow (\ std.mk(`Val "7220"), \ 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[:] var buf : byte[4096] var v, n v = eval(e) n = std.bigbfmt(buf[:], v, 0) testr.check(c, std.eq(buf[:n], res), "{} != {}", 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") ;; } const somebigdivmod = {c var inputs : (byte[:], byte[:], byte[:], byte[:])[:] = [ /* ( a, b, a/b, a%b), */ ("6185103187", "3519152458", "1", "2665950729"), ("6980766832", "3087864937", "2", "805036958"), ("4991855479", "6447381549", "0", "4991855479"), ("6119892968", "8374603717", "0", "6119892968"), ("7442542736", "5989044918", "1", "1453497818"), ("4580939187", "4661174670", "0", "4580939187"), ("4935237814", "3140079933", "1", "1795157881"), ("1010425087", "446887574", "2", "116649939"), ("1892124804", "4011235814", "0", "1892124804"), ("2457899196", "1885658848", "1", "572240348"), ("262030672", "1329267171", "0", "262030672"), ("8430016289", "6215302855", "1", "2214713434"), ("3347587073", "3855445301", "0", "3347587073"), ("8014059310", "4622364950", "1", "3391694360"), ("2934470708", "6439081239", "0", "2934470708"), ("420917856", "5020252044", "0", "420917856"), ("3862040257", "4601227994", "0", "3862040257"), ("4439858911", "4387180962", "1", "52677949"), ("165706876", "7452574618", "0", "165706876"), ("268686047", "3047271875", "0", "268686047"), ("83484791", "4899367309", "0", "83484791"), ("1242378916", "4909326080", "0", "1242378916"), ("980437482", "2305509838", "0", "980437482"), ("118982655", "5051748984", "0", "118982655"), ("8521162809", "2888108066", "2", "2744946677"), ("4600797553", "7579789288", "0", "4600797553"), ("5533774720", "3320264831", "1", "2213509889"), ][:] for (aS, bS, qS, rS) : inputs var a = try(std.bigparse(aS)) var b = try(std.bigparse(bS)) var q_exp = try(std.bigparse(qS)) var r_exp = try(std.bigparse(rS)) var q_act, r_act (q_act, r_act) = std.bigdivmod(a, b) testr.check(c, std.bigeq(q_exp, q_act), "expected {} / {} to be {}, was {}", a, b, q_exp, q_act) testr.check(c, std.bigeq(r_exp, r_act), "expected {} % {} to be {}, was {}", a, b, r_exp, r_act) ;; }