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

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