diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cauchy.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cauchy.java index 3ab4aaf4548915fe6de78d90ce103a82f522d559..f316640b6f3d78f09dac706a26d94790e5bf5a36 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cauchy.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cauchy.java @@ -25,9 +25,9 @@ public final class Cauchy { // contains only static classes } - public static final class RCauchy implements RandFunction2_Double { + public static final class RCauchy extends RandFunction2_Double { @Override - public double evaluate(double location, double scale, RandomNumberProvider rand) { + public double execute(double location, double scale, RandomNumberProvider rand) { if (Double.isNaN(location) || !Double.isFinite(scale) || scale < 0) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java index 4925be2e7668b809c858a9ab8357bf45df62bcdb..24e3dfb71a5fcc398c73a54ba570045501f9ae2b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java @@ -12,7 +12,6 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.library.stats.MathConstants.M_LN2; -import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -26,13 +25,19 @@ public final class DPQ { // only static methods } - public static final class EarlyReturn extends ControlFlowException { + public static final class EarlyReturn extends Exception { private static final long serialVersionUID = 1182697355931636213L; public final double result; private EarlyReturn(double result) { this.result = result; } + + @SuppressWarnings("sync-override") + @Override + public Throwable fillInStackTrace() { + return null; + } } // R >= 3.1.0: # define R_nonint(x) (fabs((x) - R_forceint(x)) > 1e-7) @@ -148,6 +153,13 @@ public final class DPQ { } } + // R_P_bounds_Inf_01 + public static void rpboundsinf01(double x, boolean lowerTail, boolean logP) throws EarlyReturn { + if (!Double.isFinite(x)) { + throw new EarlyReturn(x > 0 ? rdt0(lowerTail, logP) : rdt0(lowerTail, logP)); + } + } + // R_Q_P01_check public static void rqp01check(double p, boolean logP) throws EarlyReturn { if ((logP && p > 0) || (!logP && (p < 0 || p > 1))) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Exp.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Exp.java index 05c81882607860c2964fcd497ca817555579a8b3..0d3e6ecbc329391c74220746d77accc7919f6f49 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Exp.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Exp.java @@ -17,7 +17,11 @@ import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberPr import com.oracle.truffle.r.library.stats.StatsFunctions.Function2_1; import com.oracle.truffle.r.library.stats.StatsFunctions.Function2_2; -public class Exp { +public final class Exp { + private Exp() { + // only static members + } + public static final class DExp implements Function2_1 { @Override public double evaluate(double x, double scale, boolean giveLog) { @@ -37,9 +41,9 @@ public class Exp { } } - public static final class RExp implements RandFunction1_Double { + public static final class RExp extends RandFunction1_Double { @Override - public double evaluate(double scale, RandomNumberProvider rand) { + public double execute(double scale, RandomNumberProvider rand) { if (!Double.isFinite(scale) || scale <= 0.0) { return scale == 0. ? 0. : RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Geom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Geom.java index 2d9c81f9f15d5b506cc803b3adabdd34cf30ade5..05443e198bffdfd8b79857b67b4ffbd56d6c5949 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Geom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Geom.java @@ -35,7 +35,11 @@ import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberPr import com.oracle.truffle.r.library.stats.StatsFunctions.Function2_1; import com.oracle.truffle.r.library.stats.StatsFunctions.Function2_2; -public class Geom { +public final class Geom { + private Geom() { + // only static members + } + public static final class QGeom implements Function2_2 { @Override public double evaluate(double p, double prob, boolean lowerTail, boolean logP) { @@ -87,9 +91,9 @@ public class Geom { } } - public static final class RGeom implements RandFunction1_Double { + public static final class RGeom extends RandFunction1_Double { @Override - public double evaluate(double p, RandomNumberProvider rand) { + public double execute(double p, RandomNumberProvider rand) { if (!Double.isFinite(p) || p <= 0 || p > 1) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/LogNormal.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/LogNormal.java index 824a4acef8f241ac6d5d34f358f970ce727e15a7..b95f76cf446c1a27b23bca81504db510a9c110ef 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/LogNormal.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/LogNormal.java @@ -23,15 +23,15 @@ public final class LogNormal { // only static members } - public static final class RLNorm implements RandFunction2_Double { + public static final class RLNorm extends RandFunction2_Double { private final Rnorm rnorm = new Rnorm(); @Override - public double evaluate(double meanlog, double sdlog, RandomNumberProvider rand) { + public double execute(double meanlog, double sdlog, RandomNumberProvider rand) { if (Double.isNaN(meanlog) || !Double.isFinite(sdlog) || sdlog < 0.) { return RMath.mlError(); } - return Math.exp(rnorm.evaluate(meanlog, sdlog, rand)); + return Math.exp(rnorm.execute(meanlog, sdlog, rand)); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java index d62ab89e7e74c7d8962352525c10588f022e4c2d..5e1ce8ccb67f9fe4a5636c9194a4bcdf78437e24 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java @@ -20,12 +20,12 @@ import static com.oracle.truffle.r.library.stats.RMath.fmin2; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RBeta implements RandFunction2_Double { +public final class RBeta extends RandFunction2_Double { private static final double expmax = (DBL_MAX_EXP * M_LN2); /* = log(DBL_MAX) */ @Override - public double evaluate(double aa, double bb, RandomNumberProvider rand) { + public double execute(double aa, double bb, RandomNumberProvider rand) { if (Double.isNaN(aa) || Double.isNaN(bb) || aa < 0. || bb < 0.) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RChisq.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RChisq.java index 67ba496753caf017b672e0003654a11f1eb4904d..975819f6bf3be065b8036f7c4c4aeb2b512db474 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RChisq.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RChisq.java @@ -14,16 +14,16 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RChisq implements RandFunction1_Double { +public final class RChisq extends RandFunction1_Double { public static double rchisq(double df, RandomNumberProvider rand) { if (!Double.isFinite(df) || df < 0.0) { return RMath.mlError(); } - return new RGamma().evaluate(df / 2.0, 2.0, rand); + return new RGamma().execute(df / 2.0, 2.0, rand); } @Override - public double evaluate(double a, RandomNumberProvider rand) { + public double execute(double a, RandomNumberProvider rand) { return rchisq(a, rand); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RGamma.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RGamma.java index eea9b5aea8027a913db009a0f96260fa22327fed..c5b40e24c48e85810274f072acbc2304e48147e8 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RGamma.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RGamma.java @@ -16,7 +16,7 @@ import static com.oracle.truffle.r.library.stats.TOMS708.fabs; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public class RGamma implements RandFunction2_Double { +public class RGamma extends RandFunction2_Double { private static final double sqrt32 = 5.656854; private static final double exp_m1 = 0.36787944117144232159; /* exp(-1) = 1/e */ @@ -41,7 +41,7 @@ public class RGamma implements RandFunction2_Double { private static final double a7 = 0.1233795; @Override - public double evaluate(double a, double scale, RandomNumberProvider rand) { + public double execute(double a, double scale, RandomNumberProvider rand) { // TODO: state variables double aa = 0.; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RHyper.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RHyper.java index 7dba16badee221972e01340629a88e35ffe0a1b1..7af8863b92164203fd5a0d8ccf56771a7d0e940b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RHyper.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RHyper.java @@ -21,7 +21,7 @@ import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberPr import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; -public final class RHyper implements RandFunction3_Double { +public final class RHyper extends RandFunction3_Double { private static final double[] al = { 0.0, /* ln(0!)=ln(1) */ 0.0, /* ln(1!)=ln(1) */ @@ -87,7 +87,7 @@ public final class RHyper implements RandFunction3_Double { // rhyper(NR, NB, n) -- NR 'red', NB 'blue', n drawn, how many are 'red' @Override @TruffleBoundary - public double evaluate(double nn1in, double nn2in, double kkin, RandomNumberProvider rand) { + public double execute(double nn1in, double nn2in, double kkin, RandomNumberProvider rand) { /* extern double afc(int); */ int nn1; @@ -117,7 +117,7 @@ public final class RHyper implements RandFunction3_Double { // FIXME: Much faster to give rbinom() approx when appropriate; -> see Kuensch(1989) // Johnson, Kotz,.. p.258 (top) mention the *four* different binomial approximations if (kkin == 1.) { // Bernoulli - return rbinom.evaluate(kkin, nn1in / (nn1in + nn2in), rand); + return rbinom.execute(kkin, nn1in / (nn1in + nn2in), rand); } // Slow, but safe: return F^{-1}(U) where F(.) = phyper(.) and U ~ U[0,1] return QHyper.qhyper(rand.unifRand(), nn1in, nn2in, kkin, false, false); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java index 961dafe00d10a34156926a5b54379f5510e45ebc..f21be8e24cffbacfc8038804da8c2027be0cbf4a 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java @@ -14,9 +14,9 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RLogis implements RandFunction2_Double { +public final class RLogis extends RandFunction2_Double { @Override - public double evaluate(double location, double scale, RandomNumberProvider rand) { + public double execute(double location, double scale, RandomNumberProvider rand) { if (Double.isNaN(location) || !Double.isFinite(scale)) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinom.java index 7a49a79e36cf75d48bb04762daeac1bb7e791042..8480bde3c0db7647e925bf2254fff2c68d00e5e9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinom.java @@ -163,7 +163,7 @@ public abstract class RMultinom extends RExternalBuiltinNode.Arg3 { if (probK.compareTo(BigDecimal.ZERO) != 0) { pp = probK.divide(pTot, RoundingMode.HALF_UP).doubleValue(); // System.out.printf("[%d] %.17f\n", k + 1, pp); - rN[rnStartIdx + k] = ((pp < 1.) ? (int) rbinom.evaluate((double) n, pp, rand) : + rN[rnStartIdx + k] = ((pp < 1.) ? (int) rbinom.execute((double) n, pp, rand) : /* >= 1; > 1 happens because of rounding */ n); n -= rN[rnStartIdx + k]; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNbinomMu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNbinomMu.java index c095616fa14e46565ba778fbf3356a6f257ddc66..03118361e216015b5a02094b8c0cb0255036da12 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNbinomMu.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNbinomMu.java @@ -14,17 +14,17 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RNbinomMu implements RandFunction2_Double { +public final class RNbinomMu extends RandFunction2_Double { private final RGamma rgamma = new RGamma(); @Override - public double evaluate(double size, double mu, RandomNumberProvider rand) { + public double execute(double size, double mu, RandomNumberProvider rand) { if (!Double.isFinite(mu) || Double.isNaN(size) || size <= 0 || mu < 0) { return RMath.mlError(); } if (!Double.isFinite(size)) { size = Double.MAX_VALUE / 2.; } - return (mu == 0) ? 0 : RPois.rpois(rgamma.evaluate(size, mu / size, rand), rand); + return (mu == 0) ? 0 : RPois.rpois(rgamma.execute(size, mu / size, rand), rand); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNchisq.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNchisq.java index 5e22bda3f5faf7e3fd655ed596183d3df56e6c07..3b17100cc5cad25ce2b30d84993069af020931fc 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNchisq.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNchisq.java @@ -16,24 +16,24 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RNchisq implements RandFunction2_Double { +public final class RNchisq extends RandFunction2_Double { private final RGamma rgamma = new RGamma(); @Override - public double evaluate(double df, double lambda, RandomNumberProvider rand) { + public double execute(double df, double lambda, RandomNumberProvider rand) { if (!Double.isFinite(df) || !Double.isFinite(lambda) || df < 0. || lambda < 0.) { return RMath.mlError(); } if (lambda == 0.) { - return (df == 0.) ? 0. : rgamma.evaluate(df / 2., 2., rand); + return (df == 0.) ? 0. : rgamma.execute(df / 2., 2., rand); } else { double r = RPois.rpois(lambda / 2., rand); if (r > 0.) { r = RChisq.rchisq(2. * r, rand); } if (df > 0.) { - r += rgamma.evaluate(df / 2., 2., rand); + r += rgamma.execute(df / 2., 2., rand); } return r; } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RPois.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RPois.java index 2638fa34de84ce1797d21b9e75acdb4798ab2ba5..397cd4f7a7b437a580af80d175f0318d18432b15 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RPois.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RPois.java @@ -16,7 +16,7 @@ import static com.oracle.truffle.r.library.stats.MathConstants.M_1_SQRT_2PI; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RPois implements RandFunction1_Double { +public final class RPois extends RandFunction1_Double { private static final double a0 = -0.5; private static final double a1 = 0.3333333; @@ -38,25 +38,25 @@ public final class RPois implements RandFunction1_Double { /* These are static --- persistent between calls for same mu : */ // TODO: state variables - static int l = 0; - static int m = 0; - static double b1; - static double b2; - static double c = 0; - static double c0 = 0; - static double c1 = 0; - static double c2 = 0; - static double c3 = 0; - static double[] pp = new double[36]; - static double p0 = 0; - static double p = 0; - static double q = 0; - static double s = 0; - static double d = 0; - static double omega = 0; - static double bigL = 0; /* integer "w/o overflow" */ - static double muprev = 0.; - static double muprev2 = 0.; /* , muold = 0. */ + private static int l = 0; + private static int m = 0; + private static double b1; + private static double b2; + private static double c = 0; + private static double c0 = 0; + private static double c1 = 0; + private static double c2 = 0; + private static double c3 = 0; + private static final double[] pp = new double[36]; + private static double p0 = 0; + private static double p = 0; + private static double q = 0; + private static double s = 0; + private static double d = 0; + private static double omega = 0; + private static double bigL = 0; /* integer "w/o overflow" */ + private static double muprev = 0.; + private static double muprev2 = 0.; /* , muold = 0. */ public static double rpois(double mu, RandomNumberProvider rand) { /* Local Vars [initialize some for -Wall]: */ @@ -275,7 +275,7 @@ public final class RPois implements RandFunction1_Double { } @Override - public double evaluate(double mu, RandomNumberProvider rand) { + public double execute(double mu, RandomNumberProvider rand) { return rpois(mu, rand); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RWeibull.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RWeibull.java index 3686f96591d283d05747f0a49deb6dbb5b4c1b93..638e406f5404fb7cf7613e122f0a31b2ab5b5a42 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RWeibull.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RWeibull.java @@ -14,9 +14,9 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class RWeibull implements RandFunction2_Double { +public final class RWeibull extends RandFunction2_Double { @Override - public double evaluate(double shape, double scale, RandomNumberProvider rand) { + public double execute(double shape, double scale, RandomNumberProvider rand) { if (!Double.isFinite(shape) || !Double.isFinite(scale) || shape <= 0. || scale <= 0.) { return scale == 0. ? 0. : RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java index b3548e5ea37864b9ef8641ae6a6b5d13ac0b7e56..2bdaeeef565e8154753a5c4b561d1e56db0d6bd1 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java @@ -22,16 +22,21 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; -import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory.ConvertToLengthNodeGen; +import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory.RandFunction1NodeGen; +import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory.RandFunction2NodeGen; +import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory.RandFunction3NodeGen; +import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDouble; @@ -43,6 +48,11 @@ import com.oracle.truffle.r.runtime.rng.RRNG; import com.oracle.truffle.r.runtime.rng.RRNG.NormKind; import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator; +/** + * Contains infrastructure for R external functions implementing generation of a random value from + * given random value distribution. To implement such external function, implement one of: + * {@link RandFunction3_Double}, {@link RandFunction2_Double} or {@link RandFunction1_Double}. + */ public final class RandGenerationFunctions { @CompilationFinal private static final RDouble DUMMY_VECTOR = RDouble.valueOf(1); @@ -51,14 +61,22 @@ public final class RandGenerationFunctions { } public static final class RandomNumberProvider { - private final RandomNumberGenerator generator; - private final NormKind normKind; + final RandomNumberGenerator generator; + final NormKind normKind; public RandomNumberProvider(RandomNumberGenerator generator, NormKind normKind) { this.generator = generator; this.normKind = normKind; } + public static RandomNumberProvider fromCurrentRNG() { + return new RandomNumberProvider(RRNG.currentGenerator(), RRNG.currentNormKind()); + } + + protected boolean isSame(RandomNumberProvider other) { + return this.generator == other.generator && this.normKind == other.normKind; + } + public double unifRand() { return generator.genrandDouble(); } @@ -74,135 +92,32 @@ public final class RandGenerationFunctions { // inspired by the DEFRAND{X}_REAL and DEFRAND{X}_INT macros in GnuR - public interface RandFunction3_Double { - double evaluate(double a, double b, double c, RandomNumberProvider rand); + public abstract static class RandFunction3_Double extends Node { + public abstract double execute(double a, double b, double c, RandomNumberProvider rand); } - public interface RandFunction2_Double extends RandFunction3_Double { - double evaluate(double a, double b, RandomNumberProvider rand); + public abstract static class RandFunction2_Double extends RandFunction3_Double { + public abstract double execute(double a, double b, RandomNumberProvider rand); @Override - default double evaluate(double a, double b, double c, RandomNumberProvider rand) { - return evaluate(a, b, rand); + public final double execute(double a, double b, double c, RandomNumberProvider rand) { + return execute(a, b, rand); } } - public interface RandFunction1_Double extends RandFunction2_Double { - double evaluate(double a, RandomNumberProvider rand); + public abstract static class RandFunction1_Double extends RandFunction2_Double { + public abstract double execute(double a, RandomNumberProvider rand); @Override - default double evaluate(double a, double b, RandomNumberProvider rand) { - return evaluate(a, rand); - } - } - - static final class RandGenerationProfiles { - final BranchProfile nanResult = BranchProfile.create(); - final BranchProfile nan = BranchProfile.create(); - final VectorLengthProfile resultVectorLengthProfile = VectorLengthProfile.create(); - final LoopConditionProfile loopConditionProfile = LoopConditionProfile.createCountingProfile(); - private final ValueProfile randClassProfile = ValueProfile.createClassProfile(); - private final ValueProfile generatorProfile = ValueProfile.createIdentityProfile(); - private final ValueProfile normKindProfile = ValueProfile.createEqualityProfile(); - - public static RandGenerationProfiles create() { - return new RandGenerationProfiles(); - } - - public RandomNumberProvider createRandProvider() { - return new RandomNumberProvider(randClassProfile.profile(generatorProfile.profile(RRNG.currentGenerator())), normKindProfile.profile(RRNG.currentNormKind())); - } - } - - private static RAbstractIntVector evaluate3Int(Node node, RandFunction3_Double function, int lengthIn, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, - RandGenerationProfiles profiles) { - int length = lengthIn; - int aLength = a.getLength(); - int bLength = b.getLength(); - int cLength = c.getLength(); - if (aLength == 0 || bLength == 0 || cLength == 0) { - profiles.nanResult.enter(); - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); - int[] nansResult = new int[length]; - Arrays.fill(nansResult, RRuntime.INT_NA); - return RDataFactory.createIntVector(nansResult, false); - } - - length = profiles.resultVectorLengthProfile.profile(length); - RNode.reportWork(node, length); - boolean nans = false; - int[] result = new int[length]; - RRNG.getRNGState(); - RandomNumberProvider rand = profiles.createRandProvider(); - profiles.loopConditionProfile.profileCounted(length); - for (int i = 0; profiles.loopConditionProfile.inject(i < length); i++) { - double aValue = a.getDataAt(i % aLength); - double bValue = b.getDataAt(i % bLength); - double cValue = c.getDataAt(i % cLength); - double value = function.evaluate(aValue, bValue, cValue, rand); - if (Double.isNaN(value) || value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - profiles.nan.enter(); - nans = true; - result[i] = RRuntime.INT_NA; - } else { - result[i] = (int) value; - } - } - RRNG.putRNGState(); - if (nans) { - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); - } - return RDataFactory.createIntVector(result, !nans); - } - - private static RAbstractDoubleVector evaluate3Double(Node node, RandFunction3_Double function, int lengthIn, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, - RandGenerationProfiles profiles) { - int length = lengthIn; - int aLength = a.getLength(); - int bLength = b.getLength(); - int cLength = c.getLength(); - if (aLength == 0 || bLength == 0 || cLength == 0) { - profiles.nanResult.enter(); - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); - return createVectorOf(length, RRuntime.DOUBLE_NA); - } - - length = profiles.resultVectorLengthProfile.profile(length); - RNode.reportWork(node, length); - boolean nans = false; - double[] result; - result = new double[length]; - RRNG.getRNGState(); - RandomNumberProvider rand = profiles.createRandProvider(); - profiles.loopConditionProfile.profileCounted(length); - for (int i = 0; profiles.loopConditionProfile.inject(i < length); i++) { - double aValue = a.getDataAt(i % aLength); - double bValue = b.getDataAt(i % bLength); - double cValue = c.getDataAt(i % cLength); - double value = function.evaluate(aValue, bValue, cValue, rand); - if (Double.isNaN(value) || RRuntime.isNA(value)) { - profiles.nan.enter(); - nans = true; - } - result[i] = value; + public final double execute(double a, double b, RandomNumberProvider rand) { + return execute(a, rand); } - RRNG.putRNGState(); - if (nans) { - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); - } - return RDataFactory.createDoubleVector(result, !nans); - } - - private static RAbstractDoubleVector createVectorOf(int length, double element) { - double[] nansResult = new double[length]; - Arrays.fill(nansResult, element); - return RDataFactory.createDoubleVector(nansResult, false); } /** * Converts given value to actual length that should be used as length of the output vector. The * argument must be cast using {@link #addLengthCast(CastBuilder)}. Using this node allows us to - * avoid casting of long vectors to integers, if we only need to know their length. + * avoid casting of long vectors to integers if we only need to know their length. */ protected abstract static class ConvertToLength extends Node { public abstract int execute(RAbstractVector value); @@ -229,112 +144,242 @@ public final class RandGenerationFunctions { } } - public abstract static class Function3_IntNode extends RExternalBuiltinNode.Arg4 { - private final RandFunction3_Double function; + /** + * Executor node handles the validation, the loop over all vector elements, the creation of the + * result vector, and similar. The random function is provided as implementation of + * {@link RandFunction3_Double}. + */ + @TypeSystemReference(EmptyTypeSystemFlatLayout.class) + protected abstract static class RandFunctionExecutorBase extends Node { + static final class RandGenerationNodeData { + final BranchProfile nanResult = BranchProfile.create(); + final BranchProfile nan = BranchProfile.create(); + final VectorLengthProfile resultVectorLengthProfile = VectorLengthProfile.create(); + final LoopConditionProfile loopConditionProfile = LoopConditionProfile.createCountingProfile(); + + public static RandGenerationNodeData create() { + return new RandGenerationNodeData(); + } + } + + public abstract Object execute(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandomNumberProvider rand); + @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); - protected Function3_IntNode(RandFunction3_Double function) { - this.function = function; + @Specialization(guards = {"randCached.isSame(rand)"}) + protected final Object evaluateWithCached(RAbstractVector lengthVec, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, + @SuppressWarnings("unused") RandomNumberProvider rand, + @Cached("rand") RandomNumberProvider randCached, + @Cached("create()") RandGenerationNodeData nodeData) { + return evaluateWrapper(lengthVec, a, b, c, randCached, nodeData); } - @Override - protected void createCasts(CastBuilder casts) { - ConvertToLength.addLengthCast(casts); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asDoubleVector(); + @Specialization(contains = "evaluateWithCached") + protected final Object evaluateFallback(RAbstractVector lengthVec, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandomNumberProvider rand, + @Cached("create()") RandGenerationNodeData nodeData) { + return evaluateWrapper(lengthVec, a, b, c, rand, nodeData); } - @Specialization - protected RAbstractIntVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate3Int(this, function, convertToLength.execute(length), a, b, c, profiles); + private Object evaluateWrapper(RAbstractVector lengthVec, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandomNumberProvider rand, + RandGenerationNodeData nodeData) { + int length = nodeData.resultVectorLengthProfile.profile(convertToLength.execute(lengthVec)); + RNode.reportWork(this, length); + Object result = evaluate(length, a, b, c, nodeData, rand); + return result; + } + + Object evaluate(int length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandGenerationNodeData nodeData, RandomNumberProvider randProvider) { + // DSL generates code for this class too, with abstract method it would not compile + throw RInternalError.shouldNotReachHere("must be overridden"); + } + + static void putRNGState() { + // Note: we call putRNGState only if we actually changed the state, i.e. called random + // number generation. We do not need to getRNGState() because the parent wrapper node + // should do that for us + RRNG.putRNGState(); + } + + static void showNAWarning() { + RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); } } - public abstract static class Function2_IntNode extends RExternalBuiltinNode.Arg3 { - private final RandFunction2_Double function; - @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + @TypeSystemReference(EmptyTypeSystemFlatLayout.class) + protected abstract static class RandFunctionIntExecutorNode extends RandFunctionExecutorBase { + @Child private RandFunction3_Double function; - protected Function2_IntNode(RandFunction2_Double function) { + protected RandFunctionIntExecutorNode(RandFunction3_Double function) { this.function = function; } @Override - protected void createCasts(CastBuilder casts) { - ConvertToLength.addLengthCast(casts); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - } + protected RAbstractIntVector evaluate(int length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandGenerationNodeData nodeData, + RandomNumberProvider randProvider) { + int aLength = a.getLength(); + int bLength = b.getLength(); + int cLength = c.getLength(); + if (aLength == 0 || bLength == 0 || cLength == 0) { + nodeData.nanResult.enter(); + showNAWarning(); + int[] nansResult = new int[length]; + Arrays.fill(nansResult, RRuntime.INT_NA); + return RDataFactory.createIntVector(nansResult, false); + } - @Specialization - protected RAbstractIntVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate3Int(this, function, convertToLength.execute(length), a, b, DUMMY_VECTOR, profiles); + boolean nans = false; + int[] result = new int[length]; + nodeData.loopConditionProfile.profileCounted(length); + for (int i = 0; nodeData.loopConditionProfile.inject(i < length); i++) { + double aValue = a.getDataAt(i % aLength); + double bValue = b.getDataAt(i % bLength); + double cValue = c.getDataAt(i % cLength); + double value = function.execute(aValue, bValue, cValue, randProvider); + if (Double.isNaN(value) || value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + nodeData.nan.enter(); + nans = true; + result[i] = RRuntime.INT_NA; + } else { + result[i] = (int) value; + } + } + putRNGState(); + if (nans) { + showNAWarning(); + } + return RDataFactory.createIntVector(result, !nans); } } - public abstract static class Function1_IntNode extends RExternalBuiltinNode.Arg2 { - private final RandFunction1_Double function; - @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + @TypeSystemReference(EmptyTypeSystemFlatLayout.class) + protected abstract static class RandFunctionDoubleExecutorNode extends RandFunctionExecutorBase { + @Child private RandFunction3_Double function; - protected Function1_IntNode(RandFunction1_Double function) { + protected RandFunctionDoubleExecutorNode(RandFunction3_Double function) { this.function = function; } + @Override + protected RAbstractDoubleVector evaluate(int length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandGenerationNodeData nodeData, + RandomNumberProvider randProvider) { + int aLength = a.getLength(); + int bLength = b.getLength(); + int cLength = c.getLength(); + if (aLength == 0 || bLength == 0 || cLength == 0) { + nodeData.nanResult.enter(); + showNAWarning(); + double[] nansResult = new double[length]; + Arrays.fill(nansResult, RRuntime.DOUBLE_NA); + return RDataFactory.createDoubleVector(nansResult, false); + } + + boolean nans = false; + double[] result; + result = new double[length]; + nodeData.loopConditionProfile.profileCounted(length); + for (int i = 0; nodeData.loopConditionProfile.inject(i < length); i++) { + double aValue = a.getDataAt(i % aLength); + double bValue = b.getDataAt(i % bLength); + double cValue = c.getDataAt(i % cLength); + double value = function.execute(aValue, bValue, cValue, randProvider); + if (Double.isNaN(value) || RRuntime.isNA(value)) { + nodeData.nan.enter(); + nans = true; + } + result[i] = value; + } + putRNGState(); + if (nans) { + showNAWarning(); + } + return RDataFactory.createDoubleVector(result, !nans); + } + } + + public abstract static class RandFunction3Node extends RExternalBuiltinNode.Arg4 { + @Child private RandFunctionExecutorBase inner; + + protected RandFunction3Node(RandFunctionExecutorBase inner) { + this.inner = inner; + } + + public static RandFunction3Node createInt(RandFunction3_Double function) { + return RandFunction3NodeGen.create(RandGenerationFunctionsFactory.RandFunctionIntExecutorNodeGen.create(function)); + } + + public static RandFunction3Node createDouble(RandFunction3_Double function) { + return RandFunction3NodeGen.create(RandGenerationFunctionsFactory.RandFunctionDoubleExecutorNodeGen.create(function)); + } + @Override protected void createCasts(CastBuilder casts) { ConvertToLength.addLengthCast(casts); casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); + casts.arg(3).asDoubleVector(); } @Specialization - protected RAbstractIntVector evaluate(RAbstractVector length, RAbstractDoubleVector a, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate3Int(this, function, convertToLength.execute(length), a, DUMMY_VECTOR, DUMMY_VECTOR, profiles); + protected Object evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c) { + RRNG.getRNGState(); + return inner.execute(length, a, b, c, RandomNumberProvider.fromCurrentRNG()); } } - public abstract static class Function1_DoubleNode extends RExternalBuiltinNode.Arg2 { - private final RandFunction1_Double function; - @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + public abstract static class RandFunction2Node extends RExternalBuiltinNode.Arg3 { + @Child private RandFunctionExecutorBase inner; - protected Function1_DoubleNode(RandFunction1_Double function) { - this.function = function; + protected RandFunction2Node(RandFunctionExecutorBase inner) { + this.inner = inner; + } + + public static RandFunction2Node createInt(RandFunction2_Double function) { + return RandFunction2NodeGen.create(RandGenerationFunctionsFactory.RandFunctionIntExecutorNodeGen.create(function)); + } + + public static RandFunction2Node createDouble(RandFunction2_Double function) { + return RandFunction2NodeGen.create(RandGenerationFunctionsFactory.RandFunctionDoubleExecutorNodeGen.create(function)); } @Override protected void createCasts(CastBuilder casts) { ConvertToLength.addLengthCast(casts); casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); } @Specialization - protected RAbstractDoubleVector evaluate(RAbstractVector length, RAbstractDoubleVector a, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate3Double(this, function, convertToLength.execute(length), a, DUMMY_VECTOR, DUMMY_VECTOR, profiles); + protected Object evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b) { + RRNG.getRNGState(); + return inner.execute(length, a, b, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG()); } } - public abstract static class Function2_DoubleNode extends RExternalBuiltinNode.Arg3 { - private final RandFunction2_Double function; - @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + public abstract static class RandFunction1Node extends RExternalBuiltinNode.Arg2 { + @Child private RandFunctionExecutorBase inner; - protected Function2_DoubleNode(RandFunction2_Double function) { - this.function = function; + protected RandFunction1Node(RandFunctionExecutorBase inner) { + this.inner = inner; + } + + public static RandFunction1Node createInt(RandFunction1_Double function) { + return RandFunction1NodeGen.create(RandGenerationFunctionsFactory.RandFunctionIntExecutorNodeGen.create(function)); + } + + public static RandFunction1Node createDouble(RandFunction1_Double function) { + return RandFunction1NodeGen.create(RandGenerationFunctionsFactory.RandFunctionDoubleExecutorNodeGen.create(function)); } @Override protected void createCasts(CastBuilder casts) { ConvertToLength.addLengthCast(casts); casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); } @Specialization - protected RAbstractDoubleVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate3Double(this, function, convertToLength.execute(length), a, b, DUMMY_VECTOR, profiles); + protected Object evaluate(RAbstractVector length, RAbstractDoubleVector a) { + RRNG.getRNGState(); + return inner.execute(length, a, DUMMY_VECTOR, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG()); } } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java index db6545e1e193ce0332d1ef64f35802b55ab55aa2..edd2864e79a007ee03e027004f64e8298c44f509 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java @@ -18,12 +18,12 @@ import com.oracle.truffle.r.runtime.RRuntime; // transcribed from rbinom.c -public final class Rbinom implements RandFunction2_Double { +public final class Rbinom extends RandFunction2_Double { private final Qbinom qbinom = new Qbinom(); @Override - public double evaluate(double nin, double pp, RandomNumberProvider rand) { + public double execute(double nin, double pp, RandomNumberProvider rand) { double psave = -1.0; int nsave = -1; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rf.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rf.java index 21cbb6d2bcf8609018f0fa730b73c6f59f0c8892..c753f1777fe6e31adb429f4ae2779b1d951bea3c 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rf.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rf.java @@ -14,9 +14,9 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class Rf implements RandFunction2_Double { +public final class Rf extends RandFunction2_Double { @Override - public double evaluate(double n1, double n2, RandomNumberProvider rand) { + public double execute(double n1, double n2, RandomNumberProvider rand) { if (Double.isNaN(n1) || Double.isNaN(n2) || n1 <= 0. || n2 <= 0.) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java index 1996274e87ea2c9c733dfdf4ad7ff06cb2eb0270..be60d6863d13ddd4bf96b974ef6a97b40ccfe4d4 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java @@ -11,16 +11,27 @@ */ package com.oracle.truffle.r.library.stats; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class Rnorm implements RandFunction2_Double { +public final class Rnorm extends RandFunction2_Double { + private final BranchProfile errorProfile = BranchProfile.create(); + private final ConditionProfile zeroSigmaProfile = ConditionProfile.createBinaryProfile(); + private final ValueProfile sigmaValueProfile = ValueProfile.createEqualityProfile(); + private final ValueProfile muValueProfile = ValueProfile.createEqualityProfile(); + @Override - public double evaluate(double mu, double sigma, RandomNumberProvider rand) { + public double execute(double muIn, double sigmaIn, RandomNumberProvider rand) { + double sigma = sigmaValueProfile.profile(sigmaIn); + double mu = muValueProfile.profile(muIn); if (Double.isNaN(mu) || !Double.isFinite(sigma) || sigma < 0.) { + errorProfile.enter(); return RMath.mlError(); } - if (sigma == 0. || !Double.isFinite(mu)) { + if (zeroSigmaProfile.profile(sigma == 0. || !Double.isFinite(mu))) { return mu; /* includes mu = +/- Inf with finite sigma */ } else { return mu + sigma * rand.normRand(); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rt.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rt.java index 51a266499e2e0af2b8c120ff15edcc26ae123310..80c8ea59fc6e6b06560ceac696d508d192bb1d59 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rt.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rt.java @@ -16,9 +16,9 @@ import static com.oracle.truffle.r.library.stats.RChisq.rchisq; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; -public final class Rt implements RandFunction1_Double { +public final class Rt extends RandFunction1_Double { @Override - public double evaluate(double df, RandomNumberProvider rand) { + public double execute(double df, RandomNumberProvider rand) { if (Double.isNaN(df) || df <= 0.0) { return RMath.mlError(); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java index 5701011cf53f8e9f6ee09cae6e6294696b393de8..d5729f4a3bd45aa8ad117e0f5ed3a2d3ef066886 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java @@ -22,17 +22,28 @@ */ package com.oracle.truffle.r.library.stats; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; import com.oracle.truffle.r.runtime.RRuntime; -public final class Runif implements RandFunction2_Double { +public final class Runif extends RandFunction2_Double { + private final BranchProfile errorProfile = BranchProfile.create(); + private final ConditionProfile minEqualsMaxProfile = ConditionProfile.createBinaryProfile(); + private final ValueProfile minValueProfile = ValueProfile.createEqualityProfile(); + private final ValueProfile maxValueProfile = ValueProfile.createEqualityProfile(); + @Override - public double evaluate(double min, double max, RandomNumberProvider rand) { + public double execute(double minIn, double maxIn, RandomNumberProvider rand) { + double min = minValueProfile.profile(minIn); + double max = maxValueProfile.profile(maxIn); if (!RRuntime.isFinite(min) || !RRuntime.isFinite(max) || max < min) { + errorProfile.enter(); return RMath.mlError(); } - if (min == max) { + if (minEqualsMaxProfile.profile(min == max)) { return min; } return min + rand.unifRand() * (max - min); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Signrank.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Signrank.java index 1b33cb4ddb8d4aeac8960ed8a69100feefeec1e2..a6747c5660a3a8f134c1f57246f02008e5f560ce 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Signrank.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Signrank.java @@ -17,10 +17,13 @@ import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_ import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; public final class Signrank { + private Signrank() { + // only static members + } - public static final class RSignrank implements RandFunction1_Double { + public static final class RSignrank extends RandFunction1_Double { @Override - public double evaluate(double n, RandomNumberProvider rand) { + public double execute(double n, RandomNumberProvider rand) { int i; int k; double r; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java index 006474114406a883f3eecd34dd174f20d8c847b0..acf8b5555f4b196401ecdf46965206a71ca1ff90 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java @@ -19,10 +19,13 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; public final class Wilcox { + private Wilcox() { + // only static members + } - public static final class RWilcox implements RandFunction2_Double { + public static final class RWilcox extends RandFunction2_Double { @Override - public double evaluate(double m, double n, RandomNumberProvider rand) { + public double execute(double m, double n, RandomNumberProvider rand) { int i; int j; int k; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index 279790c9b7f5c15e33802be3b956aefe106a481d..2c2f2c79834c75d9fd5ed6fdf84c491fd066a0ee 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -85,7 +85,9 @@ import com.oracle.truffle.r.library.stats.RNchisq; import com.oracle.truffle.r.library.stats.RPois; import com.oracle.truffle.r.library.stats.RWeibull; import com.oracle.truffle.r.library.stats.RandGenerationFunctions; -import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1Node; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2Node; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction3Node; import com.oracle.truffle.r.library.stats.Rbinom; import com.oracle.truffle.r.library.stats.Rf; import com.oracle.truffle.r.library.stats.Rnorm; @@ -249,41 +251,41 @@ public class CallAndExternalFunctions { case "qnorm": return StatsFunctionsFactory.Function3_2NodeGen.create(new Qnorm()); case "rnorm": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Rnorm()); + return RandFunction2Node.createDouble(new Rnorm()); case "runif": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Runif()); + return RandFunction2Node.createDouble(new Runif()); case "rbeta": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RBeta()); + return RandFunction2Node.createDouble(new RBeta()); case "rgamma": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RGamma()); + return RandFunction2Node.createDouble(new RGamma()); case "rcauchy": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RCauchy()); + return RandFunction2Node.createDouble(new RCauchy()); case "rf": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Rf()); + return RandFunction2Node.createDouble(new Rf()); case "rlogis": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RLogis()); + return RandFunction2Node.createDouble(new RLogis()); case "rweibull": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RWeibull()); + return RandFunction2Node.createDouble(new RWeibull()); case "rnchisq": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RNchisq()); + return RandFunction2Node.createDouble(new RNchisq()); case "rnbinom_mu": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RNbinomMu()); + return RandFunction2Node.createDouble(new RNbinomMu()); case "rwilcox": - return RandGenerationFunctionsFactory.Function2_IntNodeGen.create(new RWilcox()); + return RandFunction2Node.createInt(new RWilcox()); case "rchisq": - return RandGenerationFunctionsFactory.Function1_DoubleNodeGen.create(new RChisq()); + return RandFunction1Node.createDouble(new RChisq()); case "rexp": - return RandGenerationFunctionsFactory.Function1_DoubleNodeGen.create(new RExp()); + return RandFunction1Node.createDouble(new RExp()); case "rgeom": - return RandGenerationFunctionsFactory.Function1_IntNodeGen.create(new RGeom()); + return RandFunction1Node.createInt(new RGeom()); case "rpois": - return RandGenerationFunctionsFactory.Function1_IntNodeGen.create(new RPois()); + return RandFunction1Node.createInt(new RPois()); case "rt": - return RandGenerationFunctionsFactory.Function1_DoubleNodeGen.create(new Rt()); + return RandFunction1Node.createDouble(new Rt()); case "rsignrank": - return RandGenerationFunctionsFactory.Function1_IntNodeGen.create(new RSignrank()); + return RandFunction1Node.createInt(new RSignrank()); case "rhyper": - return RandGenerationFunctionsFactory.Function3_IntNodeGen.create(new RHyper()); + return RandFunction3Node.createInt(new RHyper()); case "qgamma": return StatsFunctionsFactory.Function3_2NodeGen.create(new QgammaFunc()); case "dbinom": @@ -291,7 +293,7 @@ public class CallAndExternalFunctions { case "qbinom": return StatsFunctionsFactory.Function3_2NodeGen.create(new Qbinom()); case "rbinom": - return RandGenerationFunctionsFactory.Function2_IntNodeGen.create(new Rbinom()); + return RandFunction2Node.createInt(new Rbinom()); case "pbinom": return StatsFunctionsFactory.Function3_2NodeGen.create(new Pbinom()); case "pbeta": @@ -329,7 +331,7 @@ public class CallAndExternalFunctions { case "dt": return StatsFunctionsFactory.Function2_1NodeGen.create(new Dt()); case "rlnorm": - return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new LogNormal.RLNorm()); + return RandFunction2Node.createDouble(new LogNormal.RLNorm()); case "dlnorm": return StatsFunctionsFactory.Function3_1NodeGen.create(new DLNorm()); case "qlnorm":