gen.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:10k
源码类别:

数学计算

开发平台:

Unix_Linux

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