From 8089c53a49097118d86b56072e03b431701f65fe Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 29 Aug 2016 17:35:27 +0200
Subject: [PATCH] Revert "Rewritten parameter casts for seq.int builtin."

---
 .../truffle/r/nodes/builtin/base/Seq.java     | 977 ++++++++++--------
 .../r/test/builtins/TestBuiltin_seq.java      |   2 +-
 2 files changed, 528 insertions(+), 451 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
index 0ac91dce83..3bb2747dee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
@@ -22,22 +22,16 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE;
 
-import java.util.function.Function;
-
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.ArgCastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.SeqNodeGen.SeqInternalNodeGen;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -54,7 +48,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "seq.default", aliases = {"seq.int"}, kind = SUBSTITUTE, parameterNames = {"from", "to", "by", "length.out", "along.with"}, behavior = PURE)
@@ -62,554 +55,638 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 // below)
 @SuppressWarnings("unused")
 public abstract class Seq extends RBuiltinNode {
+    private final ConditionProfile lengthProfile1 = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile lengthProfile2 = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile topLengthProfile = ConditionProfile.createBinaryProfile();
+    private final BranchProfile error = BranchProfile.create();
 
-    private final CastBuilder argCastBuilder = new CastBuilder();
-    private final ConditionProfile isEmptyProfile = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile oneElementProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile singleLogical = BranchProfile.create();
-
-    @Children private final CastNode[] argCastNodes = new CastNode[5];
-    @Child private SeqInternal seqInternal;
-
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        casts.arg("from").mapIf(missingValue().not(), asVector());
-        casts.arg("to").mapIf(missingValue().not(), asVector());
-    }
-
-    private void initSeqInternal() {
-        // this looks a bit crazy because the conversion to int should only happen if the
-        // param is not originally double (unless its value is 0), but the checks have to be
-        // performed on converted and "original" values; also "32" should be converted to int,
-        // but TRUE should become double
-        //@formatter:off
-        seqInternal = insert(SeqInternalNodeGen.create());
-        Function<ArgCastBuilder<Object, ?>, CastNode> castNonDoubleFrom =
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "from")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "from")).
-                        with(mapIf(isFractional().not().and(neq((double) 0)),
-                                        chain(map(doubleToInt())).
-                                        end())).
-                        end();
-        argCastBuilder.arg(0).mapIf(missingValue().not().and(doubleValue().not().and(logicalValue().not())), castNonDoubleFrom).mapIf(doubleValue().or(logicalValue()),
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "from")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "from")).
-                        end());
-        argCastNodes[0] = insert(argCastBuilder.getCasts()[0]);
-
-        Function<ArgCastBuilder<Object, ?>, CastNode> castNonDoubleTo =
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "to")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "to")).
-                        with(mapIf(isFractional().not().and(neq((double) 0)),
-                                        chain(map(doubleToInt())).
-                                        end())).
-                        end();
-        argCastBuilder.arg(1).mapIf(missingValue().not().and(doubleValue().not()), castNonDoubleTo).mapIf(doubleValue().or(logicalValue()),
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "to")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "from")).
-                        end());
-        argCastNodes[1] = insert(argCastBuilder.getCasts()[1]);
-
-        Function<ArgCastBuilder<Object, ?>, CastNode> castNonDoubleStride =
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "by")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "by")).
-                        with(mapIf(isFractional().not().and(neq((double) 0)),
-                                        chain(map(doubleToInt())).
-                                        end())).
-                        end();
-        argCastBuilder.arg(2).mapIf(missingValue().not().and(doubleValue().not()), castNonDoubleTo).mapIf(doubleValue().or(logicalValue()),
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "by")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "by")).
-                        end());
-        argCastNodes[2] = insert(argCastBuilder.getCasts()[2]);
-
-        Function<ArgCastBuilder<Object, ?>, CastNode> castNonDoubleLengthOut =
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "by")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "length.out")).
-                        with(mapIf(isFractional().not().and(neq((double) 0)),
-                                        chain(map(doubleToInt())).
-                                        end())).
-                        end();
-        argCastBuilder.arg(3).mapIf(missingValue().not().and(doubleValue().not()), castNonDoubleTo).mapIf(doubleValue().or(logicalValue()),
-                        chain(asDoubleVector()).
-                        with(mustBe(singleElement(), RError.SHOW_CALLER, true, RError.Message.MUST_BE_SCALAR, "length.out")).
-                        with(findFirst().doubleElement()).
-                        with(mustBe(notDoubleNA().and(isFinite()), RError.SHOW_CALLER, false, RError.Message.CANNOT_BE_INVALID, "length.out")).
-                        end());
-        argCastNodes[3] = insert(argCastBuilder.getCasts()[3]);
-
-        argCastBuilder.arg(4).mapIf(missingValue().not(), asVector());
-        argCastNodes[4] = insert(argCastBuilder.getCasts()[4]);
-        //@formatter:on
-    }
-
-    @Specialization
-    protected Object seq(RAbstractVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
-        if (isEmptyProfile.profile(start.getLength() == 0)) {
-            return RDataFactory.createEmptyIntVector();
-        } else if (oneElementProfile.profile(start.getLength() == 1)) {
-            if (start.getDataAtAsObject(0) instanceof Byte) {
-                // this is mostly to handle somewhat unintuitive:
-                // > seq.int(FALSE)
-                // [1] 1
-                singleLogical.enter();
-                return 1;
-            }
-            initSeqInternal();
-            Object newTo = argCastNodes[0].execute(start);
-            // this is real:
-            // > seq(10)
-            // [1] 1 2 3 4 5 6 7 8 9 10
-            // but
-            // > seq(NaN)
-            // Error in seq.default(NaN) : 'from' cannot be NA, NaN or infinite
-            return seqInternal.execute(1, newTo, stride, lengthOut, alongWith);
-        } else {
-            // GNU R really does that (take the length of start to create a sequence)
-            // > seq(c(10, 10))
-            // [1] 1 2
-            // > seq(c(NaN, NaN))
-            // [1] 1 2
-            return RDataFactory.createIntSequence(1, 1, start.getLength());
+    @Child private Seq seqRecursive;
+
+    protected abstract Object execute(Object start, Object to, Object stride, Object lengthOut, Object alongWith);
+
+    private Object seqRecursive(Object start, Object to, Object stride, Object lengthOut, Object alongWith) {
+        if (seqRecursive == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            seqRecursive = insert(SeqNodeGen.create(null));
         }
+        return seqRecursive.execute(start, to, stride, lengthOut, alongWith);
     }
 
-    @Specialization(guards = "notStartOnly(to, stride, lengthOut, alongWith)")
-    protected Object seq(RAbstractVector start, Object to, Object stride, Object lengthOut, Object alongWith) {
-        initSeqInternal();
-        return seqInternal.execute(argCastNodes[0].execute(start), argCastNodes[1].execute(to), argCastNodes[2].execute(stride), argCastNodes[3].execute(lengthOut),
-                        argCastNodes[4].execute(alongWith));
+    private void validateParam(int v, String vName) {
+        if (RRuntime.isNA(v)) {
+            error.enter();
+            throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName);
+        }
     }
 
-    @Specialization()
-    protected Object seq(RMissing start, RAbstractVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
-        initSeqInternal();
-        return seqInternal.execute(1.0, argCastNodes[1].execute(to), argCastNodes[2].execute(stride), argCastNodes[3].execute(lengthOut), argCastNodes[4].execute(alongWith));
+    private void validateParam(double v, String vName) {
+        if (RRuntime.isNAorNaN(v) || Double.isInfinite(v)) {
+            error.enter();
+            throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName);
+        }
     }
 
-    @Specialization(guards = "passMissingStart(to, lengthOut, alongWith)") // complement of previous
-                                                                           // specialization
-    protected Object seq(RMissing start, Object to, Object stride, Object lengthOut, Object alongWith) {
-        initSeqInternal();
-        return seqInternal.execute(start, argCastNodes[1].execute(to), argCastNodes[2].execute(stride), argCastNodes[3].execute(lengthOut), argCastNodes[4].execute(alongWith));
+    private void validateParams(RAbstractIntVector start, RAbstractIntVector to) {
+        if (start != null) {
+            validateParam(start.getDataAt(0), "from");
+        }
+        if (to != null) {
+            validateParam(start.getDataAt(0), "to");
+        }
     }
 
-    protected boolean notStartOnly(Object to, Object stride, Object lengthOut, Object alongWith) {
-        return !(to == RMissing.instance && stride == RMissing.instance && lengthOut == RMissing.instance && alongWith == RMissing.instance);
+    private void validateParams(RAbstractDoubleVector start, RAbstractIntVector to) {
+        if (start != null) {
+            validateParam(start.getDataAt(0), "from");
+        }
+        if (to != null) {
+            validateParam(start.getDataAt(0), "to");
+        }
     }
 
-    protected boolean passMissingStart(Object to, Object lengthOut, Object alongWith) {
-        return !(to instanceof RAbstractVector && lengthOut == RMissing.instance && alongWith == RMissing.instance);
+    private void validateParams(RAbstractIntVector start, RAbstractDoubleVector to) {
+        if (start != null) {
+            validateParam(start.getDataAt(0), "from");
+        }
+        if (to != null) {
+            validateParam(start.getDataAt(0), "to");
+        }
     }
 
-    protected abstract static class SeqInternal extends RBaseNode {
-
-        protected abstract Object execute(Object start, Object to, Object stride, Object lengthOut, Object alongWith);
+    private void validateParams(double start, double to) {
+        validateParam(start, "from");
+        validateParam(to, "to");
+    }
 
-        private final ConditionProfile lengthProfile1 = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile lengthProfile2 = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile topLengthProfile = ConditionProfile.createBinaryProfile();
-        private final BranchProfile error = BranchProfile.create();
+    private void validateParams(RAbstractDoubleVector start, RAbstractDoubleVector to) {
+        if (start != null) {
+            validateParam(start.getDataAt(0), "from");
+        }
+        if (to != null) {
+            validateParam(start.getDataAt(0), "to");
+        }
+    }
 
-        private RDoubleVector getVectorWithComputedStride(double start, double to, double lengthOut, boolean ascending) {
-            int length = (int) Math.ceil(lengthOut);
-            if (lengthProfile1.profile(length == 1)) {
-                return RDataFactory.createDoubleVector(new double[]{start}, RDataFactory.COMPLETE_VECTOR);
-            } else if (lengthProfile2.profile(length == 2)) {
-                return RDataFactory.createDoubleVector(new double[]{start, to}, RDataFactory.COMPLETE_VECTOR);
-            } else {
-                double[] data = new double[length];
-                data[0] = start;
-                double newStride = (to - start) / (length - 1);
-                if (!ascending) {
-                    newStride = -newStride;
-                }
-                for (int i = 1; i < length - 1; i++) {
-                    data[i] = start + (i * newStride);
-                }
-                data[length - 1] = to;
-                return RDataFactory.createDoubleVector(data, RDataFactory.COMPLETE_VECTOR);
+    private RDoubleVector getVectorWithComputedStride(double start, double to, double lengthOut, boolean ascending) {
+        validateParams(start, to);
+        int length = (int) Math.ceil(lengthOut);
+        if (lengthProfile1.profile(length == 1)) {
+            return RDataFactory.createDoubleVector(new double[]{start}, RDataFactory.COMPLETE_VECTOR);
+        } else if (lengthProfile2.profile(length == 2)) {
+            return RDataFactory.createDoubleVector(new double[]{start, to}, RDataFactory.COMPLETE_VECTOR);
+        } else {
+            double[] data = new double[length];
+            data[0] = start;
+            double newStride = (to - start) / (length - 1);
+            if (!ascending) {
+                newStride = -newStride;
             }
+            for (int i = 1; i < length - 1; i++) {
+                data[i] = start + (i * newStride);
+            }
+            data[length - 1] = to;
+            return RDataFactory.createDoubleVector(data, RDataFactory.COMPLETE_VECTOR);
         }
+    }
 
-        private RIntVector getVectorWithComputedStride(int start, int to, double lengthOut, boolean ascending) {
-            int length = (int) Math.ceil(lengthOut);
-            if (lengthProfile1.profile(length == 1)) {
-                return RDataFactory.createIntVector(new int[]{start}, RDataFactory.COMPLETE_VECTOR);
-            } else if (lengthProfile2.profile(length == 2)) {
-                return RDataFactory.createIntVector(new int[]{start, to}, RDataFactory.COMPLETE_VECTOR);
-            } else {
-                int[] data = new int[length];
-                data[0] = start;
-                int newStride = (to - start) / (length - 1);
-                if (!ascending) {
-                    newStride = -newStride;
-                }
-                for (int i = 1; i < length - 1; i++) {
-                    data[i] = start + (i * newStride);
-                }
-                data[length - 1] = to;
-                return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
+    private RIntVector getVectorWithComputedStride(int start, int to, double lengthOut, boolean ascending) {
+        validateParams(start, to);
+        int length = (int) Math.ceil(lengthOut);
+        if (lengthProfile1.profile(length == 1)) {
+            return RDataFactory.createIntVector(new int[]{start}, RDataFactory.COMPLETE_VECTOR);
+        } else if (lengthProfile2.profile(length == 2)) {
+            return RDataFactory.createIntVector(new int[]{start, to}, RDataFactory.COMPLETE_VECTOR);
+        } else {
+            int[] data = new int[length];
+            data[0] = start;
+            int newStride = (to - start) / (length - 1);
+            if (!ascending) {
+                newStride = -newStride;
             }
+            for (int i = 1; i < length - 1; i++) {
+                data[i] = start + (i * newStride);
+            }
+            data[length - 1] = to;
+            return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
         }
+    }
 
-        @Specialization(guards = {"zero(start, to)"})
-        protected int seqZero(double start, double to, Object stride, RMissing lengthOut, RMissing alongWith) {
-            return 0;
-        }
+    @Specialization
+    protected RIntSequence seqFromOneArg(RAbstractListVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
+        // GNU R really does that (take the length of start to create a sequence)
+        return RDataFactory.createIntSequence(1, 1, start.getLength());
+    }
 
-        // int vector start, missing to
+    @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"})
+    protected int seqZero(RAbstractIntVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+        return 0;
+    }
 
-        @Specialization
-        protected RAbstractVector seq(int start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createDoubleSequence(RRuntime.int2double(start), 1, lengthOut);
-            }
-        }
+    @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"})
+    protected int seqZero(RAbstractDoubleVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+        return 0;
+    }
 
-        @Specialization
-        protected RAbstractVector seq(int start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createDoubleSequence(RRuntime.int2double(start), 1, (int) Math.ceil(lengthOut));
-            }
-        }
+    @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"})
+    protected int seqZero(RAbstractIntVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+        return 0;
+    }
 
-        // int vector start, int vector to
+    @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"})
+    protected int seqZero(RAbstractDoubleVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+        return 0;
+    }
 
-        @Specialization
-        protected Object seq(int start, int to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createIntSequence(start, ascending(start, to) ? 1 : -1, Math.abs(to - start) + 1);
-            }
-        }
+    // int vector start, missing to
 
-        @Specialization
-        protected Object seq(int start, int to, int stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createIntSequence(start, stride, Math.abs((to - start) / stride) + 1);
-            }
+    @Specialization
+    protected RAbstractIntVector seqFromOneArg(RAbstractIntVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
+        if (topLengthProfile.profile(start.getLength() == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParam(start.getDataAt(0), "to");
+            // GNU R really does that (take the length of start to create a sequence)
+            return RDataFactory.createIntSequence(1, 1, start.getLength());
         }
+    }
 
-        @Specialization
-        protected Object seq(int start, int to, double stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createDoubleSequence(RRuntime.int2double(start), stride, (int) (Math.abs((to - start) / stride)) + 1);
-            }
+    @Specialization
+    protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        validateParam(start.getDataAt(0), "from");
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, lengthOut);
         }
+    }
 
-        @Specialization
-        protected RIntVector seq(int start, int to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(start, to, RRuntime.int2double(lengthOut), ascending(start, to));
-            }
+    @Specialization
+    protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        validateParam(start.getDataAt(0), "from");
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, (int) Math.ceil(lengthOut));
         }
+    }
 
-        @Specialization
-        protected RIntVector seq(int start, int to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(start, to, lengthOut, ascending(start, to));
-            }
-        }
+    // int vector start, int vector to
 
-        @Specialization
-        protected RAbstractVector seq(int start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
-            if (topLengthProfile.profile(alongWith.getLength() == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createIntSequence(start, 1, alongWith.getLength());
-            }
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1);
         }
+    }
 
