Miller–Rabin primality test: Difference between revisions

Content added Content deleted
m (Removed reference to Erlang because the Erlang version is too different, whereas the Prolog version was the model used.)
(Mercury: minor format edit. Oz: added the language.)
Line 1,879: Line 1,879:


=={{header|Mercury}}==
=={{header|Mercury}}==


<lang Mercury>
<lang Mercury>
These were compiled using Mercury 14.01.1 and are adapted from
These were compiled using Mercury 14.01.1 and are adapted from
Line 2,105: Line 2,103:
</lang>
</lang>


=={{header|Oz}}==
<lang Oz>
The following is adapted from the Prolog and Mercury versions.
%--------------------------------------------------------------------------%
% module: Primality
% file: Primality.oz
% version: 17 DEC 2014 @ 6:50AM
%--------------------------------------------------------------------------%


declare
%--------------------------------------------------------------------------%

fun {IsPrime N} % main interface of module
if N < 2 then false
elseif N < 4 then true
elseif (N mod 2) == 0 then false
elseif N < 341330071728321 then {IsMRprime N {DetWit N}}
else {IsMRprime N {ProbWit N 20}}
end
end
%--------------------------------------------------------------------------%

fun {DetWit N} % deterministic witnesses
if N < 1373653 then [2 3]
elseif N < 9080191 then [31 73]
elseif N < 25326001 then [2 3 5]
elseif N < 3215031751 then [2 3 5 7]
elseif N < 4759123141 then [2 7 61]
elseif N < 1122004669633 then [2 13 23 1662803]
elseif N < 2152302898747 then [2 3 5 7 11]
elseif N < 3474749660383 then [2 3 5 7 11 13]
elseif N < 341550071728321 then [2 3 5 7 11 13 17]
else nil
end
end
%--------------------------------------------------------------------------%

fun {ProbWit N K} % probabilistic witnesses
local A B C in
A = 6364136223846793005
B = 1442695040888963407
C = N - 2
{RWloop N A B C K nil}
end
end

fun {RWloop N A B C K L}
local N1 in
N1 = (((N * A) + B) mod C) + 1
if K == 0 then L
else {RWloop N1 A B C (K - 1) N1|L}
end
end
end
%--------------------------------------------------------------------------%

fun {IsMRprime N As} % the Miller-Rabin algorithm
local D S T Ts in
{FindDS N} = D|S
{OuterLoop N As D S}
end
end

fun {OuterLoop N As D S}
local A At Base C in
As = A|At
Base = {Powm A D N}
C = {InnerLoop Base N 0 S}
if {Not C} then false
elseif {And C (At == nil)} then true
else {OuterLoop N At D S}
end
end
end
fun {InnerLoop Base N Loop S}
local NextBase NextLoop in
NextBase = (Base * Base) mod N
NextLoop = Loop + 1
if {And (Loop == 0) (Base == 1)} then true
elseif Base == (N - 1) then true
elseif NextLoop == S then false
else {InnerLoop NextBase N NextLoop S}
end
end
end
%--------------------------------------------------------------------------%

fun {FindDS N}
{FindDS1 (N - 1) 0}
end

fun {FindDS1 D S}
if (D mod 2 == 0) then {FindDS1 (D div 2) (S + 1)}
else D|S
end
end
%--------------------------------------------------------------------------%
fun {Powm A D N} % returns (A ^ D) mod N
if D == 0 then 1
elseif (D mod 2) == 0 then {Pow {Powm A (D div 2) N} 2} mod N
else (A * {Powm A (D - 1) N}) mod N
end
end
%--------------------------------------------------------------------------%
% end_module Primality

</lang>