shithub: mc

ref: b65a821ba2d8c753e974b02e541229dfd6754a6a
dir: /test/stdbigint.myr/

View raw version
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[:]
	`Res cmd#
;;

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.put("%s\n", buf[:n])

	/* make sure we format '0' correctly */
	run(std.mk(`Res (std.mk(`Val "0"))))
	/* smoke test for division */
	run(std.mk(`Res \
			std.mk(`Div (\
				std.mk(`Val "1234_5678_1234_6789_6666_7777_8888"), \
				std.mk(`Val "1234_5678_1234_6789_6666_7777")))))
	run(std.mk(`Res \
		std.mk(`Div (\
			std.mk(`Val "0xffff_1234_1234_1234_1234"), \
			std.mk(`Val "0xf010_1234_2314")))))
	run(std.mk(`Res \
		std.mk(`Div (\
			std.mk(`Val "5192296858534810493479828944327220"), \
			std.mk(`Val "75557863709417659441940")))))
	run(std.mk(`Res \
		std.mk(`Div (\
			std.mk(`Val "75557863709417659441940"), \
			std.mk(`Val "5192296858534810493479828944327220")))))

	/* smoke test for mod */
	run(std.mk(`Res \
		std.mk(`Mod (\
			std.mk(`Val "5192296858534810493479828944327220"), \
			std.mk(`Val "75557863709417659441940")))))

	run(std.mk(`Res \
		std.mk(`Modpow (\
			std.mk(`Val "1"), \
			std.mk(`Val "3"), \
			std.mk(`Val "2")))))

	run(std.mk(`Res \
		std.mk(`Modpow (\
			std.mk(`Val "5192296858534810493479828944327220"), \
			std.mk(`Val "75557863709417659441940"), \
			std.mk(`Val "755578")))))
	run(std.mk(`Res \
		std.mk(`Modpow (\
			std.mk(`Val "7220"), \
			std.mk(`Val "755578"), \
			std.mk(`Val "75557863709417659441940")))))

}

const run = {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)
		std.put("%s", buf[:n])
		-> a
	| `Res r:
		a = run(r)
		n = std.bigbfmt(buf[:], a, 0)
		std.put(" == %s\n", buf[:n])
		-> a
	| `Modpow (x, y, z):
		std.put("("); 
		a = run(x)
		std.put(" ^ ")
		b = run(y)
		std.put(") %% ")
		c = run(z)
		-> std.bigmodpow(a, b, c)
	;;
}

const binop = {name, op, x, y
	var a, b

	a = run(x)
	std.put(" %s ", name)
	b = run(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")
	;;
}