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