1/* random.c -- Handle seed for random numbers. 2 3// Copyright (C) 2008, 2009, 2010, 2011 INRIA 4 5This file is part of GNU MPC. 6 7GNU MPC is free software; you can redistribute it and/or modify it under 8the terms of the GNU Lesser General Public License as published by the 9Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along 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 41gmp_randstate_t rands; 42static char rands_initialized; 43 44void 45test_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 89void 90test_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*/ 107void 108test_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