diff --git a/ints/big.go b/ints/big.go new file mode 100644 index 0000000..ef361e7 --- /dev/null +++ b/ints/big.go @@ -0,0 +1,13 @@ +package ints + +import "math/big" + +func CopyBig(i *big.Int) *big.Int { return (&big.Int{}).Set(i) } + +func DivBig(x, y *big.Int) *big.Int { return x.Div(x, y) } + +func MulBig(x, y *big.Int) *big.Int { return x.Mul(x, y) } + +func PowTenBig(p int) *big.Int { return Big.PowTen(p) } + +func RepunitBig(k int) *big.Int { return Big.Repunit(k) } diff --git a/ints/big_test.go b/ints/big_test.go new file mode 100644 index 0000000..bff5779 --- /dev/null +++ b/ints/big_test.go @@ -0,0 +1,17 @@ +package ints + +import ( + "testing" +) + +func BenchmarkIntsSmallRepunit(b *testing.B) { + for i := 0; i < b.N; i++ { + Big.Repunit(1234) + } +} + +func BenchmarkIntsLargeRepunit(b *testing.B) { + for i := 0; i < b.N; i++ { + Big.Repunit(1234567) + } +} diff --git a/ints/bignumbers.go b/ints/bignumbers.go new file mode 100644 index 0000000..c764961 --- /dev/null +++ b/ints/bignumbers.go @@ -0,0 +1,98 @@ +package ints + +import "math/big" + +type BigNumbers struct { + Zero *big.Int + One *big.Int + Two *big.Int + Nine *big.Int + Ten *big.Int + Thousand *big.Int + Million *big.Int + Ten10 *big.Int + Ten30 *big.Int + Ten100 *big.Int + Ten300 *big.Int + Ten1000 *big.Int + Ten3000 *big.Int + Ten10000 *big.Int + Ten30000 *big.Int + Ten100000 *big.Int + Ten300000 *big.Int + Ten1000000 *big.Int +} + +var Big *BigNumbers = NewBigNumbers() + +func NewBigNumbers() *BigNumbers { + ten := big.NewInt(10) + thousand := big.NewInt(1000) + million := big.NewInt(1000000) + ten10 := MulBig(MulBig(MulBig(big.NewInt(1), million), thousand), ten) + ten30 := MulBig(MulBig(MulBig(big.NewInt(1), ten10), ten10), ten10) + ten100 := MulBig(MulBig(MulBig(MulBig(big.NewInt(1), ten30), ten30), ten30), ten10) + ten300 := MulBig(MulBig(MulBig(big.NewInt(1), ten100), ten100), ten100) + ten1000 := MulBig(MulBig(MulBig(MulBig(big.NewInt(1), ten300), ten300), ten300), ten100) + ten3000 := MulBig(MulBig(MulBig(big.NewInt(1), ten1000), ten1000), ten1000) + ten10000 := MulBig(MulBig(MulBig(MulBig(big.NewInt(1), ten3000), ten3000), ten3000), ten1000) + ten30000 := MulBig(MulBig(MulBig(big.NewInt(1), ten10000), ten10000), ten10000) + ten100000 := MulBig(MulBig(MulBig(MulBig(big.NewInt(1), ten30000), ten30000), ten30000), ten10000) + ten300000 := MulBig(MulBig(MulBig(big.NewInt(1), ten100000), ten100000), ten100000) + ten1000000 := MulBig(MulBig(MulBig(MulBig(big.NewInt(1), ten300000), ten300000), ten300000), ten100000) + return &BigNumbers{ + Zero: big.NewInt(0), + One: big.NewInt(1), + Two: big.NewInt(2), + Nine: big.NewInt(9), + Ten: ten, + Thousand: thousand, + Million: million, + Ten10: ten10, + Ten30: ten30, + Ten100: ten100, + Ten300: ten300, + Ten1000: ten1000, + Ten3000: ten3000, + Ten10000: ten10000, + Ten30000: ten30000, + Ten100000: ten100000, + Ten300000: ten300000, + Ten1000000: ten1000000, + } +} + +func (n *BigNumbers) Repunit(k int) *big.Int { + rep := n.PowTen(k) + return rep.Sub(rep, n.One).Div(rep, n.Nine) +} + +func (n *BigNumbers) PowTen(p int) *big.Int { + result := big.NewInt(1) + pow := func(n int, one, three *big.Int) { + for n >= 3 { + result.Mul(result, three) + n -= 3 + } + for n >= 1 { + result.Mul(result, one) + n-- + } + } + mul := func(n int, one, three *big.Int) int { + mod := n % 10 + pow(mod, one, three) + return n / 10 + } + p = mul(p, n.Ten, n.Thousand) + p = mul(p, n.Ten10, n.Ten30) + p = mul(p, n.Ten100, n.Ten300) + p = mul(p, n.Ten1000, n.Ten3000) + p = mul(p, n.Ten10000, n.Ten30000) + p = mul(p, n.Ten100000, n.Ten300000) + for p > 0 { + result.Mul(result, n.Ten1000000) + p-- + } + return result +}