41 changes: 28 additions & 13 deletions test/test_fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,46 @@

using namespace TestUtils;

struct test_fill {
struct test_fill
{
template <typename It, typename T>
bool check(It first, It last, const T& value) {
bool
check(It first, It last, const T& value)
{
for (; first != last; ++first)
if (*first != value)
return false;
return true;
}

template <typename Policy, typename Iterator, typename T>
void operator()(Policy&& exec, Iterator first, Iterator last, const T& value) {
fill(first, last, T(value+1)); // initialize memory with different value
void
operator()(Policy&& exec, Iterator first, Iterator last, const T& value)
{
fill(first, last, T(value + 1)); // initialize memory with different value

fill(exec, first, last, value);
EXPECT_TRUE(check(first, last, value), "fill wrong result");
}
};

struct test_fill_n {
struct test_fill_n
{
template <typename It, typename Size, typename T>
bool check(It first, Size n, const T& value) {
bool
check(It first, Size n, const T& value)
{
for (Size i = 0; i < n; ++i, ++first)
if (*first != value)
return false;
return true;
}

template <typename Policy, typename Iterator, typename Size, typename T>
void operator()(Policy&& exec, Iterator first, Size n, const T& value) {
fill_n(first, n, T(value+1)); // initialize memory with different value
void
operator()(Policy&& exec, Iterator first, Size n, const T& value)
{
fill_n(first, n, T(value + 1)); // initialize memory with different value

const Iterator one_past_last = fill_n(exec, first, n, value);
const Iterator expected_return = std::next(first, n);
Expand All @@ -70,24 +80,29 @@ struct test_fill_n {
};

template <typename T>
void test_fill_by_type(std::size_t n) {
Sequence<T> in(n, [](std::size_t v)->T { return T(0); }); //fill with zeros
void
test_fill_by_type(std::size_t n)
{
Sequence<T> in(n, [](std::size_t v) -> T { return T(0); }); //fill with zeros
T value = -1;

invoke_on_all_policies(test_fill(), in.begin(), in.end(), value);
invoke_on_all_policies(test_fill_n(), in.begin(), n, value);
}

int32_t main( ) {
int32_t
main()
{

const std::size_t N = 100000;

for(std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.1415 * n)) {
for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.1415 * n))
{
test_fill_by_type<int32_t>(n);
test_fill_by_type<float64_t>(n);
}

std::cout<<done()<<std::endl;
std::cout << done() << std::endl;

return 0;
}
74 changes: 45 additions & 29 deletions test/test_find.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,61 +27,77 @@

using namespace TestUtils;

struct test_find {
#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
struct test_find
{
#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 Iterator, typename Value>
void operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) { }
void
operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value)
{
}
template <typename Iterator, typename Value>
void operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) { }
void
operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value)
{
}
#endif

template <typename Policy, typename Iterator, typename Value>
void operator()( Policy&& exec, Iterator first, Iterator last, Value value ) {
void
operator()(Policy&& exec, Iterator first, Iterator last, Value value)
{
auto i = std::find(first, last, value);
auto j = find( exec, first, last, value );
EXPECT_TRUE( i == j,
"wrong return value from find" );
auto j = find(exec, first, last, value);
EXPECT_TRUE(i == j, "wrong return value from find");
}
};

template<typename T, typename Value, typename Hit, typename Miss>
void test(Value value, Hit hit, Miss miss) {
template <typename T, typename Value, typename Hit, typename Miss>
void
test(Value value, Hit hit, Miss miss)
{
// Try sequences of various lengths.
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n) ) {
Sequence<T> in(n, [&](size_t k) -> T {
return miss(n^k);
});
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
Sequence<T> in(n, [&](size_t k) -> T { return miss(n ^ k); });
// Try different find positions, including not found.
// By going backwards, we can add extra matches that are *not* supposed to be found.
// The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time.
for( size_t m=n; m>0 ; m *= 0.6 ) {
if(m<n)
in[m] = hit(n^m);
for (size_t m = n; m > 0; m *= 0.6)
{
if (m < n)
in[m] = hit(n ^ m);
invoke_on_all_policies(test_find(), in.begin(), in.end(), value);
invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value);
}
}
}

// Type defined for sake of checking that std::find works with asymmetric ==.
class Weird {
class Weird
{
Number value;
public:
friend bool operator==(Number x, Weird y) {return x==y.value;}
Weird(int32_t val, OddTag ) : value(val,OddTag()) {}

public:
friend bool
operator==(Number x, Weird y)
{
return x == y.value;
}
Weird(int32_t val, OddTag) : value(val, OddTag()) {}
};

int32_t main( ) {
int32_t
main()
{
// Note that the "hit" and "miss" functions here avoid overflow issues.
test<Number>( Weird(42,OddTag()),
[](int32_t j){return Number(42,OddTag());}, // hit
[](int32_t j){return Number(j==42 ? 0 : j,OddTag());}); // miss
test<Number>(Weird(42, OddTag()), [](int32_t j) { return Number(42, OddTag()); }, // hit
[](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss

// Test with value that is equal to two different bit patterns (-0.0 and 0.0)
test<float32_t>( -0.0,
[](int32_t j){return j&1 ? 0.0 : -0.0;}, // hit
[](int32_t j){return j==0 ? ~j : j;}); // miss

test<float32_t>(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit
[](int32_t j) { return j == 0 ? ~j : j; }); // miss

std::cout << done() << std::endl;
return 0;
Expand Down
72 changes: 47 additions & 25 deletions test/test_find_end.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,28 @@

using namespace TestUtils;

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 specialization by policy type, in case of broken configuration
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 specialization by policy type, in case of broken configuration
template <typename Iterator1, typename Iterator2, typename Predicate>
void operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { }
void
operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
Predicate pred)
{
}
template <typename Iterator1, typename Iterator2, typename Predicate>
void operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { }
void
operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
Predicate pred)
{
}
#endif

template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
void operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) {
void
operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred)
{
using namespace std;
// For find_end
{
Expand All @@ -60,43 +72,53 @@ struct test_one_policy {
};

template <typename T>
void test(const std::size_t bits) {
void
test(const std::size_t bits)
{

const std::size_t max_n1 = 1000;
const std::size_t max_n2 = (max_n1 * 10) / 8;
Sequence<T> in(max_n1, [max_n1, bits](std::size_t k) {return T(2 * HashBits(max_n1, bits - 1) ^ 1); });
Sequence<T> sub(max_n2, [max_n1, bits](std::size_t k) {return T(2 * HashBits(max_n1, bits - 1)); });
for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) {
std::size_t sub_n[] = { 0, 1, 3, n1, (n1 * 10) / 8 };
std::size_t res[] = { 0, 1, n1 / 2, n1 };
for(auto n2 : sub_n) {
for(auto r : res) {
Sequence<T> in(max_n1, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); });
Sequence<T> sub(max_n2, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1)); });
for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
{
std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8};
std::size_t res[] = {0, 1, n1 / 2, n1};
for (auto n2 : sub_n)
{
for (auto r : res)
{
std::size_t i = r, isub = 0;
for(; i < n1 & isub < n2; ++i, ++isub)
for (; i < n1 & isub < n2; ++i, ++isub)
in[i] = sub[isub];
invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2, std::equal_to<T>());
invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(), sub.cbegin() + n2, std::equal_to<T>());
invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2,
std::equal_to<T>());
invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(),
sub.cbegin() + n2, std::equal_to<T>());
}
}
}
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename FirstIterator, typename SecondInterator>
void operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) {
void
operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
{
invoke_if(exec, [&]() {
find_end(exec, first_iter, first_iter, second_iter, second_iter,
non_const(std::equal_to<T>()));
search(exec, first_iter, first_iter, second_iter, second_iter,
non_const(std::equal_to<T>()));
find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
});
}
};

int32_t main( ) {
test<int32_t>(8*sizeof(int32_t));
test<uint16_t>(8*sizeof(uint16_t));
int32_t
main()
{
test<int32_t>(8 * sizeof(int32_t));
test<uint16_t>(8 * sizeof(uint16_t));
test<float64_t>(53);
#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
test<bool>(1);
Expand Down
66 changes: 45 additions & 21 deletions test/test_find_first_of.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,28 @@

using namespace TestUtils;

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 specialization by policy type, in case of broken configuration
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 specialization by policy type, in case of broken configuration
template <typename Iterator1, typename Iterator2, typename Predicate>
void operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { }
void
operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
Predicate pred)
{
}
template <typename Iterator1, typename Iterator2, typename Predicate>
void operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { }
void
operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
Predicate pred)
{
}
#endif

template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
void operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) {
void
operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred)
{
using namespace std;
Iterator1 expected = find_first_of(b, e, bsub, esub, pred);
Iterator1 actual = find_first_of(exec, b, e, bsub, esub, pred);
Expand All @@ -48,46 +60,58 @@ struct test_one_policy {
};

template <typename T, typename Predicate>
void test(Predicate pred) {
void
test(Predicate pred)
{

const std::size_t max_n1 = 1000;
const std::size_t max_n2 = (max_n1 * 10) / 8;
Sequence<T> in1(max_n1, [](std::size_t k) {return T(1); });
Sequence<T> in2(max_n2, [](std::size_t k) {return T(0); });
for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) {
std::size_t sub_n[] = { 0, 1, n1 / 3, n1, (n1 * 10) / 8 };
for(const auto n2 : sub_n) {
Sequence<T> in1(max_n1, [](std::size_t k) { return T(1); });
Sequence<T> in2(max_n2, [](std::size_t k) { return T(0); });
for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
{
std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8};
for (const auto n2 : sub_n)
{
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.data(), in2.data() + n2, pred);

in2[n2 / 2] = T(1);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2, pred);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2,
pred);

if (n2 >= 3) {
if (n2 >= 3)
{
in2[2 * n2 / 3] = T(1);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(), in2.begin() + n2, pred);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(),
in2.begin() + n2, pred);
in2[2 * n2 / 3] = T(0);
}
in2[n2 / 2] = T(0);
}
}
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(), in1.data() + max_n1 / 10, pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(),
in1.data() + max_n1 / 10, pred);
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename FirstIterator, typename SecondInterator>
void operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) {
void
operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
{
invoke_if(exec, [&]() {
find_first_of(exec, first_iter, first_iter, second_iter, second_iter,
non_const(std::equal_to<T>()));
find_first_of(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
});
}
};

int32_t main() {
int32_t
main()
{
test<int32_t>(std::equal_to<int32_t>());
test<uint16_t>(std::not_equal_to<uint16_t>());
test<float64_t>([](const float64_t x, const float64_t y) {return x*x == y*y; });
test<float64_t>([](const float64_t x, const float64_t y) { return x * x == y * y; });

test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());

Expand Down
75 changes: 45 additions & 30 deletions test/test_find_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,49 +27,64 @@

using namespace TestUtils;

struct test_find_if {
#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
struct test_find_if
{
#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 Iterator, typename Predicate, typename NotPredicate>
void operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) { }
void
operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred,
NotPredicate not_pred)
{
}
template <typename Iterator, typename Predicate, typename NotPredicate>
void operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) { }
void
operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred,
NotPredicate not_pred)
{
}
#endif

