Multiplicative order: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Haskell}}: Fixed formatting, second attempt)
(Reverted global description, adding the book excerpt at end. Reverted J comments.)
Line 2: Line 2:
{{clarified-review}}
{{clarified-review}}


<p>The '''multiplicative order''' of ''a'' relative to ''m'' is the least positive integer ''n'' such that ''a^n'' is 1 (modulo ''m'').
The '''multiplicative order''' of ''a'' relative to ''m'' is the least positive integer ''n'' such that ''a^n'' is 1 (modulo ''m'').
For example, the multiplicative oder of 37 relative to 1000 is 100 because 37^100 is 1 (modulo 1000), and no number smaller than 100 would do. An algorithm can be found in
For example, the multiplicative oder of 37 relative to 1000 is 100 because 37^100 is 1 (modulo 1000), and no number smaller than 100 would do.
Note that the multiplicative order is undefined if ''a'' and ''m'' are not relatively prime.
Bach & Shallit, <i>Algorithmic Number Theory, Volume I: Efficient Algorithms</i>, The MIT Press, 1996.</p>

One possible algorithm that is efficient also for large numbers is the following: By the [http://en.wikipedia.org/wiki/Chinese_Remainder_Theorem Chinese Remainder Theorem], it's enough to calculate the multiplicative order for each prime exponent ''p^k'' of ''m'', and
combine the results with the ''least common multiple'' operation.
Now the order of ''a'' wrt. to ''p^k'' must divide ''&Phi;(p^k)''. Call this number ''t'', and determine it's factors ''q^e''. Since each multiple of the order will also yield 1 when used as exponent for ''a'', it's enough to find the least d such that ''(q^d)*(t/(q^e))'' yields 1 when used as exponent.

Implement a routine to calculate the multiplicative order along these lines. You may assume that routines to determine the factorization into prime powers are available in some library.

----

An analysis of the efficiency of the step in the inner loop can be found in Bach & Shallit, <i>Algorithmic Number Theory, Volume I: Efficient Algorithms</i>, The MIT Press, 1996:


<p>Exercise 5.8, page 115:</p>
<p>Exercise 5.8, page 115:</p>
Line 10: Line 20:
<p>Suppose you are given a prime<tt> p </tt>and a complete factorization
<p>Suppose you are given a prime<tt> p </tt>and a complete factorization
of<tt> p-1</tt> .<tt> </tt>Show how to compute the order of an
of<tt> p-1</tt> .<tt> </tt>Show how to compute the order of an
element<tt> a </tt>in<tt> (Z/(p))* </tt>using<tt> O((lg p)<sup>4</sup>/(lg lg p)) </tt>bit
element<tt> a </tt>in<tt> (Z/(p))<sup>*</sup> </tt>using<tt> O((lg p)<sup>4</sup>/(lg lg p)) </tt>bit
operations.</p>
operations.</p>


<p>Solution, page 337:</p>
<p>Solution, page 337:</p>


<p>Let the prime factorization of<tt> p-1 </tt>
<p>Let the prime factorization of<tt> p-1 </tt> be<tt> q1<sup>e1</sup>q2<sup>e2</sup>...qk<sup>ek</sup></tt> .<tt> </tt>We use the following observation:
be<tt> q1<sup>e1</sup>q2<sup>e2</sup>...qk<sup>ek</sup></tt> .<tt> </tt>We use
the following observation:
if<tt> x^((p-1)/qi<sup>fi</sup>) = 1 (mod p)</tt> ,<tt> </tt>
if<tt> x^((p-1)/qi<sup>fi</sup>) = 1 (mod p)</tt> ,<tt> </tt>
and<tt> fi=ei </tt>or<tt> x^((p-1)/qi<sup>fi+1</sup>) != 1 (mod p)</tt> ,<tt> </tt>
and<tt> fi=ei </tt>or<tt> x^((p-1)/qi<sup>fi+1</sup>) != 1 (mod p)</tt> ,<tt> </tt>then<tt> qi<sup>ei-fi</sup>|ord<sub>p</sub> x</tt> .<tt> </tt>
then<tt> q<sup>ei-fi</sup>||ord<sub>p</sub> x</tt> .<tt> </tt>
(This follows by combining Exercises 5.1 and 2.10.)
(This follows by combining Exercises 5.1 and 2.10.)

Hence it suffices to find, for each<tt> i</tt> ,<tt> </tt>the exponent<tt> fi </tt>
such that the condition above holds.</p>
Hence it suffices to find, for each<tt> i</tt> ,<tt> </tt>the exponent<tt> fi </tt> such that the condition above holds.</p>


<p>This can be done as follows: first compute<tt> q1<sup>e1</sup>, q2<sup>e2</sup>, ... ,
<p>This can be done as follows: first compute<tt> q1<sup>e1</sup>, q2<sup>e2</sup>, ... ,
qk<sup>ek</sup></tt> .<tt> </tt> This can be done using<tt> O((lg p)<sup>2</sup>) </tt>bit operations. Next, compute<tt> y1=(p-1)/q1<sup>e1</sup>, ... , yk=(p-1)/qk<sup>ek</sup></tt> .<tt> </tt>
qk<sup>ek</sup></tt> .<tt> </tt>
This can be done using<tt> O((lg p)<sup>2</sup>) </tt>bit operations. Next,
This can be done using<tt> O((lg p)<sup>2</sup>) </tt>bit operations. Now, using the binary method,
compute<tt> y1=(p-1)/q1<sup>e1</sup>, ... , yk=(p-1)/qk<sup>ek</sup></tt> .<tt> </tt>
This can be done using<tt> O((lg p)<sup>2</sup>) </tt>bit operations.
Now, using the binary method,
compute<tt> x1=a<sup>y1</sup>(mod p), ... , xk=a<sup>yk</sup>(mod p) </tt>.<tt> </tt>
compute<tt> x1=a<sup>y1</sup>(mod p), ... , xk=a<sup>yk</sup>(mod p) </tt>.<tt> </tt>
This can be done using<tt> O(k(lg p)<sup>3</sup>) </tt>bit operations,
This can be done using<tt> O(k(lg p)<sup>3</sup>) </tt>bit operations, and<tt> k=O((lg p)/(lg lg p)) </tt>by Theorem 8.8.10.
Finally, for each<tt> i</tt> ,<tt> </tt>repeatedly raise<tt> xi </tt>to the<tt> qi</tt>-th power<tt> (mod p) </tt>(as many as<tt> ei-1 </tt> times), checking to see when 1 is obtained.
and<tt> k=O((lg p)/(lg lg p)) </tt>by Theorem 8.8.10.
Finally, for each<tt> i</tt> ,<tt> </tt>repeatedly raise<tt> xi </tt>to
the<tt> qi</tt>-th power<tt> (mod p) </tt>(as many as<tt> ei-1 </tt> times),
checking to see when 1 is obtained.
This can be done using<tt> O((lg p)<sup>3</sup>) </tt>steps.
This can be done using<tt> O((lg p)<sup>3</sup>) </tt>steps.
The total cost is dominated by<tt> O(k(lg p)<sup>3</sup>)</tt> ,<tt> </tt>
The total cost is dominated by<tt> O(k(lg p)<sup>3</sup>)</tt> ,<tt> </tt>which is<tt> O(k(lg p)<sup>4</sup>/(lg lg p))</tt> .
which is<tt> O(k(lg p)<sup>4</sup>/(lg lg p))</tt> .



=={{header|J}}==
=={{header|J}}==

The dyadic verb ''mo'' converts it's arguments to exact numbers ''a'' and ''m'', executes ''mopk'' on the factorization of ''m'', and combines the result with the ''least common multiple'' operation.


mo=: 4 : 0
mo=: 4 : 0
Line 50: Line 51:
*./ a mopk"1 |: __ q: m
*./ a mopk"1 |: __ q: m
)
)

