summaryrefslogtreecommitdiff
path: root/tests/turandom.c
diff options
context:
space:
mode:
authorthevenyp <thevenyp@280ebfd0-de03-0410-8827-d642c229c3f4>2010-01-13 18:12:54 +0000
committerthevenyp <thevenyp@280ebfd0-de03-0410-8827-d642c229c3f4>2010-01-13 18:12:54 +0000
commit83d4eefdf522528bd15ba629de5bb5daec320b68 (patch)
tree78fab7a50f50fd49d7228080d030dee490bc9815 /tests/turandom.c
parent793ef03698899a4481974eb520c23e1dcb281a37 (diff)
downloadmpfr-83d4eefdf522528bd15ba629de5bb5daec320b68.tar.gz
New function mpfr_urandom.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@6654 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tests/turandom.c')
-rw-r--r--tests/turandom.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/tests/turandom.c b/tests/turandom.c
new file mode 100644
index 000000000..7c3af4595
--- /dev/null
+++ b/tests/turandom.c
@@ -0,0 +1,187 @@
+/* Test file for mpfr_urandom
+
+Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+Contributed by the Arenaire and Cacao projects, INRIA.
+
+This file is part of the GNU MPFR Library.
+
+The GNU MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+The GNU MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
+http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mpfr-test.h"
+
+static void
+test_urandom (long nbtests, mp_prec_t prec, mpfr_rnd_t rnd, long bit_index,
+ int verbose)
+{
+ mpfr_t x;
+ int *tab, size_tab, k, sh, xn;
+ double d, av = 0, var = 0, chi2 = 0, th;
+ mp_exp_t emin;
+ mp_size_t limb_index = 0;
+ mp_limb_t limb_mask = 0;
+ long count = 0;
+ int i;
+
+ size_tab = (nbtests >= 1000 ? nbtests / 50 : 20);
+ tab = (int *) calloc (size_tab, sizeof(int));
+ if (tab == NULL)
+ {
+ fprintf (stderr, "trandom: can't allocate memory in test_urandom\n");
+ exit (1);
+ }
+
+ mpfr_init2 (x, prec);
+ xn = 1 + (prec - 1) / mp_bits_per_limb;
+ sh = xn * mp_bits_per_limb - prec;
+ if (bit_index >= 0 && bit_index < prec)
+ {
+ /* compute the limb index and limb mask to fetch the bit #bit_index */
+ limb_index = (prec - bit_index) / mp_bits_per_limb;
+ i = 1 + bit_index - (bit_index / mp_bits_per_limb) * mp_bits_per_limb;
+ limb_mask = MPFR_LIMB_ONE << (mp_bits_per_limb - i);
+ }
+
+ for (k = 0; k < nbtests; k++)
+ {
+ mpfr_urandom (x, RANDS, rnd);
+ /* check that lower bits are zero */
+ if (MPFR_MANT(x)[0] & MPFR_LIMB_MASK(sh) && !MPFR_IS_ZERO (x))
+ {
+ printf ("Error: mpfr_urandom() returns invalid numbers:\n");
+ mpfr_print_binary (x); puts ("");
+ exit (1);
+ }
+ d = mpfr_get_d1 (x); av += d; var += d*d;
+ i = (int)(size_tab * d);
+ if (d == 1.0) i --;
+ tab[i]++;
+
+ if (limb_mask && (MPFR_MANT (x)[limb_index] & limb_mask))
+ count ++;
+ }
+
+ /* coverage test */
+ emin = mpfr_get_emin ();
+ set_emin (1);
+ /* the generated number in [0,1] is not in the exponent range, except:
+ - if it is zero and rnd is toward zero or to nearest
+ - if it is one and rnd is not toward zero and not to nearest */
+ k = mpfr_urandom (x, RANDS, rnd);
+ if ((k == 0 || mpfr_nan_p (x) == 0)
+ && (((rnd != MPFR_RNDZ && rnd != MPFR_RNDN) && MPFR_IS_ZERO (x))
+ || ((rnd==MPFR_RNDZ || rnd==MPFR_RNDN) && mpfr_cmp_ui (x, 1)==0)))
+ {
+ printf ("Error in mpfr_urandom, expected NaN, got ");
+ mpfr_dump (x);
+ exit (1);
+ }
+ set_emin (emin);
+
+ mpfr_clear (x);
+ if (!verbose)
+ {
+ free(tab);
+ return;
+ }
+
+ av /= nbtests;
+ var = (var / nbtests) - av * av;
+
+ th = (double)nbtests / size_tab;
+ printf("Average = %.5f\nVariance = %.5f\n", av, var);
+ printf("Repartition for urandom with rounding mode %s. "
+ "Each integer should be close to %d.\n",
+ mpfr_print_rnd_mode (rnd), (int)th);
+
+ for (k = 0; k < size_tab; k++)
+ {
+ chi2 += (tab[k] - th) * (tab[k] - th) / th;
+ printf("%d ", tab[k]);
+ if (((k+1) & 7) == 0)
+ printf("\n");
+ }
+
+ printf("\nChi2 statistics value (with %d degrees of freedom) : %.5f\n",
+ size_tab - 1, chi2);
+
+ if (limb_mask)
+ printf ("Bit #%ld is set %ld/%ld = %.1f %% of time\n",
+ bit_index, count, nbtests, count * 100.0 / nbtests);
+
+ puts ("");
+
+ free(tab);
+ return;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ long nbtests;
+ mp_prec_t prec;
+ int verbose = 0;
+ mpfr_rnd_t rnd;
+ long bit_index;
+
+ tests_start_mpfr ();
+
+ if (argc > 1)
+ verbose = 1;
+
+ nbtests = 10000;
+ if (argc > 1)
+ {
+ long a = atol(argv[1]);
+ if (a != 0)
+ nbtests = a;
+ }
+
+ if (argc <= 2)
+ prec = 1000;
+ else
+ prec = atol(argv[2]);
+
+ if (argc <= 3)
+ bit_index = -1;
+ else
+ {
+ bit_index = atol(argv[3]);
+ if (bit_index >= prec)
+ {
+ printf ("Warning. Cannot compute the bit frequency: the given bit "
+ "index (= %ld) is not less than the precision (= %ld).\n",
+ bit_index, prec);
+ bit_index = -1;
+ }
+ }
+
+ RND_LOOP(rnd)
+ {
+ test_urandom (nbtests, prec, rnd, bit_index, verbose);
+
+ if (argc == 1) /* check also small precision */
+ {
+ test_urandom (nbtests, 2, rnd, -1, 0);
+ }
+ }
+
+ tests_end_mpfr ();
+ return 0;
+}