36# include <type_traits>
105 typename HeadC::Iterator it;
107 using T = std::decay_t<typename HeadC::Item_Type>;
113 std::declval<std::tuple<T>>(),
151 std::tuple<T> curr(it.get_curr());
161 std::tuple<T> curr(it.get_curr_ne());
197 using T = std::decay_t<typename C::Item_Type>;
219 return std::tuple<T>(C::Iterator::get_curr());
228 return std::tuple<T>(C::Iterator::get_curr_ne());
234 l.
append(C::Iterator::get_curr());
248template <
class ...
Cs>
262template <
class ...
Cs>
267 for (
size_t i = 0; i < pos; ++i)
273template <
class ...
Cs>
281template <
class ...
Cs>
294template <
class ...
Cs>
299 for (; it.has_curr(); it.next_ne())
302 return it.completed();
332template <
class Op,
class ...
Cs>
336 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
337 if (
not std::forward<Op>(op)(it.get_curr()))
350template <
class Op,
class ...
Cs>
355 for (; it.has_curr(); it.next_ne())
356 if (
not std::forward<Op>(op)(it.get_curr()))
358 return it.completed();
390template <
class Op,
class ...
Cs>
394 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
395 std::forward<Op>(op)(it.get_curr());
405template <
class Op,
class ...
Cs>
410 for (; it.has_curr(); it.next_ne())
411 std::forward<Op>(op)(it.get_curr());
414 <<
"zip_for_each_eq() containers sizes mismatch";
427template <
class Op,
class ...
Cs>
432 for (; it.has_curr(); it.next_ne())
433 if (
not std::forward<Op>(op)(it.get_curr()))
436 return it.completed();
449template <
class Op,
class ...
Cs>
453 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
454 if (
not std::forward<Op>(op)(it.get_curr()))
464template <
class Op,
class ...
Cs>
468 return zip_all(std::forward<Op>(op),
cs...);
475template <
class Op,
class ...
Cs>
491template <
class Op,
class ...
Cs>
495 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
496 if (std::forward<Op>(op)(it.get_curr()))
506template <
class Op,
class ...
Cs>
522template <
class Op,
class ...
Cs>
536template <
class Op,
class ...
Cs>
541 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
542 if (std::forward<Op>(op)(it.get_curr()))
553template <
class ...
Cs>
558 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
571template <
class Op,
class ...
Cs>
577 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
578 if (
auto t = it.get_curr(); std::forward<Op>(op)(t))
579 return std::make_pair(t,
true);
581 return std::make_pair(
ZipType{},
false);
592template <
class Op,
class ...
Cs>
601 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
602 if (
auto t = it.get_curr(); std::forward<Op>(op)(t))
608 return std::make_pair(result,
found);
619template <
class ...
Cs>
626 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne(), ++i)
628 return std::make_pair(it.get_curr(),
true);
630 return std::make_pair(
ZipType{},
false);
640template <
class ...
Cs>
677template <
typename T,
class Op,
class ...
Cs>
682 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
696template <
typename T,
class Prop,
class Op,
class ...
Cs>
701 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
702 if (
auto t = it.get_curr();
prop(t))
736template <
typename T,
class Op,
class ...
Cs>
741 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
742 acu = op(
acu, it.get_curr());
756template <
typename T,
class Op,
class ...
Cs>
762 for (; it.has_curr(); it.next_ne())
763 acu = op(
acu, it.get_curr());
766 <<
"zip_foldl_eq() containers sizes mismatch";
780template <
typename T,
class Op,
class ...
Cs>
786 for (; it.has_curr(); it.next_ne())
790 <<
"zip_maps_eq() containers sizes mismatch";
805template <
typename T,
class Prop,
class Op,
class ...
Cs>
811 for (; it.has_curr(); it.next_ne())
812 if (
auto t = it.get_curr();
prop(t))
816 <<
"zip_maps_if_eq() containers sizes mismatch";
831template <
class Op,
class ...
Cs>
836 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
839 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
840 ret.
append(std::forward<Op>(op)(it.get_curr()));
852template <
class Op,
class ...
Cs>
857 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
861 for (; it.has_curr(); it.next_ne())
862 ret.
append(std::forward<Op>(op)(it.get_curr()));
865 <<
"zip_map_eq() containers sizes mismatch";
893template <
class Op,
class ...
Cs>
900 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
901 if (
auto t = it.get_curr(); op(t))
934template <
class Op,
class ...
Cs>
942 for (; it.has_curr(); it.next_ne())
943 if (
auto t = it.get_curr(); op(t))
947 <<
"zip_filter_eq() containers sizes mismatch";
962 template <
class Cmp,
class Tuple,
size_t...
Is>
966 return (...
and cmp(std::get<Is>(t), std::get<Is + 1>(t)));
990template <
class Cmp,
class ...
Cs>
994 constexpr size_t N =
sizeof...(Cs);
995 static_assert(
N >= 2,
"zip_cmp requires at least 2 containers");
997 for (
auto it =
get_zip_it(
cs...); it.has_curr(); it.next_ne())
1012template <
class Op,
class ...
Cs>
1017 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne(), ++i)
1018 if (
auto t = it.get_curr(); op(t))
1059template <
class Op,
class ...
Cs>
1066 size_t n1 = 0, n2 = 0;
1067 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
1068 if (
auto t = it.get_curr(); op(t))
1079 return std::make_tuple(
ret1, n1,
ret2, n2);
1110template <
class ...
Cs>
1115 using T =
decltype(it.get_curr());
1117 for (; it.has_curr(); it.next_ne())
1130template <
class ...
Cs>
1135 using T =
decltype(it.get_curr());
1137 for (; it.has_curr(); it.next_ne())
1141 <<
"Container sizes mismatch";
1177 typename HeadC::Iterator it;
1179 using T = std::decay_t<typename HeadC::Item_Type>;
1208 std::tuple<T> curr(it.get_curr());
1221 std::tuple<T> curr(it.get_curr_ne());
1246 C::Iterator::next();
1256 C::Iterator::next_ne();
1260 using T = std::decay_t<typename C::Item_Type>;
1271 return std::tuple<T, size_t>(C::Iterator::get_curr(), i);
1280 return std::tuple<T, size_t>(C::Iterator::get_curr_ne(), i);
1293template <
class ...
Cs>
1308template <
class C,
class ...
Cs>
1314 for (
size_t i = 0; i < pos; ++i)
1321template <
class ...
Cs>
1329template <
class ...
Cs>
1344template <
class ...
Cs>
1349 using T =
decltype(it.get_curr());
1351 for (; it.has_curr(); it.next_ne())
1364template <
class ...
Cs>
1369 using T =
decltype(it.get_curr());
1371 for (; it.has_curr(); it.next_ne())
1375 <<
"Container sizes mismatch";
1380template <
typename...
Ts,
size_t...
is>
1383 std::index_sequence<is...>)
1385 std::tuple<DynList<Ts>...>
ret;
1386 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1387 std::initializer_list<int>{(std::get<is>(
ret).append(std::get<is>(it.get_curr())), 0)...};
1398template <
class...
Ts>
1422template <
class C,
typename ...
Lists>
1426 using T =
typename C::Item_Type;
1441template <
class C,
typename ...
Lists>
1445 using T =
typename C::Item_Type;
1448 for (; it.has_curr(); it.next_ne())
1452 <<
"zip_list_eq: container sizes mismatch";
1460namespace std_zip_detail
1466 template <
typename...
Its>
1469 return (...
and (
its.first !=
its.second));
1475 template <
typename...
Its>
1485 template <
typename...
Its>
1488 return std::make_tuple(*
its.first...);
1496template <
typename C1,
typename C2>
1500 using T =
typename C1::value_type;
1501 using U =
typename C2::value_type;
1502 std::vector<std::pair<T, U>> result;
1506 result.emplace_back(*it1, *it2);
1524template <
typename...
Cs>
1528 static_assert(
sizeof...(Cs) >= 2,
"tzip_std requires at least 2 containers");
1530 using TupleType = std::tuple<
typename Cs::value_type...>;
1531 std::vector<TupleType>
ret;
1558template <
typename...
Cs>
1576template <
class Op,
class ...
Cs>
1581 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
1583 std::vector<ResultType>
ret;
1584 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
1585 ret.push_back(std::forward<Op>(op)(it.get_curr()));
1598template <
class Op,
class ...
Cs>
1603 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
1605 std::vector<ResultType>
ret;
1607 for (; it.has_curr(); it.next_ne())
1608 ret.push_back(std::forward<Op>(op)(it.get_curr()));
1611 <<
"zip_transform_eq() containers sizes mismatch";
1623template <
class Op,
class ...
Cs>
1628 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne(), ++idx)
1629 std::forward<Op>(op)(idx, it.get_curr());
1639template <
class Op,
class ...
Cs>
1645 for (; it.has_curr(); it.next_ne(), ++idx)
1646 std::forward<Op>(op)(idx, it.get_curr());
1649 <<
"zip_for_each_indexed_eq() containers sizes mismatch";
1659template <
class ...
Cs>
1678template <
class ...
Cs>
1687 for (
size_t i = 0; i < n
and it.has_curr(); ++i)
1691 for (; it.has_curr(); it.next_ne())
1703template <
class Pred,
class ...
Cs>
1709 for (
auto it =
zip_it(
cs...); it.has_curr(); it.next_ne())
1711 auto t = it.get_curr();
1712 if (
not std::forward<Pred>(
pred)(t))
1726template <
class Pred,
class ...
Cs>
1735 for (; it.has_curr()
and std::forward<Pred>(
pred)(it.get_curr()); it.next_ne())
1739 for (; it.has_curr(); it.next_ne())
1751namespace zip_index_detail
1757 template <
class Op,
class Tuple,
size_t...
Is>
1760 (std::forward<Op>(op)(std::get<Is>(std::forward<Tuple>(t))), ...);
1768 template <
class Op,
class Tuple,
size_t...
Is>
1771 return std::make_tuple(std::forward<Op>(op)(std::get<Is>(std::forward<Tuple>(t)))...);
1782 return (...
and std::forward<Pred>(
pred)(std::get<Is>(t)));
1793 return (...
or std::forward<Pred>(
pred)(std::get<Is>(t)));
1826template <
class Op,
class Tuple>
1829 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1831 std::forward<Op>(op), std::forward<Tuple>(t), std::make_index_sequence<N>{});
1864template <
class Op,
class Tuple>
1868 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1870 std::forward<Op>(op), std::forward<Tuple>(t), std::make_index_sequence<N>{});
1894template <
class Pred,
class Tuple>
1898 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1900 std::forward<Pred>(
pred), t, std::make_index_sequence<N>{});
1923template <
class Pred,
class Tuple>
1927 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1929 std::forward<Pred>(
pred), t, std::make_index_sequence<N>{});
1952template <
class Pred,
class Tuple>
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
Functional programming utilities for Aleph-w containers.
Dynamic singly linked list with functional programming support.
T & append(const T &item)
Append a new item by copy.
bool completed() const noexcept
Return true if the underlying iterator has reached the end.
std::tuple< T, size_t > get_curr_ne() const noexcept
Return the current tuple (value, index) (no-throw variant).
std::tuple< T, size_t > get_curr() const
Return the current tuple (value, index) (bounds-checked).
EnumZipIterator(const C &c)
Construct an enumerating iterator over a single container.
void next()
Advance the iterator and increment the associated index (bounds-checked).
void next_ne() noexcept
Advance the iterator and increment the associated index (no-throw variant).
std::decay_t< typename C::Item_Type > T
std::tuple< T > get_curr_ne() const noexcept
Return the current tuple (no-throw variant).
std::tuple< T > Tuple_Type
The tuple type returned by get_curr() and get_curr_ne()
std::decay_t< typename C::Item_Type > T
bool completed() const noexcept
Return true if the underlying iterator has reached the end.
DynList< T > get_curr_list() const
std::tuple< T > get_curr() const
Return the current tuple (bounds-checked).
ZipIterator(const C &c)
Construct a zip iterator over a single container.
T Item_Type
Type of elements from the container.
Iterator that traverses multiple containers with enumeration index.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Iterator that traverses multiple Aleph containers in lockstep.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Singly linked list implementations with head-tail access.
Freq_Node * pred
Predecessor node in level-order traversal.
bool all_valid(const Its &... its)
Check if all iterators are valid (not at end).
auto deref_all(const Its &... its)
Dereference all iterators and make a tuple.
void advance_all(Its &... its)
Advance all iterators.
bool compare_adjacent(Cmp &cmp, const Tuple &t, std::index_sequence< Is... >)
Compare all adjacent pairs in a tuple using the given comparator.
bool any_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence< Is... >)
Check if any element satisfies a predicate.
auto transform_tuple_impl(Op &&op, Tuple &&t, std::index_sequence< Is... >)
Transform each element in a tuple.
void for_each_in_tuple_impl(Op &&op, Tuple &&t, std::index_sequence< Is... >)
Apply a function to each element in a tuple.
bool all_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence< Is... >)
Check if all elements satisfy a predicate.
Main namespace for Aleph-w library functions.
void zip_for_each(Op &&op, const Cs &... cs)
Apply op to every zipped tuple.
DynList< T > zip_maps_eq(Op op, const Cs &... cs)
Map op over zipped tuples; throw if containers differ in length.
bool zip_none(Op &&op, const Cs &... cs)
Return true if op returns false for all tuples.
bool zip_all(Op &&op, const Cs &... cs)
Return true if op returns true for all tuples and containers have equal length.
bool zip_cmp(Cmp cmp, const Cs &... cs)
Return true if cmp(t) is true for each built tuple t.
auto zip_find_first(Op &&op, const Cs &... cs)
Return the first tuple that satisfies predicate op.
T Item_Type
Type of elements from the first container.
bool completed() const noexcept
Return true if all underlying iterators are finished.
size_t zip_find_index(Op op, const Cs &... cs)
Find the first index where op returns true.
EnumZipIterator< Cs... > enum_zip_it(const Cs &... cs)
Alias for get_enum_zip_it.
size_t zip_count(Op &&op, const Cs &... cs)
Count tuples that satisfy predicate op.
auto zip_transform_eq(Op &&op, const Cs &... cs)
Transform zipped tuples; throw if containers differ in length.
auto zip_drop_while(Pred &&pred, const Cs &... cs)
Skip tuples while predicate pred returns true, then return the rest.
auto zip_first(const Cs &... cs)
Return the first tuple from zipped containers.
T zip_foldl(const T &init, Op op, const Cs &... cs)
Left fold (reduce) over zipped tuples.
auto std_zip(const C1 &c1, const C2 &c2)
Build a vector of pairs from two STL containers.
auto tzip_std(const Cs &... cs)
Build a vector of tuples from 2 or more STL containers (variadic).
bool all_of_tuple(Pred &&pred, const Tuple &t)
Return true if all tuple elements satisfy pred.
auto transform_tuple(Op &&op, Tuple &&t)
Transform each element of a tuple, returning a new tuple.
static auto t_unzip_impl(const DynList< std::tuple< Ts... > > &l, std::index_sequence< is... >)
auto zip_filter(Op op, const Cs &... cs)
Filter zipped tuples by predicate op.
EnumZipIterator< Cs... > get_enum_zip_it(const Cs &... cs)
Create an EnumZipIterator over the given containers.
bool zip_any(Op &&op, const Cs &... cs)
Alias for zip_exists.
auto zip_take_while(Pred &&pred, const Cs &... cs)
Take tuples while predicate pred returns true.
void for_each_in_tuple(Op &&op, Tuple &&t)
Apply op to each element of a tuple.
ZipIterator< Cs... > zip_it_pos(size_t pos, const Cs &... cs)
Alias for get_zip_it_pos.
void zip_for_each_indexed(Op &&op, const Cs &... cs)
Apply op to each zipped tuple along with its index.
void next_ne() noexcept
Advance all underlying iterators (no-throw variant).
bool zip_traverse(Op &&op, const Cs &... cs)
Traverse zipped containers while op returns true.
bool zip_forall(Op &&op, const Cs &... cs)
Alias for zip_all.
bool equal_length(const Cs &... cs)
Return true if all containers have the same length.
std::decay_t< typename HeadC::Item_Type > T
bool zip_traverse_eq(Op &&op, const Cs &... cs)
Traverse zipped containers while op returns true; verify equal lengths.
auto zip_lists(const C &c, const Lists &... lists)
Take several container of same type and some length and builds a list of lists.
decltype(std::tuple_cat(std::declval< std::tuple< T > >(), std::declval< typename ZipIterator< TailC... >::Tuple_Type >())) Tuple_Type
The tuple type returned by get_curr() and get_curr_ne()
void zip_for_each_eq(Op &&op, const Cs &... cs)
Apply op to every zipped tuple; throw if containers differ in length.
bool any_of_tuple(Pred &&pred, const Tuple &t)
Return true if any tuple element satisfies pred.
bool zip_forall_short(Op &&op, const Cs &... cs)
Alias for zip_all_short.
auto zip_transform(Op &&op, const Cs &... cs)
Transform zipped tuples using op and return results in a vector.
auto zip_map_eq(Op &&op, const Cs &... cs)
Map op over zipped tuples with auto-deduced return type; throw if lengths differ.
auto zip_take(size_t n, const Cs &... cs)
Take at most n tuples from the zipped containers.
auto get_curr() const
Return the current tuple (bounds-checked).
bool none_of_tuple(Pred &&pred, const Tuple &t)
Return true if no tuple element satisfies pred.
auto t_zip(const Cs &... cs)
Materialize zipped tuples into a DynList.
bool has_curr() const noexcept
Return true if all underlying iterators are positioned on a valid item.
auto zip_lists_eq(const C &c, const Lists &... lists)
Like zip_lists but throws if containers differ in length.
auto t_enum_zip_eq(const Cs &... cs)
Materialize enumerated zipped tuples; throw if containers differ in length.
auto t_unzip(const DynList< std::tuple< Ts... > > &tuples)
Unzip a list of tuples into a tuple of lists.
DynList< T > zip_maps_if_eq(Prop prop, Op op, const Cs &... cs)
Map op over zipped tuples that satisfy prop; throw if lengths differ.
T zip_foldl_eq(const T &init, Op op, const Cs &... cs)
Left fold over zipped tuples; throw if containers differ in length.
auto zip_partition(Op op, const Cs &... cs)
Partition zipped tuples by predicate op.
bool zip_all_short(Op &&op, const Cs &... cs)
Return true if op returns true for all tuples (without length check).
size_t zip_length(const Cs &... cs)
Count all tuples (minimum length of containers).
DynList< T > zip_maps_if(Prop prop, Op op, const Cs &... cs)
Map op over zipped tuples that satisfy prop.
auto t_enum_zip(const Cs &... cs)
Materialize enumerated zipped tuples into a DynList.
auto zip_nth(size_t n, const Cs &... cs)
Return the n-th tuple from zipped containers.
auto t_zip_eq(const Cs &... cs)
Materialize zipped tuples; throw if containers differ in length.
DynList< T > get_curr_list() const
Returns current elements as a DynList (requires homogeneous Item_Type)
auto get_curr_ne() const noexcept
Return the current tuple (no-throw variant).
EnumZipIterator< Cs... > enum_zip_it_pos(size_t pos, const Cs &... cs)
Alias for get_enum_zip_it_pos.
void next()
Advance all underlying iterators (bounds-checked).
auto std_zip_n(const Cs &... cs)
Build a vector of tuples from 2 or more STL containers (variadic).
EnumZipIterator< C, Cs... > get_enum_zip_it_pos(size_t pos, const C &c, const Cs &... cs)
Create an EnumZipIterator positioned at index pos.
auto zip_drop(size_t n, const Cs &... cs)
Skip n tuples and return the rest.
ZipIterator< Cs... > get_zip_it_pos(size_t pos, const Cs &... cs)
Create a ZipIterator positioned at index pos.
auto zip_filter_eq(Op op, const Cs &... cs)
Filter zipped tuples by predicate op; throw if containers differ in length.
auto zip_map(Op &&op, const Cs &... cs)
Map op over zipped tuples with auto-deduced return type.
bool zip_exists(Op &&op, const Cs &... cs)
Return true if op returns true for at least one tuple.
ZipIterator< Cs... > get_zip_it(const Cs &... cs)
Create a ZipIterator over the given containers.
DynList< T > zip_maps(Op op, const Cs &... cs)
Map op over zipped tuples, returning a list of results.
ZipIterator< Cs... > zip_it(const Cs &... cs)
Alias for get_zip_it.
auto zip_find_last(Op &&op, const Cs &... cs)
Return the last tuple that satisfies predicate op.
void zip_for_each_indexed_eq(Op &&op, const Cs &... cs)
Apply op to each zipped tuple with index; throw if lengths differ.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Dynamic ordered set implemented with a Skip List.