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