1 /* random.c -- Handle seed for random numbers.
3 // Copyright (C) 2008, 2009, 2010, 2011 INRIA
5 This file is part of GNU MPC.
7 GNU MPC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/ .
21 /* Put test_start at the beginning of your test function and
23 These are an adaptation of those of MPFR. */
27 #include "mpc-tests.h"
30 #ifdef TIME_WITH_SYS_TIME
31 # include <sys/time.h>
34 # ifdef HAVE_SYS_TIME_H
35 # include <sys/time.h>
41 gmp_randstate_t rands;
42 static char rands_initialized;
47 char *environment_seed;
50 if (rands_initialized)
53 "Put test_start at the beginning of your test function.\n");
57 gmp_randinit_default (rands);
58 rands_initialized = 1;
60 environment_seed = getenv ("GMP_CHECK_RANDOMIZE");
61 if (environment_seed == NULL)
62 gmp_randseed_ui (rands, 0xfac11e);
65 seed = (unsigned long int) atoi (environment_seed);
66 if (seed == 0 || seed == 1)
68 #if defined HAVE_GETTIMEOFDAY
70 gettimeofday (&tv, NULL);
71 seed = (unsigned long int) (tv.tv_sec + tv.tv_usec);
75 seed = (unsigned long int) tv;
77 gmp_randseed_ui (rands, seed);
78 printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
79 "(include this in bug reports)\n", seed);
83 printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
84 gmp_randseed_ui (rands, seed);
92 if (rands_initialized)
94 rands_initialized = 0;
95 gmp_randclear (rands);
100 /* Set z to a non zero value random value with absolute values of Re(z) and
101 Im(z) either zero (but not both in the same time) or otherwise greater than
102 or equal to 2^{emin-1} and less than 2^emax.
103 Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
104 The result has one zero part (but never the two of them) with probability
105 equal to ZERO_PROBABILITY / 256.
108 test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
109 unsigned int negative_probability,
110 unsigned int zero_probability)
112 const unsigned long range = (unsigned long int) (emax - emin) + 1;
115 if (!rands_initialized)
118 "Put test_start at the beginning of your test function.\n");
124 mpc_urandom (z, rands);
125 } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
127 if (zero_probability > 256)
128 zero_probability = 256;
129 r = gmp_urandomb_ui (rands, 19);
130 if ((r & 0x1FF) < zero_probability
131 || ((r >> 9) & 0x1FF) < zero_probability)
133 int zero_re_p = (r & 0x1FF) < zero_probability;
134 int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
136 if (zero_re_p && zero_im_p)
138 /* we just want one zero part. */
139 zero_re_p = (r >> 18) & 1;
140 zero_im_p = !zero_re_p;
143 mpfr_set_ui (mpc_realref (z), 0, GMP_RNDN);
145 mpfr_set_ui (mpc_imagref (z), 0, GMP_RNDN);
147 if (!mpfr_zero_p (mpc_realref (z)))
148 mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
150 if (!mpfr_zero_p (mpc_imagref (z)))
151 mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
153 if (negative_probability > 256)
154 negative_probability = 256;
155 r = gmp_urandomb_ui (rands, 16);
156 if ((r & 0xFF) < negative_probability)
157 mpfr_neg (mpc_realref (z), mpc_realref (z), GMP_RNDN);
158 if (((r>>8) & 0xFF) < negative_probability)
159 mpfr_neg (mpc_imagref (z), mpc_imagref (z), GMP_RNDN);