From f5265173e99b8cf7154854c8cefa5d60e0729cc0 Mon Sep 17 00:00:00 2001 From: Lukas Stadler <lukas.stadler@oracle.com> Date: Tue, 11 Nov 2014 12:54:09 +0100 Subject: [PATCH] check for NA results in binary boolean operations --- .../r/nodes/binary/BinaryBooleanNode.java | 173 +++++++++++++----- 1 file changed, 129 insertions(+), 44 deletions(-) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java index cd90c95aa5..4ed662fbd4 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java @@ -28,6 +28,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.unary.CastLogicalNode.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.closures.*; @@ -46,6 +47,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { private final NACheck leftNACheck = NACheck.create(); private final NACheck rightNACheck = NACheck.create(); + private final NAProfile resultNAProfile = NAProfile.create(); + public BinaryBooleanNode(BooleanOperationFactory factory) { this.factory = factory; this.logic = factory.create(); @@ -1483,19 +1486,27 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { // int vector and scalar implementation + private RLogicalVector createResult(RAbstractVector left, byte[] result, boolean naResult) { + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); + ret.copyNamesFrom(left); + return ret; + } + private RLogicalVector performIntVectorOp(RAbstractIntVector left, double rightValue, boolean reverse) { int length = left.getLength(); byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { int leftValue = left.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performIntVectorOp(RAbstractIntVector left, String rightValue, boolean reverse) { @@ -1503,14 +1514,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = RRuntime.intToString(left.getDataAt(i), false); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performIntVectorOp(RAbstractIntVector left, RComplex rightValue, boolean reverse) { @@ -1518,9 +1531,13 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = RRuntime.int2complex(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); @@ -1535,14 +1552,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { double leftValue = left.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performDoubleVectorOp(RAbstractDoubleVector left, String rightValue, boolean reverse) { @@ -1550,14 +1569,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = RRuntime.doubleToString(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performDoubleVectorOp(RAbstractDoubleVector left, RComplex rightValue, boolean reverse) { @@ -1565,9 +1586,13 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = RRuntime.double2complex(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); @@ -1582,14 +1607,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { byte leftValue = left.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performLogicalVectorOp(RAbstractLogicalVector left, String rightValue, boolean reverse) { @@ -1597,9 +1624,13 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = RRuntime.logicalToString(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); @@ -1612,14 +1643,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = RRuntime.logical2complex(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } // string vector and scalar implementation @@ -1629,14 +1662,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = left.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } // complex vector and scalar implementation @@ -1646,14 +1681,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = left.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performComplexVectorOp(RAbstractComplexVector left, String rightValue, boolean reverse) { @@ -1661,14 +1698,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = RRuntime.complexToString(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performRawVectorOp(RAbstractRawVector left, double rightValue, boolean reverse) { @@ -1676,14 +1715,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { double leftValue = RRuntime.raw2double(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performRawVectorOp(RAbstractRawVector left, String rightValue, boolean reverse) { @@ -1691,14 +1732,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = RRuntime.rawToString(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RLogicalVector performRawVectorOp(RAbstractRawVector left, RComplex rightValue, boolean reverse) { @@ -1706,14 +1749,16 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(rightValue); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = RRuntime.raw2complex(left.getDataAt(i)); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue)); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions()); - ret.copyNamesFrom(left); - return ret; + return createResult(left, result, naResult); } private RRawVector performRawVectorOp(RAbstractRawVector left, RRaw rightValue, boolean reverse) { @@ -1737,13 +1782,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(right); + boolean naResult = false; for (int i = 0; i < length; ++i) { int leftValue = left.getDataAt(i); int rightValue = right.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), + left.hasDimensions() ? left.getDimensions() : right.getDimensions()); ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right); return ret; } @@ -1758,17 +1808,21 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { rightNACheck.enable(right); int l = 0; int r = 0; + boolean naResult = false; for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) { int leftValue = left.getDataAt(l); int rightValue = right.getDataAt(r); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } boolean notMultiple = l != 0 || r != 0; if (notMultiple) { RError.warning(RError.Message.LENGTH_NOT_MULTI); } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection()); ret.copyNamesFrom(leftLength == resultLength ? left : right); return ret; @@ -1782,13 +1836,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(right); + boolean naResult = false; for (int i = 0; i < length; ++i) { double leftValue = left.getDataAt(i); double rightValue = right.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), + left.hasDimensions() ? left.getDimensions() : right.getDimensions()); ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right); return ret; } @@ -1803,17 +1862,21 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { rightNACheck.enable(right); int l = 0; int r = 0; + boolean naResult = false; for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) { double leftValue = left.getDataAt(l); double rightValue = right.getDataAt(r); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } boolean notMultiple = l != 0 || r != 0; if (notMultiple) { RError.warning(RError.Message.LENGTH_NOT_MULTI); } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection()); ret.copyNamesFrom(leftLength == resultLength ? left : right); return ret; @@ -1827,13 +1890,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(right); + boolean naResult = false; for (int i = 0; i < length; ++i) { String leftValue = left.getDataAt(i); String rightValue = right.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), + left.hasDimensions() ? left.getDimensions() : right.getDimensions()); ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right); return ret; } @@ -1848,17 +1916,21 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { rightNACheck.enable(right); int l = 0; int r = 0; + boolean naResult = false; for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) { String leftValue = left.getDataAt(l); String rightValue = right.getDataAt(r); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } boolean notMultiple = l != 0 || r != 0; if (notMultiple) { RError.warning(RError.Message.LENGTH_NOT_MULTI); } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection()); ret.copyNamesFrom(leftLength == resultLength ? left : right); return ret; @@ -1872,13 +1944,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { byte[] result = new byte[length]; leftNACheck.enable(left); rightNACheck.enable(right); + boolean naResult = false; for (int i = 0; i < length; ++i) { RComplex leftValue = left.getDataAt(i); RComplex rightValue = right.getDataAt(i); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), + left.hasDimensions() ? left.getDimensions() : right.getDimensions()); ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right); return ret; } @@ -1893,17 +1970,21 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { rightNACheck.enable(right); int l = 0; int r = 0; + boolean naResult = false; for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) { RComplex leftValue = left.getDataAt(l); RComplex rightValue = right.getDataAt(r); byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } boolean notMultiple = l != 0 || r != 0; if (notMultiple) { RError.warning(RError.Message.LENGTH_NOT_MULTI); } - RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); + RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA()); ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection()); ret.copyNamesFrom(leftLength == resultLength ? left : right); return ret; @@ -1915,10 +1996,14 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { assert areSameLength(left, right); int length = left.getLength(); byte[] result = new byte[length]; + boolean naResult = false; for (int i = 0; i < length; ++i) { RRaw leftValue = left.getDataAt(i); RRaw rightValue = right.getDataAt(i); byte resultValue = logic.op(leftValue, rightValue).getValue(); + if (resultNAProfile.isNA(resultValue)) { + naResult = true; + } result[i] = resultValue; } RRawVector ret = RDataFactory.createRawVector(result, left.hasDimensions() ? left.getDimensions() : right.getDimensions()); -- GitLab