You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2020/04/04 21:16:30 UTC

[commons-numbers] branch master updated (f12139e -> dc0071f)

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

aherbert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git.


    from f12139e  Complex hypot: use 54 as the exponent difference to ignore overlap
     new c461f25  Default the jacoco coverage checks to those in parent.
     new 104254a  Remove deprecated RNG from test.
     new 894e726  Increase coverage in PrecisionTest to 100%.
     new 08edae9  Remove a branch from equals tests with NaN.
     new 98b64f1  Fixed test coverage for field.
     new 66a3a2d  Fixed test coverage in LogFactorialTest
     new 36679a7  Fixed test coverage in BinomialCoefficientTest
     new e20c9fd  Fixed test coverage in FactorialDoubleTest
     new dc0071f  Fixed test coverage in CombinationsTest

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../numbers/arrays/LinearCombinationTest.java      |   2 +-
 .../numbers/combinatorics/Combinations.java        |  10 +-
 .../combinatorics/BinomialCoefficientTest.java     |  23 +-
 .../numbers/combinatorics/CombinationsTest.java    |  61 +++-
 .../numbers/combinatorics/FactorialDoubleTest.java |   7 +
 .../numbers/combinatorics/LogFactorialTest.java    |  10 +-
 .../org/apache/commons/numbers/core/Precision.java |  12 +-
 .../apache/commons/numbers/core/PrecisionTest.java | 338 ++++++++++++---------
 .../org/apache/commons/numbers/field/FP64Test.java |  16 +
 pom.xml                                            |  11 +-
 10 files changed, 311 insertions(+), 179 deletions(-)


[commons-numbers] 06/09: Fixed test coverage in LogFactorialTest

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 66a3a2d3180bc9ecd0e16ae03aa4a43d1e08279f
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 21:41:19 2020 +0100

    Fixed test coverage in LogFactorialTest
---
 .../apache/commons/numbers/combinatorics/LogFactorialTest.java | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/LogFactorialTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/LogFactorialTest.java
