%mathpiper,def="Bernoulli"

/////////////////////////////////////////////////
/// Bernoulli numbers and polynomials
/////////////////////////////////////////////////
/// Serge Winitzki

/// Bernoulli(n): interface to Bernoulli numbers
10 # Bernoulli(0) <-- 1;
10 # Bernoulli(1) <-- -1/2;
15 # Bernoulli(n_IsInteger)_(n<0) <-- Undefined;
30 # Bernoulli(n_IsOdd) <-- 0;

/// numerical computations of Bernulli numbers use two different methods, one good for small numbers and one good only for very large numbers (using Zeta function)
20 # Bernoulli(n_IsEven)_(n<=Bernoulli1Threshold()) <-- Internal'BernoulliArray(n)[n+1];
20 # Bernoulli(n_IsEven)_(n>Bernoulli1Threshold()) <-- Bernoulli1(n);

LocalSymbols(bernoulli1Threshold) [
  /// Bernoulli1Threshold could in principle be set by the user
  If(Not IsBound(bernoulli1Threshold), bernoulli1Threshold := 20);

  Bernoulli1Threshold() := bernoulli1Threshold;
  SetBernoulli1Threshold(threshold) := [ bernoulli1Threshold := threshold;];

] ; // LocalSymbols(bernoulli1Threshold)

/// Bernoulli polynomials of degree n in variable x
Bernoulli(n_IsInteger, _x) <-- [
	Local(B, i, result);
	B := Internal'BernoulliArray(n);
	result := B[1];
	For(i:=n-1, i>=0, i--) [
		result := result * x + B[n-i+1]*BinomialCoefficient(n,i);
	];
	result;
];

%/mathpiper



%mathpiper_docs,name="Bernoulli",categories="User Functions;Special Functions"
*CMD Bernoulli --- Bernoulli numbers and polynomials
*STD
*CALL
	Bernoulli(index)
	Bernoulli(index, x)

*PARMS

{x} -- expression that will be the variable in the polynomial

{index} -- expression that can be evaluated to an integer

*DESC

{Bernoulli(n)} evaluates the $n$-th Bernoulli number. {Bernoulli(n, x)} returns the $n$-th Bernoulli polynomial in the variable $x$. The polynomial is returned in the Horner form.

*E.G.

In> Bernoulli(20);
Result: -174611/330;
In> Bernoulli(4, x);
Result: ((x-2)*x+1)*x^2-1/30;

*SEE Gamma, Zeta
%/mathpiper_docs