-        // int vector start, double vector to
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractIntVector to, int stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createIntSequence(start.getDataAt(0), stride, Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1);
+        }
+    }
 
-        @Specialization
-        protected Object seq(int start, double to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createIntSequence(start, ascending(start, to) ? 1 : -1, (int) Math.abs(to - start) + 1);
-            }
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractIntVector to, double stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), stride, (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride)) + 1);
         }
+    }
 
-        @Specialization
-        protected Object seq(int start, double to, int stride, RMissing lengthOut, RMissing alongWith) {
-            return seq(start, to, (double) stride, lengthOut, alongWith);
+    @Specialization
+    protected RIntVector seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected Object seq(int start, double to, double stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                int length = (int) (Math.abs(to - start) / stride);
-                if (start + length * stride == to) {
-                    length++;
-                }
-                return RDataFactory.createDoubleSequence(start, stride, length);
-            }
+    @Specialization
+    protected RIntVector seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(int start, double to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(RRuntime.int2double(start), to, lengthOut, ascending(start, to));
-            }
+    @Specialization
+    protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
+        startLengthOne(start);
+        if (topLengthProfile.profile(alongWith.getLength() == 0)) {
+            validateParam(start.getDataAt(0), "from");
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParam(start.getDataAt(0), "from");
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength());
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(int start, double to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(RRuntime.int2double(start), to, lengthOut, ascending(start, to));
-            }
+    // int vector start, double vector to
+
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1);
         }
+    }
 
-        // double vector start, missing to
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, int stride, RMissing lengthOut, RMissing alongWith) {
+        return seq(start, to, (double) stride, lengthOut, alongWith);
+    }
 
-        @Specialization
-        protected RAbstractVector seqStartLengthOne(double start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createDoubleSequence(start, 1, lengthOut);
+    @Specialization
+    protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, double stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            int length = (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) / stride);
+            if (start.getDataAt(0) + length * stride == to.getDataAt(0)) {
+                length++;
             }
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, length);
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqStartLengthOne(double start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createDoubleSequence(start, 1, (int) Math.ceil(lengthOut));
-            }
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqStartLengthOne(double start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
-            if (topLengthProfile.profile(alongWith.getLength() == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createDoubleSequence(start, 1, alongWith.getLength());
-            }
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to));
         }
+    }
 
-        // double vector start, int vector to
+    // double vector start, missing to
 
-        @Specialization
-        protected Object seq(double start, int to, RMissing stride, RMissing lengthOut, RMissing alongWith,
-                        @Cached("createBinaryProfile()") ConditionProfile intProfile) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                if (intProfile.profile((int) start == start)) {
-                    return RDataFactory.createIntSequence((int) start, ascending(start, to) ? 1 : -1, (int) (Math.abs(to - start) + 1));
-                } else {
-                    return RDataFactory.createDoubleSequence(start, ascending(start, to) ? 1 : -1, (int) (Math.abs(to - start) + 1));
-                }
-            }
+    @Specialization
+    protected RAbstractVector seqFromOneArg(RAbstractDoubleVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) {
+        if (topLengthProfile.profile(start.getLength() == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParam(start.getDataAt(0), "from");
+            // GNU R really does that (take the length of start to create a sequence)
+            return RDataFactory.createDoubleSequence(1, 1, start.getLength());
         }
+    }
 
-        @Specialization
-        protected Object seq(double start, int to, int stride, RMissing lengthOut, RMissing alongWith) {
-            return seq(start, to, (double) stride, lengthOut, alongWith);
+    @Specialization
+    protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        validateParam(start.getDataAt(0), "from");
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, lengthOut);
         }
