Correct verification of zero length values and weights

This bug was found when checking the sonar report for the variance class
which uses MathArrays.verifyValues.
This commit is contained in:
Alex Herbert 2021-08-21 09:58:13 +01:00
parent 3f7de0eb1e
commit a2efd4fad5
2 changed files with 32 additions and 19 deletions

View File

@ -968,6 +968,7 @@ public final class MathArrays {
* <li>the weights array contains one or more infinite values</li>
* <li>the weights array contains one or more NaN values</li>
* <li>the weights array contains negative values</li>
* <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
* <li>the start and length arguments do not determine a valid array</li></ul>
* </li>
* <li>returns <code>false</code> if the array is non-null, but
@ -1004,6 +1005,7 @@ public final class MathArrays {
* <li>the weights array contains one or more infinite values</li>
* <li>the weights array contains one or more NaN values</li>
* <li>the weights array contains negative values</li>
* <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
* <li>the start and length arguments do not determine a valid array</li></ul>
* </li>
* <li>returns <code>false</code> if the array is non-null, but
@ -1031,27 +1033,29 @@ public final class MathArrays {
checkEqualLength(weights, values);
boolean containsPositiveWeight = false;
for (int i = begin; i < begin + length; i++) {
final double weight = weights[i];
if (Double.isNaN(weight)) {
throw new MathIllegalArgumentException(LocalizedFormats.NAN_ELEMENT_AT_INDEX, Integer.valueOf(i));
if (length != 0) {
boolean containsPositiveWeight = false;
for (int i = begin; i < begin + length; i++) {
final double weight = weights[i];
if (Double.isNaN(weight)) {
throw new MathIllegalArgumentException(LocalizedFormats.NAN_ELEMENT_AT_INDEX, Integer.valueOf(i));
}
if (Double.isInfinite(weight)) {
throw new MathIllegalArgumentException(LocalizedFormats.INFINITE_ARRAY_ELEMENT,
Double.valueOf(weight), Integer.valueOf(i));
}
if (weight < 0) {
throw new MathIllegalArgumentException(LocalizedFormats.NEGATIVE_ELEMENT_AT_INDEX,
Integer.valueOf(i), Double.valueOf(weight));
}
if (!containsPositiveWeight && weight > 0.0) {
containsPositiveWeight = true;
}
}
if (Double.isInfinite(weight)) {
throw new MathIllegalArgumentException(LocalizedFormats.INFINITE_ARRAY_ELEMENT,
Double.valueOf(weight), Integer.valueOf(i));
}
if (weight < 0) {
throw new MathIllegalArgumentException(LocalizedFormats.NEGATIVE_ELEMENT_AT_INDEX,
Integer.valueOf(i), Double.valueOf(weight));
}
if (!containsPositiveWeight && weight > 0.0) {
containsPositiveWeight = true;
}
}
if (!containsPositiveWeight) {
throw new MathIllegalArgumentException(LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
if (!containsPositiveWeight) {
throw new MathIllegalArgumentException(LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
}
}
return verifyValues(values, begin, length, allowEmpty);

View File

@ -635,6 +635,9 @@ public class MathArraysTest {
final double[] nullArray = null;
Assert.assertFalse(MathArrays.verifyValues(singletonArray, 0, 0));
Assert.assertFalse(MathArrays.verifyValues(testArray, 0, 0));
Assert.assertTrue(MathArrays.verifyValues(testArray, 0, 0, true));
Assert.assertFalse(MathArrays.verifyValues(testArray, testWeightsArray, 0, 0));
Assert.assertTrue(MathArrays.verifyValues(testArray, testWeightsArray, 0, 0, true));
try {
MathArrays.verifyValues(singletonArray, 2, 1); // start past end
Assert.fail("Expecting MathIllegalArgumentException");
@ -683,6 +686,12 @@ public class MathArraysTest {
} catch (MathIllegalArgumentException ex) {
// expected
}
try {
MathArrays.verifyValues(testArray, new double[testArray.length], 0, 6); // can't have all zero weights
Assert.fail("Expecting MathIllegalArgumentException");
} catch (MathIllegalArgumentException ex) {
// expected
}
}
@Test