random.c revision 1.1 1 1.1 mrg /* random.c -- Handle seed for random numbers.
2 1.1 mrg
3 1.1 mrg // Copyright (C) 2008, 2009, 2010, 2011 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 mrg }
88 1.1 mrg
89 1.1 mrg void
90 1.1 mrg test_end (void)
91 1.1 mrg {
92 1.1 mrg if (rands_initialized)
93 1.1 mrg {
94 1.1 mrg rands_initialized = 0;
95 1.1 mrg gmp_randclear (rands);
96 1.1 mrg }
97 1.1 mrg mpfr_free_cache ();
98 1.1 mrg }
99 1.1 mrg
100 1.1 mrg /* Set z to a non zero value random value with absolute values of Re(z) and
101 1.1 mrg Im(z) either zero (but not both in the same time) or otherwise greater than
102 1.1 mrg or equal to 2^{emin-1} and less than 2^emax.
103 1.1 mrg Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
104 1.1 mrg The result has one zero part (but never the two of them) with probability
105 1.1 mrg equal to ZERO_PROBABILITY / 256.
106 1.1 mrg */
107 1.1 mrg void
108 1.1 mrg test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
109 1.1 mrg unsigned int negative_probability,
110 1.1 mrg unsigned int zero_probability)
111 1.1 mrg {
112 1.1 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1;
113 1.1 mrg unsigned long r;
114 1.1 mrg
115 1.1 mrg if (!rands_initialized)
116 1.1 mrg {
117 1.1 mrg fprintf (stderr,
118 1.1 mrg "Put test_start at the beginning of your test function.\n");
119 1.1 mrg exit (1);
120 1.1 mrg }
121 1.1 mrg
122 1.1 mrg do
123 1.1 mrg {
124 1.1 mrg mpc_urandom (z, rands);
125 1.1 mrg } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
126 1.1 mrg
127 1.1 mrg if (zero_probability > 256)
128 1.1 mrg zero_probability = 256;
129 1.1 mrg r = gmp_urandomb_ui (rands, 19);
130 1.1 mrg if ((r & 0x1FF) < zero_probability
131 1.1 mrg || ((r >> 9) & 0x1FF) < zero_probability)
132 1.1 mrg {
133 1.1 mrg int zero_re_p = (r & 0x1FF) < zero_probability;
134 1.1 mrg int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
135 1.1 mrg
136 1.1 mrg if (zero_re_p && zero_im_p)
137 1.1 mrg {
138 1.1 mrg /* we just want one zero part. */
139 1.1 mrg zero_re_p = (r >> 18) & 1;
140 1.1 mrg zero_im_p = !zero_re_p;
141 1.1 mrg }
142 1.1 mrg if (zero_re_p)
143 1.1 mrg mpfr_set_ui (mpc_realref (z), 0, GMP_RNDN);
144 1.1 mrg if (zero_im_p)
145 1.1 mrg mpfr_set_ui (mpc_imagref (z), 0, GMP_RNDN);
146 1.1 mrg }
147 1.1 mrg if (!mpfr_zero_p (mpc_realref (z)))
148 1.1 mrg mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
149 1.1 mrg
150 1.1 mrg if (!mpfr_zero_p (mpc_imagref (z)))
151 1.1 mrg mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
152 1.1 mrg
153 1.1 mrg if (negative_probability > 256)
154 1.1 mrg negative_probability = 256;
155 1.1 mrg r = gmp_urandomb_ui (rands, 16);
156 1.1 mrg if ((r & 0xFF) < negative_probability)
157 1.1 mrg mpfr_neg (mpc_realref (z), mpc_realref (z), GMP_RNDN);
158 1.1 mrg if (((r>>8) & 0xFF) < negative_probability)
159 1.1 mrg mpfr_neg (mpc_imagref (z), mpc_imagref (z), GMP_RNDN);
160 1.1 mrg }
161