summaryrefslogtreecommitdiff
path: root/src/bernoulli.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2014-02-13 09:38:34 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2014-02-13 09:38:34 +0000
commit7c761d08d0bfcfb363622091fa85e24a267e9129 (patch)
treecb595a32e92a7b7dfd8ce39fe9fd625f9bd0dc74 /src/bernoulli.c
parent690760f684d03421cc0cb9932dc8e2fdf44b162e (diff)
downloadmpfr-7c761d08d0bfcfb363622091fa85e24a267e9129.tar.gz
implement cache for Bernoulli numbers (patch from Patrick PĂ©lisser)
tuned parameters for [ln]gamma now that we cache Bernoulli numbers git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@8963 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/bernoulli.c')
-rw-r--r--src/bernoulli.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/src/bernoulli.c b/src/bernoulli.c
index 0aa8eba2f..e224c6b5e 100644
--- a/src/bernoulli.c
+++ b/src/bernoulli.c
@@ -35,12 +35,11 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
Then C[n] = -sum(binomial(n+1,k)*C[k]*n!/(k+1)!, k=0..n-1),
which proves that the C[n] are integers.
*/
-mpz_t*
+void
mpfr_bernoulli_internal (mpz_t *b, unsigned long n)
{
if (n == 0)
{
- b = (mpz_t *) (*__gmp_allocate_func) (sizeof (mpz_t));
mpz_init_set_ui (b[0], 1);
}
else
@@ -48,8 +47,6 @@ mpfr_bernoulli_internal (mpz_t *b, unsigned long n)
mpz_t t;
unsigned long k;
- b = (mpz_t *) (*__gmp_reallocate_func)
- (b, n * sizeof (mpz_t), (n + 1) * sizeof (mpz_t));
mpz_init (b[n]);
/* b[n] = -sum(binomial(2n+1,2k)*C[k]*(2n)!/(2k+1)!, k=0..n-1) */
mpz_init_set_ui (t, 2 * n + 1);
@@ -76,5 +73,55 @@ mpfr_bernoulli_internal (mpz_t *b, unsigned long n)
mpz_neg (b[n], b[n]);
mpz_clear (t);
}
- return b;
+ return;
+}
+
+static MPFR_THREAD_ATTR mpz_t *bernoulli_table = NULL;
+static MPFR_THREAD_ATTR unsigned long bernoulli_size = 0;
+static MPFR_THREAD_ATTR unsigned long bernoulli_alloc = 0;
+
+mpz_srcptr
+mpfr_bernoulli_cache (unsigned long n)
+{
+ unsigned long i;
+
+ if (n >= bernoulli_size) {
+ if (bernoulli_alloc == 0)
+ {
+ bernoulli_alloc = MAX(16, n + n/4);
+ bernoulli_table = (mpz_t *)
+ (*__gmp_allocate_func) (bernoulli_alloc * sizeof (mpz_t));
+ bernoulli_size = 0;
+ }
+ else if (n >= bernoulli_alloc)
+ {
+ bernoulli_table = (mpz_t *) (*__gmp_reallocate_func)
+ (bernoulli_table, bernoulli_alloc * sizeof (mpz_t),
+ (n + n/4) * sizeof (mpz_t));
+ bernoulli_alloc = n + n/4;
+ }
+ MPFR_ASSERTD(bernoulli_alloc > n);
+ MPFR_ASSERTD(bernoulli_size >= 0);
+ for(i = bernoulli_size; i <= n; i++)
+ mpfr_bernoulli_internal(bernoulli_table, i);
+ bernoulli_size = n+1;
+ }
+ MPFR_ASSERTD(bernoulli_size > n);
+ return bernoulli_table[n];
+}
+
+void
+mpfr_bernoulli_freecache(void)
+{
+ unsigned long i;
+
+ if (bernoulli_table != NULL) {
+ for(i = 0; i < bernoulli_size; i++) {
+ mpz_clear (bernoulli_table[i]);
+ }
+ (*__gmp_free_func) (bernoulli_table, bernoulli_alloc * sizeof (mpz_t));
+ bernoulli_table = NULL;
+ bernoulli_alloc = 0;
+ bernoulli_size = 0;
+ }
}