Home | History | Annotate | Line # | Download | only in tests
random.c revision 1.1.1.2
      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