WarpPI/core/src/main/java/org/nevec/rjm/Bernoulli.java

103 lines
2.3 KiB
Java
Raw Normal View History

2016-09-02 20:32:37 +02:00
package org.nevec.rjm;
2016-03-15 10:41:39 +01:00
import java.math.BigInteger;
import java.util.Vector;
import it.cavallium.warppi.util.Error;
2016-07-12 22:26:54 +02:00
2016-09-02 20:32:37 +02:00
/**
* Bernoulli numbers.
2018-09-22 11:17:30 +02:00
*
2016-09-02 20:32:37 +02:00
* @since 2006-06-25
* @author Richard J. Mathar
*/
public class Bernoulli {
/*
* The list of all Bernoulli numbers as a vector, n=0,2,4,....
*/
2017-01-17 22:32:40 +01:00
static Vector<Rational> a = new Vector<>();
2016-03-15 10:41:39 +01:00
2016-09-02 20:32:37 +02:00
public Bernoulli() {
2018-09-22 11:17:30 +02:00
if (Bernoulli.a.size() == 0) {
Bernoulli.a.add(Rational.ONE);
Bernoulli.a.add(new Rational(1, 6));
2016-09-02 20:32:37 +02:00
}
}
2016-03-15 10:41:39 +01:00
2016-09-02 20:32:37 +02:00
/**
* Set a coefficient in the internal table.
2018-09-22 11:17:30 +02:00
*
2016-09-02 20:32:37 +02:00
* @param n
* the zero-based index of the coefficient. n=0 for the constant
* term.
* @param value
* the new value of the coefficient.
*/
protected void set(final int n, final Rational value) {
final int nindx = n / 2;
2018-09-28 11:39:28 +02:00
if (nindx < Bernoulli.a.size()) {
2018-09-22 11:17:30 +02:00
Bernoulli.a.set(nindx, value);
2018-09-28 11:39:28 +02:00
} else {
while (Bernoulli.a.size() < nindx) {
2018-09-22 11:17:30 +02:00
Bernoulli.a.add(Rational.ZERO);
2018-09-28 11:39:28 +02:00
}
2018-09-22 11:17:30 +02:00
Bernoulli.a.add(value);
2016-09-02 20:32:37 +02:00
}
}
2016-03-15 10:41:39 +01:00
2016-09-02 20:32:37 +02:00
/**
* The Bernoulli number at the index provided.
2018-09-22 11:17:30 +02:00
*
2016-09-02 20:32:37 +02:00
* @param n
* the index, non-negative.
* @return the B_0=1 for n=0, B_1=-1/2 for n=1, B_2=1/6 for n=2 etc
* @throws Error
2016-09-02 20:32:37 +02:00
*/
2018-09-22 11:17:30 +02:00
public Rational at(final int n) throws Error {
2018-09-28 11:39:28 +02:00
if (n == 1) {
2018-09-22 11:17:30 +02:00
return new Rational(-1, 2);
2018-09-28 11:39:28 +02:00
} else if (n % 2 != 0) {
2016-09-02 20:32:37 +02:00
return Rational.ZERO;
2018-09-28 11:39:28 +02:00
} else {
2016-09-02 20:32:37 +02:00
final int nindx = n / 2;
2018-09-28 11:39:28 +02:00
if (Bernoulli.a.size() <= nindx) {
for (int i = 2 * Bernoulli.a.size(); i <= n; i += 2) {
2016-09-02 20:32:37 +02:00
set(i, doubleSum(i));
2018-09-28 11:39:28 +02:00
}
}
2018-09-22 11:17:30 +02:00
return Bernoulli.a.elementAt(nindx);
2016-09-02 20:32:37 +02:00
}
}
2016-03-15 10:41:39 +01:00
2016-09-02 20:32:37 +02:00
/*
* Generate a new B_n by a standard double sum.
2018-09-22 11:17:30 +02:00
*
2016-09-02 20:32:37 +02:00
* @param n The index of the Bernoulli number.
2018-09-22 11:17:30 +02:00
*
2016-09-02 20:32:37 +02:00
* @return The Bernoulli number at n.
*/
2018-09-22 11:17:30 +02:00
private Rational doubleSum(final int n) throws Error {
2016-09-02 20:32:37 +02:00
Rational resul = Rational.ZERO;
for (int k = 0; k <= n; k++) {
Rational jsum = Rational.ZERO;
BigInteger bin = BigInteger.ONE;
for (int j = 0; j <= k; j++) {
2018-09-22 11:17:30 +02:00
final BigInteger jpown = new BigInteger("" + j).pow(n);
2018-09-28 11:39:28 +02:00
if (j % 2 == 0) {
2016-09-02 20:32:37 +02:00
jsum = jsum.add(bin.multiply(jpown));
2018-09-28 11:39:28 +02:00
} else {
2016-09-02 20:32:37 +02:00
jsum = jsum.subtract(bin.multiply(jpown));
2018-09-28 11:39:28 +02:00
}
2016-03-15 10:41:39 +01:00
2016-09-02 20:32:37 +02:00
/*
* update binomial(k,j) recursively
*/
bin = bin.multiply(new BigInteger("" + (k - j))).divide(new BigInteger("" + (j + 1)));
}
resul = resul.add(jsum.divide(new BigInteger("" + (k + 1))));
}
return resul;
}
2016-03-15 10:41:39 +01:00
} /* Bernoulli */