blob: 8195e9a2dc8d099a398acbe063fb0ac09360160b [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LIBCXX_TEST_BENCHMARKS_ALGORITHMS_SORTING_COMMON_H
#define LIBCXX_TEST_BENCHMARKS_ALGORITHMS_SORTING_COMMON_H
#include <algorithm>
#include <cstddef>
#include <numeric>
#include <random>
#include <type_traits>
#include <vector>
namespace support {
// This function creates a vector with N int-like values.
//
// These values are arranged in such a way that they would invoke O(N^2)
// behavior on any quick sort implementation that satisifies certain conditions.
// Details are available in the following paper:
//
// "A Killer Adversary for Quicksort", M. D. McIlroy, Software-Practice &
// Experience Volume 29 Issue 4 April 10, 1999 pp 341-344.
// https://dl.acm.org/doi/10.5555/311868.311871.
template <class T>
std::vector<T> quicksort_adversarial_data(std::size_t n) {
static_assert(std::is_integral_v<T>);
assert(n > 0);
// If an element is equal to gas, it indicates that the value of the element
// is still to be decided and may change over the course of time.
T gas = n - 1;
std::vector<T> v;
v.resize(n);
for (unsigned int i = 0; i < n; ++i) {
v[i] = gas;
}
// Candidate for the pivot position.
int candidate = 0;
int nsolid = 0;
// Populate all positions in the generated input to gas.
std::vector<int> ascending_values(v.size());
// Fill up with ascending values from 0 to v.size()-1. These will act as
// indices into v.
std::iota(ascending_values.begin(), ascending_values.end(), 0);
std::sort(ascending_values.begin(), ascending_values.end(), [&](int x, int y) {
if (v[x] == gas && v[y] == gas) {
// We are comparing two inputs whose value is still to be decided.
if (x == candidate) {
v[x] = nsolid++;
} else {
v[y] = nsolid++;
}
}
if (v[x] == gas) {
candidate = x;
} else if (v[y] == gas) {
candidate = y;
}
return v[x] < v[y];
});
return v;
}
// ascending sorted values
template <class T>
std::vector<T> ascending_sorted_data(std::size_t n) {
std::vector<T> v(n);
std::iota(v.begin(), v.end(), 0);
return v;
}
// descending sorted values
template <class T>
std::vector<T> descending_sorted_data(std::size_t n) {
std::vector<T> v(n);
std::iota(v.begin(), v.end(), 0);
std::reverse(v.begin(), v.end());
return v;
}
// pipe-organ pattern
template <class T>
std::vector<T> pipe_organ_data(std::size_t n) {
std::vector<T> v(n);
std::iota(v.begin(), v.end(), 0);
auto half = v.begin() + v.size() / 2;
std::reverse(half, v.end());
return v;
}
// heap pattern
template <class T>
std::vector<T> heap_data(std::size_t n) {
std::vector<T> v(n);
std::iota(v.begin(), v.end(), 0);
std::make_heap(v.begin(), v.end());
return v;
}
// shuffled randomly
template <class T>
std::vector<T> shuffled_data(std::size_t n) {
std::vector<T> v(n);
std::iota(v.begin(), v.end(), 0);
std::mt19937 rng;
std::shuffle(v.begin(), v.end(), rng);
return v;
}
// single element in the whole sequence
template <class T>
std::vector<T> single_element_data(std::size_t n) {
std::vector<T> v(n);
return v;
}
struct NonIntegral {
NonIntegral() : value_(0) {}
NonIntegral(int i) : value_(i) {}
friend auto operator<(NonIntegral const& a, NonIntegral const& b) { return a.value_ < b.value_; }
friend auto operator>(NonIntegral const& a, NonIntegral const& b) { return a.value_ > b.value_; }
friend auto operator<=(NonIntegral const& a, NonIntegral const& b) { return a.value_ <= b.value_; }
friend auto operator>=(NonIntegral const& a, NonIntegral const& b) { return a.value_ >= b.value_; }
friend auto operator==(NonIntegral const& a, NonIntegral const& b) { return a.value_ == b.value_; }
friend auto operator!=(NonIntegral const& a, NonIntegral const& b) { return a.value_ != b.value_; }
private:
int value_;
};
} // namespace support
#endif // LIBCXX_TEST_BENCHMARKS_ALGORITHMS_SORTING_COMMON_H