Beispiel #1
0
  @Override
  public double evaluate(double x, double m, double n, boolean giveLog) {
    double p;
    double q;
    double f;
    double dens;

    if (Double.isNaN(x) || Double.isNaN(m) || Double.isNaN(n)) {
      return x + m + n;
    }

    if (m <= 0 || n <= 0) {
      return RMath.mlError();
    }
    if (x < 0.) {
      return DPQ.rd0(giveLog);
    }
    if (x == 0.) {
      return m > 2 ? DPQ.rd0(giveLog) : (m == 2 ? DPQ.rd1(giveLog) : Double.POSITIVE_INFINITY);
    }
    if (!Double.isFinite(m) && !Double.isFinite(n)) {
      /* both +Inf */
      if (x == 1.) {
        return Double.POSITIVE_INFINITY;
      } else {
        return DPQ.rd0(giveLog);
      }
    }
    if (!Double.isFinite(n)) {
      /* must be +Inf by now */
      return dgamma(x, m / 2, 2. / m, giveLog);
    }
    if (m > 1e14) {
      /* includes +Inf: code below is inaccurate there */
      dens = dgamma(1. / x, n / 2, 2. / n, giveLog);
      return giveLog ? dens - 2 * Math.log(x) : dens / (x * x);
    }

    f = 1. / (n + x * m);
    q = n * f;
    p = x * m * f;

    if (m >= 2) {
      f = m * q / 2;
      dens = dbinomRaw((m - 2) / 2, (m + n - 2) / 2, p, q, giveLog);
    } else {
      f = m * m * q / (2 * p * (m + n));
      dens = dbinomRaw(m / 2, (m + n) / 2, p, q, giveLog);
    }
    return (giveLog ? Math.log(f) + dens : f * dens);
  }
Beispiel #2
0
  @Override
  public double evaluate(double x, double lambda, boolean giveLog) {
    if (Double.isNaN(x) || Double.isNaN(lambda)) {
      return x + lambda;
    }
    if (lambda < 0) {
      return RMath.mlError();
    }

    try {
      DPQ.nonintCheck(x, giveLog);
    } catch (EarlyReturn e) {
      return e.result;
    }
    if (x < 0 || !Double.isFinite(x)) {
      return DPQ.rd0(giveLog);
    }

    return dpoisRaw(forceint(x), lambda, giveLog);
  }
