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