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