diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java index cc8bb51840f6ba32e8df0069bd2637e80d157460..890886ce7a457a23ccdb71278108283eda71ddc8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java @@ -24,6 +24,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -62,8 +63,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 { CompilerDirectives.transferToInterpreterAndInvalidate(); prodRecursive = insert(ProdNodeGen.create()); } - Object ret = prodRecursive.executeObject(args.getArgument(0)); - if (argsLen != 1) { + Object ret = 1d; + if (argsLen > 0) { double prodReal; double prodImg; boolean complex; @@ -77,7 +78,7 @@ public abstract class Prod extends RBuiltinNode.Arg2 { prodImg = 0d; complex = false; } - for (int i = 1; i < argsLen; i++) { + for (int i = 0; i < argsLen; i++) { Object aProd = prodRecursive.executeObject(args.getArgument(i)); double aProdReal; double aProdImg; @@ -108,8 +109,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 { @Specialization protected double prod(RAbstractDoubleVector x) { RAbstractDoubleVector profiledVec = intVecProfile.profile(x); - double product = profiledVec.getDataAt(0); - for (int k = 1; k < profiledVec.getLength(); k++) { + double product = 1; + for (int k = 0; k < profiledVec.getLength(); k++) { product = prod.op(product, profiledVec.getDataAt(k)); } return product; @@ -118,8 +119,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 { @Specialization protected double prod(RAbstractIntVector x) { RAbstractIntVector profiledVec = intVecProfile.profile(x); - double product = profiledVec.getDataAt(0); - for (int k = 1; k < profiledVec.getLength(); k++) { + double product = 1; + for (int k = 0; k < profiledVec.getLength(); k++) { product = prod.op(product, profiledVec.getDataAt(k)); } return product; @@ -128,8 +129,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 { @Specialization protected double prod(RAbstractLogicalVector x) { RAbstractLogicalVector profiledVec = intVecProfile.profile(x); - double product = profiledVec.getDataAt(0); - for (int k = 1; k < profiledVec.getLength(); k++) { + double product = 1; + for (int k = 0; k < profiledVec.getLength(); k++) { product = prod.op(product, profiledVec.getDataAt(k)); } return product; @@ -138,8 +139,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 { @Specialization protected RComplex prod(RAbstractComplexVector x) { RAbstractComplexVector profiledVec = intVecProfile.profile(x); - RComplex product = profiledVec.getDataAt(0); - for (int k = 1; k < profiledVec.getLength(); k++) { + RComplex product = RDataFactory.createComplexRealOne(); + for (int k = 0; k < profiledVec.getLength(); k++) { RComplex a = profiledVec.getDataAt(k); product = prod.op(product.getRealPart(), product.getImaginaryPart(), a.getRealPart(), a.getImaginaryPart()); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 8233f4cc27ba2047cc64a0bf5e8ff340351c6144..ea692637ede82a350f5340d74e004d14157f6d00 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -405,6 +405,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("create()") ClassHierarchyNode classHierarchyNodeY, @Cached("createWithException()") S3FunctionLookupNode dispatchLookupY, @Cached("createIdentityProfile()") ValueProfile builtinProfile, + @Cached("createBinaryProfile()") ConditionProfile emptyArgumentsProfile, @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileX, @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileY, @Cached("createBinaryProfile()") ConditionProfile mismatchProfile, @@ -420,6 +421,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS Object[] args = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : callArguments.evaluateFlattenObjects(frame, lookupVarArgs(frame)); ArgumentsSignature argsSignature = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getSignature() : callArguments.flattenNames(lookupVarArgs(frame)); + if (emptyArgumentsProfile.profile(args.length == 0)) { + // nothing to dispatch on, this is a valid situation, e.g. prod() == 1 + return call.execute(frame, function, new RArgsValuesAndNames(args, argsSignature), null, null); + } + RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); RDispatch dispatch = builtin.getDispatch(); 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 b1726a12cfb2df32babfc62ba312c5052b0d7ebd..a38cc30a9c9e25f7ac2c9c11a76619f75ea1cf50 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 @@ -44965,6 +44965,22 @@ age 0.00561 0.012 0.00872 0.22 1.0 0.64000 sex -1.65487 0.483 0.38527 11.74 1.0 0.00061 frailty(id, dist = 't', c 20.33 13.9 0.12000 +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#prod() +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#prod(complex()) +[1] 1+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#prod(numeric()) +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{ foo <- function(...) prod(...); foo(); } +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# #{prod('a')} Error in prod("a") : invalid 'type' (character) of argument diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java index 7d0b9d0fddf7dfbc8d302c572ab70c8403083aa1..a31d73816c2f5602bf94c40391e595e3e1ebac35 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java @@ -92,6 +92,10 @@ public class TestBuiltin_prod extends TestBase { assertEval("{prod(42,2+3i)}"); assertEval("{prod('a')}"); assertEval("{prod(list())}"); + assertEval("prod()"); + assertEval("prod(numeric())"); + assertEval("prod(complex())"); + assertEval("{ foo <- function(...) prod(...); foo(); }"); } @Test