The dyadic verb ''mopk'' expects a pair of prime and exponent
in the second argument. It sets up a verb ''pm'' to calculate
powers module ''p^k''. Then calculates ''&Phi;(p^k)'' as ''t'',
factorizes it again into ''q'' and ''e'', and calculates
''a^(t/(q^e))'' as ''x''. Now, it finds the least ''d'' such that subsequent application of ''pm'' yields ''1'' (this line could do with a more detailed explanation). Finally, it combines the
exponents ''q^d'' into a product.


mopk=: 4 : 0
mopk=: 4 : 0

Revision as of 12:47, 10 December 2007

Task
Multiplicative order
You are encouraged to solve this task according to the task description, using any language you may know.
This task has been clarified. Its programming examples are in need of review to ensure that they still fit the requirements of the task.


The multiplicative order of a relative to m is the least positive integer n such that a^n is 1 (modulo m). For example, the multiplicative oder of 37 relative to 1000 is 100 because 37^100 is 1 (modulo 1000), and no number smaller than 100 would do. Note that the multiplicative order is undefined if a and m are not relatively prime.

One possible algorithm that is efficient also for large numbers is the following: By the Chinese Remainder Theorem, it's enough to calculate the multiplicative order for each prime exponent p^k of m, and combine the results with the least common multiple operation. Now the order of a wrt. to p^k must divide Φ(p^k). Call this number t, and determine it's factors q^e. Since each multiple of the order will also yield 1 when used as exponent for a, it's enough to find the least d such that (q^d)*(t/(q^e)) yields 1 when used as exponent.