template <typename Policy, typename Iterator, typename Predicate, typename NotPredicate>
void operator()( Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred ) {
void
operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred)
{
auto i = std::find_if(first, last, pred);
auto j = find_if( exec, first, last, pred);
EXPECT_TRUE( i == j,
"wrong return value from find_if" );
auto i_not = find_if_not( exec, first, last, not_pred );
EXPECT_TRUE( i_not == i,
"wrong return value from find_if_not" );
auto j = find_if(exec, first, last, pred);
EXPECT_TRUE(i == j, "wrong return value from find_if");
auto i_not = find_if_not(exec, first, last, not_pred);
EXPECT_TRUE(i_not == i, "wrong return value from find_if_not");
}
};

template<typename T, typename Predicate, typename Hit, typename Miss>
void test(Predicate pred, Hit hit, Miss miss) {
auto not_pred = [pred](T x) {return !pred(x);};
template <typename T, typename Predicate, typename Hit, typename Miss>
void
test(Predicate pred, Hit hit, Miss miss)
{
auto not_pred = [pred](T x) { return !pred(x); };
// Try sequences of various lengths.
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n) ) {
Sequence<T> in(n, [&](size_t k) -> T {
return miss(n^k);
});
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
Sequence<T> in(n, [&](size_t k) -> T { return miss(n ^ k); });
// Try different find positions, including not found.
// By going backwards, we can add extra matches that are *not* supposed to be found.
// The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time.
for( size_t m=n; m>0; m *= 0.6 ) {
if(m<n)
in[m] = hit(n^m);
for (size_t m = n; m > 0; m *= 0.6)
{
if (m < n)
in[m] = hit(n ^ m);
invoke_on_all_policies(test_find_if(), in.begin(), in.end(), pred, not_pred);
invoke_on_all_policies(test_find_if(), in.cbegin(), in.cend(), pred, not_pred);
}
}
}

struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
auto is_even = [&](float64_t v) {
uint32_t i = (uint32_t)v;
return i % 2 == 0;
Expand All @@ -82,18 +97,18 @@ struct test_non_const {
}
};

int32_t main( ) {
int32_t
main()
{
#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
// Note that the "hit" and "miss" functions here avoid overflow issues.
test<Number>( IsMultiple(5,OddTag()),
[](int32_t j){return Number(j-j%5,OddTag());}, // hit
[](int32_t j){return Number(j%5==0 ? j^1 : j,OddTag());}); // miss
test<Number>(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit
[](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); }); // miss
#endif

// Try type for which algorithm can really be vectorized.
test<float32_t>([](float32_t x) {return x>=0;},
[](float32_t j){return j*j;},
[](float32_t j){return -1-j*j;});
test<float32_t>([](float32_t x) { return x >= 0; }, [](float32_t j) { return j * j; },
[](float32_t j) { return -1 - j * j; });

test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());

Expand Down
56 changes: 38 additions & 18 deletions test/test_for_each.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,79 @@

using namespace TestUtils;

