This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-geometry.git

commit 0ccee1783e8ae72941f3d79e88b9a8e59548fc89
Author: Matt Juntunen <[email protected]>
AuthorDate: Tue Feb 5 23:29:58 2019 -0500

    GEOMETRY-41: Adding equals(EuclideanVector, DoublePrecisionContext) and 
isZero(DoublePrecisionContext) methods to EuclideanVector and subclasses
---
 .../geometry/euclidean/EuclideanVector.java        | 30 +++++++++++
 .../commons/geometry/euclidean/oned/Vector1D.java  |  7 +++
 .../geometry/euclidean/threed/Vector3D.java        |  9 ++++
 .../commons/geometry/euclidean/twod/Vector2D.java  |  8 +++
 .../geometry/euclidean/oned/Vector1DTest.java      | 44 +++++++++++++++
 .../geometry/euclidean/threed/Vector3DTest.java    | 62 ++++++++++++++++++++++
 .../geometry/euclidean/twod/Vector2DTest.java      | 52 ++++++++++++++++++
 7 files changed, 212 insertions(+)

diff --git 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
index 00edec6..f767f97 100644
--- 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
+++ 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
@@ -21,6 +21,7 @@ import java.io.Serializable;
 import org.apache.commons.geometry.core.Point;
 import org.apache.commons.geometry.core.Vector;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.internal.Vectors;
 
 /** Abstract base class for Euclidean vectors <em>and</em> points. See
@@ -67,6 +68,35 @@ public abstract class EuclideanVector<V extends 
EuclideanVector<V>>
      */
     public abstract V lerp(V v, double t);
 