Implement a routine to calculate the multiplicative order along these lines. You may assume that routines to determine the factorization into prime powers are available in some library.


An analysis of the efficiency of the step in the inner loop can be found in Bach & Shallit, Algorithmic Number Theory, Volume I: Efficient Algorithms, The MIT Press, 1996:

Exercise 5.8, page 115:

Suppose you are given a prime p and a complete factorization of p-1 . Show how to compute the order of an element a in (Z/(p))* using O((lg p)4/(lg lg p)) bit operations.

Solution, page 337:

Let the prime factorization of p-1 be q1e1q2e2...qkek . We use the following observation: if x^((p-1)/qifi) = 1 (mod p) , and fi=ei or x^((p-1)/qifi+1) != 1 (mod p) , then qiei-fi|ordp x . (This follows by combining Exercises 5.1 and 2.10.) Hence it suffices to find, for each i , the exponent fi such that the condition above holds.

This can be done as follows: first compute q1e1, q2e2, ... , qkek . This can be done using O((lg p)2) bit operations. Next, compute y1=(p-1)/q1e1, ... , yk=(p-1)/qkek . This can be done using O((lg p)2) bit operations. Now, using the binary method, compute x1=ay1(mod p), ... , xk=ayk(mod p) . This can be done using O(k(lg p)3) bit operations, and k=O((lg p)/(lg lg p)) by Theorem 8.8.10. Finally, for each i , repeatedly raise xi to the qi-th power (mod p) (as many as ei-1 times), checking to see when 1 is obtained. This can be done using O((lg p)3) steps. The total cost is dominated by O(k(lg p)3) , which is O(k(lg p)4/(lg lg p)) .

J

The dyadic verb mo converts it's arguments to exact numbers a and m, executes mopk on the factorization of m, and combines the result with the least common multiple operation.

mo=: 4 : 0
 a=. x: x
 m=. x: y
 assert. 1=a+.m
 *./ a mopk"1 |: __ q: m
)

The dyadic verb mopk expects a pair of prime and exponent in the second argument. It sets up a verb pm to calculate powers module p^k. Then calculates Φ(p^k) as t, factorizes it again into q and e, and calculates a^(t/(q^e)) as x. Now, it finds the least d such that subsequent application of pm yields 1 (this line could do with a more detailed explanation). Finally, it combines the exponents q^d into a product.

mopk=: 4 : 0
 a=. x: x
 'p k'=. x: y
 pm=. (p^k)&|@^
 t=. (p-1)*p^k-1  NB. totient
 'q e'=. __ q: t
 x=. a pm t%q^e
 d=. (1<x)+x (pm i. 1:)&> (e-1) */\@$&.> q
 */q^d
)

For example:

   37 mo 1000
100
   2 mo _1+10^80x
190174169488577769580266953193403101748804183400400

Haskell

Assuming a function to calculate prime power factors,

primeFacsExp :: Integer -> [(Integer, Int)]

and another function

powerMod :: (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"

to efficiently calculate powers modulo some integral, we get

 
 multOrder a m 
   | gcd a m /= 1  = error "Arguments not coprime"
   | otherwise     = foldl1' lcm $ map (multOrder' a) $ primeFacsExp m
 
 multOrder' a (p,k) = r where
   pk = p^k
   t = (p-1)*p^(k-1) -- totient \Phi(p^k)
   r = product $ map find_qd $ primeFacsExp $ t
   find_qd (q,e) = q^d where
     x = powerMod pk a (t `div` (q^e))
     d = length $ takeWhile (/= 1) $ iterate (\y -> powerMod pk y q) x