Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.10.0 #187

Merged
merged 89 commits into from Mar 30, 2021
Merged

Release 1.10.0 #187

merged 89 commits into from Mar 30, 2021

Conversation

Morwenn
Copy link
Owner

@Morwenn Morwenn commented Mar 30, 2021

No description provided.

Its definition was broken for non-Clang non-GCC compilers.
Add some basic tests to ensure that every public-facing header can be
included without triggering any error.
That feature used to only be available in C++17, when the conversion of
lambdas to function pointers was made constepxr. The new design doesn't
use lambdas anymore, which allows the conversion to always be constexpr.

This commit also simplifies the implementation, making it less redundant
and easier to extend. Not using lambdas also means easier to understand
error messages and less potential generic lambda bloat.
Using signed integers ensures that we won't accidentally generate big
positive numbers instead of negative ones (which was most likely the
case for the alternating distributions).
While everything else compiles fine, the conversion from a sorter to a
function pointer seems broken with MSVC. It is reasonable to have this
single feature not working.
Grailsort creates invalid pointers here and there that are never
dereferenced, so generally don't cause any issues. However, forming
invalid iterators like that might cause issues, and MSVC debug iterators
do trip on grailsort.

This commit only fixes "strategy 3": when the algorithm can't find at
least 4 unique keys in the collection.
Add the measure of presortedness SUS(X) first described in Sorting
Shuffled Monotone Sequences by Levcopoulos and Petersson.

SUS(X) is the minimum number of non-decreasing subsequences (of possibly
non adjacent elements) into which X can be partitioned. It happens to be
equal to the size of the longest decreasing subsequence of X minus 1,
which is why we reuse the algorithm used to compute Rem(X) to compute
it.
Introduce rvalue_type_t which is rvalue_reference_t stripped of its
constness and referenceness, and use it everywhere it's relevant.
Instead of performing a binary search on the encroaching list that
checks both the greatest and smallest element, compare first to the head
and tail of the last encroaching list, then decide whether to binary
search the heads, binary search the tails, or create a new list where to
add the element.

This optimization was actually described in the original paper, but I
failed to understand it until recently. It is possible because the last
list has the biggest of the heads (smaller elements), and the smallest
of the tails (bigger elements). At worst the number of comparisons is
the same as with the previous algorithm, at best it performs up to 20%
fewer comparisons.

I haven't noticed a big difference when sorting arithmetic types, but it
should make a noticeable difference for types with a more expensive
comparisons.
This is basically the optimization that was implemented in melsort a few
commits ago: it compares every new element to the head and tail of the
last encroaching list first, then decides whether to perform a binary
search over the heads or the tails of the encroaching lists. This
optimization leads to up to 40% fewer comparisons performed in some
cases.
This will allow future algorithms to use different but compatible node
types as needed. The node pool was changed in a similar way: at some
point it is just a pool of nodes that share some properties, allowing
more types of nodes is good.

fixed_size_list_node was renamed to list_node because it could very well
be used in non-fixed-size lists in the future.
Implements the slabsort algorithm described by C. Levcopoulos and O.
Petersson in Sorting Shuffled Monotone Sequences.

Despite its suspiciously simple-looking 7 lines of pseudocode, this
algorithm required non-trivial changes in fixed_size_list and a small
refactoring of melsort, as weel as the addition of stable_partition to
the library details.
Be it in benchmarks or in tests, I never notived a significant
difference between the distributions shuffled_16_values and
alternating_16_values. The latter revealed pretty useless at the
end of the day, so I'm removing it.
This a stream from upstream, which also simplifies the block partition
logic.
I'm not sure how this managed to slip under my radar since 2015, that's
a bit embarrassing.
JFrog is sunsetting Bintray, so there's no use publishing more packages
there or mentioning them in the documentation. I don't expect this to
cause issues among users.
@Morwenn Morwenn changed the title Rlease 1.10.0 Release 1.10.0 Mar 30, 2021
@Morwenn Morwenn merged commit 67460c6 into master Mar 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant