(root)/
mpfr-4.2.1/
src/
pool.c
       1  /* mpz_t pool
       2  
       3  Copyright 2014-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_POOL_DONT_REDEFINE
      24  #include "mpfr-impl.h"
      25  
      26  #ifndef MPFR_POOL_MAX_SIZE
      27  # define MPFR_POOL_MAX_SIZE 32 /* maximal size (in limbs) for each entry */
      28  #endif
      29  
      30  /* If the number of entries of the mpz_t pool is not zero */
      31  #if MPFR_POOL_NENTRIES
      32  
      33  /* Index in the stack table of mpz_t and stack table of mpz_t */
      34  static MPFR_THREAD_ATTR int n_alloc = 0;
      35  static MPFR_THREAD_ATTR __mpz_struct mpz_tab[MPFR_POOL_NENTRIES];
      36  
      37  MPFR_HOT_FUNCTION_ATTR void
      38  mpfr_mpz_init (mpz_ptr z)
      39  {
      40    if (MPFR_LIKELY (n_alloc > 0))
      41      {
      42        /* Get a mpz_t from the MPFR stack of previously used mpz_t.
      43           It reduces memory pressure, and it allows to reuse
      44           a mpz_t that should be sufficiently big. */
      45        MPFR_ASSERTD (n_alloc <= numberof (mpz_tab));
      46        memcpy (z, &mpz_tab[--n_alloc], sizeof (mpz_t));
      47        SIZ(z) = 0;
      48      }
      49    else
      50      {
      51        /* Call the real GMP function */
      52        mpz_init (z);
      53      }
      54  }
      55  
      56  MPFR_HOT_FUNCTION_ATTR void
      57  mpfr_mpz_init2 (mpz_ptr z, mp_bitcnt_t n)
      58  {
      59    /* The condition on n is used below as the argument n will be ignored if
      60       the mpz_t is obtained from the MPFR stack of previously used mpz_t.
      61       Said otherwise, it z is expected to have a large size at the end, then
      62       it is better to allocate this size directly than to get a mpz_t of
      63       small size, with possibly several realloc's on it. But if n satisfies
      64       the condition and is larger than the stacked mpz_t, this may still
      65       yield useless realloc's. This is not ideal. We might consider to use
      66       mpz_init2 with the maximum size in mpfr_mpz_init to solve this issue. */
      67    if (MPFR_LIKELY (n_alloc > 0 && n <= MPFR_POOL_MAX_SIZE * GMP_NUMB_BITS))
      68      {
      69        /* Get a mpz_t from the MPFR stack of previously used mpz_t.
      70           It reduces memory pressure, and it allows to reuse
      71           a mpz_t that should be sufficiently big. */
      72        MPFR_ASSERTD (n_alloc <= numberof (mpz_tab));
      73        memcpy (z, &mpz_tab[--n_alloc], sizeof (mpz_t));
      74        SIZ(z) = 0;
      75      }
      76    else
      77      {
      78        /* Call the real GMP function */
      79        mpz_init2 (z, n);
      80      }
      81  }
      82  
      83  
      84  MPFR_HOT_FUNCTION_ATTR void
      85  mpfr_mpz_clear (mpz_ptr z)
      86  {
      87    /* We only put objects with at most MPFR_POOL_MAX_SIZE in the mpz_t pool,
      88       to avoid it takes too much memory (and anyway the speedup is mainly
      89       for small precision). */
      90    if (MPFR_LIKELY (n_alloc < numberof (mpz_tab) &&
      91                     ALLOC (z) <= MPFR_POOL_MAX_SIZE))
      92      {
      93        /* Push back the mpz_t inside the stack of the used mpz_t */
      94        MPFR_ASSERTD (n_alloc >= 0);
      95        memcpy (&mpz_tab[n_alloc++], z, sizeof (mpz_t));
      96      }
      97    else
      98      {
      99        /* Call the real GMP function */
     100        mpz_clear (z);
     101      }
     102  }
     103  
     104  #endif
     105  
     106  void
     107  mpfr_free_pool (void)
     108  {
     109  #if MPFR_POOL_NENTRIES
     110    int i;
     111  
     112    MPFR_ASSERTD (n_alloc >= 0 && n_alloc <= numberof (mpz_tab));
     113    for (i = 0; i < n_alloc; i++)
     114      mpz_clear (&mpz_tab[i]);
     115    n_alloc = 0;
     116  #endif
     117  }