diff --git a/.github/workflows/deploy-to-wiki.yml b/.github/workflows/deploy-to-wiki.yml deleted file mode 100644 index a4af7506..00000000 --- a/.github/workflows/deploy-to-wiki.yml +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2020-2024 Morwenn -# SPDX-License-Identifier: MIT - -name: Wiki Deployment - -on: - push: - branches: - - 1.x.y-stable - paths: - - 'docs/**' - -jobs: - sync-wiki-files: - name: Sync Wiki Files - - runs-on: ubuntu-latest - - steps: - - name: Checkout /docs - uses: actions/checkout@v4 - with: - repository: ${{github.repository}} - path: main - - - name: Checkout wiki - uses: actions/checkout@v4 - with: - repository: ${{github.repository}}.wiki - path: wiki - - - name: Sync wiki files - run: | - for docname in main/docs/*.md; do - old=$(basename "$docname"); - new=${old%.*}; - find main/docs -name "*.md" -exec sed -i "s/$old/$new/g" {} \; - done - rsync -avzr --delete --exclude='.git/' "main/docs/" "wiki/" - - - name: Commit changes - working-directory: wiki - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add . - git commit -m "Synchronize wiki with docs/" - - - name: Push changes to wiki - uses: ad-m/github-push-action@master - with: - directory: wiki - repository: ${{github.repository}}.wiki - branch: master diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cb861ec..fc4e93a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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.17.0 LANGUAGES CXX) +project(cpp-sort VERSION 1.17.1 LANGUAGES CXX) include(CMakePackageConfigHelpers) include(GNUInstallDirs) @@ -24,7 +24,7 @@ if (CPPSORT_USE_LIBASSERT) include(DownloadProject) download_project(PROJ libassert GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert - GIT_TAG 634f50fb4086d377ad9a2f83d693d2e8fe4972a7 # v2.1.4 + GIT_TAG bd33ba116f209bf71761c58dccc2f3bf277e0824 # v2.2.1 UPDATE_DISCONNECTED 1 ) add_subdirectory(${libassert_SOURCE_DIR} ${libassert_BINARY_DIR}) diff --git a/README.md b/README.md index bb061ec6..01ef2c76 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ ![cpp-sort logo](docs/images/cpp-sort-logo.svg) -[![Latest Release](https://img.shields.io/badge/release-1.17.0-blue.svg)](https://github.com/Morwenn/cpp-sort/releases/tag/1.17.0) -[![Conan Package](https://img.shields.io/badge/conan-cpp--sort%2F1.17.0-blue.svg)](https://conan.io/center/recipes/cpp-sort?version=1.17.0) +[![Latest Release](https://img.shields.io/badge/release-1.17.1-blue.svg)](https://github.com/Morwenn/cpp-sort/releases/tag/1.17.1) +[![Conan Package](https://img.shields.io/badge/conan-cpp--sort%2F1.17.1-blue.svg)](https://conan.io/center/recipes/cpp-sort?version=1.17.1) [![Code Coverage](https://codecov.io/gh/Morwenn/cpp-sort/branch/develop/graph/badge.svg)](https://codecov.io/gh/Morwenn/cpp-sort) [![Pitchfork Layout](https://img.shields.io/badge/standard-PFL-orange.svg)](https://github.com/vector-of-bool/pitchfork) +> [!WARNING] +> **Branch 1.x.y of this library is now in maintenance-only mode: bug fixes might happen and lead to patch versions, but new development will now exclusively happen in branch 2.x.y, which requires at least C++17.** + > *It would be nice if only one or two of the sorting methods would dominate all of the others, > regardless of application or the computer being used. But in fact, each method has its own > peculiar virtues. [...] Thus we find that nearly all of the algorithms deserve to be remembered, @@ -117,9 +120,10 @@ page][benchmarks]. # Compiler support & tooling -![Ubuntu builds status](https://github.com/Morwenn/cpp-sort/workflows/Ubuntu%20Builds/badge.svg?branch=develop) -![Windows builds status](https://github.com/Morwenn/cpp-sort/workflows/MSVC%20Builds/badge.svg?branch=develop) -![MacOS builds status](https://github.com/Morwenn/cpp-sort/workflows/MacOS%20Builds/badge.svg?branch=develop) +![Ubuntu builds status](https://github.com/Morwenn/cpp-sort/actions/workflows/build-ubuntu.yml/badge.svg?branch=1.x.y-develop) +![MSVC builds status](https://github.com/Morwenn/cpp-sort/actions/workflows/build-msvc.yml/badge.svg?branch=1.x.y-develop) +![MinGW-w64 builds status](https://github.com/Morwenn/cpp-sort/actions/workflows/build-mingw.yml/badge.svg?branch=1.x.y-develop) +![MacOS builds status](https://github.com/Morwenn/cpp-sort/actions/workflows/build-macos.yml/badge.svg?branch=1.x.y-develop) **cpp-sort** requires C++14 support, and should work with the following compilers: * g++-9 or more recent. diff --git a/cmake/DownloadProject.CMakeLists.cmake.in b/cmake/DownloadProject.CMakeLists.cmake.in index 89be4fdd..66c957f1 100644 --- a/cmake/DownloadProject.CMakeLists.cmake.in +++ b/cmake/DownloadProject.CMakeLists.cmake.in @@ -1,7 +1,7 @@ # Distributed under the OSI-approved MIT License. See accompanying # file LICENSE or https://github.com/Crascit/DownloadProject for details. -cmake_minimum_required(VERSION 2.8.2) +cmake_minimum_required(VERSION 3.5.0) project(${DL_ARGS_PROJ}-download NONE) diff --git a/conanfile.py b/conanfile.py index e0a85d42..9ee891ba 100644 --- a/conanfile.py +++ b/conanfile.py @@ -16,7 +16,7 @@ class CppSortConan(ConanFile): name = "cpp-sort" - version = "1.17.0" + version = "1.17.1" description = "Sorting algorithms & related tools" license = "MIT" url = "https://github.com/Morwenn/cpp-sort" diff --git a/docs/Home.md b/docs/Home.md index 57561186..fb2e2f92 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -1,6 +1,6 @@ ![cpp-sort logo](images/cpp-sort-logo.svg) -Welcome to the **cpp-sort 1.17.0** documentation! +Welcome to the **cpp-sort 1.17.1** documentation! This wiki contains documentation about the library: basic documentation about the many sorting tools and how to use them, documentation about the additional utilities provided by the library, as well as a few tutorials about writing your own sorters or sorter adapters. This main page explains a few general things that didn't quite fit in other parts of the documentation. diff --git a/docs/Measures-of-presortedness.md b/docs/Measures-of-presortedness.md index 8a9e3784..d72cd4fe 100644 --- a/docs/Measures-of-presortedness.md +++ b/docs/Measures-of-presortedness.md @@ -235,7 +235,7 @@ Computes the *Oscillation* measure described by C. Levcopoulos and O. Petersson When there isn't enough extra memory available, `probe::osc` falls back to an in-place O(n²) algorithm. -`max_for_size`: (|*X*| * (|*X*| - 2) - 1) / 2 when the values in *X* are strongly oscillating. +`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. **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. @@ -303,7 +303,7 @@ Spearman's footrule distance: sum of distances between the position of individua #include ``` -Computes the minimum number of non-decreasing subsequences (of possibly not adjacent elements) into which *X* can be partitioned. It happens to correspond to the size of the [longest decreasing subsequence][longest-increasing-subsequence] of *X*. +Computes the minimum number of non-decreasing subsequences (of possibly not adjacent elements) into which *X* can be partitioned, minus 1. It happens to correspond to the size of the [longest decreasing subsequence][longest-increasing-subsequence] of *X* minus 1. *SUS* stands for *Shuffled Up-Sequences* and was introduced in *Sorting Shuffled Monotone Sequences* by C. Levcopoulos and O. Petersson. diff --git a/docs/Tooling.md b/docs/Tooling.md index e0806548..4fa9e215 100644 --- a/docs/Tooling.md +++ b/docs/Tooling.md @@ -63,10 +63,10 @@ Note: when `CPPSORT_ENABLE_AUDITS` is `ON`, assertions in the library are enable conan search cpp-sort --remote=conancenter ``` -And then install any version to your local cache as follows (here with version 1.17.0): +And then install any version to your local cache as follows (here with version 1.17.1): ```sh -conan install --requires=cpp-sort/1.17.0 +conan install --requires=cpp-sort/1.17.1 ``` The packages downloaded from conan-center are minimal and only contain the files required to use **cpp-sort** as a library: the headers, CMake files and licensing information. If you need anything else you have to create your own package with the `conanfile.py` available in this repository. @@ -78,7 +78,7 @@ The packages downloaded from conan-center are minimal and only contain the files [Gollum][gollum], if installed, can be used to browse this documentation offline: 1. Navigate to the main `cpp-sort` directory in the command line -2. `gollum --page-file-dir docs --ref ` +2. `gollum --page-file-dir docs --ref --math katex` 3. Visit http://localhost:4567/Home This can notably used to browse old versions of the documentation. It seems however that `--ref` doesn't understand Git tags, so you have to create a proper branch from the version tag you want to browse beforehand. diff --git a/include/cpp-sort/detail/move.h b/include/cpp-sort/detail/move.h index 3d12b5a0..2de15654 100644 --- a/include/cpp-sort/detail/move.h +++ b/include/cpp-sort/detail/move.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 Morwenn + * Copyright (c) 2019-2025 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_DETAIL_MOVE_H_ @@ -102,8 +102,9 @@ namespace detail -> T* { using truth_type = std::integral_constant>::value && - std::is_trivial::value + std::is_trivially_copyable>::value && + std::is_trivially_copyable::value && + sizeof(T) == sizeof(value_type_t) >; return uninitialized_move_impl(truth_type{}, std::move(first), std::move(last), std::move(result), destroyer); diff --git a/include/cpp-sort/probes/osc.h b/include/cpp-sort/probes/osc.h index afa170b3..b78d6ca7 100644 --- a/include/cpp-sort/probes/osc.h +++ b/include/cpp-sort/probes/osc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Morwenn + * Copyright (c) 2016-2025 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_PROBES_OSC_H_ @@ -210,7 +210,12 @@ namespace probe static constexpr auto max_for_size(Integer n) -> Integer { - return n == 0 ? 0 : (n * (n - 2) - 1) / 2; + if (n < 2) return 0; + if (n % 2 == 0) { + return (n * (n - 2)) / 2; + } else { + return (n * (n - 2) - 1) / 2; + } } }; } diff --git a/include/cpp-sort/version.h b/include/cpp-sort/version.h index c84ce332..36a00237 100644 --- a/include/cpp-sort/version.h +++ b/include/cpp-sort/version.h @@ -9,6 +9,6 @@ #define CPPSORT_VERSION_MAJOR 1 #define CPPSORT_VERSION_MINOR 17 -#define CPPSORT_VERSION_PATCH 0 +#define CPPSORT_VERSION_PATCH 1 #endif // CPPSORT_VERSION_H_ diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt index f0c546bc..e0de7661 100644 --- a/test_package/CMakeLists.txt +++ b/test_package/CMakeLists.txt @@ -1,7 +1,7 @@ -# Copyright (c) 2018-2023 Morwenn +# Copyright (c) 2018-2025 Morwenn # SPDX-License-Identifier: MIT -cmake_minimum_required(VERSION 2.8.11) +cmake_minimum_required(VERSION 3.5.0) project(test_package LANGUAGES CXX) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 11d15c62..22ddb2fb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,7 +27,7 @@ else() message(STATUS "Catch2 not found") download_project(PROJ Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2 - GIT_TAG 2b60af89e23d28eefc081bc930831ee9d45ea58b # v3.8.1 + GIT_TAG 25319fd3047c6bdcf3c0170e76fa526c77f99ca9 # v3.10.0 UPDATE_DISCONNECTED 1 ) add_subdirectory(${Catch2_SOURCE_DIR} ${Catch2_BINARY_DIR}) @@ -208,6 +208,7 @@ add_executable(main-tests distributions/ascending.cpp distributions/ascending_sawtooth.cpp distributions/descending.cpp + distributions/descending_plateau.cpp distributions/descending_sawtooth.cpp distributions/median_of_3_killer.cpp distributions/pipe_organ.cpp diff --git a/tests/distributions/descending_plateau.cpp b/tests/distributions/descending_plateau.cpp new file mode 100644 index 00000000..3dfb00a1 --- /dev/null +++ b/tests/distributions/descending_plateau.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Morwenn + * SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include +#include +#include +#include +#include "test_distribution.h" + +TEMPLATE_TEST_CASE( "test random-access sorters with descending_plateau distribution", "[distributions]", + cppsort::adaptive_shivers_sorter, + cppsort::cartesian_tree_sorter, + cppsort::d_ary_heap_sorter<6>, + cppsort::drop_merge_sorter, + cppsort::grail_sorter<>, + cppsort::grail_sorter< + cppsort::utility::dynamic_buffer + >, + cppsort::heap_sorter, + cppsort::mel_sorter, + cppsort::merge_sorter, + cppsort::pdq_sorter, + cppsort::poplar_sorter, + cppsort::quick_merge_sorter, + cppsort::quick_sorter, + cppsort::ska_sorter, + cppsort::slab_sorter, + cppsort::smooth_sorter, + cppsort::spin_sorter, + cppsort::splay_sorter, + cppsort::split_sorter, + cppsort::spread_sorter, + cppsort::std_sorter, + cppsort::tim_sorter, + cppsort::verge_sorter, + cppsort::wiki_sorter<>, + cppsort::wiki_sorter< + cppsort::utility::dynamic_buffer + > ) +{ + std::vector collection; + helpers::test_distribution(collection, 10'000, dist::descending_plateau{}); +} + +TEMPLATE_TEST_CASE( "test bidirectional sorters with descending_plateau distribution", "[distributions]", + cppsort::cartesian_tree_sorter, + cppsort::drop_merge_sorter, + cppsort::merge_sorter, + cppsort::quick_merge_sorter, + cppsort::quick_sorter, + cppsort::slab_sorter, + cppsort::splay_sorter, + cppsort::verge_sorter ) +{ + std::list collection; + helpers::test_distribution(collection, 1000, dist::descending_plateau{}); +} diff --git a/tests/probes/osc.cpp b/tests/probes/osc.cpp index c650a299..aee7ecd6 100644 --- a/tests/probes/osc.cpp +++ b/tests/probes/osc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Morwenn + * Copyright (c) 2016-2025 Morwenn * SPDX-License-Identifier: MIT */ #include @@ -31,13 +31,27 @@ TEST_CASE( "presortedness measure: osc", "[probe][osc]" ) { // Example from the paper Adaptive Heapsort // by Levcopoulos and Petersson, the upper bound - // should be (size * (size - 2) - 1) / 2 + // should be: + // - When size is even: (size * (size - 2)) / 2 + // - When size is odd: (size * (size - 2) - 1) / 2 - std::forward_list li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6, 7 }; - auto max_n = osc.max_for_size(cppsort::utility::size(li)); - CHECK( max_n == 71 ); - CHECK( osc(li) == max_n ); - CHECK( osc(li.begin(), li.end()) == max_n ); + // Even number of elements + { + const std::forward_list li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6 }; + auto max_n = osc.max_for_size(cppsort::utility::size(li)); + CHECK( max_n == 60 ); + CHECK( osc(li) == max_n ); + CHECK( osc(li.begin(), li.end()) == max_n ); + } + + // Odd number of elements + { + const std::forward_list li = { 8, 5, 10, 3, 12, 1, 13, 2, 11, 4, 9, 6, 7 }; + auto max_n = osc.max_for_size(cppsort::utility::size(li)); + CHECK( max_n == 71 ); + CHECK( osc(li) == max_n ); + CHECK( osc(li.begin(), li.end()) == max_n ); + } } SECTION( "regressions" ) diff --git a/tools/test_failing_sorter.cpp b/tools/test_failing_sorter.cpp index 9c179450..7225efb9 100644 --- a/tools/test_failing_sorter.cpp +++ b/tools/test_failing_sorter.cpp @@ -71,6 +71,7 @@ void test(const char* name) << "osc: " << cppsort::probe::osc(copy2) << std::endl << "rem: " << cppsort::probe::rem(copy2) << std::endl << "runs: " << cppsort::probe::runs(copy2) << std::endl + << "spear: " << cppsort::probe::spear(copy2) << std::endl << "sus: " << cppsort::probe::sus(copy2) << std::endl << '\n';