32#ifndef AH_FUNCTIONAL_H
33#define AH_FUNCTIONAL_H
67# include <type_traits>
113 [[nodiscard]]
bool is_found() const noexcept
override {
return true; }
117 template <
typename tgtT,
typename srcT>
120 tgtT operator () (
const srcT & item)
const noexcept {
return static_cast<tgtT
>(item); }
124 template <
typename TR,
typename TD>
127 TR operator () (
const TR & ,
const TD & )
128 const noexcept {
return TR(); }
133 template <
typename Key,
class Cmp>
137 namespace functional_detail
139 template <
typename T,
class Eq,
typename =
void>
142 template <
typename T,
class Eq>
144 std::void_t<decltype(sizeof(DynSetLhash<T, Eq>))>>
145 :
public std::true_type {};
147 template <
typename T,
class Eq>
151 template <AlephSequentialIterableContainer Container,
class Equal>
155 for (
auto it1 = container.get_it(); it1.has_curr(); it1.next_ne())
159 for (; it2.has_curr(); it2.next_ne())
160 if (
eq(it1.get_curr(), it2.get_curr()))
166 template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
167 requires std::copy_constructible<typename Container::Item_Type>
168 and requires(
const typename Container::Item_Type & v, Hash
h, Equal e)
170 {
h(v) } -> std::convertible_to<size_t>;
171 { e(v, v) } -> std::convertible_to<bool>;
174 Hash & hash, Equal & eq)
176 using T =
typename Container::Item_Type;
177 using Eq_Type = std::remove_cvref_t<Equal>;
179 if constexpr (dyn_set_lhash_available<T, Eq_Type>)
182 using Hash_Fct =
typename Set_Type::Hash_Fct;
184 Hash_Fct hash_fct([&hash] (
const T & value)
186 return static_cast<size_t>(hash(value));
189 Set_Type seen(17, hash_fct,
eq,
192 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
193 if (seen.contains_or_insert(it.get_curr()).second)
203 template <
typename T>
class DynList;
214 template <
typename T =
int,
template <
typename>
class Container = DynList>
218 for (
T i = start; i <= end; i +=
step)
233 template <
typename T =
int,
template <
typename>
class Container = DynList>
245 const auto step =
static_cast<double>(end - start) / (n - 1);
246 for (
size_t i = 0; i < n; ++i)
263 template <
typename T =
int,
template <
typename>
class Container = DynList,
266 ->
Container<std::decay_t<
decltype(op(start))>>
269 for (
T i = start; i <= end; i +=
step)
275 template <
typename T =
int,
template <
typename>
class Container = DynList,
278 const T step = 1, Op && op = Op())
279 ->
Container<std::decay_t<
decltype(op(start))>>
303 template <
typename T =
int,
template <
typename>
class Container = DynList>
307 for (
size_t i = 0; i < n; ++i)
320 template <
typename T =
int,
template <
typename>
class Container = DynList>
324 for (
T i = 0; i < n; ++i)
338 template <
typename T =
int> [[
nodiscard]]
inline
342 for (
size_t i = 0; i < n; ++i)
348 template <
typename T =
int> [[
nodiscard]]
inline
386 template <AlephSequentialContainer C>
387 void fill(C & container,
const typename C::Item_Type & value)
389 container.mutable_for_each([&value](
typename C::Item_Type & item)
421 template <AlephSequentialContainer C>
422 requires requires(
typename C::Item_Type v) { ++v; }
423 void iota(C & container,
typename C::Item_Type start)
425 container.mutable_for_each([&start](
typename C::Item_Type & item)
456 template <AlephSequentialContainer C>
457 requires requires(
typename C::Item_Type v,
typename C::Item_Type s) { v += s; }
459 typename C::Item_Type start,
460 const typename C::Item_Type
step)
462 container.mutable_for_each([&start, &
step](
typename C::Item_Type & item)
495 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
508 using T =
const typename Container::Item_Type *;
510 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
534 void each(
const size_t start,
const size_t end, Op & op)
536 for (
size_t i = start; i <= end; ++i)
542 void each(
size_t start,
size_t end, Op && op)
544 each(start, end, op);
549 void each(
const size_t n, Op & op)
576 for (
auto it = c.get_it(pos); it.has_curr();
580 catch (
const std::overflow_error &) { }
615 template <
class Container,
class Operation>
inline
618 container.traverse([&
operation] (
const auto & item)
627 template <
class Container,
class Operation>
inline
630 container.traverse([&
operation] (
const auto & item)
639 template <
class Container,
class Operation>
inline
647 template <
class Container,
class Operation>
inline const Container &
680 template <
class Container,
class Operation>
inline
684 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
689 template <
class Container,
class Operation>
inline
718 template <
class Container,
class Operation>
inline
725 template <
class Container,
class Operation>
inline
732 template <
class Container,
class Operation>
inline
739 template <
class Container,
class Operation>
inline
769 template <
class Container,
class Operation>
inline
773 container.traverse([&
operation] (
const auto & item)
780 template <
class Container,
class Operation>
inline
784 container.traverse([&
operation] (
const auto & item)
791 template <
class Container,
class Operation>
inline
798 template <
class Container,
class Operation>
inline
805 template <
typename T>
808 bool operator () (
const T &)
const noexcept {
return true; }
883 template <
typename T,
class C,
class Op>
887 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
898 template <
typename T,
class Container,
class Operation> [[
nodiscard]]
inline
902 if constexpr (std::ranges::range<Container>)
908 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
939 template <
class Container1,
class Container2> [[
nodiscard]]
inline
940 DynList<std::pair<
typename Container1::Item_Type,
941 typename Container2::Item_Type>>
944 typedef typename Container1::Item_Type
T1;
945 typedef typename Container2::Item_Type
T2;
948 typename Container1::Iterator it1(a);
949 typename Container2::Iterator it2(b);
950 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
951 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
982 template <
class Container1,
class Container2> [[
nodiscard]]
inline
983 DynList<std::tuple<
typename Container1::Item_Type,
984 typename Container2::Item_Type>>
987 typedef typename Container1::Item_Type
T1;
988 typedef typename Container2::Item_Type
T2;
989 using Tuple = std::tuple<T1, T2>;
992 typename Container1::Iterator it1(a);
993 typename Container2::Iterator it2(b);
994 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1026 template <
class Container1,
class Container2> [[
nodiscard]]
inline
1027 DynList<std::pair<
typename Container1::Item_Type,
1028 typename Container2::Item_Type>>
1032 typedef typename Container1::Item_Type
T1;
1033 typedef typename Container2::Item_Type
T2;
1037 auto it2 = b.get_it();
1038 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1039 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
1041 if (it1.has_curr()
or it2.has_curr())
1063 template <
class Container1,
class Container2> [[
nodiscard]]
inline
1064 DynList<std::tuple<
typename Container1::Item_Type,
1065 typename Container2::Item_Type>>
1068 typedef typename Container1::Item_Type
T1;
1069 typedef typename Container2::Item_Type
T2;
1070 using Tuple = std::tuple<T1, T2>;
1073 typename Container1::Iterator it1(a);
1074 typename Container2::Iterator it2(b);
1075 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1078 if (it1.has_curr()
or it2.has_curr())
1109 template <
class Container> [[
nodiscard]]
1112 using Item =
typename Container::Item_Type;
1113 using Pair = std::pair<Item, size_t>;
1116 c.for_each([&i, &
ret] (
const Item & item) {
ret.append(Pair(item, i++)); });
1149 template <
class C1,
class C2,
1150 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
1153 auto it1 =
c1.get_it();
1154 auto it2 =
c2.get_it();
1155 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1156 if (
not (e(it1.get_curr(), it2.get_curr())))
1159 return not (it1.has_curr()
or it2.has_curr());
1163 template <
typename T> [[
nodiscard]]
inline
1170 template <
class C1,
class C2,
class Eq> [[
nodiscard]]
inline
1202 template <
class C1,
class C2,
1203 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
1204 std::tuple<bool, size_t, typename C1::Item_Type, typename C2::Item_Type>
1207 using T =
typename C1::Item_Type;
1208 auto it1 =
c1.get_it();
1209 auto it2 =
c2.get_it();
1211 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne(), n++)
1213 auto &
i1 = it1.get_curr();
1214 auto &
i2 = it2.get_curr();
1216 return std::make_tuple(
false, n,
i1,
i2);
1219 return std::make_tuple(
not (it1.has_curr()
or it2.has_curr()), n,
T(),
T());
1248 template <
class C1,
class C2,
1249 class Cmp = std::less<typename C1::Item_Type>> [[
nodiscard]]
inline
1252 auto it1 =
c1.get_it();
1253 auto it2 =
c2.get_it();
1254 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1256 auto &
curr1 = it1.get_curr();
1257 auto &
curr2 = it2.get_curr();
1264 if (
not it1.has_curr()
and not it2.has_curr())
1267 return it2.has_curr();
1286 template <
class C1,
class C2,
1287 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
1317 template <
class Container> [[
nodiscard]]
inline
1320 using T1 = std::decay_t<
decltype(
l.
get_first().first)>;
1321 using T2 = std::decay_t<
decltype(
l.
get_first().second)>;
1324 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1326 auto & curr = it.get_curr();
1331 return std::make_pair(std::move(
l1), std::move(
l2));
1360 template <
template <
typename>
class Container,
typename T1,
typename T2>
1366 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1368 auto & curr = it.get_curr();
1373 return std::make_tuple(std::move(
l1), std::move(
l2));
1385 [[
nodiscard]]
inline std::pair<TgtContainer<typename SrcContainer::Item_Type>,
1388 std::function<
bool(
const typename SrcContainer::Item_Type &)>
operation)
1390 typedef typename SrcContainer::Item_Type Type;
1405 template <
class Container> [[
nodiscard]]
inline
1409 using T =
typename Container::Key_Type;
1410 using Pair = std::pair<size_t, T>;
1413 return c.Container:: template
maps<Pair>([&i] (
const T & d)
1414 {
return Pair(i++, d); });
1419 template <
class Container> [[
nodiscard]]
inline
1423 using T =
typename Container::Key_Type;
1424 using Tuple = std::tuple<size_t, typename Container::Key_Type>;
1428 return Tuple(i++, d);
1453 template <
typename T,
template <
typename>
class Container>
1485 template <
class Container> [[
nodiscard]]
1488 using T =
typename Container::Item_Type;
1489 typename Container::Iterator it(c);
1491 for (
size_t i = 0; i < n; ++i, it.next())
1496 for (; it.has_curr(); it.next_ne())
1531 template <
typename T,
template <
typename>
class Container,
class Equal>
1532 [[
nodiscard]] std::pair<DynList<DynList<T>>,
size_t>
1535 using P = std::pair<DynList<DynList<T>>,
size_t>;
1543 auto it = c.get_it();
1549 for (it.next(); it.has_curr(); it.next_ne())
1551 auto & curr = it.get_curr();
1559 group->append(curr);
1566 template <
typename T,
template <
typename>
class Container,
1567 class Equal = std::equal_to<T>>
1568 [[
nodiscard]] std::pair<DynList<DynList<T>>,
size_t>
1601 template <
typename T,
template <
typename>
class Container,
class Equal>
1602 [[
nodiscard]] std::pair<DynList<T>,
size_t>
1605 using P = std::pair<DynList<T>,
size_t>;
1611 auto it = c.get_it();
1617 for (it.next(); it.has_curr(); it.next_ne())
1619 auto & curr = it.get_curr();
1632 template <
typename T,
template <
typename>
class Container,
1633 class Equal = std::equal_to<T>>
1634 [[
nodiscard]] std::pair<DynList<T>,
size_t>
1664 template <
class Itor1,
class Itor2 = Itor1>
1679 template <
class C1,
class C2>
1686 [[nodiscard]]
bool has_curr() const noexcept {
return it1.has_curr() and it2.has_curr(); }
1689 [[nodiscard]]
bool has_curr1() const noexcept {
return it1.has_curr(); }
1692 [[nodiscard]]
bool has_curr2() const noexcept {
return it2.has_curr(); }
1700 return std::make_pair(it1.get_curr(), it2.get_curr());
1709 return std::make_pair(it1.get_curr_ne(), it2.get_curr_ne());
1736 return not (it1.has_curr() or it2.has_curr());
1754 template <
class C1,
class C2>
1758 using I1 =
typename C1::Iterator;
1759 using I2 =
typename C2::Iterator;
1766 template <
class C1,
class C2>
1770 using I1 =
typename C1::Iterator;
1771 using I2 =
typename C2::Iterator;
1774 for (
size_t i = 0; i < pos; ++i)
1785 template <
class C,
typename T,
typename ...
Args>
inline
1797 template <
class C,
typename ...
Args>
inline
1808 template <
class C,
typename T,
typename ...
Args>
inline
1820 template <
class C,
typename ...
Args>
inline
1829 template <
class C,
typename ...
Args>
1838 template <
class SrcC,
class TgtC>
1842 for (
auto it =
srcc.get_it(); it.has_curr(); it.next_ne())
1843 ret.append(it.get_curr());
1849 template <
typename T,
typename ...
Args>
1858 template <
class C,
typename T,
typename ...
Args>
inline
1870 template <
class C,
typename ...
Args>
inline
1916 template <
typename T,
1917 template <
typename>
class C1,
1918 template <
typename>
class C2>
1922 for (
auto it_c = c.get_it();
it_c.has_curr();
it_c.next_ne())
1925 for (
auto it =
curr_c.get_it(); it.has_curr(); it.next_ne())
1942 template <
typename T,
1943 template <
typename>
class C1,
1944 template <
typename>
class C2,
1945 template <
typename>
class C3>
1949 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1965 template <
typename T,
1966 template <
typename>
class C1,
1967 template <
typename>
class C2,
1968 template <
typename>
class C3,
1969 template <
typename>
class C4>
1973 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1989 template <
typename T,
1990 template <
typename>
class C1,
1991 template <
typename>
class C2,
1992 template <
typename>
class C3,
1993 template <
typename>
class C4,
1994 template <
typename>
class C5>
1998 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2022 template <
typename T> [[
nodiscard]]
inline
2025 for (
const auto & v : values)
2048 template <
typename T> [[
nodiscard]]
inline
2061 template <
typename T,
typename U,
typename ...
Args> [[
nodiscard]]
inline
2073 template <
class Container,
class Operation> [[
nodiscard]]
inline
2080 template <
class Container,
class Operation> [[
nodiscard]]
inline
2113 template <
class Container,
class Pred> [[
nodiscard]]
inline
2114 typename Container::Item_Type *
2117 typename Container::Item_Type * result =
nullptr;
2118 container.traverse([&result, &
pred] (
auto & item)
2131 template <
class Container,
class Pred> [[
nodiscard]]
inline
2132 const typename Container::Item_Type *
2135 const typename Container::Item_Type * result =
nullptr;
2136 container.traverse([&result, &
pred] (
const auto & item)
2149 template <
class Container,
class Pred> [[
nodiscard]]
inline
2150 typename Container::Item_Type *
2157 template <
class Container,
class Pred> [[
nodiscard]]
inline
2158 const typename Container::Item_Type *
2186 template <
class Container,
class Pred> [[
nodiscard]]
inline
2187 std::optional<typename Container::Item_Type>
2190 std::optional<typename Container::Item_Type> result;
2191 container.traverse([&result, &
pred] (
const auto & item)
2204 template <
class Container,
class Pred> [[
nodiscard]]
inline
2205 std::optional<typename Container::Item_Type>
2220 template <
typename T,
class Container,
class Operation> [[
nodiscard]]
inline
2224 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2225 reversed.
insert(it.get_curr());
2228 for (
auto it = reversed.
get_it(); it.has_curr(); it.next_ne())
2240 template <
class Container,
typename T =
typename Container::Item_Type>
2244 if constexpr (std::ranges::range<Container>)
2250 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2251 result = result + it.get_curr();
2263 template <
class Container,
typename T =
typename Container::Item_Type>
2267 if constexpr (std::ranges::range<Container>)
2273 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2274 result = result * it.get_curr();
2286 template <
class C1,
class C2> [[
nodiscard]]
inline
2291 for (
auto it =
c1.get_it(); it.has_curr(); it.next_ne())
2292 result.
append(it.get_curr());
2293 for (
auto it =
c2.get_it(); it.has_curr(); it.next_ne())
2294 result.
append(it.get_curr());
2305 template <
class Container,
class Pred> [[
nodiscard]]
inline
2310 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2312 const auto & item = it.get_curr();
2327 template <
class Container,
class Pred> [[
nodiscard]]
inline
2333 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2335 const auto & item = it.get_curr();
2353 template <
class Container,
class Op> [[
nodiscard]]
inline
2359 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2361 auto sub = op(it.get_curr());
2362 for (
auto sit = sub.get_it();
sit.has_curr();
sit.next_ne())
2377 template <
typename T,
class Container> [[
nodiscard]]
inline
2383 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2385 acc =
acc + it.get_curr();
2401 template <
typename T,
class Container,
class Op> [[
nodiscard]]
inline
2407 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2409 acc = op(
acc, it.get_curr());
2423 class Cmp = std::less<typename Container::Item_Type>>
2424 [[
nodiscard]]
inline const typename Container::Item_Type *
2427 auto it = container.get_it();
2428 if (
not it.has_curr())
2431 const typename Container::Item_Type *
min_elem = &it.get_curr();
2432 for (it.next_ne(); it.has_curr(); it.next_ne())
2434 const auto & curr = it.get_curr();
2449 class Cmp = std::less<typename Container::Item_Type>>
2450 [[
nodiscard]]
inline const typename Container::Item_Type *
2453 auto it = container.get_it();
2454 if (
not it.has_curr())
2457 const typename Container::Item_Type *
max_elem = &it.get_curr();
2458 for (it.next_ne(); it.has_curr(); it.next_ne())
2460 const auto & curr = it.get_curr();
2475 class Cmp = std::less<typename Container::Item_Type>>
2476 [[
nodiscard]]
inline std::pair<
const typename Container::Item_Type *,
2477 const typename Container::Item_Type *>
2480 using T =
typename Container::Item_Type;
2481 auto it = container.get_it();
2482 if (
not it.has_curr())
2483 return {
nullptr,
nullptr};
2487 for (it.next_ne(); it.has_curr(); it.next_ne())
2489 const auto & curr = it.get_curr();
2505 template <
class Container,
class Pred> [[
nodiscard]]
inline
2509 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2510 if (
pred(it.get_curr()))
2531 template <AlephSequentialIterableContainer Container,
class Equal>
2534 using T =
typename Container::Item_Type;
2535 using Eq = std::remove_cvref_t<Equal>;
2537 if constexpr (std::is_same_v<Eq, std::equal_to<T>>
2538 and std::copy_constructible<T>
2539 and requires(
const T & v)
2541 { std::hash<T>{}(v) } -> std::convertible_to<size_t>;
2544 auto hash = [] (
const T & value) ->
size_t
2546 return std::hash<T>{}(value);
2568 template <AlephSequentialIterableContainer
Container,
2569 class Equal = std::equal_to<typename Container::Item_Type>>
2571 Equal &&
eq = Equal())
2591 template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
2592 requires std::copy_constructible<typename Container::Item_Type>
2593 and requires(
const typename Container::Item_Type & v, Hash
h, Equal e)
2595 {
h(v) } -> std::convertible_to<size_t>;
2596 { e(v, v) } -> std::convertible_to<bool>;
2599 Hash & hash, Equal &
eq)
2605 template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
2606 requires std::copy_constructible<typename Container::Item_Type>
2607 and requires(
const typename Container::Item_Type & v, Hash
h, Equal e)
2609 {
h(v) } -> std::convertible_to<size_t>;
2610 { e(v, v) } -> std::convertible_to<bool>;
2613 Hash && hash, Equal &&
eq)
2615 using Hash_Type = std::remove_reference_t<Hash>;
2616 using Eq_Type = std::remove_reference_t<Equal>;
2630 template <
class Container> [[
nodiscard]]
inline
2632 const typename Container::Item_Type & value)
2634 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2635 if (it.get_curr() == value)
2648 template <
class Container> [[
nodiscard]]
inline
2652 using T =
typename Container::Item_Type;
2653 using Tuple = std::tuple<size_t, T>;
2656 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
2696 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2697 DynList<std::pair<
typename Container1::Item_Type,
2698 typename Container2::Item_Type>>
2700 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2701 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2703 using T1 =
typename Container1::Item_Type;
2704 using T2 =
typename Container2::Item_Type;
2708 auto it2 = b.get_it();
2711 while (it1.has_curr()
and it2.has_curr())
2713 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
2719 while (it1.has_curr())
2726 while (it2.has_curr())
2767 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2768 DynList<std::tuple<
typename Container1::Item_Type,
2769 typename Container2::Item_Type>>
2771 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2772 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2774 using T1 =
typename Container1::Item_Type;
2775 using T2 =
typename Container2::Item_Type;
2776 using Tuple = std::tuple<T1, T2>;
2780 auto it2 = b.get_it();
2782 while (it1.has_curr()
and it2.has_curr())
2789 while (it1.has_curr())
2795 while (it2.has_curr())
2840 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2842 std::optional<typename Container2::Item_Type>>>
2845 using T1 =
typename Container1::Item_Type;
2846 using T2 =
typename Container2::Item_Type;
2847 using Opt1 = std::optional<T1>;
2848 using Opt2 = std::optional<T2>;
2852 auto it2 = b.get_it();
2854 while (it1.has_curr()
and it2.has_curr())
2856 ret_val.append(std::make_pair(
Opt1(it1.get_curr()),
Opt2(it2.get_curr())));
2861 while (it1.has_curr())
2863 ret_val.append(std::make_pair(
Opt1(it1.get_curr()), std::nullopt));
2867 while (it2.has_curr())
2869 ret_val.append(std::make_pair(std::nullopt,
Opt2(it2.get_curr())));
2930 using Key = std::invoke_result_t<KeyFunc, const T&>;
2938 auto it = c.get_it();
2943 for (it.next_ne(); it.has_curr(); it.next_ne())
2945 const auto & item = it.get_curr();
2992 template <
typename T,
template <
typename>
class Container,
2998 using Key = std::invoke_result_t<KeyFunc, const T&>;
3006 auto it = c.get_it();
3011 for (it.next_ne(); it.has_curr(); it.next_ne())
3013 const auto & item = it.get_curr();
3066 template <
typename T,
template <
typename>
class Container,
3071 std::invoke_result_t<Reducer, const DynList<T>&>>>
3073 using Key = std::invoke_result_t<KeyFunc, const T&>;
3074 using ReducedType = std::invoke_result_t<Reducer, const DynList<T>&>;
3080 for (
auto it =
groups.get_it(); it.has_curr(); it.next_ne())
3082 auto & [key,
group] = it.get_curr();
C++20 concepts for constraining comparison functors.
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error()
Throws std::length_error unconditionally.
#define ah_invalid_argument()
Throws std::invalid_argument unconditionally.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
C++20 Ranges support and adaptors for Aleph-w containers.
Dynamic singly linked list with functional programming support.
T & insert(const T &item)
T & append(const T &item)
T & get_first() const
Return the first item of the list.
Iterator that zips two other iterators.
auto get_curr_ne() const noexcept
Get current pair (no bounds check).
bool has_curr1() const noexcept
Check if first iterator has current element.
Pair_Iterator(const C1 &c1, const C2 &c2)
Construct from two containers.
Pair_Iterator(Itor1 i1, Itor2 i2)
Construct from two iterators.
bool has_curr() const noexcept
Check if both iterators have current elements.
bool was_traversed() const noexcept
Check if both iterators were completely traversed.
bool has_curr2() const noexcept
Check if second iterator has current element.
void next()
Advance both iterators (bounds-checked).
auto get_curr() const
Get current pair (bounds-checked).
void next_ne() noexcept
Advance both iterators (no bounds check).
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Common hash table utilities and base classes.
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr T ranges_fold_left(Container &&c, T init, BinaryOp &&op)
Fallback fold_left using range-based for loop.
bool pairwise_all_unique(const Container &container, Equal &eq)
bool all_unique_hash_path(const Container &container, Hash &hash, Equal &eq)
constexpr bool dyn_set_lhash_available
Main namespace for Aleph-w library functions.
std::pair< DynList< T >, size_t > unique_sequential(const Container< T > &c, Equal &eq)
Extract unique consecutive items.
and
Check uniqueness with explicit hash + equality functors.
std::tuple< bool, size_t, typename C1::Item_Type, typename C2::Item_Type > are_eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Detailed equality check returning mismatch position and values.
DynList< T > flatten(const C2< C1< T > > &c)
Flatten a nested container of one level.
Container< T > nrange(const T start, const T end, const size_t n)
Generate exactly n values evenly spaced between [start, end].
auto group_by_reduce(const Container< T > &c, KeyFunc key_func, Reducer reducer) -> DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, std::invoke_result_t< Reducer, const DynList< T > & > > >
Group consecutive elements and apply a reducer to each group.
std::pair< const typename Container::Item_Type *, const typename Container::Item_Type * > minmax_ptr(const Container &container, Cmp cmp=Cmp())
Find both min and max elements in a single pass.
const Container::Item_Type * min_ptr(const Container &container, Cmp cmp=Cmp())
Find the minimum element in a container.
DynList< std::pair< std::optional< typename Container1::Item_Type >, std::optional< typename Container2::Item_Type > > > zip_longest_opt(const Container1 &a, const Container2 &b)
Zip two containers using optionals for missing values.
auto unzip(const Container &l)
Separate a list of pairs into two lists.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
void reverse(Itor beg, Itor end)
Reverse elements in a range.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
DynList< T > scanl(const Container &container, const T &init, Op op)
Prefix scan with custom operation.
Itor unique(Itor __first, Itor __last, BinaryPredicate __binary_pred=BinaryPredicate())
Remove consecutive duplicates in place.
T Item_Type
Type of elements from the first container.
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
DynList< typename Container::Item_Type > drop_while(const Container &c, Pred pred)
Skip elements while predicate is true (drop_while).
auto set_range(const T start, const T end, const T step, Op &op) -> Container< std::decay_t< decltype(op(start))> >
Generate a range [start, end] and apply an operation to each value.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zipEq(const Container1 &a, const Container2 &b)
Zip two containers; throw if lengths differ.
DynList< T > intercept(const Container< T > &c1, const Container< T > &c2)
std::pair< TgtContainer< typename SrcContainer::Item_Type >, TgtContainer< typename SrcContainer::Item_Type > > partition(const SrcContainer &c, std::function< bool(const typename SrcContainer::Item_Type &)> operation)
Partition a container into two based on a predicate.
bool containers_eq(const C1 &c1, const C2 &c2, Eq e)
bool all_unique(const Container &container, Equal &eq)
Check if all elements in a container are unique using a comparator.
DynList< std::pair< T, size_t > > repeated_with_index(const Container< T > &c)
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
bool is_inside(const T &val, const DynList< T > &values)
Check if a value is present in a list.
DynList< T > repeated(const Container< T > &c)
const float hash_default_upper_alpha
DynList< typename Container::Item_Type > take_while(const Container &c, Pred pred)
Return elements while predicate is true (take_while).
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip(const Container1 &a, const Container2 &b)
Zip two containers into a list of pairs.
Pair_Iterator< typename C1::Iterator, typename C2::Iterator > get_pair_it(const C1 &c1, const C2 &c2)
Create a Pair_Iterator for two containers.
void fill(Itor beg, const Itor &end, const T &value)
Fill a range with a value.
T foldr(const Container &container, const T &init, Operation operation)
Right fold (reduce).
auto enumerate(const Container &c)
Return pairs of (element, index).
size_t append_in_container(C &c, Args ... args)
Append multiple items into a container.
bool is_equal(const T &val)
Variadic check for equality against multiple values.
T foldl(const Container &container, const T &init, Operation operation)
Classic left fold (reduce).
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
bool exists(Container &container, Operation &operation)
Return true if at least one element satisfies a predicate.
auto gen_seq_list_tuples(const Container &c, size_t n)
Generate all sequential tuples (sliding windows) of size n.
bool contains(const std::string_view &str, const std::string_view &substr)
Check if substr appears inside str.
DynList< T > build_dynlist(Args ... args)
Build a DynList with the given items.
void iota(C &container, typename C::Item_Type start)
Fill all elements of a container with unit-step sequential values.
std::optional< typename Container::Item_Type > find_opt(const Container &container, Pred &pred)
Find the first element satisfying pred (safe version).
void each(const size_t start, const size_t end, Op &op)
Execute an operation repeatedly over a range of indices.
DynList< T > rep(const size_t n, const T &item)
Create a sequence of repeated items.
auto flat_map(const Container &container, Op op) -> DynList< typename std::decay_t< decltype(op(std::declval< typename Container::Item_Type >()))>::Item_Type >
Apply operation and flatten results (flatMap/concatMap).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip(const Container1 &a, const Container2 &b)
Zip two containers into a list of tuples.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
DynList< typename Container::Item_Type * > pointers_list(Container &c)
Create a list of pointers to items in a container.
DynList< std::pair< size_t, typename Container::Key_Type > > indexes(const Container &c)
Return pairs of (index, key).
bool lesser(const C1 &c1, const C2 &c2, Cmp cmp=Cmp())
Lexicographical comparison between two containers.
TgtC assign_container(const SrcC &srcc)
Convert one container type to another.
DynList< std::tuple< size_t, typename Container::Item_Type > > enumerate_tuple(const Container &container)
Zip containers with an index (enumerate with zip).
const Container::Item_Type * max_ptr(const Container &container, Cmp cmp=Cmp())
Find the maximum element in a container.
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzipEq(const Container1 &a, const Container2 &b)
Zip two containers into tuples; throw if lengths differ.
Operation for_each(Itor beg, const Itor &end, Operation op)
Apply an operation to each element in a range.
std::pair< DynList< DynList< T > >, size_t > sequential_groups(const Container< T > &c, Equal &eq)
Group consecutive equal elements together.
size_t insert_in_container(C &c, Args ... args)
Insert multiple items into a container.
DynList< std::tuple< size_t, typename Container::Key_Type > > tindexes(const Container &c)
Return tuples of (index, key).
Itor::difference_type count_if(Itor beg, const Itor &end, Operation op)
Count elements satisfying a predicate.
DynList< T > scanl_sum(const Container &container, const T &init)
Compute running sums (scanl with addition).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers into tuples, padding the shorter one.
DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, DynList< T > > > group_by_eq(const Container< T > &c, KeyFunc key_func, KeyEqual key_equal)
Group consecutive elements by a key function with custom equality.
std::string concat(const Args &... args)
Concatenate multiple arguments into a single std::string.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers, padding the shorter one with a fill value.
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
DynList< typename Container::Item_Type > sublist(const Container &c, size_t pos, const size_t stride)
Extract a sublist using a stride.
Container::Item_Type * find_ptr(Container &container, Pred &pred)
Find the first element satisfying pred.
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
void enum_for_each(const Container &container, Operation &operation)
Apply an operation to each element and its index.
C build_container(Args ... args)
Build a container with the given items.
DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, DynList< T > > > group_by(const Container< T > &c, KeyFunc key_func)
Group consecutive elements by a key function.
Container< T > contiguous_range(T start, const size_t n)
Generate n contiguous values starting from start.
const float hash_default_lower_alpha
bool none(const Container &container, Operation &operation)
Return true if no element satisfies operation.
static std::atomic< bool > init
size_t remove_from_container(C &c, Args ... args)
Remove multiple items from a container.
std::tuple< Container< T1 >, Container< T2 > > tunzip(const Container< std::tuple< T1, T2 > > &l)
Separate a list of tuples into two containers.
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.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Default filter operation (always true).
Default folding operation (returns default-constructed accumulator).
Default mapping operation (identity).
Abstract base class for optional-like results.
virtual bool is_found() const noexcept=0
virtual const T & get_item() const =0
Represents a missing value.
const T & get_item() const override
bool is_found() const noexcept override
Represents a found value (stored by reference).
const T & get_item() const override
bool is_found() const noexcept override