template<typename Type>
struct Gen {
Type operator()(std::size_t k) {
return Type(k%5!=1 ? 3*k-7 : 0);
template <typename Type>
struct Gen
{
Type
operator()(std::size_t k)
{
return Type(k % 5 != 1 ? 3 * k - 7 : 0);
};
};

template<typename T>
struct Flip {
template <typename T>
struct Flip
{
int32_t val;
Flip(int32_t y) : val(y) {}
T operator()( T& x ) const {return x = val-x;}
T
operator()(T& x) const
{
return x = val - x;
}
};

struct test_one_policy {
struct test_one_policy
{
template <typename Policy, typename Iterator, typename Size>
void operator()( Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n) {
void
operator()(Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n)
{
typedef typename std::iterator_traits<Iterator>::value_type T;

// Try for_each
std::for_each(expected_first, expected_last, Flip<T>(1));
for_each( exec, first, last, Flip<T>(1) );
for_each(exec, first, last, Flip<T>(1));
EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each");

// Try for_each_n
std::for_each_n(pstl::execution::seq, expected_first, n, Flip<T>(1));
for_each_n( exec, first, n, Flip<T>(1) );
for_each_n(exec, first, n, Flip<T>(1));
EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n");
}
};

template <typename T>
void test() {
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n) ) {
void
test()
{
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
Sequence<T> inout(n, Gen<T>());
Sequence<T> expected(n, Gen<T>());
invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(), inout.size());
invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(),
inout.size());
}
}

struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
invoke_if(exec, [&]() {
auto f = [](typename std::iterator_traits<Iterator>::reference x) { x = x+1; };
auto f = [](typename std::iterator_traits<Iterator>::reference x) { x = x + 1; };

for_each(exec, iter, iter, non_const(f));
for_each_n(exec, iter, 0, non_const(f));
});
}
};

int32_t main( ) {
int32_t
main()
{
test<int32_t>();
test<uint16_t>();
test<float64_t>();
Expand Down
49 changes: 33 additions & 16 deletions test/test_generate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,78 @@
using namespace TestUtils;

template <typename T>
struct Generator_count {
struct Generator_count
{
const T def_val = T(-1);
T operator()() {
T
operator()()
{
return def_val;
}
T
default_value() const
{
return def_val;
}
T default_value() const { return def_val; }
};

struct test_generate {
struct test_generate
{
template <typename Policy, typename Iterator, typename Size>
void operator()(Policy&& exec, Iterator first, Iterator last, Size n) {
void
operator()(Policy&& exec, Iterator first, Iterator last, Size n)
{
using namespace std;
typedef typename std::iterator_traits<Iterator>::value_type T;

// Try random-access iterator
{
Generator_count<T> g;
generate(exec, first, last, g);
EXPECT_TRUE(std::count(first, last, g.default_value()) == n,
"generate wrong result for generate");
EXPECT_TRUE(std::count(first, last, g.default_value()) == n, "generate wrong result for generate");
std::fill(first, last, T(0));
}

{
Generator_count<T> g;
const auto m = n/2;
const auto m = n / 2;
auto last = generate_n(exec, first, m, g);
EXPECT_TRUE(std::count(first, last, g.default_value()) == m && last == std::next(first, m),
"generate_n wrong result for generate_n");
"generate_n wrong result for generate_n");
std::fill(first, last, T(0));
}
}
};

template <typename T>
void test_generate_by_type() {
for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n)) {
Sequence<T> in(n, [](size_t v)->T { return T(0); }); //fill by zero
void
test_generate_by_type()
{
for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n))
{
Sequence<T> in(n, [](size_t v) -> T { return T(0); }); //fill by zero

invoke_on_all_policies(test_generate(), in.begin(), in.end(), in.size());
}
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
auto gen = [](){return T(0);};
void
operator()(Policy&& exec, Iterator iter)
{
auto gen = []() { return T(0); };

generate(exec, iter, iter, non_const(gen));
generate_n(exec, iter, 0, non_const(gen));
}
};

int32_t main( ) {
int32_t
main()
{

test_generate_by_type<int32_t>();
test_generate_by_type<float64_t>();
Expand Down
53 changes: 36 additions & 17 deletions test/test_includes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,64 +29,83 @@
using namespace TestUtils;

template <typename T>
struct Num {
struct Num
{
T val;
explicit Num(const T& v) : val(v) {}

//for "includes" checks
template <typename T1>
bool operator<(const Num<T1>& v1) const{
bool
operator<(const Num<T1>& v1) const
{
return val < v1.val;
}

//The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them
template <typename T1>
operator Num<T1>() const { return Num<T1>((T1)val); }
operator Num<T1>() const
{
return Num<T1>((T1)val);
}
};

struct test_one_policy {
struct test_one_policy
{
template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type
operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) {
operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
Compare comp)
{

auto expect_res = std::includes(first1, last1, first2, last2, comp);
auto res = std::includes(exec, first1, last1, first2, last2, comp);
auto expect_res = std::includes(first1, last1, first2, last2, comp);
auto res = std::includes(exec, first1, last1, first2, last2, comp);

EXPECT_TRUE(expect_res == res, "wrong result for includes");
EXPECT_TRUE(expect_res == res, "wrong result for includes");
}

template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) {}
operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
Compare comp)
{
}
};

template<typename T1, typename T2, typename Compare>
void test_includes(Compare compare) {
template <typename T1, typename T2, typename Compare>
void
test_includes(Compare compare)
{

const std::size_t n_max = 1000000;

// The rand()%(2*n+1) encourages generation of some duplicates.
std::srand(42);

for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) {
for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m))
{
//prepare the input ranges
Sequence<T1> in1(n, [n](std::size_t k) { return rand() % (2 * k + 1); });
Sequence<T2> in2(m, [m](std::size_t k) { return rand() % (k+1); });
Sequence<T2> in2(m, [m](std::size_t k) { return rand() % (k + 1); });

std::sort(in1.begin(), in1.end(), compare);
std::sort(in2.begin(), in2.end(), compare);

invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare);

//test w/ non constant predicate
if(n < 5 && m < 5)
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), non_const(compare));
if (n < 5 && m < 5)
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(),
non_const(compare));
}
}
}

int32_t main() {
int32_t
main()
{

test_includes<float64_t, float64_t>(pstl::internal::pstl_less());
test_includes<Num<int64_t>, Num<int32_t>>([](const Num<int64_t>& x, const Num<int32_t>& y) { return x < y; });
Expand Down
122 changes: 72 additions & 50 deletions test/test_inplace_merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,32 @@

using namespace TestUtils;

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 specialization by policy type, in case of broken configuration
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 specialization by policy type, in case of broken configuration
template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
void operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1,
BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {}
void
operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
{
}

template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
void operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1,
BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {}
void
operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2,
BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
{
}
#endif

// inplace_merge works with bidirectional iterators at least
template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2,
typename Compare>
typename std::enable_if<!is_same_iterator_category<BiDirIt1, std::forward_iterator_tag>::value, void>::type
operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1,
BiDirIt1 first2, BiDirIt1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {
operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m,
Generator1 generator1, Generator2 generator2, Compare comp)
{

using T = typename std::iterator_traits<BiDirIt1>::value_type;
const BiDirIt1 mid1 = std::next(first1, m);
Expand All @@ -60,81 +69,94 @@ struct test_one_policy {
EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate");
}

template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2,
typename Compare>
typename std::enable_if<is_same_iterator_category<BiDirIt1, std::forward_iterator_tag>::value, void>::type
operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1,
BiDirIt1 first2, BiDirIt1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {}
operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m,
Generator1 generator1, Generator2 generator2, Compare comp)
{
}
};

template <typename T, typename Generator1, typename Generator2, typename Compare>
void test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) {
void
test_by_type(Generator1 generator1, Generator2 generator2, Compare comp)
{
using namespace std;
size_t max_size = 100000;
Sequence<T> in1(max_size, [](size_t v) {return T(v); });
Sequence<T> exp(max_size, [](size_t v) {return T(v); });
Sequence<T> in1(max_size, [](size_t v) { return T(v); });
Sequence<T> exp(max_size, [](size_t v) { return T(v); });
size_t m;

for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
m = 0;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n,
exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
generator1, generator2, comp);

m = n / 3;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n,
exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
generator1, generator2, comp);

