1 1.1 mrg /* random.c -- Handle seed for random numbers. 2 1.1 mrg 3 1.1.1.2 mrg // Copyright (C) 2008, 2009, 2010, 2011, 2012 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.1.2 mrg 88 1.1.1.2 mrg /* some tests assume a given exponent range for MPFR, thus since the 89 1.1.1.2 mrg default exponent range for MPFR is not specified, we hard-code it */ 90 1.1.1.2 mrg mpfr_set_emax (1073741821); 91 1.1.1.2 mrg mpfr_set_emin (-1073741821); 92 1.1 mrg } 93 1.1 mrg 94 1.1 mrg void 95 1.1 mrg test_end (void) 96 1.1 mrg { 97 1.1 mrg if (rands_initialized) 98 1.1 mrg { 99 1.1 mrg rands_initialized = 0; 100 1.1 mrg gmp_randclear (rands); 101 1.1 mrg } 102 1.1 mrg mpfr_free_cache (); 103 1.1 mrg } 104 1.1 mrg 105 1.1 mrg /* Set z to a non zero value random value with absolute values of Re(z) and 106 1.1 mrg Im(z) either zero (but not both in the same time) or otherwise greater than 107 1.1 mrg or equal to 2^{emin-1} and less than 2^emax. 108 1.1 mrg Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256. 109 1.1 mrg The result has one zero part (but never the two of them) with probability 110 1.1 mrg equal to ZERO_PROBABILITY / 256. 111 1.1 mrg */ 112 1.1 mrg void 113 1.1 mrg test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax, 114 1.1 mrg unsigned int negative_probability, 115 1.1 mrg unsigned int zero_probability) 116 1.1 mrg { 117 1.1 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1; 118 1.1 mrg unsigned long r; 119 1.1 mrg 120 1.1 mrg if (!rands_initialized) 121 1.1 mrg { 122 1.1 mrg fprintf (stderr, 123 1.1 mrg "Put test_start at the beginning of your test function.\n"); 124 1.1 mrg exit (1); 125 1.1 mrg } 126 1.1 mrg 127 1.1 mrg do 128 1.1 mrg { 129 1.1 mrg mpc_urandom (z, rands); 130 1.1 mrg } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z))); 131 1.1 mrg 132 1.1 mrg if (zero_probability > 256) 133 1.1 mrg zero_probability = 256; 134 1.1 mrg r = gmp_urandomb_ui (rands, 19); 135 1.1 mrg if ((r & 0x1FF) < zero_probability 136 1.1 mrg || ((r >> 9) & 0x1FF) < zero_probability) 137 1.1 mrg { 138 1.1 mrg int zero_re_p = (r & 0x1FF) < zero_probability; 139 1.1 mrg int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability; 140 1.1 mrg 141 1.1 mrg if (zero_re_p && zero_im_p) 142 1.1 mrg { 143 1.1 mrg /* we just want one zero part. */ 144 1.1 mrg zero_re_p = (r >> 18) & 1; 145 1.1 mrg zero_im_p = !zero_re_p; 146 1.1 mrg } 147 1.1 mrg if (zero_re_p) 148 1.1.1.2 mrg mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN); 149 1.1 mrg if (zero_im_p) 150 1.1.1.2 mrg mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN); 151 1.1 mrg } 152 1.1 mrg if (!mpfr_zero_p (mpc_realref (z))) 153 1.1 mrg mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin); 154 1.1 mrg 155 1.1 mrg if (!mpfr_zero_p (mpc_imagref (z))) 156 1.1 mrg mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin); 157 1.1 mrg 158 1.1 mrg if (negative_probability > 256) 159 1.1 mrg negative_probability = 256; 160 1.1 mrg r = gmp_urandomb_ui (rands, 16); 161 1.1 mrg if ((r & 0xFF) < negative_probability) 162 1.1.1.2 mrg mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN); 163 1.1.1.2 mrg if (((r>>8) & 0xFF) < negative_probability) 164 1.1.1.2 mrg mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN); 165 1.1.1.2 mrg } 166 1.1.1.2 mrg 167 1.1.1.2 mrg /* Set n to a non zero value random value with absolute values less than 168 1.1.1.2 mrg 2^emax. 169 1.1.1.2 mrg 170 1.1.1.2 mrg n is negative with probability equal to NEGATIVE_PROBABILITY / 256. 171 1.1.1.2 mrg */ 172 1.1.1.2 mrg void test_random_si (long int *n, unsigned long emax, 173 1.1.1.2 mrg unsigned int negative_probability) 174 1.1.1.2 mrg { 175 1.1.1.2 mrg unsigned long r; 176 1.1.1.2 mrg 177 1.1.1.2 mrg if (!rands_initialized) 178 1.1.1.2 mrg { 179 1.1.1.2 mrg fprintf (stderr, 180 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n"); 181 1.1.1.2 mrg exit (1); 182 1.1.1.2 mrg } 183 1.1.1.2 mrg 184 1.1.1.2 mrg do 185 1.1.1.2 mrg { 186 1.1.1.2 mrg *n = gmp_urandomb_ui (rands, emax); 187 1.1.1.2 mrg } while (*n == 0); 188 1.1.1.2 mrg 189 1.1.1.2 mrg if (negative_probability > 256) 190 1.1.1.2 mrg negative_probability = 256; 191 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 8); 192 1.1.1.2 mrg if ((r & 0xFF) < negative_probability) 193 1.1.1.2 mrg *n = -(*n); 194 1.1.1.2 mrg } 195 1.1.1.2 mrg 196 1.1.1.2 mrg /* Set x to a non zero value random value with absolute values greater than 197 1.1.1.2 mrg or equal to 2^{emin-1} and less than 2^emax. 198 1.1.1.2 mrg 199 1.1.1.2 mrg x is negative with probability equal to NEGATIVE_PROBABILITY / 256. 200 1.1.1.2 mrg */ 201 1.1.1.2 mrg void 202 1.1.1.2 mrg test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax, 203 1.1.1.2 mrg unsigned int negative_probability) 204 1.1.1.2 mrg { 205 1.1.1.2 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1; 206 1.1.1.2 mrg unsigned long r; 207 1.1.1.2 mrg 208 1.1.1.2 mrg if (!rands_initialized) 209 1.1.1.2 mrg { 210 1.1.1.2 mrg fprintf (stderr, 211 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n"); 212 1.1.1.2 mrg exit (1); 213 1.1.1.2 mrg } 214 1.1.1.2 mrg 215 1.1.1.2 mrg do 216 1.1.1.2 mrg { 217 1.1.1.2 mrg mpfr_urandom (x, rands, MPFR_RNDN); 218 1.1.1.2 mrg } while (mpfr_zero_p (x)); 219 1.1.1.2 mrg 220 1.1.1.2 mrg mpfr_set_exp (x, (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin); 221 1.1.1.2 mrg if (negative_probability > 256) 222 1.1.1.2 mrg negative_probability = 256; 223 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 8); 224 1.1.1.2 mrg if ((r & 0xFF) < negative_probability) 225 1.1.1.2 mrg mpfr_neg (x, x, MPFR_RNDN); 226 1.1.1.2 mrg } 227 1.1.1.2 mrg 228 1.1.1.2 mrg /* Set x to a non zero value random value. 229 1.1.1.2 mrg x is negative with probability equal to NEGATIVE_PROBABILITY / 256. 230 1.1.1.2 mrg */ 231 1.1.1.2 mrg void 232 1.1.1.2 mrg test_random_d (double *x, unsigned int negative_probability) 233 1.1.1.2 mrg { 234 1.1.1.2 mrg MPFR_DECL_INIT (mpfr_x, 53); 235 1.1.1.2 mrg test_random_mpfr (mpfr_x, -1022, 1022, negative_probability); 236 1.1.1.2 mrg *x = mpfr_get_d (mpfr_x, MPFR_RNDN); 237 1.1.1.2 mrg } 238 1.1.1.2 mrg 239 1.1.1.2 mrg /* Set z to a non zero value random value with absolute values of Re(z) and 240 1.1.1.2 mrg Im(z) greater than or equal to 2^{emin-1} and less than 2^emax. 241 1.1.1.2 mrg 242 1.1.1.2 mrg Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256. 243 1.1.1.2 mrg */ 244 1.1.1.2 mrg void 245 1.1.1.2 mrg test_random_mpc (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax, 246 1.1.1.2 mrg unsigned int negative_probability) 247 1.1.1.2 mrg { 248 1.1.1.2 mrg const unsigned long range = (unsigned long int) (emax - emin) + 1; 249 1.1.1.2 mrg unsigned long r; 250 1.1.1.2 mrg 251 1.1.1.2 mrg if (!rands_initialized) 252 1.1.1.2 mrg { 253 1.1.1.2 mrg fprintf (stderr, 254 1.1.1.2 mrg "Put test_start at the beginning of your test function.\n"); 255 1.1.1.2 mrg exit (1); 256 1.1.1.2 mrg } 257 1.1.1.2 mrg 258 1.1.1.2 mrg do 259 1.1.1.2 mrg { 260 1.1.1.2 mrg mpc_urandom (z, rands); 261 1.1.1.2 mrg } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z))); 262 1.1.1.2 mrg 263 1.1.1.2 mrg mpfr_set_exp (mpc_realref (z), 264 1.1.1.2 mrg (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin); 265 1.1.1.2 mrg 266 1.1.1.2 mrg mpfr_set_exp (mpc_imagref (z), 267 1.1.1.2 mrg (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin); 268 1.1.1.2 mrg 269 1.1.1.2 mrg if (negative_probability > 256) 270 1.1.1.2 mrg negative_probability = 256; 271 1.1.1.2 mrg r = gmp_urandomb_ui (rands, 16); 272 1.1.1.2 mrg if ((r & 0xFF) < negative_probability) 273 1.1.1.2 mrg mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN); 274 1.1 mrg if (((r>>8) & 0xFF) < negative_probability) 275 1.1.1.2 mrg mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN); 276 1.1 mrg } 277