+    }
 
-        @Specialization
-        protected Object seq(double start, int to, double stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createDoubleSequence(start, stride, (int) Math.abs((to - start) / stride) + 1);
-            }
+    @Specialization
+    protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        validateParam(start.getDataAt(0), "from");
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, (int) Math.ceil(lengthOut));
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(double start, int to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(start, RRuntime.int2double(to), lengthOut, ascending(start, to));
-            }
+    @Specialization
+    protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
+        startLengthOne(start);
+        validateParam(start.getDataAt(0), "from");
+        if (topLengthProfile.profile(alongWith.getLength() == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength());
         }
+    }
+
+    // double vector start, int vector to
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(double start, int to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith,
+                    @Cached("createBinaryProfile()") ConditionProfile intProfile) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            if (intProfile.profile((int) start.getDataAt(0) == start.getDataAt(0))) {
+                return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1));
             } else {
-                return getVectorWithComputedStride(start, RRuntime.int2double(to), lengthOut, ascending(start, to));
+                return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1));
             }
         }
+    }
 
-        // double vector start, double vector to
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, int stride, RMissing lengthOut, RMissing alongWith) {
+        return seq(start, to, (double) stride, lengthOut, alongWith);
+    }
 
-        @Specialization
-        protected Object seq(double start, double to, RMissing stride, RMissing lengthOut, RMissing alongWith, //
-                        @Cached("createBinaryProfile()") ConditionProfile intProfile) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                if (intProfile.profile((int) start == start && (int) to == to)) {
-                    return RDataFactory.createIntSequence((int) start, ascending(start, to) ? 1 : -1, (int) (Math.abs(to - start) + 1));
-                } else {
-                    return RDataFactory.createDoubleSequence(start, ascending(start, to) ? 1 : -1, (int) (Math.abs(to - start) + 1));
-                }
-            }
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, double stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1);
         }
