package main
import (
"fmt"
"math/big"
"sort"
)
// sort []*big.Int into increasing order, using sort package
type BigIntSlice []*big.Int
func (s BigIntSlice) Len() int { return len(s) }
func (s BigIntSlice) Less(i, j int) bool { return s[i].Cmp(s[j]) < 0 }
func (s BigIntSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s BigIntSlice) Sort() { sort.Sort(s) }
var (
zero = big.NewInt(0);
one = big.NewInt(1);
two = big.NewInt(2);
four = big.NewInt(4);
six = big.NewInt(6);
wheel = [11]*big.Int{one,two,two,four,two,four,two,four,six,two,six}
)
func factors(n *big.Int) (fs []*big.Int) {
mod := new(big.Int) // modulus
div := new
(big.
Int) // dividend limit := big.NewInt(1000) // switch to rho
z := big.NewInt(0); // temporary storage
w := 0 // wheel index
f := big.NewInt(2); // trial divisor
z.Mul(f, f)
for z.Cmp(n) <= 0 && f.Cmp(limit) <= 0 {
for mod.Cmp(zero) == 0 {
fs = append(fs, new(big.Int).Set(f))
}
f.Add(f, wheel[w]); z.Mul(f, f)
w += 1; if w == 11 { w = 3 }
}
if n.Cmp(one) == 0 { return fs }
h := big.NewInt(1) // hare
t := big.NewInt(1) // tortoise
g := big.NewInt(1) // greatest common divisor
c := big.NewInt(1) // random number parameter
for !(n.ProbablyPrime(20)) {
for g.Cmp(one) == 0 {
z.Mul(h, h); z.Add(z, c); z.Mod(z, n); h.Set(z)
z.Mul(h, h); z.Add(z, c); z.Mod(z, n); h.Set(z)
z.Mul(t, t); z.Add(z, c); z.Mod(z, n); t.Set(z)
z.Sub(t, h); z.Abs(z)
g.GCD(nil, nil, z, n)
}
if g.ProbablyPrime(20) {
for mod.Cmp(zero) == 0 {
fs = append(fs, new(big.Int).Set(g))
}
h.Set(one)
t.Set(one)
g.Set(one)
c.Add(c, one)
}
}
fs = append(fs, new(big.Int).Set(n))
sort.Sort(BigIntSlice(fs))
return fs
}
func main() {
fmt.Println(factors(big.NewInt(13290059)))
x := big.NewInt(583910384809)
y := big.NewInt(291648291013)
x.Mul(x,y)
fmt.Println(x)
fmt.Println(factors(x))
}
cGFja2FnZSBtYWluCgppbXBvcnQgKAogICAgImZtdCIKICAgICJtYXRoL2JpZyIKICAgICJzb3J0IgopCgovLyBzb3J0IFtdKmJpZy5JbnQgaW50byBpbmNyZWFzaW5nIG9yZGVyLCB1c2luZyBzb3J0IHBhY2thZ2UKdHlwZSBCaWdJbnRTbGljZSBbXSpiaWcuSW50CmZ1bmMgKHMgQmlnSW50U2xpY2UpIExlbigpIGludCAgICAgICAgICAgeyByZXR1cm4gbGVuKHMpIH0KZnVuYyAocyBCaWdJbnRTbGljZSkgTGVzcyhpLCBqIGludCkgYm9vbCB7IHJldHVybiBzW2ldLkNtcChzW2pdKSA8IDAgfQpmdW5jIChzIEJpZ0ludFNsaWNlKSBTd2FwKGksIGogaW50KSAgICAgIHsgc1tpXSwgc1tqXSA9IHNbal0sIHNbaV0gfQpmdW5jIChzIEJpZ0ludFNsaWNlKSBTb3J0KCkgICAgICAgICAgICAgIHsgc29ydC5Tb3J0KHMpIH0KCnZhciAoCiAgICB6ZXJvICA9IGJpZy5OZXdJbnQoMCk7CiAgICBvbmUgICA9IGJpZy5OZXdJbnQoMSk7CiAgICB0d28gICA9IGJpZy5OZXdJbnQoMik7CiAgICBmb3VyICA9IGJpZy5OZXdJbnQoNCk7CiAgICBzaXggICA9IGJpZy5OZXdJbnQoNik7CiAgICB3aGVlbCA9IFsxMV0qYmlnLkludHtvbmUsdHdvLHR3byxmb3VyLHR3byxmb3VyLHR3byxmb3VyLHNpeCx0d28sc2l4fQopCgpmdW5jIGZhY3RvcnMobiAqYmlnLkludCkgKGZzIFtdKmJpZy5JbnQpIHsKICAgIG1vZCAgIDo9IG5ldyhiaWcuSW50KSAvLyBtb2R1bHVzCiAgICBkaXYgICA6PSBuZXcoYmlnLkludCkgLy8gZGl2aWRlbmQKICAgIGxpbWl0IDo9IGJpZy5OZXdJbnQoMTAwMCkgLy8gc3dpdGNoIHRvIHJobwogICAgeiAgICAgOj0gYmlnLk5ld0ludCgwKTsgLy8gdGVtcG9yYXJ5IHN0b3JhZ2UKICAgIHcgICAgIDo9IDAgLy8gd2hlZWwgaW5kZXgKICAgIGYgICAgIDo9IGJpZy5OZXdJbnQoMik7IC8vIHRyaWFsIGRpdmlzb3IKICAgIHouTXVsKGYsIGYpCiAgICBmb3Igei5DbXAobikgPD0gMCAmJiBmLkNtcChsaW1pdCkgPD0gMCB7CiAgICAgICAgZGl2LkRpdk1vZChuLCBmLCBtb2QpCiAgICAgICAgZm9yIG1vZC5DbXAoemVybykgPT0gMCB7CiAgICAgICAgICAgIGZzID0gYXBwZW5kKGZzLCBuZXcoYmlnLkludCkuU2V0KGYpKQogICAgICAgICAgICBuLlNldChkaXYpCiAgICAgICAgICAgIGRpdi5EaXZNb2QobiwgZiwgbW9kKQogICAgICAgIH0KICAgICAgICBmLkFkZChmLCB3aGVlbFt3XSk7IHouTXVsKGYsIGYpCiAgICAgICAgdyArPSAxOyBpZiB3ID09IDExIHsgdyA9IDMgfQogICAgfQogICAgaWYgbi5DbXAob25lKSA9PSAwIHsgcmV0dXJuIGZzIH0KICAgIGggOj0gYmlnLk5ld0ludCgxKSAvLyBoYXJlCiAgICB0IDo9IGJpZy5OZXdJbnQoMSkgLy8gdG9ydG9pc2UKICAgIGcgOj0gYmlnLk5ld0ludCgxKSAvLyBncmVhdGVzdCBjb21tb24gZGl2aXNvcgogICAgYyA6PSBiaWcuTmV3SW50KDEpIC8vIHJhbmRvbSBudW1iZXIgcGFyYW1ldGVyCiAgICBmb3IgIShuLlByb2JhYmx5UHJpbWUoMjApKSB7CiAgICAJZm9yIGcuQ21wKG9uZSkgPT0gMCB7CiAgICAJCXouTXVsKGgsIGgpOyB6LkFkZCh6LCBjKTsgei5Nb2Qoeiwgbik7IGguU2V0KHopCiAgICAJCXouTXVsKGgsIGgpOyB6LkFkZCh6LCBjKTsgei5Nb2Qoeiwgbik7IGguU2V0KHopCiAgICAJCXouTXVsKHQsIHQpOyB6LkFkZCh6LCBjKTsgei5Nb2Qoeiwgbik7IHQuU2V0KHopCiAgICAJCXouU3ViKHQsIGgpOyB6LkFicyh6KQogICAgCQlnLkdDRChuaWwsIG5pbCwgeiwgbikKICAgIAl9CiAgICAJaWYgZy5Qcm9iYWJseVByaW1lKDIwKSB7CiAgICAgICAgICAgIGRpdi5EaXZNb2QobiwgZywgbW9kKQogICAgICAgICAgICBmb3IgbW9kLkNtcCh6ZXJvKSA9PSAwIHsKICAgICAgICAgICAgICAgIGZzID0gYXBwZW5kKGZzLCBuZXcoYmlnLkludCkuU2V0KGcpKQogICAgICAgICAgICAgICAgbi5TZXQoZGl2KQogICAgICAgICAgICAgICAgZGl2LkRpdk1vZChuLCBnLCBtb2QpCiAgICAgICAgICAgIH0KICAgICAgICBoLlNldChvbmUpCiAgICAgICAgdC5TZXQob25lKQogICAgICAgIGcuU2V0KG9uZSkKICAgICAgICBjLkFkZChjLCBvbmUpCiAgICAJfQogICAgfQogICAgZnMgPSBhcHBlbmQoZnMsIG5ldyhiaWcuSW50KS5TZXQobikpCiAgICBzb3J0LlNvcnQoQmlnSW50U2xpY2UoZnMpKQogICAgcmV0dXJuIGZzCn0KCmZ1bmMgbWFpbigpIHsKCWZtdC5QcmludGxuKGZhY3RvcnMoYmlnLk5ld0ludCgxMzI5MDA1OSkpKQoJeCA6PSBiaWcuTmV3SW50KDU4MzkxMDM4NDgwOSkKCXkgOj0gYmlnLk5ld0ludCgyOTE2NDgyOTEwMTMpCgl4Lk11bCh4LHkpCglmbXQuUHJpbnRsbih4KQoJZm10LlByaW50bG4oZmFjdG9ycyh4KSkKfQ==