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