Beispiel #3
0
  public static double rpois(double mu, RandomNumberProvider rand) {
    /* Local Vars [initialize some for -Wall]: */
    double del;
    double difmuk = 0.;
    double e = 0.;
    double fk = 0.;
    double fx;
    double fy;
    double g;
    double px;
    double py;
    double t = 0;
    double u = 0.;
    double v;
    double x;
    double pois = -1.;
    int k;
    int kflag = 0;
    boolean bigMu;
    boolean newBigMu = false;

    if (!Double.isFinite(mu) || mu < 0) {
      return RMath.mlError();
    }

    if (mu <= 0.) {
      return 0.;
    }

    bigMu = mu >= 10.;
    if (bigMu) {
      newBigMu = false;
    }

    if (!(bigMu && mu == muprev)) {
        /* maybe compute new persistent par.s */

      if (bigMu) {
        newBigMu = true;
        /*
         * Case A. (recalculation of s,d,l because mu has changed): The poisson
         * probabilities pk exceed the discrete normal probabilities fk whenever k >= m(mu).
         */
        muprev = mu;
        s = Math.sqrt(mu);
        d = 6. * mu * mu;
        bigL = Math.floor(mu - 1.1484);
        /* = an upper bound to m(mu) for all mu >= 10. */
      } else {
          /* Small mu ( < 10) -- not using normal approx. */

        /* Case B. (start new table and calculate p0 if necessary) */

        /* muprev = 0.;-* such that next time, mu != muprev .. */
        if (mu != muprev) {
          muprev = mu;
          m = Math.max(1, (int) mu);
          l = 0; /* pp[] is already ok up to pp[l] */
          q = p0 = p = Math.exp(-mu);
        }

        while (true) {
          /* Step U. uniform sample for inversion method */
          u = rand.unifRand();
          if (u <= p0) {
            return 0.;
          }

          /*
           * Step T. table comparison until the end pp[l] of the pp-table of cumulative
           * poisson probabilities (0.458 > ~= pp[9](= 0.45792971447) for mu=10 )
           */
          if (l != 0) {
            for (k = (u <= 0.458) ? 1 : Math.min(l, m); k <= l; k++) {
              if (u <= pp[k]) {
                return (double) k;
              }
            }
            if (l == 35) {
                /* u > pp[35] */
              continue;
            }
          }
          /*
           * Step C. creation of new poisson probabilities p[l..] and their cumulatives q
           * =: pp[k]
           */
          l++;
          for (k = l; k <= 35; k++) {
            p *= mu / k;
            q += p;
            pp[k] = q;
            if (u <= q) {
              l = k;
              return (double) k;
            }
          }
          l = 35;
        } /* end(repeat) */
      } /* mu < 10 */
    } /* end {initialize persistent vars} */

    /* Only if mu >= 10 : ----------------------- */

    /* Step N. normal sample */
    g = mu + s * rand.normRand(); /* norm_rand() ~ N(0,1), standard normal */

    if (g >= 0.) {
      pois = Math.floor(g);
      /* Step I. immediate acceptance if pois is large enough */
      if (pois >= bigL) {
        return pois;
      }
      /* Step S. squeeze acceptance */
      fk = pois;
      difmuk = mu - fk;
      u = rand.unifRand(); /* ~ U(0,1) - sample */
      if (d * u >= difmuk * difmuk * difmuk) {
        return pois;
      }
    }

    /*
     * Step P. preparations for steps Q and H. (recalculations of parameters if necessary)
     */

    if (newBigMu || mu != muprev2) {
      /*
       * Careful! muprev2 is not always == muprev because one might have exited in step I or S
       */
      muprev2 = mu;
      omega = M_1_SQRT_2PI / s;
      /*
       * The quantities b1, b2, c3, c2, c1, c0 are for the Hermite approximations to the
       * discrete normal probabilities fk.
       */

      b1 = one_24 / mu;
      b2 = 0.3 * b1 * b1;
      c3 = one_7 * b1 * b2;
      c2 = b2 - 15. * c3;
      c1 = b1 - 6. * b2 + 45. * c3;
      c0 = 1. - b1 + 3. * b2 - 15. * c3;
      c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */
    }

    boolean gotoStepF = false;
    if (g >= 0.) {
      /* 'Subroutine' F is called (kflag=0 for correct return) */
      kflag = 0;
      gotoStepF = true;
      // goto Step_F;
    }

    while (true) {
      if (!gotoStepF) {
        /* Step E. Exponential Sample */
        e = rand.expRand(); /* ~ Exp(1) (standard exponential) */

        /*
         * sample t from the laplace 'hat' (if t <= -0.6744 then pk < fk for all mu >= 10.)
         */
        u = 2 * rand.unifRand() - 1.;
        t = 1.8 + RMath.fsign(e, u);
      }

      if (t > -0.6744 || gotoStepF) {
        if (!gotoStepF) {
          pois = Math.floor(mu + s * t);
          fk = pois;
          difmuk = mu - fk;

          /* 'subroutine' F is called (kflag=1 for correct return) */
          kflag = 1;
        }

        // Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */
        gotoStepF = false;

        if (pois < 10) {
            /* use factorials from table fact[] */
          px = -mu;
          py = Math.pow(mu, pois) / fact[(int) pois];
        } else {
          /*
           * Case pois >= 10 uses polynomial approximation a0-a7 for accuracy when
           * advisable
           */
          del = one_12 / fk;
          del = del * (1. - 4.8 * del * del);
          v = difmuk / fk;
          if (TOMS708.fabs(v) <= 0.25) {
            px =
                fk
                        * v
                        * v
                        * (((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v
                            + a0)
                    - del;
          } else {
              /* |v| > 1/4 */
            px = fk * Math.log(1. + v) - difmuk - del;
          }
          py = M_1_SQRT_2PI / Math.sqrt(fk);
        }
        x = (0.5 - difmuk) / s;
        x *= x; /* x^2 */
        fx = -0.5 * x;
        fy = omega * (((c3 * x + c2) * x + c1) * x + c0);
        if (kflag > 0) {
          /* Step H. Hat acceptance (E is repeated on rejection) */
          if (c * TOMS708.fabs(u) <= py * Math.exp(px + e) - fy * Math.exp(fx + e)) {
            break;
          }
        } else {
          /* Step Q. Quotient acceptance (rare case) */
          if (fy - u * fy <= py * Math.exp(px - fx)) {
            break;
          }
        }
      } /* t > -.67.. */
    }
    return pois;
  }