Home | History | Annotate | Line # | Download | only in tests
random.c revision 1.1.1.1.30.1
      1           1.1       mrg /* random.c -- Handle seed for random numbers.
      2           1.1       mrg 
      3  1.1.1.1.30.1  christos // 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.1.30.1  christos 
     88  1.1.1.1.30.1  christos   /* some tests assume a given exponent range for MPFR, thus since the
     89  1.1.1.1.30.1  christos      default exponent range for MPFR is not specified, we hard-code it */
     90  1.1.1.1.30.1  christos   mpfr_set_emax (1073741821);
     91  1.1.1.1.30.1  christos   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.1.30.1  christos         mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN);
    149           1.1       mrg       if (zero_im_p)
    150  1.1.1.1.30.1  christos         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.1.30.1  christos     mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
    163  1.1.1.1.30.1  christos   if (((r>>8) & 0xFF) < negative_probability)
    164  1.1.1.1.30.1  christos     mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
    165  1.1.1.1.30.1  christos }
    166  1.1.1.1.30.1  christos 
    167  1.1.1.1.30.1  christos /* Set n to a non zero value random value with absolute values less than
    168  1.1.1.1.30.1  christos    2^emax.
    169  1.1.1.1.30.1  christos 
    170  1.1.1.1.30.1  christos    n is negative with probability equal to NEGATIVE_PROBABILITY / 256.
    171  1.1.1.1.30.1  christos */
    172  1.1.1.1.30.1  christos void test_random_si (long int *n, unsigned long emax,
    173  1.1.1.1.30.1  christos                      unsigned int negative_probability)
    174  1.1.1.1.30.1  christos {
    175  1.1.1.1.30.1  christos   unsigned long r;
    176  1.1.1.1.30.1  christos 
    177  1.1.1.1.30.1  christos   if (!rands_initialized)
    178  1.1.1.1.30.1  christos     {
    179  1.1.1.1.30.1  christos       fprintf (stderr,
    180  1.1.1.1.30.1  christos                "Put test_start at the beginning of your test function.\n");
    181  1.1.1.1.30.1  christos       exit (1);
    182  1.1.1.1.30.1  christos     }
    183  1.1.1.1.30.1  christos 
    184  1.1.1.1.30.1  christos   do
    185  1.1.1.1.30.1  christos     {
    186  1.1.1.1.30.1  christos       *n = gmp_urandomb_ui (rands, emax);
    187  1.1.1.1.30.1  christos     } while (*n == 0);
    188  1.1.1.1.30.1  christos 
    189  1.1.1.1.30.1  christos   if (negative_probability > 256)
    190  1.1.1.1.30.1  christos     negative_probability = 256;
    191  1.1.1.1.30.1  christos   r = gmp_urandomb_ui (rands, 8);
    192  1.1.1.1.30.1  christos   if ((r & 0xFF) < negative_probability)
    193  1.1.1.1.30.1  christos     *n = -(*n);
    194  1.1.1.1.30.1  christos }
    195  1.1.1.1.30.1  christos 
    196  1.1.1.1.30.1  christos /* Set x to a non zero value random value with absolute values greater than
    197  1.1.1.1.30.1  christos    or equal to 2^{emin-1} and less than 2^emax.
    198  1.1.1.1.30.1  christos 
    199  1.1.1.1.30.1  christos    x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
    200  1.1.1.1.30.1  christos */
    201  1.1.1.1.30.1  christos void
    202  1.1.1.1.30.1  christos test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
    203  1.1.1.1.30.1  christos                   unsigned int negative_probability)
    204  1.1.1.1.30.1  christos {
    205  1.1.1.1.30.1  christos   const unsigned long range = (unsigned long int) (emax - emin) + 1;
    206  1.1.1.1.30.1  christos   unsigned long r;
    207  1.1.1.1.30.1  christos 
    208  1.1.1.1.30.1  christos   if (!rands_initialized)
    209  1.1.1.1.30.1  christos     {
    210  1.1.1.1.30.1  christos       fprintf (stderr,
    211  1.1.1.1.30.1  christos                "Put test_start at the beginning of your test function.\n");
    212  1.1.1.1.30.1  christos       exit (1);
    213  1.1.1.1.30.1  christos     }
    214  1.1.1.1.30.1  christos 
    215  1.1.1.1.30.1  christos   do
    216  1.1.1.1.30.1  christos     {
    217  1.1.1.1.30.1  christos       mpfr_urandom (x, rands, MPFR_RNDN);
    218  1.1.1.1.30.1  christos     } while (mpfr_zero_p (x));
    219  1.1.1.1.30.1  christos 
    220  1.1.1.1.30.1  christos   mpfr_set_exp (x, (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
    221  1.1.1.1.30.1  christos   if (negative_probability > 256)
    222  1.1.1.1.30.1  christos     negative_probability = 256;
    223  1.1.1.1.30.1  christos   r = gmp_urandomb_ui (rands, 8);
    224  1.1.1.1.30.1  christos   if ((r & 0xFF) < negative_probability)
    225  1.1.1.1.30.1  christos     mpfr_neg (x, x, MPFR_RNDN);
    226  1.1.1.1.30.1  christos }
    227  1.1.1.1.30.1  christos 
    228  1.1.1.1.30.1  christos /* Set x to a non zero value random value.
    229  1.1.1.1.30.1  christos    x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
    230  1.1.1.1.30.1  christos */
    231  1.1.1.1.30.1  christos void
    232  1.1.1.1.30.1  christos test_random_d (double *x, unsigned int negative_probability)
    233  1.1.1.1.30.1  christos {
    234  1.1.1.1.30.1  christos   MPFR_DECL_INIT (mpfr_x, 53);
    235  1.1.1.1.30.1  christos   test_random_mpfr (mpfr_x, -1022, 1022, negative_probability);
    236  1.1.1.1.30.1  christos   *x = mpfr_get_d (mpfr_x, MPFR_RNDN);
    237  1.1.1.1.30.1  christos }
    238  1.1.1.1.30.1  christos 
    239  1.1.1.1.30.1  christos /* Set z to a non zero value random value with absolute values of Re(z) and
    240  1.1.1.1.30.1  christos    Im(z) greater than or equal to 2^{emin-1} and less than 2^emax.
    241  1.1.1.1.30.1  christos 
    242  1.1.1.1.30.1  christos    Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
    243  1.1.1.1.30.1  christos */
    244  1.1.1.1.30.1  christos void
    245  1.1.1.1.30.1  christos test_random_mpc (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
    246  1.1.1.1.30.1  christos                  unsigned int negative_probability)
    247  1.1.1.1.30.1  christos {
    248  1.1.1.1.30.1  christos   const unsigned long range = (unsigned long int) (emax - emin) + 1;
    249  1.1.1.1.30.1  christos   unsigned long r;
    250  1.1.1.1.30.1  christos 
    251  1.1.1.1.30.1  christos   if (!rands_initialized)
    252  1.1.1.1.30.1  christos     {
    253  1.1.1.1.30.1  christos       fprintf (stderr,
    254  1.1.1.1.30.1  christos                "Put test_start at the beginning of your test function.\n");
    255  1.1.1.1.30.1  christos       exit (1);
    256  1.1.1.1.30.1  christos     }
    257  1.1.1.1.30.1  christos 
    258  1.1.1.1.30.1  christos   do
    259  1.1.1.1.30.1  christos     {
    260  1.1.1.1.30.1  christos       mpc_urandom (z, rands);
    261  1.1.1.1.30.1  christos     } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
    262  1.1.1.1.30.1  christos 
    263  1.1.1.1.30.1  christos     mpfr_set_exp (mpc_realref (z),
    264  1.1.1.1.30.1  christos                   (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
    265  1.1.1.1.30.1  christos 
    266  1.1.1.1.30.1  christos     mpfr_set_exp (mpc_imagref (z),
    267  1.1.1.1.30.1  christos                   (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
    268  1.1.1.1.30.1  christos 
    269  1.1.1.1.30.1  christos   if (negative_probability > 256)
    270  1.1.1.1.30.1  christos     negative_probability = 256;
    271  1.1.1.1.30.1  christos   r = gmp_urandomb_ui (rands, 16);
    272  1.1.1.1.30.1  christos   if ((r & 0xFF) < negative_probability)
    273  1.1.1.1.30.1  christos     mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
    274           1.1       mrg   if (((r>>8) & 0xFF) < negative_probability)
    275  1.1.1.1.30.1  christos     mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
    276           1.1       mrg }
    277