From 6bcd9115691fe299ad3458b0bda1ee15dfde5a32 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Tue, 6 Mar 2018 11:07:14 +0100
Subject: [PATCH] Implemented Rf_*norm, Rf_ftrunc, Rf_rmultinom and others.

---
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  | 434 ++++++++++++++++++
 .../r/ffi/impl/nodes/FFIUpCallNode.java       |   9 +
 .../r/ffi/impl/nodes/RandFunctionsNodes.java  | 299 ++++++------
 .../r/ffi/impl/upcalls/StdUpCallsRFFI.java    | 342 +++++++++++++-
 .../truffle/r/ffi/processor/FFIProcessor.java |  20 +-
 .../r/ffi/processor/RFFIUpCallNode.java       |   4 +-
 .../fficall/src/common/rffi_upcalls.h         |  85 ++++
 .../fficall/src/common/rffi_upcallsindex.h    | 196 +++++++-
 .../fficall/src/truffle_common/Rmath.c        | 265 ++++-------
 .../truffle/r/runtime/nmath/RMultinom.java    | 106 +++++
 .../truffle/r/runtime/nmath/distr/Pnorm.java  |   5 +-
 .../packages/testrffi/testrffi/R/testrffi.R   |  10 +-
 .../packages/testrffi/testrffi/src/init.c     |   2 +
 .../packages/testrffi/testrffi/src/testrffi.c | 113 ++++-
 .../packages/testrffi/testrffi/src/testrffi.h |   4 +
 .../testrffi/testrffi/tests/simpleTests.R     |   4 +-
 mx.fastr/copyrights/overrides                 |   1 +
 17 files changed, 1573 insertions(+), 326 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMultinom.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 b88e5f750f..91b9929d96 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
@@ -1630,6 +1630,440 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         throw implementedAsNode();
     }
 
