Multiplicative order: Difference between revisions

(26 intermediate revisions by 14 users not shown)
Line 45:
The total cost is dominated by<tt> O(k(lg p)<sup>3</sup>)</tt> ,<tt> </tt>which is<tt> O((lg p)<sup>4</sup>/(lg lg p))</tt>.
<br><br>
 
=={{header|11l}}==
{{trans|D}}
 
<syntaxhighlight lang="11l">T PExp
BigInt prime
Int exp
F (prime, exp)
.prime = prime
.exp = exp
 
F isqrt(self)
V b = self
L
V a = b
b = (self I/ a + a) I/ 2
I b >= a
R a
 
F factor(BigInt n)
[PExp] pf
V nn = n
V b = 0
L ((nn % 2) == 0)
nn I/= 2
b++
 
I b > 0
pf [+]= PExp(BigInt(2), b)
 
V s = isqrt(nn)
V d = BigInt(3)
L nn > 1
I d > s
d = nn
V e = 0
L
V (div, rem) = divmod(nn, d)
I bits:length(rem) > 0
L.break
nn = div
e++
 
I e > 0
pf [+]= PExp(d, e)
s = isqrt(nn)
 
d += 2
 
R pf
 
F moBachShallit58(BigInt a, BigInt n; pf)
V n1 = n - 1
V mo = BigInt(1)
L(pe) pf
V y = n1 I/ pow(pe.prime, BigInt(pe.exp))
V o = 0
V x = pow(a, y, n)
L x > 1
x = pow(x, pe.prime, n)
o++
V o1 = pow(pe.prime, BigInt(o))
o1 I/= gcd(mo, o1)
mo *= o1
R mo
 
F moTest(a, n)
I bits:length(a) < 100
print(‘ord(’a‘)’, end' ‘’)
E
print(‘ord([big])’, end' ‘’)
print(‘ mod ’n‘ = ’moBachShallit58(a, n, factor(n - 1)))
 
moTest(37, 3343)
 
moTest(pow(BigInt(10), 100) + 1, 7919)
moTest(pow(BigInt(10), 1000) + 1, 15485863)
moTest(pow(BigInt(10), 10000) - 1, BigInt(22801763489))
 
moTest(1511678068, 7379191741)
moTest(BigInt(‘3047753288’), BigInt(‘2257683301’))</syntaxhighlight>
 
{{out}}
<pre>
ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425
</pre>
 
=={{header|Ada}}==
Instead of assuming a library call to factorize the modulus, we assume the caller of our Find_Order function has already factorized it. The Multiplicative_Order package is specified as follows ("multiplicative_order.ads").
<langsyntaxhighlight Adalang="ada">package Multiplicative_Order is
 
type Positive_Array is array (Positive range <>) of Positive;
Line 68 ⟶ 159:
-- (2) 1 < Coprime_Factors(I) for all I
 
end Multiplicative_Order;</langsyntaxhighlight>
 
Here is the implementation ("multiplicative_order.adb"):
 
<langsyntaxhighlight Adalang="ada">package body Multiplicative_Order is
 
function Find_Order(Element, Modulus: Positive) return Positive is
Line 137 ⟶ 228:
end Find_Order;
 
end Multiplicative_Order;</langsyntaxhighlight>
 
This is a sample program using the Multiplicative_Order package:
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Multiplicative_Order;
 
procedure Main is
Line 163 ⟶ 254:
-- it gives an incorrect result
IIO.Put(Find_Order(37, (11, 19, 8, 2)));
end Main;</langsyntaxhighlight>
 
The output from the sample program:
Line 178 ⟶ 269:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards AND formatted transput statements removed) - tested with release 1.8.8d.fc9.i386 - ELLA has no FORMATted transput, also it generates a call to undefined C LONG externals }} -->
<langsyntaxhighlight lang="algol68">MODE LOOPINT = INT;
 
