@Test public void testLogExponentialDistribution() { assertEquals( Math.log(Distributions.exponentialDistribution(5, 6)), Distributions.logExponentialDistribution(5, 6), DELTA); }
private static double do_search( double y, double[] z, double p, double n, double pr, double incr) { if (z[0] >= p) { /* search to the left */ for (; ; ) { if (y == 0 || (z[0] = Distributions.pnbinom(y - incr, (int) n, pr, /*l._t.*/ true, /*log_p*/ false)) < p) { return y; } y = Math.max(0, y - incr); } } else { /* search to the right */ for (; ; ) { y = y + incr; if ((z[0] = Distributions.pnbinom(y, (int) n, pr, /*l._t.*/ true, /*log_p*/ false)) >= p) { return y; } } } }
/** * Get a probability estimate for a value. * * @param data the value to estimate the probability of * @return the estimated probability of the supplied value */ public double getProbability(double data) { double delta = 0, sum = 0, currentProb = 0; double zLower = 0, zUpper = 0; if (m_NumValues == 0) { zLower = (data - (m_Precision / 2)) / m_StandardDev; zUpper = (data + (m_Precision / 2)) / m_StandardDev; return (Distributions.normalProbability(zUpper) - Distributions.normalProbability(zLower)); } double weightSum = 0; int start = findNearestValue(data); for (int i = start; i < m_NumValues; i++) { delta = m_Values[i] - data; zLower = (delta - (m_Precision / 2)) / m_StandardDev; zUpper = (delta + (m_Precision / 2)) / m_StandardDev; currentProb = (Distributions.normalProbability(zUpper) - Distributions.normalProbability(zLower)); sum += currentProb * m_Weights[i]; /* System.out.print("zL" + (i + 1) + ": " + zLower + " "); System.out.print("zU" + (i + 1) + ": " + zUpper + " "); System.out.print("P" + (i + 1) + ": " + currentProb + " "); System.out.println("total: " + (currentProb * m_Weights[i]) + " "); */ weightSum += m_Weights[i]; if (currentProb * (m_SumOfWeights - weightSum) < sum * MAX_ERROR) { break; } } for (int i = start - 1; i >= 0; i--) { delta = m_Values[i] - data; zLower = (delta - (m_Precision / 2)) / m_StandardDev; zUpper = (delta + (m_Precision / 2)) / m_StandardDev; currentProb = (Distributions.normalProbability(zUpper) - Distributions.normalProbability(zLower)); sum += currentProb * m_Weights[i]; weightSum += m_Weights[i]; if (currentProb * (m_SumOfWeights - weightSum) < sum * MAX_ERROR) { break; } } return sum / m_SumOfWeights; }
public static double rbinom(Context.Globals context, double nin, double pp) { /* static */ double c = 0, fm = 0, npq = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, qn = 0; double xl = 0, xll = 0, xlr = 0, xm = 0, xr = 0; double psave = -1.0; int nsave = -1; int m = 0; /* end of static */ double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2; double p, q, np, g, r, al, alv, amaxp, ffm, ynorm; int i, ix, k, n; if (Double.isInfinite(nin)) { return Double.NaN; } r = Math.floor(nin + 0.5); if (r != nin) { return Double.NaN; } if (Double.isInfinite(pp) || r < 0 || pp < 0. || pp > 1.) { return Double.NaN; } if (r == 0 || pp == 0.) { return 0; } if (pp == 1.) { return r; } if (r >= Integer.MAX_VALUE) { return Distributions.qbinom(context.rng.unif_rand(), (int) r, pp, false, false); } /* else */ n = (int) r; p = Math.min(pp, 1. - pp); q = 1. - p; np = n * p; r = p / q; g = r * (n + 1); /* Setup, perform only when parameters change [using static (globals): */ /* FIXING: Want this thread safe -- use as little (thread globals) as possible */ if (pp != psave || n != nsave) { psave = pp; nsave = n; if (np < 30.0) { /* inverse cdf logic for mean less than 30 */ qn = Math.pow(q, (double) n); /*---------------------- np = n*p < 30 : ------------------------- */ while (true) { ix = 0; f = qn; u = context.rng.unif_rand(); while (true) { if (u < f) { if (psave > 0.5) { ix = n - ix; } return (double) ix; } if (ix > 110) { break; } u -= f; ix++; f *= (g / ix - r); } } } else { ffm = np + p; m = (int) ffm; fm = m; npq = np * q; p1 = (int) (2.195 * Math.sqrt(npq) - 4.6 * q) + 0.5; xm = fm + 0.5; xl = xm - p1; xr = xm + p1; c = 0.134 + 20.5 / (15.3 + fm); al = (ffm - xl) / (ffm - xl * p); xll = al * (1.0 + 0.5 * al); al = (xr - ffm) / (xr * q); xlr = al * (1.0 + 0.5 * al); p2 = p1 * (1.0 + c + c); p3 = p2 + c / xll; p4 = p3 + c / xlr; } } else if (n == nsave) { if (np < 30.0) {} /*---------------------- np = n*p < 30 : ------------------------- */ while (true) { ix = 0; f = qn; u = context.rng.unif_rand(); while (true) { if (u < f) { if (psave > 0.5) { ix = n - ix; } return (double) ix; } if (ix > 110) { break; } u -= f; ix++; f *= (g / ix - r); } } } /*-------------------------- np = n*p >= 30 : ------------------- */ while (true) { u = context.rng.unif_rand() * p4; v = context.rng.unif_rand(); /* triangular region */ if (u <= p1) { ix = (int) (xm - p1 * v + u); if (psave > 0.5) { ix = n - ix; } return (double) ix; } /* parallelogram region */ if (u <= p2) { x = xl + (u - p1) / c; v = v * c + 1.0 - Math.abs(xm - x) / p1; if (v > 1.0 || v <= 0.) { continue; } ix = (int) x; } else { if (u > p3) { /* right tail */ ix = (int) (xr - Math.log(v) / xlr); if (ix > n) { continue; } v = v * (u - p3) * xlr; } else { /* left tail */ ix = (int) (xl + Math.log(v) / xll); if (ix < 0) { continue; } v = v * (u - p2) * xll; } } /* determine appropriate way to perform accept/reject test */ k = Math.abs(ix - m); if (k <= 20 || k >= npq / 2 - 1) { /* explicit evaluation */ f = 1.0; if (m < ix) { for (i = m + 1; i <= ix; i++) { f *= (g / i - r); } } else if (m != ix) { for (i = ix + 1; i <= m; i++) { f /= (g / i - r); } } if (v <= f) { if (psave > 0.5) { ix = n - ix; } return (double) ix; } } else { /* squeezing using upper and lower bounds on log(f(x)) */ amaxp = (k / npq) * ((k * (k / 3. + 0.625) + 0.1666666666666) / npq + 0.5); ynorm = -k * k / (2.0 * npq); alv = Math.log(v); if (alv < ynorm - amaxp) { if (psave > 0.5) { ix = n - ix; } return (double) ix; } if (alv <= ynorm + amaxp) { /* stirling's formula to machine accuracy */ /* for the final acceptance/rejection test */ x1 = ix + 1; f1 = fm + 1.0; z = n + 1 - fm; w = n - ix + 1.0; z2 = z * z; x2 = x1 * x1; f2 = f1 * f1; w2 = w * w; if (alv <= xm * Math.log(f1 / x1) + (n - m + 0.5) * Math.log(z / w) + (ix - m) * Math.log(w * p / (x1 * q)) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.) {} if (psave > 0.5) { ix = n - ix; } return (double) ix; } } } }
public static double qnbinom( double p, double size, double prob, boolean lower_tail, boolean log_p) { double P, Q, mu, sigma, gamma, y; double[] z = new double[1]; if (DoubleVector.isNaN(p) || DoubleVector.isNaN(size) || DoubleVector.isNaN(prob)) { return p + size + prob; } if (prob <= 0 || prob > 1 || size <= 0) { return DoubleVector.NaN; } /* FIXME: size = 0 is well defined ! */ if (prob == 1) { return 0; } // R_Q_P01_boundaries(p, 0, ML_POSINF); // #define R_Q_P01_boundaries(p, _LEFT_, _RIGHT_) // This macro is defined in /src/nmath/dpq.h if (log_p) { if (p > 0) { return DoubleVector.NaN; } if (p == 0) { /* upper bound*/ return lower_tail ? Double.POSITIVE_INFINITY : 0; } if (p == Double.NEGATIVE_INFINITY) { return lower_tail ? 0 : Double.POSITIVE_INFINITY; } } else { /* !log_p */ if (p < 0 || p > 1) { return DoubleVector.NaN; } if (p == 0) { return lower_tail ? 0 : Double.POSITIVE_INFINITY; } if (p == 1) { return lower_tail ? Double.POSITIVE_INFINITY : 0; } } Q = 1.0 / prob; P = (1.0 - prob) * Q; mu = size * P; sigma = Math.sqrt(size * P * Q); gamma = (Q + P) / sigma; /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if (!lower_tail || log_p) { // p = R_DT_qIv(p); /* need check again (cancellation!): */ p = Normal.R_DT_qIv(p, lower_tail ? 1.0 : 0.0, log_p ? 1.0 : 0.0); if (p == SignRank.R_DT_0(lower_tail, log_p)) { return 0; } if (p == SignRank.R_DT_1(lower_tail, log_p)) { return Double.POSITIVE_INFINITY; } } /* temporary hack --- FIXME --- */ if (p + 1.01 * SignRank.DBL_EPSILON >= 1.) { return Double.POSITIVE_INFINITY; } /* y := approx.value (Cornish-Fisher expansion) : */ z[0] = Distributions.qnorm(p, 0., 1., /*lower_tail*/ true, /*log_p*/ false); y = Math.floor(mu + sigma * (z[0] + gamma * (z[0] * z[0] - 1) / 6) + 0.5); z[0] = Distributions.pnbinom(y, (int) size, prob, /*lower_tail*/ true, /*log_p*/ false); /* fuzz to ensure left continuity: */ p *= 1 - 64 * SignRank.DBL_EPSILON; /* If the C-F value is not too large a simple search is OK */ if (y < 1e5) { return do_search(y, z, p, size, prob, 1); } /* Otherwise be a bit cleverer in the search */ { double incr = Math.floor(y * 0.001), oldincr; do { oldincr = incr; y = do_search(y, z, p, size, prob, incr); incr = Math.max(1, Math.floor(incr / 100)); } while (oldincr > 1 && incr > y * 1e-15); return y; } }