llvm-project/pstl/test/test_partial_sort_copy.cpp
JF Bastien e637637ae4 Initial PSTL commit
The initial commit of the Parallel STL upstream (under LLVM umbrella) based on
Parallel STL 20181204 open source release, which is available by
https://github.com/intel/parallelstl

Author: Mikhail Dvorskiy <mikhail.dvorskiy@intel.com>

Differential Revision: https://reviews.llvm.org/D55889

llvm-svn: 349653
2018-12-19 17:45:32 +00:00

191 lines
6.7 KiB
C++

// -*- C++ -*-
//===-- test_partial_sort_copy.cpp ----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Tests for partial_sort_copy
#include <cmath>
#include "pstl_test_config.h"
#include "pstl/execution"
#include "pstl/algorithm"
#include "utils.h"
using namespace TestUtils;
template <typename T>
struct Num
{
T val;
Num() : val(0) {}
Num(T v) : val(v) {}
Num(const Num<T>& v) : val(v.val) {}
Num(Num<T>&& v) : val(v.val) {}
Num<T>&
operator=(const Num<T>& v)
{
val = v.val;
return *this;
}
operator T() const { return val; }
bool
operator<(const Num<T>& v) const
{
return val < v.val;
}
};
template <typename RandomAccessIterator>
struct test_one_policy
{
RandomAccessIterator d_first;
RandomAccessIterator d_last;
RandomAccessIterator exp_first;
RandomAccessIterator exp_last;
// This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed)
test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2)
: d_first(b1), d_last(e1), exp_first(b2), exp_last(e2)
{
}
#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
__PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
template <typename InputIterator, typename Size, typename T, typename Compare>
void
operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
const T& trash, Compare compare)
{
}
template <typename InputIterator, typename Size, typename T, typename Compare>
void
operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
const T& trash, Compare compare)
{
}
template <typename InputIterator, typename Size, typename T>
void
operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
const T& trash)
{
}
template <typename InputIterator, typename Size, typename T>
void
operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
const T& trash)
{
}
#endif
template <typename Policy, typename InputIterator, typename Size, typename T, typename Compare>
void
operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash,
Compare compare)
{
prepare_data(first, last, n1, trash);
RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare);
RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare);
EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate");
EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate");
}
template <typename Policy, typename InputIterator, typename Size, typename T>
void
operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash)
{
prepare_data(first, last, n1, trash);
RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last);
RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last);
EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate");
EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate");
}
private:
template <typename InputIterator, typename Size, typename T>
void
prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash)
{
// The rand()%(2*n+1) encourages generation of some duplicates.
std::srand(42);
std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); });
std::fill(exp_first, exp_last, trash);
std::fill(d_first, d_last, trash);
}
};
template <typename T, typename Compare>
void
test_partial_sort_copy(Compare compare)
{
typedef typename Sequence<T>::iterator iterator_type;
const std::size_t n_max = 100000;
Sequence<T> in(n_max);
Sequence<T> out(2 * n_max);
Sequence<T> exp(2 * n_max);
std::size_t n1 = 0;
std::size_t n2;
T trash = T(-666);
for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
{
// If both sequences are equal
n2 = n1;
invoke_on_all_policies(
test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
in.begin() + n1, n1, n2, trash, compare);
// If first sequence is greater than second
n2 = n1 / 3;
invoke_on_all_policies(
test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
in.begin() + n1, n1, n2, trash, compare);
// If first sequence is less than second
n2 = 2 * n1;
invoke_on_all_policies(
test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
in.begin() + n1, n1, n2, trash, compare);
}
// Test partial_sort_copy without predicate
n1 = n_max;
n2 = 2 * n1;
invoke_on_all_policies(test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2),
in.begin(), in.begin() + n1, n1, n2, trash);
}
template <typename T>
struct test_non_const
{
template <typename Policy, typename InputIterator, typename OutputInterator>
void
operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
{
invoke_if(exec, [&]() {
partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less<T>()));
});
}
};
int32_t
main()
{
test_partial_sort_copy<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; });
test_partial_sort_copy<int32_t>([](int32_t x, int32_t y) { return x > y; });
test_algo_basic_double<int32_t>(run_for_rnd<test_non_const<int32_t>>());
std::cout << done() << std::endl;
return 0;
}