From 1afbe3b2530f0d386611dbd1911e04564b54d69a Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 5 Jan 2017 21:01:43 +0100
Subject: [PATCH] Stats: port signrank distribution functions

---
 .../r/library/stats/SignrankFreeNode.java     |  35 +++
 .../foreign/CallAndExternalFunctions.java     |  12 +
 .../com/oracle/truffle/r/runtime/RError.java  |   2 +-
 .../r/runtime/nmath/distr/Signrank.java       | 189 ++++++++++++++-
 .../truffle/r/runtime/nmath/distr/Wilcox.java |  15 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 222 ++++++++++++++++++
 .../test/library/stats/TestDistributions.java |   8 +-
 7 files changed, 471 insertions(+), 12 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SignrankFreeNode.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SignrankFreeNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SignrankFreeNode.java
new file mode 100644
index 0000000000..9a49e74cee
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SignrankFreeNode.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 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.library.stats;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.nmath.distr.Signrank.SignrankData;
+
+public final class SignrankFreeNode extends RExternalBuiltinNode.Arg0 {
+    @Override
+    public Object execute() {
+        SignrankData.freeData();
+        return RNull.instance;
+    }
+}
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 26cbf2838b..4c14ad345c 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
@@ -50,6 +50,7 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodes;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction1Node;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction2Node;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction3Node;
+import com.oracle.truffle.r.library.stats.SignrankFreeNode;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodes;
@@ -155,6 +156,9 @@ import com.oracle.truffle.r.runtime.nmath.distr.Rbinom;
 import com.oracle.truffle.r.runtime.nmath.distr.Rf;
 import com.oracle.truffle.r.runtime.nmath.distr.Rnorm;
 import com.oracle.truffle.r.runtime.nmath.distr.Rt;
+import com.oracle.truffle.r.runtime.nmath.distr.Signrank.DSignrank;
+import com.oracle.truffle.r.runtime.nmath.distr.Signrank.PSignrank;
+import com.oracle.truffle.r.runtime.nmath.distr.Signrank.QSignrank;
 import com.oracle.truffle.r.runtime.nmath.distr.Signrank.RSignrank;
 import com.oracle.truffle.r.runtime.nmath.distr.Unif.DUnif;
 import com.oracle.truffle.r.runtime.nmath.distr.Unif.PUnif;
