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 24e3dfb71a5fcc398c73a54ba570045501f9ae2b..35a19b7a93b62001827c828b49d9b444d85f9d3c 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 @@ -43,7 +43,7 @@ public final class DPQ { // R >= 3.1.0: # define R_nonint(x) (fabs((x) - R_forceint(x)) > 1e-7) // Note: if true should be followed by "return d0(logP)", consider using nointCheck instead public static boolean nonint(double x) { - return Math.abs(x - Math.round(x)) > 1e-7 * Math.max(1., Math.abs(x)); + return Math.abs(x - RMath.forceint(x)) > 1e-7 * Math.max(1., Math.abs(x)); } // R_D__0 @@ -156,7 +156,7 @@ 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)); + throw new EarlyReturn(x > 0 ? rdt1(lowerTail, logP) : rdt0(lowerTail, logP)); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPois.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPois.java index b01d2a4d75603a4b862849e498ef24a41ce0e167..c60b2f0bd5a45c0635872a019a956b6b54763e2e 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPois.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPois.java @@ -13,7 +13,7 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.library.stats.GammaFunctions.dpoisRaw; -import static com.oracle.truffle.r.library.stats.MathConstants.forceint; +import static com.oracle.truffle.r.library.stats.RMath.forceint; import com.oracle.truffle.r.library.stats.DPQ.EarlyReturn; import com.oracle.truffle.r.library.stats.StatsFunctions.Function2_1; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Dbinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Dbinom.java index 509f543c81aeb163e1eb86ccf6725ea40a88f95d..0486d311a7cce855fd617c28224dae4a39454e27 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Dbinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Dbinom.java @@ -88,6 +88,6 @@ public final class Dbinom implements StatsFunctions.Function3_1 { return DPQ.rd0(giveLog); } - return dbinomRaw(MathConstants.forceint(x), MathConstants.forceint(n), p, 1 - p, giveLog); + return dbinomRaw(RMath.forceint(x), RMath.forceint(n), p, 1 - p, giveLog); } } 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 05443e198bffdfd8b79857b67b4ffbd56d6c5949..29390fe21162fdb557584439c284c88402a1f74c 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 @@ -27,7 +27,7 @@ */ package com.oracle.truffle.r.library.stats; -import static com.oracle.truffle.r.library.stats.MathConstants.forceint; +import static com.oracle.truffle.r.library.stats.RMath.forceint; import com.oracle.truffle.r.library.stats.DPQ.EarlyReturn; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_Double; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathConstants.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathConstants.java index 0885fbeecf503bb056f1c289b3c2096f5ef3e5a3..61bc036c42e836445108ea3208bfecf9089332f2 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathConstants.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathConstants.java @@ -97,11 +97,4 @@ public final class MathConstants { public static double logspaceAdd(double logx, double logy) { return Math.max(logx, logy) + Math.log1p(Math.exp(-Math.abs(logx - logy))); } - - // R_forceint - public static double forceint(double x) { - // Note: in GnuR this is alias for nearbyint, which may not behave exactly like Math.round, - // especially Math.round(-0.5) == 0.0, instead of -0.0, does it matter a lot? - return Double.isFinite(x) ? Math.round(x) : x; - } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java index 70fcce282db80d30395effba2881a35c155aafcb..e61ab3cb1f1be4c0c18a91c878191db9aebc6382 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java @@ -34,9 +34,9 @@ public final class Pbinom implements StatsFunctions.Function3_2 { if (DPQ.nonint(size)) { nanProfile.enter(); DPQ.nointCheckWarning(size, "n"); - return DPQ.rd0(logP); + return RMath.mlError(); } - size = Math.round(size); + size = RMath.forceint(size); /* PR#8560: n=0 is a valid value */ if (size < 0 || prob < 0 || prob > 1) { nanProfile.enter(); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/QHyper.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/QHyper.java index 9a54383f82decd95101bb995de5f6fe776e444f4..e0641de73b8281b181aae6490a781256c1a96b47 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/QHyper.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/QHyper.java @@ -12,9 +12,9 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.library.stats.MathConstants.DBL_EPSILON; -import static com.oracle.truffle.r.library.stats.MathConstants.forceint; import static com.oracle.truffle.r.library.stats.RMath.fmax2; import static com.oracle.truffle.r.library.stats.RMath.fmin2; +import static com.oracle.truffle.r.library.stats.RMath.forceint; import static com.oracle.truffle.r.library.stats.RMath.lfastchoose; import com.oracle.truffle.r.library.stats.DPQ.EarlyReturn; 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 4cd77bcd0f57d21cd29bf67ae35f76dffd84e88a..197316d6df83b9e9bd01f6287742e33a742ad5cd 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 @@ -13,7 +13,7 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.library.stats.MathConstants.M_LN_SQRT_2PI; -import static com.oracle.truffle.r.library.stats.MathConstants.forceint; +import static com.oracle.truffle.r.library.stats.RMath.forceint; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction3_Double; 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 deleted file mode 100644 index f21be8e24cffbacfc8038804da8c2027be0cbf4a..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; -import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; - -public final class RLogis extends RandFunction2_Double { - @Override - public double execute(double location, double scale, RandomNumberProvider rand) { - if (Double.isNaN(location) || !Double.isFinite(scale)) { - return RMath.mlError(); - } - - if (scale == 0. || !Double.isFinite(location)) { - return location; - } else { - double u = rand.unifRand(); - return location + scale * Math.log(u / (1. - u)); - } - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMath.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMath.java index 02c61643311c94b45c6edeba1b1555115af402b4..49fc18d2d6df471eb0afffc46633af0776b25037 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMath.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMath.java @@ -37,6 +37,18 @@ public class RMath { return -Math.log(n + 1.) - lbeta(n - k + 1., k + 1.); } + /** + * Implementation of {@code R_forceint}, which is not equal to {@code Math.round}, because it + * returns {@code double} and so it can handle values that do not fit into long. + */ + public static double forceint(double x) { + // Note: in GnuR this is alias for nearbyint + if (Double.isNaN(x)) { + return 0; + } + return Math.floor(x + 0.5); + } + public static double fsign(double x, double y) { if (Double.isNaN(x) || Double.isNaN(y)) { return x + y; 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 edd2864e79a007ee03e027004f64e8298c44f509..37964392e6762bbac3cebd294e474e15b73c57cc 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 @@ -30,7 +30,7 @@ public final class Rbinom extends RandFunction2_Double { if (!Double.isFinite(nin)) { return RRuntime.INT_NA; } - double r = MathConstants.forceint(nin); + double r = RMath.forceint(nin); if (r != nin) { return RRuntime.INT_NA; } 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 9a976a351a50fa1ce7b5e8c1a92374859afa329a..f13e125ea9afa203be520a6b20d3622e74612d13 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 @@ -11,7 +11,7 @@ package com.oracle.truffle.r.library.stats; -import static com.oracle.truffle.r.library.stats.MathConstants.forceint; +import static com.oracle.truffle.r.library.stats.RMath.forceint; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction1_Double; import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandomNumberProvider; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java index 65056493bd7f7358f33beff9b9ef16afa8141c67..b9f92d9cb1fc14b314a0f88d0a71f6468d94292b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java @@ -40,7 +40,7 @@ public class TOMS708 { // R_Log1_Exp public static double log1Exp(double x) { - return ((x) > -M_LN2 ? log(-rexpm1(x)) : log1p(-exp(x))); + return ((x) > -M_LN2 ? log(-rexpm1(x)) : RMath.log1p(-exp(x))); } private static double sin(double v) { @@ -59,10 +59,6 @@ public class TOMS708 { return Math.sqrt(v); } - private static double log1p(double v) { - return Math.log1p(v); - } - private static double exp(double v) { return Math.exp(v); } @@ -357,7 +353,7 @@ public class TOMS708 { w1 = Double.NEGATIVE_INFINITY; // = 0 on log-scale } bgrat.w = w1; - bgrat.bgrat(b0, a0, y0, x0, 15 * eps, false); + bgrat.bgrat(b0, a0, y0, x0, 15 * eps, true); w1 = bgrat.w; if (bgrat.ierr != 0) { ierr = 8; @@ -594,7 +590,7 @@ public class TOMS708 { // exp(a*lnx) underflows for large (a * lnx); e.g. large a ==> using log_r := log(r): // r = r1 * exp(a * lnx) * exp(bm1 * 0.5 * lnx); // log(r)=log(b) + log1p(gam1(b)) + b * log(z) + (a * lnx) + (bm1 * 0.5 * lnx), - double logR = Math.log(b) + log1p(gam1(b)) + b * Math.log(z) + nu * lnx; + double logR = Math.log(b) + RMath.log1p(gam1(b)) + b * Math.log(z) + nu * lnx; // FIXME work with log_u = log(u) also when log_p=FALSE (??) // u is 'factored out' from the expansion {and multiplied back, at the end}: double logU = logR - (algdiv(b, a) + b * Math.log(nu)); // algdiv(b,a) = @@ -613,7 +609,7 @@ public class TOMS708 { double l = // := *w/u .. but with care: such that it also works when u underflows to 0: logW ? ((w == Double.NEGATIVE_INFINITY) ? 0. : Math.exp(w - logU)) : ((w == 0.) ? 0. : Math.exp(Math.log(w) - logU)); - debugPrintf(" bgrat(a=%f, b=%f, x=%f, *)\n -> u=%f, l='w/u'=%f, ", a, b, x, u, l); + debugPrintf(" bgrat(a=%f, b=%f, x=%f, *)\n -> u=%f, l='w/u'=%f, \n", a, b, x, u, l); double qR = gratR(b, z, logR, eps); // = q/r of former grat1(b,z, r, &p, &q) double v = 0.25 / (nu * nu); @@ -713,7 +709,7 @@ public class TOMS708 { } while (fabs(c) > tol); if (logP) { - ans += log1p(a * s); + ans += RMath.log1p(a * s); } else { ans *= a * s + 1.0; } @@ -831,7 +827,7 @@ public class TOMS708 { if (logP) { /* FIXME? potential for improving log(t) */ - ans = z + log(a0 / a) + log1p(gam1(b0)) - log(t); + ans = z + log(a0 / a) + RMath.log1p(gam1(b0)) - log(t); } else { ans = exp(z) * (a0 / a) * (gam1(b0) + 1.0) / t; } @@ -871,14 +867,14 @@ public class TOMS708 { } while (n < 1e7 && fabs(w) > tol); if (fabs(w) > tol) { // the series did not converge (in time) // warn only when the result seems to matter: - if ((logP && !(a * sum > -1. && fabs(log1p(a * sum)) < eps * fabs(ans))) || (!logP && fabs(a * sum + 1) != 1.)) { + if ((logP && !(a * sum > -1. && fabs(RMath.log1p(a * sum)) < eps * fabs(ans))) || (!logP && fabs(a * sum + 1) != 1.)) { emitWarning(" bpser(a=%f, b=%f, x=%f,...) did not converge (n=1e7, |w|/tol=%f > 1; A=%f)", a, b, x, fabs(w) / tol, ans); } } debugPrintf(" -> n=%d iterations, |w|=%f %s %f=tol:=eps/a ==> a*sum=%f\n", (int) n, fabs(w), (fabs(w) > tol) ? ">!!>" : "<=", tol, a * sum); if (logP) { if (a * sum > -1.0) { - ans += log1p(a * sum); + ans += RMath.log1p(a * sum); } else { ans = ML_NEGINF; } @@ -1115,7 +1111,7 @@ public class TOMS708 { double c = (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; /* FIXME? log(a0*c)= log(a0)+ log(c) and that is improvable */ - return (logP ? eZ + log(a0 * c) - log1p(a0 / b0) : eZ * (a0 * c) / (a0 / b0 + 1.0)); + return (logP ? eZ + log(a0 * c) - RMath.log1p(a0 / b0) : eZ * (a0 * c) / (a0 / b0 + 1.0)); } /* else : ALGORITHM FOR 1 < b0 < 8 */ @@ -1141,7 +1137,7 @@ public class TOMS708 { t = gam1(apb) + 1.0; } - return (logP ? log(a0) + z + log1p(gam1(b0)) - log(t) : a0 * exp(z) * (gam1(b0) + 1.0) / t); + return (logP ? log(a0) + z + RMath.log1p(gam1(b0)) - log(t) : a0 * exp(z) * (gam1(b0) + 1.0) / t); } else { /* ----------------------------------------------------------------------- */ @@ -1248,9 +1244,9 @@ public class TOMS708 { z = gam1(apb) + 1.0; } // L50: - double c = giveLog ? log1p(gam1(a)) + log1p(gam1(b)) - log(z) : (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; + double c = giveLog ? RMath.log1p(gam1(a)) + RMath.log1p(gam1(b)) - log(z) : (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; debugPrintf(" brcmp1(mu,a,b,*): a0 < 1, b0 <= 1; c=%.15f\n", c); - return giveLog ? ans + log(a0) + c - log1p(a0 / b0) : ans * (a0 * c) / (a0 / b0 + 1.0); + return giveLog ? ans + log(a0) + c - RMath.log1p(a0 / b0) : ans * (a0 * c) / (a0 / b0 + 1.0); } // else: algorithm for a0 < 1 < b0 < 8 // L60: @@ -1278,7 +1274,7 @@ public class TOMS708 { } debugPrintf(" brcmp1(mu,a,b,*): a0 < 1 < b0 < 8; t=%.15f\n", t); // L72: - return giveLog ? log(a0) + esum(mu, z, true) + log1p(gam1(b0)) - log(t) : a0 * esum(mu, z, false) * (gam1(b0) + 1.0) / t; + return giveLog ? log(a0) + esum(mu, z, true) + RMath.log1p(gam1(b0)) - log(t) : a0 * esum(mu, z, false) * (gam1(b0) + 1.0) / t; } else { @@ -1302,7 +1298,7 @@ public class TOMS708 { y0 = 1.0 / (h + 1.0); lambda = a - (a + b) * x; } - double lx0 = -log1p(b / a); // in both cases + double lx0 = -RMath.log1p(b / a); // in both cases debugPrintf(" brcmp1(mu,a,b,*): a,b >= 8; x0=%.15f, lx0=log(x0)=%.15f\n", x0, lx0); // L110: