You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2019/02/14 21:36:51 UTC
[commons-numbers] 01/03: NUMBERS-94: adding extra check to
PlaneAngle.normalize() to handle very small numbers
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-numbers.git
commit 00b2b5621ed39141d81b92b3fa3ba96a4e54c1c1
Author: Matt Juntunen <ma...@hotmail.com>
AuthorDate: Thu Feb 14 00:12:51 2019 -0500
NUMBERS-94: adding extra check to PlaneAngle.normalize() to handle very small numbers
---
.../apache/commons/numbers/angle/PlaneAngle.java | 16 +++++++++++++++-
.../commons/numbers/angle/PlaneAngleTest.java | 22 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/commons-numbers-angle/src/main/java/org/apache/commons/numbers/angle/PlaneAngle.java b/commons-numbers-angle/src/main/java/org/apache/commons/numbers/angle/PlaneAngle.java
index cf8f509..8a7ce0e 100644
--- a/commons-numbers-angle/src/main/java/org/apache/commons/numbers/angle/PlaneAngle.java
+++ b/commons-numbers-angle/src/main/java/org/apache/commons/numbers/angle/PlaneAngle.java
@@ -94,7 +94,21 @@ public class PlaneAngle {
* {@code center - 0.5 <= a - k < center + 0.5} (in turns).
*/
public PlaneAngle normalize(PlaneAngle center) {
- return new PlaneAngle(value - Math.floor(value + HALF_TURN - center.value));
+ final double lowerBound = center.value - HALF_TURN;
+ final double upperBound = center.value + HALF_TURN;
+
+ double normalized = value - Math.floor(value - lowerBound);
+
+ // If value is too small to be representable compared to the floor
+ // expression above (ie, if value + x = x), then we may end up with a number
+ // exactly equal to the upper bound here. In that case, subtract
+ // one from the normalized value so that we can fulfill the contract
+ // of only returning results strictly less than the upper bound.
+ if (normalized >= upperBound) {
+ normalized -= 1.0;
+ }
+
+ return new PlaneAngle(normalized);
}
/**
diff --git a/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/PlaneAngleTest.java b/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/PlaneAngleTest.java
index 3e7164e..d2f3ac8 100644
--- a/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/PlaneAngleTest.java
+++ b/commons-numbers-angle/src/test/java/org/apache/commons/numbers/angle/PlaneAngleTest.java
@@ -126,6 +126,28 @@ public class PlaneAngleTest {
}
@Test
+ public void testNormalizeVeryCloseToBounds() {
+ // arrange
+ double eps = 1e-22;
+
+ double small = 1e-16;
+ double tiny = 1e-18; // 0.5 + tiny = 0.5 (the value is too small to add to 0.5)
+
+ // act/assert
+ Assert.assertEquals(1.0 - small, PlaneAngle.ofTurns(-small).normalize(PlaneAngle.PI).toTurns(), eps);
+ Assert.assertEquals(small, PlaneAngle.ofTurns(small).normalize(PlaneAngle.PI).toTurns(), eps);
+
+ Assert.assertEquals(0.5 - small, PlaneAngle.ofTurns(-0.5 - small).normalize(PlaneAngle.ZERO).toTurns(), eps);
+ Assert.assertEquals(-0.5 + small, PlaneAngle.ofTurns(0.5 + small).normalize(PlaneAngle.ZERO).toTurns(), eps);
+
+ Assert.assertEquals(0.0, PlaneAngle.ofTurns(-tiny).normalize(PlaneAngle.PI).toTurns(), eps);
+ Assert.assertEquals(tiny, PlaneAngle.ofTurns(tiny).normalize(PlaneAngle.PI).toTurns(), eps);
+
+ Assert.assertEquals(-0.5, PlaneAngle.ofTurns(-0.5 - tiny).normalize(PlaneAngle.ZERO).toTurns(), eps);
+ Assert.assertEquals(-0.5, PlaneAngle.ofTurns(0.5 + tiny).normalize(PlaneAngle.ZERO).toTurns(), eps);
+ }
+
+ @Test
public void testHashCode() {
// Test assumes that the internal representation is in "turns".
final double value = -123.456789;