m = 2 * n / 3;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n,
exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
generator1, generator2, comp);
}
}

template<typename T>
struct LocalWrapper {
explicit LocalWrapper(int32_t k) : my_val(k) { }
LocalWrapper(LocalWrapper&& input) {
my_val = std::move(input.my_val);
}
LocalWrapper& operator=(LocalWrapper&& input) {
template <typename T>
struct LocalWrapper
{
explicit LocalWrapper(int32_t k) : my_val(k) {}
LocalWrapper(LocalWrapper&& input) { my_val = std::move(input.my_val); }
LocalWrapper&
operator=(LocalWrapper&& input)
{
my_val = std::move(input.my_val);
return *this;
}
bool operator<(const LocalWrapper<T>& w) const {
bool
operator<(const LocalWrapper<T>& w) const
{
return my_val < w.my_val;
}
friend bool operator==(const LocalWrapper<T>& x, const LocalWrapper<T>& y) {
friend bool
operator==(const LocalWrapper<T>& x, const LocalWrapper<T>& y)
{
return x.my_val == y.my_val;
}
friend std::ostream& operator<<(std::ostream& stream, const LocalWrapper<T>& input) {
friend std::ostream&
operator<<(std::ostream& stream, const LocalWrapper<T>& input)
{
return stream << input.my_val;
}
private:

private:
T my_val;
};

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
invoke_if(exec, [&]() {
inplace_merge(exec, iter, iter, iter, non_const(std::less<T>()));
});
void
operator()(Policy&& exec, Iterator iter)
{
invoke_if(exec, [&]() { inplace_merge(exec, iter, iter, iter, non_const(std::less<T>())); });
}
};

int32_t main( ) {
test_by_type<float64_t>([](int32_t i) {return -2 * i; },
[](int32_t i) {return -(2 * i + 1); },
[](const float64_t x, const float64_t y) {return x > y; });
int32_t
main()
{
test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); },
[](const float64_t x, const float64_t y) { return x > y; });

test_by_type<int32_t>([](int32_t i) { return 10 * i; },
[](int32_t i) { return i + 1; },
std::less<int32_t>());
test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>());

test_by_type<LocalWrapper<float32_t>>([](int32_t i) {return LocalWrapper<float32_t>(2*i+1); },
[](int32_t i) {return LocalWrapper<float32_t>(2 * i); },
std::less<LocalWrapper<float32_t>>());
test_by_type<LocalWrapper<float32_t>>([](int32_t i) { return LocalWrapper<float32_t>(2 * i + 1); },
[](int32_t i) { return LocalWrapper<float32_t>(2 * i); },
std::less<LocalWrapper<float32_t>>());

test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const<int32_t>>());

Expand Down
58 changes: 39 additions & 19 deletions test/test_is_heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,39 @@

using namespace TestUtils;

struct WithCmpOp {
struct WithCmpOp
{
int32_t _first;
int32_t _second;
WithCmpOp() : _first(0), _second(0) { };
explicit WithCmpOp(int32_t x) : _first(x), _second(x) { };
bool operator < (const WithCmpOp& rhs) const {
WithCmpOp() : _first(0), _second(0){};
explicit WithCmpOp(int32_t x) : _first(x), _second(x){};
bool
operator<(const WithCmpOp& rhs) const
{
return this->_first < rhs._first;
}
};

struct test_is_heap {
#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
struct test_is_heap
{
#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 Iterator, typename Predicate>
typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) { }
operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred)
{
}
template <typename Iterator, typename Predicate>
typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) { }
operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred)
{
}
#endif

template <typename Policy, typename Iterator, typename Predicate>
typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) {
operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred)
{
using namespace std;
// is_heap
{
Expand Down Expand Up @@ -83,16 +93,21 @@ struct test_is_heap {
// is_heap, is_heap_until works only with random access iterators
template <typename Policy, typename Iterator, typename Predicate>
typename std::enable_if<!is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) { }
operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred)
{
}
};

template <typename T, typename Comp>
void test_is_heap_by_type(Comp comp) {
void
test_is_heap_by_type(Comp comp)
{
using namespace std;

const size_t max_size = 100000;
for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
Sequence<T> in(n, [](size_t v)->T { return T(v); });
for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
Sequence<T> in(n, [](size_t v) -> T { return T(v); });

invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);

Expand All @@ -106,28 +121,33 @@ void test_is_heap_by_type(Comp comp) {
invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp);
}

Sequence<T> in(max_size/10, [](size_t v)->T { return T(1); });
Sequence<T> in(max_size / 10, [](size_t v) -> T { return T(1); });
invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
invoke_if(exec, [&]() {
is_heap(exec, iter, iter, non_const(std::less<T>()));
is_heap_until(exec, iter, iter, non_const(std::less<T>()));
});
}
};

int32_t main() {
int32_t
main()
{
test_is_heap_by_type<float32_t>(std::greater<float32_t>());
test_is_heap_by_type<WithCmpOp>(std::less<WithCmpOp>());
test_is_heap_by_type<uint64_t>([](uint64_t x, uint64_t y) {return x % 100 < y % 100; });
test_is_heap_by_type<uint64_t>([](uint64_t x, uint64_t y) { return x % 100 < y % 100; });

test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());

std::cout <<done() << std::endl;
std::cout << done() << std::endl;
return 0;
}
65 changes: 40 additions & 25 deletions test/test_is_partitioned.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,65 +26,80 @@

using namespace TestUtils;

struct test_one_policy {
struct test_one_policy
{
//dummy specialization by policy type, in case of broken configuration
#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN

template <typename Iterator1, typename Predicate>
void operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) {}
void
operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
{
}
template <typename Iterator1, typename Predicate>
void operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) {}
void
operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
{
}
#endif

template <typename ExecutionPolicy, typename Iterator1, typename Predicate>
void operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Predicate pred) {
void
operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Predicate pred)
{
const bool expected = std::is_partitioned(begin1, end1, pred);
const bool actual = std::is_partitioned(exec, begin1, end1, pred);
const bool actual = std::is_partitioned(exec, begin1, end1, pred);
EXPECT_TRUE(actual == expected, "wrong return result from is_partitioned");
}
};

template <typename T, typename Predicate>
void test(Predicate pred) {
void
test(Predicate pred)
{

const std::size_t max_n = 1000000;
Sequence<T> in(max_n, [](std::size_t k) {return T(k); });
Sequence<T> in(max_n, [](std::size_t k) { return T(k); });

for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) {
invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, pred);
for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
{
invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, pred);
std::partition(in.begin(), in.begin() + n1, pred);
invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, pred);
}
}

template<typename T>
struct LocalWrapper {
explicit LocalWrapper(std::size_t k) : my_val(k) { }
private:
template <typename T>
struct LocalWrapper
{
explicit LocalWrapper(std::size_t k) : my_val(k) {}

private:
T my_val;
};

struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
auto is_even = [&](float64_t v) {
uint32_t i = (uint32_t)v;
return i % 2 == 0;
};
invoke_if(exec, [&]() {
is_partitioned(exec, iter, iter, non_const(is_even));
});
invoke_if(exec, [&]() { is_partitioned(exec, iter, iter, non_const(is_even)); });
}
};

