Sindbad~EG File Manager
/* Akiyama Tanigawa algorithm for second Bernoulli numbers, found on Wikipedia in pseudocode */
/*
5.15.13 created file
*/
#include <math.h>
#include <assert.h>
#include <stdlib.h> // calloc
#include "special.h"
#include "bignum.h"
#include "heap.h" // free2
extern int dbinomial(double,double, double *);
/*_______________________________________________________________*/
#if 0
/* This code gives wrong answers starting about bernoulli(18) */
double dbernoulli(int n)
/* compute n-th second Bernoulli number.
Assumes n is a nonnegative integer. It should not
be too large because it needs an integer array of dimension n
and also is quadratic in time.
*/
{ int m,j;
double ans;
double *A;
if(n >= NSTOREDBERNOULLIS)
return BADVAL; // you will get floating-point overflow
if(stored_values[n] != 0.0)
return stored_values[n]; // for speed when graphing
A = (double *) calloc(n+1, sizeof(double)); // already initialized to zero
for(m=0;m<=n;m++)
{ A[m] = 1.0/(double)(m+1);
for(j=m; j>= 1; j--)
A[j-1] = j* (A[j-1] - A[j]);
}
ans = stored_values[n] = A[0];
free(A);
return ans;
}
#endif
#if 0
/* this code also produces wrong answers, e.g. bernoulli(54) comes out
negative, when really it is positive.
*/
double dbernoulli(int n)
/* code imitates similar code by Al Kelley, given to me 5.16.13 */
{
int i;
int k;
double* b;
double sum, t;
if (n % 2 == 1 && n > 1)
return 0.0;
if(n >= NSTOREDBERNOULLIS)
return BADVAL; // you will get floating-point overflow
if(stored_values[n] != 0.0)
return stored_values[n];
b = (double *) calloc(n+1,sizeof(double));
b[0] = 1;
b[1] = -0.5;
for (k = 3; k <= n; k += 2)
b[k] = 0.0;
for (k = 2; k <= n; k += 2) {
sum = 0.0;
for (i = 0; i < k; ++i)
{ int err = dbinomial(k+1,i,&t);
if(err)
return BADVAL;
sum += t * b[i];
}
b[k] = (-1.0 / (double) (k + 1)) * sum;
}
if(n < NSTOREDBERNOULLIS)
stored_values[n] = b[n];
return b[n];
free(b);
}
#endif
double dbernoulli(long n)
{ int err;
double a,b,ans;
bignum num, denom;
static double stored_bvalues[NSTOREDBERNOULLIS];
if(n==0)
return 1.0;
if(n % 2 == 1)
return 0.0;
if(stored_bvalues[n/2] > 0.0)
return stored_bvalues[n/2];
err = exact_bernoulli(n,&num,&denom);
if(err)
return BADVAL;
err = bignum_double(num,&a);
if(err)
goto fail;
err = bignum_double(denom,&b);
if(err)
goto fail;
freespace(num.val);
freespace(denom.val);
if(n % 4 == 0)
ans = -a/b; // exact_bernoulli just gets the num and denom, so here we supply the sign
else
ans = a/b;
stored_bvalues[n/2] = ans;
return ans;
fail:
freespace(num.val);
freespace(denom.val);
return BADVAL;
}
double deulernumber(long n)
{ int err;
double a;
bignum ans;
double finalans;
static double stored_evalues[NSTOREDBERNOULLIS];
if(n==0)
return 1.0;
if(n % 2 == 1)
return 0.0;
if(stored_evalues[n/2] > 0.0)
return stored_evalues[n/2];
err = exact_eulernumber(n,&ans);
if(err)
return BADVAL;
err = bignum_double(ans,&a);
if(err)
goto fail;
freespace(ans.val);
if(n % 4 == 2)
finalans = -a; // exact_eulernumber just gets the num and denom, so here we supply the sign
else
finalans = a;
stored_evalues[n/2] = finalans;
return finalans;
fail:
freespace(ans.val);
return BADVAL;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists