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