int32_t main( ) {
test<float64_t>([](const float64_t x) {return x < 0; });
test<int32_t>([](const int32_t x) {return x > 1000; });
test<uint16_t>([](const uint16_t x) {return x % 5 < 3; });
int32_t
main()
{
test<float64_t>([](const float64_t x) { return x < 0; });
test<int32_t>([](const int32_t x) { return x > 1000; });
test<uint16_t>([](const uint16_t x) { return x % 5 < 3; });
#if !__PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN && !__PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN
test<LocalWrapper<float64_t>>(
[](const LocalWrapper<float64_t>& x) {return true; }
);
test<LocalWrapper<float64_t>>([](const LocalWrapper<float64_t>& x) { return true; });
#endif

test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
Expand Down
34 changes: 22 additions & 12 deletions test/test_is_sorted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@

using namespace TestUtils;

struct test_is_sorted {
struct test_is_sorted
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator first, Iterator last, bool exam) {
void
operator()(Policy&& exec, Iterator first, Iterator last, bool exam)
{
using namespace std;
typedef typename std::iterator_traits<Iterator>::value_type T;

Expand All @@ -37,26 +40,28 @@ struct test_is_sorted {
EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator");
auto iexam = is_sorted_until(first, last);
auto ires = is_sorted_until(exec, first, last);
EXPECT_TRUE(iexam==ires, "is_sorted_until wrong result for random-access iterator");
EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator");

//try random-access iterator with a predicate
res = is_sorted(exec, first, last, std::less<T>());
EXPECT_TRUE(exam==res, "is_sorted wrong result for random-access iterator");
EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator");
iexam = is_sorted_until(first, last, std::less<T>());
ires = is_sorted_until(exec, first, last, std::less<T>());
EXPECT_TRUE(iexam==ires, "is_sorted_until wrong result for random-access iterator");
EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator");
}
};

template <typename T>
void test_is_sorted_by_type() {
void
test_is_sorted_by_type()
{

Sequence<T> in(99999, [](size_t v)->T { return T(v); }); //fill 0..n
Sequence<T> in(99999, [](size_t v) -> T { return T(v); }); //fill 0..n

invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end()));
invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end()));

in[in.size()/2] = -1;
in[in.size() / 2] = -1;
invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end()));
invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end()));

Expand All @@ -70,21 +75,26 @@ void test_is_sorted_by_type() {
invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end()));

//non-descending order
Sequence<T> in1(9, [](size_t v)->T { return T(0); });
Sequence<T> in1(9, [](size_t v) -> T { return T(0); });
invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end()));
invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end()));
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
is_sorted(exec, iter, iter, std::less<T>());
is_sorted_until(exec, iter, iter, std::less<T>());
}
};

int32_t main( ) {
int32_t
main()
{

test_is_sorted_by_type<int32_t>();
test_is_sorted_by_type<float64_t>();
Expand Down
93 changes: 58 additions & 35 deletions test/test_lexicographical_compare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,50 +28,61 @@

using namespace TestUtils;

struct test_one_policy {
struct test_one_policy
{

template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
void operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1,
Iterator2 begin2, Iterator2 end2, Predicate pred) {
void
operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2,
Predicate pred)
{
const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2, pred);
const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2, pred);
EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare with predicate");
}

template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
void operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) {
void
operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2)
{
const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2);
const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2);
EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare without predicate");
}
};

template <typename T1, typename T2, typename Predicate>
void test(Predicate pred) {
void
test(Predicate pred)
{

const std::size_t max_n = 1000000;
Sequence<T1> in1(max_n, [](std::size_t k) {return T1(k); });
Sequence<T2> in2(2 * max_n, [](std::size_t k) {return T2(k); });
Sequence<T1> in1(max_n, [](std::size_t k) { return T1(k); });
Sequence<T2> in2(2 * max_n, [](std::size_t k) { return T2(k); });

std::size_t n2;

// Test case: Call algorithm's version without predicate.
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, in2.cbegin() + 5 * max_n / 10);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10,
in2.cbegin() + 5 * max_n / 10);

// Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other.
std::size_t max_n2 = max_n / 10;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2, pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2, in2.begin() + 3 * max_n2, pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2,
pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2,
in2.begin() + 3 * max_n2, pred);

// Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other.
max_n2 = 2 * max_n;
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2, pred);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2,
pred);

for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) {
for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
{
// Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal.
n2 = n1;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1,
in2.begin(), in2.begin() + n2, pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);

n2 = n1;
// Test case: two ranges have different elements and are of the same length (second sequence less than first)
Expand All @@ -89,26 +100,30 @@ void test(Predicate pred) {
}

template <typename Predicate>
void test_string(Predicate pred) {
void
test_string(Predicate pred)
{

const std::size_t max_n = 1000000;
std::string in1 = "";
std::string in2 = "";
for (std::size_t n1 = 0; n1 <= max_n; ++n1) {
for (std::size_t n1 = 0; n1 <= max_n; ++n1)
{
in1 += n1;
}

for (std::size_t n1 = 0; n1 <= 2*max_n; ++n1) {
for (std::size_t n1 = 0; n1 <= 2 * max_n; ++n1)
{
in2 += n1;
}

std::size_t n2;

for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) {
for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
{
// Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal.
n2 = n1;
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1,
in2.begin(), in2.begin() + n2, pred);
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);

n2 = n1;
// Test case: two ranges have different elements and are of the same length (second sequence less than first)
Expand All @@ -119,40 +134,48 @@ void test_string(Predicate pred) {
in1[n1 / 5] = 'a';
invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred);
}
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, in2.cbegin() + 5 * max_n / 10);
invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10,
in2.cbegin() + 5 * max_n / 10);
}

template<typename T>
struct LocalWrapper {
explicit LocalWrapper(std::size_t k) : my_val(k) { }
bool operator<(const LocalWrapper<T>& w) const {
template <typename T>
struct LocalWrapper
{
explicit LocalWrapper(std::size_t k) : my_val(k) {}
bool
operator<(const LocalWrapper<T>& w) const
{
return my_val < w.my_val;
}
private:

private:
T my_val;
};

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename FirstIterator, typename SecondInterator>
void operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) {
void
operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
{
invoke_if(exec, [&]() {
lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter,
non_const(std::less<T>()));
lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less<T>()));
});
}
};

int32_t main( ) {
int32_t
main()
{
test<uint16_t, float64_t>(std::less<float64_t>());
test<float32_t, int32_t>(std::greater<float32_t>());
#if !__PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN
test<float64_t, int32_t>([](const float64_t x, const int32_t y) {return x*x < y*y; });
test<float64_t, int32_t>([](const float64_t x, const int32_t y) { return x * x < y * y; });
#endif
test<LocalWrapper<int32_t>, LocalWrapper<int32_t>>(
[](const LocalWrapper<int32_t>& x, const LocalWrapper<int32_t>& y) {return x < y; }
);
test_string([](const char x, const char y) {return x < y; });
[](const LocalWrapper<int32_t>& x, const LocalWrapper<int32_t>& y) { return x < y; });
test_string([](const char x, const char y) { return x < y; });

test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());