MODE POWMODSTRUCT = LONG INT;
Line 297 ⟶ 388:
printf(($g$, "Everything checks.", $l$))
FI
)</langsyntaxhighlight>
Output:
<pre>
Line 310 ⟶ 401:
=={{header|C}}==
Uses prime/factor functions from [[Factors of an integer#Prime factoring]]. This implementation is not robust because of integer overflows. To properly deal with even moderately large numbers, an arbitrary precision integer package is a must.
<langsyntaxhighlight lang="c">ulong mpow(ulong a, ulong p, ulong m)
{
ulong r = 1;
Line 369 ⟶ 460:
{
sieve();
printf("The multiplicative order of %d related to %d is %lu \n", 37, 1000, multi_order(37, 1000));
printf("The multiplicative order of %d related to %d is %lu \n", 54, 100001, multi_order(54, 100001));
return 0;
}</langsyntaxhighlight>
 
=={{header|C#|C sharp|C#}}==
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Numerics;
Line 564 ⟶ 655:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>ord(37) mod 3343 = 1114
Line 572 ⟶ 663:
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425</pre>
 
=={{header|C++}}==
{{trans|C}}
<syntaxhighlight lang="cpp">#include <algorithm>
#include <bitset>
#include <iostream>
#include <vector>
 
typedef unsigned long ulong;
std::vector<ulong> primes;
 
typedef struct {
ulong p, e;
} prime_factor; /* prime, exponent */
 
void sieve() {
/* 65536 = 2^16, so we can factor all 32 bit ints */
constexpr int SIZE = 1 << 16;
 
std::bitset<SIZE> bits;
bits.flip(); // set all bits
bits.reset(0);
bits.reset(1);
for (int i = 0; i < 256; i++) {
if (bits.test(i)) {
for (int j = i * i; j < SIZE; j += i) {
bits.reset(j);
}
}
}
 
/* collect primes into a list. slightly faster this way if dealing with large numbers */
for (int i = 0; i < SIZE; i++) {
if (bits.test(i)) {
primes.push_back(i);
}
}
}
 
auto get_prime_factors(ulong n) {
std::vector<prime_factor> lst;
ulong e, p;
 
for (ulong i = 0; i < primes.size(); i++) {
p = primes[i];
if (p * p > n) break;
for (e = 0; !(n % p); n /= p, e++);
if (e) {
lst.push_back({ p, e });
}
}
 
if (n != 1) {
lst.push_back({ n, 1 });
}
return lst;
}
 
auto get_factors(ulong n) {
auto f = get_prime_factors(n);
std::vector<ulong> lst{ 1 };
 
size_t len2 = 1;
/* L = (1); L = (L, L * p**(1 .. e)) forall((p, e)) */
for (size_t i = 0; i < f.size(); i++, len2 = lst.size()) {
for (ulong j = 0, p = f[i].p; j < f[i].e; j++, p *= f[i].p) {
for (size_t k = 0; k < len2; k++) {
lst.push_back(lst[k] * p);
}
}
}
 
std::sort(lst.begin(), lst.end());
return lst;
}
 
ulong mpow(ulong a, ulong p, ulong m) {
ulong r = 1;
while (p) {
if (p & 1) {
r = r * a % m;
}
a = a * a % m;
p >>= 1;
}
return r;
}
 
ulong ipow(ulong a, ulong p) {
ulong r = 1;
while (p) {
if (p & 1) r *= a;
a *= a;
p >>= 1;
}
return r;
}
 
ulong gcd(ulong m, ulong n) {
ulong t;
while (m) {
t = m;
m = n % m;
n = t;
}
return n;
}
 
ulong lcm(ulong m, ulong n) {
ulong g = gcd(m, n);
return m / g * n;
}
 
ulong multi_order_p(ulong a, ulong p, ulong e) {
ulong m = ipow(p, e);
ulong t = m / p * (p - 1);
auto fac = get_factors(t);
for (size_t i = 0; i < fac.size(); i++) {
if (mpow(a, fac[i], m) == 1) {
return fac[i];
}
}
return 0;
}
 
ulong multi_order(ulong a, ulong m) {
auto pf = get_prime_factors(m);
ulong res = 1;
for (size_t i = 0; i < pf.size(); i++) {
res = lcm(res, multi_order_p(a, pf[i].p, pf[i].e));
}
return res;
}
 
int main() {
sieve();
 
printf("%lu\n", multi_order(37, 1000)); // expect 100
printf("%lu\n", multi_order(54, 100001)); // expect 9090
 
return 0;
}</syntaxhighlight>
{{out}}
<pre>100
9090</pre>
 
=={{header|Clojure}}==
Translation of Julie, then revised to be more clojure idiomatic. It references some external modules for factoring and integer exponentiation.
<syntaxhighlight lang="clojure">(defn gcd [a b]
(if (zero? b)
a
(recur b (mod a b))))
 
(defn lcm [a b]
(/ (* a b) (gcd a b)))
 
(def NaN (Math/log -1))
 
(defn ord' [a [p e]]
(let [m (imath/expt p e)
t (* (quot m p) (dec p))]
(loop [dv (factor/divisors t)]
(let [d (first dv)]
(if (= (mmath/expm a d m) 1)
d
(recur (next dv)))))))
 
(defn ord [a n]
(if (not= (gcd a n) 1)
NaN
(->>
(factor/factorize n)
(map (partial ord' a))
(reduce lcm))))
</syntaxhighlight>
{{out}}
<pre>
user=> (ord 37 1000)
100
</pre>
 
=={{header|D}}==
{{trans|Java}}
<langsyntaxhighlight lang="d">import std.bigint;
import std.random;
import std.stdio;
Line 730 ⟶ 1,001:
moTest(1511678068, 7379191741);
moTest(3047753288, 2257683301);
}</langsyntaxhighlight>
{{out}}
<pre>ord(37) mod 3343 = 1114
Line 740 ⟶ 1,011:
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
(require 'bigint)
 
Line 773 ⟶ 1,044:
(order (+ (expt 10 1000) 1) 15485863)
→ 15485862
</syntaxhighlight>
</lang>
 
=={{header|ClojureFactor}}==
{{works with|Factor|0.99 2020-01-23}}
Translation of Julie, then revised to be more clojure idiomatic. It references some external modules for factoring and integer exponentiation.
<syntaxhighlight lang="factor">USING: kernel math math.functions math.primes.factors sequences ;
<lang clojure>(defn gcd [a b]
(if (zero? b)
a
(recur b (mod a b))))
 
: (ord) ( a pair -- n )
(defn lcm [a b]
first2 dupd ^ swap dupd [ /i ] keep 1 - * divisors
(/ (* a b) (gcd a b)))
[ swap ^mod 1 = ] 2with find nip ;
 
(def NaN: ord (Math/log a n -1)- m )
2dup gcd nip 1 =
 
[ group-factors [ (ord) ] with [ lcm ] map-reduce ]
(defn ord' [a [p e]]
[ 2drop 0/0. ] if ;</syntaxhighlight>
(let [m (imath/expt p e)
t (* (quot m p) (dec p))]
(loop [dv (factor/divisors t)]
(let [d (first dv)]
(if (= (mmath/expm a d m) 1)
d
(recur (next dv)))))))
 
(defn ord [a n]
(if (not= (gcd a n) 1)
NaN
(->>
(factor/factorize n)
(map (partial ord' a))
(reduce lcm))))
</lang>
{{out}}
<pre>
user=>IN: (ordscratchpad 37 1000) ord .
100
IN: scratchpad 10 100 ^ 1 + 7919 ord .
3959
</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 912 ⟶ 1,169:
}
return a.SetInt64(0)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 927 ⟶ 1,184:
Assuming a function
 
<syntaxhighlight lang="haskell">powerMod
<lang haskell>primeFacsExp :: Integer -> [(Integer, Int)]</lang>
:: (Integral a, Integral b)
=> a -> a -> b -> a
powerMod m _ 0 = 1
powerMod m x n
| n > 0 = f x_ (n - 1) x_
where
x_ = x `rem` m
f _ 0 y = y
f a d y = g a d
where
g b i
| even i = g (b * b `rem` m) (i `quot` 2)
| otherwise = f b (i - 1) (b * y `rem` m)
powerMod m _ _ = error "powerMod: negative exponent"</syntaxhighlight>
 
to efficiently calculate primepowers powermodulo factors,some and another<code>Integral</code>, functionwe get
 
<syntaxhighlight lang ="haskell">powerModimport ::Data.List (Integral a, Integral bfoldl1') => a -> a -> b -> a'
powerMod m _ 0 = 1
powerMod m x n | n > 0 = f x' (n-1) x' where
x' = x `rem` m
f _ 0 y = y
f a d y = g a d where
g b i | even i = g (b*b `rem` m) (i `quot` 2)
| otherwise = f b (i-1) (b*y `rem` m)
powerMod m _ _ = error "powerMod: negative exponent"</lang>
 
foldl1_ = foldl1' --'
to efficiently calculate powers modulo some <code>Integral</code>, we get
 
<lang haskell>multOrder a m
| gcd a m /= 1 = error "Arguments not coprime"
| otherwise = foldl1'foldl1_ lcm $ map (multOrder'multOrder_ a) $ primeFacsExp m
 
multOrder'multOrder_ a (p, k) = r where
where
pk = p^k
t pk = (p-1)*p ^(k-1) -- totient \Phi(p^k)
t = (p - 1) * p ^ (k - 1) -- totient \Phi(p^k)
r = product $ map find_qd $ primeFacsExp $ t
r = product $ map find_qd $ primeFacsExp t
find_qd (q,e) = q^d where
xfind_qd =(q, powerMode) pk= aq (t^ `div` (q^e))d
where
d = length $ takeWhile (/= 1) $ iterate (\y -> powerMod pk y q) x</lang>
x = powerMod pk a (t `div` (q ^ e))
d = length $ takeWhile (/= 1) $ iterate (\y -> powerMod pk y q) x</syntaxhighlight>
 
=={{header|J}}==
Line 959 ⟶ 1,224:
The dyadic verb ''mo'' converts its arguments to exact numbers ''a'' and ''m'', executes ''mopk'' on the factorization of ''m'', and combines the result with the ''least common multiple'' operation.
 
<langsyntaxhighlight lang="j">mo=: 4 : 0
a=. x: x
m=. x: y
assert. 1=a+.m
*./ a mopk"1 |: __ q: m
)</langsyntaxhighlight>
 
The dyadic verb ''mopk'' expects a pair of prime and exponent
Line 973 ⟶ 1,238:
exponents ''q^d'' into a product.
 
<langsyntaxhighlight lang="j">mopk=: 4 : 0
a=. x: x
'p k'=. x: y
Line 982 ⟶ 1,247:
d=. (1<x)+x (pm i. 1:)&> (e-1) */\@$&.> q
*/q^d
)</langsyntaxhighlight>
 
For example:
 
<langsyntaxhighlight lang="j"> 37 mo 1000
100
2 mo _1+10^80x
190174169488577769580266953193403101748804183400400</langsyntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight Javalang="java">import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
Line 1,098 ⟶ 1,363:
moTest(BigInteger.valueOf(3047753288L), BigInteger.valueOf(2257683301L));
}
}</langsyntaxhighlight>
{{out}}
<pre>ord(37) mod 3343 = 1114
Line 1,106 ⟶ 1,371:
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with gojq, the Go implementation of jq'''
 
The Go implementation of jq supports unbounded-precision integer
arithmetic and so is suitable for the specified tasks. The program
given here also runs using the C implementation of jq but falters for
large integers.
 
<syntaxhighlight lang="jq">
# Part 1: Library functions
 
### Counting and integer arithmetic
 
def count(s): reduce s as $x (0; .+1);
 
# If $j is 0, then an error condition is raised;
# otherwise, assuming infinite-precision integer arithmetic,
# if the input and $j are integers, then the result will be an integer.
def idivide($j):
(. - (. % $j)) / $j ;
 
def idivide($i; $j):
$i | idivide($j);
# Emit [dividend, mod]
def divmod($j):
(. % $j) as $mod
| [(. - $mod) / $j, $mod] ;
 
# input should be a non-negative integer for accuracy
# but may be any non-negative finite number
def isqrt:
def irt:
. as $x
| 1 | until(. > $x; . * 4) as $q
| {$q, $x, r: 0}
| until( .q <= 1;
.q |= idivide(4)
| .t = .x - .r - .q
| .r |= idivide(2)
| if .t >= 0
then .x = .t
| .r += .q
else .
end)
| .r ;
if type == "number" and (isinfinite|not) and (isnan|not) and . >= 0
then irt
else "isqrt requires a non-negative integer for accuracy" | error
end ;
 
# It is assumed that $n >= 0
def power($n):
. as $in
| reduce range(0;$n) as $i (1; .* $in);
 
# For syntactic convenience
def power($in; $n): $in | power($n);
 
def gcd(a; b):
# subfunction expects [a,b] as input
# i.e. a ~ .[0] and b ~ .[1]
def rgcd: if .[1] == 0 then .[0]
else [.[1], .[0] % .[1]] | rgcd
end;
[a,b] | rgcd;
 
 
### Bit arrays and streams
 
def rightshift($n):
reduce range(0;$n) as $i (.; idivide(2));
 
# Convert the input integer to a stream of 0s and 1s, least significant bit first
def bitwise:
recurse( if . >= 2 then idivide(2) else empty end) | . % 2;
 
def bitLength: count(bitwise);
 
def firstBit:
if . == 0 then empty
else first( foreach bitwise as $b (-1; .+1; if $b == 1 then . else empty end))
end;
 
# Return true if the $i-th least-significant bit is 1, and false otherwise
def testBit($i):
(nth($i; bitwise) // 0) == 1;
 
# Part 2: "modulo" functions
 
# The multiplicative inverse of . modulo $n
def modInv($n):
. as $in
| { r: $n,
newR: length, # abs
t: 0,
newT: 1 }
| until (.newR != 0.;
idivide(.r; .newR) as $q
| .lastT = .t
| .lastR = .r
| .t = .newT
| .r = .newR
| .newT = .lastT - $q*.newT
| .newR = .lastR - $q*.newR )
| if .r != 1
then "\($in) and \($n) are not co-prime." | error
else if (.t < 0) then .t += $n end
| if ($in < 0) then - .t else .t end
end;
 
# Return . to the power $exp modulo $mod
def modPow($exp; $mod):
def isOdd: . % 2 == 1;
if $mod == 0 then "Cannot take modPow with modulus 0." | error
else {r: 1, base: (. % $mod), $exp}
| if .exp < 0
then .exp *= -1
| .base |= modInv($mod)
end
| until ((.exp == 0) or .emit;
if .base == 0 then .emit = 0
else if (.exp | isOdd) then .r = (.r * .base) % $mod end
| .exp |= idivide(2)
| .base |= (.*.) % $mod
end )
| (.emit // .r)
end ;
 
# Part 3: Multiplicative order
 
def moBachShallit58($a; $n; $pf):
{n1: ($n - 1),
mo: 1 }
| reduce $pf[] as $pe (.;
(.n1 | idivide($pe.prime | power($pe.exp))) as $y
| .o = 0
| .x = ($a | modPow($y; ($n|length)))
| until (.x <= 1;
.x |= modPow($pe.prime; ($n|length) )
| .o += 1 )
| .o1 = .o
| .o1 = power($pe.prime;.o1)
| .o1 = idivide(.o1; gcd(.mo; .o1) )
| .mo = .mo * .o1 )
| .mo ;
 
def factor($n):
{ pf: [],
nn: $n,
e: ($n | firstBit)}
| if .e > 0
then .e as $e
| .nn |= rightshift($e)
| .pf = [{prime: 2, exp: .e}]
end
| (.nn | isqrt) as $s
| .d = 3
| until (.nn <= 1;
if .d > $s then .d = .nn end
| .e = 0
| .done = null
| until( .done;
.d as $d
| (.nn | divmod($d)) as $dm
| if $dm[1] > 0
then .done = true
else .nn = $dm[0]
| .e += 1
end )
| if .e > 0
then .pf += [{prime: .d, exp: .e}]
|.s = (.nn|isqrt)
end
| .d += 2
)
| .pf ;
 
# $n should be prime
def moTest($a; $n):
if ($a|bitLength) < 100 then "ord(\($a)) " else "ord([big]) " end +
if ($n|bitLength) < 100 then "mod \($n) " else "mod [big] " end +
"= \(moBachShallit58($a; $n; factor($n - 1)))" ;
 
moTest(37; 3343),
moTest(1 + power(10;100); 7919),
moTest(1 + power(10;100); 15485863),
moTest(power(10;10000) - 1; 22801763489),
moTest(1511678068; 7379191741),
moTest(3047753288; 2257683301)
</syntaxhighlight>
{{output}}
<pre>
ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425
</pre>
 
=={{header|Julia}}==
(Uses the <code>factors</code> function from [[Factors of an integer#Julia]].)
<syntaxhighlight lang="julia">using Primes
<lang julia>function factors(n)
 
function factors(n)
f = [one(n)]
for (p,e) in factor(n)
f = reduce(vcat, f, [f*p^j for j in 1:e], init=f)
end
return length(f) == 1 ? [one(n), n] : sort!(f)
Line 1,131 ⟶ 1,601:
end
res
end</langsyntaxhighlight>
 
Example output (using <code>big</code> to employ arbitrary-precision arithmetic where needed):
Line 1,150 ⟶ 1,620:
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import java.math.BigInteger
Line 1,243 ⟶ 1,713:
moTest(BigInteger("1511678068"), BigInteger("7379191741"))
moTest(BigInteger("3047753288"), BigInteger("2257683301"))
}</langsyntaxhighlight>
 
{{out}}
Line 1,256 ⟶ 1,726:
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">numtheory:-order( a, n )</langsyntaxhighlight>
For example,
<langsyntaxhighlight Maplelang="maple">> numtheory:-order( 37, 1000 );
100</langsyntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
In Mathematica this is really easy, as this function is built-in:
MultiplicativeOrder[k,n] gives the multiplicative order of k modulo n, defined as the smallest integer m such that k^m == 1 mod n.<br>
MultiplicativeOrder[k,n,{r1,r2,...}] gives the generalized multiplicative order of k modulo n, defined as the smallest integer m such that k^m==ri mod n for some i.<BR>
Examples:
<langsyntaxhighlight Mathematicalang="mathematica">MultiplicativeOrder[37, 1000]
MultiplicativeOrder[10^100 + 1, 7919] (*10^3th prime number Prime[1000]*)
MultiplicativeOrder[10^1000 + 1, 15485863] (*10^6th prime number*)
MultiplicativeOrder[10^10000 - 1, 22801763489] (*10^9th prime number*)
MultiplicativeOrder[13, 1 + 10^80]
MultiplicativeOrder[11, 1 + 10^100]</langsyntaxhighlight>
gives back:
<pre>100
Line 1,281 ⟶ 1,751:
 
=={{header|Maxima}}==
<langsyntaxhighlight lang="maxima">zn_order(37, 1000);
/* 100 */
 
Line 1,297 ⟶ 1,767:
 
zn_order(11, 1 + 10^100);
/* 2583496112724752500580158969425549088007844580826869433740066152289289764829816356800 */</langsyntaxhighlight>
 
=={{header|PARI/GPNim}}==
{{trans|Kotlin}}
<lang parigp>znorder(Mod(a,n))</lang>
{{libheader|bignum}}
<syntaxhighlight lang="nim">import strformat
import bignum
 
type PExp = tuple[prime: Int; exp: uint]
=={{header|Perl}}==
Using modules:
{{libheader|ntheory}}
<lang perl>use ntheory qw/znorder/;
say znorder(54, 100001);
use bigint; say znorder(11, 1 + 10**100);</lang>
or
<lang perl>use Math::Pari qw/znorder Mod/;
say znorder(Mod(54, 100001));
say znorder(Mod(11, 1 + Math::Pari::PARI(10)**100));</lang>
 
let
=={{header|Perl 6}}==
one = newInt(1)
<lang perl6>my @primes := 2, |grep *.is-prime, (3,5,7...*);
two = newInt(2)
ten = newInt(10)
 
sub factor($a is copy) {
gather {
for @primes -> $p {
my $j = 0;
while $a %% $p {
$a div= $p;
$j++;
}
take $p => $j if $j > 0;
last if $a < $p * $p;
}
take $a => 1 if $a > 1;
}
}
sub mo-prime($a, $p, $e) {
my $m = $p ** $e;
my $t = ($p - 1) * ($p ** ($e - 1)); # = Phi($p**$e) where $p prime
my @qs = 1;
for factor($t) -> $f {
@qs = flat @qs.map(-> $q { (0..$f.value).map(-> $j { $q * $f.key ** $j }) });
}
@qs.sort.first(-> $q { expmod( $a, $q, $m ) == 1});
}
sub mo($a, $m) {
$a gcd $m == 1 || die "$a and $m are not relatively prime";
[lcm] flat 1, factor($m).map(-> $r { mo-prime($a, $r.key, $r.value) });
}
sub MAIN("test") {
use Test;
for (10, 21, 25, 150, 1231, 123141, 34131) -> $n {
is ([*] factor($n).map(-> $pair { $pair.key ** $pair.value })), $n, "$n factors correctly";
}
is mo(37, 1000), 100, 'mo(37,1000) == 100';
my $b = 10**20-1;
is mo(2, $b), 3748806900, 'mo(2,10**20-1) == 3748806900';
is mo(17, $b), 1499522760, 'mo(17,10**20-1) == 1499522760';
$b = 100001;
is mo(54, $b), 9090, 'mo(54,100001) == 9090';
}</lang>
{{out}}
<pre>ok 1 - 10 factors correctly
ok 2 - 21 factors correctly
ok 3 - 25 factors correctly
ok 4 - 150 factors correctly
ok 5 - 1231 factors correctly
ok 6 - 123141 factors correctly
ok 7 - 34131 factors correctly
ok 8 - mo(37,1000) == 100
ok 9 - mo(2,10**20-1) == 3748806900
ok 10 - mo(17,10**20-1) == 1499522760
ok 11 - mo(54,100001) == 9090</pre>
 
func sqrt(n: Int): Int =
=={{header|Phix}}==
var s = n
{{trans|Ruby}}
while true:
Note this is considerably slower than Ruby, which completes in a fraction of a second, mainly I suspect
result = s
due to the fact that bigatom.e operates on a digit-by-digit basis.
s = (n div result + result) shr 1
if s >= result: break
 
Also, ba_mod_exp is fairly likely to get added to bigatom.e in a future release, likewise
the other ba_xxx routines below have been earmarked for possible inclusion.
<lang Phix>include bigatom.e
 
proc factor(n: Int): seq[PExp] =
function ba_mod_exp(object base, exponent, modulus)
var n = n
-- base/exponent/modulus can be integer/string/bigatom
var e = 0u
-- returns mod(power(base,exponent),modulus) [aka b^e%m], but in bigatoms and faster.
while n.bit(e) == 0: inc e
bigatom res = BA_ONE
if e != 0:
base = ba_mod(base,modulus)
n = n shr e
while ba_compare(exponent,0)!=0 do
result.add (two, e)
if ba_mod(exponent,2)=BA_ONE then
var s = sqrt(n)
res = ba_mod(ba_multiply(res,base),modulus)
var d = end ifnewInt(3)
while n > one:
base = ba_mod(ba_multiply(base,base),modulus)
if d > s: exponentd = ba_idivide(exponent,2)n
ende while= 0u
returnwhile restrue:
let (q, r) = divMod(n, d)
end function
if not r.isZero: break
n = q
inc e
if e != 0:
result.add (d.clone, e)
s = sqrt(n)
inc d, two
 
function ba_factor(object n)
-- eg ba_factor(1000) -> {{2,3},{5,3}}, ie power(2,3)*power(5,3) == 8*125 == 1000.
-- (note that each res[i] is {bigatom,integer})
if ba_compare(n,BA_ZERO)=0 then return {} end if
sequence pf = {}
integer e = 0
while ba_mod(n,2)=BA_ZERO do
n = ba_idivide(n,2)
e += 1
end while
if e>0 then
pf = {{2,e}}
end if
bigatom s = ba_sqrt(n),
d = ba_new(3)
while ba_compare(n,BA_ONE)>0 do
if ba_compare(d,s)>0 then
d = ba_new(n)
end if
e = 0
while true do
bigatom r = ba_mod(n,d)
if r!=BA_ZERO then exit end if
n = ba_idivide(n,d)
e += 1
end while
if e>0 then
pf = append(pf,{d,e})
s = ba_sqrt(n)
end if
d = ba_add(d,2)
end while
return pf
end function
 
proc moBachShallit58(a, n: Int; pf: seq[PExp]): Int =
function ba_gcd(object m, n)
let n = abs(n)
while ba_compare(n,BA_ZERO)!=0 do
let n1 = {m,n} =- {n,ba_mod(m,n)}one
result = newInt(1)
end while
for pe returnin mpf:
let y = n1 div pe.prime.pow(pe.exp)
end function
var o = 0u
var x = a.exp(y.toInt.uint, n)
while x > one:
x = x.exp(pe.prime.toInt.uint, n)
inc o
var o1 = pe.prime.pow(o)
o1 = o1 div gcd(result, o1)
result *= o1
 
function ba_lcm(object m, n)
return ba_mul(ba_idivide(m,ba_gcd(m,n)),n)
end function
 
proc moTest(a, n: Int) =
function multi_order(object a, sequence p_and_k)
if n.probablyPrime(25) == 0:
{object p, integer k} = p_and_k
echo "Not computed. Modulus must be prime for this algorithm."
bigatom pk = ba_power(p,k),
return
t = ba_mul(ba_sub(p,1),ba_power(p,ba_sub(k,1))),
r = BA_ONE
sequence pf = ba_factor(t)
for i=1 to length(pf) do
{object q, integer e} = pf[i]
bigatom x = ba_mod_exp(a,ba_idiv(t,ba_power(q,e)),pk)
--
-- previous attempts at this task resulted in an infinite loop,
-- so I added a quard; feel free to increase limit as needed.
--
integer guard = 0
while x!=BA_ONE do
r = ba_mul(r,q)
x = ba_mod_exp(x,q,pk)
guard += 1
if guard>100 then ?9/0 end if
end while
end for
return r
end function
function multiplicative_order(object a, m)
if ba_gcd(a,m)!=BA_ONE then return "(a,m) not coprime" end if
sequence pf = ba_factor(m)
bigatom res = BA_ONE
for i=1 to length(pf) do
res = ba_lcm(res,multi_order(a,pf[i]))
end for
return res
end function
 
stdout.write if a.bitLen < 100: &"ord({a})" else: "ord([big])"
constant b100 = ba_power(2,100)
stdout.write if n.bitlen < 100: &" mod {n}" else: " mod [big]"
let mob = moBachShallit58(a, n, factor(n - one))
echo &" = {mob}"
 
function shorta(object n)
return iff(ba_compare(n,b100)>0?"[big]":ba_sprint(n))
end function
 
when isMainModule:
procedure mo_test(object a, n)
moTest(newInt(37), newInt(3343))
string res = ba_sprint(multiplicative_order(a, n))
 
printf(1,"ord(%s) mod %s = %s\n",{shorta(a),shorta(n),res})
var b = ten.pow(100) + one
end procedure
motest(b, newInt(7919))
 
b = ten.pow(1000) + one
moTest(b, newInt("15485863"))
 
b = ten.pow(10000) - one
moTest(b, newInt("22801763489"))
 
moTest(newInt("1511678068"), newInt("7379191741"))
 
moTest(newInt("3047753288"), newInt("2257683301"))</syntaxhighlight>
 
atom t = time()
mo_test(37, 1000)
mo_test(37, 3343)
mo_test(ba_add(ba_power(10,100),1), 7919)
mo_test(ba_add(ba_power(10,1000),1), 15485863)
mo_test(ba_sub(ba_power(10,10000),1), 22801763489)
mo_test(1511678068, 7379191741)
mo_test(3047753288, 2257683301)
?"==="
bigatom b = ba_sub(ba_power(10,20),1)
mo_test(2, b)
mo_test(17,b)
mo_test(54,100001)
--/*
-- this all works fine, but doubles the runtime...
bigatom b9090 = multiplicative_order(54,100001)
ba_printf(1,"%B\n",b9090)
if ba_compare(b9090,9090)!=0 then ?9/0 end if
ba_printf(1,"%B\n",ba_mod_exp(54,b9090,100001))
bool error = false
atom t1 = time()+1
for r=1 to 9090-1 do
if ba_compare(ba_mod_exp(54,r,100001),1)=0 then
printf(1,"ba_mod_exp(54,%d,100001) gives 1!\n",r)
error = true
exit
end if
if time()>t1 then
printf(1,"checking %d...\r",r)
t1 = time()+1
end if
end for
if not error then puts(1,"Everything checks.\n") end if
--*/
?elapsed(time()-t)</lang>
{{out}}
<pre>ord(37) mod 3343 = 1114
<pre>
ord(37) mod 1000 = 100
ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425</pre>
 
=={{header|PARI/GP}}==
<syntaxhighlight lang="parigp">znorder(Mod(a,n))</syntaxhighlight>
 
=={{header|Perl}}==
Using modules:
{{libheader|ntheory}}
<syntaxhighlight lang="perl">use ntheory qw/znorder/;
say znorder(54, 100001);
use bigint; say znorder(11, 1 + 10**100);</syntaxhighlight>
or
<syntaxhighlight lang="perl">use Math::Pari qw/znorder Mod/;
say znorder(Mod(54, 100001));
say znorder(Mod(11, 1 + Math::Pari::PARI(10)**100));</syntaxhighlight>
 
=={{header|Phix}}==
{{trans|Ruby}}
{{libheader|Phix/mpfr}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">multi_order</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">p_and_k</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpz</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p_and_k</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ps</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p_and_k</span>
<span style="color: #7060A8;">mpz_set_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ps</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p_and_k</span>
<span style="color: #7060A8;">mpz_set_d</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_prime_factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">fs</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">mpz_set_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fs</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">qi</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">ei</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qi</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ei</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">mpz_fdiv_q</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">guard</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pk</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">guard</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">guard</span><span style="color: #0000FF;">></span><span style="color: #000000;">100</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (increase if rqd)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">multiplicative_order</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">mpz_gcd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"(a,m) not coprime"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_prime_factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (increase if rqd)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">multi_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">mpz_lcm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">shorta</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lr</span><span style="color: #0000FF;">></span><span style="color: #000000;">80</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"..."</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" (%d digits)"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">multiplicative_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ord(%s) mod %s = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">shorta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span><span style="color: #000000;">shorta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span> <span style="color: #000080;font-style:italic;">-- (ugh)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">p10</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- init to 10^e+i</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">37</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">37</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">37</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3343</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">37</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3344</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7919</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">15485863</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">22801763489</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1511678068</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7379191741</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3047753288</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2257683301</span><span style="color: #0000FF;">))</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"==="</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">17</span><span style="color: #0000FF;">),</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mo_test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">54</span><span style="color: #0000FF;">),</span><span style="color: #000000;">i</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100001</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s9090</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">multiplicative_order</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">54</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100001</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s9090</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">"9090"</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">m54</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">54</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">m100001</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100001</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_powm_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m54</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9090</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m100001</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9090</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">mpz_powm_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m54</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m100001</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mpz_powm_ui(54,%d,100001) gives 1!\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Everything checks. (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
ord(3) mod 10 = 4
ord(37) mod 1000 = 100
ord(37) mod 10000 = 500
ord(37) mod 3343 = 1114
ord(37) mod 3344 = 20
ord(2) mod 1000 = (a,m) not coprime
ord(10000...00001 (101 digits)) mod 7919 = 3959
ord(10000...00001 (1001 digits)) mod 15485863 = 15485862
ord(99999...99999 (10000 digits)) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425
Line 1,538 ⟶ 2,014:
ord(17) mod 99999999999999999999 = 1499522760
ord(54) mod 100001 = 9090
1
"1 minute and 11s"
Everything checks. (0.2s)
</pre>
 
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">def gcd(a, b):
while b != 0:
a, b = b, a % b
Line 1,608 ⟶ 2,085:
print 'Exists a power r < 9090 where pow(54,r,b)==1'
else:
print 'Everything checks.'</langsyntaxhighlight>
 
=={{header|Racket}}==
Line 1,615 ⟶ 2,092:
shown below.
 
<langsyntaxhighlight lang="racket">
#lang racket
(require math)
Line 1,641 ⟶ 2,118:
(order (- (expt 10 10000) 1) 22801763489)
(order 13 (+ 1 (expt 10 80)))
</syntaxhighlight>
</lang>
Output:
<langsyntaxhighlight lang="racket">
100
3959
Line 1,649 ⟶ 2,126:
22801763488
109609547199756140150989321269669269476675495992554276140800
</syntaxhighlight>
</lang>
 
=={{header|REXXRaku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>use Prime::Factor;
 
sub mo-prime($a, $p, $e) {
<lang rexx>/*REXX pgm computes multiplicative order of a minimum integer N such that a^n mod m≡1*/
my $m = $p ** $e;
wa=0; wm=0 /* ═a═ ══m══ */ /*maximum widths of the A and M values.*/
@.=.; my $t = ($p - 1) * ($p ** ($e - @.1=)); # 3 = Phi($p**$e) where $p 10prime
my @qs = 1;
@.2= 37 1000
for @prime-factors($t).3= 37Bag -> $f 10000{
@qs = flat @qs.map(-> $q { (0..$f.value).map(-> $j { $q * @$f.4= 37key ** $j }) 3343});
}
@.5= 37 3344
 
@.6= 2 1000
@qs.sort.first: -> $q { expmod( $a, $q, $m ) == 1 };
pad=left('',9)
}
d=100 /*use 100 decimal digits for a starter.*/
 
sub mo($a, $m) {
$a gcd $m == 1 or die "$a and $m are not relatively prime";
[lcm] flat 1, prime-factors($m).Bag.map: { mo-prime($a, .key, .value) };
}
 
multi MAIN('test') {
use Test;
 
for (10, 21, 25, 150, 1231, 123141, 34131) -> $n {
is ([*] prime-factors($n).Bag.map( { .key ** .value } )), $n, "$n factors correctly";
}
 
is mo(37, 1000), 100, 'mo(37,1000) == 100';
my $b = 10**20-1;
is mo(2, $b), 3748806900, 'mo(2,10**20-1) == 3748806900';
is mo(17, $b), 1499522760, 'mo(17,10**20-1) == 1499522760';
$b = 100001;
is mo(54, $b), 9090, 'mo(54,100001) == 9090';
}</syntaxhighlight>
{{out}}
<pre>ok 1 - 10 factors correctly
ok 2 - 21 factors correctly
ok 3 - 25 factors correctly
ok 4 - 150 factors correctly
ok 5 - 1231 factors correctly
ok 6 - 123141 factors correctly
ok 7 - 34131 factors correctly
ok 8 - mo(37,1000) == 100
ok 9 - mo(2,10**20-1) == 3748806900
ok 10 - mo(17,10**20-1) == 1499522760
ok 11 - mo(54,100001) == 9090</pre>
 
=={{header|REXX}}==
<syntaxhighlight lang="rexx">/*REXX pgm computes multiplicative order of a minimum integer N such that a^n mod m≡1*/
wa= 0; wm= 0 /* ═a═ ══m══ */ /*maximum widths of the A and M values.*/
@.=.; @.1= 3 10
@.2= 37 1000
@.3= 37 10000
@.4= 37 3343
@.5= 37 3344
@.6= 2 1000
pad= left('', 9)
d= 500 /*use 500 decimal digits for a starter.*/
do w=1 for 2 /*when W≡1, find max widths of A and M.*/
do j=1 while @.j\==.; parse var @.j a . 1 r m , n
if w==1 then do; wa= max(wa, length(a) ); wm= max(wm, length(m) ); iterate; enditerate
if m//a==0 then n= ' [solution not possible]' /*test co-prime for A and B. */end
if m//a==0 then n= ' [solution not possible]' /*test co─prime for A and B. */
numeric digits d /*start with 100 decimal digits. */
if n=='' then do n= 2; p= r *a a /*compute product──may have an exponent*/
parse var p 'E' _ /*try to extract the exponent from P. */
if _\=='' then do; numeric digits _+d /*bump the decimal digs.*/
p=r*a /*recalculate integer P.*/
end
if p//m==1 then leave /*now, perform the nitty-grittynitty─gritty modulo.*/
r= p /*assign product to R for next mult. multiply*/
end /*n*/ /* [↑] // is really ÷ remainder.*/
say pad 'a=' right(a,wa) pad "m=" right(m,wm) pad 'multiplicative order:' n
end /*j*/
end /*w*/ /*stick a fork in it, we're all done. */</langsyntaxhighlight>
'''{{out|output'''|.}}
<pre>
a= 3 m= 10 multiplicative order: 4
Line 1,691 ⟶ 2,215:
=={{header|Ruby}}==
 
<langsyntaxhighlight lang="ruby">require 'prime'
 
def powerMod(b, p, m)
Line 1,731 ⟶ 2,255:
else
puts 'Everything checks.'
end</langsyntaxhighlight>
 
{{out}}
Line 1,744 ⟶ 2,268:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "bigint.s7i";
 
Line 1,861 ⟶ 2,385:
moTest(1511678068_, 7379191741_);
moTest(3047753288_, 2257683301_);
end func;</langsyntaxhighlight>
 
{{out}}
Line 1,874 ⟶ 2,398:
 
=={{header|Sidef}}==
 
{{trans|Perl 6}}
Built-in:
<lang ruby>func mo_prime(a, p, e) {
<syntaxhighlight lang="ruby">say 37.znorder(1000) #=> 100
say 54.znorder(100001) #=> 9090</syntaxhighlight>
 
{{trans|Raku}}
<syntaxhighlight lang="ruby">func mo_prime(a, p, e) {
var m = p**e
var t = (p-1)*(p**(e-1))
Line 1,900 ⟶ 2,429:
say mo(2, b)
say mo(17, b)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,912 ⟶ 2,441:
{{trans|Python}}
{{tcllib|struct::list}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require struct::list
 
Line 2,089 ⟶ 2,618:
if {$r % 1000 == 0} {puts "$r ..."}
}
puts "OK, $n is the smallest n such that {$a $n $m} satisfies $lambda"</langsyntaxhighlight>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Numerics
Imports System.Runtime.CompilerServices
Imports System.Threading
 
Module Module1
Private s_gen As New ThreadLocal(Of Random)(Function() New Random())
 
Private Function Gen()
Return s_gen.Value
End Function
 
<Extension()>
Public Function IsProbablyPrime(value As BigInteger, Optional witnesses As Integer = 10) As Boolean
If value <= 1 Then
Return False
End If
 
If witnesses <= 0 Then
witnesses = 10
End If
 
Dim d = value - 1
Dim s = 0
 
While d Mod 2 = 0
d /= 2
s += 1
End While
 
Dim bytes(value.ToByteArray.LongLength - 1) As Byte
Dim a As BigInteger
 
For i = 1 To witnesses
Do
Gen.NextBytes(bytes)
 
a = New BigInteger(bytes)
Loop While a < 2 OrElse a >= value - 2
 
Dim x = BigInteger.ModPow(a, d, value)
If x = 1 OrElse x = value - 1 Then
Continue For
End If
 
For r = 1 To s - 1
x = BigInteger.ModPow(x, 2, value)
 
If x = 1 Then
Return False
End If
If x = value - 1 Then
Exit For
End If
Next
 
If x <> value - 1 Then
Return False
End If
Next
 
Return True
End Function
 
<Extension()>
Function Sqrt(self As BigInteger) As BigInteger
Dim b = self
While True
Dim a = b
b = self / a + a >> 1
If b >= a Then
Return a
End If
End While
Throw New Exception("Should not have happened")
End Function
 
<Extension()>
Function BitLength(self As BigInteger) As Long
Dim bi = self
Dim len = 0L
While bi <> 0
len += 1
bi >>= 1
End While
Return len
End Function
 
<Extension()>
Function BitTest(self As BigInteger, pos As Integer) As Boolean
Dim arr = self.ToByteArray
Dim i = pos \ 8
Dim m = pos Mod 8
If i >= arr.Length Then
Return False
End If
Return (arr(i) And (1 << m)) > 0
End Function
 
Class PExp
Sub New(p As BigInteger, e As Integer)
Prime = p
Exp = e
End Sub
 
Public ReadOnly Property Prime As BigInteger
Public ReadOnly Property Exp As Integer
End Class
 
Function MoBachShallit58(a As BigInteger, n As BigInteger, pf As List(Of PExp)) As BigInteger
Dim n1 = n - 1
Dim mo As BigInteger = 1
For Each pe In pf
Dim y = n1 / BigInteger.Pow(pe.Prime, pe.Exp)
Dim o = 0
Dim x = BigInteger.ModPow(a, y, BigInteger.Abs(n))
While x > 1
x = BigInteger.ModPow(x, pe.Prime, BigInteger.Abs(n))
o += 1
End While
Dim o1 = BigInteger.Pow(pe.Prime, o)
o1 /= BigInteger.GreatestCommonDivisor(mo, o1)
mo *= o1
Next
Return mo
End Function
 
Function Factor(n As BigInteger) As List(Of PExp)
Dim pf As New List(Of PExp)
Dim nn = n
Dim e = 0
While Not nn.BitTest(e)
e += 1
End While
If e > 0 Then
nn >>= e
pf.Add(New PExp(2, e))
End If
Dim s = nn.Sqrt
Dim d As BigInteger = 3
While nn > 1
If d > s Then
d = nn
End If
e = 0
While True
Dim remainder As New BigInteger
Dim div = BigInteger.DivRem(nn, d, remainder)
If remainder.BitLength > 0 Then
Exit While
End If
nn = div
e += 1
End While
If e > 0 Then
pf.Add(New PExp(d, e))
s = nn.Sqrt
End If
d += 2
End While
Return pf
End Function
 
Sub MoTest(a As BigInteger, n As BigInteger)
If Not n.IsProbablyPrime(20) Then
Console.WriteLine("Not computed. Modulus must be prime for this algorithm.")
Return
End If
If a.BitLength < 100 Then
Console.Write("ord({0})", a)
Else
Console.Write("ord([big])")
End If
If n.BitLength < 100 Then
Console.Write(" mod {0}", n)
Else
Console.Write(" mod [big]")
End If
Dim mob = MoBachShallit58(a, n, Factor(n - 1))
Console.WriteLine(" = {0}", mob)
End Sub
 
Sub Main()
MoTest(37, 3343)
MoTest(BigInteger.Pow(10, 100) + 1, 7919)
MoTest(BigInteger.Pow(10, 1000) + 1, 15485863)
MoTest(BigInteger.Pow(10, 10000) - 1, 22801763489)
MoTest(1511678068, 7379191741)
MoTest(3047753288, 2257683301)
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-big}}
<syntaxhighlight lang="wren">import "./big" for BigInt
 
class PExp {
construct new(prime, exp) {
_prime = prime
_exp = exp
}
prime { _prime }
exp { _exp }
}
 
var moBachShallit58 = Fn.new { |a, n, pf|
var n1 = n - BigInt.one
var mo = BigInt.one
for (pe in pf) {
var y = n1 / pe.prime.pow(pe.exp)
var o = 0
var x = a.modPow(y, n.abs)
while (x > BigInt.one) {
x = x.modPow(pe.prime, n.abs)
o = o + 1
}
var o1 = BigInt.new(o)
o1 = pe.prime.pow(o1)
o1 = o1 / BigInt.gcd(mo, o1)
mo = mo * o1
}
return mo
}
 
var factor = Fn.new { |n|
var pf = []
var nn = n.copy()
var e = 0
while (!nn.testBit(e)) e = e + 1
if (e > 0) {
nn = nn >> e
pf.add(PExp.new(BigInt.two, e))
}
var s = nn.isqrt
var d = BigInt.three
while (nn > BigInt.one) {
if (d > s) d = nn
e = 0
while (true) {
var dm = nn.divMod(d)
if (dm[1].bitLength > 0) break
nn = dm[0]
e = e + 1
}
if (e > 0) {
pf.add(PExp.new(d, e))
s = nn.isqrt
}
d = d + BigInt.two
}
return pf
}
 
var moTest = Fn.new { |a, n|
if (!n.isProbablePrime(10)) {
System.print("Not computed. Modulus must be prime for this algorithm.")
return
}
System.write((a.bitLength < 100) ? "ord(%(a))" : "ord([big])")
System.write((n.bitLength < 100) ? " mod %(n) " : "mod([big])")
var mob = moBachShallit58.call(a, n, factor.call(n - BigInt.one))
System.print("= %(mob)")
}
 
moTest.call(BigInt.new(37), BigInt.new(3343))
 
var b = BigInt.ten.pow(100) + BigInt.one
moTest.call(b, BigInt.new(7919))
 
b = BigInt.ten.pow(1000) + BigInt.one
moTest.call(b, BigInt.new(15485863))
 
b = BigInt.ten.pow(10000) - BigInt.one
moTest.call(b, BigInt.new(22801763489))
 
moTest.call(BigInt.new(1511678068), BigInt.new(7379191741))
moTest.call(BigInt.new(3047753288), BigInt.new(2257683301))</syntaxhighlight>
 
{{out}}
<pre>
ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425
</pre>
 
=={{header|zkl}}==
Line 2,096 ⟶ 2,923:
 
It would probably be nice to memoize the prime numbers but that isn't necessary for this task.
<langsyntaxhighlight lang="zkl">var BN =Import("zklBigNum");
var Sieve=Import("sieve");
 
Line 2,130 ⟶ 2,957:
}
return(res);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">multiOrder(37,1000).println();
b:=BN(10).pow(20)-1;
multiOrder(2,b).println();
Line 2,139 ⟶ 2,966:
[BN(1)..multiOrder(54,b)-1].filter1('wrap(r,b54){b54.powm(r,b)==1},BN(54)) :
if (_) println("Exists a power r < 9090 where (54^r)%b)==1");
else println("Everything checks.");</langsyntaxhighlight>
{{out}}
<pre>
2,442

edits