Skip to content

Commit

Permalink
Merge pull request #173 from Morwenn/develop
Browse files Browse the repository at this point in the history
Release 1.8.1
  • Loading branch information
Morwenn committed Oct 25, 2020
2 parents b168400 + 2f4ec6c commit 432511a
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 44 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.8.0)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

project(cpp-sort VERSION 1.8.0 LANGUAGES CXX)
project(cpp-sort VERSION 1.8.1 LANGUAGES CXX)

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
Expand Down
4 changes: 2 additions & 2 deletions README.md
@@ -1,5 +1,5 @@
[![Latest Release](https://img.shields.io/badge/release-cpp--sort%2F1.8.0-blue.svg)](https://github.com/Morwenn/cpp-sort/releases)
[![Conan Package](https://img.shields.io/badge/conan-1.8.0-blue.svg)](https://bintray.com/conan/conan-center/cpp-sort%3A_)
[![Latest Release](https://img.shields.io/badge/release-cpp--sort%2F1.8.1-blue.svg)](https://github.com/Morwenn/cpp-sort/releases/tag/1.8.1)
[![Conan Package](https://img.shields.io/badge/conan-1.8.1-blue.svg)](https://conan.io/center/cpp-sort?version=1.8.1)
[![Build Status](https://travis-ci.org/Morwenn/cpp-sort.svg?branch=master)](https://travis-ci.org/Morwenn/cpp-sort)
[![License](https://img.shields.io/:license-mit-blue.svg)](https://doge.mit-license.org)
[![Code Coverage](https://codecov.io/gh/Morwenn/cpp-sort/branch/master/graph/badge.svg)](https://codecov.io/gh/Morwenn/cpp-sort)
Expand Down
2 changes: 1 addition & 1 deletion conanfile.py
Expand Up @@ -8,7 +8,7 @@

class CppSortConan(ConanFile):
name = "cpp-sort"
version = "1.8.0"
version = "1.8.1"
description = "Additional sorting algorithms & related tools"
topics = "conan", "cpp-sort", "sorting", "algorithms"
url = "https://github.com/Morwenn/cpp-sort"
Expand Down
64 changes: 36 additions & 28 deletions docs/Original-research.md

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions docs/Sorters.md
Expand Up @@ -228,11 +228,12 @@ Implements a flavour of [QuickMergeSort](https://arxiv.org/abs/1307.3033).
| Best | Average | Worst | Memory | Stable | Iterators |
| ----------- | ----------- | ----------- | ----------- | ----------- | ------------- |
| n | n log n | n log n | log n | No | Random-access |
| n | n log n | n log n | log² n | No | Forward |
| n | n log n | n log n | log² n | No | Bidirectional |
| n | n log² n | n log² n | log² n | No | Forward |

QuickMergeSort is an algorithm that performs a quicksort-like partition and tries to use mergesort on the bigger partition, using the smaller one as a swap buffer used for the merge operation when possible. The flavour of QuickMergeSort used by `quick_merge_sorter` actually uses an equivalent of [`std::nth_element`](https://en.cppreference.com/w/cpp/algorithm/nth_element) to partition the collection in 1/3-2/3 parts in order to maximize the size of the partition (2 thirds of the space) that can be merge-sorted using the other partition as a swap buffer.

The log n memory is due to top-down mergesort stack recursion in the random-access version, while the memory of the forward version use is dominated by the mutually recursive [introselect](https://en.wikipedia.org/wiki/Introselect) algorithm which is used to implement an `nth_element` equivalent for forward iterators.
The change in time complexity for forward iterators is due to the partitioning algorithm being O(n log n) instead of O(n). The log n memory is due to top-down mergesort stack recursion in the random-access version, while the memory of the forward version use is dominated by the mutually recursive [introselect](https://en.wikipedia.org/wiki/Introselect) algorithm which is used to implement an `nth_element` equivalent for forward iterators.

This sorter can't throw `std::bad_alloc`.

Expand All @@ -248,13 +249,14 @@ Implements a [quicksort](https://en.wikipedia.org/wiki/Quicksort).

| Best | Average | Worst | Memory | Stable | Iterators |
| ----------- | ----------- | ----------- | ----------- | ----------- | ------------- |
| n | n log n | n log n | log² n | No | Forward |
| n | n log n | n log n | log² n | No | Bidirectional |
| n | n log² n | n log² n | log² n | No | Forward |

Despite the name, this sorter actually implements some flavour of introsort: if quicksort performs more than 2*log(n) steps, it falls back to a [median-of-medians](https://en.wikipedia.org/wiki/Median_of_medians) pivot selection instead of the usual median-of-9 one. The median-of-medians selection being mutually recursive with an introselect algorithm explains the use of log²n stack memory.

This sorter can't throw `std::bad_alloc`.

*Changed in version 1.2.0:* `quick_sorter` used to run in O(n²), but a fallback to median-of-medians pivot selection was introduced to make it run in O(n log n), the tradeoff being the log²n space used by stack recursion (as opposed to the previous log n one).
*Changed in version 1.2.0:* `quick_sorter` used to run in O(n²), but a fallback to median-of-medians pivot selection was introduced to make it run in O(n log n) or O(n log² n) depending of the iterator category, the tradeoff being the log² n space used by stack recursion (as opposed to the previous log n one).

### `selection_sorter`

Expand Down
1 change: 1 addition & 0 deletions include/cpp-sort/adapters/indirect_adapter.h
Expand Up @@ -26,6 +26,7 @@
#include "../detail/iterator_traits.h"
#include "../detail/memory.h"
#include "../detail/scope_exit.h"
#include "../detail/type_traits.h"

namespace cppsort
{
Expand Down
2 changes: 1 addition & 1 deletion include/cpp-sort/detail/introselect.h
Expand Up @@ -250,7 +250,7 @@ namespace detail
iter_sort3(first, it1, it2, compare, projection);
iter_sort3(it3, middle, it4, compare, projection);
iter_sort3(it5, it6, last_1, compare, projection);
auto median_it = iter_sort3(it1, middle, it4, std::move(compare), std::move(projection));
auto median_it = iter_sort3(it1, middle, it6, std::move(compare), std::move(projection));
return std::make_pair(median_it, last_1);
} else {
auto last_1 = last_it(first, last, size);
Expand Down
4 changes: 3 additions & 1 deletion include/cpp-sort/detail/poplar_sort.h
Expand Up @@ -133,7 +133,9 @@ namespace detail
if (size < 2) return;

std::vector<poplar<RandomAccessIterator>> poplars;
poplars.reserve(log2(size));
// Harvey & Zatloukal, The Post-Order Heap:
// [...] the number of trees, k, is at most floor(lg(n + 1)) + 1
poplars.reserve(log2(size + 1) + 1);

//
// Size of the biggest poplar in the array, which always is a number
Expand Down
1 change: 0 additions & 1 deletion include/cpp-sort/detail/recmerge_bidirectional.h
Expand Up @@ -26,7 +26,6 @@
#include "iterator_traits.h"
#include "lower_bound.h"
#include "rotate.h"
#include "type_traits.h"
#include "upper_bound.h"

namespace cppsort
Expand Down
2 changes: 1 addition & 1 deletion include/cpp-sort/detail/timsort.h
Expand Up @@ -189,7 +189,7 @@ namespace detail
CPPSORT_ASSERT(n >= 0);

difference_type r = 0;
while (n >= min_merge) {
while (n >= 2 * min_merge) {
r |= (n & 1);
n >>= 1;
}
Expand Down
1 change: 1 addition & 0 deletions include/cpp-sort/detail/vergesort.h
Expand Up @@ -54,6 +54,7 @@ namespace detail

// Pair of iterators to iterate through the collection
auto next = is_sorted_until(first, last, compare, projection);
if (next == last) return;
auto current = std::prev(next);

while (true) {
Expand Down
4 changes: 2 additions & 2 deletions include/cpp-sort/sorters/quick_merge_sorter.h
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Morwenn
* Copyright (c) 2018-2020 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_SORTERS_QUICK_MERGE_SORTER_H_
Expand Down Expand Up @@ -82,7 +82,7 @@ namespace cppsort
////////////////////////////////////////////////////////////
// Sorter traits

using iterator_category = std::random_access_iterator_tag;
using iterator_category = std::forward_iterator_tag;
using is_always_stable = std::false_type;
};
}
Expand Down
2 changes: 1 addition & 1 deletion include/cpp-sort/version.h
Expand Up @@ -9,6 +9,6 @@

#define CPPSORT_VERSION_MAJOR 1
#define CPPSORT_VERSION_MINOR 8
#define CPPSORT_VERSION_PATCH 0
#define CPPSORT_VERSION_PATCH 1

#endif // CPPSORT_VERSION_H_
2 changes: 1 addition & 1 deletion testsuite/CMakeLists.txt
Expand Up @@ -19,7 +19,7 @@ else()
message(STATUS "Catch2 not found")
download_project(PROJ Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2
GIT_TAG master
GIT_TAG v2.13.2
UPDATE_DISCONNECTED 1
)
add_subdirectory(${Catch2_SOURCE_DIR} ${Catch2_BINARY_DIR})
Expand Down
36 changes: 36 additions & 0 deletions tools/release-checklist.md
@@ -0,0 +1,36 @@
List of actions to perform when releasing a new cpp-sort version.

### During the development

The following things need be done prior to the release if they didn't happen during the main
development phase:
- [ ] Update the documentation.
- [ ] Update the releases notes.
- [ ] Keep track of the things that will be changed in 2.0.0.

### Before the release

- [ ] Check that all issues linked to the milestone are closed.
- [ ] Check `NOTICE.txt` and `README.md` conformance for stolen code.
- [ ] Make sure that tests pass and examples build.
- [ ] Regenerate the benchmarks.
- [ ] Replace occurences of the version number:
- [ ] CMakeLists.txt
- [ ] conanfile.py
- [ ] README.md
- [ ] version.h
- [ ] Find a name for the new version.
- [ ] Open a merge request, let the CI do its job.
- [ ] Merge `develop` into `master`.
- [ ] Publish the release, don't forget to target `master`.

### After the release

- [ ] Add the Zenodo badge to the release notes.
- [ ] Close the new version's milestone.
- [ ] Push the new version to Bincrafters.
- [ ] Add the new version to Conan Center Index.
- [ ] Brag about it where relevant.
- [ ] Merge master into 2.0.0-develop branch.
- [ ] Fix merge issues.
- [ ] Improve as needed with C++17 and C++20 features.

0 comments on commit 432511a

Please sign in to comment.