Expand Down
65 changes: 41 additions & 24 deletions test/test_merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@

using namespace TestUtils;

struct test_merge {
template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
void operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
OutputIterator out_first, OutputIterator out_last, Compare comp) {
struct test_merge
{
template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator,
typename Compare>
void
operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
OutputIterator out_first, OutputIterator out_last, Compare comp)
{
using namespace std;
{
const auto res = merge(exec, first1, last1, first2, last2, out_first, comp);
Expand All @@ -49,23 +53,31 @@ struct test_merge {
}

// for reverse iterators
template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
void operator()(Policy&& exec, std::reverse_iterator<InputIterator1> first1, std::reverse_iterator<InputIterator1> last1,
std::reverse_iterator<InputIterator2> first2, std::reverse_iterator<InputIterator2> last2,
std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last, Compare comp) {
template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator,
typename Compare>
void
operator()(Policy&& exec, std::reverse_iterator<InputIterator1> first1, std::reverse_iterator<InputIterator1> last1,
std::reverse_iterator<InputIterator2> first2, std::reverse_iterator<InputIterator2> last2,
std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last,
Compare comp)
{
using namespace std;
typedef typename std::iterator_traits<std::reverse_iterator<InputIterator1>>::value_type T;
const auto res = merge(exec, first1, last1, first2, last2, out_first, std::greater<T>());

EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate");
EXPECT_TRUE(is_sorted(out_first, res, std::greater<T>()), "wrong result from merge with predicate");
EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater<T>()), "first sequence is not a part of result");
EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater<T>()), "second sequence is not a part of result");
EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater<T>()),
"first sequence is not a part of result");
EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater<T>()),
"second sequence is not a part of result");
}
};

template <typename T, typename Generator1, typename Generator2>
void test_merge_by_type(Generator1 generator1, Generator2 generator2) {
void
test_merge_by_type(Generator1 generator1, Generator2 generator2)
{
using namespace std;
size_t max_size = 100000;
Sequence<T> in1(max_size, generator1);
Expand All @@ -74,30 +86,35 @@ void test_merge_by_type(Generator1 generator1, Generator2 generator2) {
std::sort(in1.begin(), in1.end());
std::sort(in2.begin(), in2.end());

for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) {
invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2, out.begin(), out.begin() + 1.5 * size, std::less<T>());
invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2, out.begin(), out.begin() + 3 * size/2, std::less<T>());
for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size))
{
invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2,
out.begin(), out.begin() + 1.5 * size, std::less<T>());
invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2,
out.begin(), out.begin() + 3 * size / 2, std::less<T>());
}
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename InputIterator, typename OutputIterator>
void operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) {
merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter,
non_const(std::less<T>()));
void
operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter)
{
merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
}
};

int32_t main( ) {
test_merge_by_type<int32_t>([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; },
[](size_t v) { return v * 2; });
test_merge_by_type<float64_t>([](size_t v) { return float64_t(v); },
[](size_t v) { return float64_t(v - 100); });
int32_t
main()
{
test_merge_by_type<int32_t>([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; });
test_merge_by_type<float64_t>([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); });

#if !__PSTL_ICC_16_17_TEST_64_TIMEOUT
test_merge_by_type<Wrapper<int16_t>>([](size_t v) { return Wrapper<int16_t>(v % 100); },
[](size_t v) { return Wrapper<int16_t>(v % 10); });
[](size_t v) { return Wrapper<int16_t>(v % 10); });
#endif

test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
Expand Down
97 changes: 64 additions & 33 deletions test/test_minmax_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@

using namespace TestUtils;

