/* gen.c -- Generate pseudorandom numbers. Copyright 1999, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ /* Examples: $ gen 10 10 integers 0 <= X < 2^32 generated by mpz_urandomb() $ gen -f mpf_urandomb 10 10 real numbers 0 <= X < 1 $ gen -z 127 10 10 integers 0 <= X < 2^127 $ gen -f mpf_urandomb -x .9,1 10 10 real numbers 0 <= X < .9 $ gen -s 1 10 10 integers, sequence seeded with 1 */ #include #include #include #include #include #include #include #if !HAVE_DECL_OPTARG extern char *optarg; extern int optind, opterr; #endif #include "gmp.h" #include "gmp-impl.h" int main (argc, argv) int argc; char *argv[]; { const char usage[] = "usage: gen [-bhpq] [-a n] [-c a,c,m2exp] [-C a,c,m] [-f func] [-g alg] [-m n] [-s n] " \ "[-x f,t] [-z n] [n]\n" \ " n number of random numbers to generate\n" \ " -a n ASCII output in radix n (default, with n=10)\n" \ " -b binary output\n" \ " -c a,c,m2exp use supplied LC scheme\n" \ " -f func random function, one of\n" \ " mpz_urandomb (default), mpz_urandomm, mpf_urandomb, rand, random\n" \ " -g alg algorithm, one of mt (default), lc\n" \ " -h print this text and exit\n" \ " -m n maximum size of generated number plus 1 (0<= X < n) for mpz_urandomm\n" \ " -p print used seed on stderr\n" \ " -q quiet, no output\n" \ " -s n initial seed (default: output from time(3))\n" \ " -x f,t exclude all numbers f <= x <= t\n" \ " -z n size in bits of generated numbers (0<= X <2^n) (default 32)\n" \ ""; unsigned long int f; unsigned long int n = 0; unsigned long int seed; unsigned long int m2exp = 0; unsigned int size = 32; int seed_from_user = 0; int ascout = 1, binout = 0, printseed = 0; int output_radix = 10; int lc_scheme_from_user = 0; int quiet_flag = 0; mpz_t z_seed; mpz_t z1; mpf_t f1; gmp_randstate_t rstate; int c, i; double drand; long lrand; int do_exclude = 0; mpf_t f_xf, f_xt; /* numbers to exclude from sequence */ char *str_xf, *str_xt; /* numbers to exclude from sequence */ char *str_a, *str_adder, *str_m; mpz_t z_a, z_m, z_mmax; unsigned long int ul_adder; enum { RFUNC_mpz_urandomb = 0, RFUNC_mpz_urandomm, RFUNC_mpf_urandomb, RFUNC_rand, RFUNC_random, } rfunc = RFUNC_mpz_urandomb; char *rfunc_str[] = { "mpz_urandomb", "mpz_urandomm", "mpf_urandomb", "rand", "random" }; enum { RNG_MT = 0, RNG_LC }; gmp_randalg_t ralg = RNG_MT; /* Texts for the algorithms. The index of each must match the corresponding algorithm in the enum above. */ char *ralg_str[] = { "mt", "lc" }; mpf_init (f_xf); mpf_init (f_xt); mpf_init (f1); mpz_init (z1); mpz_init (z_seed); mpz_init_set_ui (z_mmax, 0); while ((c = getopt (argc, argv, "a:bc:f:g:hm:n:pqs:z:x:")) != -1) switch (c) { case 'a': ascout = 1; binout = 0; output_radix = atoi (optarg); break; case 'b': ascout = 0; binout = 1; break; case 'c': /* User supplied LC scheme: a,c,m2exp */ if (NULL == (str_a = strtok (optarg, ",")) || NULL == (str_adder = strtok (NULL, ",")) || NULL == (str_m = strtok (NULL, ","))) { fprintf (stderr, "gen: bad LC scheme parameters: %s\n", optarg); exit (1); } #ifdef HAVE_STRTOUL ul_adder = strtoul (str_adder, NULL, 0); #elif HAVE_STRTOL ul_adder = (unsigned long int) strtol (str_adder, NULL, 0); #else ul_adder = (unsigned long int) atoi (str_adder); #endif if (mpz_init_set_str (z_a, str_a, 0)) { fprintf (stderr, "gen: bad LC scheme parameter `a': %s\n", str_a); exit (1); } if (ULONG_MAX == ul_adder) { fprintf (stderr, "gen: bad LC scheme parameter `c': %s\n", str_adder); exit (1); } m2exp = atol (str_m); lc_scheme_from_user = 1; break; case 'f': rfunc = -1; for (f = 0; f < sizeof (rfunc_str) / sizeof (*rfunc_str); f++) if (!strcmp (optarg, rfunc_str[f])) { rfunc = f; break; } if (rfunc == -1) { fputs (usage, stderr); exit (1); } break; case 'g': /* algorithm */ ralg = -1; for (f = 0; f < sizeof (ralg_str) / sizeof (*ralg_str); f++) if (!strcmp (optarg, ralg_str[f])) { ralg = f; break; } if (ralg == -1) { fputs (usage, stderr); exit (1); } break; case 'm': /* max for mpz_urandomm() */ if (mpz_set_str (z_mmax, optarg, 0)) { fprintf (stderr, "gen: bad max value: %s\n", optarg); exit (1); } break; case 'p': /* print seed on stderr */ printseed = 1; break; case 'q': /* quiet */ quiet_flag = 1; break; case 's': /* user provided seed */ if (mpz_set_str (z_seed, optarg, 0)) { fprintf (stderr, "gen: bad seed argument %s\n", optarg); exit (1); } seed_from_user = 1; break; case 'z': size = atoi (optarg); if (size < 1) { fprintf (stderr, "gen: bad size argument (-z %u)\n", size); exit (1); } break; case 'x': /* Exclude. from,to */ str_xf = optarg; str_xt = strchr (optarg, ','); if (NULL == str_xt) { fprintf (stderr, "gen: bad exclusion parameters: %s\n", optarg); exit (1); } *str_xt++ = '\0'; do_exclude = 1; break; case 'h': case '?': default: fputs (usage, stderr); exit (1); } argc -= optind; argv += optind; if (! seed_from_user) mpz_set_ui (z_seed, (unsigned long int) time (NULL)); seed = mpz_get_ui (z_seed); if (printseed) { fprintf (stderr, "gen: seed used: "); mpz_out_str (stderr, output_radix, z_seed); fprintf (stderr, "\n"); } mpf_set_prec (f1, size); /* init random state and plant seed */ switch (rfunc) { case RFUNC_mpf_urandomb: #if 0 /* Don't init a too small generator. */ size = PREC (f1) * GMP_LIMB_BITS; /* Fall through. */ #endif case RFUNC_mpz_urandomb: case RFUNC_mpz_urandomm: switch (ralg) { case RNG_MT: gmp_randinit_mt (rstate); break; case RNG_LC: if (! lc_scheme_from_user) gmp_randinit_lc_2exp_size (rstate, MIN (128, size)); else gmp_randinit_lc_2exp (rstate, z_a, ul_adder, m2exp); break; default: fprintf (stderr, "gen: unsupported algorithm\n"); exit (1); } gmp_randseed (rstate, z_seed); break; case RFUNC_rand: srand (seed); break; case RFUNC_random: #ifdef __FreeBSD__ /* FIXME */ if (seed_from_user) srandom (seed); else srandomdev (); #else fprintf (stderr, "gen: unsupported algorithm\n"); #endif break; default: fprintf (stderr, "gen: random function not implemented\n"); exit (1); } /* set up excludes */ if (do_exclude) switch (rfunc) { case RFUNC_mpf_urandomb: if (mpf_set_str (f_xf, str_xf, 10) || mpf_set_str (f_xt, str_xt, 10)) { fprintf (stderr, "gen: bad exclusion-from (\"%s\") " \ "or exclusion-to (\"%s\") string. no exclusion done.\n", str_xf, str_xt); do_exclude = 0; } break; default: fprintf (stderr, "gen: exclusion not implemented for chosen " \ "randomization function. all numbers included in sequence.\n"); } /* generate and print */ if (argc > 0) { #if HAVE_STRTOUL n = strtoul (argv[0], (char **) NULL, 10); #elif HAVE_STRTOL n = (unsigned long int) strtol (argv[0], (char **) NULL, 10); #else n = (unsigned long int) atoi (argv[0]); #endif } for (f = 0; n == 0 || f < n; f++) { switch (rfunc) { case RFUNC_mpz_urandomb: mpz_urandomb (z1, rstate, size); if (quiet_flag) break; if (binout) { /*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/ fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n"); exit (1); } else { mpz_out_str (stdout, output_radix, z1); puts (""); } break; case RFUNC_mpz_urandomm: mpz_urandomm (z1, rstate, z_mmax); if (quiet_flag) break; if (binout) { /*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/ fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n"); exit (1); } else { mpz_out_str (stdout, output_radix, z1); puts (""); } break; case RFUNC_mpf_urandomb: mpf_urandomb (f1, rstate, size); if (do_exclude) if (mpf_cmp (f1, f_xf) >= 0 && mpf_cmp (f1, f_xt) <= 0) break; if (quiet_flag) break; if (binout) { fprintf (stderr, "gen: binary output for floating point numbers "\ "not implemented\n"); exit (1); } else { mpf_out_str (stdout, output_radix, 0, f1); puts (""); } break; case RFUNC_rand: i = rand (); #ifdef FLOAT_OUTPUT if (i) drand = (double) i / (double) RAND_MAX; else drand = 0.0; if (quiet_flag) break; if (binout) fwrite (&drand, sizeof (drand), 1, stdout); else printf ("%e\n", drand); #else if (quiet_flag) break; if (binout) fwrite (&i, sizeof (i), 1, stdout); else printf ("%d\n", i); #endif break; case RFUNC_random: lrand = random (); if (lrand) drand = (double) lrand / (double) 0x7fffffff; else drand = 0; if (quiet_flag) break; if (binout) fwrite (&drand, sizeof (drand), 1, stdout); else printf ("%e\n", drand); break; default: fprintf (stderr, "gen: random function not implemented\n"); exit (1); } } /* clean up */ switch (rfunc) { case RFUNC_mpz_urandomb: case RFUNC_mpf_urandomb: gmp_randclear (rstate); break; default: break; } mpf_clear (f1); mpf_clear (f_xf); mpf_clear (f_xt); mpz_clear (z1); mpz_clear (z_seed); return 0; } static void *debug_dummyz = mpz_dump; static void *debug_dummyf = mpf_dump;