@@ -457,6 +461,12 @@ public class CallAndExternalFunctions {
                     return StatsFunctionsNodes.Function3_2Node.create(new PWilcox());
                 case "dwilcox":
                     return StatsFunctionsNodes.Function3_1Node.create(new DWilcox());
+                case "dsignrank":
+                    return StatsFunctionsNodes.Function2_1Node.create(new DSignrank());
+                case "psignrank":
+                    return StatsFunctionsNodes.Function2_2Node.create(new PSignrank());
+                case "qsignrank":
+                    return StatsFunctionsNodes.Function2_2Node.create(new QSignrank());
                 case "rmultinom":
                     return RMultinomNode.create();
                 case "Approx":
@@ -710,6 +720,8 @@ public class CallAndExternalFunctions {
                     return RprofmemNodeGen.create();
                 case "wilcox_free":
                     return new WilcoxFreeNode();
+                case "signrank_free":
+                    return new SignrankFreeNode();
                 case "unzip":
                 case "addhistory":
                 case "loadhistory":
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 290c7a823c..e455c657cb 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
@@ -466,7 +466,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)"),
+        CALLOC_COULD_NOT_ALLOCATE("'Calloc' could not allocate memory (%s of %d 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.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
index a45f69b73f..8d0f14b554 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
@@ -11,14 +11,22 @@
 
 package com.oracle.truffle.r.runtime.nmath.distr;
 
-import static com.oracle.truffle.r.runtime.RError.Message.GENERIC;
+import static com.oracle.truffle.r.runtime.RError.Message.CALLOC_COULD_NOT_ALLOCATE;
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_EPSILON;
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_LN2;
 import static com.oracle.truffle.r.runtime.nmath.RMath.forceint;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.nmath.DPQ;
+import com.oracle.truffle.r.runtime.nmath.DPQ.EarlyReturn;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_1;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_2;
+import com.oracle.truffle.r.runtime.nmath.RMath;
 import com.oracle.truffle.r.runtime.nmath.RMathError;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction1_Double;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
+import com.oracle.truffle.r.runtime.nmath.TOMS708;
 
 public final class Signrank {
     private Signrank() {
@@ -26,7 +34,7 @@ public final class Signrank {
     }
 
     /**
-     * Holds cache for the dynamic algorithm that wilcox uses.
+     * Holds cache for the dynamic algorithm that signrank uses.
      */
     public static final class SignrankData {
         private static final ThreadLocal<double[]> data = new ThreadLocal<>();
@@ -44,7 +52,8 @@ public final class Signrank {
                 try {
                     result = new double[c + 1];
                 } catch (OutOfMemoryError e) {
-                    throw RError.error(RError.SHOW_CALLER, GENERIC, "signrank allocation error");
+                    // GnuR seems to be reporting the same number regardless of 'c'
+                    throw couldNotAllocateError();
                 }
                 data.set(result);
             }
@@ -56,6 +65,180 @@ public final class Signrank {
         }
     }
 
+    private static RError couldNotAllocateError() {
+        return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744073172680704", 8);
+    }
+
+    private static double csignrank(double[] w, int kIn, int n) {
+        int u = n * (n + 1) / 2;
+        int c = (u / 2);
+
+        if (kIn < 0 || kIn > u) {
+            return 0;
+        }
+        int k = kIn <= c ? kIn : u - kIn;
+
+        if (n == 1) {
+            return 1.;
+        }
+        if (w[0] == 1.) {
+            return w[k];
+        }
+
+        w[0] = w[1] = 1.;
+        for (int j = 2; j < n + 1; ++j) {
+            int end = Math.min(j * (j + 1) / 2, c);
+            for (int i = end; i >= j; --i) {
+                w[i] += w[i - j];
+            }
+        }
+        return w[k];
+    }
+
+    public static final class DSignrank implements Function2_1 {
+        @Override
+        public double evaluate(double xIn, double nIn, boolean giveLog) {
+            /* NaNs propagated correctly */
+            if (Double.isNaN(xIn) || Double.isNaN(nIn)) {
+                return xIn + nIn;
+            }
+
+            if (nIn == Double.POSITIVE_INFINITY) {
+                // to have the same output as GnuR:
+                throw couldNotAllocateError();
+            }
+
+            double n = RMath.forceint(nIn);
+            if (n <= 0) {
+                return RMathError.defaultError();
+            }
+
+            double x = RMath.forceint(xIn);
+            if (TOMS708.fabs(xIn - x) > 1e-7) {
+                return DPQ.rd0(giveLog);
+            }
+            if ((x < 0) || (x > (n * (n + 1) / 2))) {
+                return DPQ.rd0(giveLog);
+            }
+
+            int nn = (int) n;
+            double[] data = SignrankData.getData(nn);
+            return DPQ.rdexp(Math.log(csignrank(data, (int) x, nn)) - n * M_LN2, giveLog);
+        }
+    }
+
+    public static final class PSignrank implements Function2_2 {
+        @Override
+        public double evaluate(double xIn, double nIn, boolean lowerTail, boolean logP) {
+            if (Double.isNaN(xIn) || Double.isNaN(nIn)) {
+                return (xIn + nIn);
+            }
+            if (!Double.isFinite(nIn)) {
+                return RMathError.defaultError();
+            }
+
+            double n = RMath.forceint(nIn);
+            if (n <= 0) {
+                return RMathError.defaultError();
+            }
+
+            double x = RMath.forceint(xIn + 1e-7);
+            if (x < 0.0) {
+                return DPQ.rdt0(lowerTail, logP);
+            }
+            if (x >= n * (n + 1) / 2) {
+                return DPQ.rdt1(lowerTail, logP);
+            }
+
+            int nn = (int) n;
+            double[] data = SignrankData.getData(nn);
+            double f = Math.exp(-n * M_LN2);
+            double p = 0;
+            if (x <= (n * (n + 1) / 4)) {
+                int xUpperLimit = getUpperIntBound(x);
+                for (int i = 0; i <= xUpperLimit; i++) {
+                    p += csignrank(data, i, nn) * f;
+                }
+                return DPQ.rdtval(p, lowerTail, logP);
+            } else {
+                x = n * (n + 1) / 2 - x;
+                int xUpperLimit = getUpperIntBound(x);
+                for (int i = 0; i < xUpperLimit; i++) {
+                    p += csignrank(data, i, nn) * f;
+                }
+                // !lowerTail, because p = 1 - p; */
+                return DPQ.rdtval(p, !lowerTail, logP);
+            }
+        }
+
+        /**
+         * Makes sure that the value can be reached by integer counter, this is probably just really
+         * defensive, since the allocation with such number is bound to fail anyway.
+         */
+        private int getUpperIntBound(double x) {
+            return (x + 1) > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) Math.ceil(x);
+        }
+    }
+
+    public static final class QSignrank implements Function2_2 {
+        @Override
+        public double evaluate(double xIn, double nIn, boolean lowerTail, boolean logP) {
+            if (Double.isNaN(xIn) || Double.isNaN(nIn)) {
+                return (xIn + nIn);
+            }
+
+            if (!Double.isFinite(xIn) || !Double.isFinite(nIn)) {
+                return RMathError.defaultError();
+            }
+
+            try {
+                DPQ.rqp01check(xIn, logP);
+            } catch (EarlyReturn earlyReturn) {
+                return earlyReturn.result;
+            }
+
+            double n = RMath.forceint(nIn);
+            if (n <= 0) {
+                return RMathError.defaultError();
+            }
+
+            if (xIn == DPQ.rdt0(lowerTail, logP)) {
+                return 0;
+            }
+            if (xIn == DPQ.rdt1(lowerTail, logP)) {
+                return n * (n + 1) / 2;
+            }
+
+            double x = !logP && lowerTail ? xIn : DPQ.rdtqiv(xIn, lowerTail, logP);
+            int nn = (int) n;
+            double[] data = SignrankData.getData(nn);
+            double f = Math.exp(-n * M_LN2);
+            double p = 0;
+            int q = 0;
+            if (x <= 0.5) {
+                x = x - 10 * DBL_EPSILON;
+                while (true) {
+                    p += csignrank(data, q, nn) * f;
+                    if (p >= x) {
+                        break;
+                    }
+                    q++;
+                }
+            } else {
+                x = 1 - x + 10 * DBL_EPSILON;
+                while (true) {
+                    p += csignrank(data, q, nn) * f;
+                    if (p > x) {
+                        q = (int) (n * (n + 1) / 2 - q);
+                        break;
+                    }
+                    q++;
+                }
+            }
+            return q;
+        }
+    }
+
     public static final class RSignrank extends RandFunction1_Double {
         @Override
         public double execute(double nIn, RandomNumberProvider rand) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
index feee67ad95..9320af8efe 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
@@ -11,7 +11,7 @@
 
 package com.oracle.truffle.r.runtime.nmath.distr;
 
-import static com.oracle.truffle.r.runtime.RError.Message.CALLOC_COULD_NOT_ALLOCATE_INF;
+import static com.oracle.truffle.r.runtime.RError.Message.CALLOC_COULD_NOT_ALLOCATE;
 import static com.oracle.truffle.r.runtime.nmath.Choose.choose;
 import static com.oracle.truffle.r.runtime.nmath.Choose.lchoose;
 import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_EPSILON;
@@ -86,8 +86,7 @@ public final class Wilcox {
                 try {
                     result = new double[m + 1][n + 1][];
                 } catch (OutOfMemoryError e) {
-                    // GnuR seems to be reporting the same number regardless of the actual size
-                    throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE_INF);
+                    throw couldNotAllocateError();
                 }
                 data.set(result);
             }
@@ -99,6 +98,11 @@ public final class Wilcox {
         }
     }
 
+    private static RError couldNotAllocateError() {
+        // GnuR seems to be reporting the same number regardless of the actual size?
+        return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744071562067968", 4);
+    }
+
     private static double cwilcox(double[][][] w, int kIn, int m, int n) {
         int u = m * n;
         if (kIn < 0 || kIn > u) {
@@ -318,7 +322,7 @@ public final class Wilcox {
             if (!Double.isFinite(mIn) || !Double.isFinite(nIn)) {
                 // 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);
+                throw couldNotAllocateError();
             }
 
             double m = RMath.round(mIn);
@@ -343,8 +347,7 @@ public final class Wilcox {
             try {
                 x = new int[k];
             } catch (OutOfMemoryError ex) {
-                // GnuR seems to be reporting the same number regardless of 'k'
-                throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE_INF);
+                throw couldNotAllocateError();
             }
             for (int i = 0; i < k; i++) {
                 x[i] = i;
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 b57be5195c..aec62f93a8 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
@@ -112678,6 +112678,54 @@ In dpois(c(1e-11, 0.1, 1, 10), 1e-07, log = T) : non-integer x = 0.100000
  [1]  -3.274566  -2.078562  -3.360495  -6.283915 -15.580684       -Inf
  [7]       -Inf -10.000000 -10.000000       -Inf        NaN
 
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(0, -3)
+[1] NaN
+Warning message:
+In dsignrank(0, -3) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(0, -Inf)
+[1] NaN
+Warning message:
+In dsignrank(0, -Inf) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(0, 0)
+[1] NaN
+Warning message:
+In dsignrank(0, 0) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(0, Inf)
+Error in dsignrank(0, Inf) :
+  'Calloc' could not allocate memory (18446744073172680704 of 8 bytes)
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(0, NaN)
+[1] NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, log=F)
+[1] 0.000000 0.000000 0.015625 0.031250 0.062500 0.062500 0.015625
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, log=T)
+[1]      -Inf      -Inf -4.158883 -3.465736 -2.772589 -2.772589 -4.158883
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, log=F)
+ [1] 0.0029296875 0.0195312500 0.0302734375 0.0390625000 0.0302734375
+ [6] 0.0029296875 0.0009765625 0.0009765625 0.0000000000 0.0000000000
+[11] 0.0000000000 0.0009765625 0.0009765625 0.0009765625 0.0000000000
+[16]          NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
+#dsignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, log=T)
+ [1] -5.832860 -3.935740 -3.497485 -3.242592 -3.497485 -5.832860 -6.931472
+ [8] -6.931472      -Inf      -Inf      -Inf -6.931472 -6.931472 -6.931472
+[15]      -Inf       NaN
+
 ##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
 #dunif(0, -3, -Inf)
 [1] NaN
@@ -114352,6 +114400,80 @@ In ppois(0, -Inf) : NaNs produced
  [6]          -Inf          -Inf -1.000000e+01 -1.000000e+01  0.000000e+00
 [11]           NaN
 
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(0, -3)
+[1] NaN
+Warning message:
+In psignrank(0, -3) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(0, -Inf)
+[1] NaN
+Warning message:
+In psignrank(0, -Inf) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(0, 0)
+[1] NaN
+Warning message:
+In psignrank(0, 0) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(0, Inf)
+[1] NaN
+Warning message:
+In psignrank(0, Inf) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(0, NaN)
+[1] NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, lower.tail=F, log.p=F)
+[1] 0.984375 0.968750 0.953125 0.921875 0.781250 0.156250 0.015625
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, lower.tail=F, log.p=T)
+[1] -0.01574836 -0.03174870 -0.04800922 -0.08134564 -0.24686008 -1.85629799
+[7] -4.15888308
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, lower.tail=T, log.p=F)
+[1] 0.015625 0.031250 0.046875 0.078125 0.218750 0.843750 0.984375
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(0.3, 0.6, 2, 3, 6, 15, 20), 5.5, lower.tail=T, log.p=T)
+[1] -4.15888308 -3.46573590 -3.06027079 -2.54944517 -1.51982575 -0.16989904
+[7] -0.01574836
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, lower.tail=F, log.p=F)
+ [1] 0.9902343750 0.8837890625 0.7539062500 0.5000000000 0.2158203125
+ [6] 0.0068359375 0.0009765625 0.0000000000 0.0000000000 0.0000000000
+[11] 1.0000000000 0.9990234375 0.9990234375 0.9990234375 0.0000000000
+[16]          NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, lower.tail=F, log.p=T)
+ [1] -0.0098136214 -0.1235368619 -0.2824872556 -0.6931471806 -1.5333091041
+ [6] -4.9855616565 -6.9314718056          -Inf          -Inf          -Inf
+[11]  0.0000000000 -0.0009770396 -0.0009770396 -0.0009770396          -Inf
+[16]           NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, lower.tail=T, log.p=F)
+ [1] 0.0097656250 0.1162109375 0.2460937500 0.5000000000 0.7841796875
+ [6] 0.9931640625 0.9990234375 1.0000000000 1.0000000000 1.0000000000
+[11] 0.0000000000 0.0009765625 0.0009765625 0.0009765625 1.0000000000
+[16]          NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
+#psignrank(c(5, 15, 20, 27, 35, 50, 54, 55, 56, 100, -Inf, -0.42e-30, 0, 0.42e-30, Inf, NaN), 10, lower.tail=T, log.p=T)
+ [1] -4.6288867126 -2.1523483125 -1.4020427181 -0.6931471806 -0.2431170917
+ [6] -0.0068594096 -0.0009770396  0.0000000000  0.0000000000  0.0000000000
+[11]          -Inf -6.9314718056 -6.9314718056 -6.9314718056  0.0000000000
+[16]           NaN
+
 ##com.oracle.truffle.r.test.library.stats.TestDistributions.testDistributionFunctions#Output.MayIgnoreWarningContext#
 #punif(0, -3, -Inf)
 [1] NaN
