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 new file mode 100644 index 0000000000000000000000000000000000000000..d7e72dd1f0745a5be4e65d8488bc54fdaee65656 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java @@ -0,0 +1,157 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2003-2015, The R Foundation + * Copyright (c) 2016, 2016, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.stats; + +import static com.oracle.truffle.r.library.stats.MathConstants.M_LN2; +import static com.oracle.truffle.r.library.stats.StatsUtil.DBL_MAX_EXP; +import static com.oracle.truffle.r.library.stats.StatsUtil.fmax2; +import static com.oracle.truffle.r.library.stats.StatsUtil.fmin2; + +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; + +public final class RBeta implements RandFunction2_Double { + + private static final double expmax = (DBL_MAX_EXP * M_LN2); /* = log(DBL_MAX) */ + + @Override + public double evaluate(int index, double aa, double bb, double random, RandomNumberNode randomNode) { + if (Double.isNaN(aa) || Double.isNaN(bb) || aa < 0. || bb < 0.) { + StatsUtil.mlError(); + } + if (!Double.isFinite(aa) && !Double.isFinite(bb)) { // a = b = Inf : all mass at 1/2 + return 0.5; + } + if (aa == 0. && bb == 0.) { // point mass 1/2 at each of {0,1} : + return (randomNode.executeSingleDouble() < 0.5) ? 0. : 1.; + } + // now, at least one of a, b is finite and positive + if (!Double.isFinite(aa) || bb == 0.) { + return 1.0; + } + if (!Double.isFinite(bb) || aa == 0.) { + return 0.0; + } + + double a; + double b; + double r; + double s; + double t; + double u1; + double u2; + double v = 0; + double w = 0; + double y; + double z; + double olda = -1.0; + double oldb = -1.0; + + double beta = 0; + double gamma = 1; + double delta; + double k1 = 0; + double k2 = 0; + + /* Test if we need new "initializing" */ + boolean qsame = (olda == aa) && (oldb == bb); + if (!qsame) { + olda = aa; + oldb = bb; + } + + a = fmin2(aa, bb); + b = fmax2(aa, bb); /* a <= b */ + double alpha = a + b; + + if (a <= 1.0) { /* --- Algorithm BC --- */ + /* changed notation, now also a <= b (was reversed) */ + if (!qsame) { /* initialize */ + beta = 1.0 / a; + delta = 1.0 + b - a; + k1 = delta * (0.0138889 + 0.0416667 * a) / (b * beta - 0.777778); + k2 = 0.25 + (0.5 + 0.25 / delta) * a; + } + /* FIXME: "do { } while()", but not trivially because of "continue"s: */ + for (;;) { + u1 = randomNode.executeSingleDouble(); + u2 = randomNode.executeSingleDouble(); + if (u1 < 0.5) { + y = u1 * u2; + z = u1 * y; + if (0.25 * u2 + z - y >= k1) { + continue; + } + } else { + z = u1 * u1 * u2; + if (z <= 0.25) { + v = beta * Math.log(u1 / (1.0 - u1)); + w = wFromU1Bet(b, v, w); + break; + } + if (z >= k2) { + continue; + } + } + + v = beta * Math.log(u1 / (1.0 - u1)); + w = wFromU1Bet(b, v, w); + + if (alpha * (Math.log(alpha / (a + w)) + v) - 1.3862944 >= Math.log(z)) { + break; + } + } + return (aa == a) ? a / (a + w) : w / (a + w); + + } else { /* Algorithm BB */ + + if (!qsame) { /* initialize */ + beta = Math.sqrt((alpha - 2.0) / (2.0 * a * b - alpha)); + gamma = a + 1.0 / beta; + } + do { + u1 = randomNode.executeSingleDouble(); + u2 = randomNode.executeSingleDouble(); + + v = beta * Math.log(u1 / (1.0 - u1)); + w = wFromU1Bet(a, v, w); + + z = u1 * u1 * u2; + r = gamma * v - 1.3862944; + s = a + r - w; + if (s + 2.609438 >= 5.0 * z) { + break; + } + t = Math.log(z); + if (s > t) { + break; + } + } while (r + alpha * Math.log(alpha / (b + w)) < t); + + return (aa != a) ? b / (b + w) : w / (b + w); + } + } + + private static double wFromU1Bet(double aa, double v, double w) { + if (v <= expmax) { + w = aa * Math.exp(v); + if (!Double.isFinite(w)) { + w = Double.MAX_VALUE; + } + } else { + w = Double.MAX_VALUE; + } + return w; + } + +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RCauchy.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RCauchy.java new file mode 100644 index 0000000000000000000000000000000000000000..4ec84f33dd4c9433818f7ebe0919bea71468ffe8 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RCauchy.java @@ -0,0 +1,31 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (C) 1998 Ross Ihaka + * Copyright (c) 1998--2008, The R Core Team + * Copyright (c) 2016, 2016, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.stats; + +import static com.oracle.truffle.r.library.stats.MathConstants.M_PI; + +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; + +public final class RCauchy implements RandFunction2_Double { + @Override + public double evaluate(int index, double location, double scale, double random, RandomNumberNode randomNode) { + if (Double.isNaN(location) || !Double.isFinite(scale) || scale < 0) { + return StatsUtil.mlError(); + } + if (scale == 0. || !Double.isFinite(location)) { + return location; + } else { + return location + scale * Math.tan(M_PI * randomNode.executeSingleDouble()); + } + } +} 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 a176c75521e98ca8e7e4333acef9c87500348287..b0d34cd6095b383d1ea66d9b4f1c103f64065a92 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 @@ -37,11 +37,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.rng.RRNG; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; public final class RandGenerationFunctions { - public static final double ERR_NA = RRuntime.DOUBLE_NA; private static final RDouble DUMMY_VECTOR = RDouble.valueOf(1); private RandGenerationFunctions() { @@ -50,46 +49,57 @@ public final class RandGenerationFunctions { // inspired by the DEFRAND{X}_REAL and DEFRAND{X}_INT macros in GnuR - public interface RandFunction3_Int { - int evaluate(double a, double b, double c); + public interface RandFunction { + /** + * Allows to execute any initialization logic before the main loop that generates the + * resulting vector. This is place where the function should generate necessary random + * values if possible. + */ + default void init(int resultLength, RandomNumberNode randNode) { + RRNG.getRNGState(); + } + + default void finish() { + RRNG.putRNGState(); + } + } + + public interface RandFunction3_Int extends RandFunction { + int evaluate(int index, double a, double b, double c, RandomNumberNode randomNode); } public interface RandFunction2_Int extends RandFunction3_Int { @Override - default int evaluate(double a, double b, double c) { - return evaluate(a, b); + default int evaluate(int index, double a, double b, double c, RandomNumberNode randomNode) { + return evaluate(index, a, b, randomNode); } - int evaluate(double a, double b); + int evaluate(int index, double a, double b, RandomNumberNode randomNode); } - public interface RandFunction2_Double { + public interface RandFunction2_Double extends RandFunction { /** - * If returns {@code false}, {@link #evaluate(double, double)} will not be invoked. + * Opt-in possibility for random functions returning double: the infrastructure will + * preallocate array of random values and reuse it for storing the result. The random values + * will be passed to {@link #evaluate(int, double, double, double, RandomNumberNode)} as the + * 'random' argument. If this method returns {@code true} (default), the random numbers + * generation can be done in {@link #init(int, RandomNumberNode)} and {@link #finish()} or + * in {@link #evaluate(int, double, double, double, RandomNumberNode)}. */ - boolean isValid(double a, double b); + default boolean hasCustomRandomGeneration() { + return true; + } /** - * Is guaranteed to be preceded by invocation of {@link #isValid(double, double)} with the - * same arguments. + * Should generate the value that will be stored to the result vector under given index. + * Error is indicated by returning {@link StatsUtil#mlError()}. */ - double evaluate(double a, double b); - } - - public abstract static class RandFunction2_DoubleAdapter implements RandFunction2_Double { - @Override - public boolean isValid(double a, double b) { - return true; - } + double evaluate(int index, double a, double b, double random, RandomNumberNode randomNode); } static final class RandGenerationProfiles { final BranchProfile nanResult = BranchProfile.create(); - final BranchProfile errResult = BranchProfile.create(); final BranchProfile nan = BranchProfile.create(); - final NACheck aCheck = NACheck.create(); - final NACheck bCheck = NACheck.create(); - final NACheck cCheck = NACheck.create(); final VectorLengthProfile resultVectorLengthProfile = VectorLengthProfile.create(); final LoopConditionProfile loopConditionProfile = LoopConditionProfile.createCountingProfile(); @@ -99,7 +109,7 @@ public final class RandGenerationFunctions { } private static RAbstractIntVector evaluate3Int(Node node, RandFunction3_Int function, int lengthIn, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, - RandGenerationProfiles profiles) { + RandGenerationProfiles profiles, RandomNumberNode randNode) { int length = profiles.resultVectorLengthProfile.profile(lengthIn); int aLength = a.getLength(); int bLength = b.getLength(); @@ -113,41 +123,30 @@ public final class RandGenerationFunctions { } RNode.reportWork(node, length); - boolean complete = true; boolean nans = false; - profiles.aCheck.enable(a); - profiles.bCheck.enable(b); - profiles.cCheck.enable(c); int[] result = new int[length]; - RRNG.getRNGState(); + function.init(length, randNode); 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); - int value; - if (Double.isNaN(aValue) || Double.isNaN(bValue) || Double.isNaN(cValue)) { + int value = function.evaluate(i, aValue, bValue, cValue, randNode); + if (Double.isNaN(value)) { profiles.nan.enter(); - value = RRuntime.INT_NA; - if (profiles.aCheck.check(aValue) || profiles.bCheck.check(bValue) || profiles.cCheck.check(cValue)) { - complete = false; - } - } else { - value = function.evaluate(aValue, bValue, cValue); - if (Double.isNaN(value)) { - profiles.nan.enter(); - nans = true; - } + nans = true; } result[i] = value; } - RRNG.putRNGState(); + function.finish(); if (nans) { RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); } - return RDataFactory.createIntVector(result, complete); + return RDataFactory.createIntVector(result, !nans); } - private static RAbstractDoubleVector evaluate2Double(Node node, RandFunction2_Double function, int length, RAbstractDoubleVector a, RAbstractDoubleVector b, RandGenerationProfiles profiles) { + private static RAbstractDoubleVector evaluate2Double(Node node, RandFunction2_Double function, int lengthIn, RAbstractDoubleVector a, RAbstractDoubleVector b, RandGenerationProfiles profiles, + RandomNumberNode randNode) { + int length = profiles.resultVectorLengthProfile.profile(lengthIn); int aLength = a.getLength(); int bLength = b.getLength(); if (aLength == 0 || bLength == 0) { @@ -157,41 +156,33 @@ public final class RandGenerationFunctions { } RNode.reportWork(node, length); - boolean complete = true; boolean nans = false; - profiles.aCheck.enable(a); - profiles.bCheck.enable(b); - double[] result = new double[length]; - RRNG.getRNGState(); - for (int i = 0; i < length; i++) { + double[] result; + if (function.hasCustomRandomGeneration()) { + function.init(length, randNode); + result = new double[length]; + } else { + RRNG.getRNGState(); + result = randNode.executeDouble(length); + RRNG.putRNGState(); + } + for (int i = 0; profiles.loopConditionProfile.inject(i < length); i++) { double aValue = a.getDataAt(i % aLength); double bValue = b.getDataAt(i % bLength); - double value; - if (Double.isNaN(aValue) || Double.isNaN(bValue)) { + double value = function.evaluate(i, aValue, bValue, result[i], randNode); + if (Double.isNaN(value)) { profiles.nan.enter(); - value = RRuntime.INT_NA; - if (profiles.aCheck.check(aValue) || profiles.bCheck.check(bValue)) { - complete = false; - } - } else { - if (!function.isValid(aValue, bValue)) { - profiles.errResult.enter(); - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); - return createVectorOf(length, Double.NaN); - } - value = function.evaluate(aValue, bValue); - if (Double.isNaN(value)) { - profiles.nan.enter(); - nans = true; - } + nans = true; } result[i] = value; } - RRNG.putRNGState(); + if (function.hasCustomRandomGeneration()) { + function.finish(); + } if (nans) { - RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); + RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); } - return RDataFactory.createDoubleVector(result, complete); + return RDataFactory.createDoubleVector(result, !nans); } private static RAbstractDoubleVector createVectorOf(int length, double element) { @@ -248,8 +239,9 @@ public final class RandGenerationFunctions { @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); + @Cached("create()") RandGenerationProfiles profiles, + @Cached("create()") RandomNumberNode randNode) { + return evaluate3Int(this, function, convertToLength.execute(length), a, b, c, profiles, randNode); } } @@ -270,8 +262,9 @@ public final class RandGenerationFunctions { @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); + @Cached("create()") RandGenerationProfiles profiles, + @Cached("create()") RandomNumberNode randNode) { + return evaluate3Int(this, function, convertToLength.execute(length), a, b, DUMMY_VECTOR, profiles, randNode); } } @@ -292,8 +285,9 @@ public final class RandGenerationFunctions { @Specialization protected RAbstractDoubleVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, - @Cached("create()") RandGenerationProfiles profiles) { - return evaluate2Double(this, function, convertToLength.execute(length), a, b, profiles); + @Cached("create()") RandGenerationProfiles profiles, + @Cached("create()") RandomNumberNode randNode) { + return evaluate2Double(this, function, convertToLength.execute(length), a, b, profiles, randNode); } } } 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 e814c90a222325d9ba8f6e91524cbbdd602b2f08..051c0822f9fb40f7f37f85bd232ecca4510e055d 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 @@ -12,10 +12,9 @@ */ package com.oracle.truffle.r.library.stats; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Int; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.rng.RRNG; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; // transcribed from rbinom.c @@ -23,13 +22,12 @@ public final class Rbinom implements RandFunction2_Int { private final Qbinom qbinom = new Qbinom(); - @TruffleBoundary - private static double unifRand() { - return RRNG.unifRand(); + private static double unifRand(RandomNumberNode randNode) { + return randNode.executeDouble(1)[0]; } @Override - public int evaluate(double nin, double pp) { + public int evaluate(int index, double nin, double pp, RandomNumberNode randomNode) { double psave = -1.0; int nsave = -1; @@ -56,7 +54,7 @@ public final class Rbinom implements RandFunction2_Int { /* * evade integer overflow, and r == INT_MAX gave only even values */ - return (int) qbinom.evaluate(unifRand(), r, pp, /* lower_tail */false, /* log_p */false); + return (int) qbinom.evaluate(unifRand(randomNode), r, pp, /* lower_tail */false, /* log_p */false); } /* else */ int n = (int) r; @@ -137,8 +135,8 @@ public final class Rbinom implements RandFunction2_Int { /*-------------------------- np = n*p >= 30 : ------------------- */ while (true) { - u = unifRand() * p4; - v = unifRand(); + u = unifRand(randomNode) * p4; + v = unifRand(randomNode); /* triangular region */ if (u <= p1) { ix = (int) (xm - p1 * v + u); @@ -225,7 +223,7 @@ public final class Rbinom implements RandFunction2_Int { while (true) { ix = 0; f = qn; - u = unifRand(); + u = unifRand(randomNode); while (true) { if (u < f) { // goto finis; 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 641b1163688c4117d5b47a94d771ed72cdea9bea..8a55565f261df940882ccef50c475c1111ac21b1 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,17 +11,30 @@ */ package com.oracle.truffle.r.library.stats; -import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_DoubleAdapter; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.runtime.rng.RRNG; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; -public final class Rnorm extends RandFunction2_DoubleAdapter { +public final class Rnorm implements RandFunction2_Double { private static final double BIG = 134217728; + private double[] randomVals; @Override - public double evaluate(double mu, double sigma) { + public void init(int length, RandomNumberNode randNode) { + RRNG.getRNGState(); + randomVals = randNode.executeDouble(length * 2); + } + + @Override + public void finish() { + RRNG.putRNGState(); + } + + @Override + public double evaluate(int index, double mu, double sigma, double random, RandomNumberNode randomNode) { // TODO: GnuR invokes norm_rand to get "rand" - double u1 = (int) (BIG * RRNG.unifRand()) + RRNG.unifRand(); + double u1 = (int) (BIG * randomVals[index * 2]) + randomVals[index * 2 + 1]; double rand = Random2.qnorm5(u1 / BIG, 0.0, 1.0, true, false); return rand * sigma + mu; } 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 443074c1da94cb62a6c9b028f9b258b32a6e3bbc..c5fb0cdcd9a67cbf042ef4037957042254b5e3ca 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 @@ -24,16 +24,20 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.rng.RRNG; +import com.oracle.truffle.r.runtime.rng.RandomNumberNode; public final class Runif implements RandFunction2_Double { + @Override - public boolean isValid(double min, double max) { - return RRuntime.isFinite(min) && RRuntime.isFinite(max) && max >= min; + public boolean hasCustomRandomGeneration() { + return false; } @Override - public double evaluate(double min, double max) { - return min + RRNG.unifRand() * (max - min); + public double evaluate(int index, double min, double max, double random, RandomNumberNode randomNode) { + if (!RRuntime.isFinite(min) || !RRuntime.isFinite(max) || max < min) { + return StatsUtil.mlError(); + } + return min + random * (max - min); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsUtil.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsUtil.java index 5ddb311b43a74aabe28ca2a8547fd2a47ffc3fea..76fe2473335bca7fd404efc89a49945704360171 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsUtil.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsUtil.java @@ -21,6 +21,13 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; */ public class StatsUtil { + /** + * corresponds to macro {@code ML_ERR_return_NAN} in GnuR. + */ + public static double mlError() { + return Double.NaN; + } + public static final double DBLEPSILON = 2.2204460492503131e-16; @TruffleBoundary @@ -112,6 +119,10 @@ public class StatsUtil { return giveLog ? -0.5 * Math.log(f) + x : Math.exp(x) / Math.sqrt(f); } + // + // GNUR from fmin2.c and fmax2 + // + public static double fmax2(double x, double y) { if (Double.isNaN(x) || Double.isNaN(y)) { return x + y; @@ -119,6 +130,13 @@ public class StatsUtil { return (x < y) ? y : x; } + public static double fmin2(double x, double y) { + if (Double.isNaN(x) || Double.isNaN(y)) { + return x + y; + } + return (x < y) ? x : y; + } + // // GNUR from expm1.c // @@ -150,7 +168,7 @@ public class StatsUtil { // GNUR from log1p.c // - @CompilationFinal private static final double[] alnrcs = {+.10378693562743769800686267719098e+1, -.13364301504908918098766041553133e+0, +.19408249135520563357926199374750e-1, + @CompilationFinal(dimensions = 1) private static final double[] alnrcs = {+.10378693562743769800686267719098e+1, -.13364301504908918098766041553133e+0, +.19408249135520563357926199374750e-1, -.30107551127535777690376537776592e-2, +.48694614797154850090456366509137e-3, -.81054881893175356066809943008622e-4, +.13778847799559524782938251496059e-4, -.23802210894358970251369992914935e-5, +.41640416213865183476391859901989e-6, -.73595828378075994984266837031998e-7, +.13117611876241674949152294345011e-7, -.23546709317742425136696092330175e-8, +.42522773276034997775638052962567e-9, -.77190894134840796826108107493300e-10, +.14075746481359069909215356472191e-10, diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java index 9b49dab85d20085b3ddb4ed9dc1916e290d87afe..f059e6c94b411a8a6783712b09d188a26c18a220 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java @@ -51,6 +51,8 @@ import com.oracle.truffle.r.library.stats.Pf; import com.oracle.truffle.r.library.stats.Pnorm; import com.oracle.truffle.r.library.stats.Qbinom; import com.oracle.truffle.r.library.stats.Qnorm; +import com.oracle.truffle.r.library.stats.RBeta; +import com.oracle.truffle.r.library.stats.RCauchy; import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory; import com.oracle.truffle.r.library.stats.Rbinom; import com.oracle.truffle.r.library.stats.Rnorm; @@ -362,6 +364,10 @@ public class ForeignFunctions { return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Rnorm()); case "runif": return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Runif()); + case "rbeta": + return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RBeta()); + case "rcauchy": + return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RCauchy()); case "qgamma": return StatsFunctionsFactory.Function3_2NodeGen.create(new QgammaFunc()); case "dbinom": diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberNode.java index b02f2ab8da1cbb540c2ecdb891ebaf6fff6a8f03..f77dda2729d47d7406f9bc68719cc8e71a8e2faa 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,4 +33,12 @@ public final class RandomNumberNode extends RBaseNode { public double[] executeDouble(int count) { return generatorClassProfile.profile(generatorProfile.profile(RRNG.currentGenerator())).genrandDouble(count); } + + public double executeSingleDouble() { + return generatorClassProfile.profile(generatorProfile.profile(RRNG.currentGenerator())).genrandDouble(1)[0]; + } + + public static RandomNumberNode create() { + return new RandomNumberNode(); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 998aa5bca342d0d75f878d80a9bc810dc88baa9c..0b6de6c730ad5ae949b375c523f698a62ac608b7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -111006,6 +111006,16 @@ Error: 'x' is NULL Warning message: In qgamma(10, 1) : NaNs produced +##com.oracle.truffle.r.test.library.stats.TestExternal_rbeta.testRbeta# +#set.seed(42); rbeta(10, 10, 10) + [1] 0.4282247 0.5459560 0.5805863 0.5512005 0.4866080 0.6987626 0.4880555 + [8] 0.7691043 0.4920874 0.6702352 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbeta.testRbeta# +#set.seed(42); rbeta(10, c(0.1, 2:10), c(0.1, 0.5, 0.9, 3:5)) + [1] 0.002930982 0.969019187 0.872817723 0.593769928 0.260911852 0.561458988 + [7] 1.000000000 0.929063923 0.991793861 0.914489454 + ##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# #set.seed(42); rbinom('10', 10, 0.5) [1] 7 7 4 7 6 5 6 3 6 6 @@ -111032,6 +111042,23 @@ In rbinom("aa", 10, 0.5) : NAs introduced by coercion #set.seed(42); rbinom(c(1,2), 11:12, c(0.1, 0.5, 0.9)) [1] 3 9 +##com.oracle.truffle.r.test.library.stats.TestExternal_rcauchy.testRcauchy# +#set.seed(42); rcauchy(10, 10, -1) + [1] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN +Warning message: +In rcauchy(10, 10, -1) : NAs produced + +##com.oracle.truffle.r.test.library.stats.TestExternal_rcauchy.testRcauchy# +#set.seed(42); rcauchy(10, 10, 10) + [1] 7.2577591 7.9970061 22.5740275 4.1049817 -10.9520771 + [6] -156.4897232 -0.8802923 14.5025696 -8.6041975 -3.3131055 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rcauchy.testRcauchy# +#set.seed(42); rcauchy(10, NaN, 10) + [1] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN +Warning message: +In rcauchy(10, NaN, 10) : NAs produced + ##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# #set.seed(42); rnorm('10', 10, 5) [1] 16.854792 7.176509 11.815642 13.164313 12.021342 9.469377 17.557610 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbeta.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbeta.java new file mode 100644 index 0000000000000000000000000000000000000000..f4ab519fd490edcbcb89bb8f9e1f1e6a94b2cf7b --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbeta.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_rbeta extends TestBase { + @Test + public void testRbeta() { + assertEval("set.seed(42); rbeta(10, 10, 10)"); + assertEval("set.seed(42); rbeta(10, c(0.1, 2:10), c(0.1, 0.5, 0.9, 3:5))"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rcauchy.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rcauchy.java new file mode 100644 index 0000000000000000000000000000000000000000..f909eb9268bf84271a71a98d47b9a9c536c8e89e --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rcauchy.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_rcauchy extends TestBase { + @Test + public void testRcauchy() { + assertEval("set.seed(42); rcauchy(10, 10, 10)"); + assertEval("set.seed(42); rcauchy(10, 10, -1)"); + assertEval("set.seed(42); rcauchy(10, NaN, 10)"); + } +} diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index b2774bbe81df2fcdb8776e053ecbdb3aec5e15f4..86dfbf89ffa674a46361a96dbaa700c75bc9174c 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -29,6 +29,8 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Arithmetic.java,gnu_r_gentleman_ihaka.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RBeta.java,gnu_r_gentleman_ihaka.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RCauchy.java,gnu_r_ihaka_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Dbinom.java,gnu_r.copyright