random.c revision 1.1.1.2 1 1.1 mrg /* random.c -- Handle seed for random numbers.
2 1.1 mrg
3 1.1.1.2 mrg // Copyright (C) 2008, 2009, 2010, 2011, 2012 INRIA
4 1.1 mrg
5 1.1 mrg This file is part of GNU MPC.
6 1.1 mrg
7 1.1 mrg GNU MPC is free software; you can redistribute it and/or modify it under
8 1.1 mrg the terms of the GNU Lesser General Public License as published by the
9 1.1 mrg Free Software Foundation; either version 3 of the License, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 1.1 mrg more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU Lesser General Public License
18 1.1 mrg along with this program. If not, see http://www.gnu.org/licenses/ .
19 1.1 mrg */
20 1.1 mrg
21 1.1 mrg /* Put test_start at the beginning of your test function and
22 1.1 mrg test_end at the end.
23 1.1 mrg These are an adaptation of those of MPFR. */
24 1.1 mrg
25 1.1 mrg #include "config.h"
26 1.1 mrg #include <stdlib.h>
27 1.1 mrg #include "mpc-tests.h"
28 1.1 mrg
29 1.1 mrg
30 1.1 mrg #ifdef TIME_WITH_SYS_TIME
31 1.1 mrg # include <sys/time.h>
32 1.1 mrg # include <time.h>
33 1.1 mrg #else
34 1.1 mrg # ifdef HAVE_SYS_TIME_H
35 1.1 mrg # include <sys/time.h>
36 1.1 mrg # else
37 1.1 mrg # include <time.h>
38 1.1 mrg # endif
39 1.1 mrg #endif
40 1.1 mrg
41 1.1 mrg gmp_randstate_t rands;
42 1.1 mrg static char rands_initialized;
43 1.1 mrg
44 1.1 mrg void
45 1.1 mrg test_start (void)
46 1.1 mrg {
47 1.1 mrg char *environment_seed;
48 1.1 mrg unsigned long seed;
49 1.1 mrg
50 1.1 mrg if (rands_initialized)
51 1.1 mrg {
52 1.1 mrg fprintf (stderr,
53 1.1 mrg "Put test_start at the beginning of your test function.\n");
54 1.1 mrg exit (1);
55 1.1 mrg }
56 1.1 mrg
57 1.1 mrg gmp_randinit_default (rands);
58 1.1 mrg rands_initialized = 1;
59 1.1 mrg
60 1.1 mrg environment_seed = getenv ("GMP_CHECK_RANDOMIZE");
61 1.1 mrg if (environment_seed == NULL)
62 1.1 mrg gmp_randseed_ui (rands, 0xfac11e);
63 1.1 mrg else
64 1.1 mrg {
65 1.1 mrg seed = (unsigned long int) atoi (environment_seed);
66 1.1 mrg if (seed == 0 || seed == 1)
67 1.1 mrg {
68 1.1 mrg #if defined HAVE_GETTIMEOFDAY
69 1.1 mrg struct timeval tv;
70 1.1 mrg gettimeofday (&tv, NULL);
71 1.1 mrg seed = (unsigned long int) (tv.tv_sec + tv.tv_usec);
72 1.1 mrg #else
73 1.1 mrg time_t tv;
74 1.1 mrg time (&tv);
75 1.1 mrg seed = (unsigned long int) tv;
76 1.1 mrg #endif
77 1.1 mrg gmp_randseed_ui (rands, seed);
78 1.1 mrg printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
79 1.1 mrg "(include this in bug reports)\n", seed);
80 1.1 mrg }
81 1.1 mrg else
82 1.1 mrg {
83 1.1 mrg printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
84 1.1 mrg gmp_randseed_ui (rands, seed);
85 1.1 mrg }
86 1.1 mrg }
87 1.1.1.2 mrg
88 1.1.1.2 mrg /* some tests assume a given exponent range for MPFR, thus since the
89 1.1.1.2 mrg default exponent range for MPFR is not specified, we hard-code it */
90 1.1.1.2 mrg mpfr_set_emax (1073741821);
91 1.1.1.2 mrg mpfr_set_emin (-1073741821);
92 1.1 mrg }
93 1.1 mrg
94 1.1 mrg void
95 1.1 mrg test_end (void)
96 1.1 mrg {
97 1.1 mrg if (rands_initialized)
98 1.1 mrg {
99 1.1 mrg rands_initialized = 0;
100 1.1 mrg gmp_randclear (rands);
101 1.1 mrg }
102 1.1 mrg mpfr_free_cache ();
103 1.1 mrg }
104 1.1 mrg
105 1.1 mrg /* Set z to a non zero value random value with absolute values of Re(z) and
106 1.1 mrg Im(z) either zero (but not both in the same time) or otherwise greater than
107 1.1 mrg or equal to 2^{emin-1} and less than 2^emax.
108 1.1 mrg Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
109 1.1 mrg The result has one zero part (but never the two of them) with probability
110 1.1 mrg equal to ZERO_PROBABILITY / 256.
111 1.1 mrg */
112 1.1 mrg void
113 1.1 mrg test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
114 1.1 mrg unsigned int negative_probability,
115 1.1 mrg unsigned int zero_probability)
116 1.1 mrg {
117 1.1 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1;
118 1.1 mrg unsigned long r;
119 1.1 mrg
120 1.1 mrg if (!rands_initialized)
121 1.1 mrg {
122 1.1 mrg fprintf (stderr,
123 1.1 mrg "Put test_start at the beginning of your test function.\n");
124 1.1 mrg exit (1);
125 1.1 mrg }
126 1.1 mrg
127 1.1 mrg do
128 1.1 mrg {
129 1.1 mrg mpc_urandom (z, rands);
130 1.1 mrg } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
131 1.1 mrg
132 1.1 mrg if (zero_probability > 256)
133 1.1 mrg zero_probability = 256;
134 1.1 mrg r = gmp_urandomb_ui (rands, 19);
135 1.1 mrg if ((r & 0x1FF) < zero_probability
136 1.1 mrg || ((r >> 9) & 0x1FF) < zero_probability)
137 1.1 mrg {
138 1.1 mrg int zero_re_p = (r & 0x1FF) < zero_probability;
139 1.1 mrg int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
140 1.1 mrg
141 1.1 mrg if (zero_re_p && zero_im_p)
142 1.1 mrg {
143 1.1 mrg /* we just want one zero part. */
144 1.1 mrg zero_re_p = (r >> 18) & 1;
145 1.1 mrg zero_im_p = !zero_re_p;
146 1.1 mrg }
147 1.1 mrg if (zero_re_p)
148 1.1.1.2 mrg mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN);
149 1.1 mrg if (zero_im_p)
150 1.1.1.2 mrg mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN);
151 1.1 mrg }
152 1.1 mrg if (!mpfr_zero_p (mpc_realref (z)))
153 1.1 mrg mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
154 1.1 mrg
155 1.1 mrg if (!mpfr_zero_p (mpc_imagref (z)))
156 1.1 mrg mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
157 1.1 mrg
158 1.1 mrg if (negative_probability > 256)
159 1.1 mrg negative_probability = 256;
160 1.1 mrg r = gmp_urandomb_ui (rands, 16);
161 1.1 mrg if ((r & 0xFF) < negative_probability)
162 1.1.1.2 mrg mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
163 1.1.1.2 mrg if (((r>>8) & 0xFF) < negative_probability)
164 1.1.1.2 mrg mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
165 1.1.1.2 mrg }
166 1.1.1.2 mrg
167 1.1.1.2 mrg /* Set n to a non zero value random value with absolute values less than
168 1.1.1.2 mrg 2^emax.
169 1.1.1.2 mrg
170 1.1.1.2 mrg n is negative with probability equal to NEGATIVE_PROBABILITY / 256.
171 1.1.1.2 mrg */
172 1.1.1.2 mrg void test_random_si (long int *n, unsigned long emax,
173 1.1.1.2 mrg unsigned int negative_probability)
174 1.1.1.2 mrg {
175 1.1.1.2 mrg unsigned long r;
176 1.1.1.2 mrg
177 1.1.1.2 mrg if (!rands_initialized)
178 1.1.1.2 mrg {
179 1.1.1.2 mrg fprintf (stderr,
180 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n");
181 1.1.1.2 mrg exit (1);
182 1.1.1.2 mrg }
183 1.1.1.2 mrg
184 1.1.1.2 mrg do
185 1.1.1.2 mrg {
186 1.1.1.2 mrg *n = gmp_urandomb_ui (rands, emax);
187 1.1.1.2 mrg } while (*n == 0);
188 1.1.1.2 mrg
189 1.1.1.2 mrg if (negative_probability > 256)
190 1.1.1.2 mrg negative_probability = 256;
191 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 8);
192 1.1.1.2 mrg if ((r & 0xFF) < negative_probability)
193 1.1.1.2 mrg *n = -(*n);
194 1.1.1.2 mrg }
195 1.1.1.2 mrg
196 1.1.1.2 mrg /* Set x to a non zero value random value with absolute values greater than
197 1.1.1.2 mrg or equal to 2^{emin-1} and less than 2^emax.
198 1.1.1.2 mrg
199 1.1.1.2 mrg x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
200 1.1.1.2 mrg */
201 1.1.1.2 mrg void
202 1.1.1.2 mrg test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
203 1.1.1.2 mrg unsigned int negative_probability)
204 1.1.1.2 mrg {
205 1.1.1.2 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1;
206 1.1.1.2 mrg unsigned long r;
207 1.1.1.2 mrg
208 1.1.1.2 mrg if (!rands_initialized)
209 1.1.1.2 mrg {
210 1.1.1.2 mrg fprintf (stderr,
211 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n");
212 1.1.1.2 mrg exit (1);
213 1.1.1.2 mrg }
214 1.1.1.2 mrg
215 1.1.1.2 mrg do
216 1.1.1.2 mrg {
217 1.1.1.2 mrg mpfr_urandom (x, rands, MPFR_RNDN);
218 1.1.1.2 mrg } while (mpfr_zero_p (x));
219 1.1.1.2 mrg
220 1.1.1.2 mrg mpfr_set_exp (x, (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
221 1.1.1.2 mrg if (negative_probability > 256)
222 1.1.1.2 mrg negative_probability = 256;
223 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 8);
224 1.1.1.2 mrg if ((r & 0xFF) < negative_probability)
225 1.1.1.2 mrg mpfr_neg (x, x, MPFR_RNDN);
226 1.1.1.2 mrg }
227 1.1.1.2 mrg
228 1.1.1.2 mrg /* Set x to a non zero value random value.
229 1.1.1.2 mrg x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
230 1.1.1.2 mrg */
231 1.1.1.2 mrg void
232 1.1.1.2 mrg test_random_d (double *x, unsigned int negative_probability)
233 1.1.1.2 mrg {
234 1.1.1.2 mrg MPFR_DECL_INIT (mpfr_x, 53);
235 1.1.1.2 mrg test_random_mpfr (mpfr_x, -1022, 1022, negative_probability);
236 1.1.1.2 mrg *x = mpfr_get_d (mpfr_x, MPFR_RNDN);
237 1.1.1.2 mrg }
238 1.1.1.2 mrg
239 1.1.1.2 mrg /* Set z to a non zero value random value with absolute values of Re(z) and
240 1.1.1.2 mrg Im(z) greater than or equal to 2^{emin-1} and less than 2^emax.
241 1.1.1.2 mrg
242 1.1.1.2 mrg Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
243 1.1.1.2 mrg */
244 1.1.1.2 mrg void
245 1.1.1.2 mrg test_random_mpc (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
246 1.1.1.2 mrg unsigned int negative_probability)
247 1.1.1.2 mrg {
248 1.1.1.2 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1;
249 1.1.1.2 mrg unsigned long r;
250 1.1.1.2 mrg
251 1.1.1.2 mrg if (!rands_initialized)
252 1.1.1.2 mrg {
253 1.1.1.2 mrg fprintf (stderr,
254 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n");
255 1.1.1.2 mrg exit (1);
256 1.1.1.2 mrg }
257 1.1.1.2 mrg
258 1.1.1.2 mrg do
259 1.1.1.2 mrg {
260 1.1.1.2 mrg mpc_urandom (z, rands);
261 1.1.1.2 mrg } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
262 1.1.1.2 mrg
263 1.1.1.2 mrg mpfr_set_exp (mpc_realref (z),
264 1.1.1.2 mrg (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
265 1.1.1.2 mrg
266 1.1.1.2 mrg mpfr_set_exp (mpc_imagref (z),
267 1.1.1.2 mrg (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
268 1.1.1.2 mrg
269 1.1.1.2 mrg if (negative_probability > 256)
270 1.1.1.2 mrg negative_probability = 256;
271 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 16);
272 1.1.1.2 mrg if ((r & 0xFF) < negative_probability)
273 1.1.1.2 mrg mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
274 1.1 mrg if (((r>>8) & 0xFF) < negative_probability)
275 1.1.1.2 mrg mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
276 1.1 mrg }
277