diff --git a/java/algorithm/src/main/java/org/apache/arrow/algorithm/deduplicate/DeduplicationUtils.java b/java/algorithm/src/main/java/org/apache/arrow/algorithm/deduplicate/DeduplicationUtils.java index a9fe328125f..8c0c4af502d 100644 --- a/java/algorithm/src/main/java/org/apache/arrow/algorithm/deduplicate/DeduplicationUtils.java +++ b/java/algorithm/src/main/java/org/apache/arrow/algorithm/deduplicate/DeduplicationUtils.java @@ -22,6 +22,7 @@ import org.apache.arrow.vector.BitVectorHelper; import org.apache.arrow.vector.IntVector; import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.compare.Range; import org.apache.arrow.vector.compare.RangeEqualsVisitor; import io.netty.buffer.ArrowBuf; @@ -43,11 +44,11 @@ public static void populateRunStartIndicators(V vector, runStarts.setZero(0, bufSize); BitVectorHelper.setValidityBitToOne(runStarts, 0); - + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector, vector, false); + Range range = new Range(0, 0, 1); for (int i = 1; i < vector.getValueCount(); i++) { - RangeEqualsVisitor visitor = new RangeEqualsVisitor( - vector, i - 1, i, /* length */1, /* need check type*/false); - if (!visitor.equals(vector)) { + range.setLeftStart(i).setRightStart(i - 1); + if (!visitor.rangeEquals(range)) { BitVectorHelper.setValidityBitToOne(runStarts, i); } } diff --git a/java/vector/src/main/java/org/apache/arrow/vector/compare/ApproxEqualsVisitor.java b/java/vector/src/main/java/org/apache/arrow/vector/compare/ApproxEqualsVisitor.java index 3e9783f43d6..1c12768547f 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/compare/ApproxEqualsVisitor.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/compare/ApproxEqualsVisitor.java @@ -17,18 +17,10 @@ package org.apache.arrow.vector.compare; -import java.util.List; - import org.apache.arrow.vector.BaseFixedWidthVector; -import org.apache.arrow.vector.FieldVector; import org.apache.arrow.vector.Float4Vector; import org.apache.arrow.vector.Float8Vector; import org.apache.arrow.vector.ValueVector; -import org.apache.arrow.vector.complex.BaseRepeatedValueVector; -import org.apache.arrow.vector.complex.FixedSizeListVector; -import org.apache.arrow.vector.complex.ListVector; -import org.apache.arrow.vector.complex.NonNullableStructVector; -import org.apache.arrow.vector.complex.UnionVector; /** * Visitor to compare floating point. @@ -49,24 +41,16 @@ public class ApproxEqualsVisitor extends RangeEqualsVisitor { private DiffFunction doubleDiffFunction = (Double value1, Double value2) -> Math.abs(value1 - value2); - public ApproxEqualsVisitor(ValueVector right, float epsilon) { - this (right, epsilon, epsilon, true); - } - - public ApproxEqualsVisitor(ValueVector right, float floatEpsilon, double doubleEpsilon) { - this (right, floatEpsilon, doubleEpsilon, true); - } - - public ApproxEqualsVisitor(ValueVector right, float floatEpsilon, double doubleEpsilon, boolean typeCheckNeeded) { - this (right, floatEpsilon, doubleEpsilon, typeCheckNeeded, 0, 0, right.getValueCount()); - } - /** - * Construct an instance. + * Constructs a new instance. + * + * @param left left vector + * @param right right vector + * @param floatEpsilon difference for float values + * @param doubleEpsilon difference for double values */ - public ApproxEqualsVisitor(ValueVector right, float floatEpsilon, double doubleEpsilon, boolean typeCheckNeeded, - int leftStart, int rightStart, int length) { - super(right, rightStart, leftStart, length, typeCheckNeeded); + public ApproxEqualsVisitor(ValueVector left, ValueVector right, float floatEpsilon, double doubleEpsilon) { + super(left, right, true); this.floatEpsilon = floatEpsilon; this.doubleEpsilon = doubleEpsilon; } @@ -80,151 +64,38 @@ public void setDoubleDiffFunction(DiffFunction doubleDiffFunction) { } @Override - public Boolean visit(BaseFixedWidthVector left, Void value) { + public Boolean visit(BaseFixedWidthVector left, Range range) { if (left instanceof Float4Vector) { - return validate(left) && float4ApproxEquals((Float4Vector) left); + return float4ApproxEquals(range); } else if (left instanceof Float8Vector) { - return validate(left) && float8ApproxEquals((Float8Vector) left); + return float8ApproxEquals(range); } else { - return super.visit(left, value); + return super.visit(left, range); } } @Override - protected boolean compareUnionVectors(UnionVector left) { - - UnionVector rightVector = (UnionVector) right; - - List leftChildren = left.getChildrenFromFields(); - List rightChildren = rightVector.getChildrenFromFields(); - - if (leftChildren.size() != rightChildren.size()) { - return false; - } - - for (int k = 0; k < leftChildren.size(); k++) { - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(rightChildren.get(k), - floatEpsilon, doubleEpsilon); - if (!leftChildren.get(k).accept(visitor, null)) { - return false; - } - } - return true; + protected ApproxEqualsVisitor createInnerVisitor(ValueVector left, ValueVector right) { + return new ApproxEqualsVisitor(left, right, floatEpsilon, doubleEpsilon); } - @Override - protected boolean compareStructVectors(NonNullableStructVector left) { + private boolean float4ApproxEquals(Range range) { + Float4Vector leftVector = (Float4Vector) getLeft(); + Float4Vector rightVector = (Float4Vector) getRight(); - NonNullableStructVector rightVector = (NonNullableStructVector) right; + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; - if (!left.getChildFieldNames().equals(rightVector.getChildFieldNames())) { - return false; - } + boolean isNull = leftVector.isNull(leftIndex); - for (String name : left.getChildFieldNames()) { - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(rightVector.getChild(name), - floatEpsilon, doubleEpsilon); - if (!left.getChild(name).accept(visitor, null)) { + if (isNull != rightVector.isNull(rightIndex)) { return false; } - } - - return true; - } - - @Override - protected boolean compareListVectors(ListVector left) { - - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; - - boolean isNull = left.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { - return false; - } - - int offsetWidth = BaseRepeatedValueVector.OFFSET_WIDTH; if (!isNull) { - final int startIndexLeft = left.getOffsetBuffer().getInt(leftIndex * offsetWidth); - final int endIndexLeft = left.getOffsetBuffer().getInt((leftIndex + 1) * offsetWidth); - - final int startIndexRight = right.getOffsetBuffer().getInt(rightIndex * offsetWidth); - final int endIndexRight = right.getOffsetBuffer().getInt((rightIndex + 1) * offsetWidth); - - if ((endIndexLeft - startIndexLeft) != (endIndexRight - startIndexRight)) { - return false; - } - - ValueVector leftDataVector = left.getDataVector(); - ValueVector rightDataVector = ((ListVector)right).getDataVector(); - - if (!leftDataVector.accept(new ApproxEqualsVisitor(rightDataVector, floatEpsilon, doubleEpsilon, - typeCheckNeeded, startIndexLeft, startIndexRight, (endIndexLeft - startIndexLeft)), null)) { - return false; - } - } - } - return true; - } - - protected boolean compareFixedSizeListVectors(FixedSizeListVector left) { - - if (left.getListSize() != ((FixedSizeListVector)right).getListSize()) { - return false; - } - - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; - - boolean isNull = left.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { - return false; - } - - int listSize = left.getListSize(); - - if (!isNull) { - final int startIndexLeft = leftIndex * listSize; - final int endIndexLeft = (leftIndex + 1) * listSize; - - final int startIndexRight = rightIndex * listSize; - final int endIndexRight = (rightIndex + 1) * listSize; - - if ((endIndexLeft - startIndexLeft) != (endIndexRight - startIndexRight)) { - return false; - } - - ValueVector leftDataVector = left.getDataVector(); - ValueVector rightDataVector = ((FixedSizeListVector)right).getDataVector(); - - if (!leftDataVector.accept(new ApproxEqualsVisitor(rightDataVector, floatEpsilon, doubleEpsilon, - typeCheckNeeded, startIndexLeft, startIndexRight, (endIndexLeft - startIndexLeft)), null)) { - return false; - } - } - } - return true; - } - - private boolean float4ApproxEquals(Float4Vector left) { - - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; - - boolean isNull = left.isNull(leftIndex); - - if (isNull != right.isNull(rightIndex)) { - return false; - } - - if (!isNull) { - - Float leftValue = left.get(leftIndex); - Float rightValue = ((Float4Vector)right).get(rightIndex); + Float leftValue = leftVector.get(leftIndex); + Float rightValue = rightVector.get(rightIndex); if (leftValue.isNaN()) { return rightValue.isNaN(); } @@ -239,21 +110,24 @@ private boolean float4ApproxEquals(Float4Vector left) { return true; } - private boolean float8ApproxEquals(Float8Vector left) { - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; + private boolean float8ApproxEquals(Range range) { + Float8Vector leftVector = (Float8Vector) getLeft(); + Float8Vector rightVector = (Float8Vector) getRight(); + + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; - boolean isNull = left.isNull(leftIndex); + boolean isNull = leftVector.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { + if (isNull != rightVector.isNull(rightIndex)) { return false; } if (!isNull) { - Double leftValue = left.get(leftIndex); - Double rightValue = ((Float8Vector)right).get(rightIndex); + Double leftValue = leftVector.get(leftIndex); + Double rightValue = rightVector.get(rightIndex); if (leftValue.isNaN()) { return rightValue.isNaN(); } diff --git a/java/vector/src/main/java/org/apache/arrow/vector/compare/Range.java b/java/vector/src/main/java/org/apache/arrow/vector/compare/Range.java new file mode 100644 index 00000000000..0de99ab011f --- /dev/null +++ b/java/vector/src/main/java/org/apache/arrow/vector/compare/Range.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.arrow.vector.compare; + +/** + * Wrapper for the parameters of comparing a range of values in two vectors. + */ +public class Range { + + /** + * Start position in the left vector. + */ + private int leftStart = -1; + + /** + * Start position in the right vector. + */ + private int rightStart = -1; + + /** + * Length of the range. + */ + private int length = -1; + + + /** + * Constructs a new instance. + */ + public Range() {} + + /** + * Constructs a new instance. + * + * @param leftStart start index in left vector + * @param rightStart start index in right vector + * @param length length of range + */ + public Range(int leftStart, int rightStart, int length) { + this.leftStart = leftStart; + this.rightStart = rightStart; + this.length = length; + } + + public int getLeftStart() { + return leftStart; + } + + public int getRightStart() { + return rightStart; + } + + public int getLength() { + return length; + } + + public Range setLeftStart(int leftStart) { + this.leftStart = leftStart; + return this; + } + + public Range setRightStart(int rightStart) { + this.rightStart = rightStart; + return this; + } + + public Range setLength(int length) { + this.length = length; + return this; + } +} diff --git a/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java b/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java index d69cb7cd0f3..5d43031ffb5 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java @@ -35,109 +35,131 @@ /** * Visitor to compare a range of values for vectors. */ -public class RangeEqualsVisitor implements VectorVisitor { - - protected final ValueVector right; - protected int leftStart; - protected int rightStart; - protected int length; - - protected boolean typeCheckNeeded = true; +public class RangeEqualsVisitor implements VectorVisitor { + private ValueVector left; + private ValueVector right; + private boolean isTypeCheckNeeded; + private boolean typeCompareResult; /** * Constructs a new instance. + * + * @param left left vector + * @param right right vector + * @param isTypeCheckNeeded type check needed */ - public RangeEqualsVisitor(ValueVector right, int rightStart, int leftStart, int length, boolean typeCheckNeeded) { - this.leftStart = leftStart; - this.rightStart = rightStart; + public RangeEqualsVisitor(ValueVector left, ValueVector right, boolean isTypeCheckNeeded) { + this.left = left; this.right = right; - this.length = length; - this.typeCheckNeeded = typeCheckNeeded; - Preconditions.checkArgument(length >= 0, "length must be non negative"); + this.isTypeCheckNeeded = isTypeCheckNeeded; + + Preconditions.checkArgument(left != null, + "left vector cannot be null"); + Preconditions.checkArgument(right != null, + "right vector cannot be null"); + + // types cannot change for a visitor instance. so, the check is done only once. + if (!isTypeCheckNeeded) { + typeCompareResult = true; + } else if (left == right) { + typeCompareResult = true; + } else { + typeCompareResult = left.getField().getType().equals(right.getField().getType()); + } } /** * Constructs a new instance. + * + * @param left left vector + * @param right right vector */ - public RangeEqualsVisitor(ValueVector right, int leftStart, int rightStart, int length) { - this(right, rightStart, leftStart, length, true); + public RangeEqualsVisitor(ValueVector left, ValueVector right) { + this(left, right, true); } /** - * Do some validation work, like type check and indices check. + * Check range equals without passing IN param in VectorVisitor. */ - protected boolean validate(ValueVector left) { - - if (!compareValueVector(left, right)) { + public boolean rangeEquals(Range range) { + if (!typeCompareResult) { return false; } - Preconditions.checkArgument(leftStart >= 0, - "leftStart %s must be non negative.", leftStart); - Preconditions.checkArgument((leftStart + length) <= left.getValueCount(), - "(leftStart + length) %s out of range[0, %s].", 0, left.getValueCount()); - Preconditions.checkArgument(rightStart >= 0, - "rightStart %s must be non negative.", rightStart); - Preconditions.checkArgument((rightStart + length) <= right.getValueCount(), + Preconditions.checkArgument(range.getLeftStart() >= 0, + "leftStart %s must be non negative.", range.getLeftStart()); + Preconditions.checkArgument(range.getRightStart() >= 0, + "rightStart %s must be non negative.", range.getRightStart()); + + Preconditions.checkArgument(range.getRightStart() + range.getLength() <= right.getValueCount(), "(rightStart + length) %s out of range[0, %s].", 0, right.getValueCount()); + Preconditions.checkArgument(range.getLeftStart() + range.getLength() <= left.getValueCount(), + "(leftStart + length) %s out of range[0, %s].", 0, left.getValueCount()); - return true; + return left.accept(this, range); } - /** - * Check range equals without passing IN param in VectorVisitor. - */ - public boolean equals(ValueVector left) { - return left.accept(this, null); + public ValueVector getLeft() { + return left; } - @Override - public Boolean visit(BaseFixedWidthVector left, Void value) { - return validate(left) && compareBaseFixedWidthVectors(left); + public ValueVector getRight() { + return right; + } + + public boolean isTypeCheckNeeded() { + return isTypeCheckNeeded; } @Override - public Boolean visit(BaseVariableWidthVector left, Void value) { - return validate(left) && compareBaseVariableWidthVectors(left); + public Boolean visit(BaseFixedWidthVector left, Range range) { + return compareBaseFixedWidthVectors(range); } @Override - public Boolean visit(ListVector left, Void value) { - return validate(left) && compareListVectors(left); + public Boolean visit(BaseVariableWidthVector left, Range range) { + return compareBaseVariableWidthVectors(range); } @Override - public Boolean visit(FixedSizeListVector left, Void value) { - return validate(left) && compareFixedSizeListVectors(left); + public Boolean visit(ListVector left, Range range) { + return compareListVectors(range); } @Override - public Boolean visit(NonNullableStructVector left, Void value) { - return validate(left) && compareStructVectors(left); + public Boolean visit(FixedSizeListVector left, Range range) { + return compareFixedSizeListVectors(range); } @Override - public Boolean visit(UnionVector left, Void value) { - return validate(left) && compareUnionVectors(left); + public Boolean visit(NonNullableStructVector left, Range range) { + return compareStructVectors(range); } @Override - public Boolean visit(ZeroVector left, Void value) { - return validate(left); + public Boolean visit(UnionVector left, Range range) { + return compareUnionVectors(range); } - protected boolean compareValueVector(ValueVector left, ValueVector right) { - if (!typeCheckNeeded) { - return true; - } - return left.getField().getType().equals(right.getField().getType()); + @Override + public Boolean visit(ZeroVector left, Range range) { + return true; } - protected boolean compareUnionVectors(UnionVector left) { + /** + * Creates a visitor to visit child vectors. + * It is used for complex vector types. + * @return the visitor for child vecors. + */ + protected RangeEqualsVisitor createInnerVisitor(ValueVector leftInner, ValueVector rightInner) { + return new RangeEqualsVisitor(leftInner, rightInner, isTypeCheckNeeded); + } + protected boolean compareUnionVectors(Range range) { + UnionVector leftVector = (UnionVector) left; UnionVector rightVector = (UnionVector) right; - List leftChildren = left.getChildrenFromFields(); + List leftChildren = leftVector.getChildrenFromFields(); List rightChildren = rightVector.getChildrenFromFields(); if (leftChildren.size() != rightChildren.size()) { @@ -145,27 +167,26 @@ protected boolean compareUnionVectors(UnionVector left) { } for (int k = 0; k < leftChildren.size(); k++) { - RangeEqualsVisitor visitor = new RangeEqualsVisitor(rightChildren.get(k), - leftStart, rightStart, length); - if (!leftChildren.get(k).accept(visitor, null)) { + RangeEqualsVisitor visitor = createInnerVisitor(leftChildren.get(k), rightChildren.get(k)); + if (!visitor.rangeEquals(range)) { return false; } } return true; } - protected boolean compareStructVectors(NonNullableStructVector left) { - + protected boolean compareStructVectors(Range range) { + NonNullableStructVector leftVector = (NonNullableStructVector) left; NonNullableStructVector rightVector = (NonNullableStructVector) right; - if (!left.getChildFieldNames().equals(rightVector.getChildFieldNames())) { + List leftChildNames = leftVector.getChildFieldNames(); + if (!leftChildNames.equals(rightVector.getChildFieldNames())) { return false; } - for (String name : left.getChildFieldNames()) { - RangeEqualsVisitor visitor = new RangeEqualsVisitor(rightVector.getChild(name), - leftStart, rightStart, length); - if (!left.getChild(name).accept(visitor, null)) { + for (String name : leftChildNames) { + RangeEqualsVisitor visitor = createInnerVisitor(leftVector.getChild(name), rightVector.getChild(name)); + if (!visitor.rangeEquals(range)) { return false; } } @@ -173,19 +194,21 @@ protected boolean compareStructVectors(NonNullableStructVector left) { return true; } - protected boolean compareBaseFixedWidthVectors(BaseFixedWidthVector left) { + protected boolean compareBaseFixedWidthVectors(Range range) { + BaseFixedWidthVector leftVector = (BaseFixedWidthVector) left; + BaseFixedWidthVector rightVector = (BaseFixedWidthVector) right; - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; - boolean isNull = left.isNull(leftIndex); + boolean isNull = leftVector.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { + if (isNull != rightVector.isNull(rightIndex)) { return false; } - int typeWidth = left.getTypeWidth(); + int typeWidth = leftVector.getTypeWidth(); if (!isNull) { int startIndexLeft = typeWidth * leftIndex; int endIndexLeft = typeWidth * (leftIndex + 1); @@ -193,8 +216,8 @@ protected boolean compareBaseFixedWidthVectors(BaseFixedWidthVector left) { int startIndexRight = typeWidth * rightIndex; int endIndexRight = typeWidth * (rightIndex + 1); - int ret = ByteFunctionHelpers.equal(left.getDataBuffer(), startIndexLeft, endIndexLeft, - right.getDataBuffer(), startIndexRight, endIndexRight); + int ret = ByteFunctionHelpers.equal(leftVector.getDataBuffer(), startIndexLeft, endIndexLeft, + rightVector.getDataBuffer(), startIndexRight, endIndexRight); if (ret == 0) { return false; @@ -204,28 +227,30 @@ protected boolean compareBaseFixedWidthVectors(BaseFixedWidthVector left) { return true; } - protected boolean compareBaseVariableWidthVectors(BaseVariableWidthVector left) { + protected boolean compareBaseVariableWidthVectors(Range range) { + BaseVariableWidthVector leftVector = (BaseVariableWidthVector) left; + BaseVariableWidthVector rightVector = (BaseVariableWidthVector) right; - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; - boolean isNull = left.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { + boolean isNull = leftVector.isNull(leftIndex); + if (isNull != rightVector.isNull(rightIndex)) { return false; } int offsetWidth = BaseVariableWidthVector.OFFSET_WIDTH; if (!isNull) { - final int startIndexLeft = left.getOffsetBuffer().getInt(leftIndex * offsetWidth); - final int endIndexLeft = left.getOffsetBuffer().getInt((leftIndex + 1) * offsetWidth); + final int startIndexLeft = leftVector.getOffsetBuffer().getInt(leftIndex * offsetWidth); + final int endIndexLeft = leftVector.getOffsetBuffer().getInt((leftIndex + 1) * offsetWidth); - final int startIndexRight = right.getOffsetBuffer().getInt(rightIndex * offsetWidth); - final int endIndexRight = right.getOffsetBuffer().getInt((rightIndex + 1) * offsetWidth); + final int startIndexRight = rightVector.getOffsetBuffer().getInt(rightIndex * offsetWidth); + final int endIndexRight = rightVector.getOffsetBuffer().getInt((rightIndex + 1) * offsetWidth); - int ret = ByteFunctionHelpers.equal(left.getDataBuffer(), startIndexLeft, endIndexLeft, - right.getDataBuffer(), startIndexRight, endIndexRight); + int ret = ByteFunctionHelpers.equal(leftVector.getDataBuffer(), startIndexLeft, endIndexLeft, + rightVector.getDataBuffer(), startIndexRight, endIndexRight); if (ret == 0) { return false; @@ -235,35 +260,40 @@ protected boolean compareBaseVariableWidthVectors(BaseVariableWidthVector left) return true; } - protected boolean compareListVectors(ListVector left) { + protected boolean compareListVectors(Range range) { + ListVector leftVector = (ListVector) left; + ListVector rightVector = (ListVector) right; + + RangeEqualsVisitor innerVisitor = createInnerVisitor(leftVector.getDataVector(), rightVector.getDataVector()); + Range innerRange = new Range(); - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; - boolean isNull = left.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { + boolean isNull = leftVector.isNull(leftIndex); + if (isNull != rightVector.isNull(rightIndex)) { return false; } int offsetWidth = BaseRepeatedValueVector.OFFSET_WIDTH; if (!isNull) { - final int startIndexLeft = left.getOffsetBuffer().getInt(leftIndex * offsetWidth); - final int endIndexLeft = left.getOffsetBuffer().getInt((leftIndex + 1) * offsetWidth); + final int startIndexLeft = leftVector.getOffsetBuffer().getInt(leftIndex * offsetWidth); + final int endIndexLeft = leftVector.getOffsetBuffer().getInt((leftIndex + 1) * offsetWidth); - final int startIndexRight = right.getOffsetBuffer().getInt(rightIndex * offsetWidth); - final int endIndexRight = right.getOffsetBuffer().getInt((rightIndex + 1) * offsetWidth); + final int startIndexRight = rightVector.getOffsetBuffer().getInt(rightIndex * offsetWidth); + final int endIndexRight = rightVector.getOffsetBuffer().getInt((rightIndex + 1) * offsetWidth); if ((endIndexLeft - startIndexLeft) != (endIndexRight - startIndexRight)) { return false; } - ValueVector leftDataVector = left.getDataVector(); - ValueVector rightDataVector = ((ListVector)right).getDataVector(); - - if (!leftDataVector.accept(new RangeEqualsVisitor(rightDataVector, startIndexLeft, - startIndexRight, (endIndexLeft - startIndexLeft)), null)) { + innerRange = innerRange + .setRightStart(startIndexRight) + .setLeftStart(startIndexLeft) + .setLength(endIndexLeft - startIndexLeft); + if (!innerVisitor.rangeEquals(innerRange)) { return false; } } @@ -271,23 +301,27 @@ protected boolean compareListVectors(ListVector left) { return true; } - protected boolean compareFixedSizeListVectors(FixedSizeListVector left) { + protected boolean compareFixedSizeListVectors(Range range) { + FixedSizeListVector leftVector = (FixedSizeListVector) left; + FixedSizeListVector rightVector = (FixedSizeListVector) right; - if (left.getListSize() != ((FixedSizeListVector)right).getListSize()) { + if (leftVector.getListSize() != rightVector.getListSize()) { return false; } - for (int i = 0; i < length; i++) { - int leftIndex = leftStart + i; - int rightIndex = rightStart + i; + int listSize = leftVector.getListSize(); + RangeEqualsVisitor innerVisitor = createInnerVisitor(leftVector, rightVector); + Range innerRange = new Range(0, 0, listSize); - boolean isNull = left.isNull(leftIndex); - if (isNull != right.isNull(rightIndex)) { + for (int i = 0; i < range.getLength(); i++) { + int leftIndex = range.getLeftStart() + i; + int rightIndex = range.getRightStart() + i; + + boolean isNull = leftVector.isNull(leftIndex); + if (isNull != rightVector.isNull(rightIndex)) { return false; } - int listSize = left.getListSize(); - if (!isNull) { final int startIndexLeft = leftIndex * listSize; final int endIndexLeft = (leftIndex + 1) * listSize; @@ -299,11 +333,9 @@ protected boolean compareFixedSizeListVectors(FixedSizeListVector left) { return false; } - ValueVector leftDataVector = left.getDataVector(); - ValueVector rightDataVector = ((FixedSizeListVector)right).getDataVector(); - - if (!leftDataVector.accept(new RangeEqualsVisitor(rightDataVector, startIndexLeft, startIndexRight, - (endIndexLeft - startIndexLeft)), null)) { + innerRange = innerRange.setLeftStart(startIndexLeft) + .setRightStart(startIndexRight); + if (!innerVisitor.rangeEquals(innerRange)) { return false; } } diff --git a/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorEqualsVisitor.java b/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorEqualsVisitor.java index dfaf45fa43f..2ba9509a825 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorEqualsVisitor.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorEqualsVisitor.java @@ -17,27 +17,36 @@ package org.apache.arrow.vector.compare; -import org.apache.arrow.util.Preconditions; import org.apache.arrow.vector.ValueVector; /** * Visitor to compare vectors equal. */ -public class VectorEqualsVisitor extends RangeEqualsVisitor { +public class VectorEqualsVisitor { - public VectorEqualsVisitor(ValueVector right) { - this(right, true); + /** + * Checks if two vectors are equals. + * @param left the left vector to compare. + * @param right the right vector to compare. + * @return true if the vectors are equal, and false otherwise. + */ + public static boolean vectorEquals(ValueVector left, ValueVector right) { + return vectorEquals(left, right, true); } - public VectorEqualsVisitor(ValueVector right, boolean typeCheckNeeded) { - super(Preconditions.checkNotNull(right), 0, 0, right.getValueCount(), typeCheckNeeded); - } - - @Override - protected boolean compareValueVector(ValueVector left, ValueVector right) { - if (!super.compareValueVector(left, right)) { + /** + * Checks if two vectors are equals. + * @param left the left vector to compare. + * @param right the right vector to compare. + * @param isTypeCheckNeeded check equality of types + * @return true if the vectors are equal, and false otherwise. + */ + public static boolean vectorEquals(ValueVector left, ValueVector right, boolean isTypeCheckNeeded) { + if (left.getValueCount() != right.getValueCount()) { return false; } - return left.getValueCount() == right.getValueCount(); + + RangeEqualsVisitor visitor = new RangeEqualsVisitor(left, right, isTypeCheckNeeded); + return visitor.rangeEquals(new Range(0, 0, left.getValueCount())); } } diff --git a/java/vector/src/main/java/org/apache/arrow/vector/dictionary/Dictionary.java b/java/vector/src/main/java/org/apache/arrow/vector/dictionary/Dictionary.java index 0f917e50b3a..6f40e5814b9 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/dictionary/Dictionary.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/dictionary/Dictionary.java @@ -65,7 +65,7 @@ public boolean equals(Object o) { } Dictionary that = (Dictionary) o; return Objects.equals(encoding, that.encoding) && - (new VectorEqualsVisitor(that.dictionary)).equals(dictionary); + new VectorEqualsVisitor().vectorEquals(that.dictionary, dictionary); } @Override diff --git a/java/vector/src/main/java/org/apache/arrow/vector/dictionary/DictionaryHashTable.java b/java/vector/src/main/java/org/apache/arrow/vector/dictionary/DictionaryHashTable.java index d012c45471c..c4e003d2998 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/dictionary/DictionaryHashTable.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/dictionary/DictionaryHashTable.java @@ -18,6 +18,7 @@ package org.apache.arrow.vector.dictionary; import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.compare.Range; import org.apache.arrow.vector.compare.RangeEqualsVisitor; /** @@ -136,12 +137,17 @@ static final int roundUpToPowerOf2(int size) { public int getIndex(int indexInArray, ValueVector toEncode) { int hash = toEncode.hashCode(indexInArray); int index = indexFor(hash, table.length); + + RangeEqualsVisitor equalVisitor = new RangeEqualsVisitor(dictionary, toEncode, false); + Range range = new Range(0, 0, 1); + for (DictionaryHashTable.Entry e = table[index]; e != null ; e = e.next) { if (e.hash == hash) { int dictIndex = e.index; - if (new RangeEqualsVisitor(dictionary, dictIndex, indexInArray, 1, false) - .equals(toEncode)) { + range = range.setRightStart(indexInArray) + .setLeftStart(dictIndex); + if (equalVisitor.rangeEquals(range)) { return dictIndex; } } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java index b826908cb15..d2f9fc194da 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java @@ -36,6 +36,7 @@ import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.memory.util.ArrowBufPointer; +import org.apache.arrow.vector.compare.Range; import org.apache.arrow.vector.compare.RangeEqualsVisitor; import org.apache.arrow.vector.compare.VectorEqualsVisitor; import org.apache.arrow.vector.complex.ListVector; @@ -2261,8 +2262,8 @@ public void testZeroVectorEquals() { try (final ZeroVector vector1 = new ZeroVector(); final ZeroVector vector2 = new ZeroVector()) { - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertTrue(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2271,11 +2272,11 @@ public void testZeroVectorNotEquals() { try (final IntVector intVector = new IntVector("int", allocator); final ZeroVector zeroVector = new ZeroVector()) { - VectorEqualsVisitor zeroVisitor = new VectorEqualsVisitor(zeroVector); - assertFalse(zeroVisitor.equals(intVector)); + VectorEqualsVisitor zeroVisitor = new VectorEqualsVisitor(); + assertFalse(zeroVisitor.vectorEquals(intVector, zeroVector)); - VectorEqualsVisitor intVisitor = new VectorEqualsVisitor(intVector); - assertFalse(intVisitor.equals(zeroVector)); + VectorEqualsVisitor intVisitor = new VectorEqualsVisitor(); + assertFalse(intVisitor.vectorEquals(zeroVector, intVector)); } } @@ -2293,9 +2294,9 @@ public void testIntVectorEqualsWithNull() { vector1.setSafe(1, 2); vector2.setSafe(0, 1); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); - assertFalse(visitor.equals(vector1)); + assertFalse(visitor.vectorEquals(vector1, vector2)); } } @@ -2316,16 +2317,16 @@ public void testIntVectorEquals() { vector2.setSafe(0, 1); vector2.setSafe(1, 2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); - assertFalse(visitor.equals(vector1)); + assertFalse(visitor.vectorEquals(vector1, vector2)); vector2.setValueCount(3); vector2.setSafe(2, 2); assertFalse(vector1.equals(vector2)); vector2.setSafe(2, 3); - assertTrue(visitor.equals(vector1)); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2351,11 +2352,11 @@ public void testDecimalVectorEquals() { vector3.setSafe(0, 100); vector3.setSafe(1, 200); - VectorEqualsVisitor visitor1 = new VectorEqualsVisitor(vector2); - VectorEqualsVisitor visitor2 = new VectorEqualsVisitor(vector3); + VectorEqualsVisitor visitor1 = new VectorEqualsVisitor(); + VectorEqualsVisitor visitor2 = new VectorEqualsVisitor(); - assertTrue(visitor1.equals(vector1)); - assertFalse(visitor2.equals(vector1)); + assertTrue(visitor1.vectorEquals(vector1, vector2)); + assertFalse(visitor2.vectorEquals(vector1, vector3)); } } @@ -2375,8 +2376,8 @@ public void testVarcharVectorEuqalsWithNull() { vector2.setSafe(0, STR1, 0, STR1.length); vector2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); } } @@ -2398,12 +2399,12 @@ public void testVarcharVectorEquals() { vector2.setSafe(1, STR2, 0, STR2.length); vector2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); vector2.setSafe(2, STR3, 0, STR3.length); vector2.setValueCount(3); - assertTrue(visitor.equals(vector1)); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2425,12 +2426,12 @@ public void testVarBinaryVectorEquals() { vector2.setSafe(1, STR2, 0, STR2.length); vector2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); vector2.setSafe(2, STR3, 0, STR3.length); vector2.setValueCount(3); - assertTrue(visitor.equals(vector1)); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2456,9 +2457,9 @@ public void testListVectorEqualsWithNull() { writeListVector(writer2, new int[] {3, 4}); writer2.setValueCount(3); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); - assertFalse(visitor.equals(vector1)); + assertFalse(visitor.vectorEquals(vector1, vector2)); } } @@ -2484,13 +2485,13 @@ public void testListVectorEquals() { writeListVector(writer2, new int[] {3, 4}); writer2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); writeListVector(writer2, new int[] {5, 6}); writer2.setValueCount(3); - assertTrue(visitor.equals(vector1)); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2519,8 +2520,8 @@ public void testStructVectorEqualsWithNull() { writeStructVector(writer2, 3, 30L); writer2.setValueCount(3); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); } } @@ -2548,13 +2549,13 @@ public void testStructVectorEquals() { writeStructVector(writer2, 2, 20L); writer2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); writeStructVector(writer2, 3, 30L); writer2.setValueCount(3); - assertTrue(visitor.equals(vector1)); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2581,8 +2582,8 @@ public void testStructVectorEqualsWithDiffChild() { writeStructVector(writer2, 2, 20L); writer2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertFalse(visitor.vectorEquals(vector1, vector2)); } } @@ -2613,8 +2614,8 @@ public void testUnionVectorEquals() { vector2.setSafe(1, intHolder); vector2.setValueCount(2); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertTrue(visitor.equals(vector1)); + VectorEqualsVisitor visitor = new VectorEqualsVisitor(); + assertTrue(visitor.vectorEquals(vector1, vector2)); } } @@ -2634,8 +2635,7 @@ public void testEqualsWithIndexOutOfRange() { vector2.setSafe(0, 1); vector2.setSafe(1, 2); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 3, 2, 1); - assertTrue(visitor.equals(vector1)); + assertTrue(new RangeEqualsVisitor(vector1, vector2).rangeEquals(new Range(2, 3, 1))); } } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java index 3757757b684..04d73e231cd 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java @@ -45,6 +45,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; public class TestRangeEqualsVisitor { @@ -80,9 +81,8 @@ public void testIntVectorEqualsWithNull() { vector1.setSafe(1, 2); vector2.setSafe(0, 1); - VectorEqualsVisitor visitor = new VectorEqualsVisitor(vector2); - assertFalse(visitor.equals(vector1)); + assertFalse(VectorEqualsVisitor.vectorEquals(vector1, vector2)); } } @@ -108,8 +108,8 @@ public void testBaseFixedWidthVectorRangeEqual() { vector2.setSafe(3,4); vector2.setSafe(4,55); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 1, 1, 3); - assertTrue(visitor.equals(vector1)); + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2); + assertTrue(visitor.rangeEquals(new Range(1, 1, 3))); } } @@ -136,8 +136,8 @@ public void testBaseVariableVectorRangeEquals() { vector2.setSafe(4, STR1, 0, STR1.length); vector2.setValueCount(5); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 1, 1, 3); - assertTrue(visitor.equals(vector1)); + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2); + assertTrue(visitor.rangeEquals(new Range(1, 1, 3))); } } @@ -168,8 +168,8 @@ public void testListVectorRangeEquals() { writeListVector(writer2, new int[] {0, 0}); writer2.setValueCount(5); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 1, 1, 3); - assertTrue(visitor.equals(vector1)); + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2); + assertTrue(visitor.rangeEquals(new Range(1, 1, 3))); } } @@ -202,8 +202,8 @@ public void testStructVectorRangeEquals() { writeStructVector(writer2, 0, 0L); writer2.setValueCount(5); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 1, 1, 3); - assertTrue(visitor.equals(vector1)); + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2); + assertTrue(visitor.rangeEquals(new Range(1, 1, 3))); } } @@ -240,21 +240,19 @@ public void testUnionVectorRangeEquals() { vector2.setSafe(2, intHolder); vector2.setValueCount(3); - RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector2, 1, 1, 2); - assertTrue(visitor.equals(vector1)); + RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2); + assertTrue(visitor.rangeEquals(new Range(1, 1, 2))); } } + @Ignore @Test public void testEqualsWithOutTypeCheck() { try (final IntVector intVector = new IntVector("int", allocator); final ZeroVector zeroVector = new ZeroVector()) { - VectorEqualsVisitor zeroVisitor = new VectorEqualsVisitor(zeroVector, false); - assertTrue(zeroVisitor.equals(intVector)); - - VectorEqualsVisitor intVisitor = new VectorEqualsVisitor(intVector, false); - assertTrue(intVisitor.equals(zeroVector)); + assertTrue(VectorEqualsVisitor.vectorEquals(intVector, zeroVector, false)); + assertTrue(VectorEqualsVisitor.vectorEquals(zeroVector, intVector, false)); } } @@ -282,10 +280,13 @@ public void testFloat4ApproxEquals() { vector3.setSafe(0, 1.1f + epsilon * 2); vector3.setSafe(1, 2.2f + epsilon * 2); - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(vector1, epsilon); + Range range = new Range(0, 0, vector1.getValueCount()); + + ApproxEqualsVisitor visitor12 = new ApproxEqualsVisitor(vector1, vector2, epsilon, epsilon); + assertTrue(visitor12.rangeEquals(range)); - assertTrue(visitor.equals(vector2)); - assertFalse(visitor.equals(vector3)); + ApproxEqualsVisitor visitor13 = new ApproxEqualsVisitor(vector1, vector3, epsilon, epsilon); + assertFalse(visitor13.rangeEquals(range)); } } @@ -313,10 +314,9 @@ public void testFloat8ApproxEquals() { vector3.setSafe(0, 1.1 + epsilon * 2); vector3.setSafe(1, 2.2 + epsilon * 2); - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(vector1, epsilon); - - assertTrue(visitor.equals(vector2)); - assertFalse(visitor.equals(vector3)); + Range range = new Range(0, 0, vector1.getValueCount()); + assertTrue(new ApproxEqualsVisitor(vector1, vector2, epsilon, epsilon).rangeEquals(range)); + assertFalse(new ApproxEqualsVisitor(vector1, vector3, epsilon, epsilon).rangeEquals(range)); } } @@ -359,9 +359,9 @@ public void testStructVectorApproxEquals() { writeStructVector(leftWriter2, 2.02f - epsilon * 2, 4.04 - epsilon * 2); leftWriter2.setValueCount(2); - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(right, epsilon); - assertTrue(visitor.equals(left1)); - assertFalse(visitor.equals(left2)); + Range range = new Range(0, 0, right.getValueCount()); + assertTrue(new ApproxEqualsVisitor(left1, right, epsilon, epsilon).rangeEquals(range)); + assertFalse(new ApproxEqualsVisitor(left2, right, epsilon, epsilon).rangeEquals(range)); } } @@ -405,9 +405,9 @@ public void testUnionVectorApproxEquals() { left2.setSafe(1, float8Holder); left2.setValueCount(2); - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(right, epsilon); - assertTrue(visitor.equals(left1)); - assertFalse(visitor.equals(left2)); + Range range = new Range(0, 0, right.getValueCount()); + assertTrue(new ApproxEqualsVisitor(left1, right, epsilon, epsilon).rangeEquals(range)); + assertFalse(new ApproxEqualsVisitor(left2, right, epsilon, epsilon).rangeEquals(range)); } } @@ -437,9 +437,9 @@ public void testListVectorApproxEquals() { writeListVector(leftWriter2, new double[] {1.01 + epsilon * 2, 2.02 - epsilon * 2}); leftWriter2.setValueCount(2); - ApproxEqualsVisitor visitor = new ApproxEqualsVisitor(right, epsilon); - assertTrue(visitor.equals(left1)); - assertFalse(visitor.equals(left2)); + Range range = new Range(0, 0, right.getValueCount()); + assertTrue(new ApproxEqualsVisitor(left1, right, epsilon, epsilon).rangeEquals(range)); + assertFalse(new ApproxEqualsVisitor(left2, right, epsilon, epsilon).rangeEquals(range)); } }