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;