+    }
 
-        @Specialization
-        protected Object seq(double start, double to, int stride, RMissing lengthOut, RMissing alongWith) {
-            return seq(start, to, (double) stride, lengthOut, alongWith);
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected Object seq(double start, double to, double stride, RMissing lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(zero(start, to))) {
-                return 0;
-            } else {
-                return RDataFactory.createDoubleSequence(start, stride, (int) (Math.abs((to - start) / stride) + 1));
-            }
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(double start, double to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return getVectorWithComputedStride(start, to, RRuntime.int2double(lengthOut), ascending(start, to));
-            }
-        }
+    // double vector start, double vector to
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(double start, double to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith, //
+                    @Cached("createBinaryProfile()") ConditionProfile intProfile) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            if (intProfile.profile((int) start.getDataAt(0) == start.getDataAt(0) && (int) to.getDataAt(0) == to.getDataAt(0))) {
+                return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1));
             } else {
-                return getVectorWithComputedStride(start, to, lengthOut, ascending(start, to));
+                return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1));
             }
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createIntSequence(1, 1, lengthOut);
-            }
-        }
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, int stride, RMissing lengthOut, RMissing alongWith) {
+        return seq(start, to, (double) stride, lengthOut, alongWith);
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
-            if (topLengthProfile.profile(lengthOut == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createIntSequence(1, 1, (int) Math.ceil(lengthOut));
-            }
+    @Specialization
+    protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, double stride, RMissing lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        validateParams(start, to);
+        if (topLengthProfile.profile(zero(start, to))) {
+            return 0;
+        } else {
+            return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1));
         }
