alpaqa 1.0.0a12
Nonconvex constrained optimization
Loading...
Searching...
No Matches
set-intersection.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <functional>
5#include <iterator>
6#include <ranges>
7
8namespace alpaqa::util {
9
10template <std::ranges::input_range R1, std::ranges::input_range R2,
11 class Comp = std::ranges::less, class Proj1 = std::identity,
12 class Proj2 = std::identity>
13 requires(std::ranges::view<R1> && std::ranges::view<R2>)
15 : std::ranges::view_interface<
17
23
24 // P2325R3: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2325r3.html
26 set_intersection_iterable(R1 &&range1, R2 &&range2, Comp &&comp,
27 Proj1 &&proj1, Proj2 &&proj2)
28 : range1{std::forward<R1>(range1)}, range2{std::forward<R2>(range2)},
29 comp{std::forward<Comp>(comp)}, proj1{std::forward<Proj1>(proj1)},
30 proj2{std::forward<Proj2>(proj2)} {}
31
32 struct sentinel_t {};
33 template <std::input_iterator I1, std::sentinel_for<I1> S1,
34 std::input_iterator I2, std::sentinel_for<I2> S2>
35 struct iter_t {
36 // P2325R3: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2325r3.html
37 iter_t() = default;
38 iter_t(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp, Proj1 proj1,
39 Proj2 proj2)
40 : first1{std::move(first1)}, last1{std::move(last1)},
41 first2{std::move(first2)}, last2{std::move(last2)},
42 comp{std::move(comp)}, proj1{std::move(proj1)},
43 proj2{std::move(proj2)} {}
48 Comp comp;
49 Proj1 proj1;
50 Proj2 proj2;
51
52 using difference_type = std::ptrdiff_t; // TODO
53 using value_type = std::tuple<decltype(*first1), decltype(*first2)>;
54
55 bool operator!=(sentinel_t) const {
56 return first1 != last1 && first2 != last2;
57 }
58 bool operator==(sentinel_t s) const { return !(*this != s); }
59 // TODO: For Clang bug
60 friend bool operator!=(sentinel_t s, const iter_t &i) { return i != s; }
61 friend bool operator==(sentinel_t s, const iter_t &i) { return i == s; }
62
64 ++first1, ++first2;
65 advance();
66 return *this;
67 }
69 auto tmp = *this;
70 ++*this;
71 return tmp;
72 }
73 value_type operator*() const { return {*first1, *first2}; }
74 void advance() {
75 while (*this != sentinel_t{}) {
76 if (std::invoke(comp, std::invoke(proj1, *first1),
77 std::invoke(proj2, *first2)))
78 ++first1;
79 else if (std::invoke(comp, std::invoke(proj2, *first2),
80 std::invoke(proj1, *first1)))
81 ++first2;
82 else
83 break;
84 }
85 }
86 };
87
88 private:
89 template <class I1, class S1, class I2, class S2>
90 iter_t<I1, S1, I2, S2> iter(I1 first1, S1 last1, I2 first2,
91 S2 last2) const {
92 return {first1, last1, first2, last2, comp, proj1, proj2};
93 }
94
95 public:
97 auto it = iter(std::ranges::begin(range1), std::ranges::end(range1),
98 std::ranges::begin(range2), std::ranges::end(range2));
99 it.advance();
100 return it;
101 }
102 auto end() const
103 // -> std::sentinel_for< decltype(std::declval<set_intersection_iterable>().begin())> auto
104 {
105 return sentinel_t{};
106 }
107};
108
109template <std::ranges::viewable_range R1, std::ranges::viewable_range R2,
110 class Comp = std::ranges::less, class Proj1 = std::identity,
111 class Proj2 = std::identity>
113 std::ranges::views::all_t<R2>, Comp, Proj1, Proj2>
114iter_set_intersection(R1 &&r1, R2 &&r2, Comp comp = {}, Proj1 proj1 = {},
115 Proj2 proj2 = {}) {
116 static_assert(
118 std::ranges::views::all_t<R2>, Comp,
119 Proj1, Proj2>
120 s) {
121 { s.end() } -> std::sentinel_for<decltype(s.begin())>;
122 });
123 return {
124 std::forward<R1>(r1), std::forward<R2>(r2), std::move(comp),
125 std::move(proj1), std::move(proj2),
126 };
127}
128
129} // namespace alpaqa::util
set_intersection_iterable< std::ranges::views::all_t< R1 >, std::ranges::views::all_t< R2 >, Comp, Proj1, Proj2 > iter_set_intersection(R1 &&r1, R2 &&r2, Comp comp={}, Proj1 proj1={}, Proj2 proj2={})
constexpr const auto inf
Definition config.hpp:85
std::tuple< decltype(*first1), decltype(*first2)> value_type
iter_t(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp, Proj1 proj1, Proj2 proj2)
friend bool operator==(sentinel_t s, const iter_t &i)
friend bool operator!=(sentinel_t s, const iter_t &i)
set_intersection_iterable(R1 &&range1, R2 &&range2, Comp &&comp, Proj1 &&proj1, Proj2 &&proj2)
auto begin() const -> std::input_or_output_iterator auto
iter_t< I1, S1, I2, S2 > iter(I1 first1, S1 last1, I2 first2, S2 last2) const