struct check_minelement {
struct check_minelement
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator begin, Iterator end) {
void
operator()(Policy&& exec, Iterator begin, Iterator end)
{
typedef typename std::iterator_traits<Iterator>::value_type T;
const Iterator expect = std::min_element(begin, end);
const Iterator result = std::min_element(exec, begin, end);
Expand All @@ -42,9 +45,12 @@ struct check_minelement {
}
};

struct check_maxelement {
struct check_maxelement
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator begin, Iterator end) {
void
operator()(Policy&& exec, Iterator begin, Iterator end)
{
typedef typename std::iterator_traits<Iterator>::value_type T;
const Iterator expect = std::max_element(begin, end);
const Iterator result = std::max_element(exec, begin, end);
Expand All @@ -54,9 +60,12 @@ struct check_maxelement {
}
};

struct check_minmaxelement {
struct check_minmaxelement
{
template <typename Policy, typename Iterator>
void operator() (Policy&& exec, Iterator begin, Iterator end) {
void
operator()(Policy&& exec, Iterator begin, Iterator end)
{
typedef typename std::iterator_traits<Iterator>::value_type T;
const std::pair<Iterator, Iterator> expect = std::minmax_element(begin, end);
const std::pair<Iterator, Iterator> got = std::minmax_element(exec, begin, end);
Expand All @@ -68,47 +77,56 @@ struct check_minmaxelement {
};

template <typename T>
struct sequence_wrapper {
struct sequence_wrapper
{
TestUtils::Sequence<T> seq;
const T min_value;
const T max_value;
static const std::size_t bits = 30; // We assume that T can handle signed 2^bits+1 value

// TestUtils::HashBits returns value between 0 and (1<<bits)-1,
// therefore we could threat 1<<bits as maximum and -(1<<bits) as a minimum
sequence_wrapper(std::size_t n) : seq(n), min_value(-(1<<bits)), max_value(1<<bits) {}
sequence_wrapper(std::size_t n) : seq(n), min_value(-(1 << bits)), max_value(1 << bits) {}

void pattern_fill() {
seq.fill( [](std::size_t i) -> T { return T(TestUtils::HashBits(i, bits)); });
void
pattern_fill()
{
seq.fill([](std::size_t i) -> T { return T(TestUtils::HashBits(i, bits)); });
}

// sets first one at position `at` and bunch of them farther
void set_desired_value(std::size_t at, T value) {
if(seq.size() == 0)
void
set_desired_value(std::size_t at, T value)
{
if (seq.size() == 0)
return;
seq[at] = value;

//Producing serveral red herrings
for(std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5))
for (std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5))
seq[i] = value;
}
};

template<typename T>
void test_by_type(std::size_t n){
template <typename T>
void
test_by_type(std::size_t n)
{
sequence_wrapper<T> wseq(n);

// to avoid overtesing we use std::set to leave only unique indexes
std::set<std::size_t> targets{0};
if(n > 1) {
if (n > 1)
{
targets.insert(1);
targets.insert(2.718282*n/3);
targets.insert(n/2);
targets.insert(n/7.389056);
targets.insert(n-1); // last
targets.insert(2.718282 * n / 3);
targets.insert(n / 2);
targets.insert(n / 7.389056);
targets.insert(n - 1); // last
}

for(std::set<std::size_t>::iterator it = targets.begin(); it != targets.end(); ++it) {
for (std::set<std::size_t>::iterator it = targets.begin(); it != targets.end(); ++it)
{
wseq.pattern_fill();
wseq.set_desired_value(*it, wseq.min_value);
TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.cbegin(), wseq.seq.cend());
Expand All @@ -118,48 +136,61 @@ void test_by_type(std::size_t n){
TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.cbegin(), wseq.seq.cend());
TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.begin(), wseq.seq.end());

if(targets.size() > 1) {
for(std::set<std::size_t>::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit) {
if(*rit == *it) // we requires at least 2 unique indexes in targets
if (targets.size() > 1)
{
for (std::set<std::size_t>::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit)
{
if (*rit == *it) // we requires at least 2 unique indexes in targets
break;
wseq.pattern_fill();
wseq.set_desired_value(*it, wseq.min_value); // setting minimum element
wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element
wseq.set_desired_value(*it, wseq.min_value); // setting minimum element
wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element
TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend());
TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end());
}
} else { // we must check this corner case; it can not be tested in loop above
}
else
{ // we must check this corner case; it can not be tested in loop above
TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend());
TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end());
}
}
}

// should provide minimal requirements only
struct OnlyLessCompare {
struct OnlyLessCompare
{
int32_t val;
OnlyLessCompare() : val(0) {}
OnlyLessCompare(int32_t val_) : val(val_) {}
bool operator<(const OnlyLessCompare& other) const {
bool
operator<(const OnlyLessCompare& other) const
{
return val < other.val;
}
};

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
max_element(exec, iter, iter, non_const(std::less<T>()));
min_element(exec, iter, iter, non_const(std::less<T>()));
minmax_element(exec, iter, iter, non_const(std::less<T>()));
}
};

int32_t main() {
int32_t
main()
{
using TestUtils::float64_t;
const std::size_t N = 100000;

for(std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n)) {
for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n))
{
test_by_type<float64_t>(n);
test_by_type<OnlyLessCompare>(n);
}
Expand Down
37 changes: 25 additions & 12 deletions test/test_mismatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@

using namespace TestUtils;

struct test_mismatch {
struct test_mismatch
{
template <typename Policy, typename Iterator1, typename Iterator2>
void operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2) {
void
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2)
{
using namespace std;
typedef typename iterator_traits<Iterator1>::value_type T;
{
Expand All @@ -43,7 +46,9 @@ struct test_mismatch {
}
}
template <typename Policy, typename Iterator1, typename Iterator2>
void operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) {
void
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
{
using namespace std;
typedef typename iterator_traits<Iterator1>::value_type T;
{
Expand All @@ -57,34 +62,38 @@ struct test_mismatch {
};

template <typename T>
void test_mismatch_by_type() {
void
test_mismatch_by_type()
{
using namespace std;
for (size_t size = 0; size <= 100000; size = size <= 16 ? size + 1 : size_t(3.1415 * size))
{
const T val = T(-1);
Sequence<T> in(size, [](size_t v)->T { return T(v % 100); });
Sequence<T> in(size, [](size_t v) -> T { return T(v % 100); });
{
Sequence<T> in2(in);
invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end());
invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin());

const size_t min_size = 3;
if (size > min_size) {
if (size > min_size)
{
const size_t idx_for_1 = size / min_size;
in[idx_for_1] = val, in[idx_for_1 + 1] = val, in[idx_for_1 + 2] = val;
invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end());
invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin());
}

const size_t idx_for_2 = 500;
if (size >= idx_for_2 - 1) {
if (size >= idx_for_2 - 1)
{
in2[size / idx_for_2] = val;
invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend());
invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin());
}
}
{
Sequence<T> in2(100, [](size_t v)->T { return T(v); });
Sequence<T> in2(100, [](size_t v) -> T { return T(v); });
invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end());
// We can't call std::mismatch with semantic below when size of second sequence less than size of first sequence
if (in2.size() <= in.size())
Expand All @@ -106,18 +115,22 @@ void test_mismatch_by_type() {
invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin());
}
}

}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename FirstIterator, typename SecondInterator>
void operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) {
void
operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
{
mismatch(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less<T>()));
}
};

int32_t main( ) {
int32_t
main()
{

test_mismatch_by_type<int32_t>();
test_mismatch_by_type<float64_t>();
Expand Down
42 changes: 27 additions & 15 deletions test/test_none_of.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,45 +35,55 @@

using namespace TestUtils;

struct test_none_of {
struct test_none_of
{
template <typename ExecutionPolicy, typename Iterator, typename Predicate>
void operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) {
void
operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected)
{

auto actualr = std::none_of(exec, begin, end, pred);
EXPECT_EQ( expected, actualr, "result for none_of" );
EXPECT_EQ(expected, actualr, "result for none_of");
}
};

template <typename T>
void test( size_t bits ) {
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
void
test(size_t bits)
{
for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{

// Sequence of odd values
Sequence<T> in(n, [n, bits](size_t k) {return T(2 * HashBits(n, bits - 1) ^ 1); });
Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });

// Even value, or false when T is bool.
T spike(2 * HashBits(n, bits - 1));

invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), true);
invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), true);
if( n>0 ) {
if (n > 0)
{
// Sprinkle in a hit
in[2*n/3] = spike;
in[2 * n / 3] = spike;
invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), false);
invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), false);

// Sprinkle in a few more hits
in[n/3] = spike;
in[n/2] = spike;
in[n / 3] = spike;
in[n / 2] = spike;
invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), false);
invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), false);
}
}
}

struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
auto is_even = [&](float64_t v) {
uint32_t i = (uint32_t)v;
return i % 2 == 0;
Expand All @@ -82,9 +92,11 @@ struct test_non_const {
}
};

