Home | History | Annotate | Line # | Download | only in tests
random2.c revision 1.1.1.3
      1      1.1  mrg /* mpfr_random2 -- Generate a positive random mpfr_t of specified size, with
      2      1.1  mrg    long runs of consecutive ones and zeros in the binary representation.
      3      1.1  mrg 
      4  1.1.1.3  mrg Copyright 1999, 2001-2004, 2006-2016 Free Software Foundation, Inc.
      5  1.1.1.3  mrg Contributed by the AriC and Caramba projects, INRIA.
      6      1.1  mrg 
      7      1.1  mrg This file is part of the GNU MPFR Library.
      8      1.1  mrg 
      9      1.1  mrg The GNU MPFR Library is free software; you can redistribute it and/or modify
     10      1.1  mrg it under the terms of the GNU Lesser General Public License as published by
     11      1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     12      1.1  mrg option) any later version.
     13      1.1  mrg 
     14      1.1  mrg The GNU MPFR Library is distributed in the hope that it will be useful, but
     15      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     16      1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     17      1.1  mrg License for more details.
     18      1.1  mrg 
     19      1.1  mrg You should have received a copy of the GNU Lesser General Public License
     20      1.1  mrg along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     21      1.1  mrg http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     22      1.1  mrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     23      1.1  mrg 
     24      1.1  mrg #include "mpfr-test.h"
     25      1.1  mrg 
     26      1.1  mrg #define LOGBITS_PER_BLOCK 4
     27      1.1  mrg #if GMP_NUMB_BITS < 32
     28      1.1  mrg #define BITS_PER_RANDCALL GMP_NUMB_BITS
     29      1.1  mrg #else
     30      1.1  mrg #define BITS_PER_RANDCALL 32
     31      1.1  mrg #endif
     32      1.1  mrg 
     33      1.1  mrg void
     34      1.1  mrg mpfr_random2 (mpfr_ptr x, mp_size_t size, mpfr_exp_t exp,
     35      1.1  mrg               gmp_randstate_t rstate)
     36      1.1  mrg {
     37      1.1  mrg   mp_size_t xn, k, ri;
     38      1.1  mrg   unsigned long sh;
     39      1.1  mrg   mp_limb_t *xp;
     40      1.1  mrg   mp_limb_t elimb, ran, acc;
     41      1.1  mrg   int ran_nbits, bit_pos, nb;
     42      1.1  mrg 
     43      1.1  mrg   if (MPFR_UNLIKELY(size == 0))
     44      1.1  mrg     {
     45      1.1  mrg       MPFR_SET_ZERO (x);
     46      1.1  mrg       MPFR_SET_POS (x);
     47      1.1  mrg       return ;
     48      1.1  mrg     }
     49      1.1  mrg   else if (size > 0)
     50      1.1  mrg     {
     51      1.1  mrg       MPFR_SET_POS (x);
     52      1.1  mrg     }
     53      1.1  mrg   else
     54      1.1  mrg     {
     55      1.1  mrg       MPFR_SET_NEG (x);
     56      1.1  mrg       size = -size;
     57      1.1  mrg     }
     58      1.1  mrg 
     59      1.1  mrg   xn = MPFR_LIMB_SIZE (x);
     60      1.1  mrg   xp = MPFR_MANT (x);
     61      1.1  mrg   if (size > xn)
     62      1.1  mrg     size = xn;
     63      1.1  mrg   k = xn - size;
     64      1.1  mrg 
     65      1.1  mrg   /* Code extracted from GMP, function mpn_random2, to avoid the use
     66      1.1  mrg      of GMP's internal random state in MPFR */
     67      1.1  mrg 
     68      1.1  mrg   mpfr_rand_raw (&elimb, rstate, BITS_PER_RANDCALL);
     69      1.1  mrg   ran = elimb;
     70      1.1  mrg 
     71      1.1  mrg   /* Start off at a random bit position in the most significant limb.  */
     72      1.1  mrg   bit_pos = GMP_NUMB_BITS - 1;
     73      1.1  mrg   ran >>= 6;                            /* Ideally   log2(GMP_NUMB_BITS) */
     74      1.1  mrg   ran_nbits = BITS_PER_RANDCALL - 6;    /* Ideally - log2(GMP_NUMB_BITS) */
     75      1.1  mrg 
     76      1.1  mrg   /* Bit 0 of ran chooses string of ones/string of zeroes.
     77      1.1  mrg      Make most significant limb be non-zero by setting bit 0 of RAN.  */
     78      1.1  mrg   ran |= 1;
     79      1.1  mrg   ri = xn - 1;
     80      1.1  mrg 
     81      1.1  mrg   acc = 0;
     82      1.1  mrg   while (ri >= k)
     83      1.1  mrg     {
     84      1.1  mrg       if (ran_nbits < LOGBITS_PER_BLOCK + 1)
     85      1.1  mrg         {
     86      1.1  mrg           mpfr_rand_raw (&elimb, rstate, BITS_PER_RANDCALL);
     87      1.1  mrg           ran = elimb;
     88      1.1  mrg           ran_nbits = BITS_PER_RANDCALL;
     89      1.1  mrg         }
     90      1.1  mrg 
     91      1.1  mrg       nb = (ran >> 1) % (1 << LOGBITS_PER_BLOCK) + 1;
     92      1.1  mrg       if ((ran & 1) != 0)
     93      1.1  mrg         {
     94      1.1  mrg           /* Generate a string of nb ones.  */
     95      1.1  mrg           if (nb > bit_pos)
     96      1.1  mrg             {
     97      1.1  mrg               xp[ri--] = acc | (((mp_limb_t) 2 << bit_pos) - 1);
     98      1.1  mrg               bit_pos += GMP_NUMB_BITS;
     99      1.1  mrg               bit_pos -= nb;
    100      1.1  mrg               acc = ((~(mp_limb_t) 1) << bit_pos) & GMP_NUMB_MASK;
    101      1.1  mrg             }
    102      1.1  mrg           else
    103      1.1  mrg             {
    104      1.1  mrg               bit_pos -= nb;
    105      1.1  mrg               acc |= (((mp_limb_t) 2 << nb) - 2) << bit_pos;
    106      1.1  mrg             }
    107      1.1  mrg         }
    108      1.1  mrg       else
    109      1.1  mrg         {
    110      1.1  mrg           /* Generate a string of nb zeroes.  */
    111      1.1  mrg           if (nb > bit_pos)
    112      1.1  mrg             {
    113      1.1  mrg               xp[ri--] = acc;
    114      1.1  mrg               acc = 0;
    115      1.1  mrg               bit_pos += GMP_NUMB_BITS;
    116      1.1  mrg             }
    117      1.1  mrg           bit_pos -= nb;
    118      1.1  mrg         }
    119      1.1  mrg       ran_nbits -= LOGBITS_PER_BLOCK + 1;
    120      1.1  mrg       ran >>= LOGBITS_PER_BLOCK + 1;
    121      1.1  mrg     }
    122      1.1  mrg 
    123      1.1  mrg   /* Set mandatory most significant bit.  */
    124      1.1  mrg   /* xp[xn - 1] |= MPFR_LIMB_HIGHBIT; */
    125      1.1  mrg 
    126      1.1  mrg   if (k != 0)
    127      1.1  mrg     {
    128      1.1  mrg       /* Clear last limbs */
    129      1.1  mrg       MPN_ZERO (xp, k);
    130      1.1  mrg     }
    131      1.1  mrg   else
    132      1.1  mrg     {
    133      1.1  mrg       /* Mask off non significant bits in the low limb.  */
    134      1.1  mrg       MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (x));
    135      1.1  mrg       xp[0] &= ~MPFR_LIMB_MASK (sh);
    136      1.1  mrg     }
    137      1.1  mrg 
    138      1.1  mrg   /* Generate random exponent.  */
    139      1.1  mrg   mpfr_rand_raw (&elimb, RANDS, GMP_NUMB_BITS);
    140      1.1  mrg   exp = ABS (exp);
    141      1.1  mrg   MPFR_SET_EXP (x, elimb % (2 * exp + 1) - exp);
    142      1.1  mrg 
    143      1.1  mrg   return ;
    144      1.1  mrg }
    145