xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/turandom.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /* Test file for mpfr_urandom
2 
3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao 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 http://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 <stdio.h>
24 #include <stdlib.h>
25 
26 #include "mpfr-test.h"
27 
28 static void
29 test_urandom (long nbtests, mpfr_prec_t prec, mpfr_rnd_t rnd, long bit_index,
30               int verbose)
31 {
32   mpfr_t x;
33   int *tab, size_tab, k, sh, xn;
34   double d, av = 0, var = 0, chi2 = 0, th;
35   mpfr_exp_t emin;
36   mp_size_t limb_index = 0;
37   mp_limb_t limb_mask = 0;
38   long count = 0;
39   int i;
40   int inex = 1;
41 
42   size_tab = (nbtests >= 1000 ? nbtests / 50 : 20);
43   tab = (int *) calloc (size_tab, sizeof(int));
44   if (tab == NULL)
45     {
46       fprintf (stderr, "trandom: can't allocate memory in test_urandom\n");
47       exit (1);
48     }
49 
50   mpfr_init2 (x, prec);
51   xn = 1 + (prec - 1) / mp_bits_per_limb;
52   sh = xn * mp_bits_per_limb - prec;
53   if (bit_index >= 0 && bit_index < prec)
54     {
55       /* compute the limb index and limb mask to fetch the bit #bit_index */
56       limb_index = (prec - bit_index) / mp_bits_per_limb;
57       i = 1 + bit_index - (bit_index / mp_bits_per_limb) * mp_bits_per_limb;
58       limb_mask = MPFR_LIMB_ONE << (mp_bits_per_limb - i);
59     }
60 
61   for (k = 0; k < nbtests; k++)
62     {
63       i = mpfr_urandom (x, RANDS, rnd);
64       inex = (i != 0) && inex;
65       /* check that lower bits are zero */
66       if (MPFR_MANT(x)[0] & MPFR_LIMB_MASK(sh) && !MPFR_IS_ZERO (x))
67         {
68           printf ("Error: mpfr_urandom() returns invalid numbers:\n");
69           mpfr_print_binary (x); puts ("");
70           exit (1);
71         }
72       /* check that the value is in [0,1] */
73       if (mpfr_cmp_ui (x, 0) < 0 || mpfr_cmp_ui (x, 1) > 0)
74         {
75           printf ("Error: mpfr_urandom() returns number outside [0, 1]:\n");
76           mpfr_print_binary (x); puts ("");
77           exit (1);
78         }
79 
80       d = mpfr_get_d1 (x); av += d; var += d*d;
81       i = (int)(size_tab * d);
82       if (d == 1.0) i --;
83       tab[i]++;
84 
85       if (limb_mask && (MPFR_MANT (x)[limb_index] & limb_mask))
86         count ++;
87     }
88 
89   if (inex == 0)
90     {
91       /* one call in the loop pretended to return an exact number! */
92       printf ("Error: mpfr_urandom() returns a zero ternary value.\n");
93       exit (1);
94     }
95 
96   /* coverage test */
97   emin = mpfr_get_emin ();
98   for (k = 0; k < 5; k++)
99     {
100       set_emin (k+1);
101       inex = mpfr_urandom (x, RANDS, rnd);
102       if ((   (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
103               && (!MPFR_IS_ZERO (x) || inex != -1))
104           || ((rnd == MPFR_RNDU || rnd == MPFR_RNDA)
105               && (mpfr_cmp_ui (x, 1 << k) != 0 || inex != +1))
106           || (rnd == MPFR_RNDN
107               && (k > 0 || mpfr_cmp_ui (x, 1 << k) != 0 || inex != +1)
108               && (!MPFR_IS_ZERO (x) || inex != -1)))
109         {
110           printf ("Error: mpfr_urandom() do not handle correctly a restricted"
111                   " exponent range.\nrounding mode: %s\nternary value: %d\n"
112                   "random value: ", mpfr_print_rnd_mode (rnd), inex);
113           mpfr_print_binary (x); puts ("");
114           exit (1);
115         }
116     }
117   set_emin (emin);
118 
119   mpfr_clear (x);
120   if (!verbose)
121     {
122       free(tab);
123       return;
124     }
125 
126   av /= nbtests;
127   var = (var / nbtests) - av * av;
128 
129   th = (double)nbtests / size_tab;
130   printf ("Average = %.5f\nVariance = %.5f\n", av, var);
131   printf ("Repartition for urandom with rounding mode %s. "
132           "Each integer should be close to %d.\n",
133          mpfr_print_rnd_mode (rnd), (int)th);
134 
135   for (k = 0; k < size_tab; k++)
136     {
137       chi2 += (tab[k] - th) * (tab[k] - th) / th;
138       printf("%d ", tab[k]);
139       if (((k+1) & 7) == 0)
140         printf("\n");
141     }
142 
143   printf("\nChi2 statistics value (with %d degrees of freedom) : %.5f\n",
144          size_tab - 1, chi2);
145 
146   if (limb_mask)
147     printf ("Bit #%ld is set %ld/%ld = %.1f %% of time\n",
148             bit_index, count, nbtests, count * 100.0 / nbtests);
149 
150   puts ("");
151 
152   free(tab);
153   return;
154 }
155 
156 
157 int
158 main (int argc, char *argv[])
159 {
160   long nbtests;
161   mpfr_prec_t prec;
162   int verbose = 0;
163   int rnd;
164   long bit_index;
165 
166   tests_start_mpfr ();
167 
168   if (argc > 1)
169     verbose = 1;
170 
171   nbtests = 10000;
172   if (argc > 1)
173     {
174       long a = atol(argv[1]);
175       if (a != 0)
176         nbtests = a;
177     }
178 
179   if (argc <= 2)
180     prec = 1000;
181   else
182     prec = atol(argv[2]);
183 
184   if (argc <= 3)
185     bit_index = -1;
186   else
187     {
188       bit_index = atol(argv[3]);
189       if (bit_index >= prec)
190         {
191           printf ("Warning. Cannot compute the bit frequency: the given bit "
192                   "index (= %ld) is not less than the precision (= %ld).\n",
193                   bit_index, prec);
194           bit_index = -1;
195         }
196     }
197 
198   RND_LOOP(rnd)
199     {
200       test_urandom (nbtests, prec, (mpfr_rnd_t) rnd, bit_index, verbose);
201 
202       if (argc == 1)  /* check also small precision */
203         {
204           test_urandom (nbtests, 2, (mpfr_rnd_t) rnd, -1, 0);
205         }
206     }
207 
208   tests_end_mpfr ();
209   return 0;
210 }
211