index 0a4beae..291c557 100644
--- a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/LogFactorialTest.java
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/LogFactorialTest.java
@@ -26,13 +26,21 @@ import org.junit.jupiter.api.Test;
  */
 public class LogFactorialTest {
     @Test
-    public void testNonPositiveArgument() {
+    public void testNonPositiveArgumentWithCache() {
         Assertions.assertThrows(IllegalArgumentException.class,
             () -> LogFactorial.create().withCache(-1)
         );
     }
 
     @Test
+    public void testNonPositiveArgument() {
+        final LogFactorial f = LogFactorial.create();
+        Assertions.assertThrows(IllegalArgumentException.class,
+            () -> f.value(-1)
+        );
+    }
+
+    @Test
     public void testDelegation() {
         final LogFactorial f = LogFactorial.create();
 


[commons-numbers] 07/09: Fixed test coverage in BinomialCoefficientTest

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 36679a7ad08ffb53287f5c6ccdf6fa5c5d9821ab
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 21:47:39 2020 +0100

    Fixed test coverage in BinomialCoefficientTest
---
 .../combinatorics/BinomialCoefficientTest.java     | 23 ++++++++--------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/BinomialCoefficientTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/BinomialCoefficientTest.java
index b266930..8080f80 100644
--- a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/BinomialCoefficientTest.java
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/BinomialCoefficientTest.java
@@ -72,37 +72,30 @@ public class BinomialCoefficientTest {
     }
 
     @Test
-    public void testBinomialCoefficientFail1() {
+    public void testBinomialCoefficientKLargerThanN() {
         Assertions.assertThrows(CombinatoricsException.class,
             () -> BinomialCoefficient.value(4, 5)
         );
     }
 
     @Test
-    public void testBinomialCoefficientFail2() {
+    public void testBinomialCoefficientNegativeN() {
         Assertions.assertThrows(CombinatoricsException.class,
-            () -> BinomialCoefficient.value(-1, -2)
+            () -> BinomialCoefficient.value(-1, 1)
         );
     }
 
     @Test
-    public void testBinomialCoefficientFail3() {
-        Assertions.assertThrows(ArithmeticException.class,
-            () -> BinomialCoefficient.value(67, 30)
-        );
-    }
-
-    @Test
-    public void testBinomialCoefficientFail4() {
-        Assertions.assertThrows(ArithmeticException.class,
-            () -> BinomialCoefficient.value(67, 34)
+    public void testBinomialCoefficientNegativeK() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> BinomialCoefficient.value(10, -1)
         );
     }
 
     @Test
-    public void testBinomialCoefficientFail5() {
+    public void testBinomialCoefficientNAbove66ResultOverflow() {
         Assertions.assertThrows(ArithmeticException.class,
-            () -> BinomialCoefficient.value(700, 300)
+            () -> BinomialCoefficient.value(67, 30)
         );
     }
 


Re: [commons-numbers] 04/09: Remove a branch from equals tests with NaN.

Posted by Gilles Sadowski <gi...@gmail.com>.
Le dim. 5 avr. 2020 à 00:36, Alex Herbert <al...@gmail.com> a écrit :
>
>
>
> > On 4 Apr 2020, at 22:35, Gilles Sadowski <gi...@gmail.com> wrote:
> >
> > Hello.
> >
> > Le sam. 4 avr. 2020 à 23:16, <aherbert@apache.org <ma...@apache.org>> a écrit :
> >>
> >> This is an automated email from the ASF dual-hosted git repository.
> >>
> >> aherbert pushed a commit to branch master
> >> in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
> >>
> >> commit 08edae944e4abe7ec4b95a72d3791a9f39fb53c8
> >> Author: Alex Herbert <ah...@apache.org>
> >> AuthorDate: Sat Apr 4 21:23:08 2020 +0100
> >>
> >>    Remove a branch from equals tests with NaN.
> >>
> >>    A bitwise OR of the booleans is true if either boolean is true. Since
> >>    they are both already computed then the || operator short circuit (if
> >>    first is true) cannot avoid having to compute the second boolean.
> >>
> >>    This change converts 3 conditional evaluations to 2 conditional
> >>    evaluations.
> >
> > Is this measurable?  Is the difference significant?
> > I'm not actually asking any benchmarking, but such changes
> > should be balanced with the resulting code reduced (IMO)
> > readability.
>
> I do not know. I ensured the unit tests had full coverage and then looked at a few ways to improve the class. This change may be reverted.

No need to bother.
Perhaps it's just a matter of habit or taste.
The method is short, and someone puzzled can check
that it behaves as expected.

> It may be something that is done by a good compiler anyway.
>
> There is another change that will eliminate the unreachable code branch. But I did not make that change as it was less readable IMO:
>
> Original:
>
> return isEqual && !Double.isNaN(x) && !Double.isNaN(y);
>
> Verses:
>
> return isEqual && !Double.isNaN(x + y);
>
> As is this perhaps:
>
> if (((xInt ^ yInt) & SGN_MASK) == 0L) {
>
> Verses:
>
> if (((xInt ^ yInt) >= 0L) {
>
> Given that none of this is in anyway expected to be in performance critical code I can put it back to the previous version if you prefer.

Perhaps just add the equivalent alternative code that's
could be more readily understandable?

Best,
Gilles

> >> [...]

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: [commons-numbers] 04/09: Remove a branch from equals tests with NaN.

Posted by Alex Herbert <al...@gmail.com>.

> On 4 Apr 2020, at 22:35, Gilles Sadowski <gi...@gmail.com> wrote:
> 
> Hello.
> 
> Le sam. 4 avr. 2020 à 23:16, <aherbert@apache.org <ma...@apache.org>> a écrit :
>> 
>> This is an automated email from the ASF dual-hosted git repository.
>> 
>> aherbert pushed a commit to branch master
>> in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
>> 
>> commit 08edae944e4abe7ec4b95a72d3791a9f39fb53c8
>> Author: Alex Herbert <ah...@apache.org>
>> AuthorDate: Sat Apr 4 21:23:08 2020 +0100
>> 
>>    Remove a branch from equals tests with NaN.
>> 
>>    A bitwise OR of the booleans is true if either boolean is true. Since
>>    they are both already computed then the || operator short circuit (if
>>    first is true) cannot avoid having to compute the second boolean.
>> 
>>    This change converts 3 conditional evaluations to 2 conditional
>>    evaluations.
> 
> Is this measurable?  Is the difference significant?
> I'm not actually asking any benchmarking, but such changes
> should be balanced with the resulting code reduced (IMO)
> readability.

I do not know. I ensured the unit tests had full coverage and then looked at a few ways to improve the class. This change may be reverted. It may be something that is done by a good compiler anyway.

There is another change that will eliminate the unreachable code branch. But I did not make that change as it was less readable IMO:

Original:

return isEqual && !Double.isNaN(x) && !Double.isNaN(y);

Verses:

return isEqual && !Double.isNaN(x + y);

As is this perhaps:

if (((xInt ^ yInt) & SGN_MASK) == 0L) {

Verses:

if (((xInt ^ yInt) >= 0L) {

Given that none of this is in anyway expected to be in performance critical code I can put it back to the previous version if you prefer.

> 
> 
> Best,
> Gilles
> 
>> ---
>> .../main/java/org/apache/commons/numbers/core/Precision.java | 12 ++++++++----
>> 1 file changed, 8 insertions(+), 4 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 d60806d..4155b51 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
>> @@ -177,7 +177,8 @@ public final class Precision {
>>     public static boolean equalsIncludingNaN(float x, float y) {
>>         final boolean xIsNan = Float.isNaN(x);
>>         final boolean yIsNan = Float.isNaN(y);
>> -        return xIsNan || yIsNan ?
>> +        // Combine the booleans with bitwise OR
>> +        return (xIsNan | yIsNan) ?
>>             !(xIsNan ^ yIsNan) :
>>             equals(x, y, 1);
>>     }
>> @@ -274,7 +275,8 @@ public final class Precision {
>>     public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
>>         final boolean xIsNan = Float.isNaN(x);
>>         final boolean yIsNan = Float.isNaN(y);
>> -        return xIsNan || yIsNan ?
>> +        // Combine the booleans with bitwise OR
>> +        return (xIsNan | yIsNan) ?
>>             !(xIsNan ^ yIsNan) :
>>             equals(x, y, maxUlps);
>>     }
>> @@ -302,7 +304,8 @@ public final class Precision {
>>     public static boolean equalsIncludingNaN(double x, double y) {
>>         final boolean xIsNan = Double.isNaN(x);
>>         final boolean yIsNan = Double.isNaN(y);
>> -        return xIsNan || yIsNan ?
>> +        // Combine the booleans with bitwise OR
>> +        return (xIsNan | yIsNan) ?
>>             !(xIsNan ^ yIsNan) :
>>             equals(x, y, 1);
>>     }
>> @@ -428,7 +431,8 @@ public final class Precision {
>>     public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
>>         final boolean xIsNan = Double.isNaN(x);
>>         final boolean yIsNan = Double.isNaN(y);
>> -        return xIsNan || yIsNan ?
>> +        // Combine the booleans with bitwise OR
>> +        return (xIsNan | yIsNan) ?
>>             !(xIsNan ^ yIsNan) :
>>             equals(x, y, maxUlps);
>>     }
>> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org <ma...@commons.apache.org>
> For additional commands, e-mail: dev-help@commons.apache.org <ma...@commons.apache.org>

Re: [commons-numbers] 04/09: Remove a branch from equals tests with NaN.

Posted by Gilles Sadowski <gi...@gmail.com>.
Hello.

Le sam. 4 avr. 2020 à 23:16, <ah...@apache.org> a écrit :
>
> This is an automated email from the ASF dual-hosted git repository.
>
> aherbert pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
>
> commit 08edae944e4abe7ec4b95a72d3791a9f39fb53c8
> Author: Alex Herbert <ah...@apache.org>
> AuthorDate: Sat Apr 4 21:23:08 2020 +0100
>
>     Remove a branch from equals tests with NaN.
>
>     A bitwise OR of the booleans is true if either boolean is true. Since
>     they are both already computed then the || operator short circuit (if
>     first is true) cannot avoid having to compute the second boolean.
>
>     This change converts 3 conditional evaluations to 2 conditional
>     evaluations.

Is this measurable?  Is the difference significant?
I'm not actually asking any benchmarking, but such changes
should be balanced with the resulting code reduced (IMO)
readability.


Best,
Gilles

> ---
>  .../main/java/org/apache/commons/numbers/core/Precision.java | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 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 d60806d..4155b51 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
> @@ -177,7 +177,8 @@ public final class Precision {
>      public static boolean equalsIncludingNaN(float x, float y) {
>          final boolean xIsNan = Float.isNaN(x);
>          final boolean yIsNan = Float.isNaN(y);
> -        return xIsNan || yIsNan ?
> +        // Combine the booleans with bitwise OR
> +        return (xIsNan | yIsNan) ?
>              !(xIsNan ^ yIsNan) :
>              equals(x, y, 1);
>      }
> @@ -274,7 +275,8 @@ public final class Precision {
>      public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
>          final boolean xIsNan = Float.isNaN(x);
>          final boolean yIsNan = Float.isNaN(y);
> -        return xIsNan || yIsNan ?
> +        // Combine the booleans with bitwise OR
> +        return (xIsNan | yIsNan) ?
>              !(xIsNan ^ yIsNan) :
>              equals(x, y, maxUlps);
>      }
> @@ -302,7 +304,8 @@ public final class Precision {
>      public static boolean equalsIncludingNaN(double x, double y) {
>          final boolean xIsNan = Double.isNaN(x);
>          final boolean yIsNan = Double.isNaN(y);
> -        return xIsNan || yIsNan ?
> +        // Combine the booleans with bitwise OR
> +        return (xIsNan | yIsNan) ?
>              !(xIsNan ^ yIsNan) :
>              equals(x, y, 1);
>      }
> @@ -428,7 +431,8 @@ public final class Precision {
>      public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
>          final boolean xIsNan = Double.isNaN(x);
>          final boolean yIsNan = Double.isNaN(y);
> -        return xIsNan || yIsNan ?
> +        // Combine the booleans with bitwise OR
> +        return (xIsNan | yIsNan) ?
>              !(xIsNan ^ yIsNan) :
>              equals(x, y, maxUlps);
>      }
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


[commons-numbers] 04/09: Remove a branch from equals tests with NaN.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 08edae944e4abe7ec4b95a72d3791a9f39fb53c8
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 21:23:08 2020 +0100

    Remove a branch from equals tests with NaN.
    
    A bitwise OR of the booleans is true if either boolean is true. Since
    they are both already computed then the || operator short circuit (if
    first is true) cannot avoid having to compute the second boolean.
    
    This change converts 3 conditional evaluations to 2 conditional
    evaluations.
---
 .../main/java/org/apache/commons/numbers/core/Precision.java | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 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 d60806d..4155b51 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
@@ -177,7 +177,8 @@ public final class Precision {
     public static boolean equalsIncludingNaN(float x, float y) {
         final boolean xIsNan = Float.isNaN(x);
         final boolean yIsNan = Float.isNaN(y);
-        return xIsNan || yIsNan ?
+        // Combine the booleans with bitwise OR
+        return (xIsNan | yIsNan) ?
             !(xIsNan ^ yIsNan) :
             equals(x, y, 1);
     }
@@ -274,7 +275,8 @@ public final class Precision {
     public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
         final boolean xIsNan = Float.isNaN(x);
         final boolean yIsNan = Float.isNaN(y);
-        return xIsNan || yIsNan ?
+        // Combine the booleans with bitwise OR
+        return (xIsNan | yIsNan) ?
             !(xIsNan ^ yIsNan) :
             equals(x, y, maxUlps);
     }
@@ -302,7 +304,8 @@ public final class Precision {
     public static boolean equalsIncludingNaN(double x, double y) {
         final boolean xIsNan = Double.isNaN(x);
         final boolean yIsNan = Double.isNaN(y);
-        return xIsNan || yIsNan ?
+        // Combine the booleans with bitwise OR
+        return (xIsNan | yIsNan) ?
             !(xIsNan ^ yIsNan) :
             equals(x, y, 1);
     }
@@ -428,7 +431,8 @@ public final class Precision {
     public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
         final boolean xIsNan = Double.isNaN(x);
         final boolean yIsNan = Double.isNaN(y);
-        return xIsNan || yIsNan ?
+        // Combine the booleans with bitwise OR
+        return (xIsNan | yIsNan) ?
             !(xIsNan ^ yIsNan) :
             equals(x, y, maxUlps);
     }


[commons-numbers] 05/09: Fixed test coverage for field.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 98b64f1eeda26cac21e3923b1350b9ba0e2d6671
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 21:37:31 2020 +0100

    Fixed test coverage for field.
    
    Added test for FP64 equals.
---
 .../java/org/apache/commons/numbers/field/FP64Test.java  | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/FP64Test.java b/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/FP64Test.java
index cbd6137..260ecc7 100644
--- a/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/FP64Test.java
+++ b/commons-numbers-field/src/test/java/org/apache/commons/numbers/field/FP64Test.java
@@ -38,6 +38,22 @@ public class FP64Test {
     }
 
     @Test
+    public void testEquals() {
+        final FP64 a = FP64.of(1.23);
+        final FP64 b = FP64.of(4.56);
+
+        // Same instance
+        Assertions.assertTrue(a.equals(a));
+        // Same value
+        Assertions.assertTrue(a.equals(FP64.of(a.doubleValue())));
+        // Different value
+        Assertions.assertFalse(a.equals(b));
+        // Different object
+        Assertions.assertFalse(a.equals(new Object()));
+        Assertions.assertFalse(a.equals(null));
+    }
+
+    @Test
     public void testOne() {
         Assertions.assertEquals(1d, FP64.of(-3.4).one().doubleValue(), 0d);
     }


[commons-numbers] 01/09: Default the jacoco coverage checks to those in parent.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c461f2509c08bf896beb8bbfc0b9c3bc7393c397
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 17:07:43 2020 +0100

    Default the jacoco coverage checks to those in parent.
    
    commons-parent is stricter than the removed configuration.
    
    Here we set the method ratio to 1.00. It should be possible to call all
    methods via the test suite.
    
    jacoco version 0.8.2 -> 0.8.5
    classRatio 0.96 -> 1.00
    instructionRatio 0.8 -> 0.90
    methodRatio 0.8 -> 0.95 => 1.00
    branchRatio 0.8 -> 0.85
    complexityRatio 0.8 -> 0.85
    lineRatio 0.85 -> 0.90
    
    haltOnFailure is still false to prevent build failure.
---
 pom.xml | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/pom.xml b/pom.xml
index 70790c0..b7ccc85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,14 +67,9 @@
     <!-- Workaround to avoid duplicating config files. -->
     <numbers.parent.dir>${basedir}</numbers.parent.dir>
 
-    <!-- Temporary fix to support Java 8 -->
-    <commons.jacoco.version>0.8.2</commons.jacoco.version>
-    <commons.jacoco.classRatio>0.96</commons.jacoco.classRatio>
-    <commons.jacoco.instructionRatio>0.8</commons.jacoco.instructionRatio>
-    <commons.jacoco.methodRatio>0.8</commons.jacoco.methodRatio>
-    <commons.jacoco.branchRatio>0.8</commons.jacoco.branchRatio>
-    <commons.jacoco.complexityRatio>0.8</commons.jacoco.complexityRatio>
-    <commons.jacoco.lineRatio>0.85</commons.jacoco.lineRatio>
+    <!-- Increase from commons-parent -->
+    <commons.jacoco.methodRatio>1.00</commons.jacoco.methodRatio>
+    <!-- Set to true when coverage goals are achieved -->
     <commons.jacoco.haltOnFailure>false</commons.jacoco.haltOnFailure>
 
     <!-- Override CP 47 -->


[commons-numbers] 03/09: Increase coverage in PrecisionTest to 100%.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 894e72614487cea0cb152044a9fad9bf60f09e97
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 19:03:08 2020 +0100

    Increase coverage in PrecisionTest to 100%.
    
    Some code is unreachable in the equals test using NaN since since two
    values cannot be equal and have one nan but not the other value a nan.
---
 .../apache/commons/numbers/core/PrecisionTest.java | 338 ++++++++++++---------
 1 file changed, 202 insertions(+), 136 deletions(-)

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 93fe99b..ee2f90a 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
@@ -26,6 +26,29 @@ import org.junit.jupiter.api.Test;
  *
  */
 public class PrecisionTest {
+
+    // Interfaces to allow testing equals variants with the same conditions
+
+    @FunctionalInterface
+    private interface EqualsWithDelta {
+        boolean equals(double a, double b, double delta);
+    }
+
+    @FunctionalInterface
+    private interface EqualsWithUlps {
+        boolean equals(double a, double b, int ulps);
+    }
+
+    @FunctionalInterface
+    private interface FloatEqualsWithDelta {
+        boolean equals(float a, float b, float delta);
+    }
+
+    @FunctionalInterface
+    private interface FloatEqualsWithUlps {
+        boolean equals(float a, float b, int ulps);
+    }
+
     @Test
     public void testEqualsWithRelativeTolerance() {
         Assertions.assertTrue(Precision.equalsWithRelativeTolerance(0d, 0d, 0d));
@@ -76,167 +99,174 @@ public class PrecisionTest {
 
     @Test
     public void testEqualsWithAllowedDelta() {
-        Assertions.assertTrue(Precision.equals(153.0000, 153.0000, .0625));
-        Assertions.assertTrue(Precision.equals(153.0000, 153.0625, .0625));
-        Assertions.assertTrue(Precision.equals(152.9375, 153.0000, .0625));
-        Assertions.assertFalse(Precision.equals(153.0000, 153.0625, .0624));
-        Assertions.assertFalse(Precision.equals(152.9374, 153.0000, .0625));
-        Assertions.assertFalse(Precision.equals(Double.NaN, Double.NaN, 1.0));
-        Assertions.assertTrue(Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
-        Assertions.assertTrue(Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
-        Assertions.assertFalse(Precision.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
+        assertEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true);
     }
 
     @Test
-    public void testMath475() {
-        final double a = 1.7976931348623182E16;
-        final double b = Math.nextUp(a);
-
-        double diff = Math.abs(a - b);
-        // Because they are adjacent floating point numbers, "a" and "b" are
-        // considered equal even though the allowed error is smaller than
-        // their difference.
-        Assertions.assertTrue(Precision.equals(a, b, 0.5 * diff));
+    public void testEqualsIncludingNaNWithAllowedDelta() {
+        assertEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true);
+    }
 
-        final double c = Math.nextUp(b);
-        diff = Math.abs(a - c);
-        // Because "a" and "c" are not adjacent, the tolerance is taken into
-        // account for assessing equality.
-        Assertions.assertTrue(Precision.equals(a, c, diff));
-        Assertions.assertFalse(Precision.equals(a, c, (1 - 1e-16) * diff));
+    private static void assertEqualsWithAllowedDelta(EqualsWithDelta fun, boolean nanAreEqual) {
+        Assertions.assertTrue(fun.equals(153.0000, 153.0000, .0625));
+        Assertions.assertTrue(fun.equals(153.0000, 153.0625, .0625));
+        Assertions.assertTrue(fun.equals(152.9375, 153.0000, .0625));
+        Assertions.assertFalse(fun.equals(153.0000, 153.0625, .0624));
+        Assertions.assertFalse(fun.equals(152.9374, 153.0000, .0625));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 1.0));
+        Assertions.assertTrue(fun.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
+        Assertions.assertTrue(fun.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
+        Assertions.assertFalse(fun.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
     }
 
     @Test
-    public void testEqualsIncludingNaNWithAllowedDelta() {
-        Assertions.assertTrue(Precision.equalsIncludingNaN(153.0000, 153.0000, .0625));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(153.0000, 153.0625, .0625));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(152.9375, 153.0000, .0625));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.NaN, Double.NaN, 1.0));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(153.0000, 153.0625, .0624));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(152.9374, 153.0000, .0625));
+    public void testEqualsWithAllowedUlps() {
+        assertEqualsIncludingNaNWithAllowedUlps(Precision::equals, false, false);
     }
 
-    // Tests for floating point equality
     @Test
-    public void testFloatEqualsWithAllowedUlps() {
-        Assertions.assertTrue(Precision.equals(0.0f, -0.0f), "+0.0f == -0.0f");
-        Assertions.assertTrue(Precision.equals(0.0f, -0.0f, 1), "+0.0f == -0.0f (1 ulp)");
-        float oneFloat = 1.0f;
-        Assertions.assertTrue(Precision.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat))), "1.0f == 1.0f + 1 ulp");
-        Assertions.assertTrue(Precision.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)), 1), "1.0f == 1.0f + 1 ulp (1 ulp)");
-        Assertions.assertFalse(Precision.equals(oneFloat, Float.intBitsToFloat(2 + Float.floatToIntBits(oneFloat)), 1), "1.0f != 1.0f + 2 ulp (1 ulp)");
-
-        Assertions.assertTrue(Precision.equals(153.0f, 153.0f, 1));
-
-        // These tests need adjusting for floating point precision
-//        Assert.assertTrue(Precision.equals(153.0f, 153.00000000000003f, 1));
-//        Assert.assertFalse(Precision.equals(153.0f, 153.00000000000006f, 1));
-//        Assert.assertTrue(Precision.equals(153.0f, 152.99999999999997f, 1));
-//        Assert.assertFalse(Precision.equals(153f, 152.99999999999994f, 1));
-//
-//        Assert.assertTrue(Precision.equals(-128.0f, -127.99999999999999f, 1));
-//        Assert.assertFalse(Precision.equals(-128.0f, -127.99999999999997f, 1));
-//        Assert.assertTrue(Precision.equals(-128.0f, -128.00000000000003f, 1));
-//        Assert.assertFalse(Precision.equals(-128.0f, -128.00000000000006f, 1));
-
-        Assertions.assertTrue(Precision.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equals(Double.MAX_VALUE, Float.POSITIVE_INFINITY, 1));
-
-        Assertions.assertTrue(Precision.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equals(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, 1));
-
-        Assertions.assertFalse(Precision.equals(Float.NaN, Float.NaN, 1));
-        Assertions.assertFalse(Precision.equals(Float.NaN, Float.NaN, 0));
-        Assertions.assertFalse(Precision.equals(Float.NaN, 0, 0));
-        Assertions.assertFalse(Precision.equals(Float.NaN, Float.POSITIVE_INFINITY, 0));
-        Assertions.assertFalse(Precision.equals(Float.NaN, Float.NEGATIVE_INFINITY, 0));
-
-        Assertions.assertFalse(Precision.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 100000));
+    public void testEqualsWithImplicitAllowedUlpsOf1() {
+        // Use the version without the ulp argument
+        assertEqualsIncludingNaNWithAllowedUlps((a, b, ulp) -> Precision.equals(a, b), false, true);
     }
 
     @Test
-    public void testEqualsWithAllowedUlps() {
-        Assertions.assertTrue(Precision.equals(0.0, -0.0, 1));
-
-        Assertions.assertTrue(Precision.equals(1.0, 1 + Math.ulp(1d), 1));
-        Assertions.assertFalse(Precision.equals(1.0, 1 + 2 * Math.ulp(1d), 1));
-
-        final double nUp1 = Math.nextAfter(1d, Double.POSITIVE_INFINITY);
-        final double nnUp1 = Math.nextAfter(nUp1, Double.POSITIVE_INFINITY);
-        Assertions.assertTrue(Precision.equals(1.0, nUp1, 1));
-        Assertions.assertTrue(Precision.equals(nUp1, nnUp1, 1));
-        Assertions.assertFalse(Precision.equals(1.0, nnUp1, 1));
-
-        Assertions.assertTrue(Precision.equals(0.0, Math.ulp(0d), 1));
-        Assertions.assertTrue(Precision.equals(0.0, -Math.ulp(0d), 1));
+    public void testEqualsIncludingNaNWithAllowedUlps() {
+        assertEqualsIncludingNaNWithAllowedUlps(Precision::equalsIncludingNaN, true, false);
+    }
 
-        Assertions.assertTrue(Precision.equals(153.0, 153.0, 1));
+    private static void assertEqualsIncludingNaNWithAllowedUlps(EqualsWithUlps fun,
+            boolean nanAreEqual, boolean fixed1Ulp) {
+        Assertions.assertTrue(fun.equals(0.0, -0.0, 1));
+
+        Assertions.assertTrue(fun.equals(1.0, 1 + Math.ulp(1d), 1));
+        Assertions.assertFalse(fun.equals(1.0, 1 + 2 * Math.ulp(1d), 1));
+
+        for (double value : new double[] {153.0, -128.0, 0.0, 1.0}) {
+            Assertions.assertTrue(fun.equals(value, value, 1));
+            Assertions.assertTrue(fun.equals(value, Math.nextUp(value), 1));
+            Assertions.assertFalse(fun.equals(value, Math.nextUp(Math.nextUp(value)), 1));
+            Assertions.assertTrue(fun.equals(value, Math.nextDown(value), 1));
+            Assertions.assertFalse(fun.equals(value, Math.nextDown(Math.nextDown(value)), 1));
+            // This test is conditional
+            if (!fixed1Ulp) {
+                Assertions.assertTrue(fun.equals(value, Math.nextUp(Math.nextUp(value)), 2));
+                Assertions.assertTrue(fun.equals(value, Math.nextDown(Math.nextDown(value)), 2));
+            }
+        }
 
-        Assertions.assertTrue(Precision.equals(153.0, 153.00000000000003, 1));
-        Assertions.assertFalse(Precision.equals(153.0, 153.00000000000006, 1));
-        Assertions.assertTrue(Precision.equals(153.0, 152.99999999999997, 1));
-        Assertions.assertFalse(Precision.equals(153, 152.99999999999994, 1));
+        Assertions.assertTrue(fun.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
 
-        Assertions.assertTrue(Precision.equals(-128.0, -127.99999999999999, 1));
-        Assertions.assertFalse(Precision.equals(-128.0, -127.99999999999997, 1));
-        Assertions.assertTrue(Precision.equals(-128.0, -128.00000000000003, 1));
-        Assertions.assertFalse(Precision.equals(-128.0, -128.00000000000006, 1));
+        Assertions.assertTrue(fun.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
 
-        Assertions.assertTrue(Precision.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 1));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 0));
+        Assertions.assertFalse(fun.equals(Double.NaN, 0, 0));
+        Assertions.assertFalse(fun.equals(0, Double.NaN, 0));
+        Assertions.assertFalse(fun.equals(Double.NaN, Double.POSITIVE_INFINITY, 0));
+        Assertions.assertFalse(fun.equals(Double.NaN, Double.NEGATIVE_INFINITY, 0));
 
-        Assertions.assertTrue(Precision.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
+        Assertions.assertFalse(fun.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
+    }
 
-        Assertions.assertFalse(Precision.equals(Double.NaN, Double.NaN, 1));
-        Assertions.assertFalse(Precision.equals(Double.NaN, Double.NaN, 0));
-        Assertions.assertFalse(Precision.equals(Double.NaN, 0, 0));
-        Assertions.assertFalse(Precision.equals(Double.NaN, Double.POSITIVE_INFINITY, 0));
-        Assertions.assertFalse(Precision.equals(Double.NaN, Double.NEGATIVE_INFINITY, 0));
+    // Tests for floating point equality match the above tests with arguments
+    // converted to float
 
-        Assertions.assertFalse(Precision.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
+    @Test
+    public void testFloatEqualsIncludingNaN() {
+        float[] testArray = {
+            Float.NaN,
+            Float.POSITIVE_INFINITY,
+            Float.NEGATIVE_INFINITY,
+            1f,
+            0f };
+        for (int i = 0; i < testArray.length; i++) {
+            for (int j = 0; j < testArray.length; j++) {
+                if (i == j) {
+                    Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[i], testArray[j]));
+                    Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[j], testArray[i]));
+                } else {
+                    Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[i], testArray[j]));
+                    Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[j], testArray[i]));
+                }
+            }
+        }
     }
 
     @Test
-    public void testEqualsIncludingNaNWithAllowedUlps() {
-        Assertions.assertTrue(Precision.equalsIncludingNaN(0.0, -0.0, 1));
+    public void testFloatEqualsWithAllowedDelta() {
+        assertFloatEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true);
+    }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(1.0, 1 + Math.ulp(1d), 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(1.0, 1 + 2 * Math.ulp(1d), 1));
+    @Test
+    public void testFloatEqualsIncludingNaNWithAllowedDelta() {
+        assertFloatEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true);
+    }
 
-        final double nUp1 = Math.nextAfter(1d, Double.POSITIVE_INFINITY);
-        final double nnUp1 = Math.nextAfter(nUp1, Double.POSITIVE_INFINITY);
-        Assertions.assertTrue(Precision.equalsIncludingNaN(1.0, nUp1, 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(nUp1, nnUp1, 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(1.0, nnUp1, 1));
+    private static void assertFloatEqualsWithAllowedDelta(FloatEqualsWithDelta fun, boolean nanAreEqual) {
+        Assertions.assertTrue(fun.equals(153.0000f, 153.0000f, .0625f));
+        Assertions.assertTrue(fun.equals(153.0000f, 153.0625f, .0625f));
+        Assertions.assertTrue(fun.equals(152.9375f, 153.0000f, .0625f));
+        Assertions.assertFalse(fun.equals(153.0000f, 153.0625f, .0624f));
+        Assertions.assertFalse(fun.equals(152.9374f, 153.0000f, .0625f));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 1.0f));
+        Assertions.assertTrue(fun.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1.0f));
+        Assertions.assertTrue(fun.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1.0f));
+        Assertions.assertFalse(fun.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 1.0f));
+    }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(0.0, Math.ulp(0d), 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(0.0, -Math.ulp(0d), 1));
+    @Test
+    public void testFloatEqualsWithAllowedUlps() {
+        assertFloatEqualsIncludingNaNWithAllowedUlps(Precision::equals, false, false);
+    }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(153.0, 153.0, 1));
+    @Test
+    public void testFloatEqualsWithImplicitAllowedUlpsOf1() {
+        // Use the version without the ulp argument
+        assertFloatEqualsIncludingNaNWithAllowedUlps((a, b, ulp) -> Precision.equals(a, b), false, true);
+    }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(153.0, 153.00000000000003, 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(153.0, 153.00000000000006, 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(153.0, 152.99999999999997, 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(153, 152.99999999999994, 1));
+    @Test
+    public void testFloatEqualsIncludingNaNWithAllowedUlps() {
+        assertFloatEqualsIncludingNaNWithAllowedUlps(Precision::equalsIncludingNaN, true, false);
+    }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(-128.0, -127.99999999999999, 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(-128.0, -127.99999999999997, 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(-128.0, -128.00000000000003, 1));
-        Assertions.assertFalse(Precision.equalsIncludingNaN(-128.0, -128.00000000000006, 1));
+    private static void assertFloatEqualsIncludingNaNWithAllowedUlps(FloatEqualsWithUlps fun,
+            boolean nanAreEqual, boolean fixed1Ulp) {
+        Assertions.assertTrue(fun.equals(0.0f, -0.0f, 1));
+
+        Assertions.assertTrue(fun.equals(1.0f, 1f + Math.ulp(1f), 1));
+        Assertions.assertFalse(fun.equals(1.0f, 1f + 2 * Math.ulp(1f), 1));
+
+        for (float value : new float[] {153.0f, -128.0f, 0.0f, 1.0f}) {
+            Assertions.assertTrue(fun.equals(value, value, 1));
+            Assertions.assertTrue(fun.equals(value, Math.nextUp(value), 1));
+            Assertions.assertFalse(fun.equals(value, Math.nextUp(Math.nextUp(value)), 1));
+            Assertions.assertTrue(fun.equals(value, Math.nextDown(value), 1));
+            Assertions.assertFalse(fun.equals(value, Math.nextDown(Math.nextDown(value)), 1));
+            // This test is conditional
+            if (!fixed1Ulp) {
+                Assertions.assertTrue(fun.equals(value, Math.nextUp(Math.nextUp(value)), 2));
+                Assertions.assertTrue(fun.equals(value, Math.nextDown(Math.nextDown(value)), 2));
+            }
+        }
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(Float.MAX_VALUE, Float.POSITIVE_INFINITY, 1));
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
-        Assertions.assertTrue(Precision.equalsIncludingNaN(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1));
+        Assertions.assertTrue(fun.equals(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, 1));
 
-        Assertions.assertTrue(Precision.equalsIncludingNaN(Double.NaN, Double.NaN, 1));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 1));
+        Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 0));
+        Assertions.assertFalse(fun.equals(Float.NaN, 0, 0));
+        Assertions.assertFalse(fun.equals(0, Float.NaN, 0));
+        Assertions.assertFalse(fun.equals(Float.NaN, Float.POSITIVE_INFINITY, 0));
+        Assertions.assertFalse(fun.equals(Float.NaN, Float.NEGATIVE_INFINITY, 0));
 
-        Assertions.assertFalse(Precision.equalsIncludingNaN(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
+        Assertions.assertFalse(fun.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 100000));
     }
 
     @Test
@@ -390,14 +420,6 @@ public class PrecisionTest {
         Assertions.assertEquals("-0.0", Double.toString(Precision.round(-1e-10, 0)));
     }
 
-
-    @Test
-    public void testIssue721() {
-        Assertions.assertEquals(-53,   Math.getExponent(Precision.EPSILON));
-        Assertions.assertEquals(-1022, Math.getExponent(Precision.SAFE_MIN));
-    }
-
-
     @Test
     public void testRepresentableDelta() {
         int nonRepresentableCount = 0;
@@ -415,6 +437,50 @@ public class PrecisionTest {
     }
 
     @Test
+    public void testIssue721() {
+        Assertions.assertEquals(-53, Math.getExponent(Precision.EPSILON));
+        Assertions.assertEquals(-1022, Math.getExponent(Precision.SAFE_MIN));
+    }
+
+    @Test
+    public void testMath475() {
+        final double a = 1.7976931348623182E16;
+        final double b = Math.nextUp(a);
+
+        double diff = Math.abs(a - b);
+        // Because they are adjacent floating point numbers, "a" and "b" are
+        // considered equal even though the allowed error is smaller than
+        // their difference.
+        Assertions.assertTrue(Precision.equals(a, b, 0.5 * diff));
+
+        final double c = Math.nextUp(b);
+        diff = Math.abs(a - c);
+        // Because "a" and "c" are not adjacent, the tolerance is taken into
+        // account for assessing equality.
+        Assertions.assertTrue(Precision.equals(a, c, diff));
+        Assertions.assertFalse(Precision.equals(a, c, Math.nextDown(1.0) * diff));
+    }
+
+    @Test
+    public void testMath475Float() {
+        final float a = 1.7976931348623182E16f;
+        final float b = Math.nextUp(a);
+
+        float diff = Math.abs(a - b);
+        // Because they are adjacent floating point numbers, "a" and "b" are
+        // considered equal even though the allowed error is smaller than
+        // their difference.
+        Assertions.assertTrue(Precision.equals(a, b, 0.5f * diff));
+
+        final float c = Math.nextUp(b);
+        diff = Math.abs(a - c);
+        // Because "a" and "c" are not adjacent, the tolerance is taken into
+        // account for assessing equality.
+        Assertions.assertTrue(Precision.equals(a, c, diff));
+        Assertions.assertFalse(Precision.equals(a, c, Math.nextDown(1.0f) * diff));
+    }
+
+    @Test
     public void testMath843() {
         final double afterEpsilon = Math.nextAfter(Precision.EPSILON,
                                                    Double.POSITIVE_INFINITY);


[commons-numbers] 02/09: Remove deprecated RNG from test.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 104254a7888663f625b271aff21fb4b4f9c155ec
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 17:41:56 2020 +0100

    Remove deprecated RNG from test.
---
 .../java/org/apache/commons/numbers/arrays/LinearCombinationTest.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/LinearCombinationTest.java b/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/LinearCombinationTest.java
index 6edcb1c..82894f6 100644
--- a/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/LinearCombinationTest.java
+++ b/commons-numbers-arrays/src/test/java/org/apache/commons/numbers/arrays/LinearCombinationTest.java
@@ -78,7 +78,7 @@ public class LinearCombinationTest {
 
     @Test
     public void testArrayVsInline() {
-        final UniformRandomProvider rng = RandomSource.create(RandomSource.XOR_SHIFT_1024_S);
+        final UniformRandomProvider rng = RandomSource.create(RandomSource.XO_SHI_RO_256_PP);
 
         double sInline;
         double sArray;


[commons-numbers] 08/09: Fixed test coverage in FactorialDoubleTest

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e20c9fd5ec8674abee243e6524df810efbe8b136
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 21:50:27 2020 +0100

    Fixed test coverage in FactorialDoubleTest
---
 .../apache/commons/numbers/combinatorics/FactorialDoubleTest.java  | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
index 7dc1b9a..c4075ea 100644
--- a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
@@ -51,6 +51,13 @@ public class FactorialDoubleTest {
     }
 
     @Test
+    public void testNonPositiveArgumentWithCache() {
+        Assertions.assertThrows(IllegalArgumentException.class,
+            () -> FactorialDouble.create().withCache(-1)
+        );
+    }
+
+    @Test
     public void testNonPositiveArgument() {
         Assertions.assertThrows(IllegalArgumentException.class,
             () -> FactorialDouble.create().value(-1)


[commons-numbers] 09/09: Fixed test coverage in CombinationsTest

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit dc0071f91f110f7e7974f568ff54bf77f13e72ac
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 22:09:31 2020 +0100

    Fixed test coverage in CombinationsTest
---
 .../numbers/combinatorics/Combinations.java        | 10 +---
 .../numbers/combinatorics/CombinationsTest.java    | 61 +++++++++++++++++++---
 2 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
index 86ef55a..6d19160 100644
--- a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
+++ b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
@@ -123,8 +123,7 @@ public final class Combinations implements Iterable<int[]> {
      * Combinations, D. Knuth, 2004.</p>
      * <p>
      * The degenerate cases {@code k == 0} and {@code k == n} are NOT handled by this
-     * implementation.  If constructor arguments satisfy {@code k == 0}
-     * or {@code k >= n}, no exception is generated, but the iterator is empty.
+     * implementation. It is assumed that {@code n > k > 0}.
      * </p>
      */
     private static class LexicographicIterator implements Iterator<int[]> {
@@ -151,8 +150,7 @@ public final class Combinations implements Iterable<int[]> {
          * Construct a CombinationIterator to enumerate {@code k}-sets from a set
          * of size {@code n}.
          * <p>
-         * NOTE: If {@code k === 0} or {@code k >= n}, the Iterator will be empty
-         * (that is, {@link #hasNext()} will return {@code false} immediately.
+         * NOTE: It is assumed that {@code n > k > 0}.
          * </p>
          *
          * @param n Size of the set from which subsets are enumerated.
@@ -161,10 +159,6 @@ public final class Combinations implements Iterable<int[]> {
         LexicographicIterator(int n, int k) {
             this.k = k;
             c = new int[k + 3];
-            if (k == 0 || k >= n) {
-                more = false;
-                return;
-            }
             // Initialize c to start with lexicographically first k-set
             for (int i = 1; i <= k; i++) {
                 c[i] = i - 1;
diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
index fba85bb..ca3ead1 100644
--- a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
@@ -17,6 +17,7 @@
 package org.apache.commons.numbers.combinatorics;
 
 import java.util.Iterator;
+import java.util.NoSuchElementException;
 import java.util.Comparator;
 
 import org.junit.jupiter.api.Assertions;
@@ -48,6 +49,7 @@ public class CombinationsTest {
         checkLexicographicIterator(6, 1);
         checkLexicographicIterator(3, 3);
         checkLexicographicIterator(1, 1);
+        checkLexicographicIterator(2, 0);
         checkLexicographicIterator(1, 0);
         checkLexicographicIterator(0, 0);
         checkLexicographicIterator(4, 2);
@@ -55,6 +57,13 @@ public class CombinationsTest {
     }
 
     @Test
+    public void testLexicographicIteratorThrows() {
+        checkLexicographicIteratorThrows(2, 1);
+        // Only 1 combination
+        checkLexicographicIteratorThrows(1, 1);
+    }
+
+    @Test
     public void testLexicographicComparatorWrongIterate1() {
         final int n = 5;
         final int k = 3;
@@ -182,14 +191,54 @@ public class CombinationsTest {
         Assertions.assertEquals(BinomialCoefficient.value(n, k), numIterates);
     }
 
+    /**
+     * Verifies that the iterator throws exceptions when misused.
+     *
+     * @param n Size of the set from which subsets are selected.
+     * @param k Size of the subsets to be enumerated.
+     */
+    private static void checkLexicographicIteratorThrows(int n,
+                                                         int k) {
+        Iterator<int[]> iter = Combinations.of(n, k).iterator();
+
+        // First call
+        iter.next();
+        // Check remove is not supported
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> iter.remove());
+
+        // Consume the rest
+        final long numIterates = BinomialCoefficient.value(n, k);
+        for (long i = 1; i < numIterates; i++) {
+            iter.next();
+        }
+        Assertions.assertThrows(NoSuchElementException.class, () -> iter.next());
+    }
+
     @Test
-    public void testCombinationsPrecondition1() {
-        Assertions.assertThrows(IllegalArgumentException.class,
-            () -> Combinations.of(4, 5));
+    public void testBinomialCoefficientKLargerThanN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(4, 5)
+        );
     }
+
     @Test
-    public void testCombinationsPrecondition2() {
-        Assertions.assertThrows(IllegalArgumentException.class,
-            () -> Combinations.of(-1, -2));
+    public void testBinomialCoefficientNegativeN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(-1, 1)
+        );
+    }
+
+    @Test
+    public void testBinomialCoefficientNegativeK() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(10, -1)
+        );
+    }
+
+    @Test
+    public void testBinomialCoefficientKAboveN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(10, 20)
+        );
     }
 }