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 2021/04/23 00:28:39 UTC

[commons-numbers] branch master updated: NUMBERS-154: Handle NaN to allow consistent sorting.

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


The following commit(s) were added to refs/heads/master by this push:
     new 4f0cf07  NUMBERS-154: Handle NaN to allow consistent sorting.
4f0cf07 is described below

commit 4f0cf073de18650a2cedd9c1ca07cff9bee44d8d
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Fri Apr 23 02:26:49 2021 +0200

    NUMBERS-154: Handle NaN to allow consistent sorting.
    
    Thanks to Alex Herbert.
---
 .../org/apache/commons/numbers/core/Precision.java |  5 ++++-
 .../numbers/core/EpsilonDoubleEquivalenceTest.java |  8 +++----
 .../apache/commons/numbers/core/PrecisionTest.java | 26 ++++++++++++++++++++++
 3 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Precision.java b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Precision.java
index 6d32631..c4e376d 100644
--- a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Precision.java
+++ b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Precision.java
@@ -112,8 +112,11 @@ public final class Precision {
             return 0;
         } else if (x < y) {
             return -1;
+        } else if (x > y) {
+            return 1;
         }
-        return 1;
+        // NaN input.
+        return Double.compare(x, y);
     }
 
     /**
diff --git a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/EpsilonDoubleEquivalenceTest.java b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/EpsilonDoubleEquivalenceTest.java
index 623c95d..5eac0e8 100644
--- a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/EpsilonDoubleEquivalenceTest.java
+++ b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/EpsilonDoubleEquivalenceTest.java
@@ -121,14 +121,14 @@ class EpsilonDoubleEquivalenceTest {
         final Precision.DoubleEquivalence cmp = Precision.doubleEquivalenceOfEpsilon(1e-6);
 
         // act/assert
-        Assertions.assertEquals(1, cmp.compare(0, Double.NaN));
+        Assertions.assertEquals(-1, cmp.compare(0, Double.NaN));
         Assertions.assertEquals(1, cmp.compare(Double.NaN, 0));
-        Assertions.assertEquals(1, cmp.compare(Double.NaN, Double.NaN));
+        Assertions.assertEquals(0, cmp.compare(Double.NaN, Double.NaN));
 
-        Assertions.assertEquals(1, cmp.compare(Double.POSITIVE_INFINITY, Double.NaN));
+        Assertions.assertEquals(-1, cmp.compare(Double.POSITIVE_INFINITY, Double.NaN));
         Assertions.assertEquals(1, cmp.compare(Double.NaN, Double.POSITIVE_INFINITY));
 
-        Assertions.assertEquals(1, cmp.compare(Double.NEGATIVE_INFINITY, Double.NaN));
+        Assertions.assertEquals(-1, cmp.compare(Double.NEGATIVE_INFINITY, Double.NaN));
         Assertions.assertEquals(1, cmp.compare(Double.NaN, Double.NEGATIVE_INFINITY));
     }
 
diff --git a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/PrecisionTest.java b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/PrecisionTest.java
index 8e784bf..12a4f1f 100644
--- a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/PrecisionTest.java
+++ b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/PrecisionTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.numbers.core;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.math.RoundingMode;
 
 import org.junit.jupiter.api.Assertions;
@@ -281,6 +283,30 @@ class PrecisionTest {
     }
 
     @Test
+    void testSortWithCompareTo() {
+        final Double[] array = {Double.NaN, 0.02, 0.01, Double.NaN, 2.0, 1.0};
+        final double eps = 0.1;
+        for (int i = 0; i < 10; i++) {
+            Collections.shuffle(Arrays.asList(array));
+            Arrays.sort(array, (a, b) -> Precision.compareTo(a, b, eps));
+
+            for (int j = 0; j < array.length - 1; j++) {
+                final int c = Precision.compareTo(array[j],
+                                                  array[j + 1],
+                                                  eps);
+                // Check that order is consistent with the comparison function.
+                Assertions.assertNotEquals(c, 1);
+            }
+            Assertions.assertTrue(array[0] == 0.01 || array[0] == 0.02);
+            Assertions.assertTrue(array[1] == 0.01 || array[1] == 0.02);
+            Assertions.assertEquals(1, array[2], 0d);
+            Assertions.assertEquals(2, array[3], 0d);
+            Assertions.assertTrue(Double.isNaN(array[4]));
+            Assertions.assertTrue(Double.isNaN(array[5]));
+        }
+    }
+
+    @Test
     void testCompareToMaxUlps() {
         double a = 152.32;
         double delta = Math.ulp(a);