1 /* Test file for mpfr_urandomb
2
3 Copyright 1999-2004, 2006-2020 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include "mpfr-test.h"
24
25 static void
test_urandomb(long nbtests,mpfr_prec_t prec,int verbose)26 test_urandomb (long nbtests, mpfr_prec_t prec, int verbose)
27 {
28 mpfr_t x;
29 int *tab, size_tab, k, sh, xn;
30 double d, av = 0, var = 0, chi2 = 0, th;
31 mpfr_exp_t emin;
32
33 size_tab = (nbtests >= 1000 ? nbtests / 50 : 20);
34 tab = (int *) tests_allocate (size_tab * sizeof (int));
35 for (k = 0; k < size_tab; k++)
36 tab[k] = 0;
37
38 mpfr_init2 (x, prec);
39 xn = 1 + (prec - 1) / mp_bits_per_limb;
40 sh = xn * mp_bits_per_limb - prec;
41
42 for (k = 0; k < nbtests; k++)
43 {
44 mpfr_urandomb (x, RANDS);
45 MPFR_ASSERTN (MPFR_IS_FP (x));
46 /* check that lower bits are zero */
47 if (MPFR_NOTZERO(x) && (MPFR_MANT(x)[0] & MPFR_LIMB_MASK(sh)))
48 {
49 printf ("Error: mpfr_urandomb() returns invalid numbers:\n");
50 mpfr_dump (x);
51 exit (1);
52 }
53 d = mpfr_get_d1 (x); av += d; var += d*d;
54 tab[(int)(size_tab * d)]++;
55 }
56
57 /* coverage test */
58 emin = mpfr_get_emin ();
59 set_emin (1); /* the generated number in [0,1[ is not in the exponent
60 range, except if it is zero */
61 k = mpfr_urandomb (x, RANDS);
62 if (MPFR_IS_ZERO(x) == 0 && (k == 0 || mpfr_nan_p (x) == 0))
63 {
64 printf ("Error in mpfr_urandomb, expected NaN, got ");
65 mpfr_dump (x);
66 exit (1);
67 }
68 set_emin (emin);
69
70 mpfr_clear (x);
71
72 if (verbose)
73 {
74 av /= nbtests;
75 var = (var / nbtests) - av * av;
76
77 th = (double) nbtests / size_tab;
78 printf ("Average = %.5f\nVariance = %.5f\n", av, var);
79 printf ("Repartition for urandomb. Each integer should be close to"
80 " %d.\n", (int) th);
81
82 for (k = 0; k < size_tab; k++)
83 {
84 chi2 += (tab[k] - th) * (tab[k] - th) / th;
85 printf ("%d ", tab[k]);
86 if (((unsigned int) (k+1) & 7) == 0)
87 printf ("\n");
88 }
89
90 printf ("\nChi2 statistics value (with %d degrees of freedom) :"
91 " %.5f\n\n", size_tab - 1, chi2);
92 }
93
94 tests_free (tab, size_tab * sizeof (int));
95 return;
96 }
97
98 #ifndef MPFR_USE_MINI_GMP
99 /* Problem reported by Carl Witty: check mpfr_urandomb give similar results
100 on 32-bit and 64-bit machines.
101 We assume the default GMP random generator does not depend on the machine
102 word size, not on the GMP version.
103 */
104 static void
bug20100914(void)105 bug20100914 (void)
106 {
107 mpfr_t x;
108 gmp_randstate_t s;
109
110 #if __MPFR_GMP(4,2,0)
111 # define C1 "0.895943"
112 # define C2 "0.848824"
113 #else
114 # define C1 "0.479652"
115 # define C2 "0.648529"
116 #endif
117
118 gmp_randinit_default (s);
119 gmp_randseed_ui (s, 42);
120 mpfr_init2 (x, 17);
121 mpfr_urandomb (x, s);
122 if (mpfr_cmp_str1 (x, C1) != 0)
123 {
124 printf ("Error in bug20100914, expected " C1 ", got ");
125 mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
126 printf ("\n");
127 exit (1);
128 }
129 mpfr_urandomb (x, s);
130 if (mpfr_cmp_str1 (x, C2) != 0)
131 {
132 printf ("Error in bug20100914, expected " C2 ", got ");
133 mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
134 printf ("\n");
135 exit (1);
136 }
137 mpfr_clear (x);
138 gmp_randclear (s);
139 }
140 #endif
141
142 int
main(int argc,char * argv[])143 main (int argc, char *argv[])
144 {
145 long nbtests;
146 mpfr_prec_t prec;
147 int verbose = 0;
148
149 tests_start_mpfr ();
150
151 if (argc > 1)
152 verbose = 1;
153
154 nbtests = 10000;
155 if (argc > 1)
156 {
157 long a = atol (argv[1]);
158 if (a != 0)
159 nbtests = a;
160 }
161
162 if (argc <= 2)
163 prec = 1000;
164 else
165 prec = atol (argv[2]);
166
167 test_urandomb (nbtests, prec, verbose);
168
169 if (argc == 1) /* check also small precision */
170 {
171 test_urandomb (nbtests, 2, 0);
172 }
173
174 #ifndef MPFR_USE_MINI_GMP
175
176 /* Since these tests assume a deterministic random generator, and this
177 is not implemented in mini-gmp, we omit them with mini-gmp. */
178
179 bug20100914 ();
180
181 #if __MPFR_GMP(4,2,0)
182 /* Get a non-zero fixed-point number whose first 32 bits are 0 with the
183 default GMP PRNG. This corresponds to the case cnt == 0 && k != 0 in
184 src/urandomb.c (fixed in r8762) with the 32-bit ABI. */
185 {
186 gmp_randstate_t s;
187 mpfr_t x;
188 const char *str = "0.1010111100000000000000000000000000000000E-32";
189 int k;
190
191 gmp_randinit_default (s);
192 gmp_randseed_ui (s, 4518);
193 mpfr_init2 (x, 40);
194
195 for (k = 0; k < 575123; k++)
196 {
197 mpfr_urandomb (x, s);
198 MPFR_ASSERTN (MPFR_IS_FP (x));
199 }
200
201 if (mpfr_cmp_str (x, str, 2, MPFR_RNDN) != 0)
202 {
203 printf ("Error in test_urandomb:\n");
204 printf ("Expected %s\n", str);
205 printf ("Got ");
206 mpfr_dump (x);
207 exit (1);
208 }
209
210 mpfr_clear (x);
211 gmp_randclear (s);
212 }
213 #endif
214
215 #endif
216
217 tests_end_mpfr ();
218 return 0;
219 }
220