This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits 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 f971927c Partition KBM to return the exact pivot range
f971927c is described below
commit f971927cf4cceee33991f90ab188aa2caf27da99
Author: Alex Herbert <[email protected]>
AuthorDate: Thu Aug 27 18:44:37 2026 +0100
Partition KBM to return the exact pivot range
Returning [l, r] instead of [l, rr] where rr = r-1 creates a bug in
linearPartition when a sub-range of the array is partitioned for the
FLAG_MOVE_SAMPLE option, and a[r] > a[rr]. The bound p1 == r is
incorrect and a[p0] != a[p1] for some data.
---
.../numbers/examples/jmh/arrays/Partition.java | 8 ++++--
.../numbers/examples/jmh/arrays/PartitionTest.java | 32 +++++++++++++++++++++-
2 files changed, 36 insertions(+), 4 deletions(-)
diff --git
a/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/arrays/Partition.java
b/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/arrays/Partition.java
index ce748984..a927cb5f 100644
---
a/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/arrays/Partition.java
+++
b/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/arrays/Partition.java
@@ -7835,9 +7835,11 @@ final class Partition {
while (x[p + 1] == v) {
if (++p == rr) {
// Edge-case: constant value in [ll, rr]
- // Return the full range [l, r] as a single edge element
- // will also be partitioned.
- upper[0] = r;
+ // Note the full range [l, r] will also be partitioned
+ // as a[r] >= a[rr].
+ // Callers that have used part of the remaining array
+ // to find a pivot require [l, rr] not [l, r].
+ upper[0] = rr;
return l;
}
}
diff --git
a/commons-numbers-examples/examples-jmh/src/test/java/org/apache/commons/numbers/examples/jmh/arrays/PartitionTest.java
b/commons-numbers-examples/examples-jmh/src/test/java/org/apache/commons/numbers/examples/jmh/arrays/PartitionTest.java
index 23d94ede..b4ec887f 100644
---
a/commons-numbers-examples/examples-jmh/src/test/java/org/apache/commons/numbers/examples/jmh/arrays/PartitionTest.java
+++
b/commons-numbers-examples/examples-jmh/src/test/java/org/apache/commons/numbers/examples/jmh/arrays/PartitionTest.java
@@ -968,7 +968,7 @@ class PartitionTest {
}
@ParameterizedTest
- @MethodSource(value = {"testPartition"})
+ @MethodSource(value = {"testPartition", "testPartitionLSPMoveSample"})
void testPartitionLSPMoveSample(double[] values, int[] indices) {
Assumptions.assumeTrue(indices.length == 1 ||
(indices.length == 2 && Math.abs(indices[1] - indices[0]) < 10));
@@ -979,6 +979,36 @@ class PartitionTest {
::partitionLSP);
}
+ static Stream<Arguments> testPartitionLSPMoveSample() {
+ return Stream.of(
+ // Edge case that uncovered a bug in partitionKBM when upgrading
+ // Commons RNG 1.6 to 1.7.
+ Arguments.of(
+ new double[] {0.0, -0.0, -14.0, 11.0, 20.0, 0.0, 21.0, -21.0,
0.0, 22.0, 0.0, -0.0, 15.0, -0.0, -19.0,
+ 0.0, -22.0, 0.0, -18.0, 13.0, -0.0, -0.0, 0.0, 12.0, 16.0,
17.0, 19.0, 23.0, 0.0, 14.0, 0.0, -0.0,
+ 0.0, -13.0, -15.0, -23.0, -0.0, -0.0, -17.0, -0.0, -16.0,
-0.0, -20.0, -0.0, 0.0, 18.0, -0.0},
+ new int[] {37}));
+ }
+
+ /**
+ * Test partition KBM honours the contract to return the correct bounds
+ * of the pivot region [p0, p1] when the input array is a constant
+ * value with a single higher value at the end of the array.
+ * Returning the full range [l, r] is an optimisation if the method is
allowed
+ * to indicate the full range of partitioned data. It will cause a bug if
+ * downstream code requires p1 to define the end the the pivot region.
+ * This occurs in linearSelect when the {@link Partition#FLAG_MOVE_SAMPLE}
+ * option is enabled and KBM is used for the sub-partition.
+ */
+ @Test
+ void testPartitionKBM() {
+ final double[] a = {0, 0, 0, 0, 1};
+ final int bound[] = {0};
+ final double p0 = Partition.partitionKBM(a, 0, a.length - 1, 2, bound);
+ Assertions.assertEquals(p0, 0);
+ Assertions.assertEquals(bound[0], 3);
+ }
+
@ParameterizedTest
@MethodSource(value = {"testPartition"})
void testPartitionLinearBFPRTPER(double[] values, int[] indices) {