xref: /netbsd-src/external/lgpl3/mpfr/dist/src/pool.c (revision ba125506a622fe649968631a56eba5d42ff57863)
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
mpfr_mpz_init(mpz_ptr z)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
mpfr_mpz_init2(mpz_ptr z,mp_bitcnt_t n)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
mpfr_mpz_clear(mpz_ptr z)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
mpfr_free_pool(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 }
118