+    /** Return true if the current instance and given vector are considered 
equal as evaluated by the
+     * given precision context.
+     *
+     * <p>Equality is determined by comparing each pair of components in turn 
from the two
+     * vectors. If all components evaluate as equal, then the vectors are 
considered equal. If any are
+     * not equal, then the vectors are not considered equal. Note that this 
approach means that the
+     * calculated distance between two "equal" vectors may be as much as 
<code>&radic;(n * eps<sup>2</sup>)</code>,
+     * where {@code n} is the number of components in the vector and {@code 
eps} is the maximum epsilon
+     * value allowed by the precision context.
+     * @param v vector to check for equality
+     * @param precision precision context used to determine floating point 
equality
+     * @return true if the current instance is considered equal to the given 
vector when using
+     *      the given precision context; otherwise false
+     */
+    public abstract boolean equals(V v, DoublePrecisionContext precision);
+
+    /** Return true if the current instance is considered equal to the zero 
vector as evaluated by the
+     * given precision context. This is a convenience method equivalent to
+     * {@code vec.equals(vec.getZero(), precision)}.
+     *
+     * @param precision precision context used to determine floating point 
equality
+     * @return true if the current instance is considered equal to the zero 
vector when using
+     *      the given precision context; otherwise false
+     * @see #equals(EuclideanVector, DoublePrecisionContext)
+     */
+    public boolean isZero(final DoublePrecisionContext precision) {
+        return equals(getZero(), precision);
+    }
+
     /** Return the vector norm value, throwing an {@link IllegalNormException} 
if the value
      * is not real (ie, NaN or infinite) or zero.
      * @return the vector norm value, guaranteed to be real and non-zero
diff --git 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
index 6556ca0..67a683a 100644
--- 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
+++ 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
@@ -19,6 +19,7 @@ package org.apache.commons.geometry.euclidean.oned;
 import org.apache.commons.geometry.core.Geometry;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
 import org.apache.commons.geometry.core.internal.SimpleTupleFormat;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.EuclideanVector;
 import org.apache.commons.geometry.euclidean.internal.Vectors;
 import org.apache.commons.numbers.arrays.LinearCombination;
@@ -219,6 +220,12 @@ public class Vector1D extends EuclideanVector<Vector1D> {
         return transform.apply(this);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean equals(final Vector1D vec, final DoublePrecisionContext 
precision) {
+        return precision.areEqual(x, vec.x);
+    }
+
     /**
      * Get a hashCode for the vector.
      * <p>All NaN values have the same hash code.</p>
diff --git 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
index b59793a..e350ef7 100644
--- 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
+++ 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
@@ -20,6 +20,7 @@ package org.apache.commons.geometry.euclidean.threed;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
 import org.apache.commons.geometry.core.internal.DoubleFunction3N;
 import org.apache.commons.geometry.core.internal.SimpleTupleFormat;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.MultiDimensionalEuclideanVector;
 import org.apache.commons.geometry.euclidean.internal.Vectors;
 import org.apache.commons.numbers.arrays.LinearCombination;
@@ -370,6 +371,14 @@ public class Vector3D extends 
MultiDimensionalEuclideanVector<Vector3D> {
         return transform.apply(this);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean equals(final Vector3D vec, final DoublePrecisionContext 
precision) {
+        return precision.areEqual(x, vec.x) &&
+                precision.areEqual(y, vec.y) &&
+                precision.areEqual(z, vec.z);
+    }
+
     /**
      * Get a hashCode for the vector.
      * <p>All NaN values have the same hash code.</p>
diff --git 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
index 08b4f1f..582f66f 100644
--- 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
+++ 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
@@ -19,6 +19,7 @@ package org.apache.commons.geometry.euclidean.twod;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
 import org.apache.commons.geometry.core.internal.DoubleFunction2N;
 import org.apache.commons.geometry.core.internal.SimpleTupleFormat;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.MultiDimensionalEuclideanVector;
 import org.apache.commons.geometry.euclidean.internal.Vectors;
 import org.apache.commons.numbers.arrays.LinearCombination;
@@ -319,6 +320,13 @@ public class Vector2D extends 
MultiDimensionalEuclideanVector<Vector2D> {
         return transform.apply(this);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean equals(final Vector2D vec, final DoublePrecisionContext 
precision) {
+        return precision.areEqual(x, vec.x) &&
+                precision.areEqual(y, vec.y);
+    }
+
     /**
      * Get a hashCode for the 2D coordinates.
      * <p>
diff --git 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java
 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java
index 8aa06b7..e3b015d 100644
--- 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java
+++ 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java
@@ -21,6 +21,8 @@ import java.util.regex.Pattern;
 import org.apache.commons.geometry.core.Geometry;
 import org.apache.commons.geometry.core.GeometryTestUtils;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
+import 
org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
 import org.apache.commons.numbers.core.Precision;
 import org.junit.Assert;
 import org.junit.Test;
@@ -464,6 +466,48 @@ public class Vector1DTest {
     }
 
     @Test
+    public void testPrecisionEquals() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        Vector1D vec = Vector1D.of(1);
+
+        // act/assert
+        Assert.assertTrue(vec.equals(vec, smallEps));
+        Assert.assertTrue(vec.equals(vec, largeEps));
+
+        Assert.assertTrue(vec.equals(Vector1D.of(1.0000007), smallEps));
+        Assert.assertTrue(vec.equals(Vector1D.of(1.0000007), largeEps));
+
+        Assert.assertFalse(vec.equals(Vector1D.of(1.004), smallEps));
+        Assert.assertTrue(vec.equals(Vector1D.of(1.004), largeEps));
+
+        Assert.assertFalse(vec.equals(Vector1D.of(2), smallEps));
+        Assert.assertFalse(vec.equals(Vector1D.of(-2), largeEps));
+    }
+
+    @Test
+    public void testIsZero() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        // act/assert
+        Assert.assertTrue(Vector1D.of(0.0).isZero(smallEps));
+        Assert.assertTrue(Vector1D.of(-0.0).isZero(largeEps));
+
+        Assert.assertTrue(Vector1D.of(1e-7).isZero(smallEps));
+        Assert.assertTrue(Vector1D.of(-1e-7).isZero(largeEps));
+
+        Assert.assertFalse(Vector1D.of(1e-2).isZero(smallEps));
+        Assert.assertTrue(Vector1D.of(-1e-2).isZero(largeEps));
+
+        Assert.assertFalse(Vector1D.of(0.2).isZero(smallEps));
+        Assert.assertFalse(Vector1D.of(-0.2).isZero(largeEps));
+    }
+
+    @Test
     public void testHashCode() {
         // arrange
         Vector1D u = Vector1D.of(1);
diff --git 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
index c6243d5..95f6077 100644
--- 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
+++ 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
@@ -22,6 +22,8 @@ import java.util.regex.Pattern;
 import org.apache.commons.geometry.core.Geometry;
 import org.apache.commons.geometry.core.GeometryTestUtils;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
+import 
org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
 import org.apache.commons.numbers.core.Precision;
 import org.apache.commons.rng.UniformRandomProvider;
@@ -934,6 +936,66 @@ public class Vector3DTest {
     }
 
     @Test
+    public void testPrecisionEquals() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        Vector3D vec = Vector3D.of(1, -2, 3);
+
+        // act/assert
+        Assert.assertTrue(vec.equals(vec, smallEps));
+        Assert.assertTrue(vec.equals(vec, largeEps));
+
+        Assert.assertTrue(vec.equals(Vector3D.of(1.0000007, -2.0000009, 
3.0000009), smallEps));
+        Assert.assertTrue(vec.equals(Vector3D.of(1.0000007, -2.0000009, 
3.0000009), largeEps));
+
+        Assert.assertFalse(vec.equals(Vector3D.of(1.004, -2, 3), smallEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -2.004, 3), smallEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -2, 2.999), smallEps));
+        Assert.assertTrue(vec.equals(Vector3D.of(1.004, -2.004, 2.999), 
largeEps));
+
+        Assert.assertFalse(vec.equals(Vector3D.of(2, -2, 3), smallEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -3, 3), smallEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -2, 4), smallEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(2, -3, 4), smallEps));
+
+        Assert.assertFalse(vec.equals(Vector3D.of(2, -2, 3), largeEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -3, 3), largeEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(1, -2, 4), largeEps));
+        Assert.assertFalse(vec.equals(Vector3D.of(2, -3, 4), largeEps));
+    }
+
+    @Test
+    public void testIsZero() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        // act/assert
+        Assert.assertTrue(Vector3D.of(0.0, -0.0, 0.0).isZero(smallEps));
+        Assert.assertTrue(Vector3D.of(-0.0, 0.0, -0.0).isZero(largeEps));
+
+        Assert.assertTrue(Vector3D.of(-1e-7, 1e-7, -1e-8).isZero(smallEps));
+        Assert.assertTrue(Vector3D.of(1e-7, -1e-7, 1e-8).isZero(largeEps));
+
+        Assert.assertFalse(Vector3D.of(1e-2, 0.0, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector3D.of(0.0, 1e-2, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector3D.of(0.0, 0.0, 1e-2).isZero(smallEps));
+        Assert.assertTrue(Vector3D.of(1e-2, -1e-2, 1e-2).isZero(largeEps));
+
+        Assert.assertFalse(Vector3D.of(0.2, 0.0, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector3D.of(0.0, 0.2, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector3D.of(0.0, 0.0, 0.2).isZero(smallEps));
+        Assert.assertFalse(Vector3D.of(0.2, 0.2, 0.2).isZero(smallEps));
+
+        Assert.assertFalse(Vector3D.of(0.2, 0.0, 0.0).isZero(largeEps));
+        Assert.assertFalse(Vector3D.of(0.0, 0.2, 0.0).isZero(largeEps));
+        Assert.assertFalse(Vector3D.of(0.0, 0.0, 0.2).isZero(largeEps));
+        Assert.assertFalse(Vector3D.of(0.2, 0.2, 0.2).isZero(largeEps));
+    }
+
+    @Test
     public void testHashCode() {
         // arrange
         double delta = 10 * Precision.EPSILON;
diff --git 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
index 5a4c268..76564b4 100644
--- 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
+++ 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
@@ -21,6 +21,8 @@ import java.util.regex.Pattern;
 import org.apache.commons.geometry.core.Geometry;
 import org.apache.commons.geometry.core.GeometryTestUtils;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
+import 
org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
 import org.apache.commons.numbers.core.Precision;
 import org.junit.Assert;
@@ -741,6 +743,56 @@ public class Vector2DTest {
     }
 
     @Test
+    public void testPrecisionEquals() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        Vector2D vec = Vector2D.of(1, -2);
+
+        // act/assert
+        Assert.assertTrue(vec.equals(vec, smallEps));
+        Assert.assertTrue(vec.equals(vec, largeEps));
+
+        Assert.assertTrue(vec.equals(Vector2D.of(1.0000007, -2.0000009), 
smallEps));
+        Assert.assertTrue(vec.equals(Vector2D.of(1.0000007, -2.0000009), 
largeEps));
+
+        Assert.assertFalse(vec.equals(Vector2D.of(1.004, -2), smallEps));
+        Assert.assertFalse(vec.equals(Vector2D.of(1, -2.004), smallEps));
+        Assert.assertTrue(vec.equals(Vector2D.of(1.004, -2.004), largeEps));
+
+        Assert.assertFalse(vec.equals(Vector2D.of(1, -3), smallEps));
+        Assert.assertFalse(vec.equals(Vector2D.of(2, -2), smallEps));
+        Assert.assertFalse(vec.equals(Vector2D.of(1, -3), largeEps));
+        Assert.assertFalse(vec.equals(Vector2D.of(2, -2), largeEps));
+    }
+
+    @Test
+    public void testIsZero() {
+        // arrange
+        DoublePrecisionContext smallEps = new 
EpsilonDoublePrecisionContext(1e-6);
+        DoublePrecisionContext largeEps = new 
EpsilonDoublePrecisionContext(1e-1);
+
+        // act/assert
+        Assert.assertTrue(Vector2D.of(0.0, -0.0).isZero(smallEps));
+        Assert.assertTrue(Vector2D.of(-0.0, 0.0).isZero(largeEps));
+
+        Assert.assertTrue(Vector2D.of(-1e-7, 1e-7).isZero(smallEps));
+        Assert.assertTrue(Vector2D.of(1e-7, 1e-7).isZero(largeEps));
+
+        Assert.assertFalse(Vector2D.of(1e-2, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector2D.of(0.0, 1e-2).isZero(smallEps));
+        Assert.assertTrue(Vector2D.of(1e-2, -1e-2).isZero(largeEps));
+
+        Assert.assertFalse(Vector2D.of(0.2, 0.0).isZero(smallEps));
+        Assert.assertFalse(Vector2D.of(0.0, 0.2).isZero(smallEps));
+        Assert.assertFalse(Vector2D.of(0.2, 0.2).isZero(smallEps));
+        Assert.assertFalse(Vector2D.of(-0.2, 0.0).isZero(largeEps));
+        Assert.assertFalse(Vector2D.of(0.0, -0.2).isZero(largeEps));
+        Assert.assertFalse(Vector2D.of(-0.2, -0.2).isZero(largeEps));
+    }
+
+    @Test
     public void testHashCode() {
         // arrange
         Vector2D u = Vector2D.of(1, 1);

Reply via email to