+    @Override
+    public double Rf_dnorm(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnorm(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnorm(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rnorm(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dlnorm(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_plnorm(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qlnorm(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rlnorm(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dgamma(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pgamma(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qgamma(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rgamma(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dbeta(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pbeta(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qbeta(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rbeta(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_df(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pf(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qf(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rf(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dt(double a, double b, int c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pt(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qt(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rt(double a) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dbinom(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pbinom(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qbinom(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rbinom(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dcauchy(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pcauchy(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qcauchy(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rcauchy(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dexp(double a, double b, int c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pexp(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qexp(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rexp(double a) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dgeom(double a, double b, int c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pgeom(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qgeom(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rgeom(double a) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dhyper(double a, double b, double c, double d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_phyper(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qhyper(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rhyper(double a, double b, double c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dnbinom(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnbinom(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnbinom(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rnbinom(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dnbinom_mu(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnbinom_mu(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnbinom_mu(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rnbinom_mu(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public void Rf_rmultinom(int a, Object b, int c, Object d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dpois(double a, double b, int c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_ppois(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qpois(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rpois(double a) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dweibull(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pweibull(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qweibull(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rweibull(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dlogis(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_plogis(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qlogis(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rlogis(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dnbeta(double a, double b, double c, double d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnbeta(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnbeta(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    // @Override
+    // public double Rf_rnbeta(double a, double b, double c) {
+    // throw implementedAsNode();
+    // }
+
+    @Override
+    public double Rf_dnf(double a, double b, double c, double d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnf(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnf(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dnt(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pnt(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qnt(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_ptukey(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qtukey(double a, double b, double c, double d, int e, int f) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dwilcox(double a, double b, double c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_pwilcox(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qwilcox(double a, double b, double c, int d, int e) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rwilcox(double a, double b) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_dsignrank(double a, double b, int c) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_psignrank(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_qsignrank(double a, double b, int c, int d) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_rsignrank(double a) {
+        throw implementedAsNode();
+    }
+
+    @Override
+    public double Rf_ftrunc(double a) {
+        if (a > 0) {
+            return Math.floor(a);
+        } else {
+            return Math.ceil(a);
+        }
+    }
+
     @Override
     public Object Rf_namesgets(Object x, Object y) {
         throw implementedAsNode();
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 4a86d30d42..d18cd0bf67 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
@@ -95,4 +95,13 @@ public abstract class FFIUpCallNode extends Node {
             return 5;
         }
     }
+
+    public abstract static class Arg6 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
+
+        @Override
+        protected int numArgs() {
+            return 6;
+        }
+    }
 }
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
index 116f953e4a..c6bab31f20 100644
--- 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
@@ -22,27 +22,40 @@
  */
 package com.oracle.truffle.r.ffi.impl.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.nmath.MathFunctions;
 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.MathFunctions.Function3_1;
 import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_2;
-import com.oracle.truffle.r.runtime.nmath.RandomFunctions;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function4_1;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function4_2;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction1_Double;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction3_Double;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
-import com.oracle.truffle.r.runtime.nmath.distr.Chisq;
-import com.oracle.truffle.r.runtime.nmath.distr.DNChisq;
-import com.oracle.truffle.r.runtime.nmath.distr.PNChisq;
-import com.oracle.truffle.r.runtime.nmath.distr.QNChisq;
-import com.oracle.truffle.r.runtime.nmath.distr.RNchisq;
-import com.oracle.truffle.r.runtime.nmath.distr.Unif;
+import com.oracle.truffle.r.runtime.nmath.RMultinom;
+import com.oracle.truffle.r.runtime.nmath.distr.Rbinom;
 
 public final class RandFunctionsNodes {
 
-    abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 {
-        private final MathFunctions.Function3_2 inner;
+    public abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 {
+        private final Function3_2 inner;
 
         protected RandFunction3_2Node(MathFunctions.Function3_2 inner) {
             this.inner = inner;
@@ -52,10 +65,15 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a, double b, double c, int d, int e) {
             return inner.evaluate(a, b, c, d != 0, e != 0);
         }
+
+        public static RandFunction3_2Node create(Function3_2 inner) {
+            return RandFunctionsNodesFactory.RandFunction3_2NodeGen.create(inner);
+        }
+
     }
 
-    abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 {
-        private final MathFunctions.Function3_1 inner;
+    public abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 {
+        private final Function3_1 inner;
 
         protected RandFunction3_1Node(MathFunctions.Function3_1 inner) {
             this.inner = inner;
@@ -65,10 +83,31 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a, double b, double c, int d) {
             return inner.evaluate(a, b, c, d != 0);
         }
+
+        public static RandFunction3_1Node create(Function3_1 inner) {
+            return RandFunctionsNodesFactory.RandFunction3_1NodeGen.create(inner);
+        }
+    }
+
+    public abstract static class RandFunction3Node extends FFIUpCallNode.Arg3 {
+        @Child private RandFunction3_Double inner;
+
+        protected RandFunction3Node(RandFunction3_Double inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b, double c) {
+            return inner.execute(a, b, c, RandomNumberProvider.fromCurrentRNG());
+        }
+
+        public static RandFunction3Node create(RandFunction3_Double inner) {
+            return RandFunctionsNodesFactory.RandFunction3NodeGen.create(inner);
+        }
     }
 
-    abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 {
-        @Child private RandomFunctions.RandFunction2_Double inner;
+    public abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 {
+        @Child private RandFunction2_Double inner;
 
         protected RandFunction2Node(RandFunction2_Double inner) {
             this.inner = inner;
@@ -78,9 +117,13 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a, double b) {
             return inner.execute(a, b, RandomNumberProvider.fromCurrentRNG());
         }
+
+        public static RandFunction2Node create(RandFunction2_Double inner) {
+            return RandFunctionsNodesFactory.RandFunction2NodeGen.create(inner);
+        }
     }
 
-    abstract static class RandFunction1Node extends FFIUpCallNode.Arg1 {
+    public abstract static class RandFunction1Node extends FFIUpCallNode.Arg1 {
         @Child private RandFunction1_Double inner;
 
         protected RandFunction1Node(RandFunction1_Double inner) {
@@ -91,10 +134,14 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a) {
             return inner.execute(a, RandomNumberProvider.fromCurrentRNG());
         }
+
+        public static RandFunction1Node create(RandFunction1_Double inner) {
+            return RandFunctionsNodesFactory.RandFunction1NodeGen.create(inner);
+        }
     }
 
-    abstract static class RandFunction2_1Node extends FFIUpCallNode.Arg3 {
-        private final MathFunctions.Function2_1 inner;
+    public abstract static class RandFunction2_1Node extends FFIUpCallNode.Arg3 {
+        private final Function2_1 inner;
 
         protected RandFunction2_1Node(MathFunctions.Function2_1 inner) {
             this.inner = inner;
@@ -104,10 +151,14 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a, double b, int c) {
             return inner.evaluate(a, b, c != 0);
         }
+
+        public static RandFunction2_1Node create(Function2_1 inner) {
+            return RandFunctionsNodesFactory.RandFunction2_1NodeGen.create(inner);
+        }
     }
 
-    abstract static class RandFunction2_2Node extends FFIUpCallNode.Arg4 {
-        private final MathFunctions.Function2_2 inner;
+    public abstract static class RandFunction2_2Node extends FFIUpCallNode.Arg4 {
+        private final Function2_2 inner;
 
         protected RandFunction2_2Node(MathFunctions.Function2_2 inner) {
             this.inner = inner;
@@ -117,148 +168,134 @@ public final class RandFunctionsNodes {
         protected double evaluate(double a, double b, int c, int d) {
             return inner.evaluate(a, b, c != 0, d != 0);
         }
-    }
-
-    public abstract static class RunifNode extends RandFunction2Node {
-
-        protected RunifNode(RandFunction2_Double inner) {
-            super(inner);
-        }
-
-        public static RunifNode create() {
-            return RandFunctionsNodesFactory.RunifNodeGen.create(new Unif.Runif());
-        }
-
-    }
-
-    public abstract static class DunifNode extends RandFunction3_1Node {
-
-        protected DunifNode(Function3_1 inner) {
-            super(inner);
-        }
-
-        public static DunifNode create() {
-            return RandFunctionsNodesFactory.DunifNodeGen.create(new Unif.DUnif());
-        }
-
-    }
-
-    public abstract static class QunifNode extends RandFunction3_2Node {
-
-        protected QunifNode(Function3_2 inner) {
-            super(inner);
-        }
 
-        public static QunifNode create() {
-            return RandFunctionsNodesFactory.QunifNodeGen.create(new Unif.QUnif());
+        public static RandFunction2_2Node create(Function2_2 inner) {
+            return RandFunctionsNodesFactory.RandFunction2_2NodeGen.create(inner);
         }
-
     }
 
-    public abstract static class PunifNode extends RandFunction3_2Node {
+    public abstract static class RandFunction4_1Node extends FFIUpCallNode.Arg5 {
+        private final Function4_1 inner;
 
-        protected PunifNode(Function3_2 inner) {
-            super(inner);
-        }
-
-        public static PunifNode create() {
-            return RandFunctionsNodesFactory.PunifNodeGen.create(new Unif.PUnif());
-        }
-
-    }
-
-    public abstract static class DChisqNode extends RandFunction2_1Node {
-
-        protected DChisqNode(Function2_1 inner) {
-            super(inner);
-        }
-
-        public static DChisqNode create() {
-            return RandFunctionsNodesFactory.DChisqNodeGen.create(new Chisq.DChisq());
-        }
-
-    }
-
-    public abstract static class PChisqNode extends RandFunction2_2Node {
-
-        protected PChisqNode(Function2_2 inner) {
-            super(inner);
-        }
-
-        public static PChisqNode create() {
-            return RandFunctionsNodesFactory.PChisqNodeGen.create(new Chisq.PChisq());
+        protected RandFunction4_1Node(MathFunctions.Function4_1 inner) {
+            this.inner = inner;
         }
 
-    }
-
-    public abstract static class QChisqNode extends RandFunction2_2Node {
-
-        protected QChisqNode(Function2_2 inner) {
-            super(inner);
+        @Specialization
+        protected double evaluate(double a, double b, double c, double d, int e) {
+            return inner.evaluate(a, b, c, d, e != 0);
         }
 
-        public static QChisqNode create() {
-            return RandFunctionsNodesFactory.QChisqNodeGen.create(new Chisq.QChisq());
+        public static RandFunction4_1Node create(Function4_1 inner) {
+            return RandFunctionsNodesFactory.RandFunction4_1NodeGen.create(inner);
         }
-
     }
 
-    public abstract static class RChisqNode extends RandFunction1Node {
+    public abstract static class RandFunction4_2Node extends FFIUpCallNode.Arg6 {
+        private final Function4_2 inner;
 
-        protected RChisqNode(RandFunction1_Double inner) {
-            super(inner);
-        }
-
-        public static RChisqNode create() {
-            return RandFunctionsNodesFactory.RChisqNodeGen.create(new Chisq.RChisq());
+        protected RandFunction4_2Node(MathFunctions.Function4_2 inner) {
+            this.inner = inner;
         }
 
-    }
-
-    public abstract static class DNChisqNode extends RandFunction3_1Node {
-
-        protected DNChisqNode(Function3_1 inner) {
-            super(inner);
+        @Specialization
+        protected double evaluate(double a, double b, double c, double d, int e, int f) {
+            return inner.evaluate(a, b, c, d, e != 0, f != 0);
         }
 
-        public static DNChisqNode create() {
-            return RandFunctionsNodesFactory.DNChisqNodeGen.create(new DNChisq());
+        public static RandFunction4_2Node create(Function4_2 inner) {
+            return RandFunctionsNodesFactory.RandFunction4_2NodeGen.create(inner);
         }
-
     }
 
-    public abstract static class PNChisqNode extends RandFunction3_2Node {
+    public abstract static class RfRMultinomNode extends FFIUpCallNode.Arg4 {
 
-        protected PNChisqNode(Function3_2 inner) {
-            super(inner);
-        }
+        @Child private Node probIsPointerNode = Message.IS_POINTER.createNode();
+        @Child private Node probAsPointerNode;
+        @Child private Node rNIsPointerNode = Message.IS_POINTER.createNode();
+        @Child private Node rNAsPointerNode;
+        @Child private ForeignArray2R probForeignArray2R;
+        @Child private ForeignArray2R rNForeignArray2R;
+        @Child private DoRMultinomNode doRMultinomNode = RandFunctionsNodesFactory.DoRMultinomNodeGen.create();
 
-        public static PNChisqNode create() {
-            return RandFunctionsNodesFactory.PNChisqNodeGen.create(new PNChisq());
+        @Specialization
+        protected Object evaluate(int n, Object prob, int k, Object rN) {
+            // prob is double* and rN is int*
+            // Return a vector data in rN rN[1:K] {K := length(prob)}
+            RAbstractDoubleVector probVector;
+            TruffleObject probTO = (TruffleObject) prob;
+            if (ForeignAccess.sendIsPointer(probIsPointerNode, probTO)) {
+                if (probAsPointerNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    probAsPointerNode = insert(Message.AS_POINTER.createNode());
+                }
+                long addr;
+                try {
+                    addr = ForeignAccess.sendAsPointer(probAsPointerNode, probTO);
+                    probVector = RDataFactory.createDoubleVectorFromNative(addr, k);
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
+                }
+            } else {
+                if (probForeignArray2R == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    probForeignArray2R = ForeignArray2R.create();
+                }
+                probVector = (RAbstractDoubleVector) probForeignArray2R.convert(prob);
+            }
+
+            RAbstractIntVector rNVector;
+            TruffleObject rNTO = (TruffleObject) rN;
+            if (ForeignAccess.sendIsPointer(rNIsPointerNode, rNTO)) {
+                if (rNAsPointerNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    rNAsPointerNode = insert(Message.AS_POINTER.createNode());
+                }
+                long addr;
+                try {
+                    addr = ForeignAccess.sendAsPointer(rNAsPointerNode, rNTO);
+                    rNVector = RDataFactory.createIntVectorFromNative(addr, k);
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
+                }
+            } else {
+                if (rNForeignArray2R == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    rNForeignArray2R = ForeignArray2R.create();
+                }
+                rNVector = (RAbstractIntVector) probForeignArray2R.convert(prob);
+            }
+
+            doRMultinomNode.execute(n, probVector, k, rNVector);
+            return RNull.instance;
+        }
+
+        public static RfRMultinomNode create() {
+            return RandFunctionsNodesFactory.RfRMultinomNodeGen.create();
         }
-
     }
 
-    public abstract static class QNChisqNode extends RandFunction3_2Node {
-
-        protected QNChisqNode(Function3_2 inner) {
-            super(inner);
-        }
-
-        public static QNChisqNode create() {
-            return RandFunctionsNodesFactory.QNChisqNodeGen.create(new QNChisq());
-        }
-
-    }
+    abstract static class DoRMultinomNode extends Node {
 
-    public abstract static class RNChisqNode extends RandFunction2Node {
+        public abstract void execute(int n, RAbstractDoubleVector prob, int k, RAbstractIntVector rN);
 
-        protected RNChisqNode(RandFunction2_Double inner) {
-            super(inner);
+        @Specialization(guards = {"probAccess.supports(prob)", "rNAccess.supports(rN)"})
+        protected void doRMultinom(int n, RAbstractDoubleVector prob, int k, RAbstractIntVector rN,
+                        @Cached("prob.access()") VectorAccess probAccess,
+                        @Cached("rN.access()") VectorAccess rNAccess,
+                        @Cached("new()") Rbinom rbinom) {
+            int[] rNArr = new int[k];
+            RMultinom.rmultinom(n, probAccess.access(prob), probAccess, 1d, rNArr, 0, RandomNumberProvider.fromCurrentRNG(), rbinom);
+            int i = 0;
+            for (SequentialIterator rNIter = rNAccess.access(rN); rNAccess.next(rNIter);) {
+                rNAccess.setInt(rNIter, rNArr[i++]);
+            }
         }
 
-        public static RNChisqNode create() {
-            return RandFunctionsNodesFactory.RNChisqNodeGen.create(new RNchisq());
+        @Specialization(replaces = "doRMultinom")
+        protected void doGeneric(int n, RAbstractDoubleVector prob, int k, RAbstractIntVector rN,
+                        @Cached("new()") Rbinom rbinom) {
+            doRMultinom(n, prob, k, rN, prob.slowPathAccess(), rN.slowPathAccess(), rbinom);
         }
 
     }
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 c74c973809..1e4f75b9fa 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
@@ -67,6 +67,67 @@ import com.oracle.truffle.r.ffi.processor.RFFICpointer;
 import com.oracle.truffle.r.ffi.processor.RFFICstring;
 import com.oracle.truffle.r.ffi.processor.RFFIRunGC;
 import com.oracle.truffle.r.ffi.processor.RFFIUpCallNode;
+import com.oracle.truffle.r.runtime.nmath.distr.Cauchy;
+import com.oracle.truffle.r.runtime.nmath.distr.Chisq;
+import com.oracle.truffle.r.runtime.nmath.distr.DBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.DGamma;
+import com.oracle.truffle.r.runtime.nmath.distr.DHyper;
+import com.oracle.truffle.r.runtime.nmath.distr.DNBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.DNBinom;
+import com.oracle.truffle.r.runtime.nmath.distr.DNChisq;
+import com.oracle.truffle.r.runtime.nmath.distr.DNorm;
+import com.oracle.truffle.r.runtime.nmath.distr.DPois;
+import com.oracle.truffle.r.runtime.nmath.distr.Dbinom;
+import com.oracle.truffle.r.runtime.nmath.distr.Df;
+import com.oracle.truffle.r.runtime.nmath.distr.Dnf;
+import com.oracle.truffle.r.runtime.nmath.distr.Dnt;
+import com.oracle.truffle.r.runtime.nmath.distr.Dt;
+import com.oracle.truffle.r.runtime.nmath.distr.Exp;
+import com.oracle.truffle.r.runtime.nmath.distr.Geom;
+import com.oracle.truffle.r.runtime.nmath.distr.LogNormal;
+import com.oracle.truffle.r.runtime.nmath.distr.Logis;
+import com.oracle.truffle.r.runtime.nmath.distr.PGamma;
+import com.oracle.truffle.r.runtime.nmath.distr.PHyper;
+import com.oracle.truffle.r.runtime.nmath.distr.PNBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.PNBinom;
+import com.oracle.truffle.r.runtime.nmath.distr.PNChisq;
+import com.oracle.truffle.r.runtime.nmath.distr.PPois;
+import com.oracle.truffle.r.runtime.nmath.distr.PTukey;
+import com.oracle.truffle.r.runtime.nmath.distr.Pbeta;
+import com.oracle.truffle.r.runtime.nmath.distr.Pbinom;
+import com.oracle.truffle.r.runtime.nmath.distr.Pf;
+import com.oracle.truffle.r.runtime.nmath.distr.Pnf;
+import com.oracle.truffle.r.runtime.nmath.distr.Pnorm;
+import com.oracle.truffle.r.runtime.nmath.distr.Pnt;
+import com.oracle.truffle.r.runtime.nmath.distr.Pt;
+import com.oracle.truffle.r.runtime.nmath.distr.QBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.QGamma;
+import com.oracle.truffle.r.runtime.nmath.distr.QHyper;
+import com.oracle.truffle.r.runtime.nmath.distr.QNBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.QNBinom;
+import com.oracle.truffle.r.runtime.nmath.distr.QNChisq;
+import com.oracle.truffle.r.runtime.nmath.distr.QPois;
+import com.oracle.truffle.r.runtime.nmath.distr.QTukey;
+import com.oracle.truffle.r.runtime.nmath.distr.Qbinom;
+import com.oracle.truffle.r.runtime.nmath.distr.Qf;
+import com.oracle.truffle.r.runtime.nmath.distr.Qnf;
+import com.oracle.truffle.r.runtime.nmath.distr.Qnorm;
+import com.oracle.truffle.r.runtime.nmath.distr.Qnt;
+import com.oracle.truffle.r.runtime.nmath.distr.Qt;
+import com.oracle.truffle.r.runtime.nmath.distr.RBeta;
+import com.oracle.truffle.r.runtime.nmath.distr.RGamma;
+import com.oracle.truffle.r.runtime.nmath.distr.RHyper;
+import com.oracle.truffle.r.runtime.nmath.distr.RNBinom;
+import com.oracle.truffle.r.runtime.nmath.distr.RNchisq;
+import com.oracle.truffle.r.runtime.nmath.distr.RPois;
+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;
+import com.oracle.truffle.r.runtime.nmath.distr.Unif;
+import com.oracle.truffle.r.runtime.nmath.distr.Weibull;
+import com.oracle.truffle.r.runtime.nmath.distr.Wilcox;
 
 /**
  * This class defines methods that match the functionality of the macro/function definitions in the
@@ -419,42 +480,299 @@ public interface StdUpCallsRFFI {
 
     int FASTR_getConnectionChar(Object obj);
 
-    @RFFIUpCallNode(RandFunctionsNodes.DunifNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Unif.DUnif.class)
     double Rf_dunif(double a, double b, double c, int d);
 
-    @RFFIUpCallNode(RandFunctionsNodes.QunifNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Unif.QUnif.class)
     double Rf_qunif(double a, double b, double c, int d, int e);
 
-    @RFFIUpCallNode(RandFunctionsNodes.PunifNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Unif.PUnif.class)
     double Rf_punif(double a, double b, double c, int d, int e);
 
-    @RFFIUpCallNode(RandFunctionsNodes.RunifNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Unif.Runif.class)
     double Rf_runif(double a, double b);
 
-    @RFFIUpCallNode(RandFunctionsNodes.DChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = Chisq.DChisq.class)
     double Rf_dchisq(double a, double b, int c);
 
-    @RFFIUpCallNode(RandFunctionsNodes.PChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Chisq.PChisq.class)
     double Rf_pchisq(double a, double b, int c, int d);
 
-    @RFFIUpCallNode(RandFunctionsNodes.QChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Chisq.QChisq.class)
     double Rf_qchisq(double a, double b, int c, int d);
 
-    @RFFIUpCallNode(RandFunctionsNodes.RChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = Chisq.RChisq.class)
     double Rf_rchisq(double a);
 
-    @RFFIUpCallNode(RandFunctionsNodes.DNChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DNChisq.class)
     double Rf_dnchisq(double a, double b, double c, int d);
 
-    @RFFIUpCallNode(RandFunctionsNodes.PNChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = PNChisq.class)
     double Rf_pnchisq(double a, double b, double c, int d, int e);
 
-    @RFFIUpCallNode(RandFunctionsNodes.QNChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = QNChisq.class)
     double Rf_qnchisq(double a, double b, double c, int d, int e);
 
-    @RFFIUpCallNode(RandFunctionsNodes.RNChisqNode.class)
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = RNchisq.class)
     double Rf_rnchisq(double a, double b);
 
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DNorm.class)
+    double Rf_dnorm(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Pnorm.class)
+    double Rf_pnorm(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Qnorm.class)
+    double Rf_qnorm(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Rnorm.class)
+    double Rf_rnorm(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = LogNormal.DLNorm.class)
+    double Rf_dlnorm(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = LogNormal.PLNorm.class)
+    double Rf_plnorm(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = LogNormal.QLNorm.class)
+    double Rf_qlnorm(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = LogNormal.RLNorm.class)
+    double Rf_rlnorm(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DGamma.class)
+    double Rf_dgamma(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = PGamma.class)
+    double Rf_pgamma(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = QGamma.class)
+    double Rf_qgamma(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = RGamma.class)
+    double Rf_rgamma(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DBeta.class)
+    double Rf_dbeta(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Pbeta.class)
+    double Rf_pbeta(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = QBeta.class)
+    double Rf_qbeta(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = RBeta.class)
+    double Rf_rbeta(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Df.class)
+    double Rf_df(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Pf.class)
+    double Rf_pf(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Qf.class)
+    double Rf_qf(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Rf.class)
+    double Rf_rf(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = Dt.class)
+    double Rf_dt(double a, double b, int c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Pt.class)
+    double Rf_pt(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Qt.class)
+    double Rf_qt(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = Rt.class)
+    double Rf_rt(double a);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Dbinom.class)
+    double Rf_dbinom(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Pbinom.class)
+    double Rf_pbinom(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Qbinom.class)
+    double Rf_qbinom(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Rbinom.class)
+    double Rf_rbinom(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Cauchy.DCauchy.class)
+    double Rf_dcauchy(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Cauchy.PCauchy.class)
+    double Rf_pcauchy(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Cauchy.QCauchy.class)
+    double Rf_qcauchy(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Cauchy.RCauchy.class)
+    double Rf_rcauchy(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = Exp.DExp.class)
+    double Rf_dexp(double a, double b, int c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Exp.PExp.class)
+    double Rf_pexp(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Exp.QExp.class)
+    double Rf_qexp(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = Exp.RExp.class)
+    double Rf_rexp(double a);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = Geom.DGeom.class)
+    double Rf_dgeom(double a, double b, int c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Geom.PGeom.class)
+    double Rf_pgeom(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Geom.QGeom.class)
+    double Rf_qgeom(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = Geom.RGeom.class)
+    double Rf_rgeom(double a);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_1Node.class, functionClass = DHyper.class)
+    double Rf_dhyper(double a, double b, double c, double d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = PHyper.class)
+    double Rf_phyper(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = QHyper.class)
+    double Rf_qhyper(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3Node.class, functionClass = RHyper.class)
+    double Rf_rhyper(double a, double b, double c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DNBinom.DNBinomFunc.class)
+    double Rf_dnbinom(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = PNBinom.PNBinomFunc.class)
+    double Rf_pnbinom(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = QNBinom.QNBinomFunc.class)
+    double Rf_qnbinom(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = RNBinom.RNBinomFunc.class)
+    double Rf_rnbinom(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = DNBinom.DNBinomMu.class)
+    double Rf_dnbinom_mu(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = PNBinom.PNBinomMu.class)
+    double Rf_pnbinom_mu(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = QNBinom.QNBinomMu.class)
+    double Rf_qnbinom_mu(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = RNBinom.RNBinomMu.class)
+    double Rf_rnbinom_mu(double a, double b);
+
+    @RFFIRunGC
+    @RFFIUpCallNode(value = RandFunctionsNodes.RfRMultinomNode.class)
+    void Rf_rmultinom(int a, @RFFICpointer Object b, int c, @RFFICpointer Object d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = DPois.class)
+    double Rf_dpois(double a, double b, int c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = PPois.class)
+    double Rf_ppois(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = QPois.class)
+    double Rf_qpois(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = RPois.class)
+    double Rf_rpois(double a);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Weibull.DWeibull.class)
+    double Rf_dweibull(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Weibull.PWeibull.class)
+    double Rf_pweibull(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Weibull.QWeibull.class)
+    double Rf_qweibull(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Weibull.RWeibull.class)
+    double Rf_rweibull(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Logis.DLogis.class)
+    double Rf_dlogis(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Logis.PLogis.class)
+    double Rf_plogis(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Logis.QLogis.class)
+    double Rf_qlogis(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Logis.RLogis.class)
+    double Rf_rlogis(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_1Node.class, functionClass = DNBeta.class)
+    double Rf_dnbeta(double a, double b, double c, double d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = PNBeta.class)
+    double Rf_pnbeta(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = QNBeta.class)
+    double Rf_qnbeta(double a, double b, double c, double d, int e, int f);
+
+    // double Rf_rnbeta(double a, double b, double c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_1Node.class, functionClass = Dnf.class)
+    double Rf_dnf(double a, double b, double c, double d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = Pnf.class)
+    double Rf_pnf(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = Qnf.class)
+    double Rf_qnf(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Dnt.class)
+    double Rf_dnt(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Pnt.class)
+    double Rf_pnt(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Qnt.class)
+    double Rf_qnt(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = PTukey.class)
+    double Rf_ptukey(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction4_2Node.class, functionClass = QTukey.class)
+    double Rf_qtukey(double a, double b, double c, double d, int e, int f);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_1Node.class, functionClass = Wilcox.DWilcox.class)
+    double Rf_dwilcox(double a, double b, double c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Wilcox.PWilcox.class)
+    double Rf_pwilcox(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction3_2Node.class, functionClass = Wilcox.QWilcox.class)
+    double Rf_qwilcox(double a, double b, double c, int d, int e);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2Node.class, functionClass = Wilcox.RWilcox.class)
+    double Rf_rwilcox(double a, double b);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_1Node.class, functionClass = Signrank.DSignrank.class)
+    double Rf_dsignrank(double a, double b, int c);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Signrank.PSignrank.class)
+    double Rf_psignrank(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction2_2Node.class, functionClass = Signrank.QSignrank.class)
+    double Rf_qsignrank(double a, double b, int c, int d);
+
+    @RFFIUpCallNode(value = RandFunctionsNodes.RandFunction1Node.class, functionClass = Signrank.RSignrank.class)
+    double Rf_rsignrank(double a);
+
+    double Rf_ftrunc(double a);
+
     @RFFIUpCallNode(MiscNodes.NamesGetsNode.class)
     Object Rf_namesgets(Object vec, Object val);
 
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
index d694878543..c98595d2d0 100644
--- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
@@ -170,6 +170,8 @@ public final class FFIProcessor extends AbstractProcessor {
         String canRunGc = m.getAnnotation(RFFIRunGC.class) == null ? "false" : "true";
         String nodeClassName = null;
         TypeElement nodeClass = null;
+        String functionClassName = null;
+        TypeElement functionClass = null;
         if (nodeAnnotation != null) {
             try {
                 nodeAnnotation.value();
@@ -177,6 +179,12 @@ public final class FFIProcessor extends AbstractProcessor {
                 nodeClass = (TypeElement) processingEnv.getTypeUtils().asElement(e.getTypeMirror());
                 nodeClassName = nodeClass.getQualifiedName().toString();
             }
+            try {
+                nodeAnnotation.functionClass();
+            } catch (MirroredTypeException e) {
+                functionClass = (TypeElement) processingEnv.getTypeUtils().asElement(e.getTypeMirror());
+                functionClassName = functionClass.getQualifiedName().toString();
+            }
         }
         // process arguments first to see if unwrap is necessary
         List<? extends VariableElement> params = m.getParameters();
@@ -284,12 +292,20 @@ public final class FFIProcessor extends AbstractProcessor {
                 }
             }
             if (createFunction) {
-                w.append("                @Child private " + nodeClassName + " node = " + nodeClassName + ".create();\n");
+                if (!Void.class.getName().equals(functionClassName)) {
+                    w.append("                @Child private " + nodeClassName + " node = " + nodeClassName + ".create(new " + functionClassName + "());\n");
+                } else {
+                    w.append("                @Child private " + nodeClassName + " node = " + nodeClassName + ".create();\n");
+                }
             } else if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) {
                 w.append("                @Child private " + nodeClassName + " node;\n");
                 processingEnv.getMessager().printMessage(Kind.ERROR, "Need static create for abstract classes", m);
             } else {
-                w.append("                @Child private " + nodeClassName + " node = new " + nodeClassName + "();\n");
+                if (!Void.class.getName().equals(functionClassName)) {
+                    w.append("                @Child private " + nodeClassName + " node = new " + nodeClassName + "(new " + functionClassName + "());\n");
+                } else {
+                    w.append("                @Child private " + nodeClassName + " node = new " + nodeClassName + "();\n");
+                }
             }
 
         }
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java
index d41af7c487..8e8dfa6ce9 100644
--- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -31,4 +31,6 @@ import java.lang.annotation.Target;
 @Target({ElementType.METHOD})
 public @interface RFFIUpCallNode {
     Class<?> value();
+
+    Class<?> functionClass() default Void.class;
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index e60dcbfe7f..c6a6da14a0 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -284,6 +284,91 @@ typedef double (*call_Rf_dnchisq)(double a, double b, double c, int d);
 typedef double (*call_Rf_pnchisq)(double a, double b, double c, int d, int e);
 typedef double (*call_Rf_qnchisq)(double a, double b, double c, int d, int e);
 typedef double (*call_Rf_rnchisq)(double a, double b);
+typedef double (*call_Rf_dnorm)(double a, double b, double c, int d);
+typedef double (*call_Rf_pnorm)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qnorm)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rnorm)(double a, double b);
+typedef double (*call_Rf_dlnorm)(double a, double b, double c, int d);
+typedef double (*call_Rf_plnorm)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qlnorm)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rlnorm)(double a, double b);
+typedef double (*call_Rf_dgamma)(double a, double b, double c, int d);
+typedef double (*call_Rf_pgamma)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qgamma)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rgamma)(double a, double b);
+typedef double (*call_Rf_dbeta)(double a, double b, double c, int d);
+typedef double (*call_Rf_pbeta)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qbeta)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rbeta)(double a, double b);
+typedef double (*call_Rf_df)(double a, double b, double c, int d);
+typedef double (*call_Rf_pf)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qf)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rf)(double a, double b);
+typedef double (*call_Rf_dt)(double a, double b, int c);
+typedef double (*call_Rf_pt)(double a, double b, int c, int d);
+typedef double (*call_Rf_qt)(double a, double b, int c, int d);
+typedef double (*call_Rf_rt)(double a);
+typedef double (*call_Rf_dbinom)(double a, double b, double c, int d);
+typedef double (*call_Rf_pbinom)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qbinom)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rbinom)(double a, double b);
+typedef double (*call_Rf_dcauchy)(double a, double b, double c, int d);
+typedef double (*call_Rf_pcauchy)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qcauchy)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rcauchy)(double a, double b);
+typedef double (*call_Rf_dexp)(double a, double b, int c);
+typedef double (*call_Rf_pexp)(double a, double b, int c, int d);
+typedef double (*call_Rf_qexp)(double a, double b, int c, int d);
+typedef double (*call_Rf_rexp)(double a);
+typedef double (*call_Rf_dgeom)(double a, double b, int c);
+typedef double (*call_Rf_pgeom)(double a, double b, int c, int d);
+typedef double (*call_Rf_qgeom)(double a, double b, int c, int d);
+typedef double (*call_Rf_rgeom)(double a);
+typedef double (*call_Rf_dhyper)(double a, double b, double c, double d, int e);
+typedef double (*call_Rf_phyper)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_qhyper)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_rhyper)(double a, double b, double c);
+typedef double (*call_Rf_dnbinom)(double a, double b, double c, int d);
+typedef double (*call_Rf_pnbinom)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qnbinom)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rnbinom)(double a, double b);
+typedef double (*call_Rf_dnbinom_mu)(double a, double b, double c, int d);
+typedef double (*call_Rf_pnbinom_mu)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qnbinom_mu)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rnbinom_mu)(double a, double b);
+typedef void (*call_Rf_rmultinom)(int a, double* b, int c, int* d);
+typedef double (*call_Rf_dpois)(double a, double b, int c);
+typedef double (*call_Rf_ppois)(double a, double b, int c, int d);
+typedef double (*call_Rf_qpois)(double a, double b, int c, int d);
+typedef double (*call_Rf_rpois)(double a);
+typedef double (*call_Rf_dweibull)(double a, double b, double c, int d);
+typedef double (*call_Rf_pweibull)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qweibull)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rweibull)(double a, double b);
+typedef double (*call_Rf_dlogis)(double a, double b, double c, int d);
+typedef double (*call_Rf_plogis)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qlogis)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rlogis)(double a, double b);
+typedef double (*call_Rf_dnbeta)(double a, double b, double c, double d, int e);
+typedef double (*call_Rf_pnbeta)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_qnbeta)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_dnf)(double a, double b, double c, double d, int e);
+typedef double (*call_Rf_pnf)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_qnf)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_dnt)(double a, double b, double c, int d);
+typedef double (*call_Rf_pnt)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qnt)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_ptukey)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_qtukey)(double a, double b, double c, double d, int e, int f);
+typedef double (*call_Rf_dwilcox)(double a, double b, double c, int d);
+typedef double (*call_Rf_pwilcox)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_qwilcox)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_rwilcox)(double a, double b);
+typedef double (*call_Rf_dsignrank)(double a, double b, int c);
+typedef double (*call_Rf_psignrank)(double a, double b, int c, int d);
+typedef double (*call_Rf_qsignrank)(double a, double b, int c, int d);
+typedef double (*call_Rf_rsignrank)(double a);
+typedef double (*call_Rf_ftrunc)(double a);
 typedef SEXP (*call_Rf_match)(SEXP itable, SEXP ix, int nmatch);
 typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t);
 typedef SEXP (*call_getvar)();
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 1dc742abd6..1a22cd98df 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -196,7 +196,201 @@
 #define setDotSymbolValues_x 191
 #define unif_rand_x 192
 #define useDynamicSymbols_x 193
+#define Rf_any_duplicated3_x 102
+#define Rf_asChar_x 103
+#define Rf_asCharacterFactor_x 104
+#define Rf_asInteger_x 105
+#define Rf_asLogical_x 106
+#define Rf_asReal_x 107
+#define Rf_classgets_x 108
+#define Rf_coerceVector_x 109
+#define Rf_cons_x 110
+#define Rf_copyListMatrix_x 111
+#define isSeekable_x 186
+#define octsize_x 187
+#define registerCCallable_x 188
+#define registerRoutines_x 189
+#define restoreHandlerStacks_x 190
+#define setDotSymbolValues_x 191
+#define unif_rand_x 192
+#define useDynamicSymbols_x 193
+#define Rf_asChar_x 102
+#define Rf_asCharacterFactor_x 103
+#define Rf_asInteger_x 104
+#define Rf_asLogical_x 105
+#define Rf_asReal_x 106
+#define Rf_classgets_x 107
+#define Rf_coerceVector_x 108
+#define Rf_cons_x 109
+#define Rf_copyListMatrix_x 110
+#define Rf_copyMatrix_x 111
+#define Rf_copyMostAttrib_x 112
+#define Rf_dbeta_x 113
+#define Rf_dbinom_x 114
+#define Rf_dcauchy_x 115
+#define Rf_dchisq_x 116
+#define Rf_defineVar_x 117
+#define Rf_dexp_x 118
+#define Rf_df_x 119
+#define Rf_dgamma_x 120
+#define Rf_dgeom_x 121
+#define Rf_dhyper_x 122
+#define Rf_dlnorm_x 123
+#define Rf_dlogis_x 124
+#define Rf_dnbeta_x 125
+#define Rf_dnbinom_x 126
+#define Rf_dnbinom_mu_x 127
+#define Rf_dnchisq_x 128
+#define Rf_dnf_x 129
+#define Rf_dnorm_x 130
+#define Rf_dnt_x 131
+#define Rf_dpois_x 132
+#define Rf_dsignrank_x 133
+#define Rf_dt_x 134
+#define Rf_dunif_x 135
+#define Rf_duplicate_x 136
+#define Rf_dweibull_x 137
+#define Rf_dwilcox_x 138
+#define Rf_error_x 139
+#define Rf_errorcall_x 140
+#define Rf_eval_x 141
+#define Rf_findFun_x 142
+#define Rf_findVar_x 143
+#define Rf_findVarInFrame_x 144
+#define Rf_findVarInFrame3_x 145
+#define Rf_ftrunc_x 146
+#define Rf_getAttrib_x 147
+#define Rf_gsetVar_x 148
+#define Rf_inherits_x 149
+#define Rf_install_x 150
+#define Rf_installChar_x 151
+#define Rf_isNull_x 152
+#define Rf_isString_x 153
+#define Rf_lengthgets_x 154
+#define Rf_match_x 155
+#define Rf_mkCharLenCE_x 156
+#define Rf_namesgets_x 157
+#define Rf_ncols_x 158
+#define Rf_nrows_x 159
+#define Rf_pbeta_x 160
+#define Rf_pbinom_x 161
+#define Rf_pcauchy_x 162
+#define Rf_pchisq_x 163
+#define Rf_pexp_x 164
+#define Rf_pf_x 165
+#define Rf_pgamma_x 166
+#define Rf_pgeom_x 167
+#define Rf_phyper_x 168
+#define Rf_plnorm_x 169
+#define Rf_plogis_x 170
+#define Rf_pnbeta_x 171
+#define Rf_pnbinom_x 172
+#define Rf_pnbinom_mu_x 173
+#define Rf_pnchisq_x 174
+#define Rf_pnf_x 175
+#define Rf_pnorm_x 176
+#define Rf_pnt_x 177
+#define Rf_ppois_x 178
+#define Rf_protect_x 179
+#define Rf_psignrank_x 180
+#define Rf_pt_x 181
+#define Rf_ptukey_x 182
+#define Rf_punif_x 183
+#define Rf_pweibull_x 184
+#define Rf_pwilcox_x 185
+#define Rf_qbeta_x 186
+#define Rf_qbinom_x 187
+#define Rf_qcauchy_x 188
+#define Rf_qchisq_x 189
+#define Rf_qexp_x 190
+#define Rf_qf_x 191
+#define Rf_qgamma_x 192
+#define Rf_qgeom_x 193
+#define Rf_qhyper_x 194
+#define Rf_qlnorm_x 195
+#define Rf_qlogis_x 196
+#define Rf_qnbeta_x 197
+#define Rf_qnbinom_x 198
+#define Rf_qnbinom_mu_x 199
+#define Rf_qnchisq_x 200
+#define Rf_qnf_x 201
+#define Rf_qnorm_x 202
+#define Rf_qnt_x 203
+#define Rf_qpois_x 204
+#define Rf_qsignrank_x 205
+#define Rf_qt_x 206
+#define Rf_qtukey_x 207
+#define Rf_qunif_x 208
+#define Rf_qweibull_x 209
+#define Rf_qwilcox_x 210
+#define Rf_rbeta_x 211
+#define Rf_rbinom_x 212
+#define Rf_rcauchy_x 213
+#define Rf_rchisq_x 214
+#define Rf_rexp_x 215
+#define Rf_rf_x 216
+#define Rf_rgamma_x 217
+#define Rf_rgeom_x 218
+#define Rf_rhyper_x 219
+#define Rf_rlnorm_x 220
+#define Rf_rlogis_x 221
+#define Rf_rmultinom_x 222
+#define Rf_rnbinom_x 223
+#define Rf_rnbinom_mu_x 224
+#define Rf_rnchisq_x 225
+#define Rf_rnorm_x 226
+#define Rf_rpois_x 227
+#define Rf_rsignrank_x 228
+#define Rf_rt_x 229
+#define Rf_runif_x 230
+#define Rf_rweibull_x 231
+#define Rf_rwilcox_x 232
+#define Rf_setAttrib_x 233
+#define Rf_str2type_x 234
+#define Rf_unprotect_x 235
+#define Rf_unprotect_ptr_x 236
+#define Rf_warning_x 237
+#define Rf_warningcall_x 238
+#define Rprintf_x 239
+#define SETCAD4R_x 240
+#define SETCADDDR_x 241
+#define SETCADDR_x 242
+#define SETCADR_x 243
+#define SETCAR_x 244
+#define SETCDR_x 245
+#define SET_BODY_x 246
+#define SET_CLOENV_x 247
+#define SET_FORMALS_x 248
+#define SET_NAMED_FASTR_x 249
+#define SET_RDEBUG_x 250
+#define SET_RSTEP_x 251
+#define SET_S4_OBJECT_x 252
+#define SET_STRING_ELT_x 253
+#define SET_SYMVALUE_x 254
+#define SET_TAG_x 255
+#define SET_TYPEOF_FASTR_x 256
+#define SET_VECTOR_ELT_x 257
+#define STRING_ELT_x 258
+#define SYMVALUE_x 259
+#define TAG_x 260
+#define TYPEOF_x 261
+#define UNSET_S4_OBJECT_x 262
+#define VECTOR_ELT_x 263
+#define forceSymbols_x 264
+#define getCCallable_x 265
+#define getConnectionClassString_x 266
+#define getEmbeddingDLLInfo_x 267
+#define getOpenModeString_x 268
+#define getSummaryDescription_x 269
+#define isSeekable_x 270
+#define octsize_x 271
+#define registerCCallable_x 272
+#define registerRoutines_x 273
+#define restoreHandlerStacks_x 274
+#define setDotSymbolValues_x 275
+#define unif_rand_x 276
+#define useDynamicSymbols_x 277
 
-#define UPCALLS_TABLE_SIZE 194
+#define UPCALLS_TABLE_SIZE 278
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rmath.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rmath.c
index 791442ee7a..b06cd4087e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rmath.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rmath.c
@@ -24,8 +24,7 @@
 #include "rffi_upcalls.h"
 
 double Rf_dnorm(double a, double b, double c, int d) {
-    unimplemented("Rf_dnorm");
-    return 0;
+    return ((call_Rf_dnorm) callbacks[Rf_dnorm_x])(a, b, c, d);
 }
 
 double Rf_dnorm4(double a, double b, double c, int d) {
@@ -33,8 +32,7 @@ double Rf_dnorm4(double a, double b, double c, int d) {
 }
 
 double Rf_pnorm(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pnorm");
-    return 0;
+    return ((call_Rf_pnorm) callbacks[Rf_pnorm_x])(a, b, c, d, e);
 }
 
 double Rf_pnorm5(double a, double b, double c, int d, int e) {
@@ -42,8 +40,7 @@ double Rf_pnorm5(double a, double b, double c, int d, int e) {
 }
 
 double Rf_qnorm(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qnorm");
-    return 0;
+    return ((call_Rf_qnorm) callbacks[Rf_qnorm_x])(a, b, c, d, e);
 }
 
 double Rf_qnorm5(double a, double b, double c, int d, int e) {
@@ -51,48 +48,44 @@ double Rf_qnorm5(double a, double b, double c, int d, int e) {
 }
 
 double Rf_rnorm(double a, double b) {
-    unimplemented("Rf_rnorm");
-    return 0;
+    return ((call_Rf_rnorm) callbacks[Rf_rnorm_x])(a, b);
 }
 
 void Rf_pnorm_both(double a, double * b, double * c, int d, int e) {
-    unimplemented("Rf_pnorm_both");
+    unimplemented("Rf_rnorm");
+//    return ((call_Rf_pnorm_both) callbacks[Rf_pnorm_both_x])(a, b, c, d, e);
 }
 
 double Rf_dunif(double a, double b, double c, int d) {
-	return ((call_Rf_dunif) callbacks[Rf_dunif_x])(a, b, c, d);
+    return ((call_Rf_dunif) callbacks[Rf_dunif_x])(a, b, c, d);
 }
 
 double Rf_punif(double a, double b, double c, int d, int e) {
-	return ((call_Rf_punif) callbacks[Rf_punif_x])(a, b, c, d, e);
+    return ((call_Rf_punif) callbacks[Rf_punif_x])(a, b, c, d, e);
 }
 
 double Rf_qunif(double a, double b, double c, int d, int e) {
-	return ((call_Rf_qunif) callbacks[Rf_qunif_x])(a, b, c, d, e);
+    return ((call_Rf_qunif) callbacks[Rf_qunif_x])(a, b, c, d, e);
 }
 
 double Rf_runif(double a, double b) {
-	return ((call_Rf_runif) callbacks[Rf_runif_x])(a, b);
+    return ((call_Rf_runif) callbacks[Rf_runif_x])(a, b);
 }
 
 double Rf_dgamma(double a, double b, double c, int d) {
-    unimplemented("Rf_dgamma");
-    return 0;
+    return ((call_Rf_dgamma) callbacks[Rf_dgamma_x])(a, b, c, d);
 }
 
 double Rf_pgamma(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pgamma");
-    return 0;
+    return ((call_Rf_pgamma) callbacks[Rf_pgamma_x])(a, b, c, d, e);
 }
 
 double Rf_qgamma(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qgamma");
-    return 0;
+    return ((call_Rf_qgamma) callbacks[Rf_qgamma_x])(a, b, c, d, e);
 }
 
 double Rf_rgamma(double a, double b) {
-    unimplemented("Rf_rgamma");
-    return 0;
+    return ((call_Rf_rgamma) callbacks[Rf_rgamma_x])(a, b);
 }
 
 double Rf_log1pmx(double a) {
@@ -121,43 +114,35 @@ double Rf_logspace_sub(double a, double b) {
 }
 
 double Rf_dbeta(double a, double b, double c, int d) {
-    unimplemented("Rf_dbeta");
-    return 0;
+    return ((call_Rf_dbeta) callbacks[Rf_dbeta_x])(a, b, c, d);
 }
 
 double Rf_pbeta(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pbeta");
-    return 0;
+    return ((call_Rf_pbeta) callbacks[Rf_pbeta_x])(a, b, c, d, e);
 }
 
 double Rf_qbeta(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qbeta");
-    return 0;
+    return ((call_Rf_qbeta) callbacks[Rf_qbeta_x])(a, b, c, d, e);
 }
 
 double Rf_rbeta(double a, double b) {
-    unimplemented("Rf_rbeta");
-    return 0;
+    return ((call_Rf_rbeta) callbacks[Rf_rbeta_x])(a, b);
 }
 
 double Rf_dlnorm(double a, double b, double c, int d) {
-    unimplemented("Rf_dlnorm");
-    return 0;
+    return ((call_Rf_dlnorm) callbacks[Rf_dlnorm_x])(a, b, c, d);
 }
 
 double Rf_plnorm(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_plnorm");
-    return 0;
+    return ((call_Rf_plnorm) callbacks[Rf_plnorm_x])(a, b, c, d, e);
 }
 
 double Rf_qlnorm(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qlnorm");
-    return 0;
+    return ((call_Rf_qlnorm) callbacks[Rf_qlnorm_x])(a, b, c, d, e);
 }
 
 double Rf_rlnorm(double a, double b) {
-    unimplemented("Rf_rlnorm");
-    return 0;
+    return ((call_Rf_rlnorm) callbacks[Rf_rlnorm_x])(a, b);
 }
 
 double Rf_dchisq(double a, double b, int c) {
@@ -193,262 +178,211 @@ double Rf_rnchisq(double a, double b) {
 }
 
 double Rf_df(double a, double b, double c, int d) {
-    unimplemented("Rf_df");
-    return 0;
+    return ((call_Rf_df) callbacks[Rf_df_x])(a, b, c, d);
 }
 
 double Rf_pf(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pf");
-    return 0;
+    return ((call_Rf_pf) callbacks[Rf_pf_x])(a, b, c, d, e);
 }
 
 double Rf_qf(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qf");
-    return 0;
+    return ((call_Rf_qf) callbacks[Rf_qf_x])(a, b, c, d, e);
 }
 
 double Rf_rf(double a, double b) {
-    unimplemented("Rf_rf");
-    return 0;
+    return ((call_Rf_rf) callbacks[Rf_rf_x])(a, b);
 }
 
 double Rf_dt(double a, double b, int c) {
-    unimplemented("Rf_dt");
-    return 0;
+    return ((call_Rf_dt) callbacks[Rf_dt_x])(a, b, c);
 }
 
 double Rf_pt(double a, double b, int c, int d) {
-    unimplemented("Rf_pt");
-    return 0;
+    return ((call_Rf_pt) callbacks[Rf_pt_x])(a, b, c, d);
 }
 
 double Rf_qt(double a, double b, int c, int d) {
-    unimplemented("Rf_qt");
-    return 0;
+    return ((call_Rf_qt) callbacks[Rf_qt_x])(a, b, c, d);
 }
 
 double Rf_rt(double a) {
-    unimplemented("Rf_rt");
-    return 0;
+    return ((call_Rf_rt) callbacks[Rf_rt_x])(a);
 }
 
 double Rf_dbinom(double a, double b, double c, int d) {
-    unimplemented("Rf_dbinom");
-    return 0;
+    return ((call_Rf_dbinom) callbacks[Rf_dbinom_x])(a, b, c, d);
 }
 
 double Rf_pbinom(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pbinom");
-    return 0;
+    return ((call_Rf_pbinom) callbacks[Rf_pbinom_x])(a, b, c, d, e);
 }
 
 double Rf_qbinom(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qbinom");
-    return 0;
+    return ((call_Rf_qbinom) callbacks[Rf_qbinom_x])(a, b, c, d, e);
 }
 
 double Rf_rbinom(double a, double b) {
-    unimplemented("Rf_rbinom");
-    return 0;
+    return ((call_Rf_rbinom) callbacks[Rf_rbinom_x])(a, b);
 }
 
 void Rf_rmultinom(int a, double* b, int c, int* d) {
-    unimplemented("Rf_rmultinom");
+    ((call_Rf_rmultinom) callbacks[Rf_rmultinom_x])(a, b, c, d);
 }
 
 double Rf_dcauchy(double a, double b, double c, int d) {
-    unimplemented("Rf_dcauchy");
-    return 0;
+    return ((call_Rf_dcauchy) callbacks[Rf_dcauchy_x])(a, b, c, d);
 }
 
 double Rf_pcauchy(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pcauchy");
-    return 0;
+    return ((call_Rf_pcauchy) callbacks[Rf_pcauchy_x])(a, b, c, d, e);
 }
 
 double Rf_qcauchy(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qcauchy");
-    return 0;
+    return ((call_Rf_qcauchy) callbacks[Rf_qcauchy_x])(a, b, c, d, e);
 }
 
 double Rf_rcauchy(double a, double b) {
-    unimplemented("Rf_rcauchy");
-    return 0;
+    return ((call_Rf_rcauchy) callbacks[Rf_rcauchy_x])(a, b);
 }
 
 double Rf_dexp(double a, double b, int c) {
-    unimplemented("Rf_dexp");
-    return 0;
+    return ((call_Rf_dexp) callbacks[Rf_dexp_x])(a, b, c);
 }
 
 double Rf_pexp(double a, double b, int c, int d) {
-    unimplemented("Rf_pexp");
-    return 0;
+    return ((call_Rf_pexp) callbacks[Rf_pexp_x])(a, b, c, d);
 }
 
 double Rf_qexp(double a, double b, int c, int d) {
-    unimplemented("Rf_qexp");
-    return 0;
+    return ((call_Rf_qexp) callbacks[Rf_qexp_x])(a, b, c, d);
 }
 
 double Rf_rexp(double a) {
-    unimplemented("Rf_rexp");
-    return 0;
+    return ((call_Rf_rexp) callbacks[Rf_rexp_x])(a);
 }
 
 double Rf_dgeom(double a, double b, int c) {
-    unimplemented("Rf_dgeom");
-    return 0;
+    return ((call_Rf_dgeom) callbacks[Rf_dgeom_x])(a, b, c);
 }
 
 double Rf_pgeom(double a, double b, int c, int d) {
-    unimplemented("Rf_pgeom");
-    return 0;
+    return ((call_Rf_pgeom) callbacks[Rf_pgeom_x])(a, b, c, d);
 }
 
 double Rf_qgeom(double a, double b, int c, int d) {
-    unimplemented("Rf_qgeom");
-    return 0;
+    return ((call_Rf_qgeom) callbacks[Rf_qgeom_x])(a, b, c, d);
 }
 
 double Rf_rgeom(double a) {
-    unimplemented("Rf_rgeom");
-    return 0;
+    return ((call_Rf_rgeom) callbacks[Rf_rgeom_x])(a);
 }
 
 double Rf_dhyper(double a, double b, double c, double d, int e) {
-    unimplemented("Rf_dhyper");
-    return 0;
+    return ((call_Rf_dhyper) callbacks[Rf_dhyper_x])(a, b, c, d, e);
 }
 
 double Rf_phyper(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_phyper");
-    return 0;
+    return ((call_Rf_phyper) callbacks[Rf_phyper_x])(a, b, c, d, e, f);
 }
 
 double Rf_qhyper(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_qhyper");
-    return 0;
+    return ((call_Rf_qhyper) callbacks[Rf_qhyper_x])(a, b, c, d, e, f);
 }
 
 double Rf_rhyper(double a, double b, double c) {
-    unimplemented("Rf_rhyper");
-    return 0;
+    return ((call_Rf_rhyper) callbacks[Rf_rhyper_x])(a, b, c);
 }
 
 double Rf_dnbinom(double a, double b, double c, int d) {
-    unimplemented("Rf_dnbinom");
-    return 0;
+    return ((call_Rf_dnbinom) callbacks[Rf_dnbinom_x])(a, b, c, d);
 }
 
 double Rf_pnbinom(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pnbinom");
-    return 0;
+    return ((call_Rf_pnbinom) callbacks[Rf_pnbinom_x])(a, b, c, d, e);
 }
 
 double Rf_qnbinom(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qnbinom");
-    return 0;
+    return ((call_Rf_qnbinom) callbacks[Rf_qnbinom_x])(a, b, c, d, e);
 }
 
 double Rf_rnbinom(double a, double b) {
-    unimplemented("Rf_rnbinom");
-    return 0;
+    return ((call_Rf_rnbinom) callbacks[Rf_rnbinom_x])(a, b);
 }
 
 double Rf_dnbinom_mu(double a, double b, double c, int d) {
-    unimplemented("Rf_dnbinom_mu");
-    return 0;
+    return ((call_Rf_dnbinom_mu) callbacks[Rf_dnbinom_mu_x])(a, b, c, d);
 }
 
 double Rf_pnbinom_mu(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pnbinom_mu");
-    return 0;
+    return ((call_Rf_pnbinom_mu) callbacks[Rf_pnbinom_mu_x])(a, b, c, d, e);
 }
 
 double Rf_qnbinom_mu(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qnbinom_mu");
-    return 0;
+    return ((call_Rf_qnbinom_mu) callbacks[Rf_qnbinom_mu_x])(a, b, c, d, e);
 }
 
 double Rf_rnbinom_mu(double a, double b) {
-    unimplemented("Rf_rnbinom_mu");
-    return 0;
+    return ((call_Rf_rnbinom_mu) callbacks[Rf_rnbinom_mu_x])(a, b);
 }
 
 double Rf_dpois(double a, double b, int c) {
-    unimplemented("Rf_dpois");
-    return 0;
+    return ((call_Rf_dpois) callbacks[Rf_dpois_x])(a, b, c);
 }
 
 double Rf_ppois(double a, double b, int c, int d) {
-    unimplemented("Rf_ppois");
-    return 0;
+    return ((call_Rf_ppois) callbacks[Rf_ppois_x])(a, b, c, d);
 }
 
 double Rf_qpois(double a, double b, int c, int d) {
-    unimplemented("Rf_qpois");
-    return 0;
+    return ((call_Rf_qpois) callbacks[Rf_qpois_x])(a, b, c, d);
 }
 
 double Rf_rpois(double a) {
-    unimplemented("Rf_rpois");
-    return 0;
+    return ((call_Rf_rpois) callbacks[Rf_rpois_x])(a);
 }
 
 double Rf_dweibull(double a, double b, double c, int d) {
-    unimplemented("Rf_dweibull");
-    return 0;
+    return ((call_Rf_dweibull) callbacks[Rf_dweibull_x])(a, b, c, d);
 }
 
 double Rf_pweibull(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pweibull");
-    return 0;
+    return ((call_Rf_pweibull) callbacks[Rf_pweibull_x])(a, b, c, d, e);
 }
 
 double Rf_qweibull(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qweibull");
-    return 0;
+    return ((call_Rf_qweibull) callbacks[Rf_qweibull_x])(a, b, c, d, e);
 }
 
 double Rf_rweibull(double a, double b) {
-    unimplemented("Rf_rweibull");
-    return 0;
+    return ((call_Rf_rweibull) callbacks[Rf_rweibull_x])(a, b);
 }
 
 double Rf_dlogis(double a, double b, double c, int d) {
-    unimplemented("Rf_dlogis");
-    return 0;
+    return ((call_Rf_dlogis) callbacks[Rf_dlogis_x])(a, b, c, d);
 }
 
 double Rf_plogis(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_plogis");
-    return 0;
+    return ((call_Rf_plogis) callbacks[Rf_plogis_x])(a, b, c, d, e);
 }
 
 double Rf_qlogis(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qlogis");
-    return 0;
+    return ((call_Rf_qlogis) callbacks[Rf_qlogis_x])(a, b, c, d, e);
 }
 
 double Rf_rlogis(double a, double b) {
-    unimplemented("Rf_rlogis");
-    return 0;
+    return ((call_Rf_rlogis) callbacks[Rf_rlogis_x])(a, b);
 }
 
 double Rf_dnbeta(double a, double b, double c, double d, int e) {
-    unimplemented("Rf_dnbeta");
-    return 0;
+    return ((call_Rf_dnbeta) callbacks[Rf_dnbeta_x])(a, b, c, d, e);
 }
 
 double Rf_pnbeta(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_pnbeta");
-    return 0;
+    return ((call_Rf_pnbeta) callbacks[Rf_pnbeta_x])(a, b, c, d, e, f);
 }
 
 double Rf_qnbeta(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_qnbeta");
-    return 0;
+    return ((call_Rf_qnbeta) callbacks[Rf_qnbeta_x])(a, b, c, d, e, f);
 }
 
 double Rf_rnbeta(double a, double b, double c) {
@@ -457,83 +391,67 @@ double Rf_rnbeta(double a, double b, double c) {
 }
 
 double Rf_dnf(double a, double b, double c, double d, int e) {
-    unimplemented("Rf_dnf");
-    return 0;
+    return ((call_Rf_dnf) callbacks[Rf_dnf_x])(a, b, c, d, e);
 }
 
 double Rf_pnf(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_pnf");
-    return 0;
+    return ((call_Rf_pnf) callbacks[Rf_pnf_x])(a, b, c, d, e, f);
 }
 
 double Rf_qnf(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_qnf");
-    return 0;
+    return ((call_Rf_qnf) callbacks[Rf_qnf_x])(a, b, c, d, e, f);
 }
 
 double Rf_dnt(double a, double b, double c, int d) {
-    unimplemented("Rf_dnt");
-    return 0;
+    return ((call_Rf_dnt) callbacks[Rf_dnt_x])(a, b, c, d);
 }
 
 double Rf_pnt(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pnt");
-    return 0;
+    return ((call_Rf_pnt) callbacks[Rf_pnt_x])(a, b, c, d, e);
 }
 
 double Rf_qnt(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qnt");
-    return 0;
+    return ((call_Rf_qnt) callbacks[Rf_qnt_x])(a, b, c, d, e);
 }
 
 double Rf_ptukey(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_ptukey");
-    return 0;
+    return ((call_Rf_ptukey) callbacks[Rf_ptukey_x])(a, b, c, d, e, f);
 }
 
 double Rf_qtukey(double a, double b, double c, double d, int e, int f) {
-    unimplemented("Rf_qtukey");
-    return 0;
+    return ((call_Rf_qtukey) callbacks[Rf_qtukey_x])(a, b, c, d, e, f);
 }
 
 double Rf_dwilcox(double a, double b, double c, int d) {
-    unimplemented("Rf_dwilcox");
-    return 0;
+    return ((call_Rf_dwilcox) callbacks[Rf_dwilcox_x])(a, b, c, d);
 }
 
 double Rf_pwilcox(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_pwilcox");
-    return 0;
+    return ((call_Rf_pwilcox) callbacks[Rf_pwilcox_x])(a, b, c, d, e);
 }
 
 double Rf_qwilcox(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qwilcox");
-    return 0;
+    return ((call_Rf_qwilcox) callbacks[Rf_qwilcox_x])(a, b, c, d, e);
 }
 
 double Rf_rwilcox(double a, double b) {
-    unimplemented("Rf_rwilcox");
-    return 0;
+    return ((call_Rf_rwilcox) callbacks[Rf_rwilcox_x])(a, b);
 }
 
 double Rf_dsignrank(double a, double b, int c) {
-    unimplemented("Rf_dsignrank");
-    return 0;
+    return ((call_Rf_dsignrank) callbacks[Rf_dsignrank_x])(a, b, c);
 }
 
 double Rf_psignrank(double a, double b, int c, int d) {
-    unimplemented("Rf_psignrank");
-    return 0;
+    return ((call_Rf_psignrank) callbacks[Rf_psignrank_x])(a, b, c, d);
 }
 
 double Rf_qsignrank(double a, double b, int c, int d) {
-    unimplemented("Rf_qsignrank");
-    return 0;
+    return ((call_Rf_qsignrank) callbacks[Rf_qsignrank_x])(a, b, c, d);
 }
 
 double Rf_rsignrank(double a) {
-    unimplemented("Rf_rsignrank");
-    return 0;
+    return ((call_Rf_rsignrank) callbacks[Rf_rsignrank_x])(a);
 }
 
 double Rf_gammafn(double a) {
@@ -675,8 +593,7 @@ double Rf_fsign(double a, double b) {
 }
 
 double Rf_ftrunc(double a) {
-    unimplemented("Rf_ftrunc");
-    return 0;
+    return ((call_Rf_ftrunc) callbacks[Rf_ftrunc_x])(a);
 }
 
 double Rf_cospi(double a) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMultinom.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMultinom.java
new file mode 100644
index 0000000000..cc3b4ec1c1
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMultinom.java
@@ -0,0 +1,106 @@
+/*
+ * 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) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2012, The R Core Team
+ * Copyright (c) 2003-2008, The R Foundation
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.runtime.nmath;
+
+import com.oracle.truffle.r.runtime.nmath.distr.*;
+import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+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.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
+
+public final class RMultinom {
+    private RMultinom() {
+        // only static method rmultinom
+    }
+
+    /**
+     * Returns true if no element of the vector rN got assigned value NA, i.e. is stayed complete if
+     * it was before. GnuR doc: `Return' vector rN[1:K] {K := length(prob)} where rN[j] ~ Bin(n,
+     * prob[j]) , sum_j rN[j] == n, sum_j prob[j] == 1.
+     */
+    @TruffleBoundary
+    public static boolean rmultinom(int nIn, SequentialIterator probsIter, VectorAccess probsAccess, double sum, int[] rN, int rnStartIdx, RandomNumberProvider rand, Rbinom rbinom) {
+        /*
+         * This calculation is sensitive to exact values, so we try to ensure that the calculations
+         * are as accurate as possible so different platforms are more likely to give the same
+         * result.
+         */
+
+        int n = nIn;
+        int maxK = probsAccess.getLength(probsIter);
+        if (RRuntime.isNA(maxK) || maxK < 1 || RRuntime.isNA(n) || n < 0) {
+            if (rN.length > rnStartIdx) {
+                rN[rnStartIdx] = RRuntime.INT_NA;
+            }
+            return false;
+        }
+
+        /*
+         * Note: prob[K] is only used here for checking sum_k prob[k] = 1 ; Could make loop one
+         * shorter and drop that check !
+         */
+        /* LDOUBLE */double pTot = 0.;
+        probsAccess.reset(probsIter);
+        for (int k = 0; probsAccess.next(probsIter); k++) {
+            double pp = probsAccess.getDouble(probsIter) / sum;
+            if (!Double.isFinite(pp) || pp < 0. || pp > 1.) {
+                rN[rnStartIdx + k] = RRuntime.INT_NA;
+                return false;
+            }
+            pTot += pp;
+            rN[rnStartIdx + k] = 0;
+        }
+
+        /* LDOUBLE */double probSum = Math.abs(pTot - 1);
+        if (probSum > 1e-7) {
+            throw RError.error(SHOW_CALLER, Message.GENERIC, String.format("rbinom: probability sum should be 1, but is %g", pTot));
+        }
+        if (n == 0) {
+            return true;
+        }
+        if (maxK == 1 && pTot == 0.) {
+            return true; /* trivial border case: do as rbinom */
+        }
+
+        /* Generate the first K-1 obs. via binomials */
+        probsAccess.reset(probsIter);
+        for (int k = 0; probsAccess.next(probsIter) && k < maxK - 1; k++) {
+            /* (p_tot, n) are for "remaining binomial" */
+            /* LDOUBLE */double probK = probsAccess.getDouble(probsIter) / sum;
+            if (probK != 0.) {
+                double pp = probK / pTot;
+                // System.out.printf("[%d] %.17f\n", k + 1, pp);
+                rN[rnStartIdx + k] = ((pp < 1.) ? (int) rbinom.execute(n, pp, rand) :
+                /* >= 1; > 1 happens because of rounding */
+                                n);
+                n -= rN[rnStartIdx + k];
+            } else {
+                rN[rnStartIdx + k] = 0;
+            }
+            if (n <= 0) {
+                /* we have all */
+                return true;
+            }
+            /* i.e. = sum(prob[(k+1):K]) */
+            pTot -= probK;
+        }
+
+        rN[rnStartIdx + maxK - 1] = n;
+        return true;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
index 4bb9d06fc8..c8ae38cd2b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
@@ -6,7 +6,7 @@
  * Copyright (C) 1998 Ross Ihaka
  * Copyright (c) 2000--2013, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -76,7 +76,8 @@ public final class Pnorm implements Function3_2 {
         return (lowerTail ? pnormBoth.cum : pnormBoth.ccum);
     }
 
-    private static final class PnormBoth {
+    public static final class PnormBoth {
+
         private double cum;
         private double ccum;
 
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index 51693ce40f..54ea96bf5f 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -213,6 +213,14 @@ rffi.getBytes <- function(x) {
 	.Call('test_getBytes', x)
 }
 
-rffi.RFRandomFunctions <- function() {
+rffi.RfRandomFunctions <- function() {
 	.Call('test_RfRandomFunctions')
 }
+
+rffi.RfRMultinom <- function() {
+	.Call('test_RfRMultinom')
+}
+
+rffi.RfFunctions <- function() {
+	.Call('test_RfFunctions')
+}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
index 9bb75279de..72f204258e 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
@@ -86,6 +86,8 @@ static const R_CallMethodDef CallEntries[] = {
         CALLDEF(test_getBytes, 1),
         CALLDEF(test_setStringElt, 2),
         CALLDEF(test_RfRandomFunctions, 0),
+        CALLDEF(test_RfRMultinom, 0),
+        CALLDEF(test_RfFunctions, 0),
         {NULL, NULL, 0}
 };
 
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index a810e4c92e..057eaa8954 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -34,6 +34,8 @@
 #include <string.h>
 #include "testrffi.h"
 
+#define K_RMULTINOM 4
+
 void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata, char** cdata) {
     for (int i = 0; i < len[0]; i++) {
 	idata[i] ++;
@@ -589,7 +591,7 @@ SEXP test_RfEvalWithPromiseInPairList() {
 
 SEXP test_RfRandomFunctions() {
     SEXP v;
-    PROTECT(v = allocVector(REALSXP, 12));
+    PROTECT(v = allocVector(REALSXP, 95));
     int n = 0;
     REAL(v)[n++] = Rf_dunif(1, 0, 1, FALSE);
     REAL(v)[n++] = Rf_qunif(1, 0, 1, TRUE, FALSE);
@@ -603,6 +605,115 @@ SEXP test_RfRandomFunctions() {
     REAL(v)[n++] = Rf_pnchisq(1, 0, 1, TRUE, FALSE);
     REAL(v)[n++] = Rf_qnchisq(1, 0, 1, TRUE, FALSE);
     REAL(v)[n++] = Rf_rnchisq(0, 1);
+    REAL(v)[n++] = Rf_dnorm4(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pnorm5(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnorm5(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rnorm(1, 0);
+    REAL(v)[n++] = Rf_dlnorm(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_plnorm(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qlnorm(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rlnorm(1, 0);
+    REAL(v)[n++] = Rf_dgamma(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pgamma(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qgamma(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rgamma(1, 0);
+    REAL(v)[n++] = Rf_dbeta(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pbeta(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qbeta(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rbeta(1, 0);
+    REAL(v)[n++] = Rf_df(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pf(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qf(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rf(1, 0);
+    REAL(v)[n++] = Rf_dt(1, 0, FALSE);
+    REAL(v)[n++] = Rf_pt(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qt(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rt(1);
+    REAL(v)[n++] = Rf_dbinom(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pbinom(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qbinom(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rbinom(1, 0);
+    REAL(v)[n++] = Rf_dcauchy(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pcauchy(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qcauchy(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rcauchy(1, 0);
+    REAL(v)[n++] = Rf_dexp(1, 0, FALSE);
+    REAL(v)[n++] = Rf_pexp(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qexp(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rexp(1);
+    REAL(v)[n++] = Rf_dgeom(1, 0, FALSE);
+    REAL(v)[n++] = Rf_pgeom(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qgeom(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rgeom(1);
+    REAL(v)[n++] = Rf_dhyper(1, 0, 1, 0, FALSE);
+    REAL(v)[n++] = Rf_phyper(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qhyper(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rhyper(1, 0, 1);
+    REAL(v)[n++] = Rf_dnbinom(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pnbinom(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnbinom(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rnbinom(1, 0);
+    REAL(v)[n++] = Rf_dnbinom_mu(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pnbinom_mu(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnbinom_mu(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rnbinom_mu(1, 0);
+    REAL(v)[n++] = Rf_dpois(1, 0, FALSE);
+    REAL(v)[n++] = Rf_ppois(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qpois(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rpois(1);
+    REAL(v)[n++] = Rf_dweibull(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pweibull(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qweibull(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rweibull(1, 0);
+    REAL(v)[n++] = Rf_dlogis(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_plogis(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qlogis(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rlogis(1, 0);
+    REAL(v)[n++] = Rf_dnbeta(1, 0, 1, 0, FALSE);
+    REAL(v)[n++] = Rf_pnbeta(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnbeta(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_dnf(1, 0, 1, 0, FALSE);
+    REAL(v)[n++] = Rf_pnf(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnf(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_dnt(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pnt(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qnt(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_ptukey(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qtukey(1, 0, 1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_dwilcox(1, 0, 1, FALSE);
+    REAL(v)[n++] = Rf_pwilcox(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qwilcox(1, 0, 1, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rwilcox(1, 0);
+    REAL(v)[n++] = Rf_dsignrank(1, 0, FALSE);
+    REAL(v)[n++] = Rf_psignrank(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_qsignrank(1, 0, TRUE, FALSE);
+    REAL(v)[n++] = Rf_rsignrank(1);
+    UNPROTECT(1);
+    return v;
+}
+
+SEXP test_RfRMultinom() {
+    SEXP v;
+    PROTECT(v = allocVector(REALSXP, K_RMULTINOM));
+    double prob[K_RMULTINOM] = {0.1, 0.3, 0.5, 0.1};
+    int rN[K_RMULTINOM] = {0, 0, 0, 0};
+    Rf_rmultinom(10, prob, K_RMULTINOM, rN);
+    for (int i = 0; i < K_RMULTINOM; i++) {
+        REAL(v)[i] = rN[i];
+    }
     UNPROTECT(1);
     return v;
 }
+
+SEXP test_RfFunctions() {
+    SEXP v;
+    PROTECT(v = allocVector(REALSXP, 4));
+    int n = 0;
+    REAL(v)[n++] = Rf_ftrunc(2.6);
+    REAL(v)[n++] = Rf_ftrunc(5.3);
+    REAL(v)[n++] = Rf_ftrunc(-2.6);
+    REAL(v)[n++] = Rf_ftrunc(-5.3);
+    UNPROTECT(1);
+    return v;
+}
+
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
index e8e6b43373..eac32181f6 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
@@ -118,3 +118,7 @@ extern SEXP test_setStringElt(SEXP vec, SEXP elt);
 extern SEXP test_getBytes(SEXP vec);
 
 extern SEXP test_RfRandomFunctions();
+
+extern SEXP test_RfRMultinom();
+
+extern SEXP test_RfFunctions();
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
index 09e10aeb4e..6c3f566281 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
@@ -137,5 +137,7 @@ rffi.CDR(NULL)
 invisible(rffi.CAR(as.symbol('a'))) # TODO: printing CHARSEXP not implemented in FastR
 
 set.seed(42)
-rffi.RFRandomFunctions()
+rffi.RfRandomFunctions()
 
+rffi.RfRMultinom()
+rffi.RfFunctions()
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index cbafb063d5..100cb2cf76 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -278,6 +278,7 @@ com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java,gn
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/MathConstants.java,gnu_r_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java,gnu_r_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMathError.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMultinom.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/TOMS708.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/DuplicationHelper.java,purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java,gnu_r_purdue.copyright
-- 
GitLab