random.c revision 1.1.1.1 1 /* random.c -- Handle seed for random numbers.
2
3 // Copyright (C) 2008, 2009, 2010, 2011 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
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
89 void
90 test_end (void)
91 {
92 if (rands_initialized)
93 {
94 rands_initialized = 0;
95 gmp_randclear (rands);
96 }
97 mpfr_free_cache ();
98 }
99
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.
106 */
107 void
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)
111 {
112 const unsigned long range = (unsigned long int) (emax - emin) + 1;
113 unsigned long r;
114
115 if (!rands_initialized)
116 {
117 fprintf (stderr,
118 "Put test_start at the beginning of your test function.\n");
119 exit (1);
120 }
121
122 do
123 {
124 mpc_urandom (z, rands);
125 } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
126
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)
132 {
133 int zero_re_p = (r & 0x1FF) < zero_probability;
134 int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
135
136 if (zero_re_p && zero_im_p)
137 {
138 /* we just want one zero part. */
139 zero_re_p = (r >> 18) & 1;
140 zero_im_p = !zero_re_p;
141 }
142 if (zero_re_p)
143 mpfr_set_ui (mpc_realref (z), 0, GMP_RNDN);
144 if (zero_im_p)
145 mpfr_set_ui (mpc_imagref (z), 0, GMP_RNDN);
146 }
147 if (!mpfr_zero_p (mpc_realref (z)))
148 mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
149
150 if (!mpfr_zero_p (mpc_imagref (z)))
151 mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
152
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);
160 }
161