35# include <type_traits>
93 namespace stl_zip_detail
99 return (...
and (std::get<0>(
its) != std::get<1>(
its)));
106 (++std::get<0>(
its), ...);
113 return std::tuple<decltype(*std::get<0>(
its))...>(*std::get<0>(
its)...);
117 template <
typename IterPair>
118 using iter_value_t = std::decay_t<decltype(*std::get<0>(std::declval<IterPair>()))>;
150 std::pair<typename std::decay_t<Containers>::const_iterator,
151 typename std::decay_t<Containers>::const_iterator>...>;
155 typename std::decay_t<Containers>::value_type...>;
158 const typename std::decay_t<Containers>::value_type &...>;
166 template <
size_t...
Is>
173 template <
size_t...
Is>
180 template <
size_t...
Is>
187 template <
size_t...
Is>
190 return (...
and (std::get<0>(std::get<Is>(
iters_)) ==
191 std::get<1>(std::get<Is>(
iters_))));
222 return has_curr_impl(std::make_index_sequence<num_containers>{});
233 return completed_impl(std::make_index_sequence<num_containers>{});
243 return deref_impl(std::make_index_sequence<num_containers>{});
252 advance_impl(std::make_index_sequence<num_containers>{});
352 return std::apply([](
const auto &...
cs)
364 return std::apply([](
const auto &...
cs)
423 static_assert(
sizeof...(Containers) >= 2,
"stl_zip requires at least 2 containers");
481 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
482 if (
not std::forward<Pred>(
pred)(it.get_curr()))
503 for (; it.has_curr(); it.next())
504 if (
not std::forward<Pred>(
pred)(it.get_curr()))
506 return it.completed();
538 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
539 if (std::forward<Pred>(
pred)(it.get_curr()))
593 template <
typename Op,
typename...
Containers>
596 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
597 std::forward<Op>(op)(it.get_curr());
609 template <
typename Op,
typename...
Containers>
613 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
614 std::forward<Op>(op)(idx, it.get_curr());
647 template <
typename T,
typename Op,
typename...
Containers>
651 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
652 acc = std::forward<Op>(op)(std::move(
acc), it.get_curr());
657 template <
typename T,
typename Op,
typename...
Containers>
691 template <
typename Op,
typename...
Containers>
695 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<TupleType>()))>;
697 std::vector<ResultType> result;
698 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
699 result.push_back(std::forward<Op>(op)(it.get_curr()));
720 std::vector<TupleType> result;
721 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
722 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
742 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
743 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
744 return std::optional<TupleType>(t);
745 return std::optional<TupleType>{};
762 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
763 if (std::forward<Pred>(
pred)(it.get_curr()))
781 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
799 while (it.has_curr())
801 return it.completed();
820 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++i)
822 return std::optional<TupleType>(it.get_curr());
823 return std::optional<TupleType>{};
841 std::vector<TupleType> result;
845 result.push_back(it.get_curr());
864 std::vector<TupleType> result;
868 for (
size_t i = 0; i < n
and it.has_curr(); ++i)
872 for (; it.has_curr(); it.next())
873 result.push_back(it.get_curr());
896 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
897 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
923 std::vector<TupleType> result;
924 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
925 result.push_back(it.get_curr());
949 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
950 if (
not std::forward<Pred>(
pred)(it.get_curr()))
969 for (; it.has_curr(); it.next())
970 if (
not std::forward<Pred>(
pred)(it.get_curr()))
972 return it.completed();
979 namespace stl_zip_detail
982 template <
typename Cmp,
typename Tuple,
size_t...
Is>
985 return (...
and cmp(std::get<Is>(t), std::get<Is + 1>(t)));
1017 static_assert(
sizeof...(Containers) >= 2,
"stl_zip_cmp requires at least 2 containers");
1019 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1021 constexpr size_t N =
sizeof...(Containers);
1022 if (
auto t = it.get_curr();
not
1045 template <
typename Container>
1051 using value_type = std::tuple<size_t, typename std::decay_t<Container>::value_type>;
1054 typename std::decay_t<Container>::const_iterator
curr_;
1055 typename std::decay_t<Container>::const_iterator
end_;
1112 template <
typename Container>
1153 template <
typename Container>
1193 std::vector<TupleType> result;
1194 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1197 if (
not std::forward<Pred>(
pred)(t))
1199 result.push_back(t);
1222 std::vector<TupleType> result;
1226 for (; it.has_curr()
and std::forward<Pred>(
pred)(it.get_curr()); it.next())
1230 for (; it.has_curr(); it.next())
1231 result.push_back(it.get_curr());
1270 std::optional<TupleType> result;
1271 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1291 std::optional<TupleType> result;
1292 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1295 if (std::forward<Pred>(
pred)(t))
1315 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1316 if (std::forward<Pred>(
pred)(it.get_curr()))
1343 template <
typename T,
typename U>
1348 firsts.reserve(pairs.size());
1349 seconds.reserve(pairs.size());
1351 for (
const auto & [f, s]: pairs)
1356 return std::make_pair(std::move(
firsts), std::move(
seconds));
1379 template <
typename...
Ts>
1382 std::tuple<std::vector<Ts>...> result;
1391 for (
const auto & t:
tuples)
1393 std::apply([&t](
auto &...
vecs)
1395 std::apply([&
vecs...](
const auto &...
elems)
1397 (vecs.push_back(elems), ...);
1432 template <
typename Container>
1435 using T =
typename std::decay_t<Container>::value_type;
1436 std::vector<std::pair<T, T>> result;
1438 auto it = c.begin();
1445 for (; it != c.end(); ++it)
1447 result.emplace_back(prev, *it);
1470 template <
typename Op,
typename Container>
1473 using T =
typename std::decay_t<Container>::value_type;
1474 using R = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>(), std::declval<T>()))>;
1476 std::vector<R> result;
1478 auto it = c.begin();
1485 for (; it != c.end(); ++it)
1487 result.push_back(std::forward<Op>(op)(prev, *it));
1514 template <
typename Pred,
typename Container>
1517 auto it = c.begin();
1524 for (; it != c.end(); ++it)
1526 if (
not std::forward<Pred>(
pred)(prev, *it))
1543 template <
typename Pred,
typename Container>
1546 auto it = c.begin();
1553 for (; it != c.end(); ++it)
1555 if (std::forward<Pred>(
pred)(prev, *it))
1585 template <
typename Op,
typename...
Containers>
1589 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<TupleType>()))>;
1591 std::vector<ResultType> result;
1593 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1594 result.push_back(std::forward<Op>(op)(idx, it.get_curr()));
1615 std::vector<TupleType> result;
1617 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1618 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(idx, t))
1619 result.push_back(t);
1644 template <
typename T,
typename Op,
typename...
Containers>
1647 std::vector<T> result;
1648 result.push_back(
init);
1651 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1653 acc = std::forward<Op>(op)(std::move(
acc), it.get_curr());
1654 result.push_back(
acc);
1671 template <
typename Op,
typename...
Containers>
1675 using OptType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<TupleType>()))>;
1678 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1679 if (
auto result = std::forward<Op>(op)(idx, it.get_curr()))
1701 while (it.has_curr())
1703 return it.completed();
1716 template <
typename Eq,
typename...
Containers>
1720 for (; it.has_curr(); it.next())
1721 if (
not std::forward<Eq>(
eq)(it.get_curr()))
1723 return it.completed();
1742 const std::tuple<const Containers1 &...> &
cs1,
1743 const std::tuple<const Containers2 &...> &
cs2)
1745 auto it1 = std::apply([](
const auto &...
cs) {
return stl_zip_it(
cs...); },
cs1);
1746 auto it2 = std::apply([](
const auto &...
cs) {
return stl_zip_it(
cs...); },
cs2);
1748 while (it1.has_curr()
and it2.has_curr())
1750 auto t1 = it1.get_curr();
1751 auto t2 = it2.get_curr();
1752 if (
t1 <
t2)
return -1;
1753 if (
t2 <
t1)
return 1;
1758 if (it1.has_curr())
return 1;
1759 if (it2.has_curr())
return -1;
1776 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1777 if (it.get_curr() == target)
1794 template <
typename Key,
typename...
Containers>
1799 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1800 if (
auto t = it.get_curr(); std::get<0>(t) == key)
1801 return std::optional<TupleType>(t);
1802 return std::optional<TupleType>{};
1820 if (
not it.has_curr())
1821 return std::optional<TupleType>{};
1826 for (; it.has_curr(); it.next())
1828 auto t = it.get_curr();
1832 return std::optional<TupleType>(min_val);
1850 if (
not it.has_curr())
1851 return std::optional<TupleType>{};
1856 for (; it.has_curr(); it.next())
1858 auto t = it.get_curr();
1862 return std::optional<TupleType>(max_val);
1878 using ResultType = std::optional<std::pair<TupleType, TupleType>>;
1881 if (
not it.has_curr())
1888 for (; it.has_curr(); it.next())
1890 auto t = it.get_curr();
1891 if (t < min_val) min_val = t;
1892 if (t > max_val) max_val = t;
1894 return ResultType(std::make_pair(min_val, max_val));
1914 if (
not it.has_curr())
1915 return std::optional<TupleType>{};
1920 for (; it.has_curr(); it.next())
1922 auto t = it.get_curr();
1929 return std::optional<TupleType>(
sum);
Iterator that pairs each element with its index.
constexpr bool has_curr() const noexcept
constexpr bool operator==(const StlEnumerateIterator &other) const noexcept
constexpr auto get_curr() const
constexpr void next_ne() noexcept
Advance without checking; same as next(), which does not check.
std::decay_t< Container >::const_iterator curr_
constexpr StlEnumerateIterator & operator++() noexcept
constexpr bool operator!=(const StlEnumerateIterator &other) const noexcept
std::input_iterator_tag iterator_category
constexpr auto operator*() const
std::tuple< size_t, typename std::decay_t< Container >::value_type > value_type
std::ptrdiff_t difference_type
std::decay_t< Container >::const_iterator end_
constexpr StlEnumerateIterator(const Container &c, end_tag)
constexpr StlEnumerateIterator(const Container &c)
constexpr void next() noexcept
Lazy view that pairs each element with its index.
const std::decay_t< Container > & container_
constexpr iterator begin() const
StlEnumerateIterator< std::decay_t< Container > > iterator
constexpr StlEnumerateView(const Container &c)
constexpr iterator end() const
Lazy iterator that traverses multiple STL containers in lockstep.
std::ptrdiff_t difference_type
static constexpr size_t num_containers
Number of containers being zipped.
std::input_iterator_tag iterator_category
constexpr void next() noexcept
Advance all iterators.
constexpr void next_ne() noexcept
Advance without checking; same as next(), which does not check.
constexpr bool has_curr() const noexcept
Check if iterator has current element.
std::tuple< const typename std::decay_t< Containers >::value_type &... > reference
constexpr bool completed() const noexcept
Check if all iterators have completed.
std::tuple< typename std::decay_t< Containers >::value_type... > value_type
constexpr StlZipIterator(const Containers &... cs, end_tag)
constexpr StlZipIterator operator++(int) noexcept
Post-increment operator.
constexpr bool operator!=(const StlZipIterator &other) const noexcept
Inequality comparison.
constexpr StlZipIterator(const Containers &... cs)
Construct iterator from containers.
constexpr void advance_impl(std::index_sequence< Is... >) noexcept
constexpr bool completed_impl(std::index_sequence< Is... >) const noexcept
constexpr auto get_curr() const
Get current tuple of elements.
std::tuple< std::pair< typename std::decay_t< Containers >::const_iterator, typename std::decay_t< Containers >::const_iterator >... > IteratorTuple
constexpr auto operator*() const
Dereference operator for range-based for.
constexpr bool has_curr_impl(std::index_sequence< Is... >) const noexcept
constexpr auto deref_impl(std::index_sequence< Is... >) const
constexpr StlZipIterator & operator++() noexcept
Pre-increment operator.
constexpr bool operator==(const StlZipIterator &other) const noexcept
Equality comparison.
Lazy view over multiple zipped STL containers.
std::tuple< const std::decay_t< Containers > &... > containers_
StlZipIterator< std::decay_t< Containers >... > iterator
size_t size() const
Get number of tuples (minimum size of all containers).
constexpr iterator begin() const
Get iterator to beginning.
typename iterator::value_type value_type
constexpr StlZipView(const Containers &... cs)
Construct view from containers.
constexpr bool empty() const
Check if view is empty.
constexpr iterator end() const
Get iterator to end.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr bool all_valid(const IterPairs &... its) noexcept
std::decay_t< decltype(*std::get< 0 >(std::declval< IterPair >()))> iter_value_t
constexpr void advance_all(IterPairs &... its) noexcept
bool compare_adjacent_impl(Cmp &cmp, const Tuple &t, std::index_sequence< Is... >)
constexpr auto deref_all(const IterPairs &... its)
Main namespace for Aleph-w library functions.
constexpr auto stl_zip_it(const Containers &... cs)
Get a zip iterator over STL containers.
auto stl_zip_filteri(Pred &&pred, const Containers &... cs)
Filter with index (filteri in ML).
auto stl_adjacent_map(Op &&op, const Container &c)
Apply function to adjacent pairs of elements.
bool stl_zip_exists(Pred &&pred, const Containers &... cs)
Check if predicate holds for any zipped tuple.
bool stl_zip_equal_by(Eq &&eq, const Containers &... cs)
Check equality with custom comparator.
bool stl_adjacent_exists(Pred &&pred, const Container &c)
Check if predicate holds for any adjacent pair.
auto stl_zip_find_last(Pred &&pred, const Containers &... cs)
Find last tuple satisfying predicate.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
bool stl_zip_traverse(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true.
bool stl_zip_all_eq(Pred &&pred, const Containers &... cs)
Check if predicate holds for all tuples AND containers have equal length.
auto stl_zip_min_max(const Containers &... cs)
Get both min and max in a single pass.
auto stl_zip_max(const Containers &... cs)
Get maximum tuple according to comparator.
bool stl_adjacent_all(Pred &&pred, const Container &c)
Check if predicate holds for all adjacent pairs.
auto stl_zip_take_while(Pred &&pred, const Containers &... cs)
Take tuples while predicate returns true.
size_t stl_zip_count(Pred &&pred, const Containers &... cs)
Count tuples satisfying predicate.
bool stl_zip_equal_length(const Containers &... cs)
Check if all containers have equal length.
auto stl_zip_drop_while(Pred &&pred, const Containers &... cs)
Skip tuples while predicate returns true, then return the rest.
bool stl_zip_cmp(Cmp &&cmp, const Containers &... cs)
Compare elements across containers using a comparator.
auto stl_zip_find_first(Pred &&pred, const Containers &... cs)
Find first tuple satisfying predicate.
bool stl_zip_mem(const Tuple &target, const Containers &... cs)
Check if a tuple exists in the zipped sequence (mem in ML).
and
Check uniqueness with explicit hash + equality functors.
auto stl_unzip_tuple(const std::vector< std::tuple< Ts... > > &tuples)
Unzip a vector of tuples into a tuple of vectors.
std::decay_t< typename HeadC::Item_Type > T
auto stl_zip_first(const Containers &... cs)
Get first tuple from zipped containers.
auto stl_zip_mapi(Op &&op, const Containers &... cs)
Map with index (mapi in ML).
int stl_zip_compare(const std::tuple< const Containers1 &... > &cs1, const std::tuple< const Containers2 &... > &cs2)
Compare two zipped sequences lexicographically.
size_t stl_zip_find_index(Pred &&pred, const Containers &... cs)
Find index of first tuple satisfying predicate.
bool stl_zip_none(Pred &&pred, const Containers &... cs)
Check if no tuple satisfies the predicate.
auto stl_zip_scan_left(T init, Op &&op, const Containers &... cs)
Scan left (scan_left in ML) - fold with intermediate results.
constexpr auto stl_enumerate(const Container &c)
Create an enumerate view over a container.
auto stl_zip_map(Op &&op, const Containers &... cs)
Map operation over zipped tuples, returning a vector.
bool stl_zip_equal(const Containers &... cs)
Check equality of zipped sequences.
auto stl_zip_sum(const Containers &... cs)
Sum all tuples element-wise (requires + operator on tuple elements).
auto stl_zip_find_mapi(Op &&op, const Containers &... cs)
Find and map with index (find_mapi in ML).
auto stl_zip_assoc(const Key &key, const Containers &... cs)
Find value associated with key in zipped pairs (assoc in ML).
auto stl_zip_filter(Pred &&pred, const Containers &... cs)
Filter zipped tuples by predicate.
auto stl_unzip(const std::vector< std::pair< T, U > > &pairs)
Unzip a vector of pairs into two vectors.
auto stl_zip_drop(const size_t n, const Containers &... cs)
Skip first n tuples, return the rest.
T stl_zip_foldl(T init, Op &&op, const Containers &... cs)
Left fold over zipped tuples.
auto stl_zip_min(const Containers &... cs)
Get minimum tuple according to comparator.
T stl_zip_reduce(T init, Op &&op, const Containers &... cs)
Alias for stl_zip_foldl (alternative name)
auto stl_zip_nth(const size_t n, const Containers &... cs)
Get n-th tuple from zipped containers.
auto stl_adjacent(const Container &c)
Zip adjacent (consecutive) elements of a container.
auto stl_zip_partition(Pred &&pred, const Containers &... cs)
Partition tuples by predicate.
constexpr auto stl_zip(const Containers &... cs)
Create a lazy zip view over STL containers.
auto stl_zip_take(const size_t n, const Containers &... cs)
Take first n tuples from zipped containers.
auto stl_zip_last(const Containers &... cs)
Get last tuple from zipped containers.
size_t stl_zip_length(const Containers &... cs)
Count total tuples (minimum length of containers).
bool stl_zip_traverse_eq(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true, verify equal lengths.
static std::atomic< bool > init
void stl_zip_for_each(Op &&op, const Containers &... cs)
Apply operation to each zipped tuple (for side effects).
auto stl_zip_to_vector(const Containers &... cs)
Materialize zipped tuples into a vector.
void stl_zip_for_each_indexed(Op &&op, const Containers &... cs)
Apply operation to each tuple with its index.
bool stl_zip_all(Pred &&pred, const Containers &... cs)
Check if predicate holds for all zipped tuples.
@ Tuple
Tuple type such as (Int, Bool).
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
bool stl_zip_any(Pred &&pred, const Containers &... cs)
Alias for stl_zip_exists (Python/JS style name)
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Construct end iterator (all at end).