Skip to content
Permalink
Browse files
GEOMETRY-99: using Double.compare in equals and Double.hashCode in ha…
…shCode
  • Loading branch information
darkma773r committed Jul 4, 2020
1 parent 385c02a commit fc9272b2366d6b5944e1c1a9ecf568ff89f95a30
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 40 deletions.
@@ -94,7 +94,7 @@ public boolean equals(final Object obj) {

final EpsilonDoublePrecisionContext other = (EpsilonDoublePrecisionContext) obj;

return this.epsilon == other.epsilon;
return Double.compare(this.epsilon, other.epsilon) == 0;
}

/** {@inheritDoc} **/
@@ -208,6 +208,25 @@ public void testEquals() {
Assert.assertEquals(a, c);
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final EpsilonDoublePrecisionContext a = new EpsilonDoublePrecisionContext(0.0);
final EpsilonDoublePrecisionContext b = new EpsilonDoublePrecisionContext(-0.0);
final EpsilonDoublePrecisionContext c = new EpsilonDoublePrecisionContext(0.0);
final EpsilonDoublePrecisionContext d = new EpsilonDoublePrecisionContext(-0.0);

// act/assert
Assert.assertFalse(a.equals(b));
Assert.assertNotEquals(a.hashCode(), b.hashCode());

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange
@@ -277,18 +277,16 @@ public int hashCode() {
*/
@Override
public boolean equals(final Object other) {

if (this == other) {
return true;
}

if (other instanceof Vector1D) {
final Vector1D rhs = (Vector1D) other;
if (rhs.isNaN()) {
return this.isNaN();
}

return x == rhs.x;
return Double.compare(x, rhs.x) == 0;
}
return false;
}
@@ -24,7 +24,6 @@
import org.apache.commons.geometry.euclidean.internal.Vectors;
import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
import org.apache.commons.numbers.arrays.LinearCombination;
import org.apache.commons.numbers.core.Precision;

/** Class using a matrix to represent affine transformations in 3 dimensional Euclidean space.
*
@@ -442,20 +441,20 @@ public boolean equals(final Object obj) {

final AffineTransformMatrix3D other = (AffineTransformMatrix3D) obj;

return Precision.equals(this.m00, other.m00) &&
Precision.equals(this.m01, other.m01) &&
Precision.equals(this.m02, other.m02) &&
Precision.equals(this.m03, other.m03) &&
return Double.compare(this.m00, other.m00) == 0 &&
Double.compare(this.m01, other.m01) == 0 &&
Double.compare(this.m02, other.m02) == 0 &&
Double.compare(this.m03, other.m03) == 0 &&

Precision.equals(this.m10, other.m10) &&
Precision.equals(this.m11, other.m11) &&
Precision.equals(this.m12, other.m12) &&
Precision.equals(this.m13, other.m13) &&
Double.compare(this.m10, other.m10) == 0 &&
Double.compare(this.m11, other.m11) == 0 &&
Double.compare(this.m12, other.m12) == 0 &&
Double.compare(this.m13, other.m13) == 0 &&

Precision.equals(this.m20, other.m20) &&
Precision.equals(this.m21, other.m21) &&
Precision.equals(this.m22, other.m22) &&
Precision.equals(this.m23, other.m23);
Double.compare(this.m20, other.m20) == 0 &&
Double.compare(this.m21, other.m21) == 0 &&
Double.compare(this.m22, other.m22) == 0 &&
Double.compare(this.m23, other.m23) == 0;
}

/** {@inheritDoc} */
@@ -181,14 +181,15 @@ public boolean equals(final Object other) {
if (this == other) {
return true;
}

if (other instanceof SphericalCoordinates) {
final SphericalCoordinates rhs = (SphericalCoordinates) other;
if (rhs.isNaN()) {
return this.isNaN();
}

return (radius == rhs.radius) && (azimuth == rhs.azimuth) && (polar == rhs.polar);
return Double.compare(radius, rhs.radius) == 0 &&
Double.compare(azimuth, rhs.azimuth) == 0 &&
Double.compare(polar, rhs.polar) == 0;
}
return false;
}
@@ -399,10 +399,10 @@ public int hashCode() {
if (isNaN()) {
return 642;
}
return 643 * (164 * Double.hashCode(x) + 3 * Double.hashCode(y) + Double.hashCode(z));
return 643 * (164 * Double.hashCode(x) + 3 * Double.hashCode(y) + Double.hashCode(z));
}

/**
/**d
* Test for the equality of two vector instances.
* <p>
* If all coordinates of two vectors are exactly the same, and none are
@@ -426,14 +426,15 @@ public boolean equals(final Object other) {
if (this == other) {
return true;
}

if (other instanceof Vector3D) {
final Vector3D rhs = (Vector3D) other;
if (rhs.isNaN()) {
return this.isNaN();
}

return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
return Double.compare(x, rhs.x) == 0 &&
Double.compare(y, rhs.y) == 0 &&
Double.compare(z, rhs.z) == 0;
}
return false;
}
@@ -19,8 +19,6 @@
import java.util.Arrays;
import java.util.Objects;

import org.apache.commons.numbers.core.Precision;

/** <p>
* Class representing a sequence of axis-angle rotations. These types of
* rotations are commonly called <em>Euler angles</em>, <em>Tait-Bryan angles</em>,
@@ -158,9 +156,9 @@ public boolean equals(final Object obj) {

return this.referenceFrame == other.referenceFrame &&
this.axisSequence == other.axisSequence &&
Precision.equals(this.angle1, other.angle1) &&
Precision.equals(this.angle2, other.angle2) &&
Precision.equals(this.angle3, other.angle3);
Double.compare(this.angle1, other.angle1) == 0 &&
Double.compare(this.angle2, other.angle2) == 0 &&
Double.compare(this.angle3, other.angle3) == 0;
}

/** {@inheritDoc} */
@@ -24,7 +24,6 @@
import org.apache.commons.geometry.euclidean.internal.Vectors;
import org.apache.commons.geometry.euclidean.twod.rotation.Rotation2D;
import org.apache.commons.numbers.arrays.LinearCombination;
import org.apache.commons.numbers.core.Precision;

/** Class using a matrix to represent affine transformations in 2 dimensional Euclidean space.
*
@@ -397,13 +396,13 @@ public boolean equals(final Object obj) {

final AffineTransformMatrix2D other = (AffineTransformMatrix2D) obj;

return Precision.equals(this.m00, other.m00) &&
Precision.equals(this.m01, other.m01) &&
Precision.equals(this.m02, other.m02) &&
return Double.compare(this.m00, other.m00) == 0 &&
Double.compare(this.m01, other.m01) == 0 &&
Double.compare(this.m02, other.m02) == 0 &&

Precision.equals(this.m10, other.m10) &&
Precision.equals(this.m11, other.m11) &&
Precision.equals(this.m12, other.m12);
Double.compare(this.m10, other.m10) == 0 &&
Double.compare(this.m11, other.m11) == 0 &&
Double.compare(this.m12, other.m12) == 0;
}

/** {@inheritDoc} */
@@ -151,14 +151,14 @@ public boolean equals(final Object other) {
if (this == other) {
return true;
}

if (other instanceof PolarCoordinates) {
final PolarCoordinates rhs = (PolarCoordinates) other;
if (rhs.isNaN()) {
return this.isNaN();
}

return (radius == rhs.radius) && (azimuth == rhs.azimuth);
return Double.compare(radius, rhs.radius) == 0 &&
Double.compare(azimuth, rhs.azimuth) == 0;
}
return false;
}
@@ -342,7 +342,7 @@ public int hashCode() {
if (isNaN()) {
return 542;
}
return 122 * (76 * Double.hashCode(x) + Double.hashCode(y));
return 122 * (76 * Double.hashCode(x) + Double.hashCode(y));
}

/**
@@ -369,14 +369,14 @@ public boolean equals(final Object other) {
if (this == other) {
return true;
}

if (other instanceof Vector2D) {
final Vector2D rhs = (Vector2D) other;
if (rhs.isNaN()) {
return this.isNaN();
}

return (x == rhs.x) && (y == rhs.y);
return Double.compare(x, rhs.x) == 0 &&
Double.compare(y, rhs.y) == 0;
}
return false;
}
@@ -733,6 +733,24 @@ public void testEquals() {
Assert.assertNotEquals(a, AffineTransformMatrix1D.of(1, 0));
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(0.0, -0.0);
final AffineTransformMatrix1D b = AffineTransformMatrix1D.of(-0.0, 0.0);
final AffineTransformMatrix1D c = AffineTransformMatrix1D.of(0.0, -0.0);
final AffineTransformMatrix1D d = AffineTransformMatrix1D.of(-0.0, 0.0);

// act/assert
Assert.assertFalse(a.equals(b));

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange
@@ -598,6 +598,25 @@ public void testEquals() {
Assert.assertEquals(Vector1D.of(Double.NEGATIVE_INFINITY), Vector1D.of(Double.NEGATIVE_INFINITY));
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final Vector1D a = Vector1D.of(0.0);
final Vector1D b = Vector1D.of(-0.0);
final Vector1D c = Vector1D.of(0.0);
final Vector1D d = Vector1D.of(-0.0);

// act/assert
Assert.assertFalse(a.equals(b));
Assert.assertNotEquals(a.hashCode(), b.hashCode());

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange
@@ -1180,6 +1180,35 @@ public void testEquals() {
}
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final double[] arrWithPosZero = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
};
final double[] arrWithNegZero = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, -0.0,
};
final AffineTransformMatrix3D a = AffineTransformMatrix3D.of(arrWithPosZero);
final AffineTransformMatrix3D b = AffineTransformMatrix3D.of(arrWithNegZero);
final AffineTransformMatrix3D c = AffineTransformMatrix3D.of(arrWithPosZero);
final AffineTransformMatrix3D d = AffineTransformMatrix3D.of(arrWithNegZero);

// act/assert
Assert.assertFalse(a.equals(b));
Assert.assertNotEquals(a.hashCode(), b.hashCode());

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange
@@ -320,6 +320,25 @@ public void testEquals_NaNInstancesEqual() {
Assert.assertEquals(b, c);
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final SphericalCoordinates a = SphericalCoordinates.of(0.0, -0.0, 0.0);
final SphericalCoordinates b = SphericalCoordinates.of(-0.0, 0.0, -0.0);
final SphericalCoordinates c = SphericalCoordinates.of(0.0, -0.0, 0.0);
final SphericalCoordinates d = SphericalCoordinates.of(-0.0, 0.0, -0.0);

// act/assert
Assert.assertFalse(a.equals(b));
Assert.assertNotEquals(a.hashCode(), b.hashCode());

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange
@@ -1102,6 +1102,24 @@ public void testEquals() {
Assert.assertNotEquals(Vector3D.of(0, 0, Double.NEGATIVE_INFINITY), Vector3D.of(Double.NEGATIVE_INFINITY, 0, 0));
}

@Test
public void testEqualsAndHashCode_signedZeroConsistency() {
// arrange
final Vector3D a = Vector3D.of(0.0, -0.0, 0.0);
final Vector3D b = Vector3D.of(-0.0, 0.0, -0.0);
final Vector3D c = Vector3D.of(0.0, -0.0, 0.0);
final Vector3D d = Vector3D.of(-0.0, 0.0, -0.0);

// act/assert
Assert.assertFalse(a.equals(b));

Assert.assertTrue(a.equals(c));
Assert.assertEquals(a.hashCode(), c.hashCode());

Assert.assertTrue(b.equals(d));
Assert.assertEquals(b.hashCode(), d.hashCode());
}

@Test
public void testToString() {
// arrange

0 comments on commit fc9272b

Please sign in to comment.