+    }
 
-        @Specialization
-        protected RAbstractVector seqLengthZeroAlong(RMissing start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
-            if (topLengthProfile.profile(alongWith.getLength() == 0)) {
-                return RDataFactory.createEmptyIntVector();
-            } else {
-                return RDataFactory.createIntSequence(1, 1, alongWith.getLength());
-            }
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected RDoubleSequence seq(RMissing start, int to, RMissing stride, int lengthOut, RMissing alongWith) {
-            positiveLengthOut(lengthOut);
-            return RDataFactory.createDoubleSequence(to - lengthOut + 1, 1, lengthOut);
+    @Specialization
+    protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        startLengthOne(start);
+        toLengthOne(to);
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            validateParams(start, to);
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            validateParams(start, to);
+            return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to));
         }
+    }
 
-        @Specialization
-        protected RDoubleSequence seq(RMissing start, int to, RMissing stride, double lengthOut, RMissing alongWith) {
-            return seq(start, to, stride, (int) Math.ceil(lengthOut), alongWith);
-        }
+    // logical vectors
 
-        @Specialization
-        protected RDoubleSequence seq(RMissing start, double to, RMissing stride, double lengthOut, RMissing alongWith) {
-            positiveLengthOut(lengthOut);
-            return RDataFactory.createDoubleSequence(to - lengthOut + 1, 1, (int) Math.ceil(lengthOut));
-        }
+    @Specialization
+    protected Object seq(RAbstractLogicalVector start, RAbstractLogicalVector to, Object stride, Object lengthOut, Object alongWith) {
+        return seqRecursive(RClosures.createLogicalToDoubleVector(start), RClosures.createLogicalToDoubleVector(to), stride, lengthOut, alongWith);
+    }
 
