Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/deval/
Upload File :
Current File : /usr/home/beeson/MathXpert/deval/bernoulli.c

/* 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