Skip to content

Commit

Permalink
Merge pull request #216 from Morwenn/develop
Browse files Browse the repository at this point in the history
Release 1.15.0
  • Loading branch information
Morwenn committed Aug 12, 2023
2 parents 29b593a + 6605d2c commit 31dd8e9
Show file tree
Hide file tree
Showing 165 changed files with 16,331 additions and 962 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build-ubuntu.yml
@@ -1,4 +1,4 @@
# Copyright (c) 2021 Morwenn
# Copyright (c) 2021-2022 Morwenn
# SPDX-License-Identifier: MIT

name: Ubuntu Builds
Expand All @@ -23,13 +23,13 @@ on:

jobs:
build:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04

strategy:
fail-fast: false
matrix:
cxx:
- g++-5
- g++-7
- clang++-6.0
config:
# Release build
Expand All @@ -46,8 +46,8 @@ jobs:
- uses: actions/checkout@v3

- name: Install GCC
if: ${{matrix.cxx == 'g++-5'}}
run: sudo apt-get install -y g++-5
if: ${{matrix.cxx == 'g++-7'}}
run: sudo apt-get install -y g++-7

- name: Install Clang
if: ${{matrix.cxx == 'clang++-6.0'}}
Expand Down
39 changes: 35 additions & 4 deletions CMakeLists.txt
@@ -1,11 +1,11 @@
# Copyright (c) 2015-2022 Morwenn
# Copyright (c) 2015-2023 Morwenn
# SPDX-License-Identifier: MIT

cmake_minimum_required(VERSION 3.8.0)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

