diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abs.java
index 88bdd0a26bd3b1449cda6f6ced35c8c20854e31f..e8b0a3ede352ad5dd72b25b366d258462993cfe7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abs.java
@@ -22,157 +22,69 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.attributes.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.closures.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.ops.na.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 
 @RBuiltin(name = "abs", kind = PRIMITIVE, parameterNames = {"x"})
 public abstract class Abs extends RBuiltinNode {
 
-    @Child private CopyOfRegAttributesNode copyAttributes;
-
-    private final NACheck check = NACheck.create();
-    private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
-
-    @Specialization
-    protected int abs(int value) {
-        controlVisibility();
-        check.enable(value);
-        return performInt(value);
-    }
-
-    @Specialization
-    protected int abs(byte value) {
-        controlVisibility();
-        check.enable(value);
-        if (check.check(value)) {
-            return RRuntime.INT_NA;
-        }
-        return Math.abs(value);
-    }
+    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+    @Child private UnaryArithmeticNode absNode = UnaryArithmeticNodeGen.create(AbsArithmetic::new,
+                    RError.Message.NON_NUMERIC_MATH, RType.Integer);
 
     @Specialization
-    protected double abs(double value) {
-        controlVisibility();
-        check.enable(value);
-        return performDouble(value);
+    protected Object abs(Object value) {
+        return absNode.execute(boxPrimitive.execute(value));
     }
 
-    @Specialization
-    protected double abs(RComplex value) {
-        controlVisibility();
-        check.enable(value);
-        return performComplex(value);
-    }
+    public static class AbsArithmetic extends UnaryArithmetic {
 
-    private void copyRegAttributes(RAbstractVector source, RVector target) {
-        if (copyAttributes == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            copyAttributes = insert(CopyOfRegAttributesNodeGen.create());
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            switch (argumentType) {
+                case Complex:
+                    return RType.Double;
+                default:
+                    return super.calculateResultType(argumentType);
+            }
         }
-        copyAttributes.execute(source, target);
-    }
-
-    protected boolean isPositiveSequence(RIntSequence sequence) {
-        return sequence.getStart() >= 0 && (sequence.getStart() + (sequence.getLength() - 1) * (long) sequence.getStride()) <= Integer.MAX_VALUE;
-    }
 
-    @Specialization(guards = "isPositiveSequence(vector)")
-    protected RIntSequence doAbsIntSequence(RIntSequence vector) {
-        controlVisibility();
-        return vector;
-    }
-
-    @Specialization
-    protected RIntVector doAbs(RAbstractIntVector vector) {
-        controlVisibility();
-        check.enable(vector);
-        int[] intVector = new int[vector.getLength()];
-        for (int i = 0; i < vector.getLength(); i++) {
-            intVector[i] = performInt(vector.getDataAt(i));
+        @Override
+        public int op(byte op) {
+            return Math.abs(op);
         }
-        RIntVector res = RDataFactory.createIntVector(intVector, check.neverSeenNA(), vector.getDimensions(), vector.getNames(attrProfiles));
-        copyRegAttributes(vector, res);
-        return res;
-    }
 
-    protected boolean isPositiveSequence(RDoubleSequence sequence) {
-        return sequence.getStart() >= 0 && sequence.getStride() >= 0;
-    }
-
-    @Specialization(guards = "isPositiveSequence(vector)")
-    protected RDoubleSequence doAbsDoubleSequence(RDoubleSequence vector) {
-        controlVisibility();
-        return vector;
-    }
-
-    @Specialization
-    protected RDoubleVector abs(RAbstractDoubleVector vector) {
-        controlVisibility();
-        check.enable(vector);
-        double[] doubleVector = new double[vector.getLength()];
-        for (int i = 0; i < vector.getLength(); i++) {
-            doubleVector[i] = performDouble(vector.getDataAt(i));
+        @Override
+        public int op(int op) {
+            return Math.abs(op);
         }
-        RDoubleVector res = RDataFactory.createDoubleVector(doubleVector, check.neverSeenNA(), vector.getDimensions(), vector.getNames(attrProfiles));
-        copyRegAttributes(vector, res);
-        return res;
-    }
 
-    @Specialization
-    protected RDoubleVector abs(RAbstractComplexVector vector) {
-        controlVisibility();
-        check.enable(vector);
-        double[] doubleVector = new double[vector.getLength()];
-        for (int i = 0; i < vector.getLength(); i++) {
-            doubleVector[i] = performComplex(vector.getDataAt(i));
+        @Override
+        public double op(double op) {
+            return Math.abs(op);
         }
-        RDoubleVector res = RDataFactory.createDoubleVector(doubleVector, check.neverSeenNA(), vector.getDimensions(), vector.getNames(attrProfiles));
-        copyRegAttributes(vector, res);
-        return res;
-    }
 
-    @Specialization
-    protected RIntVector abs(RAbstractLogicalVector value) {
-        controlVisibility();
-        check.enable(value);
-        return doAbs(RClosures.createLogicalToIntVector(value));
-    }
-
-    @Fallback
-    @TruffleBoundary
-    protected Object abs(@SuppressWarnings("unused") Object vector) {
-        controlVisibility();
-        throw RError.error(this, RError.Message.NON_NUMERIC_MATH);
-    }
-
-    private int performInt(int value) {
-        if (check.check(value)) {
-            return RRuntime.INT_NA;
+        @Override
+        public RComplex op(double re, double im) {
+            throw new UnsupportedOperationException();
         }
-        return Math.abs(value);
-    }
 
-    private double performDouble(double value) {
-        if (check.check(value)) {
-            return RRuntime.DOUBLE_NA;
+        @Override
+        public double opd(double re, double im) {
+            return RComplex.abs(re, im);
         }
-        return Math.abs(value);
-    }
 
-    private double performComplex(RComplex value) {
-        if (check.check(value)) {
-            return RRuntime.DOUBLE_NA;
-        }
-        return value.abs();
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
index 2dc20868b4899a43a17d4fac0cc307ce5c0d7784..fc26d9e209823718918541b7e8e8f27eef4fac51 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
@@ -34,11 +34,22 @@ import com.oracle.truffle.r.runtime.ops.*;
 @RBuiltin(name = "ceiling", kind = PRIMITIVE, parameterNames = {"x"})
 public abstract class Ceiling extends RBuiltinNode {
 
+    public static final UnaryArithmeticFactory CEILING = CeilingArithmetic::new;
+
     @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
-    @Child private UnaryArithmeticNode ceiling = UnaryArithmeticNodeGen.create(UnaryArithmetic.CEILING, RError.Message.NON_NUMERIC_MATH, RType.Double);
+    @Child private UnaryArithmeticNode ceiling = UnaryArithmeticNodeGen.create(CEILING, RError.Message.NON_NUMERIC_MATH, RType.Double);
 
     @Specialization
     protected Object ceiling(Object value) {
         return ceiling.execute(boxPrimitive.execute(value));
     }
+
+    public static class CeilingArithmetic extends Round.RoundArithmetic {
+
+        @Override
+        public double op(double op) {
+            return Math.ceil(op);
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Conj.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Conj.java
index a180cc19ae69068312bd24c132723b0ae383ba29..e6bd1412759d9d12371cf9d7f6627fde0d457a9c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Conj.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Conj.java
@@ -22,22 +22,34 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.ops.na.*;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 
 @RBuiltin(name = "Conj", kind = PRIMITIVE, parameterNames = {"z"})
 public abstract class Conj extends RBuiltinNode {
 
-    private NACheck naCheck = NACheck.create();
+    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+    @Child private UnaryArithmeticNode conjNode = UnaryArithmeticNodeGen.create(ConjArithmetic::new,
+                    RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
+
+    @Specialization
+    protected Object conj(Object value) {
+        return conjNode.execute(boxPrimitive.execute(value));
+    }
 
     @Child private CastDoubleNode castDouble;
 
@@ -49,36 +61,28 @@ public abstract class Conj extends RBuiltinNode {
         return castDouble.executeDouble(value);
     }
 
-    @Specialization
-    protected RComplexVector conj(RAbstractComplexVector vector) {
-        RComplexVector result = (RComplexVector) vector.copy();
-        naCheck.enable(vector);
-        for (int i = 0; i < vector.getLength(); i++) {
-            RComplex el = vector.getDataAt(i);
-            if (!naCheck.check(el)) {
-                result.updateDataAt(i, RDataFactory.createComplex(el.getRealPart(), -el.getImaginaryPart()), naCheck);
-            }
+    public static class ConjArithmetic extends UnaryArithmetic {
+
+        @Override
+        public int op(byte op) {
+            return op;
         }
-        return result;
-    }
 
-    @Specialization
-    protected RDoubleVector conj(RAbstractDoubleVector vector) {
-        return (RDoubleVector) vector.copy();
-    }
+        @Override
+        public int op(int op) {
+            return op;
+        }
 
-    @Specialization
-    protected Object conj(RAbstractIntVector vector) {
-        return castDouble(vector);
-    }
+        @Override
+        public double op(double op) {
+            return op;
+        }
 
-    @Specialization
-    protected Object conj(RAbstractLogicalVector vector) {
-        return castDouble(vector);
-    }
+        @Override
+        public RComplex op(double re, double im) {
+            return RComplex.valueOf(re, -im);
+        }
 
-    @Fallback
-    protected Object conj(@SuppressWarnings("unused") Object o) {
-        throw RError.error(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION);
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
index 8d363faa79dbb8163059356d872aa903910d1188..f27bd58ac6d670e39779f44993a2afa16a92c43a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
@@ -34,11 +34,22 @@ import com.oracle.truffle.r.runtime.ops.*;
 @RBuiltin(name = "floor", kind = PRIMITIVE, parameterNames = {"x"})
 public abstract class Floor extends RBuiltinNode {
 
+    public static final UnaryArithmeticFactory FLOOR = FloorArithmetic::new;
+
     @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
-    @Child private UnaryArithmeticNode floor = UnaryArithmeticNodeGen.create(UnaryArithmetic.FLOOR, RError.Message.NON_NUMERIC_MATH, RType.Double);
+    @Child private UnaryArithmeticNode floor = UnaryArithmeticNodeGen.create(FLOOR, RError.Message.NON_NUMERIC_MATH, RType.Double);
 
     @Specialization
     protected Object floor(Object value) {
         return floor.execute(boxPrimitive.execute(value));
     }
+
+    public static class FloorArithmetic extends Round.RoundArithmetic {
+
+        @Override
+        public double op(double op) {
+            return Math.floor(op);
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Im.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Im.java
index 3ab06a6e72e2bd01a57989b3149bd85173bf4ef5..cca79acfb3bb3a63531bbb553ecfba19ee139362 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Im.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Im.java
@@ -22,47 +22,71 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.nodes.builtin.base.ImNodeGen.ImInternalNodeGen;
-import com.oracle.truffle.r.nodes.unary.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.ops.na.*;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 @RBuiltin(name = "Im", kind = PRIMITIVE, parameterNames = {"z"})
 public abstract class Im extends RBuiltinNode {
 
-    @Child private ImInternalNode im = ImInternalNodeGen.create();
+    public static final UnaryArithmeticFactory IM = ImArithmetic::new;
+
+    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+    @Child private UnaryArithmeticNode imNode = UnaryArithmeticNodeGen.create(IM, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
 
     @Specialization
     protected Object im(Object value) {
-        return im.execute(value);
+        return imNode.execute(boxPrimitive.execute(value));
     }
 
-    public abstract static class ImInternalNode extends UnaryNode {
+    public static class ImArithmetic extends UnaryArithmetic {
 
-        public abstract RDoubleVector executeRDoubleVector(RAbstractComplexVector vector);
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            switch (argumentType) {
+                case Complex:
+                    return RType.Double;
+                default:
+                    return super.calculateResultType(argumentType);
+            }
+        }
 
-        private NACheck check = NACheck.create();
+        @Override
+        public int op(byte op) {
+            return 0;
+        }
 
-        @Specialization
-        protected RDoubleVector im(RAbstractComplexVector vector) {
-            double[] result = new double[vector.getLength()];
-            check.enable(vector);
-            for (int i = 0; i < vector.getLength(); i++) {
-                RComplex c = vector.getDataAt(i);
-                result[i] = check.check(c) ? RRuntime.DOUBLE_NA : c.getImaginaryPart();
-            }
-            return RDataFactory.createDoubleVector(result, check.neverSeenNA());
+        @Override
+        public int op(int op) {
+            return 0;
         }
 
-        @Specialization
-        protected RDoubleVector im(RAbstractDoubleVector vector) {
-            return RDataFactory.createDoubleVector(vector.getLength());
+        @Override
+        public double op(double op) {
+            return 0;
         }
+
+        @Override
+        public RComplex op(double re, double im) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public double opd(double re, double im) {
+            return im;
+        }
+
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 25809dc90c8c82c898a2789d1605ff0c45b8b5fe..a05aab28bb59a36cbdd4cddc208917343cba9a25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -22,12 +22,26 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 
 public class LogFunctions {
     @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"})
@@ -96,128 +110,132 @@ public class LogFunctions {
         protected static double logb(double x, double base) {
             return Math.log(x) / Math.log(base);
         }
+
     }
 
     @RBuiltin(name = "log10", kind = PRIMITIVE, parameterNames = {"x"})
     public abstract static class Log10 extends RBuiltinNode {
 
-        private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
+        @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+        @Child private UnaryArithmeticNode log10Node = UnaryArithmeticNodeGen.create(Log10Arithmetic::new,
+                        RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected RNull log(RNull x) {
-            controlVisibility();
-            throw RError.error(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION);
+        protected Object log10(Object value) {
+            return log10Node.execute(boxPrimitive.execute(value));
         }
 
-        @Specialization
-        protected double log(int value) {
-            controlVisibility();
-            return Math.log10(value);
-        }
+        public static class Log10Arithmetic extends UnaryArithmetic {
 
-        @Specialization
-        protected double log(double value) {
-            controlVisibility();
-            return Math.log10(value);
-        }
+            private static final double LOG_10 = Math.log(10);
 
-        @Specialization
-        protected RDoubleVector log(RIntVector vector) {
-            controlVisibility();
-            double[] resultVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                int inputValue = vector.getDataAt(i);
-                double result = RRuntime.DOUBLE_NA;
-                if (RRuntime.isComplete(inputValue)) {
-                    result = Math.log10(inputValue);
-                }
-                resultVector[i] = result;
+            @Override
+            public int op(byte op) {
+                throw new UnsupportedOperationException();
             }
-            RDoubleVector res = RDataFactory.createDoubleVector(resultVector, vector.isComplete(), vector.getNames(attrProfiles));
-            res.copyRegAttributesFrom(vector);
-            return res;
-        }
 
-        @Specialization
-        protected RDoubleVector log(RDoubleVector vector) {
-            controlVisibility();
-            double[] doubleVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                double value = vector.getDataAt(i);
-                if (RRuntime.isComplete(value)) {
-                    value = Math.log10(value);
-                }
-                doubleVector[i] = value;
+            @Override
+            public int op(int op) {
+                throw new UnsupportedOperationException();
             }
-            RDoubleVector res = RDataFactory.createDoubleVector(doubleVector, vector.isComplete(), vector.getNames(attrProfiles));
-            res.copyRegAttributesFrom(vector);
-            return res;
+
+            @Override
+            public double op(double op) {
+                return Math.log10(op);
+            }
+
+            @Override
+            public RComplex op(double re, double im) {
+                double arg = Math.atan2(im, re);
+                double mod = RComplex.abs(re, im);
+                return RComplex.valueOf(Math.log10(mod), arg / LOG_10);
+            }
+
         }
     }
 
     @RBuiltin(name = "log2", kind = PRIMITIVE, parameterNames = {"x"})
     public abstract static class Log2 extends RBuiltinNode {
 
-        private static final double log2value = Math.log(2);
+        @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+        @Child private UnaryArithmeticNode log2Node = UnaryArithmeticNodeGen.create(Log2Arithmetic::new,
+                        RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected RNull log(RNull x) {
-            controlVisibility();
-            throw RError.error(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION);
+        protected Object log2(Object value) {
+            return log2Node.execute(boxPrimitive.execute(value));
         }
 
-        @Specialization
-        protected double log2(int value) {
-            controlVisibility();
-            return log2((double) value);
-        }
+        public static class Log2Arithmetic extends UnaryArithmetic {
 
-        @Specialization
-        protected double log2(double value) {
-            controlVisibility();
-            return Math.log(value) / log2value;
-        }
+            private static final double LOG_2 = Math.log(2);
 
-        @Specialization
-        protected RDoubleVector log2(RIntVector vector) {
-            controlVisibility();
-            double[] resultVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                int inputValue = vector.getDataAt(i);
-                double result = RRuntime.DOUBLE_NA;
-                if (RRuntime.isComplete(inputValue)) {
-                    result = log2(inputValue);
-                }
-                resultVector[i] = result;
+            @Override
+            public int op(byte op) {
+                throw new UnsupportedOperationException();
             }
-            return RDataFactory.createDoubleVector(resultVector, vector.isComplete());
-        }
 
-        @Specialization
-        protected RDoubleVector log2(RDoubleVector vector) {
-            controlVisibility();
-            double[] doubleVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                double value = vector.getDataAt(i);
-                if (RRuntime.isComplete(value)) {
-                    value = log2(value);
-                }
-                doubleVector[i] = value;
+            @Override
+            public int op(int op) {
+                throw new UnsupportedOperationException();
             }
-            return RDataFactory.createDoubleVector(doubleVector, vector.isComplete());
+
+            @Override
+            public double op(double op) {
+                return Math.log(op) / LOG_2;
+            }
+
+            @Override
+            public RComplex op(double re, double im) {
+                double arg = Math.atan2(im, re);
+                double mod = RComplex.abs(re, im);
+                return RComplex.valueOf(Math.log(mod) / LOG_2, arg / LOG_2);
+            }
+
         }
+
     }
 
     @RBuiltin(name = "log1p", kind = PRIMITIVE, parameterNames = {"x"})
     public abstract static class Log1p extends RBuiltinNode {
 
-        @SuppressWarnings("unused")
+        @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+        @Child private UnaryArithmeticNode log1pNode = UnaryArithmeticNodeGen.create(Log1pArithmetic::new,
+                        RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
+
         @Specialization
-        protected Object log1p(Object x) {
-            throw RError.nyi(this, "log1p");
+        protected Object log1p(Object value) {
+            return log1pNode.execute(boxPrimitive.execute(value));
+        }
+
+        public static class Log1pArithmetic extends UnaryArithmetic {
+
+            @Override
+            public int op(byte op) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int op(int op) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public double op(double op) {
+                return Math.log(1 + op);
+            }
+
+            @Override
+            public RComplex op(double r, double i) {
+                double re = r + 1;
+                double im = i;
+                double arg = Math.atan2(im, re);
+                double mod = RComplex.abs(re, im);
+                return RComplex.valueOf(Math.log(mod), arg);
+            }
+
         }
+
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mod.java
index 4eff9242b9b8477254cf5ee152a8fb069e575b16..00a7e0336ff7ca6a4661e1bbb1b50683874bd9f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mod.java
@@ -22,32 +22,68 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.binary.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.nodes.*;
-import com.oracle.truffle.r.runtime.ops.*;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 
 @RBuiltin(name = "Mod", kind = PRIMITIVE, parameterNames = {"z"})
 public abstract class Mod extends RBuiltinNode {
 
-    @Child private BinaryMapArithmeticFunctionNode pow = new BinaryMapArithmeticFunctionNode(BinaryArithmetic.POW.create());
-    @Child private BinaryMapArithmeticFunctionNode add = new BinaryMapArithmeticFunctionNode(BinaryArithmetic.ADD.create());
-    @Child private Sqrt sqrt = SqrtNodeGen.create(new RNode[1], null, null);
+    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+    @Child private UnaryArithmeticNode modNode = UnaryArithmeticNodeGen.create(ModArithmetic::new, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
 
     @Specialization
-    protected RDoubleVector mod(RAbstractComplexVector vec) {
-        controlVisibility();
-        double[] data = new double[vec.getLength()];
-        for (int i = 0; i < vec.getLength(); i++) {
-            RComplex x = vec.getDataAt(i);
-            data[i] = sqrt.sqrt(add.applyDouble(pow.applyDouble(x.getRealPart(), 2), pow.applyDouble(x.getImaginaryPart(), 2)));
+    protected Object mod(Object value) {
+        return modNode.execute(boxPrimitive.execute(value));
+    }
+
+    public static class ModArithmetic extends UnaryArithmetic {
+
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            switch (argumentType) {
+                case Complex:
+                    return RType.Double;
+                default:
+                    return super.calculateResultType(argumentType);
+            }
+        }
+
+        @Override
+        public int op(byte op) {
+            return op;
+        }
+
+        @Override
+        public int op(int op) {
+            return op;
         }
-        return RDataFactory.createDoubleVector(data, RDataFactory.COMPLETE_VECTOR);
+
+        @Override
+        public double op(double op) {
+            return op;
+        }
+
+        @Override
+        public RComplex op(double re, double im) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public double opd(double re, double im) {
+            return RComplex.abs(re, im);
+        }
+
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
index f522736eca13059849b483f899a3d28d6e06d9d5..576f4e893cab89b10655d26e6038171ac88dfec3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
@@ -31,15 +31,11 @@ import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.*;
-import com.oracle.truffle.r.nodes.builtin.base.Im.ImInternalNode;
-import com.oracle.truffle.r.nodes.builtin.base.ImNodeGen.ImInternalNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrettyPrinterSingleListElementNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrettyPrinterSingleVectorElementNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintDimNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintVector2DimNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintVectorMultiDimNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.Re.ReInternalNode;
-import com.oracle.truffle.r.nodes.builtin.base.ReNodeGen.ReInternalNodeGen;
 import com.oracle.truffle.r.nodes.function.*;
 import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.runtime.*;
@@ -76,8 +72,8 @@ public abstract class PrettyPrinterNode extends RNode {
     @Child private PrettyPrinterSingleVectorElementNode singleVectorElementPrettyPrinter;
     @Child private PrintVectorMultiDimNode multiDimPrinter;
 
-    @Child private ReInternalNode re;
-    @Child private ImInternalNode im;
+    @Child private UnaryArithmeticNode re;
+    @Child private UnaryArithmeticNode im;
 
     @Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode();
 
@@ -901,12 +897,12 @@ public abstract class PrettyPrinterNode extends RNode {
         if (re == null) {
             // the two are allocated side by side; checking for re is sufficient
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            re = insert(ReInternalNodeGen.create());
-            im = insert(ImInternalNodeGen.create());
+            re = insert(UnaryArithmeticNodeGen.create(Re.RE, RError.Message.NON_NUMERIC_MATH, RType.Double));
+            im = insert(UnaryArithmeticNodeGen.create(Im.IM, RError.Message.NON_NUMERIC_MATH, RType.Double));
         }
 
-        RDoubleVector realParts = re.executeRDoubleVector(operand);
-        RDoubleVector imaginaryParts = im.executeRDoubleVector(operand);
+        RAbstractDoubleVector realParts = (RAbstractDoubleVector) re.execute(operand);
+        RAbstractDoubleVector imaginaryParts = (RAbstractDoubleVector) im.execute(operand);
 
         int length = operand.getLength();
         String[] realValues = new String[length];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Re.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Re.java
index 639cbfe8793f777bc2ff7c773662ba095c44bea3..3a9514b24c87b8e564dca48e6fba1f17a6f7aab9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Re.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Re.java
@@ -22,47 +22,71 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.nodes.builtin.base.ReNodeGen.ReInternalNodeGen;
-import com.oracle.truffle.r.nodes.unary.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.ops.na.*;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 @RBuiltin(name = "Re", kind = PRIMITIVE, parameterNames = {"z"})
 public abstract class Re extends RBuiltinNode {
 
-    @Child private ReInternalNode re = ReInternalNodeGen.create();
+    public static final UnaryArithmeticFactory RE = ReArithmetic::new;
+
+    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+    @Child private UnaryArithmeticNode reNode = UnaryArithmeticNodeGen.create(RE, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, RType.Double);
 
     @Specialization
     protected Object re(Object value) {
-        return re.execute(value);
+        return reNode.execute(boxPrimitive.execute(value));
     }
 
-    public abstract static class ReInternalNode extends UnaryNode {
+    public static class ReArithmetic extends UnaryArithmetic {
 
-        public abstract RDoubleVector executeRDoubleVector(Object value);
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            switch (argumentType) {
+                case Complex:
+                    return RType.Double;
+                default:
+                    return super.calculateResultType(argumentType);
+            }
+        }
 
-        private NACheck check = NACheck.create();
+        @Override
+        public int op(byte op) {
+            return op;
+        }
 
-        @Specialization
-        protected RDoubleVector re(RAbstractComplexVector vector) {
-            double[] result = new double[vector.getLength()];
-            check.enable(vector);
-            for (int i = 0; i < vector.getLength(); i++) {
-                result[i] = vector.getDataAt(i).getRealPart();
-                check.check(result[i]);
-            }
-            return RDataFactory.createDoubleVector(result, check.neverSeenNA());
+        @Override
+        public int op(int op) {
+            return op;
         }
 
-        @Specialization
-        protected RDoubleVector re(RAbstractDoubleVector vector) {
-            return (RDoubleVector) vector.copy();
+        @Override
+        public double op(double op) {
+            return op;
         }
+
+        @Override
+        public RComplex op(double re, double im) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public double opd(double re, double im) {
+            return re;
+        }
+
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
index 5662f28fcec5ded54024549d9107e3ca4b6d8074..6e131ecbe651a596e65b1e6135a5d733ebf4c5e5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
@@ -22,20 +22,32 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.r.nodes.builtin.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
-import com.oracle.truffle.r.runtime.ops.*;
-import com.oracle.truffle.r.runtime.ops.na.*;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
+import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "round", kind = PRIMITIVE, parameterNames = {"x", "digits"})
 public abstract class Round extends RBuiltinNode {
 
-    @Child private UnaryArithmetic roundOp = UnaryArithmetic.ROUND.create();
+    public static final UnaryArithmeticFactory ROUND = RoundArithmetic::new;
+
+    @Child private RoundArithmetic roundOp = new RoundArithmetic();
 
     private final NACheck check = NACheck.create();
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
@@ -154,4 +166,177 @@ public abstract class Round extends RBuiltinNode {
         return ret;
     }
 
+    public static class RoundArithmetic extends UnaryArithmetic {
+
+        @Child private BinaryArithmetic pow;
+
+        @Override
+        public int op(int op) {
+            return op;
+        }
+
+        @Override
+        public double op(double op) {
+            return Math.rint(op);
+        }
+
+        @Override
+        public int op(byte op) {
+            return op;
+        }
+
+        @Override
+        public RComplex op(double re, double im) {
+            return RDataFactory.createComplex(op(re), op(im));
+        }
+
+        public double opd(double op, int digits) {
+            return fround(op, digits);
+        }
+
+        public RComplex opd(double re, double im, int digits) {
+            return zrround(re, im, digits);
+        }
+
+        // The logic for fround and zrround (z_rround) is derived from GNU R.
+
+        private static final int F_MAX_DIGITS = 308; // IEEE constant
+
+        private double fround(double x, double digits) {
+            double pow10;
+            double sgn;
+            double intx;
+            int dig;
+
+            if (Double.isNaN(x) || Double.isNaN(digits)) {
+                return x + digits;
+            }
+            if (!RRuntime.isFinite(x)) {
+                return x;
+            }
+            if (digits == Double.POSITIVE_INFINITY) {
+                return x;
+            } else if (digits == Double.NEGATIVE_INFINITY) {
+                return 0.0;
+            }
+
+            double dd = digits;
+            double xx = x;
+
+            if (dd > F_MAX_DIGITS) {
+                dd = F_MAX_DIGITS;
+            }
+
+            dig = (int) Math.floor(dd + 0.5);
+            if (xx < 0.0) {
+                sgn = -1.0;
+                xx = -xx;
+            } else {
+                sgn = 1.0;
+            }
+
+            if (dig == 0) {
+                return sgn * op(xx);
+            } else if (dig > 0) {
+                pow10 = rpowdi(10.0, dig);
+                intx = Math.floor(xx);
+                // System.out.println(String.format("X %.22f RINT1 %.22f POW10 %.22f INTX %.22f",
+                // new BigDecimal(x),
+                // new BigDecimal(Math.rint((xx - intx) * pow10)), new BigDecimal(pow10),
+                // new BigDecimal(intx)));
+                return sgn * (intx + Math.rint((xx - intx) * pow10) / pow10);
+            } else {
+                pow10 = rpowdi(10.0, -dig);
+                // System.out.println(String.format("RINT2 %.22f", new BigDecimal(Math.rint(xx /
+                // pow10))));
+                return sgn * Math.rint(xx / pow10) * pow10;
+            }
+        }
+
+        private double rpowdi(double x, int n) {
+            double result = 1.0;
+
+            if (Double.isNaN(x)) {
+                return x;
+            }
+            if (n != 0) {
+                if (!RRuntime.isFinite(x)) {
+                    return rpow(x, n);
+                }
+                int nn = n;
+                double xx = x;
+                boolean isNeg = (n < 0);
+                if (isNeg) {
+                    nn = -nn;
+                }
+                for (;;) {
+                    if ((nn & 1) != 0) {
+                        result *= xx;
+                    }
+                    if ((nn >>= 1) != 0) {
+                        xx *= xx;
+                    } else {
+                        break;
+                    }
+                }
+                if (isNeg) {
+                    result = 1.0 / result;
+                }
+            }
+            return result;
+        }
+
+        private static double myfmod(double x1, double x2) {
+            double q = x1 / x2;
+            return x1 - Math.floor(q) * x2;
+        }
+
+        private double rpow(double x, double y) {
+            if (x == 1.0 || y == 0.0) {
+                return 1.0;
+            }
+            if (x == 0.0) {
+                if (y > 0.0) {
+                    return 0.0;
+                }
+                return Double.POSITIVE_INFINITY;
+            }
+            if (RRuntime.isFinite(x) && RRuntime.isFinite(y)) {
+                if (pow == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    pow = insert(BinaryArithmetic.POW.create());
+                }
+                return pow.op(x, y);
+            }
+            if (Double.isNaN(x) || Double.isNaN(y)) {
+                return x + y; // assuming IEEE 754; otherwise return NaN
+            }
+            if (!RRuntime.isFinite(x)) {
+                if (x > 0) { /* Inf ^ y */
+                    return (y < 0.0) ? 0.0 : Double.POSITIVE_INFINITY;
+                } else { /* (-Inf) ^ y */
+                    if (RRuntime.isFinite(y) && y == Math.floor(y)) { /* (-Inf) ^ n */
+                        return (y < 0.0) ? 0.0 : (myfmod(y, 2.0) != 0.0 ? x : -x);
+                    }
+                }
+            }
+            if (!RRuntime.isFinite(y)) {
+                if (x >= 0) {
+                    if (y > 0) { /* y == +Inf */
+                        return (x >= 1) ? Double.POSITIVE_INFINITY : 0.0;
+                    } else {
+                        /* y == -Inf */
+                        return (x < 1) ? Double.POSITIVE_INFINITY : 0.0;
+                    }
+                }
+            }
+            // all other cases: (-Inf)^{+-Inf, non-int}; (neg)^{+-Inf}
+            return Double.NaN;
+        }
+
+        private RComplex zrround(double re, double im, int digits) {
+            return RDataFactory.createComplex(fround(re, digits), fround(im, digits));
+        }
+
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index c173c6898e62415d1f5d20af1acb9b022df9934a..d8658e3fa8c0c86917b0ea733657c5918a33eab9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -31,15 +31,19 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNodeGen;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
 import com.oracle.truffle.r.runtime.RBuiltin;
 import com.oracle.truffle.r.runtime.RBuiltinKind;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -47,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class TrigExpFunctions {
@@ -137,62 +142,90 @@ public class TrigExpFunctions {
     }
 
     @RBuiltin(name = "exp", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x"})
-    public abstract static class Exp extends AdapterCall1 {
+    public abstract static class Exp extends RBuiltinNode {
 
         @Child private BinaryArithmetic calculatePowNode;
+        @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+        @Child private UnaryArithmeticNode expNode = UnaryArithmeticNodeGen.create(ExpArithmetic::new, RType.Double,
+                        RError.Message.ARGUMENTS_PASSED_0_1, new Object[]{getRBuiltin().name()});
 
-        public RComplex complexOp(RComplex rComplex) {
-            if (calculatePowNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                calculatePowNode = insert(BinaryArithmetic.POW.create());
-            }
-            return calculatePowNode.op(Math.E, 0, rComplex.getRealPart(), rComplex.getImaginaryPart());
+        @Specialization
+        protected Object exp(Object value) {
+            return expNode.execute(boxPrimitive.execute(value));
         }
 
-        @Override
-        protected double op(double x) {
-            return Math.exp(x);
-        }
+        public class ExpArithmetic extends UnaryArithmetic {
 
-        @Specialization
-        protected RComplex exp(RComplex power) {
-            controlVisibility();
-            return complexOp(power);
-        }
+            @Override
+            public int op(byte op) {
+                throw new UnsupportedOperationException();
+            }
 
-        @Specialization
-        protected RComplexVector exp(RComplexVector powersVector, //
-                        @Cached("createCountingProfile()") LoopConditionProfile profile) {
-            controlVisibility();
-            int length = powersVector.getLength();
-            double[] result = new double[length * 2];
-            reportWork(length);
-            profile.profileCounted(length);
-            for (int i = 0; profile.inject(i < length); i++) {
-                RComplex rComplexResult = complexOp(powersVector.getDataAt(i));
-                result[2 * i] = rComplexResult.getRealPart();
-                result[2 * i + 1] = rComplexResult.getImaginaryPart();
+            @Override
+            public int op(int op) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public double op(double op) {
+                return Math.exp(op);
+            }
+
+            @Override
+            public RComplex op(double re, double im) {
+                if (calculatePowNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    calculatePowNode = insert(BinaryArithmetic.POW.create());
+                }
+                return calculatePowNode.op(Math.E, 0, re, im);
             }
-            return RDataFactory.createComplexVector(result, true);
+
         }
 
     }
 
     @RBuiltin(name = "expm1", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x"})
-    public abstract static class ExpM1 extends Exp {
+    public abstract static class ExpM1 extends RBuiltinNode {
 
         @Child private BinaryArithmetic calculatePowNode;
+        @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
+        @Child private UnaryArithmeticNode expm1Node = UnaryArithmeticNodeGen.create(ExpM1Arithmetic::new, RType.Double,
+                        RError.Message.ARGUMENTS_PASSED_0_1, new Object[]{getRBuiltin().name()});
 
-        @Override
-        public RComplex complexOp(RComplex rComplex) {
-            RComplex intermediate = super.complexOp(rComplex);
-            return RDataFactory.createComplex(intermediate.getRealPart() - 1d, intermediate.getImaginaryPart());
+        @Specialization
+        protected Object exp(Object value) {
+            return expm1Node.execute(boxPrimitive.execute(value));
         }
 
-        @Override
-        protected double op(double x) {
-            return Math.expm1(x);
+        public class ExpM1Arithmetic extends UnaryArithmetic {
+
+            @Override
+            public int op(byte op) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int op(int op) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public double op(double op) {
+                return Math.expm1(op);
+            }
+
+            @Override
+            public RComplex op(double re, double im) {
+                if (calculatePowNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    calculatePowNode = insert(BinaryArithmetic.POW.create());
+                }
+                RComplex x = calculatePowNode.op(Math.E, 0, re, im);
+                return RDataFactory.createComplex(x.getRealPart() - 1d, x.getImaginaryPart());
+            }
+
         }
+
     }
 
     @RBuiltin(name = "sin", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x"})
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
index afb06fa9afe69952b8eeb2115c87bfb9d02c8b61..39fe96a09b211597d9fc8c5acbc700f82a6df1c2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
@@ -32,11 +32,26 @@ import com.oracle.truffle.r.runtime.ops.*;
 @RBuiltin(name = "trunc", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x"})
 public abstract class Trunc extends RBuiltinNode {
 
+    public static final UnaryArithmeticFactory TRUNC = TruncArithmetic::new;
+
     @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
-    @Child private UnaryArithmeticNode trunc = UnaryArithmeticNodeGen.create(UnaryArithmetic.TRUNC, RError.Message.NON_NUMERIC_MATH, RType.Double);
+    @Child private UnaryArithmeticNode trunc = UnaryArithmeticNodeGen.create(TRUNC, RError.Message.NON_NUMERIC_MATH, RType.Double);
 
     @Specialization
     protected Object trunc(Object value) {
         return trunc.execute(boxPrimitive.execute(value));
     }
+
+    public static class TruncArithmetic extends Round.RoundArithmetic {
+
+        @Override
+        public double op(double op) {
+            if (op > 0) {
+                return Math.floor(op);
+            } else {
+                return Math.ceil(op);
+            }
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
index f53d8e9e280f3c061b4ca4f3d4573ca7c702ade9..646179aff8a119f8cf0f47a7cbeac33d19964b7d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
@@ -16,6 +16,8 @@ import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
 
 import java.io.IOException;
 
+import com.oracle.truffle.r.nodes.builtin.base.Round;
+import com.oracle.truffle.r.nodes.builtin.base.Round.RoundArithmetic;
 import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.ScientificDouble;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -357,7 +359,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
         return new ComplexVectorMetrics(wr, dr, er, wi, di, ei);
     }
 
-    private static UnaryArithmetic round = UnaryArithmetic.ROUND.create();
+    private static RoundArithmetic round = new Round.RoundArithmetic();
 
     private static RComplex zprecr(RComplex x, int digits) {
         return round.opd(x.getRealPart(), x.getImaginaryPart(), digits);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
index 55c45f16f9030ef4881f6f3e031934c5dfc9bf4a..8841af79f1febe045956afd977160d03d5688f67 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
@@ -35,6 +35,9 @@ import org.junit.*;
 import org.junit.experimental.theories.*;
 import org.junit.runner.*;
 
+import com.oracle.truffle.r.nodes.builtin.base.Ceiling;
+import com.oracle.truffle.r.nodes.builtin.base.Floor;
+import com.oracle.truffle.r.nodes.builtin.base.Round;
 import com.oracle.truffle.r.nodes.test.TestUtilities.NodeHandle;
 import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.runtime.*;
@@ -50,6 +53,8 @@ import com.oracle.truffle.r.runtime.ops.*;
 @RunWith(Theories.class)
 public class UnaryArithmeticNodeTest extends BinaryVectorTest {
 
+    public static final UnaryArithmeticFactory[] ALL = new UnaryArithmeticFactory[]{NEGATE, Round.ROUND, Floor.FLOOR, Ceiling.CEILING, PLUS};
+
     @DataPoints public static final UnaryArithmeticFactory[] UNARY = ALL;
 
     @Theory
@@ -147,8 +152,8 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
     public void testSequenceFolding() {
         assertFold(true, createIntSequence(1, 3, 10), NEGATE);
         assertFold(true, createDoubleSequence(1, 3, 10), NEGATE);
-        assertFold(false, createIntSequence(1, 3, 10), ROUND, FLOOR, CEILING);
-        assertFold(false, createDoubleSequence(1, 3, 10), ROUND, FLOOR, CEILING);
+        assertFold(false, createIntSequence(1, 3, 10), Round.ROUND, Floor.FLOOR, Ceiling.CEILING);
+        assertFold(false, createDoubleSequence(1, 3, 10), Round.ROUND, Floor.FLOOR, Ceiling.CEILING);
     }
 
     @Theory
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapFunctionNode.java
index a1097e26fb6599aacd7dd1d4cf5ca366cd8ace63..f78762015966832779825a6a8722a6839449f8ea 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapFunctionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapFunctionNode.java
@@ -63,6 +63,10 @@ public abstract class UnaryMapFunctionNode extends RBaseNode {
         throw RInternalError.shouldNotReachHere();
     }
 
+    public double applyDouble(RComplex operand) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
     public String applyCharacter(String operand) {
         throw RInternalError.shouldNotReachHere();
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java
index 035657c065d8fd3cd9720d1c33eafac485531fae..1bbb2d8874b928c46d3a34a80f7e8cd4c23395ed 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java
@@ -111,7 +111,14 @@ public final class UnaryMapNode extends RBaseNode {
             case Double:
                 return scalarNode.applyDouble(((RAbstractDoubleVector) operand).getDataAt(0));
             case Complex:
-                return scalarNode.applyComplex(((RAbstractComplexVector) operand).getDataAt(0));
+                switch (getResultType()) {
+                    case Double:
+                        return scalarNode.applyDouble(((RAbstractComplexVector) operand).getDataAt(0));
+                    case Complex:
+                        return scalarNode.applyComplex(((RAbstractComplexVector) operand).getDataAt(0));
+                    default:
+                        throw RInternalError.shouldNotReachHere();
+                }
             default:
                 throw RInternalError.shouldNotReachHere();
         }
@@ -188,6 +195,12 @@ public final class UnaryMapNode extends RBaseNode {
             result[resultIndex << 1] = value.getRealPart();
             result[(resultIndex << 1) + 1] = value.getImaginaryPart();
         };
+
+        private static final MapIndexedAction<double[], RAbstractComplexVector> DOUBLE_COMPLEX = //
+        (arithmetic, result, resultIndex, left, leftIndex) -> {
+            result[resultIndex] = arithmetic.applyDouble(left.getDataAt(leftIndex));
+        };
+
         private static final MapIndexedAction<String[], RAbstractStringVector> CHARACTER = //
         (arithmetic, result, resultIndex, left, leftIndex) -> {
             result[resultIndex] = arithmetic.applyCharacter(left.getDataAt(leftIndex));
@@ -232,7 +245,14 @@ public final class UnaryMapNode extends RBaseNode {
                 case Double:
                     return DOUBLE;
                 case Complex:
-                    return COMPLEX;
+                    switch (resultType) {
+                        case Double:
+                            return DOUBLE_COMPLEX;
+                        case Complex:
+                            return COMPLEX;
+                        default:
+                            throw RInternalError.shouldNotReachHere();
+                    }
                 case Character:
                     return CHARACTER;
                 default:
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ScalarUnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ScalarUnaryArithmeticNode.java
index 00692250a8f5f1d907c5d842ab59043d6131eecd..91c516c6d6adb3ae48ef588d3c138762745822bb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ScalarUnaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ScalarUnaryArithmeticNode.java
@@ -74,6 +74,14 @@ public class ScalarUnaryArithmeticNode extends UnaryMapNAFunctionNode {
         return arithmetic.op(operand);
     }
 
+    @Override
+    public final double applyDouble(RComplex operand) {
+        if (operandNACheck.check(operand)) {
+            return RRuntime.DOUBLE_NA;
+        }
+        return arithmetic.opd(operand.getRealPart(), operand.getImaginaryPart());
+    }
+
     @Override
     public final RComplex applyComplex(RComplex operand) {
         if (operandNACheck.check(operand)) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
index 5c9d19b4773c1496f724cbcc82033e15b2078039..155a6fa3dc100ed325263a70c807cb1296f2c532 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
@@ -35,12 +35,21 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
     protected final UnaryArithmeticFactory unary;
     private final Message error;
+    private final Object errorArgs;
     protected final RType minPrecedence;
 
+    public UnaryArithmeticNode(UnaryArithmeticFactory factory, RType minPrecedence, Message error, Object... errorArgs) {
+        this.unary = factory;
+        this.error = error;
+        this.errorArgs = errorArgs;
+        this.minPrecedence = minPrecedence;
+    }
+
     public UnaryArithmeticNode(UnaryArithmeticFactory factory, Message error, RType minPrecedence) {
         this.unary = factory;
         this.error = error;
         this.minPrecedence = minPrecedence;
+        this.errorArgs = null;
     }
 
     public UnaryArithmeticNode(UnaryArithmeticFactory factory, Message error) {
@@ -65,7 +74,8 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
             RType operandType = castOperand.getRType();
             if (operandType.isNumeric()) {
                 RType type = RType.maxPrecedence(operandType, minPrecedence);
-                return UnaryMapNode.create(new ScalarUnaryArithmeticNode(arithmetic), castOperand, type, type);
+                RType resultType = arithmetic.calculateResultType(type);
+                return UnaryMapNode.create(new ScalarUnaryArithmeticNode(arithmetic), castOperand, type, resultType);
             }
         }
         return null;
@@ -86,7 +96,11 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
     @Fallback
     protected Object invalidArgType(@SuppressWarnings("unused") Object operand) {
-        throw RError.error(this, error);
+        if (errorArgs == null) {
+            throw RError.error(this, error);
+        } else {
+            throw RError.error(this, error, (Object[]) errorArgs);
+        }
     }
 
     protected static final class GenericNumericVectorNode extends TruffleBoundaryNode {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
index c0c25521a54957d451dddd4893d975ea3e54aeba..f7da0929205e89dc9ede7e310b13917dc22b9b5f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
@@ -123,16 +123,21 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec
     }
 
     public double abs() {
-        if (!RRuntime.isFinite(realPart) || !RRuntime.isFinite(imaginaryPart)) {
-            if (Double.isInfinite(realPart) || Double.isInfinite(imaginaryPart)) {
+        return abs(realPart, imaginaryPart);
+    }
+
+    public static double abs(double re, double im) {
+        if (!RRuntime.isFinite(re) || !RRuntime.isFinite(im)) {
+            if (Double.isInfinite(re) || Double.isInfinite(im)) {
                 return Double.POSITIVE_INFINITY;
-            } else if (Double.isNaN(imaginaryPart)) {
-                return imaginaryPart;
+            } else if (Double.isNaN(im)) {
+                return im;
             } else {
-                return realPart;
+                return re;
             }
         } else {
-            return Math.sqrt(realPart * realPart + imaginaryPart * imaginaryPart);
+            return Math.sqrt(re * re + im * im);
         }
     }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
index daaa8791f073d939e5bc5aeb5804cc742802b43d..680b5ea18c442c96a58ae02667dfd93b6e4de05b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
@@ -13,36 +13,35 @@
  */
 package com.oracle.truffle.r.runtime.ops;
 
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 
 public abstract class UnaryArithmetic extends Operation {
 
     public static final UnaryArithmeticFactory NEGATE = Negate::new;
-    public static final UnaryArithmeticFactory ROUND = Round::new;
-    public static final UnaryArithmeticFactory FLOOR = Floor::new;
-    public static final UnaryArithmeticFactory TRUNC = Trunc::new;
-    public static final UnaryArithmeticFactory CEILING = Ceiling::new;
     public static final UnaryArithmeticFactory PLUS = Plus::new;
-    public static final UnaryArithmeticFactory[] ALL = new UnaryArithmeticFactory[]{NEGATE, ROUND, FLOOR, CEILING, PLUS};
 
     public UnaryArithmetic() {
         super(false, false);
     }
 
+    public RType calculateResultType(RType argumentType) {
+        return argumentType;
+    }
+
     public abstract int op(byte op);
 
     public abstract int op(int op);
 
     public abstract double op(double op);
 
-    public abstract double opd(double op, int digits);
-
     public abstract RComplex op(double re, double im);
 
-    public abstract RComplex opd(double re, double im, int digits);
+    @SuppressWarnings("unused")
+    public double opd(double re, double im) {
+        throw new UnsupportedOperationException();
+    }
 
     public static class Negate extends UnaryArithmetic {
 
@@ -66,18 +65,6 @@ public abstract class UnaryArithmetic extends Operation {
             return RDataFactory.createComplex(op(re), op(im));
         }
 
-        @Override
-        @TruffleBoundary
-        public double opd(double op, int digits) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        @TruffleBoundary
-        public RComplex opd(double re, double im, int digits) {
-            throw new UnsupportedOperationException();
-        }
-
     }
 
     public static class Plus extends UnaryArithmetic {
@@ -102,222 +89,6 @@ public abstract class UnaryArithmetic extends Operation {
             return RDataFactory.createComplex(re, im);
         }
 
-        @Override
-        @TruffleBoundary
-        public double opd(double op, int digits) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        @TruffleBoundary
-        public RComplex opd(double re, double im, int digits) {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-    public static class Round extends UnaryArithmetic {
-
-        @Child private BinaryArithmetic pow;
-
-        @Override
-        public int op(int op) {
-            return op;
-        }
-
-        @Override
-        public double op(double op) {
-            return Math.rint(op);
-        }
-
-        @Override
-        public int op(byte op) {
-            return op;
-        }
-
-        @Override
-        public RComplex op(double re, double im) {
-            return RDataFactory.createComplex(op(re), op(im));
-        }
-
-        @Override
-        public double opd(double op, int digits) {
-            return fround(op, digits);
-        }
-
-        @Override
-        public RComplex opd(double re, double im, int digits) {
-            return zrround(re, im, digits);
-        }
-
-        // The logic for fround and zrround (z_rround) is derived from GNU R.
-
-        private static final int F_MAX_DIGITS = 308; // IEEE constant
-
-        private double fround(double x, double digits) {
-            double pow10;
-            double sgn;
-            double intx;
-            int dig;
-
-            if (Double.isNaN(x) || Double.isNaN(digits)) {
-                return x + digits;
-            }
-            if (!RRuntime.isFinite(x)) {
-                return x;
-            }
-            if (digits == Double.POSITIVE_INFINITY) {
-                return x;
-            } else if (digits == Double.NEGATIVE_INFINITY) {
-                return 0.0;
-            }
-
-            double dd = digits;
-            double xx = x;
-
-            if (dd > F_MAX_DIGITS) {
-                dd = F_MAX_DIGITS;
-            }
-
-            dig = (int) Math.floor(dd + 0.5);
-            if (xx < 0.0) {
-                sgn = -1.0;
-                xx = -xx;
-            } else {
-                sgn = 1.0;
-            }
-
-            if (dig == 0) {
-                return sgn * op(xx);
-            } else if (dig > 0) {
-                pow10 = rpowdi(10.0, dig);
-                intx = Math.floor(xx);
-                // System.out.println(String.format("X %.22f RINT1 %.22f POW10 %.22f INTX %.22f",
-                // new BigDecimal(x),
-                // new BigDecimal(Math.rint((xx - intx) * pow10)), new BigDecimal(pow10),
-                // new BigDecimal(intx)));
-                return sgn * (intx + Math.rint((xx - intx) * pow10) / pow10);
-            } else {
-                pow10 = rpowdi(10.0, -dig);
-                // System.out.println(String.format("RINT2 %.22f", new BigDecimal(Math.rint(xx /
-                // pow10))));
-                return sgn * Math.rint(xx / pow10) * pow10;
-            }
-        }
-
-        private double rpowdi(double x, int n) {
-            double result = 1.0;
-
-            if (Double.isNaN(x)) {
-                return x;
-            }
-            if (n != 0) {
-                if (!RRuntime.isFinite(x)) {
-                    return rpow(x, n);
-                }
-                int nn = n;
-                double xx = x;
-                boolean isNeg = (n < 0);
-                if (isNeg) {
-                    nn = -nn;
-                }
-                for (;;) {
-                    if ((nn & 1) != 0) {
-                        result *= xx;
-                    }
-                    if ((nn >>= 1) != 0) {
-                        xx *= xx;
-                    } else {
-                        break;
-                    }
-                }
-                if (isNeg) {
-                    result = 1.0 / result;
-                }
-            }
-            return result;
-        }
-
-        private static double myfmod(double x1, double x2) {
-            double q = x1 / x2;
-            return x1 - Math.floor(q) * x2;
-        }
-
-        private double rpow(double x, double y) {
-            if (x == 1.0 || y == 0.0) {
-                return 1.0;
-            }
-            if (x == 0.0) {
-                if (y > 0.0) {
-                    return 0.0;
-                }
-                return Double.POSITIVE_INFINITY;
-            }
-            if (RRuntime.isFinite(x) && RRuntime.isFinite(y)) {
-                if (pow == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    pow = insert(BinaryArithmetic.POW.create());
-                }
-                return pow.op(x, y);
-            }
-            if (Double.isNaN(x) || Double.isNaN(y)) {
-                return x + y; // assuming IEEE 754; otherwise return NaN
-            }
-            if (!RRuntime.isFinite(x)) {
-                if (x > 0) { /* Inf ^ y */
-                    return (y < 0.0) ? 0.0 : Double.POSITIVE_INFINITY;
-                } else { /* (-Inf) ^ y */
-                    if (RRuntime.isFinite(y) && y == Math.floor(y)) { /* (-Inf) ^ n */
-                        return (y < 0.0) ? 0.0 : (myfmod(y, 2.0) != 0.0 ? x : -x);
-                    }
-                }
-            }
-            if (!RRuntime.isFinite(y)) {
-                if (x >= 0) {
-                    if (y > 0) { /* y == +Inf */
-                        return (x >= 1) ? Double.POSITIVE_INFINITY : 0.0;
-                    } else {
-                        /* y == -Inf */
-                        return (x < 1) ? Double.POSITIVE_INFINITY : 0.0;
-                    }
-                }
-            }
-            // all other cases: (-Inf)^{+-Inf, non-int}; (neg)^{+-Inf}
-            return Double.NaN;
-        }
-
-        private RComplex zrround(double re, double im, int digits) {
-            return RDataFactory.createComplex(fround(re, digits), fround(im, digits));
-        }
-
-    }
-
-    public static class Floor extends Round {
-
-        @Override
-        public double op(double op) {
-            return Math.floor(op);
-        }
-    }
-
-    public static class Trunc extends Round {
-
-        @Override
-        public double op(double op) {
-            if (op > 0) {
-                return Math.floor(op);
-            } else {
-                return Math.ceil(op);
-            }
-        }
-    }
-
-    public static class Ceiling extends Round {
-
-        @Override
-        public double op(double op) {
-            return Math.ceil(op);
-        }
     }
 
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 6b5087fcb513526860b96e8f36080762c09f89f5..c8eac9c7ea54815f375cfb0ea98d5514ff2750c2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -605,6 +605,10 @@ Error: unexpected symbol in "argv <- list(c('* Edit the help file skeletons in '
 #{ Im(as.double(NA)) }
 [1] 0
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Im.testIm
+#{ Im(as.raw(12)) }
+Error in Im(as.raw(12)) : non-numeric argument to function
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Im.testIm
 #{ Im(c(1+1i,2-2i)) }
 [1]  1 -2
@@ -890,6 +894,14 @@ $vt
 [1,]   -2  1.5
 [2,]    1 -0.5
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Mod.testMod
+#{ Mod(as.raw(12)) }
+Error in Mod(as.raw(12)) : non-numeric argument to function
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Mod.testMod
+#{ is.integer(Mod(FALSE) }
+Error: unexpected '}' in "{ is.integer(Mod(FALSE) }"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Mod.testMod
 #{ round(Mod(1+1i)*10000) }
 [1] 14142
@@ -1074,6 +1086,10 @@ function (..., recursive = FALSE)  .Primitive("c")
 #{ Re(as.double(NA)) }
 [1] NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Re.testRe
+#{ Re(as.raw(12)) }
+Error in Re(as.raw(12)) : non-numeric argument to function
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Re.testRe
 #{ Re(c(1+1i,2-2i)) }
 [1] 1 2
@@ -1423,6 +1439,10 @@ Error in abs(NULL) : non-numeric argument to mathematical function
 #{ abs(c(1L, 2L, 3L)) }
 [1] 1 2 3
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testAbs
+#{ is.integer(abs(FALSE) }
+Error: unexpected '}' in "{ is.integer(abs(FALSE) }"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs1
 #argv <- list(c(0.9, 0.1, 0.3, 0.5, 0.7, 0.9, 0.1, 0.3, 0.5));abs(argv[[1]]);
 [1] 0.9 0.1 0.3 0.5 0.7 0.9 0.1 0.3 0.5
@@ -26899,6 +26919,10 @@ Error in eval(expr, envir, enclos) : object 'y' not found
 #{ log10(c(0,1)) }
 [1] -Inf    0
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log10.testLog10
+#{ log10(c(1+1i, -1-1i)) }
+[1] 0.150515+0.3410941i 0.150515-1.0232823i
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_log10.testLog10
 #{ m <- matrix(1:4, nrow=2) ; round( log10(m), digits=5 )  }
         [,1]    [,2]
@@ -26997,10 +27021,19 @@ wha
 #argv <- list(-7e-04);log1p(argv[[1]]);
 [1] -0.0007002451
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log1p.testlog1p3
+#log1p(c(1+1i,-1-1i))
+Error in log1p(c(1 + (0+1i), -1 - (0+1i))) :
+  unimplemented complex function
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_log2.testLog2
 #{ as.integer(log2(6)*1000000) } 
 [1] 2584962
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log2.testLog2
+#{ log10(c(1+1i, -1-1i)) }
+[1] 0.150515+0.3410941i 0.150515-1.0232823i
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_log2.testLog2
 #{ log2(0) }
 [1] -Inf
@@ -43269,6 +43302,10 @@ In sqrt(argv[[1]]) : NaNs produced
 #argv <- list(0+1i);sqrt(argv[[1]]);
 [1] 0.7071068+0.7071068i
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt12
+#argv <- list(c(TRUE, FALSE));sqrt(argv[[1]]);
+[1] 1 0
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt2
 #argv <- list(numeric(0));sqrt(argv[[1]]);
 numeric(0)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java
index c6c398e78fcbb91ab8a33d7b23f5933f340174de..6538af0b3905acb29eb387d208ce305a87c51955 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java
@@ -24,12 +24,12 @@ public class TestBuiltin_Im extends TestBase {
 
     @Test
     public void testIm2() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));Im(argv[[1]]);");
+        assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));Im(argv[[1]]);");
     }
 
     @Test
     public void testIm3() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE);Im(argv[[1]]);");
+        assertEval("argv <- list(FALSE);Im(argv[[1]]);");
     }
 
     @Test
@@ -39,8 +39,7 @@ public class TestBuiltin_Im extends TestBase {
 
     @Test
     public void testIm5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(3+2i, 3+2i, NA, 3+2i, 3+2i, 3+2i, 3+2i, 3+2i, 4-5i, 3-5i, NA, NA, 2-5i, 3-5i, 4-5i, 5-5i), .Dim = c(8L, 2L), .Dimnames = list(NULL, c('x1', 'x2'))));Im(argv[[1]]);");
+        assertEval("argv <- list(structure(c(3+2i, 3+2i, NA, 3+2i, 3+2i, 3+2i, 3+2i, 3+2i, 4-5i, 3-5i, NA, NA, 2-5i, 3-5i, 4-5i, 5-5i), .Dim = c(8L, 2L), .Dimnames = list(NULL, c('x1', 'x2'))));Im(argv[[1]]);");
     }
 
     @Test
@@ -54,11 +53,14 @@ public class TestBuiltin_Im extends TestBase {
         assertEval("{ Im(1) }");
         assertEval("{ Im(c(1+1i,2-2i)) }");
         assertEval("{ Im(c(1,2)) }");
-        assertEval("{ Im(as.double(NA)) }");
-        assertEval("{ Im(c(1,NA,2)) }");
-        assertEval("{ Im(NA+2i) }");
+        // GnuR3.1.3 probably wrongly interprets complex NAs (should be verified)
+        assertEval(Ignored.ReferenceError, "{ Im(as.double(NA)) }");
+        assertEval(Ignored.ReferenceError, "{ Im(c(1,NA,2)) }");
+        assertEval(Ignored.ReferenceError, "{ Im(NA+2i) }");
 
         assertEval(Ignored.Unknown, "{ x <- 1:2 ; attr(x,\"my\") <- 2 ; Im(x) }");
         assertEval(Ignored.Unknown, "{ x <- c(1+2i,3-4i) ; attr(x,\"my\") <- 2 ; Im(x) }");
+
+        assertEval("{ Im(as.raw(12)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java
index f0026fc6d4b52be0b5d079452a08c36930a30a6f..6a73e1dee888efadf3c00e1ca1b68d9e819db395 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java
@@ -24,29 +24,28 @@ public class TestBuiltin_Mod extends TestBase {
 
     @Test
     public void testMod2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000));Mod(argv[[1]]);");
+        assertEval("argv <- list(c(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000));Mod(argv[[1]]);");
     }
 
     @Test
     public void testMod3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-0.00275201701154004+0i, 0.73267342182576+1.53432836384434i, 1.19603180664097+2.58954103250214i, -1.78551995785074+3.6927974843213i, -0.21286727655171-2.24663622584203i, 1.71166744547715-2.14519629896288i, -1.56293209739181+1.57166915011841i, -1.58375104473686+3.6829699402818i, -2.00504145581753-1.3546174582843i, 0.683574008984187+0.815530349018154i, -1.53010401343571-2.36562392372444i, 0.99061039704013+3.53936165201907i, 1.67472443120722-1.95559489480179i, -0.68341618370449-2.47704044044817i, 1.48062655483323-1.57686725056915i, 2.87299425968444+2.35949377337065i, 1.8028932379829+0.54336001329155i, 0.8410445275115-2.79377726088858i, -0.85630340738898+1.95000905938152i, -0.070268282309003-0.407774647142381i, 0.87904100084727+1.42913449570069i, -0.5398835286832-1.49689799587001i, -4.20150499254585-1.17770608296304i, -4.20150499254585+1.17770608296304i, -0.5398835286832+1.49689799587001i, 0.87904100084727-1.42913449570068i, -0.070268282309002+0.407774647142381i, -0.85630340738898-1.95000905938152i, 0.8410445275115+2.79377726088858i, 1.8028932379829-0.54336001329155i, 2.87299425968444-2.35949377337065i, 1.48062655483323+1.57686725056915i, -0.68341618370449+2.47704044044817i, 1.67472443120722+1.95559489480179i, 0.99061039704013-3.53936165201907i, -1.53010401343571+2.36562392372443i, 0.683574008984187-0.815530349018153i, -2.00504145581753+1.3546174582843i, -1.58375104473686-3.6829699402818i, -1.56293209739181-1.57166915011841i, 1.71166744547714+2.14519629896288i, -0.21286727655171+2.24663622584203i, -1.78551995785073-3.6927974843213i, 1.19603180664097-2.58954103250214i, 0.73267342182576-1.53432836384434i), .Dim = c(45L, 1L), '`scaled:center`' = -0.00488570008479763));Mod(argv[[1]]);");
+        assertEval("argv <- list(structure(c(-0.00275201701154004+0i, 0.73267342182576+1.53432836384434i, 1.19603180664097+2.58954103250214i, -1.78551995785074+3.6927974843213i, -0.21286727655171-2.24663622584203i, 1.71166744547715-2.14519629896288i, -1.56293209739181+1.57166915011841i, -1.58375104473686+3.6829699402818i, -2.00504145581753-1.3546174582843i, 0.683574008984187+0.815530349018154i, -1.53010401343571-2.36562392372444i, 0.99061039704013+3.53936165201907i, 1.67472443120722-1.95559489480179i, -0.68341618370449-2.47704044044817i, 1.48062655483323-1.57686725056915i, 2.87299425968444+2.35949377337065i, 1.8028932379829+0.54336001329155i, 0.8410445275115-2.79377726088858i, -0.85630340738898+1.95000905938152i, -0.070268282309003-0.407774647142381i, 0.87904100084727+1.42913449570069i, -0.5398835286832-1.49689799587001i, -4.20150499254585-1.17770608296304i, -4.20150499254585+1.17770608296304i, -0.5398835286832+1.49689799587001i, 0.87904100084727-1.42913449570068i, -0.070268282309002+0.407774647142381i, -0.85630340738898-1.95000905938152i, 0.8410445275115+2.79377726088858i, 1.8028932379829-0.54336001329155i, 2.87299425968444-2.35949377337065i, 1.48062655483323+1.57686725056915i, -0.68341618370449+2.47704044044817i, 1.67472443120722+1.95559489480179i, 0.99061039704013-3.53936165201907i, -1.53010401343571+2.36562392372443i, 0.683574008984187-0.815530349018153i, -2.00504145581753+1.3546174582843i, -1.58375104473686-3.6829699402818i, -1.56293209739181-1.57166915011841i, 1.71166744547714+2.14519629896288i, -0.21286727655171+2.24663622584203i, -1.78551995785073-3.6927974843213i, 1.19603180664097-2.58954103250214i, 0.73267342182576-1.53432836384434i), .Dim = c(45L, 1L), '`scaled:center`' = -0.00488570008479763));Mod(argv[[1]]);");
     }
 
     @Test
     public void testMod4() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0));Mod(argv[[1]]);");
+        assertEval("argv <- list(logical(0));Mod(argv[[1]]);");
     }
 
     @Test
     public void testMod5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000, 1.12400072777761e+21, 2.5852016738885e+22, 6.20448401733239e+23, 1.5511210043331e+25, 4.03291461126606e+26, 1.08888694504184e+28, 3.04888344611714e+29, 8.8417619937397e+30, 2.65252859812191e+32, 8.22283865417792e+33, 2.63130836933694e+35, 8.68331761881189e+36, 2.95232799039604e+38, 1.03331479663861e+40, 3.71993326789901e+41, 1.37637530912263e+43, 5.23022617466601e+44, 2.03978820811974e+46, 8.15915283247898e+47, 3.34525266131638e+49, 1.40500611775288e+51, 6.04152630633738e+52, 2.65827157478845e+54, 1.1962222086548e+56, 5.50262215981209e+57, 2.58623241511168e+59, 1.24139155925361e+61, 6.08281864034268e+62, 3.04140932017134e+64, 1.55111875328738e+66, 8.06581751709439e+67, 4.27488328406003e+69, 2.30843697339241e+71, 1.26964033536583e+73, 7.10998587804863e+74, 4.05269195048772e+76, 2.35056133128288e+78, 1.3868311854569e+80, 8.32098711274139e+81, 5.07580213877225e+83, 3.14699732603879e+85, 1.98260831540444e+87, 1.26886932185884e+89, 8.24765059208247e+90, 5.44344939077443e+92, 3.64711109181887e+94, 2.48003554243683e+96, 1.71122452428141e+98, 1.19785716699699e+100, 8.50478588567862e+101, 6.12344583768861e+103, 4.47011546151268e+105, 3.30788544151939e+107, 2.48091408113954e+109, 1.88549470166605e+111, 1.45183092028286e+113, 1.13242811782063e+115, 8.94618213078298e+116, 7.15694570462638e+118, 5.79712602074737e+120, 4.75364333701284e+122, 3.94552396972066e+124, 3.31424013456535e+126, 2.81710411438055e+128, 2.42270953836727e+130, 2.10775729837953e+132, 1.85482642257398e+134, 1.65079551609085e+136, 1.48571596448176e+138, 1.3520015276784e+140, 1.24384140546413e+142, 1.15677250708164e+144, 1.08736615665674e+146, 1.03299784882391e+148, 9.9167793487095e+149, 9.61927596824821e+151, 9.42689044888325e+153, 9.33262154439442e+155, 9.33262154439442e+157, 9.42594775983836e+159, 9.61446671503513e+161, 9.90290071648618e+163, 1.02990167451456e+166, 1.08139675824029e+168, 1.14628056373471e+170, 1.22652020319614e+172, 1.32464181945183e+174, 1.44385958320249e+176, 1.58824554152274e+178, 1.76295255109024e+180, 1.97450685722107e+182, 2.23119274865981e+184, 2.54355973347219e+186, 2.92509369349302e+188, 3.3931086844519e+190, 3.96993716080872e+192, 4.68452584975429e+194, 5.57458576120761e+196));Mod(argv[[1]]);");
+        assertEval("argv <- list(c(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000, 1.12400072777761e+21, 2.5852016738885e+22, 6.20448401733239e+23, 1.5511210043331e+25, 4.03291461126606e+26, 1.08888694504184e+28, 3.04888344611714e+29, 8.8417619937397e+30, 2.65252859812191e+32, 8.22283865417792e+33, 2.63130836933694e+35, 8.68331761881189e+36, 2.95232799039604e+38, 1.03331479663861e+40, 3.71993326789901e+41, 1.37637530912263e+43, 5.23022617466601e+44, 2.03978820811974e+46, 8.15915283247898e+47, 3.34525266131638e+49, 1.40500611775288e+51, 6.04152630633738e+52, 2.65827157478845e+54, 1.1962222086548e+56, 5.50262215981209e+57, 2.58623241511168e+59, 1.24139155925361e+61, 6.08281864034268e+62, 3.04140932017134e+64, 1.55111875328738e+66, 8.06581751709439e+67, 4.27488328406003e+69, 2.30843697339241e+71, 1.26964033536583e+73, 7.10998587804863e+74, 4.05269195048772e+76, 2.35056133128288e+78, 1.3868311854569e+80, 8.32098711274139e+81, 5.07580213877225e+83, 3.14699732603879e+85, 1.98260831540444e+87, 1.26886932185884e+89, 8.24765059208247e+90, 5.44344939077443e+92, 3.64711109181887e+94, 2.48003554243683e+96, 1.71122452428141e+98, 1.19785716699699e+100, 8.50478588567862e+101, 6.12344583768861e+103, 4.47011546151268e+105, 3.30788544151939e+107, 2.48091408113954e+109, 1.88549470166605e+111, 1.45183092028286e+113, 1.13242811782063e+115, 8.94618213078298e+116, 7.15694570462638e+118, 5.79712602074737e+120, 4.75364333701284e+122, 3.94552396972066e+124, 3.31424013456535e+126, 2.81710411438055e+128, 2.42270953836727e+130, 2.10775729837953e+132, 1.85482642257398e+134, 1.65079551609085e+136, 1.48571596448176e+138, 1.3520015276784e+140, 1.24384140546413e+142, 1.15677250708164e+144, 1.08736615665674e+146, 1.03299784882391e+148, 9.9167793487095e+149, 9.61927596824821e+151, 9.42689044888325e+153, 9.33262154439442e+155, 9.33262154439442e+157, 9.42594775983836e+159, 9.61446671503513e+161, 9.90290071648618e+163, 1.02990167451456e+166, 1.08139675824029e+168, 1.14628056373471e+170, 1.22652020319614e+172, 1.32464181945183e+174, 1.44385958320249e+176, 1.58824554152274e+178, 1.76295255109024e+180, 1.97450685722107e+182, 2.23119274865981e+184, 2.54355973347219e+186, 2.92509369349302e+188, 3.3931086844519e+190, 3.96993716080872e+192, 4.68452584975429e+194, 5.57458576120761e+196));Mod(argv[[1]]);");
     }
 
     @Test
     public void testMod() {
         assertEval("{ round(Mod(1+1i)*10000) }");
+        assertEval("{ Mod(as.raw(12)) }");
+        assertEval("{ is.integer(Mod(FALSE) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java
index 7c47a894779c4b87ebf58e032a1239b75c56eef9..1209b66cc405b6e3a3e7f4d075c5154b838cd37c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java
@@ -24,8 +24,7 @@ public class TestBuiltin_Re extends TestBase {
 
     @Test
     public void testRe2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(3+2i, 3+2i, NA, 3+2i, 3+2i, 3+2i, 3+2i, 3+2i, 4-5i, 3-5i, NA, NA, 2-5i, 3-5i, 4-5i, 5-5i), .Dim = c(8L, 2L), .Dimnames = list(NULL, c('x1', 'x2'))));Re(argv[[1]]);");
+        assertEval("argv <- list(structure(c(3+2i, 3+2i, NA, 3+2i, 3+2i, 3+2i, 3+2i, 3+2i, 4-5i, 3-5i, NA, NA, 2-5i, 3-5i, 4-5i, 5-5i), .Dim = c(8L, 2L), .Dimnames = list(NULL, c('x1', 'x2'))));Re(argv[[1]]);");
     }
 
     @Test
@@ -40,12 +39,12 @@ public class TestBuiltin_Re extends TestBase {
 
     @Test
     public void testRe5() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0));Re(argv[[1]]);");
+        assertEval("argv <- list(logical(0));Re(argv[[1]]);");
     }
 
     @Test
     public void testRe6() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE);Re(argv[[1]]);");
+        assertEval("argv <- list(FALSE);Re(argv[[1]]);");
     }
 
     @Test
@@ -65,5 +64,7 @@ public class TestBuiltin_Re extends TestBase {
 
         assertEval(Ignored.Unknown, "{ x <- 1:2 ; attr(x,\"my\") <- 2 ; Re(x) }");
         assertEval(Ignored.Unknown, "{ x <- c(1+2i,3-4i) ; attr(x,\"my\") <- 2 ; Re(x) }");
+
+        assertEval("{ Re(as.raw(12)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
index 7f7977ebd85545415f07321c5b12f6f09e388144..53a106905f25dc4878bfc1bb29b2b02ebd254c5d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
@@ -60,7 +60,7 @@ public class TestBuiltin_abs extends TestBase {
 
     @Test
     public void testabs9() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(56.8666666666667, 52.8833333333333), .Dim = 2L, .Dimnames = structure(list(K = c('0', '1')), .Names = 'K')));abs(argv[[1]]);");
+        assertEval("argv <- list(structure(c(56.8666666666667, 52.8833333333333), .Dim = 2L, .Dimnames = structure(list(K = c('0', '1')), .Names = 'K')));abs(argv[[1]]);");
     }
 
     @Test
@@ -75,8 +75,7 @@ public class TestBuiltin_abs extends TestBase {
 
     @Test
     public void testabs12() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317, 0.948371836939988, 0.396080061109718, NA, 0.350912037541581), .Dim = c(4L, 2L), .Dimnames = list(c('(Intercept)', 'x1', 'x2', 'x3'), c('Estimate', 'Std. Error'))));abs(argv[[1]]);");
+        assertEval("argv <- list(structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317, 0.948371836939988, 0.396080061109718, NA, 0.350912037541581), .Dim = c(4L, 2L), .Dimnames = list(c('(Intercept)', 'x1', 'x2', 'x3'), c('Estimate', 'Std. Error'))));abs(argv[[1]]);");
     }
 
     @Test
@@ -91,7 +90,7 @@ public class TestBuiltin_abs extends TestBase {
 
     @Test
     public void testabs15() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(NA, NA), .Dim = 1:2, .Dimnames = list('x', c('Estimate', 'Std. Error'))));abs(argv[[1]]);");
+        assertEval("argv <- list(structure(c(NA, NA), .Dim = 1:2, .Dimnames = list('x', c('Estimate', 'Std. Error'))));abs(argv[[1]]);");
     }
 
     @Test
@@ -152,5 +151,7 @@ public class TestBuiltin_abs extends TestBase {
         assertEval(Ignored.Unknown, "{ abs(c(0/0,1i)) }");
         assertEval("{ abs(1:3) }");
         assertEval("{ abs(-1:-3) }");
+
+        assertEval("{ is.integer(abs(FALSE) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
index cf98c68626841e7fd088d6bc58f9c6a752d9db43..c82560a76829020ed342685a2d1b105a7318057b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
@@ -49,7 +49,7 @@ public class TestBuiltin_exp extends TestBase {
 
     @Test
     public void testexp8() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0));exp(argv[[1]]);");
+        assertEval("argv <- list(logical(0));exp(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_expm1.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_expm1.java
index 393f5836b80ffd28431c431b01537854dc243a14..c5994dedf9a19d6e2193fecba91252dad5f9bb11 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_expm1.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_expm1.java
@@ -34,7 +34,7 @@ public class TestBuiltin_expm1 extends TestBase {
 
     @Test
     public void testexpm14() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0));expm1(argv[[1]]);");
+        assertEval("argv <- list(logical(0));expm1(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log10.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log10.java
index 496a428341cf330c89a67ef496bcc17511d71f9b..73a0ec140dceddecd818c452df71679b2c0ca9ad 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log10.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log10.java
@@ -49,8 +49,7 @@ public class TestBuiltin_log10 extends TestBase {
 
     @Test
     public void testlog107() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(numeric(0), .Dim = c(20L, 0L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), NULL)));log10(argv[[1]]);");
+        assertEval("argv <- list(structure(numeric(0), .Dim = c(20L, 0L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), NULL)));log10(argv[[1]]);");
     }
 
     @Test
@@ -63,7 +62,9 @@ public class TestBuiltin_log10 extends TestBase {
         assertEval("{ log10(100) } ");
         assertEval("{ as.integer(log10(200)*100000) } ");
 
-        assertEval(Ignored.Unknown, "{ m <- matrix(1:4, nrow=2) ; round( log10(m), digits=5 )  }");
+        assertEval("{ m <- matrix(1:4, nrow=2) ; round( log10(m), digits=5 )  }");
         assertEval(Ignored.Unknown, "{ x <- c(a=1, b=10) ; round( c(log(x), log10(x), log2(x)), digits=5 ) }");
+
+        assertEval("{ log10(c(1+1i, -1-1i)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log1p.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log1p.java
index 5c85cc776b5bf90f26d21330fa64174e9d3c310e..3319f3c29506bab5d31c715f5f59449d91acd43b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log1p.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log1p.java
@@ -19,12 +19,16 @@ public class TestBuiltin_log1p extends TestBase {
 
     @Test
     public void testlog1p1() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(-0.160475096572577, -0.953101214495634, -0.329547420118877, -0.234819677566528, -0.108178529791777, -0.0994458210555148, -0.282992873965743, -0.731707656126625, -0.866467764292465, -0.76039953639421, -0.3580569675068, -0.52382260076554, -0.240530699925064, -0.236619747356161, -0.811827419307205, -0.154911720192001, -0.97472580847241, -0.464016625026599, -0.58493655376716, -0.230096919024049));log1p(argv[[1]]);");
+        assertEval("argv <- list(c(-0.160475096572577, -0.953101214495634, -0.329547420118877, -0.234819677566528, -0.108178529791777, -0.0994458210555148, -0.282992873965743, -0.731707656126625, -0.866467764292465, -0.76039953639421, -0.3580569675068, -0.52382260076554, -0.240530699925064, -0.236619747356161, -0.811827419307205, -0.154911720192001, -0.97472580847241, -0.464016625026599, -0.58493655376716, -0.230096919024049));log1p(argv[[1]]);");
     }
 
     @Test
     public void testlog1p2() {
-        assertEval(Ignored.Unknown, "argv <- list(-7e-04);log1p(argv[[1]]);");
+        assertEval("argv <- list(-7e-04);log1p(argv[[1]]);");
+    }
+
+    @Test
+    public void testlog1p3() {
+        assertEval(Ignored.ReferenceError, "log1p(c(1+1i,-1-1i))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log2.java
index b12eadd7a1476b8b25e75b0a11ec729505646626..10d840218a7a934f1189a154e549bcac3c4d6de1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log2.java
@@ -24,7 +24,7 @@ public class TestBuiltin_log2 extends TestBase {
 
     @Test
     public void testlog22() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE);log2(argv[[1]]);");
+        assertEval("argv <- list(FALSE);log2(argv[[1]]);");
     }
 
     @Test
@@ -46,5 +46,7 @@ public class TestBuiltin_log2 extends TestBase {
         assertEval("{ log2(2) } ");
         assertEval("{ log2(4) } ");
         assertEval("{ as.integer(log2(6)*1000000) } ");
+
+        assertEval("{ log10(c(1+1i, -1-1i)) }");
     }
 }