Skip to content

Commit 7e05df4

Browse files
committed
Fix osc.max_for_size for size=1 and for even sizes
1 parent 33bf4c7 commit 7e05df4

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

docs/Measures-of-presortedness.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ Computes the *Oscillation* measure described by C. Levcopoulos and O. Petersson
235235

236236
When there isn't enough extra memory available, `probe::osc` falls back to an in-place O(n²) algorithm.
237237

238-
`max_for_size`: (|*X*| * (|*X*| - 2) - 1) / 2 when the values in *X* are strongly oscillating.
238+
`max_for_size`: it is reached when the values in $X$ are strongly oscillating, and equals $\frac{|X|(|X| - 2)}{2}$ when $|X|$ is even, and $\frac{|X|(|X| - 2) - 1}{2}$ when $|X|$ is odd.
239239

240240
**Note:** *Osc* does not respect Mannila's criterion 5: $Osc(\langle 2, 4, 1, 3, 1, 3 \rangle) \not \le |\langle 4, 1, 3, 1, 3 \rangle| + Osc(\langle 4, 1, 3, 1, 3 \rangle)$, though it is possible that it only happens when equivalent elements are involved.
241241

include/cpp-sort/probes/osc.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2022 Morwenn
2+
* Copyright (c) 2016-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55
#ifndef CPPSORT_PROBES_OSC_H_
@@ -210,7 +210,12 @@ namespace probe
210210
static constexpr auto max_for_size(Integer n)
211211
-> Integer
212212
{
213-
return n == 0 ? 0 : (n * (n - 2) - 1) / 2;
213+
if (n < 2) return 0;
214+
if (n % 2 == 0) {
215+
return (n * (n - 2)) / 2;
216+
} else {
217+
return (n * (n - 2) - 1) / 2;
218+
}
214219
}
215220
};
216221
}

tests/probes/osc.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2022 Morwenn
2+
* Copyright (c) 2016-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55
#include <forward_list>
@@ -31,13 +31,27 @@ TEST_CASE( "presortedness measure: osc", "[probe][osc]" )
3131
{
3232
// Example from the paper Adaptive Heapsort
3333
// by Levcopoulos and Petersson, the upper bound
34-
// should be (size * (size - 2) - 1) / 2
34+
// should be:
35+
// - When size is even: (size * (size - 2)) / 2
36+
// - When size is odd: (size * (size - 2) - 1) / 2
3537

36-
std::forward_list<int> li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6, 7 };
37-
auto max_n = osc.max_for_size(cppsort::utility::size(li));
38-
CHECK( max_n == 71 );
39-
CHECK( osc(li) == max_n );
40-
CHECK( osc(li.begin(), li.end()) == max_n );
38+
// Even number of elements
39+
{
40+
const std::forward_list<int> li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6 };
41+
auto max_n = osc.max_for_size(cppsort::utility::size(li));
42+
CHECK( max_n == 60 );
43+
CHECK( osc(li) == max_n );
44+
CHECK( osc(li.begin(), li.end()) == max_n );
45+
}
46+
47+
// Odd number of elements
48+
{
49+
const std::forward_list<int> li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6, 7 };
50+
auto max_n = osc.max_for_size(cppsort::utility::size(li));
51+
CHECK( max_n == 71 );
52+
CHECK( osc(li) == max_n );
53+
CHECK( osc(li.begin(), li.end()) == max_n );
54+
}
4155
}
4256

4357
SECTION( "regressions" )

0 commit comments

Comments
 (0)