// prime numbers
package main
import (
"fmt"
)
// list of primes less than n:
// sieve of eratosthenes
func primes(n int) (ps []int) {
sieve := make([]bool, n)
for i := 2; i < n; i++ {
if !(sieve[i]) {
ps = append(ps, i)
for j := i * i; j < n; j += i {
sieve[j] = true
}
}
}
return ps
}
// true if n is prime, else false:
// trial division via 2,3,5-wheel
func isPrime(n int) (bool) {
wheel := [11]int{1,2,2,4,2,4,2,4,6,2,6}
w := 0
f := 2
for f*f <= n {
if n % f == 0 { return false }
f += wheel[w]
w += 1
if w == 11 { w = 3 }
}
return true
}
// greatest common divisor of x and y:
// via euclid's algorithm
func gcd(x int, y int) (int) {
for y != 0 {
x, y = y, x % y
}
return x
}
// absolute value of x
if x < 0 {
return -1 * x
}
return x
}
// list of prime factors of n:
// trial division via 2,3,5-wheel
// to 1000 followed by pollard rho
func factors(n int) (fs []int) {
wheel := [11]int{1,2,2,4,2,4,2,4,6,2,6}
w := 0 // wheel pointer
f := 2 // current trial factor
for f*f <= n && f < 1000 {
for n % f == 0 {
fs = append(fs, f)
n /= f
}
f += wheel[w]; w += 1
if w == 11 { w = 3 }
}
if n == 1 { return fs }
h := 1 // hare
t := 1 // turtle
g := 1 // greatest common divisor
c := 1 // random number parameter
for !(isPrime(n)) {
for g == 1 {
h = (h*h+c) % n // the hare runs
h = (h*h+c) % n // twice as fast
t = (t*t+c) % n // as the tortoise
}
if isPrime(g) {
for n % g == 0 {
fs = append(fs, g)
n /= g
}
}
h, t, g, c = 1, 1, 1, c+1
}
fs = append(fs, n)
return fs
}
func main() {
fmt.Println(primes(100))
fmt.Println(isPrime(997))
fmt.Println(isPrime(13290059))
fmt.Println(factors(13290059))
}
Ly8gcHJpbWUgbnVtYmVycwoKcGFja2FnZSBtYWluCgppbXBvcnQgKAogICAgImZtdCIKKQoKLy8gbGlzdCBvZiBwcmltZXMgbGVzcyB0aGFuIG46Ci8vIHNpZXZlIG9mIGVyYXRvc3RoZW5lcwpmdW5jIHByaW1lcyhuIGludCkgKHBzIFtdaW50KSB7CiAgICBzaWV2ZSA6PSBtYWtlKFtdYm9vbCwgbikKICAgIGZvciBpIDo9IDI7IGkgPCBuOyBpKysgewogICAgICAgIGlmICEoc2lldmVbaV0pIHsKICAgICAgICAgICAgcHMgPSBhcHBlbmQocHMsIGkpCiAgICAgICAgICAgIGZvciAgaiA6PSBpICogaTsgaiA8IG47IGogKz0gaSB7CiAgICAgICAgICAgICAgICBzaWV2ZVtqXSA9IHRydWUKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBwcwp9CgovLyB0cnVlIGlmIG4gaXMgcHJpbWUsIGVsc2UgZmFsc2U6Ci8vIHRyaWFsIGRpdmlzaW9uIHZpYSAyLDMsNS13aGVlbApmdW5jIGlzUHJpbWUobiBpbnQpIChib29sKSB7Cgl3aGVlbCA6PSBbMTFdaW50ezEsMiwyLDQsMiw0LDIsNCw2LDIsNn0KCXcgOj0gMAoJZiA6PSAyCglmb3IgZipmIDw9IG4gewoJCWlmIG4gJSBmID09IDAgeyByZXR1cm4gZmFsc2UgfQoJCWYgKz0gd2hlZWxbd10KCQl3ICs9IDEKCQlpZiB3ID09IDExIHsgdyA9IDMgfQoJfQoJcmV0dXJuIHRydWUKfQoKLy8gZ3JlYXRlc3QgY29tbW9uIGRpdmlzb3Igb2YgeCBhbmQgeToKLy8gdmlhIGV1Y2xpZCdzIGFsZ29yaXRobQpmdW5jIGdjZCh4IGludCwgeSBpbnQpIChpbnQpIHsKCWZvciB5ICE9IDAgewoJCXgsIHkgPSB5LCB4ICUgeQoJfQoJcmV0dXJuIHgKfQoKLy8gYWJzb2x1dGUgdmFsdWUgb2YgeApmdW5jIGFicyh4IGludCkgKGludCkgewoJaWYgeCA8IDAgewoJCXJldHVybiAtMSAqIHgKCX0KCXJldHVybiB4Cn0KCi8vIGxpc3Qgb2YgcHJpbWUgZmFjdG9ycyBvZiBuOgovLyB0cmlhbCBkaXZpc2lvbiB2aWEgMiwzLDUtd2hlZWwKLy8gdG8gMTAwMCBmb2xsb3dlZCBieSBwb2xsYXJkIHJobwpmdW5jIGZhY3RvcnMobiBpbnQpIChmcyBbXWludCkgewogICAgd2hlZWwgOj0gWzExXWludHsxLDIsMiw0LDIsNCwyLDQsNiwyLDZ9CiAgICB3IDo9IDAgLy8gd2hlZWwgcG9pbnRlcgogICAgZiA6PSAyIC8vIGN1cnJlbnQgdHJpYWwgZmFjdG9yCiAgICBmb3IgZipmIDw9IG4gJiYgZiA8IDEwMDAgewogICAgICAgIGZvciBuICUgZiA9PSAwIHsKICAgICAgICAgICAgZnMgPSBhcHBlbmQoZnMsIGYpCiAgICAgICAgICAgIG4gLz0gZgogICAgICAgIH0KICAgICAgICBmICs9IHdoZWVsW3ddOyB3ICs9IDEKICAgICAgICBpZiB3ID09IDExIHsgdyA9IDMgfQogICAgfQogICAgaWYgbiA9PSAxIHsgcmV0dXJuIGZzIH0KICAgIGggOj0gMSAvLyBoYXJlCiAgICB0IDo9IDEgLy8gdHVydGxlCiAgICBnIDo9IDEgLy8gZ3JlYXRlc3QgY29tbW9uIGRpdmlzb3IKICAgIGMgOj0gMSAvLyByYW5kb20gbnVtYmVyIHBhcmFtZXRlcgogICAgZm9yICEoaXNQcmltZShuKSkgewogICAgICAgIGZvciBnID09IDEgewogICAgICAgICAgICBoID0gKGgqaCtjKSAlIG4gLy8gdGhlIGhhcmUgcnVucwogICAgICAgICAgICBoID0gKGgqaCtjKSAlIG4gLy8gdHdpY2UgYXMgZmFzdAogICAgICAgICAgICB0ID0gKHQqdCtjKSAlIG4gLy8gYXMgdGhlIHRvcnRvaXNlCiAgICAgICAgICAgIGcgPSBnY2QoYWJzKHQtaCksIG4pCiAgICAgICAgfQogICAgICAgIGlmIGlzUHJpbWUoZykgewogICAgICAgICAgICBmb3IgbiAlIGcgPT0gMCB7CiAgICAgICAgICAgICAgICBmcyA9IGFwcGVuZChmcywgZykKICAgICAgICAgICAgICAgIG4gLz0gZwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGgsIHQsIGcsIGMgPSAxLCAxLCAxLCBjKzEKICAgIH0KICAgIGZzID0gYXBwZW5kKGZzLCBuKQogICAgcmV0dXJuIGZzCn0KCmZ1bmMgbWFpbigpIHsKICAgIGZtdC5QcmludGxuKHByaW1lcygxMDApKQogICAgZm10LlByaW50bG4oaXNQcmltZSg5OTcpKQogICAgZm10LlByaW50bG4oaXNQcmltZSgxMzI5MDA1OSkpCiAgICBmbXQuUHJpbnRsbihmYWN0b3JzKDEzMjkwMDU5KSkKfQ==