(root)/
mpfr-4.2.1/
tests/
trandom.c
       1  /* Test file for mpfr_urandomb
       2  
       3  Copyright 1999-2004, 2006-2023 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
      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
     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
     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  }