-        private static boolean ascending(int start, int to) {
-            return to > start;
-        }
+    @Specialization(guards = "!isLogical(to)")
+    protected Object seq(RAbstractLogicalVector start, RAbstractVector to, Object stride, Object lengthOut, Object alongWith) {
+        return seqRecursive(RClosures.createLogicalToDoubleVector(start), to, stride, lengthOut, alongWith);
+    }
 
-        private static boolean ascending(int start, double to) {
-            return to > start;
-        }
+    @Specialization(guards = "!isLogical(start)")
+    protected Object seq(RAbstractVector start, RAbstractLogicalVector to, Object stride, Object lengthOut, Object alongWith) {
+        return seqRecursive(start, RClosures.createLogicalToDoubleVector(to), stride, lengthOut, alongWith);
+    }
 
-        private static boolean ascending(double start, int to) {
-            return to > start;
-        }
+    @Specialization
+    protected Object seq(RAbstractLogicalVector start, RMissing to, Object stride, Object lengthOut, Object alongWith) {
+        return seqRecursive(RClosures.createLogicalToDoubleVector(start), to, stride, lengthOut, alongWith);
+    }
 
-        protected static boolean ascending(double start, double to) {
-            return to > start;
+    @Specialization
+    protected Object seq(RMissing start, RAbstractLogicalVector to, Object stride, Object lengthOut, Object alongWith) {
+        return seqRecursive(start, RClosures.createLogicalToDoubleVector(to), stride, lengthOut, alongWith);
+    }
+
+    protected boolean isLogical(RAbstractVector v) {
+        return v.getElementClass() == RLogical.class;
+    }
+
+    @Specialization
+    protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) {
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createIntSequence(1, 1, lengthOut);
         }
+    }
 
-        protected static boolean zero(int start, int to) {
-            return start == 0 && to == 0;
+    @Specialization
+    protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) {
+        if (topLengthProfile.profile(lengthOut == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createIntSequence(1, 1, (int) Math.ceil(lengthOut));
         }
+    }
 
-        protected static boolean zero(int start, double to) {
-            return start == 0 && to == 0;
+    @Specialization
+    protected RAbstractVector seqLengthZeroAlong(RMissing start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) {
+        if (topLengthProfile.profile(alongWith.getLength() == 0)) {
+            return RDataFactory.createEmptyIntVector();
+        } else {
+            return RDataFactory.createIntSequence(1, 1, alongWith.getLength());
         }
+    }
+
+    @Specialization
+    protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+        toLengthOne(to);
+        positiveLengthOut(lengthOut);
+        validateParam(to.getDataAt(0), "to");
+        return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, lengthOut);
+    }
 
