package com.spbsu.bernulli.caches;
public class BetaCache {
double alpha;
double beta;
int n;
public BetaCache(double alpha, double beta, int n) {
this.alpha = alpha;
this.beta = beta;
this.n = n;
logAlpha = new double[n + 1];
logBeta = new double[n + 1];
logAlphaBetaSum = 0;
}
final double logAlpha[];
int lastCachedAlpha = 0;
final double logBeta[];
int lastCachedBeta = 0;
double logAlphaBetaSum;
boolean cachedAlphaBetaSum = false;
final public double calculate(int m, int n) {
if (!cachedAlphaBetaSum) {
final double ab = alpha + beta;
for (int i = 0; i < n; ++i) {
logAlphaBetaSum += Math.log(ab + i);
}
cachedAlphaBetaSum = true;
}
if (lastCachedAlpha < m) {
for (int i = lastCachedAlpha + 1; i <= m; ++i) {
logAlpha[i] = logAlpha[i - 1] + Math.log(alpha + i - 1);
}
lastCachedAlpha = m;
}
if (lastCachedBeta < n - m) {
for (int i = lastCachedBeta + 1; i <= n - m; ++i) {
logBeta[i] = logBeta[i - 1] + Math.log(beta + i - 1);
}
lastCachedBeta = n - m;
}
return Math.exp(logAlpha[m] + logBeta[n - m] - logAlphaBetaSum);
}
final public void update(double alpha, double beta) {
if (this.alpha == alpha && this.beta == beta)
return;
this.alpha = alpha;
this.beta = beta;
logAlpha[0] = 0;
logBeta[0] = 0;
lastCachedAlpha = 0;
lastCachedBeta = 0;
logAlphaBetaSum = 0;
cachedAlphaBetaSum = false;
}
}