project(cpp-sort VERSION 1.14.0 LANGUAGES CXX)
project(cpp-sort VERSION 1.15.0 LANGUAGES CXX)

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
Expand All @@ -15,19 +15,50 @@ option(BUILD_TESTING "Build the cpp-sort test suite (deprecated, use CPPSORT_BUI
option(BUILD_EXAMPLES "Build the cpp-sort examples (deprecated, use CPPSORT_BUILD_EXAMPLES)" OFF)
option(CPPSORT_BUILD_TESTING "Build the cpp-sort test suite" ${BUILD_TESTING})
option(CPPSORT_BUILD_EXAMPLES "Build the cpp-sort examples" ${BUILD_EXAMPLES})
option(CPPSORT_ENABLE_AUDITS "Enable assertions in the library" OFF)
option(CPPSORT_ENABLE_ASSERTIONS "Enable assertions in the library" ${CPPSORT_ENABLE_AUDITS})
option(CPPSORT_USE_LIBASSERT "Use libassert for assertions (experimental)" OFF)

# Optionally use libassert for assertions
if (CPPSORT_USE_LIBASSERT)
include(DownloadProject)
download_project(PROJ libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert
GIT_TAG v1.2
UPDATE_DISCONNECTED 1
)
add_subdirectory(${libassert_SOURCE_DIR} ${libassert_BINARY_DIR})
endif()

# Create cpp-sort library and configure it
add_library(cpp-sort INTERFACE)
target_include_directories(cpp-sort INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

target_compile_features(cpp-sort INTERFACE cxx_std_14)

# MSVC won't work without a stricter standard compliance
if (MSVC)
target_compile_options(cpp-sort INTERFACE /permissive-)
target_compile_options(cpp-sort INTERFACE
/permissive-
/Zc:preprocessor
)
endif()

# Handle diagnostic options
if (CPPSORT_ENABLE_ASSERTIONS)
target_compile_definitions(cpp-sort INTERFACE CPPSORT_ENABLE_ASSERTIONS)
endif()
if (CPPSORT_ENABLE_AUDITS)
target_compile_definitions(cpp-sort INTERFACE CPPSORT_ENABLE_AUDITS)
endif()

# Optionally link to libassert
if (CPPSORT_USE_LIBASSERT)
target_link_libraries(cpp-sort INTERFACE assert)
target_compile_definitions(cpp-sort INTERFACE CPPSORT_USE_LIBASSERT)
endif()

add_library(cpp-sort::cpp-sort ALIAS cpp-sort)
Expand Down
21 changes: 11 additions & 10 deletions README.md
@@ -1,7 +1,7 @@
![cpp-sort logo](docs/images/cpp-sort-logo.svg)

[![Latest Release](https://img.shields.io/badge/release-1.14.0-blue.svg)](https://github.com/Morwenn/cpp-sort/releases/tag/1.14.0)
[![Conan Package](https://img.shields.io/badge/conan-cpp--sort%2F1.14.0-blue.svg)](https://conan.io/center/cpp-sort?version=1.14.0)
[![Latest Release](https://img.shields.io/badge/release-1.15.0-blue.svg)](https://github.com/Morwenn/cpp-sort/releases/tag/1.15.0)
[![Conan Package](https://img.shields.io/badge/conan-cpp--sort%2F1.15.0-blue.svg)](https://conan.io/center/recipes/cpp-sort?version=1.15.0)
[![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)

Expand Down Expand Up @@ -122,23 +122,22 @@ page][benchmarks].
![MacOS builds status](https://github.com/Morwenn/cpp-sort/workflows/MacOS%20Builds/badge.svg?branch=develop)

**cpp-sort** requires C++14 support, and should work with the following compilers:
* g++5.5 or more recent. It is known not to work with some older g++5 versions.
* clang++6.0 or more recent. It should work with clang++ versions all the way back to 3.8, but the CI pipeline doesn't have test for those anymore.
* Visual Studio 2019 version 16.8.3 or more recent, only with `/permissive-`. A few features are still unavailable.
* g++7 or more recent.
* clang++6.0 or more recent (with both libstdc++ and libc++).
* The versions of MinGW-w64 and AppleClang equivalent to the compilers mentioned above.
* Clang is notably tested with both libstdc++ and libc++.
* Visual Studio 2019 version 16.8.3 or more recent, only with `/permissive-`. A few features are unavailable.
* clang-cl corresponding the the Visual Studio version above.

The compilers listed above are the ones used by the CI pipeline, and the library is also tested
with the most recent versions of those compilers on a regular basis. All the other compiler
versions in-between are untested, but should also work. Feel free to open an issue if it isn't the
case.

The features in the library might differ depending on the C++ version used and on the compiler
extensions enabled. Those changes [are documented](https://github.com/Morwenn/cpp-sort/wiki/Changelog)
in the wiki.
extensions enabled. Those changes are documented [in the wiki][changelog].

The main repository contains additional support for standard tooling such as CMake or Conan.
You can read more about those [in the wiki](https://github.com/Morwenn/cpp-sort/wiki/Tooling).
You can read more about those [in the wiki][tooling].

# Thanks

Expand Down Expand Up @@ -217,7 +216,7 @@ slightly modified version of Matthew Bentley's [indiesort](https://github.com/ma
comes from Danila Kutenin's [miniselect library](https://github.com/danlark1/miniselect) and uses
Andrei Alexandrescu's [*AdaptiveQuickselect*](https://arxiv.org/abs/1606.00484) algorithm.

* The sorting networks used by `sorting_network_sorter` all come [from this list](http://users.telenet.be/bertdobbelaere/SorterHunter/sorting_networks.html)
* The sorting networks used by `sorting_network_sorter` all come [from this list](https://bertdobbelaere.github.io/sorting_networks_extended.html)
maintained by Bert Dobbelaere. The page has references to the sources of all of the sorting networks
it lists.

Expand All @@ -244,6 +243,8 @@ developed by Thøger Rivera-Thorsen.

[adaptive-sort]: https://en.wikipedia.org/wiki/Adaptive_sort
[benchmarks]: https://github.com/Morwenn/cpp-sort/wiki/Benchmarks
[changelog]: https://github.com/Morwenn/cpp-sort/wiki/Changelog
[drop-merge-adapter]: https://github.com/Morwenn/cpp-sort/wiki/Sorter-adapters#drop_merge_adapter
[heap-sorter]: https://github.com/Morwenn/cpp-sort/wiki/Sorters#heap_sorter
[split-adapter]: https://github.com/Morwenn/cpp-sort/wiki/Sorter-adapters#split_adapter
[tooling]: https://github.com/Morwenn/cpp-sort/wiki/Tooling
58 changes: 58 additions & 0 deletions benchmarks/benchmarking-tools/cpu_cycles.h
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#include <cstdint>
#include <utility>
#include <cpp-sort/utility/adapter_storage.h>
#include <cpp-sort/utility/metrics_tools.h>
#include <cpp-sort/detail/checkers.h>
#include "rdtsc.h"

////////////////////////////////////////////////////////////
// Tag

struct cpu_cycles_tag {};

////////////////////////////////////////////////////////////
// Metric

template<typename Sorter>
struct cpu_cycles:
cppsort::utility::adapter_storage<Sorter>,
cppsort::detail::check_iterator_category<Sorter>,
cppsort::detail::check_is_always_stable<Sorter>
{
using tag_t = cpu_cycles_tag;
using metric_t = cppsort::utility::metric<unsigned long long, tag_t>;

cpu_cycles() = default;

constexpr explicit cpu_cycles(Sorter sorter):
cppsort::utility::adapter_storage<Sorter>(std::move(sorter))
{}

template<typename... Args>
auto operator()(Args&&... args) const
-> decltype(
this->get()(std::forward<Args>(args)...),
metric_t(std::declval<unsigned long long>())
)
{
auto start = ::rdtsc();
this->get()(std::forward<Args>(args)...);
auto stop = ::rdtsc();
return metric_t(stop - start);
}
};

////////////////////////////////////////////////////////////
// is_stable specialization

namespace cppsort
{
template<typename Sorter, typename... Args>
struct is_stable<cpu_cycles<Sorter>(Args...)>:
is_stable<Sorter(Args...)>
{};
}
4 changes: 3 additions & 1 deletion benchmarks/benchmarking-tools/rdtsc.h
Expand Up @@ -26,7 +26,9 @@

#ifdef _WIN32
#include <intrin.h>
#define rdtsc __rdtsc
inline unsigned long long rdtsc() {
return __rdtsc();
}
#else
#ifdef __i586__
static __inline__ unsigned long long rdtsc() {
Expand Down
12 changes: 6 additions & 6 deletions benchmarks/errorbar-plot/bench.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021 Morwenn
* Copyright (c) 2020-2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#include <algorithm>
Expand All @@ -16,6 +16,7 @@
#include <string>
#include <utility>
#include <vector>
#include <cpp-sort/metrics/running_time.h>
#include <cpp-sort/sorters.h>
#include "../benchmarking-tools/distributions.h"
#include "../benchmarking-tools/filesystem.h"
Expand All @@ -36,7 +37,7 @@ using sort_f = void (*)(collection_t&);
std::pair<std::string, sort_f> sorts[] = {
{ "heap_sort", cppsort::heap_sort },
{ "poplar_sort", cppsort::poplar_sort },
{ "smooth_sort", cppsort::smooth_sort }
{ "smooth_sort", cppsort::smooth_sort },
};

// Distribution to benchmark against
Expand Down Expand Up @@ -95,11 +96,10 @@ int main(int argc, char** argv)
while (total_end - total_start < max_run_time && times.size() < max_runs_per_size) {
collection_t collection;
distribution(std::back_inserter(collection), size);
auto start = clock_type::now();
sort.second(collection);
auto end = clock_type::now();
auto do_sort = cppsort::metrics::running_time<sort_f>(sort.second);
auto duration = do_sort(collection);
assert(std::is_sorted(std::begin(collection), std::end(collection)));
times.push_back(std::chrono::duration<double, std::milli>(end - start).count());
times.push_back(duration.value().count());
total_end = clock_type::now();
}

Expand Down
21 changes: 10 additions & 11 deletions benchmarks/inversions/inv-bench.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2022 Morwenn
* Copyright (c) 2020-2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#include <cassert>
Expand All @@ -13,10 +13,11 @@
#include <string>
#include <utility>
#include <vector>
#include <cpp-sort/adapters.h>
#include <cpp-sort/sorters.h>
#include "../benchmarking-tools/cpu_cycles.h"
#include "../benchmarking-tools/distributions.h"
#include "../benchmarking-tools/filesystem.h"
#include "../benchmarking-tools/rdtsc.h"

using namespace std::chrono_literals;

Expand All @@ -31,9 +32,9 @@ using collection_t = std::vector<value_t>;
// Sorting algorithms to benchmark
using sort_f = void (*)(collection_t&);
std::pair<std::string, sort_f> sorts[] = {
{ "drop_merge_sort", cppsort::drop_merge_sort },
{ "pdq_sort", cppsort::pdq_sort },
{ "split_sort", cppsort::split_sort },
{ "heap_sort", cppsort::heap_sort },
{ "drop_merge_adapter(heap_sort)", cppsort::drop_merge_adapter<cppsort::heap_sorter>{} },
{ "split_adapter(heap_sort)", cppsort::split_adapter<cppsort::heap_sorter>{} },
};

// Size of the collections to sort
Expand Down Expand Up @@ -92,15 +93,13 @@ int main(int argc, char* argv[])

auto total_start = clock_type::now();
auto total_end = clock_type::now();
while (std::chrono::duration_cast<std::chrono::seconds>(total_end - total_start) < max_run_time &&
cycles.size() < max_runs_per_size) {
while (total_end - total_start < max_run_time && cycles.size() < max_runs_per_size) {
collection_t collection;
distribution(std::back_inserter(collection), size);
std::uint64_t start = rdtsc();
sort.second(collection);
std::uint64_t end = rdtsc();
auto do_sort = cpu_cycles<sort_f>(sort.second);
auto nb_cycles = do_sort(collection);
assert(std::is_sorted(std::begin(collection), std::end(collection)));
cycles.push_back(double(end - start) / size + 0.5);
cycles.push_back(double(nb_cycles.value()) / size + 0.5);
total_end = clock_type::now();
}

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/patterns/bars.py
Expand Up @@ -62,8 +62,8 @@ def main():
"pdq_sort",
"quick_sort",
"ska_sort",
"spin_sort",
"std_sort",
"verge_sort",
]

root = pathlib.Path(args.root)
Expand Down
19 changes: 9 additions & 10 deletions benchmarks/patterns/bench.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021 Morwenn
* Copyright (c) 2015-2023 Morwenn
* SPDX-License-Identifier: MIT
*/

Expand Down Expand Up @@ -36,8 +36,8 @@
#include <utility>
#include <vector>
#include <cpp-sort/sorters.h>
#include "../benchmarking-tools/cpu_cycles.h"
#include "../benchmarking-tools/distributions.h"
#include "../benchmarking-tools/rdtsc.h"

// Type of data to sort during the benchmark
using value_t = double;
Expand Down Expand Up @@ -77,8 +77,8 @@ int main()
{ "pdq_sort", cppsort::pdq_sort },
{ "quick_sort", cppsort::quick_sort },
{ "ska_sort", cppsort::ska_sort },
{ "spin_sort", cppsort::spin_sort },
{ "std_sort", cppsort::std_sort },
{ "verge_sort", cppsort::verge_sort },
};

std::size_t sizes[] = { 1'000'000 };
Expand All @@ -94,26 +94,25 @@ int main()
distributions_prng.seed(seed);

for (auto size: sizes) {
std::vector<std::uint64_t> cycles;
std::vector<std::uint64_t> cycles_per_element;

auto total_start = clock_type::now();
auto total_end = clock_type::now();
while (total_end - total_start < 5s) {
collection_t collection;
distribution.second(std::back_inserter(collection), size);
std::uint64_t start = rdtsc();
sort.second(collection);
std::uint64_t end = rdtsc();
auto do_sort = cpu_cycles<sort_f>(sort.second);
auto nb_cycles = do_sort(collection);
assert(std::is_sorted(std::begin(collection), std::end(collection)));
cycles.push_back(double(end - start) / size + 0.5);
cycles_per_element.push_back(double(nb_cycles.value()) / size + 0.5);
total_end = clock_type::now();
}

for (std::ostream* stream: {&std::cout, &std::cerr}) {
(*stream) << size << ", " << distribution.first << ", " << sort.first << ", ";
auto it = cycles.begin();
auto it = cycles_per_element.begin();
(*stream) << *it;
while (++it != cycles.end()) {
while (++it != cycles_per_element.end()) {
(*stream) << ", " << *it;
}
(*stream) << std::endl;
Expand Down

0 comments on commit 31dd8e9

Please sign in to comment.