(root)/
mpfr-4.2.1/
tests/
tconst_pi.c
       1  /* Test file for mpfr_const_pi.
       2  
       3  Copyright 1999, 2001-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  #if defined(MPFR_WANT_SHARED_CACHE) && defined(HAVE_PTHREAD)
      26  
      27  # include <pthread.h>
      28  
      29  #define MAX_THREAD 100
      30  
      31  static void *
      32  start_routine (void *arg)
      33  {
      34    mpfr_prec_t p;
      35    mpfr_t x;
      36    mpfr_prec_t inc = *(int *) arg;
      37    mp_limb_t *m;
      38  
      39    for (p = 100; p < 20000; p += 64 + 100 * (inc % 10))
      40      {
      41        mpfr_init2 (x, p);
      42        m = MPFR_MANT (x);
      43        mpfr_const_pi (x, MPFR_RNDD);
      44        mpfr_prec_round (x, 53, MPFR_RNDD);
      45        if (mpfr_cmp_str1 (x, "3.141592653589793116"))
      46          {
      47            printf ("mpfr_const_pi failed with threading\n");
      48            mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n');
      49            exit (1);
      50          }
      51        /* Check that no reallocation has been performed */
      52        MPFR_ASSERTN (m == MPFR_MANT (x));
      53        mpfr_clear (x);
      54      }
      55  
      56    pthread_exit (NULL);
      57  }
      58  
      59  static void
      60  run_pthread_test (void)
      61  {
      62    int i;
      63    int error_code;
      64    pthread_t thread_id[MAX_THREAD];
      65    int table[MAX_THREAD];
      66  
      67    for (i = 0; i < MAX_THREAD; i++)
      68      {
      69        table[i] = i;
      70        error_code = pthread_create(&thread_id[i],
      71                                    NULL, start_routine, &table[i]);
      72        MPFR_ASSERTN (error_code == 0);
      73      }
      74  
      75    for (i = 0; i < MAX_THREAD; i++)
      76      {
      77        error_code = pthread_join (thread_id[i], NULL);
      78        MPFR_ASSERTN (error_code == 0);
      79      }
      80  }
      81  
      82  # define RUN_PTHREAD_TEST()                                             \
      83    (MPFR_ASSERTN(mpfr_buildopt_sharedcache_p() == 1), run_pthread_test())
      84  
      85  #else
      86  
      87  # define RUN_PTHREAD_TEST() ((void) 0)
      88  
      89  #endif
      90  
      91  /* tconst_pi [prec] [rnd] [0 = no print] */
      92  
      93  static void
      94  check_large (void)
      95  {
      96    mpfr_t x, y, z;
      97  
      98    mpfr_init2 (x, 20000);
      99    mpfr_init2 (y, 21000);
     100    mpfr_init2 (z, 11791);
     101  
     102    /* The algo failed to round for p=11791. */
     103    (mpfr_const_pi) (z, MPFR_RNDU);
     104    mpfr_const_pi (x, MPFR_RNDN); /* First one ! */
     105    mpfr_const_pi (y, MPFR_RNDN); /* Then the other - cache - */
     106    mpfr_prec_round (y, 20000, MPFR_RNDN);
     107    if (mpfr_cmp (x, y)) {
     108      printf ("const_pi: error for large prec (%d)\n", 1);
     109      exit (1);
     110    }
     111    mpfr_prec_round (y, 11791, MPFR_RNDU);
     112    if (mpfr_cmp (z, y)) {
     113      printf ("const_pi: error for large prec (%d)\n", 2);
     114      exit (1);
     115    }
     116  
     117    /* a worst-case to exercise recomputation */
     118    if (MPFR_PREC_MAX > 33440) {
     119      mpfr_set_prec (x, 33440);
     120      mpfr_const_pi (x, MPFR_RNDZ);
     121    }
     122  
     123    mpfr_clears (x, y, z, (mpfr_ptr) 0);
     124  }
     125  
     126  /* Wrapper for tgeneric */
     127  static int
     128  my_const_pi (mpfr_ptr x, mpfr_srcptr y, mpfr_rnd_t r)
     129  {
     130    return mpfr_const_pi (x, r);
     131  }
     132  
     133  #define RAND_FUNCTION(x) mpfr_set_ui ((x), 0, MPFR_RNDN)
     134  #define TEST_FUNCTION my_const_pi
     135  #include "tgeneric.c"
     136  
     137  static void
     138  bug20091030 (void)
     139  {
     140    mpfr_t x, x_ref;
     141    int inex, inex_ref;
     142    mpfr_prec_t p;
     143    int r;
     144  
     145    mpfr_free_cache ();
     146    mpfr_init2 (x, MPFR_PREC_MIN);
     147    for (p = MPFR_PREC_MIN; p <= 100; p++)
     148      {
     149        mpfr_set_prec (x, p);
     150        inex = mpfr_const_pi (x, MPFR_RNDU);
     151        if (inex < 0)
     152          {
     153            printf ("Error, inex < 0 for RNDU (prec=%lu)\n",
     154                    (unsigned long) p);
     155            exit (1);
     156          }
     157        inex = mpfr_const_pi (x, MPFR_RNDD);
     158        if (inex > 0)
     159          {
     160            printf ("Error, inex > 0 for RNDD (prec=%lu)\n",
     161                    (unsigned long) p);
     162            exit (1);
     163          }
     164      }
     165    mpfr_free_cache ();
     166    mpfr_init2 (x_ref, MPFR_PREC_MIN);
     167    for (p = MPFR_PREC_MIN; p <= 100; p++)
     168      {
     169        mpfr_set_prec (x, p + 10);
     170        mpfr_const_pi (x, MPFR_RNDN);
     171        mpfr_set_prec (x, p);
     172        mpfr_set_prec (x_ref, p);
     173        RND_LOOP (r)
     174          {
     175            if (r == MPFR_RNDF)
     176              continue; /* the test below makes no sense */
     177            inex = mpfr_const_pi (x, (mpfr_rnd_t) r);
     178            inex_ref = mpfr_const_pi_internal (x_ref, (mpfr_rnd_t) r);
     179            if (inex != inex_ref || mpfr_cmp (x, x_ref) != 0)
     180              {
     181                printf ("mpfr_const_pi and mpfr_const_pi_internal disagree for rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
     182                printf ("mpfr_const_pi gives ");
     183                mpfr_dump (x);
     184                printf ("mpfr_const_pi_internal gives ");
     185                mpfr_dump (x_ref);
     186                printf ("inex=%d inex_ref=%d\n", inex, inex_ref);
     187                exit (1);
     188              }
     189          }
     190      }
     191    mpfr_clear (x);
     192    mpfr_clear (x_ref);
     193  }
     194  
     195  int
     196  main (int argc, char *argv[])
     197  {
     198    mpfr_t x;
     199    mpfr_prec_t p;
     200    mpfr_rnd_t rnd;
     201  
     202    tests_start_mpfr ();
     203  
     204    p = 53;
     205    if (argc > 1)
     206      {
     207        long a = atol (argv[1]);
     208        if (MPFR_PREC_COND (a))
     209          p = a;
     210      }
     211  
     212    rnd = (argc > 2) ? (mpfr_rnd_t) atoi(argv[2]) : MPFR_RNDZ;
     213  
     214    mpfr_init2 (x, p);
     215    mpfr_const_pi (x, rnd);
     216    if (argc >= 2)
     217      {
     218        if (argc < 4 || atoi (argv[3]) != 0)
     219          {
     220            printf ("Pi=");
     221            mpfr_out_str (stdout, 10, 0, x, rnd);
     222            puts ("");
     223          }
     224      }
     225    else if (mpfr_cmp_str1 (x, "3.141592653589793116") )
     226      {
     227        printf ("mpfr_const_pi failed for prec=53\n");
     228        mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n');
     229        exit (1);
     230      }
     231  
     232    mpfr_set_prec (x, 32);
     233    mpfr_const_pi (x, MPFR_RNDN);
     234    if (mpfr_cmp_str1 (x, "3.141592653468251") )
     235      {
     236        printf ("mpfr_const_pi failed for prec=32\n");
     237        exit (1);
     238      }
     239  
     240    mpfr_clear (x);
     241  
     242    bug20091030 ();
     243  
     244    check_large ();
     245  
     246    test_generic (MPFR_PREC_MIN, 200, 1);
     247  
     248    RUN_PTHREAD_TEST();
     249  
     250    /* the following is just to test mpfr_free_cache2 with MPFR_FREE_LOCAL_CACHE,
     251       it should not hurt, since the call to mpfr_free_cache in tests_end_mpfr
     252       will do nothing */
     253    mpfr_free_cache2 (MPFR_FREE_LOCAL_CACHE);
     254  
     255    tests_end_mpfr ();
     256  
     257    /* another test of mpfr_free_cache2 with MPFR_FREE_LOCAL_CACHE, to check
     258       that we can call it when the caches are already freed */
     259    mpfr_free_cache2 (MPFR_FREE_LOCAL_CACHE);
     260  
     261    return 0;
     262  }