|
1 | | -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors |
| 1 | +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors |
2 | 2 | // |
3 | 3 | // SPDX-License-Identifier: BSD-3-Clause |
4 | 4 |
|
5 | 5 | #include "core/base/iterator_factory.hpp" |
6 | 6 |
|
7 | 7 | #include <algorithm> |
8 | 8 | #include <complex> |
| 9 | +#include <iterator> |
9 | 10 | #include <numeric> |
10 | 11 | #include <vector> |
11 | 12 |
|
@@ -511,4 +512,141 @@ TYPED_TEST(PermuteIterator, DecreasingIterator) |
511 | 512 | } |
512 | 513 |
|
513 | 514 |
|
| 515 | +template <typename ValueType> |
| 516 | +class TransformIterator : public ::testing::Test { |
| 517 | +protected: |
| 518 | + using value_type = ValueType; |
| 519 | +}; |
| 520 | + |
| 521 | +TYPED_TEST_SUITE(TransformIterator, gko::test::ComplexAndPODTypes, |
| 522 | + TypenameNameGenerator); |
| 523 | + |
| 524 | + |
| 525 | +TYPED_TEST(TransformIterator, EmptyIterator) |
| 526 | +{ |
| 527 | + auto test_iter = gko::detail::make_transform_iterator<TypeParam*>( |
| 528 | + nullptr, [](TypeParam v) { return v; }); |
| 529 | + |
| 530 | + ASSERT_NO_THROW((void)std::find(test_iter, test_iter, TypeParam{})); |
| 531 | +} |
| 532 | + |
| 533 | + |
| 534 | +TYPED_TEST(TransformIterator, CopyingWithIdentityFunction) |
| 535 | +{ |
| 536 | + std::vector<TypeParam> vec{6, 2, 5, 2, 4}; |
| 537 | + std::vector<TypeParam> result; |
| 538 | + auto test_iter = gko::detail::make_transform_iterator( |
| 539 | + vec.begin(), [](TypeParam v) { return v; }); |
| 540 | + |
| 541 | + std::copy(test_iter, test_iter + vec.size(), std::back_inserter(result)); |
| 542 | + |
| 543 | + ASSERT_EQ(vec, result); |
| 544 | +} |
| 545 | + |
| 546 | + |
| 547 | +TYPED_TEST(TransformIterator, CopyingWithStatefulFunctor) |
| 548 | +{ |
| 549 | + TypeParam scale = 3; |
| 550 | + std::vector<TypeParam> vec{6, 2, 5, 2, 4}; |
| 551 | + std::vector<TypeParam> ref{18, 6, 15, 6, 12}; |
| 552 | + std::vector<TypeParam> result; |
| 553 | + auto test_iter = gko::detail::make_transform_iterator( |
| 554 | + vec.begin(), [scale](TypeParam v) { return scale * v; }); |
| 555 | + |
| 556 | + std::copy(test_iter, test_iter + vec.size(), std::back_inserter(result)); |
| 557 | + |
| 558 | + ASSERT_EQ(ref, result); |
| 559 | +} |
| 560 | + |
| 561 | + |
| 562 | +TYPED_TEST(TransformIterator, IncreasingIterator) |
| 563 | +{ |
| 564 | + std::vector<TypeParam> vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| 565 | + auto transform = [](TypeParam v) { return TypeParam{2} * v; }; |
| 566 | + |
| 567 | + auto test_iter = |
| 568 | + gko::detail::make_transform_iterator(vec.begin(), transform); |
| 569 | + auto begin = test_iter; |
| 570 | + auto plus_2 = begin + 2; |
| 571 | + auto plus_2_rev = 2 + begin; |
| 572 | + auto plus_minus_2 = plus_2 - 2; |
| 573 | + auto increment_pre_2 = begin; |
| 574 | + ++increment_pre_2; |
| 575 | + ++increment_pre_2; |
| 576 | + auto increment_post_2 = begin; |
| 577 | + increment_post_2++; |
| 578 | + increment_post_2++; |
| 579 | + auto increment_pre_test = begin; |
| 580 | + auto increment_post_test = begin; |
| 581 | + |
| 582 | + // check results for equality |
| 583 | + ASSERT_TRUE(begin == plus_minus_2); |
| 584 | + ASSERT_TRUE(plus_2 == increment_pre_2); |
| 585 | + ASSERT_TRUE(plus_2_rev == increment_pre_2); |
| 586 | + ASSERT_TRUE(increment_pre_2 == increment_post_2); |
| 587 | + ASSERT_TRUE(begin == increment_post_test++); |
| 588 | + ASSERT_TRUE(begin + 1 == ++increment_pre_test); |
| 589 | + ASSERT_TRUE(*plus_2 == TypeParam{2} * vec[2]); |
| 590 | + // check other comparison operators and difference |
| 591 | + std::vector<gko::detail::transform_iterator< |
| 592 | + typename std::vector<TypeParam>::iterator, decltype(transform)>> |
| 593 | + its{begin, |
| 594 | + plus_2, |
| 595 | + plus_2_rev, |
| 596 | + plus_minus_2, |
| 597 | + increment_pre_2, |
| 598 | + increment_post_2, |
| 599 | + increment_pre_test, |
| 600 | + increment_post_test, |
| 601 | + begin + 5, |
| 602 | + begin + 9}; |
| 603 | + std::sort(its.begin(), its.end()); |
| 604 | + std::vector<int> dists; |
| 605 | + std::vector<int> ref_dists{0, 1, 0, 1, 0, 0, 0, 3, 4}; |
| 606 | + for (int i = 0; i < its.size() - 1; i++) { |
| 607 | + SCOPED_TRACE(i); |
| 608 | + dists.push_back(its[i + 1] - its[i]); |
| 609 | + auto equal = dists.back() > 0; |
| 610 | + ASSERT_EQ(its[i + 1] > its[i], equal); |
| 611 | + ASSERT_EQ(its[i] < its[i + 1], equal); |
| 612 | + ASSERT_EQ(its[i] != its[i + 1], equal); |
| 613 | + ASSERT_EQ(its[i] == its[i + 1], !equal); |
| 614 | + ASSERT_EQ(its[i] >= its[i + 1], !equal); |
| 615 | + ASSERT_EQ(its[i + 1] <= its[i], !equal); |
| 616 | + ASSERT_TRUE(its[i + 1] >= its[i]); |
| 617 | + ASSERT_TRUE(its[i] <= its[i + 1]); |
| 618 | + } |
| 619 | + ASSERT_EQ(dists, ref_dists); |
| 620 | +} |
| 621 | + |
| 622 | + |
| 623 | +TYPED_TEST(TransformIterator, DecreasingIterator) |
| 624 | +{ |
| 625 | + std::vector<TypeParam> vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| 626 | + auto transform = [](TypeParam v) { return TypeParam{2} * v; }; |
| 627 | + |
| 628 | + auto test_iter = |
| 629 | + gko::detail::make_transform_iterator(vec.begin(), transform); |
| 630 | + |
| 631 | + auto iter = test_iter + 5; |
| 632 | + auto minus_2 = iter - 2; |
| 633 | + auto minus_plus_2 = minus_2 + 2; |
| 634 | + auto decrement_pre_2 = iter; |
| 635 | + --decrement_pre_2; |
| 636 | + --decrement_pre_2; |
| 637 | + auto decrement_post_2 = iter; |
| 638 | + decrement_post_2--; |
| 639 | + decrement_post_2--; |
| 640 | + auto decrement_pre_test = iter; |
| 641 | + auto decrement_post_test = iter; |
| 642 | + |
| 643 | + ASSERT_TRUE(iter == minus_plus_2); |
| 644 | + ASSERT_TRUE(minus_2 == decrement_pre_2); |
| 645 | + ASSERT_TRUE(decrement_pre_2 == decrement_post_2); |
| 646 | + ASSERT_TRUE(iter == decrement_post_test--); |
| 647 | + ASSERT_TRUE(iter - 1 == --decrement_pre_test); |
| 648 | + ASSERT_TRUE(*minus_2 == TypeParam{2} * vec[3]); |
| 649 | +} |
| 650 | + |
| 651 | + |
514 | 652 | } // namespace |
0 commit comments