(root)/
mpfr-4.2.1/
src/
const_catalan.c
       1  /* mpfr_const_catalan -- compute Catalan's constant.
       2  
       3  Copyright 2005-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  #define MPFR_NEED_LONGLONG_H
      24  #include "mpfr-impl.h"
      25  
      26  /* Declare the cache */
      27  MPFR_DECL_INIT_CACHE (__gmpfr_cache_const_catalan, mpfr_const_catalan_internal)
      28  
      29  /* Set User Interface */
      30  #undef mpfr_const_catalan
      31  int
      32  mpfr_const_catalan (mpfr_ptr x, mpfr_rnd_t rnd_mode) {
      33    return mpfr_cache (x, __gmpfr_cache_const_catalan, rnd_mode);
      34  }
      35  
      36  /* return T, Q such that T/Q = sum(k!^2/(2k)!/(2k+1)^2, k=n1..n2-1) */
      37  static void
      38  S (mpz_t T, mpz_t P, mpz_t Q, unsigned long n1, unsigned long n2)
      39  {
      40    if (n2 == n1 + 1)
      41      {
      42        if (n1 == 0)
      43          {
      44            mpz_set_ui (P, 1);
      45            mpz_set_ui (Q, 1);
      46          }
      47        else
      48          {
      49            mpz_set_ui (P, 2 * n1 - 1);
      50            mpz_mul_ui (P, P, n1);
      51            mpz_ui_pow_ui (Q, 2 * n1 + 1, 2);
      52            mpz_mul_2exp (Q, Q, 1);
      53          }
      54        mpz_set (T, P);
      55      }
      56    else
      57      {
      58        unsigned long m = (n1 + n2) / 2;
      59        mpz_t T2, P2, Q2;
      60        S (T, P, Q, n1, m);
      61        mpz_init (T2);
      62        mpz_init (P2);
      63        mpz_init (Q2);
      64        S (T2, P2, Q2, m, n2);
      65        mpz_mul (T, T, Q2);
      66        mpz_mul (T2, T2, P);
      67        mpz_add (T, T, T2);
      68        mpz_mul (P, P, P2);
      69        mpz_mul (Q, Q, Q2);
      70        mpz_clear (T2);
      71        mpz_clear (P2);
      72        mpz_clear (Q2);
      73      }
      74  }
      75  
      76  /* Don't need to save/restore exponent range: the cache does it.
      77     Catalan's constant is G = sum((-1)^k/(2*k+1)^2, k=0..infinity).
      78     We compute it using formula (31) of Victor Adamchik's page
      79     "33 representations for Catalan's constant"
      80     https://web.archive.org/web/20090624123133/http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm
      81  
      82     G = Pi/8*log(2+sqrt(3)) + 3/8*sum(k!^2/(2k)!/(2k+1)^2,k=0..infinity)
      83  */
      84  int
      85  mpfr_const_catalan_internal (mpfr_ptr g, mpfr_rnd_t rnd_mode)
      86  {
      87    mpfr_t x, y, z;
      88    mpz_t T, P, Q;
      89    mpfr_prec_t pg, p;
      90    int inex;
      91    MPFR_ZIV_DECL (loop);
      92    MPFR_GROUP_DECL (group);
      93  
      94    MPFR_LOG_FUNC (("rnd_mode=%d", rnd_mode),
      95      ("g[%Pd]=%.*Rg inex=%d", mpfr_get_prec (g), mpfr_log_prec, g, inex));
      96  
      97    /* Here are the WC (max prec = 100.000.000)
      98       Once we have found a chain of 11, we only look for bigger chain.
      99       Found 3 '1' at 0
     100       Found 5 '1' at 9
     101       Found 6 '0' at 34
     102       Found 9 '1' at 176
     103       Found 11 '1' at 705
     104       Found 12 '0' at 913
     105       Found 14 '1' at 12762
     106       Found 15 '1' at 152561
     107       Found 16 '0' at 171725
     108       Found 18 '0' at 525355
     109       Found 20 '0' at 529245
     110       Found 21 '1' at 6390133
     111       Found 22 '0' at 7806417
     112       Found 25 '1' at 11936239
     113       Found 27 '1' at 51752950
     114    */
     115    pg = MPFR_PREC (g);
     116    p = pg + MPFR_INT_CEIL_LOG2 (pg) + 7;
     117  
     118    MPFR_GROUP_INIT_3 (group, p, x, y, z);
     119    mpz_init (T);
     120    mpz_init (P);
     121    mpz_init (Q);
     122  
     123    MPFR_ZIV_INIT (loop, p);
     124    for (;;) {
     125      mpfr_sqrt_ui (x, 3, MPFR_RNDU);
     126      mpfr_add_ui (x, x, 2, MPFR_RNDU);
     127      mpfr_log (x, x, MPFR_RNDU);
     128      mpfr_const_pi (y, MPFR_RNDU);
     129      mpfr_mul (x, x, y, MPFR_RNDN);
     130      S (T, P, Q, 0, (p - 1) / 2);
     131      mpz_mul_ui (T, T, 3);
     132      mpfr_set_z (y, T, MPFR_RNDU);
     133      mpfr_set_z (z, Q, MPFR_RNDD);
     134      mpfr_div (y, y, z, MPFR_RNDN);
     135      mpfr_add (x, x, y, MPFR_RNDN);
     136      mpfr_div_2ui (x, x, 3, MPFR_RNDN);
     137  
     138      if (MPFR_LIKELY (MPFR_CAN_ROUND (x, p - 5, pg, rnd_mode)))
     139        break;
     140  
     141      MPFR_ZIV_NEXT (loop, p);
     142      MPFR_GROUP_REPREC_3 (group, p, x, y, z);
     143    }
     144    MPFR_ZIV_FREE (loop);
     145    inex = mpfr_set (g, x, rnd_mode);
     146  
     147    MPFR_GROUP_CLEAR (group);
     148    mpz_clear (T);
     149    mpz_clear (P);
     150    mpz_clear (Q);
     151  
     152    return inex;
     153  }