Indices — The Discrete Logarithm
This is Lab 12 from Clint by Hugh Montgomery, edited by Codex and Elad Zelingher. All rights reserved to Hugh Montgomery.
Suppose that is a primitive root of the prime number . If then there is a number such that ; moreover, the value of is uniquely determined modulo . This is called the index of with respect to the primitive root . In symbols we write when the value of has already been specified. By way of analogy, any positive real number can be written uniquely in the form where . Thus is a discrete analogue of .
For a given prime , the program IndTab displays a table of the indices of the reduced residue classes modulo . If there are more values than can be displayed on a single page, then you may use the pagination controls to move around in the table. Initially, is the least positive primitive root of , but you are free to switch to a different primitive root. The program will prevent you from choosing a base that is not a primitive root. The program also provides a table of the powers of , which is obtained by selecting “Powers.” To return to the table of indices from the table of exponentials, select “Indices.” These tables may be used in the manner of tables of logarithms and exponentials, to find the solutions of multiplicative congruences.
For example, to find the solutions of the congruence , we take , and write . From IndTab we discover that . That is, . Hence the initial congruence may be rewritten as . This is equivalent to asserting that . From LinCon we discover that this is equivalent to . That is, , , or modulo . Returning to the IndTab program, we enter again, and then select “Powers” to switch to the table of exponentials, i.e. powers of the primitive root 5. From this table we deduce that , that , and that . Hence the desired solutions are , , and modulo . As a check, one may use the program Power to verify that .
If the actual roots of the congruence are not needed, but only the number of roots, then one may proceed more simply, using Euler's criterion (Corollary 2.38 on p. 101 of NZM) and the program Power: Since , it follows that the given congruence has exactly solutions.
Problem 1
Use the program IndTab to find the solutions of the congruence .
Problem 2
Use IndTab to find all solutions of the congruence .
Problem 3
Use IndTab in the manner above to show that the congruence has no solution. At what point in the argument does it become apparent that there is no solution? Use Theorem 2.37 of NZM to provide a simpler proof that this congruence has no solution.
Problem 4
Use IndTab to find all solutions of the congruence .
Problem 5
Use IndTab to find all such that .
Problem 6
With , use IndTab to determine the value of .
The program IndTab is restricted to because the entire table is computed at the outset, and held in active memory (RAM). We have efficient means to compute powers, and efficient means to locate the least positive primitive root , and thus we can easily compute values of as runs over any given interval. What seems to be hard is to calculate values of for a general . Indeed, methods of encryption have been proposed whose security depends on the supposition that evaluating indices is computationally difficult. This computational snag is often referred to in the literature as the problem of the discrete logarithm.
The program IndTab first constructs a list of the values (i.e., exponentials), and then uses it to form a table of the indices. Thus is found for each (mod ), but the amount of work is proportional to . A first step toward improving on this has been suggested by Shanks: Suppose that you wish to calculate . Let be a base to be described later; we want to find and so that . To this end, use the extended Euclidean algorithm (i.e., the program LinCon) to find so that . Construct a table of the values (mod ) for . Then, for , compute (mod ), and look to see if the number computed is found in the table. When it is found, we have the desired values of and , and .
When searching for a particular value of in the table, it would be very slow to inspect all values. Instead, we sort the table of values by size, into increasing order. (A useful algorithm for sorting, called HeapSort, is discussed later in this laboratory.) Then one can search for a specified value in the table by binary subdivisions. To motivate the choice of , we consider the amount of work required. The time required to construct the table is , but the time required to sort it is a little greater, . Searching by binary subdivision takes steps, and we expect that it will be necessary to conduct such searches. Thus the total amount of work is proportional to
This is minimized by taking , and then the time involved is , a little slower than proving that is prime by trial division. Thus we see that Shanks' algorithm is not very fast for big , although it represents a big improvement over .
In practice, the parameter above is constrained also by the amount of available memory. For example, the program Ind calculates by Shanks' method for ; for it takes to be the integer nearest , but for larger it takes so that the data fits into one 64K segment of memory. (Each entry of the table occupies 4 bytes, and a companion table 2 bytes each, so the tables require 60K of memory.) To witness Shanks' algorithm in action, apply IndDem with , , . Also try , , .
For more information concerning algorithms used to calculate indices see the following papers.
- D. Coppersmith, A. M. Odlyzko, R. Schroeppel, “Discrete logarithms in GF(),” Algorithmica 1 (1986), 1–15.
- D. M. Gordon, “Discrete logarithms in GF() using the number field sieve,” SIAM J. Discrete Math. 6 (1993), 124–138.
- B. A. LaMacchia, A. M. Odlyzko, “Computation of discrete logarithms in prime fields,” Des. Codes Cryptogr. 1 (1991), 47–62.
- K. S. McCurley, “The discrete logarithm problem,” Cryptology and computational number theory (Boulder, 1989), Amer. Math. Soc., Providence, 1990, pp. 49–74.
- A. M. Odlyzko, “Discrete logarithms in finite fields and their cryptographic significance,” Advances in Cryptography (Proc. 1984 EUROCRYPT Workshop), Springer-Verlag, New York, 1985, pp. 224–314.
Problem 7
Use PrimRoot to find a primitive root modulo . Use the program Ind to determine . For example, use Ind with , , and . Use this information to find all roots of the congruence .
Problem 8
The program Ind searches for a specified value among the powers of . It is essential that , but it is not necessary that be prime or that be a primitive root. Is 3 a power of 2 modulo 123456791? That is, does the congruence have a solution? Use Ind with , , and . Here the modulus is prime, but the base is not a primitive root. Note that the program returns only the least non-negative solution. The period of the solutions is if is a primitive root (mod ), but it is smaller in other cases. Find all (mod 123456790) such that . (Hint: Use the program Order to determine the order of 2 (mod 123456791).) Confirm that Ind still works when is composite by using , , and . Use , , and . What happens?
Problem 9
Assume that is prime. Use the programs GCD and Power to determine the number of roots of the congruence . (Theorem 2.37 of NZM is relevant here.) Note that you do not have any tool available to find these roots, since is so large. Such tools do exist; for example one might elaborate on the technique developed in the next laboratory. Alternatively, the polynomial can be factored quickly (mod ), for example by the method of D. G. Cantor and H. Zassenhaus, “A new algorithm for factoring polynomials over finite fields,” Math. Comp. 36 (1981), 587–592.
We now consider the problem of sorting numbers by size. While not a number-theoretic problem, we find it useful (as above) to be able to sort numbers with reasonable efficiency. Suppose that are distinct numbers that we want to sort into increasing order. First, in Bubble Sort, one passes repeatedly through the list, transposing pairs that are found to be out of order, until a pass discloses no transpositions. This takes time , which is terrible! Never use Bubble Sort!
So how much faster can we hope for? We derive a lower bound. When two elements and are compared, the set of all possible orderings is divided into two classes, those with and those with . After such comparisons have been made, the set of all possible orderings has been divided into at most classes. If then there is a class containing two different orderings. Consequently, if the original ordering of our is one of these orderings, then we have not yet distinguished it from all other possible orderings, and at least one more comparison is necessary. Thus for any sorting algorithm there is an ordering of the that gives rise to more than comparisons. Since , the worst-case running time of any sorting algorithm is . This lower bound is of the correct order of magnitude, since we have algorithms that run in time.
Among the possible methods that one might consider, we confine our attention to HeapSort, invented by J. W. J. Williams. This method runs in time, with the worst case only about 20% longer than the average. It is very easy to understand and to program, and requires little memory. In HeapSort, we think of the as forming a binary tree, in which has subordinates and , as long as these indices do not exceed . Conversely, if then reports to its superior, . The situation for is depicted below:
If is smaller than one of its underlings then we exchange with the larger of and . We repeatedly demote a particular entry until it majorizes its subordinates. (Executives above their level of competence are demoted.) We begin at the bottom of the table (high indices), and work up. Thus in the example above, we would compare with , and exchange them if is the smaller. Then we compare with to determine which is the larger, and then compare that one with . We demote if one of the numbers under it is larger. We continue with this, until and whenever the indices lie between 1 and . Such a configuration we call a heap.
Once the heap has been formed, it is clear that is the largest number in the entire collection. We swap with . This destroys the heap property, so we demote the new until it is restored. At this point we have a heap of numbers, and is ignored at the bottom. The new entry is the largest member in the heap (second largest, overall), so we exchange and . At this point both and have reached their final resting places. We demote the new until we again have a heap, and then again the top of the heap is retired. Continuing in this manner, with successively smaller heaps, we eventually have no heap left, and .
For extremely large collections (such as the Manhattan telephone directory), it is important to sort as quickly as possible. In such cases it may be worth using the more complicated QuickSort algorithm. For a detailed discussion of sorting, see D. E. Knuth, The Art of Computer Programming, Vol. 3: Sorting and Searching, Addison-Wesley, Reading, 1973. In particular, HeapSort is described on pp. 145–149, 153–158.
Problem 10
The program HSortDem demonstrates the HeapSort algorithm. Choose the number of integers to be sorted, and witness the process. How does the number of comparisons compare with the lower bound derived above?