random.c revision 1.1.1.1.8.2 1 1.1.1.1.8.2 tls /* random.c -- Handle seed for random numbers.
2 1.1.1.1.8.2 tls
3 1.1.1.1.8.2 tls // Copyright (C) 2008, 2009, 2010, 2011 INRIA
4 1.1.1.1.8.2 tls
5 1.1.1.1.8.2 tls This file is part of GNU MPC.
6 1.1.1.1.8.2 tls
7 1.1.1.1.8.2 tls GNU MPC is free software; you can redistribute it and/or modify it under
8 1.1.1.1.8.2 tls the terms of the GNU Lesser General Public License as published by the
9 1.1.1.1.8.2 tls Free Software Foundation; either version 3 of the License, or (at your
10 1.1.1.1.8.2 tls option) any later version.
11 1.1.1.1.8.2 tls
12 1.1.1.1.8.2 tls GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1.1.1.8.2 tls WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 1.1.1.1.8.2 tls FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 1.1.1.1.8.2 tls more details.
16 1.1.1.1.8.2 tls
17 1.1.1.1.8.2 tls You should have received a copy of the GNU Lesser General Public License
18 1.1.1.1.8.2 tls along with this program. If not, see http://www.gnu.org/licenses/ .
19 1.1.1.1.8.2 tls */
20 1.1.1.1.8.2 tls
21 1.1.1.1.8.2 tls /* Put test_start at the beginning of your test function and
22 1.1.1.1.8.2 tls test_end at the end.
23 1.1.1.1.8.2 tls These are an adaptation of those of MPFR. */
24 1.1.1.1.8.2 tls
25 1.1.1.1.8.2 tls #include "config.h"
26 1.1.1.1.8.2 tls #include <stdlib.h>
27 1.1.1.1.8.2 tls #include "mpc-tests.h"
28 1.1.1.1.8.2 tls
29 1.1.1.1.8.2 tls
30 1.1.1.1.8.2 tls #ifdef TIME_WITH_SYS_TIME
31 1.1.1.1.8.2 tls # include <sys/time.h>
32 1.1.1.1.8.2 tls # include <time.h>
33 1.1.1.1.8.2 tls #else
34 1.1.1.1.8.2 tls # ifdef HAVE_SYS_TIME_H
35 1.1.1.1.8.2 tls # include <sys/time.h>
36 1.1.1.1.8.2 tls # else
37 1.1.1.1.8.2 tls # include <time.h>
38 1.1.1.1.8.2 tls # endif
39 1.1.1.1.8.2 tls #endif
40 1.1.1.1.8.2 tls
41 1.1.1.1.8.2 tls gmp_randstate_t rands;
42 1.1.1.1.8.2 tls static char rands_initialized;
43 1.1.1.1.8.2 tls
44 1.1.1.1.8.2 tls void
45 1.1.1.1.8.2 tls test_start (void)
46 1.1.1.1.8.2 tls {
47 1.1.1.1.8.2 tls char *environment_seed;
48 1.1.1.1.8.2 tls unsigned long seed;
49 1.1.1.1.8.2 tls
50 1.1.1.1.8.2 tls if (rands_initialized)
51 1.1.1.1.8.2 tls {
52 1.1.1.1.8.2 tls fprintf (stderr,
53 1.1.1.1.8.2 tls "Put test_start at the beginning of your test function.\n");
54 1.1.1.1.8.2 tls exit (1);
55 1.1.1.1.8.2 tls }
56 1.1.1.1.8.2 tls
57 1.1.1.1.8.2 tls gmp_randinit_default (rands);
58 1.1.1.1.8.2 tls rands_initialized = 1;
59 1.1.1.1.8.2 tls
60 1.1.1.1.8.2 tls environment_seed = getenv ("GMP_CHECK_RANDOMIZE");
61 1.1.1.1.8.2 tls if (environment_seed == NULL)
62 1.1.1.1.8.2 tls gmp_randseed_ui (rands, 0xfac11e);
63 1.1.1.1.8.2 tls else
64 1.1.1.1.8.2 tls {
65 1.1.1.1.8.2 tls seed = (unsigned long int) atoi (environment_seed);
66 1.1.1.1.8.2 tls if (seed == 0 || seed == 1)
67 1.1.1.1.8.2 tls {
68 1.1.1.1.8.2 tls #if defined HAVE_GETTIMEOFDAY
69 1.1.1.1.8.2 tls struct timeval tv;
70 1.1.1.1.8.2 tls gettimeofday (&tv, NULL);
71 1.1.1.1.8.2 tls seed = (unsigned long int) (tv.tv_sec + tv.tv_usec);
72 1.1.1.1.8.2 tls #else
73 1.1.1.1.8.2 tls time_t tv;
74 1.1.1.1.8.2 tls time (&tv);
75 1.1.1.1.8.2 tls seed = (unsigned long int) tv;
76 1.1.1.1.8.2 tls #endif
77 1.1.1.1.8.2 tls gmp_randseed_ui (rands, seed);
78 1.1.1.1.8.2 tls printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
79 1.1.1.1.8.2 tls "(include this in bug reports)\n", seed);
80 1.1.1.1.8.2 tls }
81 1.1.1.1.8.2 tls else
82 1.1.1.1.8.2 tls {
83 1.1.1.1.8.2 tls printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
84 1.1.1.1.8.2 tls gmp_randseed_ui (rands, seed);
85 1.1.1.1.8.2 tls }
86 1.1.1.1.8.2 tls }
87 1.1.1.1.8.2 tls }
88 1.1.1.1.8.2 tls
89 1.1.1.1.8.2 tls void
90 1.1.1.1.8.2 tls test_end (void)
91 1.1.1.1.8.2 tls {
92 1.1.1.1.8.2 tls if (rands_initialized)
93 1.1.1.1.8.2 tls {
94 1.1.1.1.8.2 tls rands_initialized = 0;
95 1.1.1.1.8.2 tls gmp_randclear (rands);
96 1.1.1.1.8.2 tls }
97 1.1.1.1.8.2 tls mpfr_free_cache ();
98 1.1.1.1.8.2 tls }
99 1.1.1.1.8.2 tls
100 1.1.1.1.8.2 tls /* Set z to a non zero value random value with absolute values of Re(z) and
101 1.1.1.1.8.2 tls Im(z) either zero (but not both in the same time) or otherwise greater than
102 1.1.1.1.8.2 tls or equal to 2^{emin-1} and less than 2^emax.
103 1.1.1.1.8.2 tls Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
104 1.1.1.1.8.2 tls The result has one zero part (but never the two of them) with probability
105 1.1.1.1.8.2 tls equal to ZERO_PROBABILITY / 256.
106 1.1.1.1.8.2 tls */
107 1.1.1.1.8.2 tls void
108 1.1.1.1.8.2 tls test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
109 1.1.1.1.8.2 tls unsigned int negative_probability,
110 1.1.1.1.8.2 tls unsigned int zero_probability)
111 1.1.1.1.8.2 tls {
112 1.1.1.1.8.2 tls const unsigned long range = (unsigned long int) (emax - emin) + 1;
113 1.1.1.1.8.2 tls unsigned long r;
114 1.1.1.1.8.2 tls
115 1.1.1.1.8.2 tls if (!rands_initialized)
116 1.1.1.1.8.2 tls {
117 1.1.1.1.8.2 tls fprintf (stderr,
118 1.1.1.1.8.2 tls "Put test_start at the beginning of your test function.\n");
119 1.1.1.1.8.2 tls exit (1);
120 1.1.1.1.8.2 tls }
121 1.1.1.1.8.2 tls
122 1.1.1.1.8.2 tls do
123 1.1.1.1.8.2 tls {
124 1.1.1.1.8.2 tls mpc_urandom (z, rands);
125 1.1.1.1.8.2 tls } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
126 1.1.1.1.8.2 tls
127 1.1.1.1.8.2 tls if (zero_probability > 256)
128 1.1.1.1.8.2 tls zero_probability = 256;
129 1.1.1.1.8.2 tls r = gmp_urandomb_ui (rands, 19);
130 1.1.1.1.8.2 tls if ((r & 0x1FF) < zero_probability
131 1.1.1.1.8.2 tls || ((r >> 9) & 0x1FF) < zero_probability)
132 1.1.1.1.8.2 tls {
133 1.1.1.1.8.2 tls int zero_re_p = (r & 0x1FF) < zero_probability;
134 1.1.1.1.8.2 tls int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
135 1.1.1.1.8.2 tls
136 1.1.1.1.8.2 tls if (zero_re_p && zero_im_p)
137 1.1.1.1.8.2 tls {
138 1.1.1.1.8.2 tls /* we just want one zero part. */
139 1.1.1.1.8.2 tls zero_re_p = (r >> 18) & 1;
140 1.1.1.1.8.2 tls zero_im_p = !zero_re_p;
141 1.1.1.1.8.2 tls }
142 1.1.1.1.8.2 tls if (zero_re_p)
143 1.1.1.1.8.2 tls mpfr_set_ui (mpc_realref (z), 0, GMP_RNDN);
144 1.1.1.1.8.2 tls if (zero_im_p)
145 1.1.1.1.8.2 tls mpfr_set_ui (mpc_imagref (z), 0, GMP_RNDN);
146 1.1.1.1.8.2 tls }
147 1.1.1.1.8.2 tls if (!mpfr_zero_p (mpc_realref (z)))
148 1.1.1.1.8.2 tls mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
149 1.1.1.1.8.2 tls
150 1.1.1.1.8.2 tls if (!mpfr_zero_p (mpc_imagref (z)))
151 1.1.1.1.8.2 tls mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
152 1.1.1.1.8.2 tls
153 1.1.1.1.8.2 tls if (negative_probability > 256)
154 1.1.1.1.8.2 tls negative_probability = 256;
155 1.1.1.1.8.2 tls r = gmp_urandomb_ui (rands, 16);
156 1.1.1.1.8.2 tls if ((r & 0xFF) < negative_probability)
157 1.1.1.1.8.2 tls mpfr_neg (mpc_realref (z), mpc_realref (z), GMP_RNDN);
158 1.1.1.1.8.2 tls if (((r>>8) & 0xFF) < negative_probability)
159 1.1.1.1.8.2 tls mpfr_neg (mpc_imagref (z), mpc_imagref (z), GMP_RNDN);
160 1.1.1.1.8.2 tls }
161