Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,73 @@
|
|||
## Nim currently doesn't have a BigInt standard library
|
||||
## so we translate the version from Go which uses a
|
||||
## deterministic approach, which is correct for all
|
||||
## possible values in uint32.
|
||||
|
||||
proc isPrime*(n: uint32): bool =
|
||||
# bases of 2, 7, 61 are sufficient to cover 2^32
|
||||
case n
|
||||
of 0, 1: return false
|
||||
of 2, 7, 61: return true
|
||||
else: discard
|
||||
|
||||
var
|
||||
nm1 = n-1
|
||||
d = nm1.int
|
||||
s = 0
|
||||
n = n.uint64
|
||||
|
||||
while d mod 2 == 0:
|
||||
d = d shr 1
|
||||
s += 1
|
||||
|
||||
for a in [2, 7, 61]:
|
||||
var
|
||||
x = 1.uint64
|
||||
p = a.uint64
|
||||
dr = d
|
||||
|
||||
while dr > 0:
|
||||
if dr mod 2 == 1:
|
||||
x = x * p mod n
|
||||
p = p * p mod n
|
||||
dr = dr shr 1
|
||||
|
||||
if x == 1 or x.uint32 == nm1:
|
||||
continue
|
||||
|
||||
var r = 1
|
||||
while true:
|
||||
if r >= s:
|
||||
return false
|
||||
x = x * x mod n
|
||||
if x == 1:
|
||||
return false
|
||||
if x.uint32 == nm1:
|
||||
break
|
||||
r += 1
|
||||
|
||||
return true
|
||||
|
||||
proc isPrime*(n: int32): bool =
|
||||
## Overload for int32
|
||||
n >= 0 and n.uint32.isPrime
|
||||
|
||||
when isMainModule:
|
||||
const primeNumber1000 = 7919 # source: https://en.wikipedia.org/wiki/List_of_prime_numbers
|
||||
var
|
||||
i = 0u32
|
||||
numberPrimes = 0
|
||||
while true:
|
||||
if isPrime(i):
|
||||
if numberPrimes == 999:
|
||||
break
|
||||
numberPrimes += 1
|
||||
i += 1
|
||||
|
||||
assert i == primeNumber1000
|
||||
assert isPrime(2u32)
|
||||
assert isPrime(31u32)
|
||||
assert isPrime(37u32)
|
||||
assert isPrime(1123u32)
|
||||
assert isPrime(492366587u32)
|
||||
assert isPrime(1645333507u32)
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# Compile as: $ nim c -d:release mrtest.nim
|
||||
# Run using: $ ./mrtest
|
||||
|
||||
import math # for gcd and mod
|
||||
import bitops # for countTrailingZeroBits
|
||||
import strutils, typetraits # for number input
|
||||
import times, os # for timing code execution
|
||||
|
||||
proc addmod*[T: SomeInteger](a, b, modulus: T): T =
|
||||
## Modular addition
|
||||
let a_m = if a < modulus: a else: a mod modulus
|
||||
if b == 0.T: return a_m
|
||||
let b_m = if b < modulus: b else: b mod modulus
|
||||
|
||||
# Avoid doing a + b that could overflow here
|
||||
let b_from_m = modulus - b_m
|
||||
if a_m >= b_from_m: return a_m - b_from_m
|
||||
return a_m + b_m # safe to add here; a + b < modulus
|
||||
|
||||
proc mulmod*[T: SomeInteger](a, b, modulus: T): T =
|
||||
## Modular multiplication
|
||||
var a_m = if a < modulus: a else: a mod modulus
|
||||
var b_m = if b < modulus: b else: b mod modulus
|
||||
if b_m > a_m: swap(a_m, b_m)
|
||||
while b_m > 0.T:
|
||||
if (b_m and 1) == 1: result = addmod(result, a_m, modulus)
|
||||
a_m = (a_m shl 1) - (if a_m >= (modulus - a_m): modulus else: 0)
|
||||
b_m = b_m shr 1
|
||||
|
||||
proc expmod*[T: SomeInteger](base, exponent, modulus: T): T =
|
||||
## Modular exponentiation
|
||||
result = 1 # (exp 0 = 1)
|
||||
var (e, b) = (exponent, base)
|
||||
while e > 0.T:
|
||||
if (e and 1) == 1: result = mulmod(result, b, modulus)
|
||||
e = e shr 1
|
||||
b = mulmod(b, b, modulus)
|
||||
|
||||
# Returns true if +self+ passes Miller-Rabin Test on witnesses +b+
|
||||
proc miller_rabin_test[T: SomeInteger](num: T, witnesses: seq[uint64]): bool =
|
||||
var d = num - 1
|
||||
let (neg_one_mod, n) = (d, d)
|
||||
d = d shr countTrailingZeroBits(d) # suck out factors of 2 from d
|
||||
for b in witnesses: # do M-R test with each witness base
|
||||
if b.T mod num == 0: continue # **skip base if a multiple of input**
|
||||
var s = d
|
||||
var y = expmod(b.T, d, num)
|
||||
while s != n and y != 1 and y != neg_one_mod:
|
||||
y = mulmod(y, y, num)
|
||||
s = s shl 1
|
||||
if y != neg_one_mod and (s and 1) != 1: return false
|
||||
true
|
||||
|
||||
proc selectWitnesses[T: SomeInteger](num: T): seq[uint64] =
|
||||
## Best known deterministic witnesses for given range and number of bases
|
||||
## https://miller-rabin.appspot.com/
|
||||
## https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
|
||||
if num < 341_531u:
|
||||
result = @[9345883071009581737u64]
|
||||
elif num < 1_050_535_501u:
|
||||
result = @[336781006125u64, 9639812373923155u64]
|
||||
elif num < 350_269_456_337u:
|
||||
result = @[4230279247111683200u64, 14694767155120705706u64, 16641139526367750375u64]
|
||||
elif num < 55_245_642_489_451u:
|
||||
result = @[2u64, 141889084524735u64, 1199124725622454117u64, 11096072698276303650u64]
|
||||
elif num < 7_999_252_175_582_851u:
|
||||
result = @[2u64, 4130806001517u64, 149795463772692060u64, 186635894390467037u64, 3967304179347715805u64]
|
||||
elif num < 585_226_005_592_931_977u:
|
||||
result = @[2u64, 123635709730000u64, 9233062284813009u64, 43835965440333360u64, 761179012939631437u64, 1263739024124850375u64]
|
||||
elif num.uint64 < 18_446_744_073_709_551_615u64:
|
||||
result = @[2u64, 325, 9375, 28178, 450775, 9780504, 1795265022]
|
||||
else:
|
||||
result = @[2u64, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
|
||||
|
||||
proc primemr*[T: SomeInteger](n: T): bool =
|
||||
let primes = @[2u64, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
|
||||
if n <= primes[^1].T: return (n in primes) # for n <= primes.last
|
||||
let modp47 = 614889782588491410u # => primes.product, largest < 2^64
|
||||
if gcd(n, modp47) != 1: return false # eliminates 86.2% of all integers
|
||||
let witnesses = selectWitnesses(n)
|
||||
miller_rabin_test(n, witnesses)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 1645333507u)
|
||||
var te = epochTime()
|
||||
echo primemr 1645333507u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 2147483647u)
|
||||
te = epochTime()
|
||||
echo primemr 2147483647u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 844674407370955389u)
|
||||
te = epochTime()
|
||||
echo primemr 844674407370955389u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 1844674407370954349u)
|
||||
te = epochTime()
|
||||
echo primemr 1844674407370954349u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 1844674407370954351u)
|
||||
te = epochTime()
|
||||
echo primemr 1844674407370954351u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 9223372036854775783u)
|
||||
te = epochTime()
|
||||
echo primemr 9223372036854775783u
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 9241386435364257883u64)
|
||||
te = epochTime()
|
||||
echo primemr 9241386435364257883u64
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
echo("n = ", 18446744073709551533u64, ", is largest prime < 2^64")
|
||||
te = epochTime()
|
||||
echo 18446744073709551533u64.primemr
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
||||
echo "\nprimemr?"
|
||||
let num = 5_000_000u # => 348_513 primes
|
||||
var primes: seq[uint] = @[]
|
||||
echo("find primes < ", num)
|
||||
te = epochTime()
|
||||
for n in 0u..num:
|
||||
if n.primemr: primes.add(n)
|
||||
stdout.write("\r",((float64(n) / float64(num))*100).formatFloat(ffDecimal, 1), "%")
|
||||
echo("\nnumber of primes < ",num, " are ", primes.len)
|
||||
echo (epochTime()-te).formatFloat(ffDecimal, 6)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
(* Translated from the wikipedia pseudo-code *)
|
||||
let miller_rabin n ~iter:k =
|
||||
(* return r and d where n = 2^r*d (from scheme implementation) *)
|
||||
let get_rd n =
|
||||
let rec loop r d =
|
||||
(* not even *)
|
||||
if Z.(equal (logand d one) one) then
|
||||
(r,d)
|
||||
else
|
||||
loop Z.(r + one) Z.(div d ~$2)
|
||||
in
|
||||
loop Z.zero n
|
||||
in
|
||||
let single_miller n r d =
|
||||
(* (random (n - 4)) + 2 *)
|
||||
let a = Bigint.to_zarith_bigint
|
||||
Bigint.((random ((of_zarith_bigint n) - (of_int 4))) + (of_int 2))
|
||||
in
|
||||
let x = Z.(powm a d n) in
|
||||
if Z.(equal x ~$1) || Z.(equal x (n - ~$1)) then true
|
||||
else
|
||||
let rec loop i x =
|
||||
if Z.(equal ~$i (r - ~$1)) then false
|
||||
else
|
||||
let x = Z.(powm x ~$2 n) in
|
||||
if Z.(equal x (n - ~$1)) then true
|
||||
else loop (i + 1) x
|
||||
in
|
||||
loop 0 x
|
||||
in
|
||||
let n = Z.abs n in
|
||||
if Z.(equal n one) then false
|
||||
else if Z.(equal (logand n one) zero) then false
|
||||
else if Z.(equal (n mod ~$3) zero) then false
|
||||
else
|
||||
let r, d = get_rd Z.(n - one) in
|
||||
let rec loop i bool =
|
||||
if i = k then bool
|
||||
else loop (i + 1) (bool && single_miller n r d)
|
||||
in
|
||||
loop 0 true
|
||||
Loading…
Add table
Add a link
Reference in a new issue