@@ -116467,6 +116589,106 @@ In qpois(Inf, 10) : NaNs produced
 #qpois(log(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1)), 1e100, lower.tail=T, log.p=T)
 [1]  0e+00 1e+100 1e+100 1e+100 1e+100    Inf    Inf
 
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(-0.42e-38, 10)
+[1] NaN
+Warning message:
+In qsignrank(-4.2e-39, 10) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(-42, 10)
+[1] NaN
+Warning message:
+In qsignrank(-42, 10) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(-Inf, 10)
+[1] NaN
+Warning message:
+In qsignrank(-Inf, 10) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(0, -3)
+[1] NaN
+Warning message:
+In qsignrank(0, -3) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(0, -Inf)
+[1] NaN
+Warning message:
+In qsignrank(0, -Inf) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(0, 0)
+[1] NaN
+Warning message:
+In qsignrank(0, 0) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(0, Inf)
+[1] NaN
+Warning message:
+In qsignrank(0, Inf) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(0, NaN)
+[1] NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(Inf, 10)
+[1] NaN
+Warning message:
+In qsignrank(Inf, 10) : NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(NaN, 10)
+[1] NaN
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1), 10, lower.tail=F, log.p=F)
+[1] 55 55 40 27 22  0  0
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1), 10, lower.tail=T, log.p=F)
+[1]  0  0 15 27 33 55 55
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1), 5.5, lower.tail=F, log.p=F)
+[1] 21 21 17 10  8  0  0
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1), 5.5, lower.tail=T, log.p=F)
+[1]  0  0  4 10 13 21 21
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(log(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1)), 10, lower.tail=F, log.p=T)
+[1] NaN  55  40  27  22   0   0
+Warning message:
+In qsignrank(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)),  :
+  NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(log(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1)), 10, lower.tail=T, log.p=T)
+[1] NaN   0  15  27  33  55  55
+Warning message:
+In qsignrank(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)),  :
+  NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(log(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1)), 5.5, lower.tail=F, log.p=T)
+[1] NaN  21  17  10   8   0   0
+Warning message:
+In qsignrank(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)),  :
+  NaNs produced
+
+##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
+#qsignrank(log(c(0, 42e-80, 0.1, 0.5, 0.7, 1-42e-80, 1)), 5.5, lower.tail=T, log.p=T)
+[1] NaN   0   4  10  13  21  21
+Warning message:
+In qsignrank(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)),  :
+  NaNs produced
+
 ##com.oracle.truffle.r.test.library.stats.TestDistributions.testQuantileFunctions#Output.MayIgnoreWarningContext#
 #qunif(-0.42e-38, -3, 3.3)
 [1] NaN
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestDistributions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestDistributions.java
index 6917112ebe..113814e3b9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestDistributions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestDistributions.java
@@ -144,10 +144,14 @@ public class TestDistributions extends TestBase {
                     test("1, 0.5", withDefaultQ("1", "2", "3.3", "4", "5", "6", "6.1", "10")).
                     test("0.5, 10", withQuantiles("1", "2", "3.3", "4", "5", "6", "6.1", "10")).
                     test("1e100, 1", withQuantiles("0.9", "0.99999999999999999", "1-1e-30", "1")),
-            // Note: wilcox is very memory consuming, so we test only small argument values here
+            // Note: wilcox and signrank are memory consuming, so we test only small argument values here
             distr("wilcox").
                     test("10, 10", withDefaultQ("1", "3", "5", "100", "1000")).
-                    test("4, 7", withQuantiles("1", "3", "5", "100", "1000"))
+                    test("4, 7", withQuantiles("1", "3", "5", "100", "1000")),
+            distr("signrank").
+                    addErrorParamValues("-3", "0").
+                    test("10", withDefaultQ("5", "15", "20", "27", "35", "50", "54", "55", "56", "100")).
+                    test("5.5", withQuantiles("0.3", "0.6", "2", "3", "6", "15", "20"))
     };
     // @formatter:on
 
-- 
GitLab