Home | History | Annotate | Line # | Download | only in tests
random2.c revision 1.1.1.3.2.1
      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.2.1  pgoyette Copyright 1999, 2001-2004, 2006-2018 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.1.3.2.1  pgoyette /* exp is the maximum exponent in absolute value */
     34          1.1       mrg void
     35          1.1       mrg mpfr_random2 (mpfr_ptr x, mp_size_t size, mpfr_exp_t exp,
     36          1.1       mrg               gmp_randstate_t rstate)
     37          1.1       mrg {
     38          1.1       mrg   mp_size_t xn, k, ri;
     39          1.1       mrg   unsigned long sh;
     40          1.1       mrg   mp_limb_t *xp;
     41          1.1       mrg   mp_limb_t elimb, ran, acc;
     42          1.1       mrg   int ran_nbits, bit_pos, nb;
     43          1.1       mrg 
     44          1.1       mrg   if (MPFR_UNLIKELY(size == 0))
     45          1.1       mrg     {
     46          1.1       mrg       MPFR_SET_ZERO (x);
     47          1.1       mrg       MPFR_SET_POS (x);
     48          1.1       mrg       return ;
     49          1.1       mrg     }
     50          1.1       mrg   else if (size > 0)
     51          1.1       mrg     {
     52          1.1       mrg       MPFR_SET_POS (x);
     53          1.1       mrg     }
     54          1.1       mrg   else
     55          1.1       mrg     {
     56          1.1       mrg       MPFR_SET_NEG (x);
     57          1.1       mrg       size = -size;
     58          1.1       mrg     }
     59          1.1       mrg 
     60          1.1       mrg   xn = MPFR_LIMB_SIZE (x);
     61          1.1       mrg   xp = MPFR_MANT (x);
     62          1.1       mrg   if (size > xn)
     63          1.1       mrg     size = xn;
     64          1.1       mrg   k = xn - size;
     65          1.1       mrg 
     66          1.1       mrg   /* Code extracted from GMP, function mpn_random2, to avoid the use
     67          1.1       mrg      of GMP's internal random state in MPFR */
     68          1.1       mrg 
     69          1.1       mrg   mpfr_rand_raw (&elimb, rstate, BITS_PER_RANDCALL);
     70          1.1       mrg   ran = elimb;
     71          1.1       mrg 
     72          1.1       mrg   /* Start off at a random bit position in the most significant limb.  */
     73          1.1       mrg   bit_pos = GMP_NUMB_BITS - 1;
     74          1.1       mrg   ran >>= 6;                            /* Ideally   log2(GMP_NUMB_BITS) */
     75          1.1       mrg   ran_nbits = BITS_PER_RANDCALL - 6;    /* Ideally - log2(GMP_NUMB_BITS) */
     76          1.1       mrg 
     77          1.1       mrg   /* Bit 0 of ran chooses string of ones/string of zeroes.
     78          1.1       mrg      Make most significant limb be non-zero by setting bit 0 of RAN.  */
     79          1.1       mrg   ran |= 1;
     80          1.1       mrg   ri = xn - 1;
     81          1.1       mrg 
     82          1.1       mrg   acc = 0;
     83          1.1       mrg   while (ri >= k)
     84          1.1       mrg     {
     85          1.1       mrg       if (ran_nbits < LOGBITS_PER_BLOCK + 1)
     86          1.1       mrg         {
     87          1.1       mrg           mpfr_rand_raw (&elimb, rstate, BITS_PER_RANDCALL);
     88          1.1       mrg           ran = elimb;
     89          1.1       mrg           ran_nbits = BITS_PER_RANDCALL;
     90          1.1       mrg         }
     91          1.1       mrg 
     92          1.1       mrg       nb = (ran >> 1) % (1 << LOGBITS_PER_BLOCK) + 1;
     93          1.1       mrg       if ((ran & 1) != 0)
     94          1.1       mrg         {
     95          1.1       mrg           /* Generate a string of nb ones.  */
     96          1.1       mrg           if (nb > bit_pos)
     97          1.1       mrg             {
     98          1.1       mrg               xp[ri--] = acc | (((mp_limb_t) 2 << bit_pos) - 1);
     99          1.1       mrg               bit_pos += GMP_NUMB_BITS;
    100          1.1       mrg               bit_pos -= nb;
    101  1.1.1.3.2.1  pgoyette               acc = (~MPFR_LIMB_ONE) << bit_pos;
    102          1.1       mrg             }
    103          1.1       mrg           else
    104          1.1       mrg             {
    105          1.1       mrg               bit_pos -= nb;
    106          1.1       mrg               acc |= (((mp_limb_t) 2 << nb) - 2) << bit_pos;
    107          1.1       mrg             }
    108          1.1       mrg         }
    109          1.1       mrg       else
    110          1.1       mrg         {
    111          1.1       mrg           /* Generate a string of nb zeroes.  */
    112          1.1       mrg           if (nb > bit_pos)
    113          1.1       mrg             {
    114          1.1       mrg               xp[ri--] = acc;
    115          1.1       mrg               acc = 0;
    116          1.1       mrg               bit_pos += GMP_NUMB_BITS;
    117          1.1       mrg             }
    118          1.1       mrg           bit_pos -= nb;
    119          1.1       mrg         }
    120          1.1       mrg       ran_nbits -= LOGBITS_PER_BLOCK + 1;
    121          1.1       mrg       ran >>= LOGBITS_PER_BLOCK + 1;
    122          1.1       mrg     }
    123          1.1       mrg 
    124          1.1       mrg   /* Set mandatory most significant bit.  */
    125          1.1       mrg   /* xp[xn - 1] |= MPFR_LIMB_HIGHBIT; */
    126          1.1       mrg 
    127          1.1       mrg   if (k != 0)
    128          1.1       mrg     {
    129          1.1       mrg       /* Clear last limbs */
    130          1.1       mrg       MPN_ZERO (xp, k);
    131          1.1       mrg     }
    132          1.1       mrg   else
    133          1.1       mrg     {
    134          1.1       mrg       /* Mask off non significant bits in the low limb.  */
    135          1.1       mrg       MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (x));
    136          1.1       mrg       xp[0] &= ~MPFR_LIMB_MASK (sh);
    137          1.1       mrg     }
    138          1.1       mrg 
    139          1.1       mrg   /* Generate random exponent.  */
    140          1.1       mrg   mpfr_rand_raw (&elimb, RANDS, GMP_NUMB_BITS);
    141  1.1.1.3.2.1  pgoyette   MPFR_ASSERTN (exp >= 0 && exp <= MPFR_EMAX_MAX);
    142  1.1.1.3.2.1  pgoyette   exp = (mpfr_exp_t) (elimb % (2 * exp + 1)) - exp;
    143  1.1.1.3.2.1  pgoyette   MPFR_SET_EXP (x, exp);
    144          1.1       mrg 
    145          1.1       mrg   return ;
    146          1.1       mrg }
    147