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