// -*- C++ -*- //===-- rotate.pass.cpp ---------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 #include "support/pstl_test_config.h" #include #include #include #include "support/utils.h" using namespace TestUtils; template struct wrapper { T t; int move_count; explicit wrapper(T t_) : t(t_), move_count(0) {} wrapper& operator=(const T& t_) { t = t_; return *this; } wrapper(const wrapper& a) : move_count(0) { t = a.t; } wrapper& operator=(wrapper& a) { t = a.t; return *this; } wrapper& operator=(wrapper&& a) { t = a.t; move_count += 1; return *this; } }; template struct compare { bool operator()(const T& a, const T& b) { return a == b; } }; template struct compare> { bool operator()(const wrapper& a, const wrapper& b) { return a.t == b.t; } }; #include struct test_one_policy { #if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specializations to skip testing in case of broken configuration template void operator()(pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, Iterator actual_e, Size shift) { } template void operator()(pstl::execution::parallel_unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, Iterator actual_e, Size shift) { } #endif template void operator()(ExecutionPolicy&& exec, Iterator data_b, Iterator data_e, Iterator actual_b, Iterator actual_e, Size shift) { using namespace std; using T = typename iterator_traits::value_type; Iterator actual_m = std::next(actual_b, shift); copy(data_b, data_e, actual_b); Iterator actual_return = rotate(exec, actual_b, actual_m, actual_e); EXPECT_TRUE(actual_return == std::next(actual_b, std::distance(actual_m, actual_e)), "wrong result of rotate"); auto comparator = compare(); bool check = std::equal(actual_return, actual_e, data_b, comparator); check = check && std::equal(actual_b, actual_return, std::next(data_b, shift), comparator); EXPECT_TRUE(check, "wrong effect of rotate"); EXPECT_TRUE(check_move(exec, actual_b, actual_e, shift), "wrong move test of rotate"); } template typename std::enable_if< is_same_iterator_category::value && !std::is_same::value && std::is_same::value_type, wrapper>::value, bool>::type check_move(ExecutionPolicy&&, Iterator b, Iterator e, Size shift) { bool result = all_of(b, e, [](wrapper& a) { bool temp = a.move_count > 0; a.move_count = 0; return temp; }); return shift == 0 || result; } template typename std::enable_if< !(is_same_iterator_category::value && !std::is_same::value && std::is_same::value_type, wrapper>::value), bool>::type check_move(ExecutionPolicy&&, Iterator, Iterator, Size) { return true; } }; template void test() { const int32_t max_len = 100000; Sequence actual(max_len, [](std::size_t i) { return T(i); }); Sequence data(max_len, [](std::size_t i) { return T(i); }); for (int32_t len = 0; len < max_len; len = len <= 16 ? len + 1 : int32_t(3.1415 * len)) { int32_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; for (auto shift : shifts) { if (shift >= 0 && shift < len) { invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), actual.begin() + len, shift); } } } } int main() { test(); test>(); std::cout << done() << std::endl; return 0; }