From 19ef5d14934814a76241329934f13db9b8e450f4 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 3 Aug 2017 18:28:21 +0200
Subject: [PATCH] Implemented Rf_runif, Rf_qunif, Rf_punif, and Rf_dunif.

---
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  | 23 +++++++++
 .../impl/common/TracingUpCallsRFFIImpl.java   | 25 ++++++++++
 .../r/ffi/impl/nodes/FFIUpCallNode.java       | 18 +++++++
 .../r/ffi/impl/nodes/FFIUpCallRootNode.java   |  8 +++
 .../r/ffi/impl/nodes/RandFunctionsNodes.java  | 50 +++++++++++++++++++
 .../r/ffi/impl/upcalls/StdUpCallsRFFI.java    |  8 +++
 .../fficall/src/jni/Rmath.c                   | 29 ++++++++---
 7 files changed, 153 insertions(+), 8 deletions(-)
 create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java

diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index 384967e805..b1bd221a64 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -110,6 +110,8 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
+import com.oracle.truffle.r.runtime.nmath.distr.Unif;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -1581,4 +1583,25 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         name2typeTable.put("numeric", SEXPTYPE.REALSXP.code);
         name2typeTable.put("name", SEXPTYPE.SYMSXP.code);
     }
+
+    @Override
+    public double Rf_dunif(double a, double b, double c, int d) {
+        return new Unif.DUnif().evaluate(a, b, c, RRuntime.fromLogical((byte) d));
+    }
+
+    @Override
+    public double Rf_qunif(double a, double b, double c, int d, int e) {
+        return new Unif.QUnif().evaluate(a, b, c, RRuntime.fromLogical((byte) d), RRuntime.fromLogical((byte) e));
+    }
+
+    @Override
+    public double Rf_punif(double a, double b, double c, int d, int e) {
+        return new Unif.PUnif().evaluate(a, b, c, RRuntime.fromLogical((byte) d), RRuntime.fromLogical((byte) e));
+    }
+
+    @Override
+    public double Rf_runif(double a, double b) {
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_runif).call(a, b);
+    }
+
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
index cf9a072f94..4add422498 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
@@ -847,4 +847,29 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         RFFIUtils.traceUpCall("Rf_str2type");
         return delegate.Rf_str2type(name);
     }
+
+    @Override
+    public double Rf_dunif(double a, double b, double c, int d) {
+        RFFIUtils.traceUpCall("Rf_dunif", a, b, c, d);
+        return delegate.Rf_dunif(a, b, c, d);
+    }
+
+    @Override
+    public double Rf_qunif(double a, double b, double c, int d, int e) {
+        RFFIUtils.traceUpCall("Rf_qunif", a, b, c, d, e);
+        return delegate.Rf_qunif(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_punif(double a, double b, double c, int d, int e) {
+        RFFIUtils.traceUpCall("Rf_punif", a, b, c, d, e);
+        return delegate.Rf_punif(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_runif(double a, double b) {
+        RFFIUtils.traceUpCall("Rf_runif", a, b);
+        return delegate.Rf_runif(a, b);
+    }
+
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
index b6a57e296c..5df825b06b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
@@ -62,4 +62,22 @@ public abstract class FFIUpCallNode extends Node {
             return 3;
         }
     }
+
+    public abstract static class Arg4 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2, Object arg3);
+
+        @Override
+        protected int numArgs() {
+            return 4;
+        }
+    }
+
+    public abstract static class Arg5 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4);
+
+        @Override
+        protected int numArgs() {
+            return 5;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java
index a3bd560c96..ae1086a488 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java
@@ -38,9 +38,13 @@ import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.LENGTHNodeGen;
 import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoNewObjectNodeGen;
 import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotAssignNodeGen;
 import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction2NodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction3_1NodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction3_2NodeGen;
 import com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.nmath.distr.Unif;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public final class FFIUpCallRootNode extends RootNode {
@@ -105,5 +109,9 @@ public final class FFIUpCallRootNode extends RootNode {
         FFIUpCallRootNode.add(RFFIUpCallTable.R_do_new_object, RDoNewObjectNodeGen::create);
         FFIUpCallRootNode.add(RFFIUpCallTable.R_do_slot, RDoSlotNodeGen::create);
         FFIUpCallRootNode.add(RFFIUpCallTable.R_do_slot_assign, RDoSlotAssignNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_runif, () -> RandFunction2NodeGen.create(new Unif.Runif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_dunif, () -> RandFunction3_1NodeGen.create(new Unif.DUnif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_qunif, () -> RandFunction3_2NodeGen.create(new Unif.QUnif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_punif, () -> RandFunction3_2NodeGen.create(new Unif.PUnif()));
     }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java
new file mode 100644
index 0000000000..807ff5d5c0
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java
@@ -0,0 +1,50 @@
+package com.oracle.truffle.r.ffi.impl.nodes;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
+
+public final class RandFunctionsNodes {
+
+    public abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 {
+        @Child private MathFunctions.Function3_2 inner;
+
+        protected RandFunction3_2Node(MathFunctions.Function3_2 inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b, double c, boolean d, boolean e) {
+            return inner.evaluate(a, b, c, d, e);
+        }
+    }
+
+    public abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 {
+        @Child private MathFunctions.Function3_1 inner;
+
+        protected RandFunction3_1Node(MathFunctions.Function3_1 inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b, double c, boolean d) {
+            return inner.evaluate(a, b, c, d);
+        }
+    }
+
+    public abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 {
+        @Child private RandomFunctions.RandFunction2_Double inner;
+
+        protected RandFunction2Node(RandFunction2_Double inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b) {
+            return inner.execute(a, b, RandomNumberProvider.fromCurrentRNG());
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 56faae246c..fe1398c447 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -295,4 +295,12 @@ public interface StdUpCallsRFFI {
 
     int Rf_str2type(@RFFICstring Object name);
 
+    double Rf_dunif(double a, double b, double c, int d);
+
+    double Rf_qunif(double a, double b, double c, int d, int e);
+
+    double Rf_punif(double a, double b, double c, int d, int e);
+
+    double Rf_runif(double a, double b);
+
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c b/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
index fd82bd5872..400076323a 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
@@ -22,8 +22,17 @@
  */
 #include <rffiutils.h>
 
+static jmethodID Rf_runifMethodID;
+static jmethodID Rf_punifMethodID;
+static jmethodID Rf_qunifMethodID;
+static jmethodID Rf_dunifMethodID;
+
 void init_rmath(JNIEnv *env) {
 
+	Rf_runifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_runif", "(DD)D", 0);
+	Rf_punifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_punif", "(DDDII)D", 0);
+	Rf_qunifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_qunif", "(DDDII)D", 0);
+	Rf_dunifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_dunif", "(DDDI)D", 0);
 }
 
 double Rf_dnorm(double a, double b, double c, int d) {
@@ -63,23 +72,27 @@ void Rf_pnorm_both(double a, double * b, double * c, int d, int e) {
 }
 
 double Rf_dunif(double a, double b, double c, int d) {
-    unimplemented("Rf_dunif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_dunifMethodID, a, b, c, d);
 }
 
 double Rf_punif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_punif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_punifMethodID, a, b, c, d, e);
 }
 
 double Rf_qunif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qunif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_qunifMethodID, a, b, c, d, e);
 }
 
 double Rf_runif(double a, double b) {
-    unimplemented("Rf_runif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_runifMethodID, a, b);
 }
 
 double Rf_dgamma(double a, double b, double c, int d) {
-- 
GitLab