github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/rand/gen.c (about)

     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 test suite.
     6  
     7  The GNU MP Library test suite is free software; you can redistribute it
     8  and/or modify it under the terms of the GNU General Public License as
     9  published by the Free Software Foundation; either version 3 of the License,
    10  or (at your option) any later version.
    11  
    12  The GNU MP Library test suite is distributed in the hope that it will be
    13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    15  Public License for more details.
    16  
    17  You should have received a copy of the GNU General Public License along with
    18  the GNU MP Library test suite.  If not, see https://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;