Miller–Rabin primality test: Difference between revisions

Refactored the code in a way that is more idiomatic to Forth.
(Refactored the code in a way that is more idiomatic to Forth.)
Line 1,510:
=={{header|Forth}}==
Forth only supports native ints (e.g. 64 bits on most modern machines), so this version uses a set of known deterministic bases that is known to be correct for 64 bit integers (and possibly greater). Prior to the Miller Rabin check, the "prime?" word checks for divisibility by some small primes.
<lang Forth>
\ small divisor check: true => possibly prime; false => definitely not prime.
31 constant π-128
create maybe-prime?
2 c, 3 c, 5 c, 7 c, 11 c, 13 c, 17 c, 19 c, 23 c, 29 c,
31 c, 37 c, 41 c, 43 c, 47 c, 53 c, 59 c, 61 c, 67 c, 71 c,
73 c, 79 c, 83 c, 89 c, 97 c, 101 c, 103 c, 107 c, 109 c, 113 c,
127 c,
does>
true -rot
π-128 bounds do
i c@ dup * over > if leave then
dup i c@ mod 0= if 2drop false unloop exit then
loop drop ;
 
<lang Forth>
\ modular multiplication and exponentiation
\
Line 1,544 ⟶ 1,530:
then
repeat nip rdrop ;
 
\ small divisor check: true => possibly prime; false => definitely not prime.
31 constant π-128
create maybe-prime?
2 c, 3 c, 5 c, 7 c, 11 c, 13 c, 17 c, 19 c, 23 c, 29 c,
31 c, 37 c, 41 c, 43 c, 47 c, 53 c, 59 c, 61 c, 67 c, 71 c,
73 c, 79 c, 83 c, 89 c, 97 c, 101 c, 103 c, 107 c, 109 c, 113 c,
127 c,
does>
true -rot
π-128 bounds do
i c@ dup * over > if leave then
dup i c@ mod 0= if 2drop false unloop exit then
loop drop ;
 
\ actual Miller-Rabin test
Line 1,554 ⟶ 1,555:
 
4.759.123.141 drop constant mr-det-3 \ Deterministic threshold; 3 bases
 
: fermat-square-test ( n m s -- ? ) \ perform n = n^2 (mod m), s-1 times
1- 0 ?do
if2dup - -1 =
if thenleave
then x>r dup nr@ mod* to xr>
cell +loop
true- -1 = ;
 
: strong-fermat-pseudoprime? ( n a -- ? )
over >r \ keep the modulus on the return stack
rot dup>r 1- factor-2s 0r> locals|\ x d-- s nd |a
swap r@ mod^ \ s d a -- s, a^d (mod n)
dup 1 = \ a^d == 1 (mod n) => Fermat pseudoprime
if 2drop rdrop true
else r> rot fermat-square-test
then ;
 
create small-prime-bases 2 , 7 , 61 , \ deterministic up to mr-det-3
Line 1,565 ⟶ 1,583:
 
: miller-rabin-primality-test ( n -- f )
dup miler-rabin-bases cells bounds do
dup i @ strong-fermat-pseudoprime? invert
rot dup 1- factor-2s 0 locals| x d s n |
cells bounds DO if drop false unloop exit then
cell +loop drop true ;
i @ d n mod^ dup to x 1 <>
if -1
begin 1+ dup s < x n 1- <> and while
x dup n mod* to x
repeat drop
x n 1- <>
if false unloop exit
then
then
cell +loop
true ;
 
: prime? ( n -- f )
357

edits