32#ifndef AH_FUNCTIONAL_H
33#define AH_FUNCTIONAL_H
93#if defined(__GNUC__) || defined(__clang__)
95#elif defined(_MSC_VER)
103#if defined(__GNUC__) || defined(__clang__)
105#elif defined(_MSC_VER)
132 [[nodiscard]]
bool is_found() const noexcept
override
139template <
typename tgtT,
typename srcT>
144 return static_cast<tgtT
>(item);
149template <
typename TR,
typename TD>
162template <
typename Key,
class Cmp>
166namespace functional_detail {
171using get_it_t = std::decay_t<decltype(std::declval<const C &>().get_it())>;
186template <
typename T,
class Eq,
typename =
void>
187struct Dyn_Set_Lhash_Available :
public std::false_type
192template <
typename T,
class Eq>
193struct Dyn_Set_Lhash_Available<
T, Eq,
std::void_t<decltype(sizeof(DynSetLhash<T, Eq>))>>
194 :
public std::true_type
198template <
typename T,
class Eq>
201template <AlephSequentialIterableContainer Container,
class Equal>
204 for (
auto it1 = container.get_it(); it1.has_curr(); it1.next_ne())
208 for (; it2.has_curr(); it2.next_ne())
209 if (
eq(it1.get_curr(), it2.get_curr()))
215template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
216 requires std::copy_constructible<typename Container::Item_Type>
217 and requires(
const typename Container::Item_Type &v, Hash
h, Equal e) {
218 {
h(v) } -> std::convertible_to<size_t>;
219 { e(v, v) } -> std::convertible_to<bool>;
223 using T =
typename Container::Item_Type;
224 using Eq_Type = std::remove_cvref_t<Equal>;
226 if constexpr (dyn_set_lhash_available<T, Eq_Type>)
229 using Hash_Fct =
typename Set_Type::Hash_Fct;
231 Hash_Fct hash_fct([&hash](
const T &
value)
233 return static_cast<size_t>(hash(
value));
238 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
239 if (seen.contains_or_insert(it.get_curr()).second)
264template <
typename T =
int,
template <
typename>
class Container = DynList>
268 for (
T i = start; i <= end; i += step)
283template <
typename T =
int,
template <
typename>
class Container = DynList>
295 const auto step =
static_cast<double>(end - start) / (n - 1);
296 for (
size_t i = 0; i < n; ++i)
297 ret_val.append(
static_cast<T>(start + i * step));
313template <
typename T =
int,
template <
typename>
class Container = DynList,
class Op>
315 ->
Container<std::decay_t<
decltype(op(start))>>
318 for (
T i = start; i <= end; i += step)
324template <
typename T =
int,
template <
typename>
class Container = DynList,
class Op>
326 ->
Container<std::decay_t<
decltype(op(start))>>
350template <
typename T =
int,
template <
typename>
class Container = DynList>
354 for (
size_t i = 0; i < n; ++i)
366template <
typename T =
int,
template <
typename>
class Container = DynList>
370 for (
T i = 0; i < n; ++i)
383template <
typename T =
int>
387 for (
size_t i = 0; i < n; ++i)
393template <
typename T =
int>
431template <AlephSequentialContainer C>
432void fill(C &container,
const typename C::Item_Type &
value)
434 container.mutable_for_each([&
value](
typename C::Item_Type &item)
466template <AlephSequentialContainer C>
467 requires requires(
typename C::Item_Type v) { ++v; }
468void iota(C &container,
typename C::Item_Type start)
470 container.mutable_for_each([&start](
typename C::Item_Type &item)
501template <AlephSequentialContainer C>
502 requires requires(
typename C::Item_Type v,
typename C::Item_Type s) { v += s; }
503void iota(C &container,
typename C::Item_Type start,
const typename C::Item_Type step)
505 container.mutable_for_each([&start, &step](
typename C::Item_Type &item)
534template <
class Container>
539 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
548template <
class Container>
552 using T =
const typename Container::Item_Type *;
554 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
579void each(
const size_t start,
const size_t end, Op &op)
581 for (
size_t i = start; i <= end; ++i)
588void each(
size_t start,
size_t end, Op &&op)
590 each(start, end, op);
596void each(
const size_t n, Op &op)
618template <
class Container>
625 for (
auto it = c.get_it(pos); it.has_curr();
each(0, stride - 1, [&it]()
631 catch (
const std::overflow_error &)
639template <
class Container>
668template <
class Container,
class Operation>
671 container.traverse([&
operation](
const auto &item)
680template <
class Container,
class Operation>
683 container.traverse([&
operation](
const auto &item)
692template <
class Container,
class Operation>
699template <
class Container,
class Operation>
732template <
class Container,
class Operation>
737 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
742template <
class Container,
class Operation>
772template <
class Container,
class Operation>
773 requires requires(
Container &c,
Operation &op) { { c.traverse(op) } -> std::convertible_to<bool>; }
780template <
class Container,
class Operation>
788template <
class Container,
class Operation>
789 requires requires(
Container &c,
Operation &op) { { c.traverse(op) } -> std::convertible_to<bool>; }
796template <
class Container,
class Operation>
826template <
class Container,
class Operation>
829 return not container.traverse([&
operation](
const auto &item)
836template <
class Container,
class Operation>
839 return not container.traverse([&
operation](
const auto &item)
846template <
class Container,
class Operation>
853template <
class Container,
class Operation>
937template <
typename T,
class C,
class Op>
938 requires requires(DynList<T> &
ret, Op &op) {
ret.append(op(std::declval<functional_detail::get_curr_t<C>>())); }
942 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
953template <
typename T,
class Container,
class Operation>
957 if constexpr (std::ranges::range<Container>)
963 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
993template <
class Container1,
class Container2>
997 typedef typename Container1::Item_Type
T1;
998 typedef typename Container2::Item_Type
T2;
1002 auto it2 = b.get_it();
1003 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1004 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
1035template <
class Container1,
class Container2>
1039 typedef typename Container1::Item_Type
T1;
1040 typedef typename Container2::Item_Type
T2;
1041 using Tuple = std::tuple<T1, T2>;
1045 auto it2 = b.get_it();
1046 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1078template <
class Container1,
class Container2>
1082 typedef typename Container1::Item_Type
T1;
1083 typedef typename Container2::Item_Type
T2;
1087 auto it2 = b.get_it();
1088 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1089 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
1112template <
class Container1,
class Container2>
1116 typedef typename Container1::Item_Type
T1;
1117 typedef typename Container2::Item_Type
T2;
1118 using Tuple = std::tuple<T1, T2>;
1122 auto it2 = b.get_it();
1123 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1156template <
class Container>
1160 using Item =
typename Container::Item_Type;
1161 using Pair = std::pair<Item, size_t>;
1164 c.for_each([&i, &
ret](
const Item &item)
1166 ret.append(Pair(item, i++));
1199template <
class C1,
class C2,
class Eq = std::equal_to<
typename C1::Item_Type>>
1202 auto it1 =
c1.get_it();
1203 auto it2 =
c2.get_it();
1204 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1205 if (
not(e(it1.get_curr(), it2.get_curr())))
1208 return not(it1.has_curr()
or it2.has_curr());
1212template <
typename T>
1219template <
class C1,
class C2,
class Eq>
1251template <
class C1,
class C2,
class Eq = std::equal_to<
typename C1::Item_Type>>
1252[[
nodiscard]]
inline std::tuple<bool, size_t, typename C1::Item_Type, typename C2::Item_Type>
1255 using T =
typename C1::Item_Type;
1256 auto it1 =
c1.get_it();
1257 auto it2 =
c2.get_it();
1259 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne(), n++)
1261 auto &
i1 = it1.get_curr();
1262 auto &
i2 = it2.get_curr();
1264 return std::make_tuple(
false, n,
i1,
i2);
1267 return std::make_tuple(
not(it1.has_curr()
or it2.has_curr()), n,
T(),
T());
1296template <
class C1,
class C2,
class Cmp = std::less<
typename C1::Item_Type>>
1299 auto it1 =
c1.get_it();
1300 auto it2 =
c2.get_it();
1301 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1303 auto &
curr1 = it1.get_curr();
1304 auto &
curr2 = it2.get_curr();
1311 if (
not it1.has_curr()
and not it2.has_curr())
1314 return it2.has_curr();
1333template <
class C1,
class C2,
class Eq = std::equal_to<
typename C1::Item_Type>>
1363template <
class Container>
1366 using T1 = std::decay_t<
decltype(
l.
get_first().first)>;
1367 using T2 = std::decay_t<
decltype(
l.
get_first().second)>;
1370 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1372 auto &curr = it.get_curr();
1377 return std::make_pair(std::move(
l1), std::move(
l2));
1406template <
template <
typename>
class Container,
typename T1,
typename T2>
1412 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1414 auto &curr = it.get_curr();
1419 return std::make_tuple(std::move(
l1), std::move(
l2));
1429[[
nodiscard]]
inline std::pair<TgtContainer<typename SrcContainer::Item_Type>,
1432 std::function<
bool(
const typename SrcContainer::Item_Type &)>
operation)
1434 typedef typename SrcContainer::Item_Type
Type;
1449template <
class Container>
1452 using T =
typename Container::Key_Type;
1453 using Pair = std::pair<size_t, T>;
1456 return c.Container::template
maps<Pair>([&i](
const T &d)
1458 return Pair(i++, d);
1463template <
class Container>
1467 using T =
typename Container::Key_Type;
1468 using Tuple = std::tuple<size_t, typename Container::Key_Type>;
1472 return Tuple(i++, d);
1496template <
typename T,
template <
typename>
class Container>
1528template <
class Container>
1532 using T =
typename Container::Item_Type;
1533 auto it = c.get_it();
1535 for (
size_t i = 0; i < n; ++i, it.next())
1540 for (; it.has_curr(); it.next_ne())
1575template <
typename T,
template <
typename>
class Container,
class Equal>
1579 using P = std::pair<DynList<DynList<T>>,
size_t>;
1587 auto it = c.get_it();
1593 for (it.next(); it.has_curr(); it.next_ne())
1595 auto &curr = it.get_curr();
1603 group->append(curr);
1610template <
typename T,
template <
typename>
class Container,
class Equal = std::equal_to<T>>
1612 Equal &&
eq = Equal())
1644template <
typename T,
template <
typename>
class Container,
class Equal>
1647 using P = std::pair<DynList<T>,
size_t>;
1653 auto it = c.get_it();
1659 for (it.next(); it.has_curr(); it.next_ne())
1661 auto &curr = it.get_curr();
1674template <
typename T,
template <
typename>
class Container,
class Equal = std::equal_to<T>>
1676 Equal &&
eq = Equal())
1705template <
class Itor1,
class Itor2 = Itor1>
1719 template <
class C1,
class C2>
1728 return it1.has_curr() and it2.has_curr();
1734 return it1.has_curr();
1740 return it2.has_curr();
1749 return std::make_pair(it1.get_curr(), it2.get_curr());
1758 return std::make_pair(it1.get_curr_ne(), it2.get_curr_ne());
1785 return not(it1.has_curr() or it2.has_curr());
1803template <
class C1,
class C2>
1808 using I1 =
typename C1::Iterator;
1809 using I2 =
typename C2::Iterator;
1810 auto i1 =
c1.get_it();
1811 auto i2 =
c2.get_it();
1816template <
class C1,
class C2>
1822 using I1 =
typename C1::Iterator;
1823 using I2 =
typename C2::Iterator;
1824 auto i1 =
c1.get_it();
1825 auto i2 =
c2.get_it();
1826 for (
size_t i = 0; i < pos; ++i)
1839template <
class C,
typename T,
typename...
Args>
1851template <
class C,
typename...
Args>
1864template <
class C,
typename T,
typename...
Args>
1876template <
class C,
typename...
Args>
1885template <
class C,
typename...
Args>
1894template <
class SrcC,
class TgtC>
1898 for (
auto it =
srcc.get_it(); it.has_curr(); it.next_ne())
1899 ret.append(it.get_curr());
1905template <
typename T,
typename...
Args>
1916template <
class C,
typename T,
typename...
Args>
1928template <
class C,
typename...
Args>
1939template <
typename T,
template <
typename>
class Container>
1943template <
typename T,
template <
typename>
class Container>
1947template <
typename T,
template <
typename>
class Container>
1951template <
typename T,
template <
typename>
class Container>
1955template <
typename T,
template <
typename>
class Container>
1978template <
typename T,
template <
typename>
class C1,
template <
typename>
class C2>
1982 for (
auto it_c = c.get_it();
it_c.has_curr();
it_c.next_ne())
1985 for (
auto it =
curr_c.get_it(); it.has_curr(); it.next_ne())
2002template <
typename T,
template <
typename>
class C1,
template <
typename>
class C2,
template <
typename>
class C3>
2006 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2022template <
typename T,
2023 template <
typename>
class C1,
2024 template <
typename>
class C2,
2025 template <
typename>
class C3,
2026 template <
typename>
class C4>
2030 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2046template <
typename T,
2047 template <
typename>
class C1,
2048 template <
typename>
class C2,
2049 template <
typename>
class C3,
2050 template <
typename>
class C4,
2051 template <
typename>
class C5>
2055 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2079template <
typename T>
2082 for (
const auto &v : values)
2105template <
typename T>
2118template <
typename T,
typename U,
typename...
Args>
2130template <
class Container,
class Operation>
2137template <
class Container,
class Operation>
2170template <
class Container,
class Pred>
2173 typename Container::Item_Type *result =
nullptr;
2174 container.traverse([&result, &
pred](
auto &item)
2187template <
class Container,
class Pred>
2191 const typename Container::Item_Type *result =
nullptr;
2192 container.traverse([&result, &
pred](
const auto &item)
2205template <
class Container,
class Pred>
2212template <
class Container,
class Pred>
2241template <
class Container,
class Pred>
2245 std::optional<typename Container::Item_Type> result;
2246 container.traverse([&result, &
pred](
const auto &item)
2259template <
class Container,
class Pred>
2275template <
typename T,
class Container,
class Operation>
2280 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2281 reversed.
insert(it.get_curr());
2284 for (
auto it = reversed.
get_it(); it.has_curr(); it.next_ne())
2296template <
class Container,
typename T =
typename Container::Item_Type>
2300 if constexpr (std::ranges::range<Container>)
2306 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2307 result = result + it.get_curr();
2319template <
class Container,
typename T =
typename Container::Item_Type>
2323 if constexpr (std::ranges::range<Container>)
2329 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2330 result = result * it.get_curr();
2342template <
class C1,
class C2>
2346 for (
auto it =
c1.get_it(); it.has_curr(); it.next_ne())
2347 result.
append(it.get_curr());
2348 for (
auto it =
c2.get_it(); it.has_curr(); it.next_ne())
2349 result.
append(it.get_curr());
2360template <
class Container,
class Pred>
2365 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2367 const auto &item = it.get_curr();
2382template <
class Container,
class Pred>
2388 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2390 const auto &item = it.get_curr();
2408template <
class Container,
class Op>
2413 typename std::decay_t<decltype(op(std::declval<typename Container::Item_Type>()))>
::Item_Type;
2415 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2417 auto sub = op(it.get_curr());
2418 for (
auto sit = sub.get_it();
sit.has_curr();
sit.next_ne())
2433template <
typename T,
class Container>
2439 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2441 acc =
acc + it.get_curr();
2457template <
typename T,
class Container,
class Op>
2458 requires requires(
T &
acc, Op &op) {
acc = op(
acc, std::declval<functional_detail::get_curr_t<Container>>()); }
2464 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2466 acc = op(
acc, it.get_curr());
2479template <
class Container,
class Cmp = std::less<
typename Container::Item_Type>>
2484 auto it = container.get_it();
2485 if (
not it.has_curr())
2488 const typename Container::Item_Type *
min_elem = &it.get_curr();
2489 for (it.next_ne(); it.has_curr(); it.next_ne())
2491 const auto &curr = it.get_curr();
2505template <
class Container,
class Cmp = std::less<
typename Container::Item_Type>>
2510 auto it = container.get_it();
2511 if (
not it.has_curr())
2514 const typename Container::Item_Type *
max_elem = &it.get_curr();
2515 for (it.next_ne(); it.has_curr(); it.next_ne())
2517 const auto &curr = it.get_curr();
2531template <
class Container,
class Cmp = std::less<
typename Container::Item_Type>>
2534[[
nodiscard]]
inline std::pair<const typename Container::Item_Type *, const typename Container::Item_Type *>
2537 using T =
typename Container::Item_Type;
2538 auto it = container.get_it();
2539 if (
not it.has_curr())
2540 return {
nullptr,
nullptr};
2544 for (it.next_ne(); it.has_curr(); it.next_ne())
2546 const auto &curr = it.get_curr();
2562template <
class Container,
class Pred>
2567 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2568 if (
pred(it.get_curr()))
2589template <AlephSequentialIterableContainer Container,
class Equal>
2592 using T =
typename Container::Item_Type;
2593 using Eq = std::remove_cvref_t<Equal>;
2595 if constexpr (std::is_same_v<Eq, std::equal_to<T>>
and std::copy_constructible<T>
2596 and requires(
const T &v) {
2597 { std::hash<T>{}(v) } -> std::convertible_to<size_t>;
2600 auto hash = [](
const T &
value) ->
size_t
2602 return std::hash<T>{}(
value);
2624template <AlephSequentialIterableContainer
Container,
2625 class Equal = std::equal_to<typename Container::Item_Type>>
2646template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
2647 requires std::copy_constructible<typename Container::Item_Type>
2648 and requires(
const typename Container::Item_Type &v, Hash
h, Equal e) {
2649 {
h(v) } -> std::convertible_to<size_t>;
2650 { e(v, v) } -> std::convertible_to<bool>;
2658template <AlephSequentialIterableContainer Container,
class Hash,
class Equal>
2659 requires std::copy_constructible<typename Container::Item_Type>
2660 and requires(
const typename Container::Item_Type &v, Hash
h, Equal e) {
2661 {
h(v) } -> std::convertible_to<size_t>;
2662 { e(v, v) } -> std::convertible_to<bool>;
2666 using Hash_Type = std::remove_reference_t<Hash>;
2667 using Eq_Type = std::remove_reference_t<Equal>;
2681template <
class Container>
2683 const typename Container::Item_Type &
value)
2685 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2686 if (it.get_curr() ==
value)
2699template <
class Container>
2703 using T =
typename Container::Item_Type;
2704 using Tuple = std::tuple<size_t, T>;
2707 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
2746template <
class Container1,
class Container2>
2750 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2751 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2753 using T1 =
typename Container1::Item_Type;
2754 using T2 =
typename Container2::Item_Type;
2758 auto it2 = b.get_it();
2761 while (it1.has_curr()
and it2.has_curr())
2763 ret_val.append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
2769 while (it1.has_curr())
2776 while (it2.has_curr())
2816template <
class Container1,
class Container2>
2820 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2821 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2823 using T1 =
typename Container1::Item_Type;
2824 using T2 =
typename Container2::Item_Type;
2825 using Tuple = std::tuple<T1, T2>;
2829 auto it2 = b.get_it();
2831 while (it1.has_curr()
and it2.has_curr())
2838 while (it1.has_curr())
2844 while (it2.has_curr())
2888template <
class Container1,
class Container2>
2890 std::optional<typename Container2::Item_Type>>>
2893 using T1 =
typename Container1::Item_Type;
2894 using T2 =
typename Container2::Item_Type;
2895 using Opt1 = std::optional<T1>;
2896 using Opt2 = std::optional<T2>;
2900 auto it2 = b.get_it();
2902 while (it1.has_curr()
and it2.has_curr())
2904 ret_val.append(std::make_pair(
Opt1(it1.get_curr()),
Opt2(it2.get_curr())));
2909 while (it1.has_curr())
2911 ret_val.append(std::make_pair(
Opt1(it1.get_curr()), std::nullopt));
2915 while (it2.has_curr())
2917 ret_val.append(std::make_pair(std::nullopt,
Opt2(it2.get_curr())));
2977 using Key = std::invoke_result_t<KeyFunc, const T &>;
2985 auto it = c.get_it();
2990 for (it.next_ne(); it.has_curr(); it.next_ne())
2992 const auto &item = it.get_curr();
3043 using Key = std::invoke_result_t<KeyFunc, const T &>;
3051 auto it = c.get_it();
3056 for (it.next_ne(); it.has_curr(); it.next_ne())
3058 const auto &item = it.get_curr();
3113 std::pair<std::invoke_result_t<KeyFunc, const T &>, std::invoke_result_t<Reducer, const DynList<T> &>>>
3115 using Key = std::invoke_result_t<KeyFunc, const T &>;
3116 using ReducedType = std::invoke_result_t<Reducer, const DynList<T> &>;
3122 for (
auto it =
groups.get_it(); it.has_curr(); it.next_ne())
3124 auto &[key,
group] = it.get_curr();
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
#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.
size_t size_t int32_t value
Doubly-linked list (defined in tpl_dynList.H).
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)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
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.
decltype(std::declval< get_it_t< C > & >().get_curr()) get_curr_t
Type of it.get_curr() on a get_it_t<C> lvalue.
const std::remove_reference_t< get_curr_t< C > > & get_curr_cref_t
Type of const auto &item = it.get_curr().
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
std::decay_t< decltype(std::declval< const C & >().get_it())> get_it_t
Type of auto it = c.get_it() for a const C &c.
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.
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.
void each(const size_t start, const size_t end, Op &op)
Execute an operation repeatedly over a range of indices.
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.
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.
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.
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.
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)
Return intersection of two containers as a DynList.
void enum_for_each(const Container &container, Operation &operation)
Apply an operation to each element and its index.
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)
Return repeated elements paired with their occurrence count.
T foldr(const Container &container, const T &init, Operation operation)
Right fold (reduce).
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
size_t remove_from_container(C &c, Args... args)
Remove multiple items from a container.
bool is_inside(const T &val, const DynList< T > &values)
Check if a value is present in a list.
std::string concat(const Args &...args)
Concatenate multiple arguments into a single std::string.
DynList< T > repeated(const Container< T > &c)
Return elements that appear more than once in the container.
const float hash_default_upper_alpha
const Container::Item_Type * max_ptr(const Container &container, Cmp cmp=Cmp())
Find the maximum element in a container.
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.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
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.
and
Check uniqueness with explicit hash + equality functors.
auto enumerate(const Container &c)
Return pairs of (element, index).
DynList< T > build_dynlist(Args... args)
Build a DynList with the given items.
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).
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.
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).
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).
auto get_curr() const
Return the current tuple (bounds-checked).
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.
and PredicateWith< Cmp &, const typename Container::Item_Type &, functional_detail::get_curr_cref_t< Container > > 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.
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.
DynList< typename Container::Item_Type > take_while(const Container &c, Pred pred)
Return elements while predicate is true (take_while).
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).
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 append_in_container(C &c, Args... args)
Append 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< T > scanl(const Container &container, const T &init, Op op)
Prefix scan with custom operation.
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.
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.
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
DynList< typename Container::Item_Type > drop_while(const Container &c, Pred pred)
Skip elements while predicate is true (drop_while).
size_t insert_in_container(C &c, Args... args)
Insert multiple items into a container.
const Container::Item_Type * min_ptr(const Container &container, Cmp cmp=Cmp())
Find the minimum element in a container.
@ Tuple
Tuple type such as (Int, Bool).
std::tuple< Container< T1 >, Container< T2 > > tunzip(const Container< std::tuple< T1, T2 > > &l)
Separate a list of tuples into two containers.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
C build_container(Args... args)
Build a container with the given items.
DynList< T > maps(const C &c, Op op)
Classic map operation.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Default filter operation (always true).
bool operator()(const T &) const noexcept
Default folding operation (returns default-constructed accumulator).
TR operator()(const TR &, const TD &) const noexcept
Default mapping operation (identity).
tgtT operator()(const srcT &item) const noexcept
Hash-based dynamic set (defined in tpl_dynSetHash.H).
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