int32_t main( ) {
test<int32_t>(8*sizeof(int32_t));
test<uint16_t>(8*sizeof(uint16_t));
int32_t
main()
{
test<int32_t>(8 * sizeof(int32_t));
test<uint16_t>(8 * sizeof(uint16_t));
test<float64_t>(53);
#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
test<bool>(1);
Expand Down
148 changes: 86 additions & 62 deletions test/test_nth_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,57 +30,77 @@
using namespace TestUtils;

// User defined type with minimal requirements
template<typename T>
struct DataType {
explicit DataType(int32_t k): my_val(k) { }
DataType(DataType&& input) {
template <typename T>
struct DataType
{
explicit DataType(int32_t k) : my_val(k) {}
DataType(DataType&& input)
{
my_val = std::move(input.my_val);
input.my_val = T(0);
}
DataType& operator=(DataType&& input) {
DataType&
operator=(DataType&& input)
{
my_val = std::move(input.my_val);
input.my_val = T(0);
return *this;
}
T get_val() const { return my_val; }
T
get_val() const
{
return my_val;
}

friend std::ostream& operator<<(std::ostream& stream, const DataType<T>& input) {
friend std::ostream&
operator<<(std::ostream& stream, const DataType<T>& input)
{
return stream << input.my_val;
}
private:

private:
T my_val;
};

template<typename T>
bool is_equal(const DataType<T>& x, const DataType<T>& y) {
template <typename T>
bool
is_equal(const DataType<T>& x, const DataType<T>& y)
{
return x.get_val() == y.get_val();
}

template<typename T>
bool is_equal(const T& x, const T& y) {
template <typename T>
bool
is_equal(const T& x, const T& y)
{
return x == y;
}

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 specialization by policy type, in case of broken configuration
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 specialization by policy type, in case of broken configuration
template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1,
Iterator1 first2, Iterator1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { }
operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
{
}
template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1,
Iterator1 first2, Iterator1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { }
operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
{
}
#endif

// nth_element works only with random access iterators
template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2,
typename Compare>
typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1,
Iterator1 first2, Iterator1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m,
Generator1 generator1, Generator2 generator2, Compare comp)
{

using T = typename std::iterator_traits<Iterator1>::value_type;
const Iterator1 mid1 = std::next(first1, m);
Expand All @@ -92,68 +112,72 @@ struct test_one_policy {
fill_data(mid2, last2, generator2);
std::nth_element(first1, mid1, last1, comp);
std::nth_element(exec, first2, mid2, last2, comp);
if (m > 0 && m < n) {
if (m > 0 && m < n)
{
EXPECT_TRUE(is_equal(*mid1, *mid2), "wrong result from nth_element with predicate");
}
EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2,
[comp](T&x, T&y) {return comp(y, x); }) == mid2, "wrong effect from nth_element with predicate");
EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2, [comp](T& x, T& y) { return comp(y, x); }) == mid2,
"wrong effect from nth_element with predicate");
}

template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2,
typename Compare>
typename std::enable_if<!is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1,
Iterator1 first2, Iterator1 last2,
Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {}
operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m,
Generator1 generator1, Generator2 generator2, Compare comp)
{
}
};

template <typename T, typename Generator1, typename Generator2, typename Compare>
void test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) {
void
test_by_type(Generator1 generator1, Generator2 generator2, Compare comp)
{
using namespace std;
size_t max_size = 10000;
Sequence<T> in1(max_size, [](size_t v) {return T(v); });
Sequence<T> exp(max_size, [](size_t v) {return T(v); });
Sequence<T> in1(max_size, [](size_t v) { return T(v); });
Sequence<T> exp(max_size, [](size_t v) { return T(v); });
size_t m;

for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
m = 0;
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n,
n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
generator1, generator2, comp);
m = n / 7;
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n,
n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
generator1, generator2, comp);
m = 3 * n / 5;
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n,
n, m, generator1, generator2, comp);
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
generator1, generator2, comp);
}
invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + max_size, in1.begin(), in1.begin() + max_size,
max_size, max_size, generator1, generator2, comp);
max_size, max_size, generator1, generator2, comp);
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
invoke_if(exec, [&]() {
nth_element(exec, iter, iter, iter, non_const(std::less<T>()));
});
void
operator()(Policy&& exec, Iterator iter)
{
invoke_if(exec, [&]() { nth_element(exec, iter, iter, iter, non_const(std::less<T>())); });
}
};

int32_t main( ) {
test_by_type<int32_t>([](int32_t i) { return 10 * i; },
[](int32_t i) { return i + 1; },
std::less<int32_t>());
test_by_type<int32_t>([](int32_t) { return 0; },
[](int32_t) { return 0; },
std::less<int32_t>());

test_by_type<float64_t>([](int32_t i) {return -2 * i; },
[](int32_t i) {return -(2 * i + 1); },
[](const float64_t x, const float64_t y) {return x > y; });

test_by_type<DataType<float32_t>>([](int32_t i) {return DataType<float32_t>(2 * i + 1); },
[](int32_t i) {return DataType<float32_t>(2 * i); },
[](const DataType<float32_t>& x, const DataType<float32_t>& y) {return x.get_val() < y.get_val(); });
int32_t
main()
{
test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>());
test_by_type<int32_t>([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less<int32_t>());

test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); },
[](const float64_t x, const float64_t y) { return x > y; });

test_by_type<DataType<float32_t>>(
[](int32_t i) { return DataType<float32_t>(2 * i + 1); }, [](int32_t i) { return DataType<float32_t>(2 * i); },
[](const DataType<float32_t>& x, const DataType<float32_t>& y) { return x.get_val() < y.get_val(); });

test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());

Expand Down
79 changes: 54 additions & 25 deletions test/test_partial_sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,52 @@ static std::atomic<int32_t> count_val;
static std::atomic<int32_t> count_comp;

template <typename T>
struct Num {
struct Num
{
T val;

Num() { ++count_val; }
Num(T v): val(v) { ++count_val; }
Num(const Num<T>& v): val(v.val) { ++count_val; }
Num(Num<T>&& v): val(v.val) { ++count_val; }
Num(T v) : val(v) { ++count_val; }
Num(const Num<T>& v) : val(v.val) { ++count_val; }
Num(Num<T>&& v) : val(v.val) { ++count_val; }
~Num() { --count_val; }
Num<T>& operator=(const Num<T>& v) { val = v.val; return *this; }
Num<T>&
operator=(const Num<T>& v)
{
val = v.val;
return *this;
}
operator T() const { return val; }
bool operator<(const Num<T>& v) const {
bool
operator<(const Num<T>& v) const
{
++count_comp;
return val < v.val;
}
};

struct test_brick_partial_sort {
struct test_brick_partial_sort
{
template <typename Policy, typename InputIterator, typename Compare>
typename std::enable_if<is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, Compare compare) {
typename std::enable_if<is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value,
void>::type
operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last,
Compare compare)
{

typedef typename std::iterator_traits<InputIterator>::value_type T;

// The rand()%(2*n+1) encourages generation of some duplicates.
std::srand(42);
const std::size_t n = last - first;
for (std::size_t k = 0; k < n; ++k) {
for (std::size_t k = 0; k < n; ++k)
{
first[k] = T(rand() % (2 * n + 1));
}
std::copy(first, last, exp_first);

for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p)) {
for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p))
{
auto m1 = first + p;
auto m2 = exp_first + p;

Expand All @@ -73,7 +87,8 @@ struct test_brick_partial_sort {
EXPECT_EQ_N(exp_first, first, p, "wrong effect from partial_sort");

//checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads;
if (m1 - first > 1) {
if (m1 - first > 1)
{
auto complex = std::ceil(n * std::log(float32_t(m1 - first)));
#if __PSTL_USE_PAR_POLICIES
auto p = tbb::this_task_arena::max_concurrency();
Expand All @@ -82,7 +97,8 @@ struct test_brick_partial_sort {
#endif

#ifdef _DEBUG
if (count_comp > complex*p) {
if (count_comp > complex * p)
{
std::cout << "complexity exceeded" << std::endl;
}
#endif
Expand All @@ -91,38 +107,51 @@ struct test_brick_partial_sort {
}

template <typename Policy, typename InputIterator, typename Compare>
typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value, void>::type
operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, Compare compare) {}
typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value,
void>::type
operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last,
Compare compare)
{
}
};

template<typename T, typename Compare>
void test_partial_sort(Compare compare) {
template <typename T, typename Compare>
void
test_partial_sort(Compare compare)
{

const std::size_t n_max = 100000;
Sequence<T> in(n_max);
Sequence<T> exp(n_max);
for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) {
invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n,
exp.begin(), exp.begin() + n, compare);
for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
{
invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n,
compare);
}
}

template <typename T>
struct test_non_const {
struct test_non_const
{
template <typename Policy, typename Iterator>
void operator()(Policy&& exec, Iterator iter) {
void
operator()(Policy&& exec, Iterator iter)
{
partial_sort(exec, iter, iter, iter, non_const(std::less<T>()));
}
};

int32_t main() {
int32_t
main()
{
count_val = 0;

test_partial_sort<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) {return x < y; });
test_partial_sort<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; });

EXPECT_TRUE(count_val == 0, "cleanup error");

test_partial_sort<int32_t>([](int32_t x, int32_t y) {return x > y; }); // Reversed so accidental use of < will be detected.
test_partial_sort<int32_t>(
[](int32_t x, int32_t y) { return x > y; }); // Reversed so accidental use of < will be detected.

test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());

Expand Down
Loading