package org.matheclipse.core.reflection.system;
import java.math.BigInteger;
import org.apache.commons.math3.fraction.BigFraction;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.expression.NumberUtil;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.parser.client.SyntaxError;
/**
* Compute the Bernoulli number of the first kind.
*
* See Wikipedia - Bernoulli number.
* For better performing implementations see ComputationAndAsymptoticsOfBernoulliNumbers
*
*/
public class BernoulliB extends AbstractFunctionEvaluator {
public BernoulliB() {
}
@Override
public IExpr evaluate(IAST ast) {
Validate.checkRange(ast, 2, 3);
if (ast.size() == 2) {
// bernoulli number
if (ast.arg1().isInteger()) {
BigFraction bernoulli = bernoulliNumber(((IInteger) ast.arg1()).getBigNumerator());
if (bernoulli != null) {
return F.fraction(bernoulli);
}
}
}
return null;
}
/**
* Compute the Bernoulli number of the first kind.
*
* @param biggi
* @return
*/
public static BigFraction bernoulliNumber(final BigInteger biggi) {
int N = 0;
try {
N = NumberUtil.toInt(biggi);
return bernoulliNumber(N);
} catch (ArithmeticException ae) {
//
}
return null;
}
/**
* Compute the Bernoulli number of the first kind.
*
* @param n
* @return
*/
public static BigFraction bernoulliNumber(int n) {
if (n == 0) {
return BigFraction.ONE;
} else if (n == 1) {
return new BigFraction(-1, 2);
} else if (n % 2 != 0) {
return BigFraction.ZERO;
}
BigFraction[] bernoulli = new BigFraction[n + 1];
bernoulli[0] = BigFraction.ONE;
bernoulli[1] = new BigFraction(-1, 2);
for (int k = 2; k <= n; k++) {
bernoulli[k] = BigFraction.ZERO;
for (int i = 0; i < k; i++) {
if (!bernoulli[i].equals(BigFraction.ZERO)) {
BigFraction bin = new BigFraction(Binomial.binomial(k + 1, k + 1 - i));
bernoulli[k] = bernoulli[k].subtract(bin.multiply(bernoulli[i]));
}
}
bernoulli[k] = bernoulli[k].divide(new BigFraction(k + 1));
}
return bernoulli[n];
}
public void setUp(final ISymbol symbol) throws SyntaxError {
symbol.setAttributes(ISymbol.LISTABLE | ISymbol.NUMERICFUNCTION);
}
}
Ads help maintain this website.