1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.arrow.vector.compare.util; 19 20 import org.apache.arrow.vector.Float4Vector; 21 import org.apache.arrow.vector.Float8Vector; 22 import org.apache.arrow.vector.FloatingPointVector; 23 import org.apache.arrow.vector.compare.VectorValueEqualizer; 24 25 /** 26 * Vector value equalizers that regard values as equal if their difference 27 * is within a small threshold (epsilon). 28 */ 29 public class ValueEpsilonEqualizers { 30 ValueEpsilonEqualizers()31 private ValueEpsilonEqualizers() { 32 33 } 34 35 /** 36 * Difference function for floating point values. 37 */ 38 public static class FloatingPointEpsilonEqualizer implements VectorValueEqualizer<FloatingPointVector> { 39 private final double epsilon; 40 FloatingPointEpsilonEqualizer(double epsilon)41 public FloatingPointEpsilonEqualizer(double epsilon) { 42 this.epsilon = epsilon; 43 } 44 45 @Override valuesEqual( FloatingPointVector vector1, int index1, FloatingPointVector vector2, int index2)46 public final boolean valuesEqual( 47 FloatingPointVector vector1, int index1, FloatingPointVector vector2, int index2) { 48 boolean isNull1 = vector1.isNull(index1); 49 boolean isNull2 = vector2.isNull(index2); 50 51 if (isNull1 || isNull2) { 52 return isNull1 == isNull2; 53 } 54 55 double d1 = vector1.getValueAsDouble(index1); 56 double d2 = vector2.getValueAsDouble(index2); 57 58 if (Double.isNaN(d1)) { 59 return Double.isNaN(d2); 60 } 61 if (Double.isInfinite(d1)) { 62 return Double.isInfinite(d2) && Math.signum(d1) == Math.signum(d2); 63 } 64 65 return Math.abs(d1 - d2) <= epsilon; 66 } 67 68 @Override clone()69 public VectorValueEqualizer<FloatingPointVector> clone() { 70 return new FloatingPointEpsilonEqualizer(epsilon); 71 } 72 } 73 74 /** 75 * Difference function for float values. 76 */ 77 public static class Float4EpsilonEqualizer implements VectorValueEqualizer<Float4Vector> { 78 private final float epsilon; 79 Float4EpsilonEqualizer(float epsilon)80 public Float4EpsilonEqualizer(float epsilon) { 81 this.epsilon = epsilon; 82 } 83 84 @Override valuesEqual(Float4Vector vector1, int index1, Float4Vector vector2, int index2)85 public final boolean valuesEqual(Float4Vector vector1, int index1, Float4Vector vector2, int index2) { 86 boolean isNull1 = vector1.isNull(index1); 87 boolean isNull2 = vector2.isNull(index2); 88 89 if (isNull1 || isNull2) { 90 return isNull1 == isNull2; 91 } 92 93 float f1 = vector1.get(index1); 94 float f2 = vector2.get(index2); 95 96 if (Float.isNaN(f1)) { 97 return Float.isNaN(f2); 98 } 99 if (Float.isInfinite(f1)) { 100 return Float.isInfinite(f2) && Math.signum(f1) == Math.signum(f2); 101 } 102 103 return Math.abs(f1 - f2) <= epsilon; 104 } 105 106 @Override clone()107 public VectorValueEqualizer<Float4Vector> clone() { 108 return new Float4EpsilonEqualizer(epsilon); 109 } 110 } 111 112 /** 113 * Difference function for double values. 114 */ 115 public static class Float8EpsilonEqualizer implements VectorValueEqualizer<Float8Vector> { 116 private final double epsilon; 117 Float8EpsilonEqualizer(double epsilon)118 public Float8EpsilonEqualizer(double epsilon) { 119 this.epsilon = epsilon; 120 } 121 122 @Override valuesEqual(Float8Vector vector1, int index1, Float8Vector vector2, int index2)123 public final boolean valuesEqual(Float8Vector vector1, int index1, Float8Vector vector2, int index2) { 124 boolean isNull1 = vector1.isNull(index1); 125 boolean isNull2 = vector2.isNull(index2); 126 127 if (isNull1 || isNull2) { 128 return isNull1 == isNull2; 129 } 130 131 double d1 = vector1.get(index1); 132 double d2 = vector2.get(index2); 133 134 if (Double.isNaN(d1)) { 135 return Double.isNaN(d2); 136 } 137 if (Double.isInfinite(d1)) { 138 return Double.isInfinite(d2) && Math.signum(d1) == Math.signum(d2); 139 } 140 141 return Math.abs(d1 - d2) <= epsilon; 142 } 143 144 @Override clone()145 public VectorValueEqualizer<Float8Vector> clone() { 146 return new Float8EpsilonEqualizer(epsilon); 147 } 148 } 149 } 150