From 7dbe0e843dbb69b0462607d638d0f67a5a7134e7 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 3 Nov 2016 10:43:31 +0100
Subject: [PATCH] Covcor converted to cast pipelines + tests

---
 .../truffle/r/library/stats/Covcor.java       | 43 +++++++++++--------
 .../base/foreign/ForeignFunctions.java        |  6 +--
 .../truffle/r/test/ExpectedTestOutput.test    | 20 +++++++++
 .../library/stats/TestExternal_covcor.java    | 43 +++++++++++++++++++
 4 files changed, 91 insertions(+), 21 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index d8e7acbe21..1aff0091ef 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -11,15 +11,22 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
+import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
+
 import java.util.Arrays;
 
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -31,7 +38,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 /*
  * Logic derived from GNU-R, library/stats/src/cov.c
  */
-public final class Covcor extends RExternalBuiltinNode {
+public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
 
     private final boolean isCor;
 
@@ -40,20 +47,21 @@ public final class Covcor extends RExternalBuiltinNode {
     }
 
     @Override
-    public Object call(RArgsValuesAndNames args) {
-        Object[] argValues = args.getArguments();
-        if (argValues[0] == RNull.instance) {
-            throw RError.error(this, RError.Message.IS_NULL, "x");
-        }
+    protected void createCasts(CastBuilder casts) {
+        casts.arg(0).mustNotBeNull(SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector();
+        casts.arg(1).allowNull().asDoubleVector();
+        casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), this, Message.NYI, "covcor: other method than 4 not implemented.");
+        casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
+    }
 
-        RAbstractDoubleVector x = castDouble(castVector(argValues[0]));
-        RAbstractDoubleVector y = argValues[1] == RNull.instance ? null : castDouble(castVector(argValues[1]));
-        int method = castInt(castVector(argValues[2]));
-        if (method != 4) {
-            throw RError.nyi(this, "method");
-        }
-        boolean iskendall = RRuntime.fromLogical(castLogical(castVector(argValues[3])));
-        return corcov(x.materialize(), y != null ? y.materialize() : null, method, iskendall, this);
+    @Specialization
+    public Object call(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, int method, boolean iskendall) {
+        return corcov(x.materialize(), null, method, iskendall, this);
+    }
+
+    @Specialization
+    public Object call(RAbstractDoubleVector x, RAbstractDoubleVector y, int method, boolean iskendall) {
+        return corcov(x.materialize(), y.materialize(), method, iskendall, this);
     }
 
     private final NACheck check = NACheck.create();
@@ -730,9 +738,8 @@ public final class Covcor extends RExternalBuiltinNode {
         }
     }
 
-    private static void error(String string) {
-        // TODO should be an R error
-        throw new UnsupportedOperationException("error: " + string);
+    private static void error(String message) {
+        RError.error(NO_CALLER, Message.GENERIC, message);
     }
 
     private boolean checkNAs(double... xs) {
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 76f8082bdc..2821716614 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
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.library.methods.SlotFactory.R_setSlotNodeGen;
 import com.oracle.truffle.r.library.methods.SubstituteDirectNodeGen;
 import com.oracle.truffle.r.library.parallel.ParallelFunctionsFactory.MCIsChildNodeGen;
 import com.oracle.truffle.r.library.stats.CompleteCases;
-import com.oracle.truffle.r.library.stats.Covcor;
+import com.oracle.truffle.r.library.stats.CovcorNodeGen;
 import com.oracle.truffle.r.library.stats.Dbinom;
 import com.oracle.truffle.r.library.stats.GammaFunctionsFactory.QgammaNodeGen;
 import com.oracle.truffle.r.library.stats.Pbinom;
@@ -345,9 +345,9 @@ public class ForeignFunctions {
                 case "fft":
                     return FftNodeGen.create();
                 case "cov":
-                    return new Covcor(false);
+                    return CovcorNodeGen.create(false);
                 case "cor":
-                    return new Covcor(true);
+                    return CovcorNodeGen.create(true);
                 case "SplineCoef":
                     return SplineCoefNodeGen.create();
                 case "SplineEval":
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 b4c4c14c8c..a73d1630d7 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
@@ -109924,6 +109924,26 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcor#
+#.Call(stats:::C_cov, 1:5, 1:5, 4, FALSE)
+[1] 2.5
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcor#
+#.Call(stats:::C_cov, 1:5, c(1,5,1,5,10), 4, FALSE)
+[1] 4.5
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcorArgsCasts#
+#.Call(stats:::C_cov, 1:3, 1:5, 4, FALSE)
+Error: incompatible dimensions
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcorArgsCasts#
+#.Call(stats:::C_cov, NULL, 1:5, 4, FALSE)
+Error: 'x' is NULL
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcorArgsCasts#
+#.Call(stats:::C_cov, c('1','2','3','4','5'), 1:5, 4, FALSE)
+[1] 2.5
+
 ##com.oracle.truffle.r.test.library.stats.TestFitting.testLm#Output.IgnoreWhitespace#
 #y <- c(26.55, 37.21, 57.28, 90.82, 20.16, 89.838, 94.46, 20.5, 17.6, 68.7, 38.41, 76.9, 49.7, 71, 99.19, 16); x <- c(26.55, 37.21, 57.28, 90.82, 20.16, 89.838, 94.46, 20.5, 17.6, 68.7, 38.41, 76.9, 49.7, 71, 99.19, 16); res <- lm(y~x); print(res$coefficients);print(res$fitted.values);print(res$xlevels);print(res$residuals);print(res$assign);print(res$effects);print(res$qr$qr);print(res$rank);print(res$model);
   (Intercept)             x
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java
new file mode 100644
index 0000000000..5f548a2355
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java
@@ -0,0 +1,43 @@
+/*
+ * 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_covcor extends TestBase {
+    @Test
+    public void testCovcor() {
+        assertEval(".Call(stats:::C_cov, 1:5, 1:5, 4, FALSE)");
+        assertEval(".Call(stats:::C_cov, 1:5, c(1,5,1,5,10), 4, FALSE)");
+    }
+
+    @Test
+    public void testCovcorArgsCasts() {
+        assertEval(".Call(stats:::C_cov, c('1','2','3','4','5'), 1:5, 4, FALSE)");
+        assertEval(".Call(stats:::C_cov, NULL, 1:5, 4, FALSE)");
+        assertEval(".Call(stats:::C_cov, 1:3, 1:5, 4, FALSE)");
+    }
+}
-- 
GitLab