-        protected static boolean zero(double start, int to) {
-            return start == 0 && to == 0;
+    @Specialization
+    protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        return seq(start, to, stride, (int) Math.ceil(lengthOut), alongWith);
+    }
+
+    @Specialization
+    protected RDoubleSequence seq(RMissing start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+        toLengthOne(to);
+        positiveLengthOut(lengthOut);
+        validateParam(to.getDataAt(0), "to");
+        return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, (int) Math.ceil(lengthOut));
+    }
+
+    @Specialization
+    protected Object seq(RMissing start, RAbstractVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+        toLengthOne(to);
+        return seqRecursive(1.0, to, stride, lengthOut, alongWith);
+    }
+
+    private static boolean ascending(RAbstractIntVector start, RAbstractIntVector to) {
+        return to.getDataAt(0) > start.getDataAt(0);
+    }
+
+    private static boolean ascending(RAbstractIntVector start, RAbstractDoubleVector to) {
+        return to.getDataAt(0) > start.getDataAt(0);
+    }
+
+    private static boolean ascending(RAbstractDoubleVector start, RAbstractIntVector to) {
+        return to.getDataAt(0) > start.getDataAt(0);
+    }
+
+    protected static boolean ascending(RAbstractDoubleVector start, RAbstractDoubleVector to) {
+        return to.getDataAt(0) > start.getDataAt(0);
+    }
+
+    protected static boolean zero(RAbstractIntVector start, RAbstractIntVector to) {
+        return start.getDataAt(0) == 0 && to.getDataAt(0) == 0;
+    }
+
+    protected static boolean zero(RAbstractLogicalVector start, RAbstractLogicalVector to) {
+        return start.getDataAt(0) == RRuntime.LOGICAL_FALSE && to.getDataAt(0) == RRuntime.LOGICAL_FALSE;
+    }
+
+    protected static boolean zero(RAbstractIntVector start, RAbstractDoubleVector to) {
+        return start.getDataAt(0) == 0 && to.getDataAt(0) == 0;
+    }
+
+    protected static boolean zero(RAbstractDoubleVector start, RAbstractIntVector to) {
+        return start.getDataAt(0) == 0 && to.getDataAt(0) == 0;
+    }
+
+    protected static boolean zero(RAbstractDoubleVector start, RAbstractDoubleVector to) {
+        return start.getDataAt(0) == 0 && to.getDataAt(0) == 0;
+    }
+
+    protected boolean startLengthOne(RAbstractVector start) {
+        if (start.getLength() != 1) {
+            error.enter();
+            throw RError.error(this, RError.Message.MUST_BE_SCALAR, "from");
         }
+        return true;
+    }
 
-        protected static boolean zero(double start, double to) {
-            return start == 0 && to == 0;
+    protected boolean toLengthOne(RAbstractVector to) {
+        if (to.getLength() != 1) {
+            error.enter();
+            throw RError.error(this, RError.Message.MUST_BE_SCALAR, "to");
         }
+        return true;
+    }
 
-        protected boolean positiveLengthOut(int lengthOut) {
-            if (lengthOut < 0) {
-                error.enter();
-                throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out");
-            }
-            return true;
+    protected boolean positiveLengthOut(int lengthOut) {
+        if (lengthOut < 0) {
+            error.enter();
+            throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out");
         }
+        return true;
+    }
 
-        protected boolean positiveLengthOut(double lengthOut) {
-            if (lengthOut < 0) {
-                error.enter();
-                throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out");
-            }
-            return true;
+    protected boolean positiveLengthOut(double lengthOut) {
+        if (lengthOut < 0) {
+            error.enter();
+            throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out");
         }
+        return true;
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
index 892e8c68d4..c0f8879bb9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
@@ -173,7 +173,7 @@ public class TestBuiltin_seq extends TestBase {
         assertEval("{ seq(0,0) }");
         assertEval("{ seq(0L,0L,0L) }");
         assertEval("{ seq(0L,0L) }");
-        assertEval(Ignored.MissingWarning, "{ seq(0,0,1i) }");
+        assertEval("{ seq(0,0,1i) }");
         assertEval(Output.IgnoreErrorContext, "{ seq(integer(), 7) }");
         assertEval(Output.MayIgnoreErrorContext, "{ seq(c(1,2), 7) }");
         assertEval(Output.IgnoreErrorContext, "{ seq(7, integer()) }");
-- 
GitLab