Multiplicative order: Difference between revisions

From Rosetta Code
Content added Content deleted
(Clarified task; added Haskell example; removed Java example; added notes to J example)
(Description from Bach & Shallit)
Line 2: Line 2:
{{clarified-review}}
{{clarified-review}}


The '''multiplicative order''' of ''a'' relative to ''m'' is the least positive integer ''n'' such that ''a^n'' is 1 (modulo ''m'').
<p>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.
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
Bach & Shallit, <i>Algorithmic Number Theory, Volume I: Efficient Algorithms</i>, The MIT Press, 1996.</p>
Note that the multiplicative order is undefined if ''a'' and ''m'' are not relatively prime.


<p>Exercise 5.8, page 115:</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.


<p>Suppose you are given a prime<tt> p </tt>and a complete factorization
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.
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
operations.</p>


<p>Solution, page 337:</p>
=={{header|J}}==


<p>Let the prime factorization of<tt> p-1 </tt>
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.
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>
and<tt> fi=ei </tt>or<tt> x^((p-1)/qi<sup>fi+1</sup>) != 1 (mod p)</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.)
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>, ... ,
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>
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>
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.
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>
which is<tt> O(k(lg p)<sup>4</sup>/(lg lg p))</tt> .


=={{header|J}}==


mo=: 4 : 0
mo=: 4 : 0
Line 22: Line 50:
*./ 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 06:21, 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. An algorithm 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 qei-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

mo=: 4 : 0
 a=. x: x
 m=. x: y
 assert. 1=a+.m
 *./ a mopk"1 |: __ q: m
)
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