diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java index 2d10974c2f2cd5be2a516cc84e5e1df3201ff6d1..87b2f73c140d235495c3bed78853de0014c771aa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -29,9 +32,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.runtime.RError; @@ -46,7 +49,6 @@ import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RRaw; @@ -66,21 +68,13 @@ import com.oracle.truffle.r.runtime.nodes.RNode; @SuppressWarnings("unused") public class IsTypeFunctions { - protected abstract static class ErrorAdapter extends RBuiltinNode { - protected final BranchProfile errorProfile = BranchProfile.create(); + protected abstract static class MissingAdapter extends RBuiltinNode { - protected RError missingError() throws RError { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MISSING, "x"); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "x"); } - } - - protected abstract static class MissingAdapter extends ErrorAdapter { - @Specialization - protected byte isType(RMissing value) throws RError { - throw missingError(); - } } @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) @@ -476,21 +470,22 @@ public class IsTypeFunctions { } @RBuiltin(name = "is.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, behavior = PURE) - public abstract static class IsVector extends ErrorAdapter { + public abstract static class IsVector extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "x"); + casts.arg("mode").defaultError(this, RError.Message.INVALID_ARGUMENT, "mode").mustBe(stringValue()).asStringVector().mustBe(size(1)); + } + @Override public Object[] getDefaultParameterValues() { // INTERNAL does not need default parameters return RNode.EMPTY_OBJECT_ARRAY; } - @Specialization - protected byte isVector(RMissing value, String mode) { - throw missingError(); - } - @Specialization protected byte isVector(RAbstractVector x, String mode) { if (!namesOnlyOrNoAttr(x) || !modeIsAnyOrMatches(x, mode)) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java index 827a48a9edae5c1acb6085e7a02e1a243b5ce150..9642e599e9e4ab7fa47d655b0442038ecadb71a4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java @@ -22,17 +22,29 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.binary.BinaryMapBooleanFunctionNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.Order.CmpNode; +import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.BinaryCompare; @RBuiltin(name = "is.unsorted", kind = INTERNAL, parameterNames = {"x", "strictly"}, behavior = PURE) @@ -41,14 +53,30 @@ import com.oracle.truffle.r.runtime.ops.BinaryCompare; public abstract class IsUnsorted extends RBuiltinNode { @Child private BinaryMapBooleanFunctionNode ge = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_EQUAL.create()); + @Child private BinaryMapBooleanFunctionNode gt = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_THAN.create()); + + private final ConditionProfile strictlyProfile = ConditionProfile.createBinaryProfile(); + + @Child private RComplexComparator ccmp = new RComplexComparator(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).notNA().map(toBoolean()); + } @Specialization - protected byte isUnsorted(RAbstractDoubleVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractDoubleVector x, boolean strictly) { double last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { double current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } @@ -56,12 +84,18 @@ public abstract class IsUnsorted extends RBuiltinNode { } @Specialization - protected byte isUnsorted(RAbstractIntVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractIntVector x, boolean strictly) { int last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { int current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } @@ -69,15 +103,113 @@ public abstract class IsUnsorted extends RBuiltinNode { } @Specialization - protected byte isUnsorted(RAbstractStringVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractStringVector x, boolean strictly) { String last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { String current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } + last = current; + } + return RRuntime.LOGICAL_FALSE; + } + + protected CmpNode createCmpNode() { + return CmpNodeGen.create(); + } + + @Specialization + protected byte isUnsorted(RAbstractRawVector x, boolean strictly) { + RRaw last = x.getDataAt(0); + for (int k = 1; k < x.getLength(); k++) { + RRaw current = x.getDataAt(k); + if (strictlyProfile.profile(strictly)) { + if (ge.applyRaw(last.getValue(), current.getValue()) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyRaw(last.getValue(), current.getValue()) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } return RRuntime.LOGICAL_FALSE; } + + @Specialization + protected byte isUnsorted(RAbstractComplexVector x, boolean strictly, @Cached("createCmpNode()") CmpNode cmpNode) { + int last = 0; + for (int k = 1; k < x.getLength(); k++) { + if (strictlyProfile.profile(strictly)) { + if (cmpNode.ccmp(x, last, k, true) >= 0) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (cmpNode.ccmp(x, last, k, true) > 0) { + return RRuntime.LOGICAL_TRUE; + } + } + last = k; + } + return RRuntime.LOGICAL_FALSE; + } + + @Fallback + @SuppressWarnings("unused") + protected byte isUnsortedFallback(Object x, boolean strictly) { + return RRuntime.LOGICAL_NA; + } + + public final class RComplexComparator extends RBaseNode { + + public Object execute(RComplex x, RComplex y, boolean naLast) { + // compare real parts + boolean nax = RRuntime.isNA(x.getRealPart()); + boolean nay = RRuntime.isNA(y.getRealPart()); + if (nax && nay) { + return 0; + } + if (nax) { + return naLast ? 1 : -1; + } + if (nay) { + return naLast ? -1 : 1; + } + if (x.getRealPart() < y.getRealPart()) { + return -1; + } + if (x.getRealPart() > y.getRealPart()) { + return 1; + } + + // compare real parts + nax = RRuntime.isNA(x.getImaginaryPart()); + nay = RRuntime.isNA(y.getImaginaryPart()); + if (nax && nay) { + return 0; + } + if (nax) { + return naLast ? 1 : -1; + } + if (nay) { + return naLast ? -1 : 1; + } + if (x.getImaginaryPart() < y.getImaginaryPart()) { + return -1; + } + if (x.getImaginaryPart() > y.getImaginaryPart()) { + return 1; + } + return 0; // equal + } + } + } 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 02ae51b88c51d7a74fa1cc7fee9daf0d4c87f480..f8ebefb298116c968780d271e8ec0542311ddea8 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 @@ -24984,6 +24984,18 @@ Error: unexpected symbol in "0.2, 18, 20, 20, 22.7, 16.3, 18.7, 21, 24.5, 17.8, #argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));is.symbol(argv[[1]]); [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=FALSE) } +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) } +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1,2,2,3), strictly=TRUE) } +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted #{ is.unsorted(c(1,2,3,4)) } [1] FALSE @@ -25091,6 +25103,14 @@ Error: unexpected symbol in "0.2, 18, 20, 20, 22.7, 16.3, 18.7, 21, 24.5, 17.8, ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector #{ x<-list(1,3); } +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector +#{is.vector(c(1,2), TRUE);} +Error in is.vector(x, mode) : invalid 'mode' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector +#{is.vector(c(1,2), c("sss", "dddd"));} +Error in is.vector(x, mode) : invalid 'mode' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector #{is.vector(c(TRUE,FALSE),"logical");} [1] TRUE diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java index a1981e67d95939c53b3d1ca2e4e458b0cdc3aa56..be6652d29a371a85ce41558f533d0eaf7bf1cdb9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java @@ -95,5 +95,8 @@ public class TestBuiltin_isunsorted extends TestBase { public void testIsUnsorted() { assertEval("{ is.unsorted(c(1,2,3,4)) }"); assertEval("{ is.unsorted(c(1,2,6,4)) }"); + assertEval("{ is.unsorted(c(1,2,2,3), strictly=TRUE) }"); + assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=FALSE) }"); + assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java index 01442b5c235bfd911bb6a53581e2fe8c8d7b0c67..4cfb24acda41b9dd827e6c07712462b071318f90 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java @@ -199,5 +199,7 @@ public class TestBuiltin_isvector extends TestBase { assertEval("{is.vector(c(TRUE,FALSE),\"logical\");}"); assertEval("{x<-1;class(x)<-\"a\";is.vector(x);}"); assertEval("{x<-1;names(x)<-\"a\";is.vector(x);}"); + assertEval("{is.vector(c(1,2), c(\"sss\", \"dddd\"));}"); + assertEval("{is.vector(c(1,2), TRUE);}"); } }