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

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