From c2b2eb9d121414c5e31f58a10f9d00e3a5268feb Mon Sep 17 00:00:00 2001 From: Tomas Stupka <tomas.stupka@oracle.com> Date: Tue, 21 Mar 2017 13:08:37 +0100 Subject: [PATCH] [GR-2950] Fix a batch of builtins with CP issues --- .../builtin/base/BaseGammaFunctions.java | 13 - .../r/nodes/builtin/base/GetFunctions.java | 3 +- .../r/nodes/builtin/base/IntToBits.java | 2 +- .../r/nodes/builtin/base/IntToUtf8.java | 2 +- .../truffle/r/nodes/builtin/base/Lapply.java | 8 +- .../r/nodes/builtin/base/LogFunctions.java | 333 ++++++++++++++++-- .../truffle/r/nodes/builtin/base/Missing.java | 5 + .../truffle/r/nodes/builtin/base/NChar.java | 2 +- .../truffle/r/nodes/builtin/base/NZChar.java | 8 + .../truffle/r/nodes/builtin/base/PMatch.java | 25 +- .../truffle/r/nodes/builtin/base/Parse.java | 2 +- .../truffle/r/nodes/builtin/base/ReadDCF.java | 5 +- .../r/nodes/builtin/base/SortFunctions.java | 21 +- .../nodes/builtin/base/infix/NextBuiltin.java | 6 + .../truffle/r/nodes/builtin/InternalNode.java | 3 +- .../r/nodes/function/ArgumentMatcher.java | 6 +- .../oracle/truffle/r/runtime/RDeparse.java | 2 + .../com/oracle/truffle/r/runtime/RError.java | 3 + .../r/test/builtins/TestBuiltin_lapply.java | 22 +- .../r/test/builtins/TestBuiltin_log.java | 138 +++++++- .../r/test/builtins/TestBuiltin_mget.java | 3 +- .../r/test/builtins/TestBuiltin_nchar.java | 10 + .../r/test/builtins/TestBuiltin_nzchar.java | 5 + .../r/test/builtins/TestBuiltin_pmatch.java | 3 + .../r/test/builtins/TestBuiltin_sort.java | 20 ++ 25 files changed, 586 insertions(+), 64 deletions(-) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java index 42702fa5b1..496698e6d4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java @@ -37,10 +37,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.closures.RClosures; 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.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.nmath.GammaFunctions; import com.oracle.truffle.r.runtime.nmath.RMath; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -97,16 +94,6 @@ public class BaseGammaFunctions { } return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA()); } - - @Specialization - protected RDoubleVector lgamma(RAbstractIntVector x) { - return lgamma(RClosures.createIntToDoubleVector(x)); - } - - @Specialization - protected RDoubleVector lgamma(RAbstractLogicalVector x) { - return lgamma(RClosures.createLogicalToDoubleVector(x)); - } } @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java index 9ccf4cdf32..42030e3dde 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java @@ -253,8 +253,7 @@ public class GetFunctions { static { Casts casts = new Casts(MGet.class); casts.arg("x").mustBe(stringValue()).asStringVector(); - casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()), - chain(asIntegerVector()).with(findFirst().integerElement()).end()); + casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(instanceOf(RS4Object.class)), RError.Message.MUST_BE_ENVIRON2, "second argument"); casts.arg("mode").mustBe(stringValue()).asStringVector(); casts.arg("ifnotfound").mustBe(RAbstractListVector.class); casts.arg("inherits").asLogicalVector().findFirst().map(toBoolean()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java index 0b85315703..1984f96e01 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java @@ -38,7 +38,7 @@ public abstract class IntToBits extends RBuiltinNode { static { Casts casts = new Casts(IntToBits.class); - casts.arg("x").asIntegerVector(); + casts.arg("x").mustNotBeMissing().asIntegerVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java index 0b617546ed..2c391f761f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java @@ -44,7 +44,7 @@ public abstract class IntToUtf8 extends RBuiltinNode { static { Casts casts = new Casts(IntToUtf8.class); - casts.arg("x").asIntegerVector(); + casts.arg("x").mustNotBeMissing().asIntegerVector(); casts.arg("multiple").mustNotBeNull().asLogicalVector().findFirst().map(toBoolean()); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index 7f2f3de45e..f9e0d535c6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -74,7 +74,7 @@ public abstract class Lapply extends RBuiltinNode { // to make conversion of X parameter 100% correct, we'd need to match semantics of // asVector() to whatever GNU R is doing there; still this can be a problem only if the // internal is called directly (otherwise, it's guaranteed that it's a vector) - casts.arg("X").asVector(); + casts.arg("X").returnIf(instanceOf(RAbstractVector.class).not()).asVector(false); casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION); } @@ -86,6 +86,12 @@ public abstract class Lapply extends RBuiltinNode { return RDataFactory.createList(result, getNamesNode.getNames(vec)); } + @Specialization + protected Object lapply(VirtualFrame frame, Object x, RFunction fun) { + Object[] result = lapply.execute(frame, x, fun); + return RDataFactory.createList(result); + } + private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall { @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false); 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 e157019c8e..5d2ddfdef3 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 @@ -34,6 +34,8 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; +import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -41,19 +43,26 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; 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.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.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; +import java.util.Arrays; +import java.util.function.Function; public class LogFunctions { @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) public abstract static class Log extends RBuiltinNode { - private final NAProfile naProfile = NAProfile.create(); + private final NAProfile naX = NAProfile.create(); private final BranchProfile nanProfile = BranchProfile.create(); @Override @@ -64,54 +73,216 @@ public class LogFunctions { static { Casts casts = new Casts(Log.class); casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); - casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue()).asDoubleVector().findFirst(); + casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())).mapIf(numericValue(), Predef.asDoubleVector(), + Predef.asComplexVector()).asVector().findFirst(); + } + + static BinaryMapArithmeticFunctionNode createDivNode() { + return new BinaryMapArithmeticFunctionNode(BinaryArithmetic.DIV.createOperation()); } @Specialization - protected double log(int x, double base) { - return logb(x, base); + protected double log(byte x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); } @Specialization - protected double log(double x, double base) { - return logb(x, base); + protected double log(int x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); + } + + @Specialization + protected double log(double x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); + } + + @Specialization + protected RComplex log(RComplex x, double base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return x; + } + return logb(x, RComplex.valueOf(base, 0), divNode, naBase); + } + + @Specialization + protected RComplex log(byte x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.createComplexNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); + } + + @Specialization + protected RComplex log(int x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.createComplexNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); + } + + @Specialization + protected RComplex log(double x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.createComplexNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); + } + + @Specialization + protected RComplex log(RComplex x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.createComplexNA(); + } + return logb(x, base, divNode, naBase); } @Specialization protected RDoubleVector log(RAbstractIntVector vector, double base, @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, @Cached("create()") GetNamesAttributeNode getNamesNode, - @Cached("create()") GetDimAttributeNode getDimsNode) { - 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 (!naProfile.isNA(inputValue)) { - result = logb(inputValue, base); - } - resultVector[i] = result; - } - return createResult(vector, resultVector, base, copyAttrsNode, getNamesNode, getDimsNode); + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> xNACheck.convertIntToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck); } @Specialization protected RDoubleVector log(RAbstractDoubleVector vector, double base, @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, @Cached("create()") GetNamesAttributeNode getNamesNode, - @Cached("create()") GetDimAttributeNode getDimsNode) { - double[] doubleVector = new double[vector.getLength()]; - for (int i = 0; i < vector.getLength(); i++) { - double value = vector.getDataAt(i); - if (!RRuntime.isNA(value)) { - value = logb(value, base); + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> checkDouble(vector.getDataAt(index), xNACheck), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck); + } + + private double checkDouble(double d, NACheck na) { + na.check(d); + return d; + } + + @Specialization + protected RDoubleVector log(RAbstractLogicalVector vector, double base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> xNACheck.convertLogicalToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck); + } + + @Specialization + protected RComplexVector log(RAbstractComplexVector vector, double base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, RComplex.valueOf(base, 0), copyAttrsNode, getNamesNode, getDimsNode, divNode, xNACheck, baseNACheck); + } + + @Specialization + protected RAbstractComplexVector log(RAbstractIntVector vector, RComplex base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> xNACheck.convertIntToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); + } + + @Specialization + protected RAbstractComplexVector log(RAbstractDoubleVector vector, RComplex base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> xNACheck.convertDoubleToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); + } + + @Specialization + protected RAbstractComplexVector log(RAbstractLogicalVector vector, RComplex base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> xNACheck.convertLogicalToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); + } + + @Specialization + protected RComplexVector log(RAbstractComplexVector vector, RComplex base, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return log(vector, base, index -> checkComplex(vector.getDataAt(index), xNACheck), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); + } + + private RComplex checkComplex(RComplex rc, NACheck xNACheck) { + xNACheck.check(rc); + return rc; + } + + private RDoubleVector log(RAbstractVector vector, double base, Function<Integer, Double> toDouble, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, + GetDimAttributeNode getDimsNode, NACheck xNACheck, NACheck baseNACheck) { + baseNACheck.enable(base); + double[] resultVector = new double[vector.getLength()]; + if (baseNACheck.check(base)) { + Arrays.fill(resultVector, 0, resultVector.length, base); + } else if (Double.isNaN(base)) { + nanProfile.enter(); + Arrays.fill(resultVector, 0, resultVector.length, Double.NaN); + } else { + xNACheck.enable(vector); + Runnable[] warningResult = new Runnable[1]; + for (int i = 0; i < vector.getLength(); i++) { + double value = toDouble.apply(i); + if (!naX.isNA(value)) { + resultVector[i] = logb(value, base, warningResult); + } else { + resultVector[i] = value; + } + } + if (warningResult[0] != null) { + warningResult[0].run(); } - doubleVector[i] = value; } - return createResult(vector, doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode); + boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA(); + return createResult(vector, resultVector, complete, copyAttrsNode, getNamesNode, getDimsNode); } - private double logb(double x, double base) { - if (naProfile.isNA(base)) { + private double logb(double x, double base, NAProfile naBase) { + if (naBase.isNA(base)) { return RRuntime.DOUBLE_NA; } @@ -119,16 +290,118 @@ public class LogFunctions { nanProfile.enter(); return base; } + Runnable[] warningResult = new Runnable[1]; + double ret = logb(x, base, warningResult); + if (warningResult[0] != null) { + warningResult[0].run(); + } + return ret; + } + + private double logb(double x, double base, Runnable[] warningResult) { + double logx = Math.log(x); + if (Double.isNaN(logx)) { + warningResult[0] = () -> RError.warning(this, RError.Message.NAN_PRODUCED); + } + if (base == Math.E) { + return logx; + } + + double result = logx / Math.log(base); + if (warningResult[0] == null && Double.isNaN(result)) { + warningResult[0] = () -> RError.warning(RError.SHOW_CALLER, RError.Message.NAN_PRODUCED); + } + + return result; + } + + private RComplexVector log(RAbstractVector vector, RComplex base, Function<Integer, RComplex> toComplex, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode, + GetNamesAttributeNode getNamesNode, CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) { + baseNACheck.enable(base); + double[] complexVector = new double[vector.getLength() * 2]; + if (baseNACheck.check(base)) { + Arrays.fill(complexVector, 0, complexVector.length, RRuntime.DOUBLE_NA); + } else if (Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart())) { + nanProfile.enter(); + Arrays.fill(complexVector, 0, complexVector.length, Double.NaN); + } else { + xNACheck.enable(vector); + boolean seenNaN = false; + for (int i = 0; i < vector.getLength(); i++) { + RComplex value = toComplex.apply(i); + if (!naX.isNA(value)) { + RComplex rc = logb(value, base, divNode, false); + seenNaN = isNaN(rc); + fill(complexVector, i * 2, rc); + } else { + fill(complexVector, i * 2, value); + } + } + if (seenNaN) { + RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log"); + } + } + boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA(); + return createResult(vector, complexVector, complete, getDimsNode, getNamesNode, copyAttrsNode); + } + + private void fill(double[] array, int i, RComplex rc) { + array[i] = rc.getRealPart(); + array[i + 1] = rc.getImaginaryPart(); + } + + private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, NAProfile naBase) { + if (naBase.isNA(base)) { + return RRuntime.createComplexNA(); + } + if (isNaN(base)) { + nanProfile.enter(); + return base; + } + return logb(x, base, div, true); + } + + private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, boolean nanWarning) { + RComplex logx = logb(x); + if (base.getRealPart() == Math.E) { + return logx; + } - return Math.log(x) / Math.log(base); + RComplex logbase = logb(base); + RComplex ret = div.applyComplex(logx, logbase); + if (nanWarning && isNaN(ret)) { + RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log"); + } + return ret; + } + + private RComplex logb(RComplex x) { + double re = x.getRealPart(); + double im = x.getImaginaryPart(); + + double mod = RComplex.abs(re, im); + double arg = Math.atan2(im, re); + + return RComplex.valueOf(Math.log(mod), arg); } - private static RDoubleVector createResult(RAbstractVector source, double[] resultData, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, + private static RDoubleVector createResult(RAbstractVector source, double[] resultData, boolean complete, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, GetDimAttributeNode getDimsNode) { - RDoubleVector result = RDataFactory.createDoubleVector(resultData, source.isComplete() && !RRuntime.isNA(base), getDimsNode.getDimensions(source), getNamesNode.getNames(source)); + RDoubleVector result = RDataFactory.createDoubleVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source)); copyAttrsNode.execute(source, result); return result; } + + private RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode, + CopyOfRegAttributesNode copyAttrsNode) { + RComplexVector result = RDataFactory.createComplexVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source)); + copyAttrsNode.execute(source, result); + return result; + } + + private boolean isNaN(RComplex base) { + return Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart()); + } } @RBuiltin(name = "log10", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java index a7ed208b7c..64f1c93b58 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java @@ -46,6 +46,11 @@ import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "missing", kind = PRIMITIVE, nonEvalArgs = 0, parameterNames = {"x"}, behavior = COMPLEX) public abstract class Missing extends RBuiltinNode { + static { + Casts casts = new Casts(Missing.class); + casts.arg("x").allowMissing(); + } + @Specialization protected byte missing(VirtualFrame frame, RPromise promise, @Cached("create(0)") MissingCheckCache cache) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java index 92e5e4f943..7f3e1055f3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java @@ -59,7 +59,7 @@ public abstract class NChar extends RBuiltinNode { static { Casts casts = new Casts(NChar.class); - casts.arg("x").allowNull().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false)); + casts.arg("x").mustNotBeMissing().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false)); casts.arg("type").asStringVector().findFirst().mustBe(lengthGt(0)); casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java index ee7883c4a4..b8ec8ffd1b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java @@ -28,10 +28,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -68,4 +70,10 @@ public abstract class NZChar extends RBuiltinNode { } return RDataFactory.createLogicalVector(result, /* complete: */ keepNA && !hasNA); } + + @Specialization + protected RLogicalVector rev(@SuppressWarnings("unused") RMissing value, @SuppressWarnings("unused") boolean keepNA) { + throw RError.error(this, RError.Message.ARGUMENT_NOT_MATCH, "keepNA", "x"); + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java index 55db842837..b9e0292d51 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; @@ -30,11 +29,14 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "pmatch", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "duplicates.ok"}, behavior = PURE) @@ -46,12 +48,27 @@ public abstract class PMatch extends RBuiltinNode { static { Casts casts = new Casts(PMatch.class); - casts.arg("x").asStringVector(); - casts.arg("table").asStringVector(); - casts.arg("nomatch").mapNull(constant(RRuntime.INT_NA)).asIntegerVector(); + casts.arg("x").mustNotBeMissing().asStringVector(); + casts.arg("table").mustNotBeMissing().asStringVector(); + casts.arg("nomatch").mustNotBeMissing().mapIf(nullValue(), constant(RRuntime.INT_NA)).asIntegerVector().findFirst(); casts.arg("duplicates.ok").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); } + @Specialization + protected RIntVector doPMatch(RNull x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + + @Specialization + protected RIntVector doPMatch(RAbstractStringVector x, RNull table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + + @Specialization + protected RIntVector doPMatch(RNull x, RNull table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + @Specialization protected RIntVector doPMatch(RAbstractStringVector x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) { int xl = x.getLength(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java index 78f3f3d6cd..f4f37e8495 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java @@ -105,7 +105,7 @@ public abstract class Parse extends RBuiltinNode { // Note: string is captured by the R wrapper and transformed to a file, other types not casts.arg("conn").defaultError(MUST_BE_STRING_OR_CONNECTION, "file").mustNotBeNull().asIntegerVector().findFirst(); casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).replaceNA(-1); - casts.arg("text").asStringVector(); + casts.arg("text").mustNotBeMissing().asStringVector(); casts.arg("prompt").asStringVector().findFirst("?"); casts.arg("encoding").mustBe(stringValue()).asStringVector().findFirst(); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java index e888b61de4..c009097405 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java @@ -35,6 +35,7 @@ import java.util.Set; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.DCF; import com.oracle.truffle.r.runtime.RError; @@ -54,8 +55,8 @@ public abstract class ReadDCF extends RBuiltinNode { static { Casts casts = new Casts(ReadDCF.class); casts.arg("conn").defaultError(Message.INVALID_CONNECTION).asIntegerVector().findFirst(); - casts.arg("fields").mapNull(emptyStringVector()).asStringVector(); - casts.arg("keepwhite").mapNull(emptyStringVector()).asStringVector(); + casts.arg("fields").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector(); + casts.arg("keepwhite").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java index 370208bd12..f06a920474 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java @@ -38,8 +38,13 @@ import java.util.Collections; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; +import static com.oracle.truffle.r.runtime.RError.Message.NOT_NUMERIC_VECTOR; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -55,6 +60,7 @@ 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.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /** * The internal functions mandated by {@code base/sort.R}. N.B. We use the standard JDK sorting @@ -200,8 +206,8 @@ public class SortFunctions { static { Casts casts = new Casts(QSort.class); - addCastForX(casts); - addCastForDecreasing(casts); + casts.arg("x").defaultError(NOT_NUMERIC_VECTOR).mustBe(instanceOf(RAbstractListVector.class).not()).mustBe(integerValue().or(doubleValue())); + casts.arg("decreasing").mapIf(numericValue().not(), Predef.constant(RRuntime.LOGICAL_TRUE)).asLogicalVector().findFirst().map(toBoolean()); } @Specialization @@ -246,6 +252,17 @@ public class SortFunctions { protected RLogicalVector sort(RAbstractLogicalVector vec, Object partial) { return jdkSort(vec, false); } + + @SuppressWarnings("unused") + @Specialization + protected RLogicalVector sort(RAbstractComplexVector vec, Object partial) { + throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); // [TODO] implement + } + + @Specialization + protected RNull sort(RNull vec, Object partial) { + return RNull.instance; + } } /** diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java index d83ea35129..16830767a1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java @@ -26,12 +26,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; +import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "next", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) public abstract class NextBuiltin extends RBuiltinNode { + + static { + noCasts(NextBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java index 8d1683a4c1..6b29fde993 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java @@ -147,7 +147,8 @@ public abstract class InternalNode extends OperatorNode { // verify the number of arguments if (factory.getSignature().getVarArgCount() == 0) { if (callArgs.length != factory.getSignature().getLength()) { - throw RError.error(RError.SHOW_CALLER, Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", factory.getSignature().getLength()); + throw RError.error(RError.SHOW_CALLER, callArgs.length == 1 ? Message.ARGUMENT_PASSED : Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", + factory.getSignature().getLength()); } for (int i = 0; i < callArgs.length; i++) { if (callArgs[i] instanceof RSyntaxConstant && ((RSyntaxConstant) callArgs[i]).getValue() == REmpty.instance) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java index 1cf534c2eb..29f3ee5e58 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java @@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments; +import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -59,6 +60,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * <p> @@ -270,14 +272,14 @@ public class ArgumentMatcher { // TODO: this error handling code takes many assumptions about the argument types RArgsValuesAndNames varArg = (RArgsValuesAndNames) frame.getObject(frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME)); RPromise promise = (RPromise) varArg.getArguments()[((VarArgNode) node).getIndex()]; - return promise.getRep().asRSyntaxNode().getSourceSection().getCode(); + return RDeparse.deparseSyntaxElement(promise.getRep().asRSyntaxNode()); } catch (FrameSlotTypeException | ClassCastException e) { throw RInternalError.shouldNotReachHere(); } } else { String code; if (node.asRSyntaxNode().getSourceSection() != null) { - code = node.asRSyntaxNode().getSourceSection().getCode(); + code = RDeparse.deparseSyntaxElement(node.asRSyntaxNode()); } else { code = "<unknown>"; // RDeparse.deparseForPrint(node.asRSyntaxNode()); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index c2591fed09..3fe65ddf1d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -682,6 +682,8 @@ public class RDeparse { append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>'); } else if (value instanceof REnvironment) { append("<environment>"); + } else if (value instanceof REmpty) { + append(""); } else if (value instanceof TruffleObject) { append("<truffle object>"); } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index a73c50c1f7..2930d06222 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -338,6 +338,7 @@ public final class RError extends RuntimeException { NON_CHARACTER_NAMES("non-character names"), NON_NUMERIC_MATH("non-numeric argument to mathematical function"), NAN_PRODUCED("NaNs produced"), + NAN_PRODUCED_IN_FUNCTION("NaNs produced in function \"%s\""), NUMERIC_COMPLEX_MATRIX_VECTOR("requires numeric/complex matrix/vector arguments"), NON_CONFORMABLE_ARGS("non-conformable arguments"), DATA_VECTOR("'data' must be of a vector type"), @@ -509,6 +510,7 @@ public final class RError extends RuntimeException { ATTRIBUTE_VECTOR_SAME_LENGTH("'%s' attribute [%d] must be the same length as the vector [%d]"), SCAN_UNEXPECTED("scan() expected '%s', got '%s'"), MUST_BE_ENVIRON("'%s' must be an environment"), + MUST_BE_ENVIRON2("%s must be an environment"), MUST_BE_INTEGER("'%s' must be an integer"), UNUSED_ARGUMENT("unused argument (%s)"), UNUSED_ARGUMENTS("unused arguments (%s)"), @@ -620,6 +622,7 @@ public final class RError extends RuntimeException { SUBSCRIPT_TYPES("incompatible types (from %s to %s) in [[ assignment"), INCOMPATIBLE_METHODS("incompatible methods (\"%s\", \"%s\") for \"%s\""), RECURSIVE_INDEXING_FAILED("recursive indexing failed at level %d"), + ARGUMENT_PASSED("%d argument passed to %s which requires %d"), ARGUMENTS_PASSED("%d arguments passed to %s which requires %d"), ARGUMENT_IGNORED("argument '%s' will be ignored"), NOT_CHARACTER_VECTOR("'%s' must be a character vector"), diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java index 72228b0de6..57999d315e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -33,6 +33,26 @@ public class TestBuiltin_lapply extends TestBase { assertEval("{ l <- list(list(1),list(2),list(3)); f <- function(a) { lapply(a, function(x) lapply(x, function(y) print(y))) }; f(l)}"); assertEval("{ .Internal(lapply(1:4, 42)) }"); + + assertEval("lapply(NULL, function(x){x})"); + assertEval("lapply(NA, FUN=function(x){x})"); + assertEval("lapply(FUN=function(x){x})"); + assertEval("lapply(1:4, NULL)"); + assertEval("lapply(1:4, NA)"); + assertEval(Output.IgnoreErrorContext, "lapply(X=1:4)"); + assertEval("lapply(X=function() {print('test')}, FUN=function(x){x})"); + assertEval(Output.IgnoreWhitespace, "lapply(X=c(function() {print(\"test1\")}, function() {print(\"test2\")}), FUN=function(x){x})"); + assertEval("lapply(X=environment(), FUN=function(x){x})"); + + assertEval("f <- function(...) { .Internal(lapply(NULL, function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(NA, FUN=function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(FUN=function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(1:4, NULL)) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(1:4, NA)) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(X=1:4)) }; f()"); + assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=function() {print('test')}, FUN=function(x){x})) }; f()"); + assertEval(Ignored.ImplementationError, "f <- function(...) { .Internal(lapply(X=c(function() {print('test1')}, function() {print('test2')}), FUN=function(x){x})) }; f()"); + assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=environment(), FUN=function(x){x})) }; f()"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java index 1cb8f1375e..4e5da9071a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -34,4 +34,140 @@ public class TestBuiltin_log extends TestBase { assertEval("{ log(c(2,3), NA) } "); assertEval("{ log(c(2,3), 0/0) } "); } + + @Test + public void testLogLogical() { + assertEval("{ log(T) }"); + assertEval("{ log(c(T)) }"); + assertEval("{ log(c(T, F)) }"); + assertEval("{ log(c(T, F), T) }"); + assertEval("{ log(T, T) }"); + assertEval("{ log(T, F) }"); + assertEval("{ log(F, F) }"); + assertEval("{ log(F, T) }"); + assertEval("{ log(c(T, T), NA) }"); + assertEval("{ log(c(T, T), NaN) }"); + } + + @Test + public void testLogInt() { + assertEval("{ log(1L) }"); + assertEval("{ log(-1L) }"); + assertEval("{ log(0L) }"); + assertEval("{ log(NA_integer_) }"); + assertEval("{ log(0L, NA_integer_) }"); + assertEval("{ log(c(0L, NA_integer_)) }"); + assertEval("{ log(1L, 1L) }"); + assertEval("{ log(10L, 1L) }"); + assertEval("{ log(10L, -1L) }"); + assertEval("{ log(10L, 10L) }"); + assertEval("{ log(c(1L, 1L, 0L, 10L), 10L) }"); + assertEval("{ log(c(1L, 0L, 10L), 1L) }"); + assertEval("{ log(c(1L, 2L), NA) }"); + assertEval("{ log(c(1L, 2L), NaN) }"); + assertEval("{ log(c(1L, 2L, NA)) }"); + } + + @Test + public void testLogDouble() { + assertEval("{ log(1.1) }"); + assertEval("{ log(-1.1) }"); + assertEval("{ log(0.0) }"); + assertEval("{ log(NA_real_) }"); + assertEval("{ log(10, NA_real_) }"); + assertEval("{ log(c(10, NA_real_)) }"); + assertEval("{ log(1.0, 1.0) }"); + assertEval("{ log(10.0, 1.0) }"); + assertEval("{ log(10.0, -1.0) }"); + assertEval("{ log(10.0, 10.0) }"); + assertEval("{ log(c(1.0, 0.0, 10.0), 10.0) }"); + assertEval("{ log(c(1.0, 0.0, 10.0), 1.0) }"); + assertEval("{ log(c(1.0, 2.0), NA) }"); + assertEval("{ log(c(1.0, 2.0), NaN) }"); + assertEval("{ log(c(1.0, 2.0, NA)) }"); + } + + @Test + public void testLogComplex() { + assertEval("{ log(0+0i) }"); + + // NaN warnigns + assertEval("{ log(0+0i, 0) }"); + assertEval("{ log(0L, 0+0i) }"); + assertEval("{ log(0.0, 0+0i) }"); + assertEval("{ log(F, 0+0i) }"); + assertEval("{ log(0+0i, 0+0i) }"); + + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(0+0i, 1) }"); + + assertEval("{ log(1+1i) }"); + assertEval("{ log(complex(real=NA, imaginary=1i)) }"); + assertEval("{ log(complex(real=1, imaginary=NA)) }"); + assertEval("{ log(complex(real=NA, imaginary=NA)) }"); + assertEval("{ log(NA_complex_) }"); + assertEval("{ log(1+1i, NA_complex_) }"); + assertEval("{ log(c(1+1i, NA_complex_)) }"); + assertEval("{ log(1+1i, 0) }"); + + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(1+1i, 1) }"); + + assertEval("{ log(10+1i, 10) }"); + assertEval("{ log(10-1i, 10) }"); + assertEval("{ log(-10-1i, 10) }"); + assertEval("{ log(10+1i, -10) }"); + assertEval("{ log(10+10i, 10) }"); + assertEval("{ log(c(1+1i)) }"); + assertEval("{ log(c(1+1i), 0) }"); + + assertEval("{ log(c(1+1i, 2+2i), NA) }"); + assertEval("{ log(c(1+1i, 2+2i), NaN) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NaN)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=1)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=NaN)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NA)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NA, imaginary=1)) }"); + assertEval("{ log(c(1+1i, 2+2i, complex(real=NA, imaginary=NA))) }"); + + assertEval("{ log(c(10+1i, 10), 10) }"); + assertEval("{ log(c(10+10i, 10), 10) }"); + assertEval("{ log(c(1+1i, 2+1i)) }"); + + assertEval("{ log(c(10, 10+10i), 10) }"); + assertEval("{ log(c(10.0, 10+10i), 10) }"); + assertEval("{ log(c(T, 10+10i), 10) }"); + + assertEval("{ log(1, 1+1i) }"); + assertEval("{ log(10, 10+10i) }"); + assertEval("{ log(1.0, 1+1i) }"); + assertEval("{ log(10.0, 1+1i) }"); + assertEval("{ log(T, 1+1i) }"); + + assertEval("{ log(1+1i, 1+1i) }"); + assertEval("{ log(1+1i, 1-1i) }"); + assertEval("{ log(1+1i, -1-1i) }"); + assertEval("{ log(10+10i, 10+10i) }"); + assertEval("{ log(1+1i, 10+10i) }"); + + assertEval("{ log(c(10, 10), 10+10i) }"); + assertEval("{ log(c(10.0, 10.0), 10+10i) }"); + assertEval("{ log(c(T, F), 1+1i) }"); + assertEval("{ log(c(10+10i, 10+10i), 10+10i) }"); + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(complex(real=sqrt(.5), imaginary=sqrt(.5)), 1) }"); + } + + @Test + public void testProducedManyNaNsButOneWarnig() { + assertEval("{ log(c(F, F), F) }"); + assertEval("{ log(c(1L, 1L), 1L) }"); + assertEval("{ log(c(1.0, 1.0), 1.0) }"); + assertEval("{ log(c(0+0i, 0+0i), 0) }"); + + assertEval("{ log(c(F, F), 0+0i) }"); + assertEval("{ log(c(0L, 0L), 0+0i) }"); + assertEval("{ log(c(0.0, 0.0), 0+0i) }"); + assertEval("{ log(c(0+0i, 0+0i), 0+0i) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java index 7f3b487981..e27d7728fc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -20,6 +20,7 @@ public class TestBuiltin_mget extends TestBase { @Test public void testMGet() { assertEval("{ a<- 1; b <- 2; mget(c(\"a\", \"b\")) }"); + assertEval("{ a<- 1; b <- 2; mget(c('a', 'b'), envir=1) }"); assertEval("{ a<- 1; b <- 2; f <- function() { mget(c(\"a\", \"b\"), inherits=TRUE)}; f() }"); assertEval("{ a<- 1; mget(c(\"a\", \"b\"), ifnotfound=list(100)) }"); assertEval("{ b <- 2; f <- function() { mget(c(\"a\", \"b\"), ifnotfound=list(100), inherits=TRUE)}; f() }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java index a62ed37731..704e3e765b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java @@ -99,4 +99,14 @@ public class TestBuiltin_nchar extends TestBase { assertEval("nchar('aasd', type='charsxzy')"); assertEval("nchar('aasd', type='')"); } + + @Test + public void testNULLAndMissing() { + assertEval("nchar()"); + assertEval("nchar(type = 'chars', allowNA = FALSE, keepNA = NA)"); + assertEval("nchar(x=NULL)"); + assertEval("nchar(x=NULL, type = 'chars', allowNA = FALSE, keepNA = NA)"); + assertEval("nchar(wrongArg=\"a\")"); + assertEval("nchar(wrongArg='a')"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java index 980d16177b..0c86bc1ebd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java @@ -83,5 +83,10 @@ public class TestBuiltin_nzchar extends TestBase { public void nonStringArgs() { assertEval("nzchar(list('x', 42, list('a'), list()))"); assertEval("nzchar(NULL)"); + assertEval("nzchar(NA)"); + assertEval("nzchar(keepNA=F)"); + assertEval("nzchar(keepNA=NA)"); + assertEval("nchar(wrongArgName=\"a\")"); + assertEval("nchar(wrongArgName='a')"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java index 70bc9c36d2..53fd3e3a12 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java @@ -61,6 +61,9 @@ public class TestBuiltin_pmatch extends TestBase { public void testArgumentsCasts() { assertEval("pmatch(NULL, 1)"); assertEval("pmatch(1, NULL)"); + assertEval("pmatch(x=NULL, table=NULL)"); + assertEval("pmatch(x=1)"); + assertEval("pmatch(table=1)"); assertEval("pmatch(1:5, c(1,3), nomatch=NULL)"); assertEval("pmatch(1:5, c(1,3), nomatch='str')"); assertEval("pmatch(1:5, c(1,3), duplicates.ok=42)"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java index 96970b11a2..081df3a505 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java @@ -130,4 +130,24 @@ public class TestBuiltin_sort extends TestBase { assertEval("{ .Internal(sort(NULL, FALSE)) }"); assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }"); } + + @Test + public void testQSort() { + assertEval("{ .Internal(qsort(NULL, F)) }"); + assertEval("{ .Internal(qsort(NULL, NULL)) }"); + // seems that when the value provided for decreased is whatever else than FALSE + // then it is interpreted as TRUE. In such a case qsort returns a list containing + // two vectors: the values sorted as in decreased=F and the original indices giving + // the decreased order. NOTE that even though the FastR impl of qsort always returns + // only 1 increasing/decreasing vector, it has no effect on the overall sort function. + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(1, decreased=NULL)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), T)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 1)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 'a')) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), c('a'))) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), list('a'))) }"); + assertEval("{ .Internal(qsort(list(1), F)) }"); + assertEval("{ .Internal(qsort(1, F)) }"); + assertEval("{ .Internal(qsort(c(1), F)) }"); + } } -- GitLab