Upload Tizen:Base source
[external/gmp.git] / tests / rand / gen.c
1 /* gen.c -- Generate pseudorandom numbers.
2
3 Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20 /* Examples:
21
22   $ gen 10
23 10 integers 0 <= X < 2^32 generated by mpz_urandomb()
24
25   $ gen -f mpf_urandomb 10
26 10 real numbers 0 <= X < 1
27
28   $ gen -z 127 10
29 10 integers 0 <= X < 2^127
30
31   $ gen -f mpf_urandomb -x .9,1 10
32 10 real numbers 0 <= X < .9
33
34   $ gen -s 1 10
35 10 integers, sequence seeded with 1
36
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #include <errno.h>
44 #include <time.h>
45 #include <string.h>
46
47 #if !HAVE_DECL_OPTARG
48 extern char *optarg;
49 extern int optind, opterr;
50 #endif
51
52 #include "gmp.h"
53 #include "gmp-impl.h"
54
55 int main (argc, argv)
56      int argc;
57      char *argv[];
58 {
59   const char usage[] =
60     "usage: gen [-bhpq] [-a n] [-c a,c,m2exp] [-C a,c,m] [-f func] [-g alg] [-m n] [-s n] " \
61     "[-x f,t] [-z n] [n]\n" \
62     "  n        number of random numbers to generate\n" \
63     "  -a n     ASCII output in radix n (default, with n=10)\n" \
64     "  -b       binary output\n" \
65     "  -c a,c,m2exp use supplied LC scheme\n" \
66     "  -f func  random function, one of\n" \
67     "           mpz_urandomb (default), mpz_urandomm, mpf_urandomb, rand, random\n" \
68     "  -g alg   algorithm, one of mt (default), lc\n" \
69     "  -h       print this text and exit\n" \
70     "  -m n     maximum size of generated number plus 1 (0<= X < n) for mpz_urandomm\n" \
71     "  -p       print used seed on stderr\n" \
72     "  -q       quiet, no output\n" \
73     "  -s n     initial seed (default: output from time(3))\n" \
74     "  -x f,t   exclude all numbers f <= x <= t\n" \
75     "  -z n     size in bits of generated numbers (0<= X <2^n) (default 32)\n" \
76     "";
77
78   unsigned long int f;
79   unsigned long int n = 0;
80   unsigned long int seed;
81   unsigned long int m2exp = 0;
82   unsigned int size = 32;
83   int seed_from_user = 0;
84   int ascout = 1, binout = 0, printseed = 0;
85   int output_radix = 10;
86   int lc_scheme_from_user = 0;
87   int quiet_flag = 0;
88   mpz_t z_seed;
89   mpz_t z1;
90   mpf_t f1;
91   gmp_randstate_t rstate;
92   int c, i;
93   double drand;
94   long lrand;
95   int do_exclude = 0;
96   mpf_t f_xf, f_xt;             /* numbers to exclude from sequence */
97   char *str_xf, *str_xt;        /* numbers to exclude from sequence */
98   char *str_a, *str_adder, *str_m;
99   mpz_t z_a, z_m, z_mmax;
100   unsigned long int ul_adder;
101
102   enum
103   {
104     RFUNC_mpz_urandomb = 0,
105     RFUNC_mpz_urandomm,
106     RFUNC_mpf_urandomb,
107     RFUNC_rand,
108     RFUNC_random,
109   } rfunc = RFUNC_mpz_urandomb;
110   char *rfunc_str[] =  { "mpz_urandomb", "mpz_urandomm", "mpf_urandomb",
111                          "rand", "random" };
112   enum
113   {
114     RNG_MT = 0,
115     RNG_LC
116   };
117   gmp_randalg_t ralg = RNG_MT;
118   /* Texts for the algorithms.  The index of each must match the
119      corresponding algorithm in the enum above.  */
120   char *ralg_str[] = { "mt", "lc" };
121
122   mpf_init (f_xf);
123   mpf_init (f_xt);
124   mpf_init (f1);
125   mpz_init (z1);
126   mpz_init (z_seed);
127   mpz_init_set_ui (z_mmax, 0);
128
129
130   while ((c = getopt (argc, argv, "a:bc:f:g:hm:n:pqs:z:x:")) != -1)
131     switch (c)
132       {
133       case 'a':
134         ascout = 1;
135         binout = 0;
136         output_radix = atoi (optarg);
137         break;
138
139       case 'b':
140         ascout = 0;
141         binout = 1;
142         break;
143
144       case 'c':                 /* User supplied LC scheme: a,c,m2exp */
145         if (NULL == (str_a = strtok (optarg, ","))
146             || NULL == (str_adder = strtok (NULL, ","))
147             || NULL == (str_m = strtok (NULL, ",")))
148           {
149             fprintf (stderr, "gen: bad LC scheme parameters: %s\n", optarg);
150             exit (1);
151           }
152 #ifdef HAVE_STRTOUL
153         ul_adder = strtoul (str_adder, NULL, 0);
154 #elif HAVE_STRTOL
155         ul_adder = (unsigned long int) strtol (str_adder, NULL, 0);
156 #else
157         ul_adder = (unsigned long int) atoi (str_adder);
158 #endif
159
160         if (mpz_init_set_str (z_a, str_a, 0))
161           {
162             fprintf (stderr, "gen: bad LC scheme parameter `a': %s\n", str_a);
163             exit (1);
164           }
165         if (ULONG_MAX == ul_adder)
166           {
167             fprintf (stderr, "gen: bad LC scheme parameter `c': %s\n",
168                      str_adder);
169             exit (1);
170           }
171         m2exp = atol (str_m);
172
173         lc_scheme_from_user = 1;
174         break;
175
176
177       case 'f':
178         rfunc = -1;
179         for (f = 0; f < sizeof (rfunc_str) / sizeof (*rfunc_str); f++)
180             if (!strcmp (optarg, rfunc_str[f]))
181               {
182                 rfunc = f;
183                 break;
184               }
185         if (rfunc == -1)
186           {
187             fputs (usage, stderr);
188             exit (1);
189           }
190         break;
191
192       case 'g':                 /* algorithm */
193         ralg = -1;
194         for (f = 0; f < sizeof (ralg_str) / sizeof (*ralg_str); f++)
195             if (!strcmp (optarg, ralg_str[f]))
196               {
197                 ralg = f;
198                 break;
199               }
200         if (ralg == -1)
201           {
202             fputs (usage, stderr);
203             exit (1);
204           }
205         break;
206
207       case 'm':                 /* max for mpz_urandomm() */
208         if (mpz_set_str (z_mmax, optarg, 0))
209           {
210             fprintf (stderr, "gen: bad max value: %s\n", optarg);
211             exit (1);
212           }
213         break;
214
215       case 'p':                 /* print seed on stderr */
216         printseed = 1;
217         break;
218
219       case 'q':                 /* quiet */
220         quiet_flag = 1;
221         break;
222
223       case 's':                 /* user provided seed */
224         if (mpz_set_str (z_seed, optarg, 0))
225           {
226             fprintf (stderr, "gen: bad seed argument %s\n", optarg);
227             exit (1);
228           }
229         seed_from_user = 1;
230         break;
231
232       case 'z':
233         size = atoi (optarg);
234         if (size < 1)
235           {
236             fprintf (stderr, "gen: bad size argument (-z %u)\n", size);
237             exit (1);
238           }
239         break;
240
241       case 'x':                 /* Exclude. from,to */
242         str_xf = optarg;
243         str_xt = strchr (optarg, ',');
244         if (NULL == str_xt)
245           {
246             fprintf (stderr, "gen: bad exclusion parameters: %s\n", optarg);
247             exit (1);
248           }
249         *str_xt++ = '\0';
250         do_exclude = 1;
251         break;
252
253       case 'h':
254       case '?':
255       default:
256         fputs (usage, stderr);
257         exit (1);
258       }
259   argc -= optind;
260   argv += optind;
261
262   if (! seed_from_user)
263     mpz_set_ui (z_seed, (unsigned long int) time (NULL));
264   seed = mpz_get_ui (z_seed);
265   if (printseed)
266     {
267       fprintf (stderr, "gen: seed used: ");
268       mpz_out_str (stderr, output_radix, z_seed);
269       fprintf (stderr, "\n");
270     }
271
272   mpf_set_prec (f1, size);
273
274   /* init random state and plant seed */
275   switch (rfunc)
276     {
277     case RFUNC_mpf_urandomb:
278 #if 0
279       /* Don't init a too small generator.  */
280       size = PREC (f1) * GMP_LIMB_BITS;
281       /* Fall through.  */
282 #endif
283     case RFUNC_mpz_urandomb:
284     case RFUNC_mpz_urandomm:
285       switch (ralg)
286         {
287         case RNG_MT:
288           gmp_randinit_mt (rstate);
289           break;
290
291         case RNG_LC:
292           if (! lc_scheme_from_user)
293             gmp_randinit_lc_2exp_size (rstate, MIN (128, size));
294           else
295             gmp_randinit_lc_2exp (rstate, z_a, ul_adder, m2exp);
296           break;
297
298         default:
299           fprintf (stderr, "gen: unsupported algorithm\n");
300           exit (1);
301         }
302
303       gmp_randseed (rstate, z_seed);
304       break;
305
306     case RFUNC_rand:
307       srand (seed);
308       break;
309
310     case RFUNC_random:
311 #ifdef __FreeBSD__              /* FIXME */
312       if (seed_from_user)
313         srandom (seed);
314       else
315         srandomdev ();
316 #else
317       fprintf (stderr, "gen: unsupported algorithm\n");
318 #endif
319       break;
320
321     default:
322       fprintf (stderr, "gen: random function not implemented\n");
323       exit (1);
324     }
325
326   /* set up excludes */
327   if (do_exclude)
328     switch (rfunc)
329       {
330       case RFUNC_mpf_urandomb:
331
332         if (mpf_set_str (f_xf, str_xf, 10) ||
333             mpf_set_str (f_xt, str_xt, 10))
334           {
335             fprintf (stderr, "gen: bad exclusion-from (\"%s\") " \
336                      "or exclusion-to (\"%s\") string.  no exclusion done.\n",
337                      str_xf, str_xt);
338             do_exclude = 0;
339           }
340         break;
341
342       default:
343         fprintf (stderr, "gen: exclusion not implemented for chosen " \
344                  "randomization function.  all numbers included in sequence.\n");
345       }
346
347   /* generate and print */
348   if (argc > 0)
349     {
350 #if HAVE_STRTOUL
351       n = strtoul (argv[0], (char **) NULL, 10);
352 #elif HAVE_STRTOL
353       n = (unsigned long int) strtol (argv[0], (char **) NULL, 10);
354 #else
355       n = (unsigned long int) atoi (argv[0]);
356 #endif
357     }
358
359   for (f = 0; n == 0 || f < n; f++)
360     {
361       switch (rfunc)
362         {
363         case RFUNC_mpz_urandomb:
364           mpz_urandomb (z1, rstate, size);
365           if (quiet_flag)
366             break;
367           if (binout)
368             {
369               /*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/
370               fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n");
371               exit (1);
372             }
373           else
374             {
375               mpz_out_str (stdout, output_radix, z1);
376               puts ("");
377             }
378           break;
379
380         case RFUNC_mpz_urandomm:
381           mpz_urandomm (z1, rstate, z_mmax);
382           if (quiet_flag)
383             break;
384           if (binout)
385             {
386               /*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/
387               fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n");
388               exit (1);
389             }
390           else
391             {
392               mpz_out_str (stdout, output_radix, z1);
393               puts ("");
394             }
395           break;
396
397         case RFUNC_mpf_urandomb:
398           mpf_urandomb (f1, rstate, size);
399           if (do_exclude)
400             if (mpf_cmp (f1, f_xf) >= 0 && mpf_cmp (f1, f_xt) <= 0)
401                 break;
402           if (quiet_flag)
403             break;
404           if (binout)
405             {
406               fprintf (stderr, "gen: binary output for floating point numbers "\
407                        "not implemented\n");
408               exit (1);
409             }
410           else
411             {
412               mpf_out_str (stdout, output_radix, 0, f1);
413               puts ("");
414             }
415           break;
416
417         case RFUNC_rand:
418           i = rand ();
419 #ifdef FLOAT_OUTPUT
420           if (i)
421             drand = (double) i / (double) RAND_MAX;
422           else
423             drand = 0.0;
424           if (quiet_flag)
425             break;
426           if (binout)
427             fwrite (&drand, sizeof (drand), 1, stdout);
428           else
429             printf ("%e\n", drand);
430 #else
431           if (quiet_flag)
432             break;
433           if (binout)
434             fwrite (&i, sizeof (i), 1, stdout);
435           else
436             printf ("%d\n", i);
437 #endif
438           break;
439
440         case RFUNC_random:
441           lrand = random ();
442           if (lrand)
443             drand = (double) lrand / (double) 0x7fffffff;
444           else
445             drand = 0;
446           if (quiet_flag)
447             break;
448           if (binout)
449             fwrite (&drand, sizeof (drand), 1, stdout);
450           else
451             printf ("%e\n", drand);
452           break;
453
454         default:
455           fprintf (stderr, "gen: random function not implemented\n");
456           exit (1);
457         }
458
459     }
460
461   /* clean up */
462   switch (rfunc)
463     {
464     case RFUNC_mpz_urandomb:
465     case RFUNC_mpf_urandomb:
466       gmp_randclear (rstate);
467       break;
468     default:
469       break;
470     }
471   mpf_clear (f1);
472   mpf_clear (f_xf);
473   mpf_clear (f_xt);
474   mpz_clear (z1);
475   mpz_clear (z_seed);
476
477   return 0;
478 }
479
480 static void *debug_dummyz = mpz_dump;
481 static void *debug_dummyf = mpf_dump;