source: git/ntl/doc/tour-ex1.html @ 199b5c

fieker-DuValspielwiese
Last change on this file since 199b5c was 2cfffe, checked in by Hans Schönemann <hannes@…>, 22 years ago
This commit was generated by cvs2svn to compensate for changes in r6316, which included commits to RCS files with non-trunk default branches. git-svn-id: file:///usr/local/Singular/svn/trunk@6317 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 10.7 KB
Line 
1<html>
2<head>
3<title>
4A Tour of NTL: Examples: Big Integers </title>
5</head>
6
7<body bgcolor="#fff9e6">
8
9<center>
10<img src="arrow1.gif" alt="[Previous]" align=bottom>
11 <a href="tour-examples.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a> 
12<a href="tour-ex2.html"> <img src="arrow3.gif" alt="[Next]" align=bottom></a>
13</center>
14
15<h1> 
16<p align=center>
17A Tour of NTL: Examples: Big Integers
18</p>
19</h1>
20
21<p> <hr>  <p>
22
23The first example makes use of the class
24<tt>ZZ</tt>,
25which
26represents "big integers": signed, arbitrary length integers.
27This program reads two big integers <tt>a</tt> and <tt>b</tt>,
28and prints <tt>(a+1)*(b+1)</tt>.
29
30<p>
31<pre>
32#include &lt;NTL/ZZ.h&gt;
33
34int main()
35{
36   ZZ a, b, c;
37
38   cin &gt;&gt; a;
39   cin &gt;&gt; b;
40   c = (a+1)*(b+1);
41   cout &lt;&lt; c &lt;&lt; "\n";
42}
43</pre>
44
45<p>
46
47This program declares three variables <tt>a</tt>, <tt>b</tt>,
48and <tt>c</tt> of type <tt>ZZ</tt>.
49The values <tt>a</tt> and <tt>b</tt> are read from standard input.
50The value <tt>c</tt> is then computed as <tt>(a+1)*(b+1)</tt>.
51Finally, the value of <tt>c</tt> is printed to the standard output.
52
53<p>
54Note that one can compute with <tt>ZZ</tt>s much as with ordinary
55<tt>int</tt>s, in that most of the standard arithmetic and
56assignment operators can be used in a direct and natural way.
57The <tt>C++</tt> compiler and the NTL library routines
58automatically take care
59of all the bookkeeping involved
60with memory management and temporary objects.
61
62<p> <hr> <p>
63
64Here's a program that reads a list of integers from standard
65input and prints the sum of their squares.
66
67<p>
68<pre>
69#include &lt;NTL/ZZ.h&gt;
70
71int main()
72{
73   ZZ acc, val;
74
75   acc = 0;
76   while (SkipWhiteSpace(cin)) {
77      cin &gt;&gt; val;
78      acc += val*val;
79   }
80
81   cout &lt;&lt; acc &lt;&lt; "\n";
82}
83</pre>
84
85<p>
86
87The function <tt>SkipWhiteSpace</tt> is defined by NTL.
88It skips over white space, and returns 1 if there is something
89following it.
90This function is useful, because
91NTL's input operators raise an error if an input
92is missing or ill-formed.
93This is different from the standard I/O library,
94which does not raise an error.
95Personally, I find that not raising an error, or at least
96an exception, is a bad idea, since the caller of the I/O
97routine must constantly check the status of the input
98stream.
99
100
101
102
103<p>
104<hr>
105<p>
106
107Here's a simple modular exponentiation routine for computing
108<tt>a^e mod n</tt>.
109NTL already provides a more sophisticated one, though.
110
111<p>
112<pre>
113ZZ PowerMod(const ZZ&amp; a, const ZZ&amp; e, const ZZ&amp; n)
114{
115   if (e == 0) return to_ZZ(1);
116
117   long k = NumBits(e);
118
119   ZZ res;
120   res = 1;
121
122   for (long i = k-1; i &gt;= 0; i--) {
123      res = (res*res) % n;
124      if (bit(e, i) == 1) res = (res*a) % n;
125   }
126
127   if (e &lt; 0)
128      return InvMod(res, n);
129   else
130      return res;
131}
132</pre>
133<p>
134
135Note that as an alternative, we could implement the inner loop
136as follows:
137
138<pre>
139   res = SqrMod(res, n);
140   if (bit(e, i) == 1) res = MulMod(res, a, n);
141</pre>
142
143We could also write this as:
144
145<pre>
146   SqrMod(res, res, n);
147   if (bit(e, i) == 1) MulMod(res, res, a, n);
148</pre>
149
150This illustrates an important point about NTL's programming interface.
151For every function in NTL, there is a procedural version that
152stores its result in its first argument.
153The reason for using the procedural variant is efficieny:
154on every iteration through the above loop, the functional form
155of <tt>SqrMod</tt> will cause a temporary <tt>ZZ</tt> object to
156be created and destroyed, whereas the procedural version
157will not create any temporaries.
158Where performance is critical, the procedural version
159is to be preferred.
160Although it is usually silly to get too worked up about performance,
161it may be reasonable to argue that modular exponentiation
162is an important enough routine that it should be as fast as possible.
163
164<p>
165
166Note that when the functional version of a function
167can be naturally named with an operator, this is done.
168So for example, NTL provides a 3-argument <tt>mul</tt> routine
169for <tt>ZZ</tt> multiplication, and a functional version
170whose name is <tt>operator *</tt>, and not <tt>mul</tt>.
171
172<p>
173
174While we are taking about temporaries, consider the first version
175of the inner loop.
176Execution of the statement
177<pre>
178   res = (res*res) % n;
179</pre>
180will result in the creation of two temporary objects,
181one for the product, and one for the result of the mod operation,
182whose value is copied into <tt>res</tt>.
183Of course, the compiler automatically generates the code for
184cleaning up temporaries and other local objects at the right time.
185The programmer does not have to worry about this.
186
187
188<p> <hr> <p>
189
190This example is a bit more interesting.
191The following program prompts the user for an input,
192and applies a simple probabilistic primality test.
193Note that NTL already provides a slightly more sophisticated
194prime test.
195
196<p>
197<pre>
198#include &lt;NTL/ZZ.h&gt;
199
200long witness(const ZZ&amp; n, const ZZ&amp; x)
201{
202   ZZ m, y, z;
203   long j, k;
204
205   if (x == 0) return 0;
206
207   // compute m, k such that n-1 = 2^k * m, m odd:
208
209   k = 1;
210   m = n/2;
211   while (m % 2 == 0) {
212      k++;
213      m /= 2;
214   }
215
216   z = PowerMod(x, m, n); // z = x^m % n
217   if (z == 1) return 0;
218
219   j = 0;
220   do {
221      y = z;
222      z = (y*y) % n;
223      j++;
224   } while (j &lt; k &amp;&amp; z != 1);
225
226   return z != 1 || y != n-1;
227}
228
229
230long PrimeTest(const ZZ&amp; n, long t)
231{
232   if (n &lt;= 1) return 0;
233
234   // first, perform trial division by primes up to 2000
235
236   PrimeSeq s;  // a class for quickly generating primes in sequence
237   long p;
238
239   p = s.next();  // first prime is always 2
240   while (p && p < 2000) {
241      if ((n % p) == 0) return (n == p);
242      p = s.next(); 
243   }
244
245   // second, perform t Miller-Rabin tests
246
247   ZZ x;
248   long i;
249
250   for (i = 0; i &lt; t; i++) {
251      x = RandomBnd(n); // random number between 0 and n-1
252
253      if (witness(n, x)) 
254         return 0;
255   }
256
257   return 1;
258}
259
260int main()
261{
262   ZZ n;
263
264   cout &lt;&lt; "n: ";
265   cin &gt;&gt; n;
266
267   if (PrimeTest(n, 10))
268      cout &lt;&lt; n &lt;&lt; " is probably prime\n";
269   else
270      cout &lt;&lt; n &lt;&lt; " is composite\n";
271}
272</pre>
273<p>
274
275Note that in NTL, there are typically a number of ways to
276compute the same thing.
277For example, consider the computation of <tt>m</tt> and <tt>k</tt>
278in function <tt>witness</tt>.
279We could have written it thusly:
280
281<pre>
282   k = 1;
283   m = n &gt;&gt; 1;
284   while (!IsOdd(m)) {
285      k++;
286      m &gt;&gt;= 1;
287   }
288</pre>
289
290It turns out that this is actually not significantly more
291efficient than the original version, because the implementation
292optimizes multiplication and division by 2.
293
294<p>
295
296The following is more efficient:
297
298<pre>
299   k = 1;
300   while (bit(n, k) == 0) k++;
301   m = n &gt;&gt; k;
302</pre>
303
304As it happens, there is a built-in NTL routine that does just what we want:
305
306<pre>
307   m = n-1;
308   k = MakeOdd(m);
309</pre>
310
311
312
313<p> <hr> <p>
314
315Having seen a number of examples involving <tt>ZZ</tt>s,
316let's look at the <tt>ZZ</tt> interface in a bit more detail.
317
318<p>
319
320<b>
321Constructors, assignment, and conversions
322</b>
323
324<p>
325
326When you declare an object of type <tt>ZZ</tt>,
327the default constructor initializes to the value <tt>0</tt>.
328As we have already seen, there is an assignment operator that
329allows one to copy the value of one <tt>ZZ</tt> to another.
330Note that these copies (like almost all copies in NTL) are "deep",
331i.e., the actual data is copied, and not just a pointer.
332Of course, if the amount of space allocated by the destination
333of the assignment is insufficient to hold the value of the source,
334space is automatically re-allocated.
335
336<p>
337One can also assign a value of type <tt>long</tt> to a <tt>ZZ</tt>:
338<pre>
339   ZZ x;
340   x = 1;
341</pre>
342
343<p>
344Note that one cannot write
345<pre>
346   ZZ x = 1;  // error
347</pre>
348to initialize a <tt>ZZ</tt>.
349As a design principle, NTL avoids implicit conversions, and unfortunately,
350the only way to allow initializations like this in <tt>C++</tt>
351is to define an implicit conversion operator.
352Instead, one could write
353<pre>
354   ZZ x = to_ZZ(1);
355</pre>
356This is an example of one of NTL's conversion routines.
357For very large constants, one can write:
358<pre>
359   ZZ x = to_ZZ("99999999999999999999");
360</pre>
361These examples illustrate conversion rountines in their
362functional forms.
363The corresponding procedural forms are all called <tt>conv</tt>, e.g.,
364<pre>
365   ZZ x;
366   conv(x, 1);
367   conv(x, "99999999999999999999");
368</pre>
369
370<p>
371<b>
372Functionality
373</b>
374<p>
375
376All of the basic arithmetic operators are supported,
377including comparison, arithmetic, shift, and bit-wise logical operations.
378One can mix <tt>ZZ</tt>s and <tt>long</tt>s in any expresion in
379a natural way.
380As was already mentioned, NTL does not support implicit type conversion;
381rather, for basic operations, it simply overloads the operators
382or functions in a way to achieve a kind of "promotion logic":
383if one input is a <tt>ZZ</tt> and the other is a <tt>long</tt>
384(or something that implicitly converts to a <tt>long</tt>, like
385an <tt>int</tt>), the <tt>long</tt> input is effectively converted
386to a <tt>ZZ</tt>.
387Moreover, wherever possible, the implementation does this
388as efficiently as possible, and usually avoids the creation
389of a temporary <tt>ZZ</tt>.
390
391<p>
392There are also procedural versions for all the basic arithmetic
393operations:
394<pre>
395   add, sub, negate, mul, sqr, div, rem, DivRem,
396   LeftShift, RightShift,
397   bit_and, bit_or, bit_xor
398</pre>
399
400<p>
401There are many other routines.
402Here is a brief summary:
403<ul>
404<li>
405<tt>GCD</tt> -- computes greatest common divisor of two integers
406<li>
407<tt>XGCD</tt> -- extended Euclidean algorithm
408<li>
409<tt>AddMod</tt>, <tt>SubMod</tt>, <tt>NegateMod</tt>,
410<tt>MulMod</tt>, <tt>SqrMod</tt>, <tt>InvMod</tt>,
411<tt>PowerMod</tt> -- routines for modular arithmetic,
412including inversion and exponentiation
413<li>
414<tt>NumBits</tt> -- length of binary representation
415<li>
416<tt>bit</tt> -- extract a bit
417<li>
418<tt>ZZFromBytes</tt>, <tt>BytesFromZZ</tt> --
419convert between octet strings and <tt>ZZ</tt>s
420<li>
421<tt>RandomBnd</tt>, <tt>RandomBits</tt>, <tt>RandomLen</tt> --
422routines for generating pseudo-random numbers
423<li>
424<tt>GenPrime</tt>, <tt>ProbPrime</tt> -- routines for generating primes
425and testing primality
426<li>
427<tt>power</tt> -- (non-modular) exponentiation
428<li>
429<tt>SqrRoot</tt> -- integer part of square root
430<li>
431<tt>Jacobi</tt>, <tt>SqrRootMod</tt> -- Jacobi symbol and modular
432square root
433</ul>
434
435<p>
436Most of these functions also have pure <tt>long</tt> versions as
437well, and as usual, there are both functional and procedural
438variants.
439
440<p>
441There are other functions as well.
442See <a href="ZZ.txt"><tt>ZZ.txt</tt></a> for complete details.
443Also see <a href="tools.txt"><tt>tools.txt</tt></a> for some basic
444services provided by NTL.
445
446
447<p>
448<center>
449<img src="arrow1.gif" alt="[Previous]" align=bottom>
450 <a href="tour-examples.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a> 
451<a href="tour-ex2.html"> <img src="arrow3.gif" alt="[Next]" align=bottom></a>
452</center>
453
454</body>
455</html>
Note: See TracBrowser for help on using the repository browser.