You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2019/02/14 13:59:24 UTC
[commons-rng] 01/17: RNG-68: Add private classes for each algorithm
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git
commit ad8739b2290ae8ea34954b08fd496c6ca07c3b33
Author: aherbert <a....@sussex.ac.uk>
AuthorDate: Mon Jan 28 10:33:09 2019 +0000
RNG-68: Add private classes for each algorithm
---
.../AhrensDieterMarsagliaTsangGammaSampler.java | 174 +++++++++++++++------
1 file changed, 123 insertions(+), 51 deletions(-)
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.java
index d34902d..ab2b176 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.java
@@ -44,48 +44,68 @@ import org.apache.commons.rng.UniformRandomProvider;
public class AhrensDieterMarsagliaTsangGammaSampler
extends SamplerBase
implements ContinuousSampler {
- /** 1/3 */
- private static final double ONE_THIRD = 1d / 3;
- /** The shape parameter. */
- private final double theta;
- /** The alpha parameter. */
- private final double alpha;
- /** Inverse of "theta". */
- private final double oneOverTheta;
- /** Optimization (see code). */
- private final double bGSOptim;
- /** Optimization (see code). */
- private final double dOptim;
- /** Optimization (see code). */
- private final double cOptim;
- /** Gaussian sampling. */
- private final NormalizedGaussianSampler gaussian;
- /** Underlying source of randomness. */
- private final UniformRandomProvider rng;
+ /** The appropriate gamma sampler for the parameters. */
+ private final ContinuousSampler delegate;
/**
- * @param rng Generator of uniformly distributed random numbers.
- * @param alpha Alpha parameter of the distribution.
- * @param theta Theta parameter of the distribution.
+ * Base class for a sampler from the Gamma distribution.
*/
- public AhrensDieterMarsagliaTsangGammaSampler(UniformRandomProvider rng,
- double alpha,
- double theta) {
- super(null);
- this.rng = rng;
- this.alpha = alpha;
- this.theta = theta;
- gaussian = new ZigguratNormalizedGaussianSampler(rng);
- oneOverTheta = 1 / theta;
- bGSOptim = 1 + theta / Math.E;
- dOptim = theta - ONE_THIRD;
- cOptim = ONE_THIRD / Math.sqrt(dOptim);
+ private abstract static class BaseAhrensDieterMarsagliaTsangGammaSampler
+ implements ContinuousSampler {
+
+ /** Underlying source of randomness. */
+ protected final UniformRandomProvider rng;
+ /** The shape parameter. */
+ protected final double theta;
+ /** The alpha parameter. */
+ protected final double alpha;
+
+ /**
+ * @param rng Generator of uniformly distributed random numbers.
+ * @param alpha Alpha shape parameter of the distribution.
+ * @param theta Theta scale parameter of the distribution.
+ */
+ BaseAhrensDieterMarsagliaTsangGammaSampler(UniformRandomProvider rng,
+ double alpha,
+ double theta) {
+ this.rng = rng;
+ this.alpha = alpha;
+ this.theta = theta;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "Ahrens-Dieter-Marsaglia-Tsang Gamma deviate [" + rng.toString() + "]";
+ }
}
- /** {@inheritDoc} */
- @Override
- public double sample() {
- if (theta < 1) {
+ /**
+ * Class to sample from the Gamma distribution when {@code 0 < theta < 1}.
+ */
+ private static class SmallThetaAhrensDieterMarsagliaTsangGammaSampler
+ extends BaseAhrensDieterMarsagliaTsangGammaSampler {
+
+ /** Inverse of "theta". */
+ private final double oneOverTheta;
+ /** Optimization (see code). */
+ private final double bGSOptim;
+
+ /**
+ * @param rng Generator of uniformly distributed random numbers.
+ * @param alpha Alpha shape parameter of the distribution.
+ * @param theta Theta scale parameter of the distribution.
+ */
+ SmallThetaAhrensDieterMarsagliaTsangGammaSampler(UniformRandomProvider rng,
+ double alpha,
+ double theta) {
+ super(rng, alpha, theta);
+ oneOverTheta = 1 / theta;
+ bGSOptim = 1 + theta / Math.E;
+ }
+
+ @Override
+ public double sample() {
// [1]: p. 228, Algorithm GS.
while (true) {
@@ -102,24 +122,56 @@ public class AhrensDieterMarsagliaTsangGammaSampler
if (u2 > Math.exp(-x)) {
// Reject.
continue;
- } else {
- return alpha * x;
}
- } else {
- // Step 3:
+ return alpha * x;
+ }
- final double x = -Math.log((bGSOptim - p) * oneOverTheta);
- final double u2 = rng.nextDouble();
+ // Step 3:
- if (u2 > Math.pow(x, theta - 1)) {
- // Reject.
- continue;
- } else {
- return alpha * x;
- }
+ final double x = -Math.log((bGSOptim - p) * oneOverTheta);
+ final double u2 = rng.nextDouble();
+
+ if (u2 > Math.pow(x, theta - 1)) {
+ // Reject.
+ continue;
}
+ return alpha * x;
}
- } else {
+ }
+ }
+
+ /**
+ * Class to sample from the Gamma distribution when the {@code theta >= 1}.
+ */
+ private static class LargeThetaAhrensDieterMarsagliaTsangGammaSampler
+ extends BaseAhrensDieterMarsagliaTsangGammaSampler {
+
+ /** 1/3 */
+ private static final double ONE_THIRD = 1d / 3;
+
+ /** Optimization (see code). */
+ private final double dOptim;
+ /** Optimization (see code). */
+ private final double cOptim;
+ /** Gaussian sampling. */
+ private final NormalizedGaussianSampler gaussian;
+
+ /**
+ * @param rng Generator of uniformly distributed random numbers.
+ * @param alpha Alpha shape parameter of the distribution.
+ * @param theta Theta scale parameter of the distribution.
+ */
+ LargeThetaAhrensDieterMarsagliaTsangGammaSampler(UniformRandomProvider rng,
+ double alpha,
+ double theta) {
+ super(rng, alpha, theta);
+ gaussian = new ZigguratNormalizedGaussianSampler(rng);
+ dOptim = theta - ONE_THIRD;
+ cOptim = ONE_THIRD / Math.sqrt(dOptim);
+ }
+
+ @Override
+ public double sample() {
while (true) {
final double x = gaussian.sample();
final double oPcTx = 1 + cOptim * x;
@@ -144,9 +196,29 @@ public class AhrensDieterMarsagliaTsangGammaSampler
}
}
+ /**
+ * @param rng Generator of uniformly distributed random numbers.
+ * @param alpha Alpha shape parameter of the distribution.
+ * @param theta Theta scale parameter of the distribution.
+ */
+ public AhrensDieterMarsagliaTsangGammaSampler(UniformRandomProvider rng,
+ double alpha,
+ double theta) {
+ super(null);
+ delegate = theta < 1 ?
+ new SmallThetaAhrensDieterMarsagliaTsangGammaSampler(rng, alpha, theta) :
+ new LargeThetaAhrensDieterMarsagliaTsangGammaSampler(rng, alpha, theta);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double sample() {
+ return delegate.sample();
+ }
+
/** {@inheritDoc} */
@Override
public String toString() {
- return "Ahrens-Dieter-Marsaglia-Tsang Gamma deviate [" + rng.toString() + "]";
+ return delegate.toString();
}
}