From 7b3a8b082dcf569e888f629bcf9c1a0865f05fde Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 25 Nov 2016 23:33:03 +0100
Subject: [PATCH] Implement rwilcox

---
 .../stats/RandGenerationFunctions.java        |  2 +-
 .../truffle/r/library/stats/Wilcox.java       | 68 +++++++++++++++++++
 .../base/foreign/ForeignFunctions.java        |  3 +
 .../com/oracle/truffle/r/runtime/RError.java  |  1 +
 .../stats/TestRandGenerationFunctions.java    |  2 +-
 mx.fastr/copyrights/overrides                 |  1 +
 6 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java

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 733f8f8b97..6ad6a060ba 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
@@ -166,7 +166,7 @@ public final class RandGenerationFunctions {
             double aValue = a.getDataAt(i % aLength);
             double bValue = b.getDataAt(i % bLength);
             double value = function.evaluate(aValue, bValue, rand);
-            if (Double.isNaN(value)) {
+            if (Double.isNaN(value) || Double.isNaN(value)) {
                 profiles.nan.enter();
                 nans = true;
             }
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
new file mode 100644
index 0000000000..04aec9c58b
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java
@@ -0,0 +1,68 @@
+/*
+ * 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) 1999--2014, The R Core Team
+ * Copyright (c) 2016, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+package com.oracle.truffle.r.library.stats;
+
+import static com.oracle.truffle.r.runtime.RError.Message.CALLOC_COULD_NOT_ALLOCATE_INF;
+
+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.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+
+public final class Wilcox {
+
+    public static final class RWilcox implements RandFunction2_Double {
+        @Override
+        public double evaluate(double m, double n, RandomNumberProvider rand) {
+            int i;
+            int j;
+            int k;
+            double r;
+
+            /* NaNs propagated correctly */
+            if (Double.isNaN(m) || Double.isNaN(n)) {
+                return (m + n);
+            }
+            if (!Double.isFinite(m) || !Double.isFinite(n)) {
+                // GnuR does not check this and tries to allocate the memory, we do check this, but
+                // fail with the same error message for compatibility reasons.
+                throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE_INF);
+            }
+
+            m = Math.round(m);
+            n = Math.round(n);
+            if ((m < 0) || (n < 0)) {
+                // TODO: for some reason the macro in GNUR here returns NA instead of NaN...
+                // return StatsUtil.mlError();
+                return RRuntime.DOUBLE_NA;
+            }
+
+            if ((m == 0) || (n == 0)) {
+                return (0);
+            }
+
+            r = 0.0;
+            k = (int) (m + n);
+
+            int[] x = new int[k];
+            for (i = 0; i < k; i++) {
+                x[i] = i;
+            }
+            for (i = 0; i < n; i++) {
+                j = (int) Math.floor(k * rand.unifRand());
+                r += x[j];
+                x[j] = x[--k];
+            }
+            return (r - n * (n - 1) / 2);
+        }
+    }
+}
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 8ea4edee78..eb498d9e37 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
@@ -70,6 +70,7 @@ import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeG
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen;
 import com.oracle.truffle.r.library.stats.StatsFunctionsFactory;
 import com.oracle.truffle.r.library.stats.StatsUtil;
+import com.oracle.truffle.r.library.stats.Wilcox.RWilcox;
 import com.oracle.truffle.r.library.tools.C_ParseRdNodeGen;
 import com.oracle.truffle.r.library.tools.DirChmodNodeGen;
 import com.oracle.truffle.r.library.tools.Rmd5NodeGen;
@@ -390,6 +391,8 @@ public class ForeignFunctions {
                     return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RNchisq());
                 case "rnbinom_mu":
                     return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RNbinomMu());
+                case "rwilcox":
+                    return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new RWilcox());
                 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/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 38c7c2c87d..b3187916a6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -457,6 +457,7 @@ public final class RError extends RuntimeException {
         UNUSED_ARGUMENT("unused argument (%s)"),
         UNUSED_ARGUMENTS("unused arguments (%s)"),
         INFINITE_MISSING_VALUES("infinite or missing values in '%s'"),
+        CALLOC_COULD_NOT_ALLOCATE_INF("'Calloc' could not allocate memory (18446744071562067968 of 4 bytes)"),
         NON_SQUARE_MATRIX("non-square matrix in '%s'"),
         LAPACK_ERROR("error code %d from Lapack routine '%s'"),
         VALUE_OUT_OF_RANGE("value out of range in '%s'"),
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index 37f836aed5..02e304d187 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.test.TestBase;
  * tests for its specific corner cases if those are not covered here.
  */
 public class TestRandGenerationFunctions extends TestBase {
-    private static final String[] FUNCTION2_NAMES = {"rnorm", "runif", "rgamma", "rbeta", "rcauchy", "rf", "rlogis", "rweibull", "rchisq"};
+    private static final String[] FUNCTION2_NAMES = {"rnorm", "runif", "rgamma", "rbeta", "rcauchy", "rf", "rlogis", "rweibull", "rchisq", "rwilcox"};
     private static final String[] FUNCTION2_PARAMS = {
                     "10, 10, 10",
                     "20, c(-1, 0, 0.2, 2:5), c(-1, 0, 0.1, 0.9, 3)",
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index fb33bd32fe..13c0f05a46 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -64,6 +64,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RLogis.java,
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rf.java,gnu_r_ihaka_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RChisq.java,gnu_r_ihaka_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RNchisq.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Wilcox.java,gnu_r.core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RWeibull.java,gnu_r_ihaka_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java,gnu_r.copyright
-- 
GitLab