32# ifndef AH_UNI_FUNCTIONAL_H
33# define AH_UNI_FUNCTIONAL_H
71# include <type_traits>
87 namespace uni_functional_detail
102 template <
typename C>
105 return typename C::Iterator(c);
109 template <
typename T>
118 template <
typename T,
typename =
void>
121 template <
typename T>
124 using type =
typename T::value_type;
127 template <
typename T>
129 has_aleph_iterator<T>::value and not has_stl_iterator<T>::value>>
131 using type = std::decay_t<typename T::Item_Type>;
134 template <
typename T>
138 template <
typename T>
142 template <
typename T>
162 template <
typename Op,
typename Container>
166 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
167 for (
const auto & item: c)
182 template <
typename Op,
typename Container>
187 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
188 for (
const auto & item: c)
204 template <
typename Op,
typename Container>
208 using R = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>()))>;
210 std::vector<R> result;
213 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
215 result.reserve(c.size());
216 for (
const auto & item: c)
217 result.push_back(
op_ref(item));
221 result.push_back(
op_ref(it.get_curr()));
235 template <
typename Op,
typename Container>
239 using R = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<T>()))>;
241 std::vector<R> result;
245 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
247 result.reserve(c.size());
248 for (
const auto & item: c)
249 result.push_back(
op_ref(i++, item));
253 result.push_back(
op_ref(i, it.get_curr()));
267 template <
typename Pred,
typename Container>
272 std::vector<T> result;
275 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
277 for (
const auto & item: c)
279 result.push_back(item);
284 if (
const auto & item = it.get_curr();
pred_ref(item))
285 result.push_back(item);
299 template <
typename Pred,
typename Container>
304 std::vector<T> result;
308 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
309 for (
const auto & item: c)
312 result.push_back(item);
317 if (
const auto & item = it.get_curr();
pred_ref(i, item))
318 result.push_back(item);
333 template <
typename T,
typename Op,
typename Container>
339 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
340 for (
const auto & item: c)
349 template <
typename T,
typename Op,
typename Container>
365 template <
typename T,
typename Op,
typename Container>
368 std::vector<T> result;
369 result.push_back(
init);
374 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
375 for (
const auto & item: c)
378 result.push_back(
acc);
384 result.push_back(
acc);
402 template <
typename Pred,
typename Container>
406 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
408 for (
const auto & item: c)
430 template <
typename Pred,
typename Container>
434 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
436 for (
const auto & item: c)
450 template <
typename Pred,
typename Container>
461 template <
typename Pred,
typename Container>
480 template <
typename Pred,
typename Container>
486 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
488 for (
const auto & item: c)
490 return std::optional<T>(item);
495 if (
const auto & item = it.get_curr();
pred_ref(item))
496 return std::optional<T>(item);
498 return std::optional<T>{};
510 template <
typename Pred,
typename Container>
516 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
518 for (
const auto & item: c)
543 template <
typename Op,
typename Container>
547 using OptType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<T>()))>;
552 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
554 for (
const auto & item: c)
555 if (
auto result =
op_ref(i++, item))
561 if (
auto result =
op_ref(i, it.get_curr()))
576 template <
typename T,
typename Container>
579 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
581 for (
const auto & item: c)
588 if (it.get_curr() == target)
607 template <
typename Pred,
typename Container>
613 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
615 for (
const auto & item: c)
636 template <
typename Container>
639 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
665 template <
typename Container>
670 std::vector<T> result;
674 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
676 for (
const auto & item: c)
678 if (
count >= n)
break;
679 result.push_back(item);
686 result.push_back(it.get_curr());
700 template <
typename Container>
705 std::vector<T> result;
708 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
710 for (
const auto & item: c)
713 result.push_back(item);
721 result.push_back(it.get_curr());
735 template <
typename Pred,
typename Container>
740 std::vector<T> result;
743 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
745 for (
const auto & item: c)
749 result.push_back(item);
756 const auto & item = it.get_curr();
759 result.push_back(item);
774 template <
typename Pred,
typename Container>
779 std::vector<T> result;
783 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
785 for (
const auto & item: c)
790 result.push_back(item);
797 const auto & item = it.get_curr();
801 result.push_back(item);
819 template <
typename Container>
824 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
828 return std::optional<T>{};
829 return std::optional<T>(*it);
834 if (
not it.has_curr())
835 return std::optional<T>{};
836 return std::optional<T>(it.get_curr());
848 template <
typename Container>
853 std::optional<T> result;
855 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
857 for (
const auto & item: c)
863 result = it.get_curr();
877 template <
typename Container>
884 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
886 for (
const auto & item: c)
889 return std::optional<T>(item);
897 return std::optional<T>(it.get_curr());
899 return std::optional<T>{};
914 template <
typename Container>
919 std::optional<T> result;
921 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
929 for (; it != c.end(); ++it)
932 return std::optional<T>(min_val);
937 if (
not it.has_curr())
940 T min_val = it.get_curr();
942 for (; it.has_curr(); it.next_ne())
944 const auto & item = it.get_curr();
948 return std::optional<T>(min_val);
960 template <
typename Container>
965 std::optional<T> result;
967 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
975 for (; it != c.end(); ++it)
978 return std::optional<T>(max_val);
983 if (
not it.has_curr())
986 T max_val = it.get_curr();
988 for (; it.has_curr(); it.next_ne())
990 const auto & item = it.get_curr();
994 return std::optional<T>(max_val);
1006 template <
typename Container>
1010 using ResultType = std::optional<std::pair<T, T>>;
1012 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1014 auto it = c.begin();
1022 for (; it != c.end(); ++it)
1024 if (*it < min_val) min_val = *it;
1025 if (*it > max_val) max_val = *it;
1027 return ResultType(std::make_pair(min_val, max_val));
1032 if (
not it.has_curr())
1035 T min_val = it.get_curr();
1036 T max_val = min_val;
1039 for (; it.has_curr(); it.next_ne())
1041 const auto & item = it.get_curr();
1042 if (item < min_val) min_val = item;
1043 if (item > max_val) max_val = item;
1045 return ResultType(std::make_pair(min_val, max_val));
1061 template <
typename Container>
1067 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1069 for (
const auto & item: c)
1075 sum =
sum + it.get_curr();
1088 template <
typename Container>
1093 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1095 auto it = c.begin();
1096 if (it == c.end())
return T{};
1100 for (; it != c.end(); ++it)
1107 if (
not it.has_curr())
return T{};
1109 T prod = it.get_curr();
1111 for (; it.has_curr(); it.next_ne())
1130 template <
typename Pred,
typename Container>
1138 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1140 for (
const auto & item: c)
1152 const auto & item = it.get_curr();
1175 template <
typename Container1,
typename Container2>
1180 std::vector<T> result;
1182 if constexpr (uni_functional_detail::is_stl_container_v<Container1>)
1183 for (
const auto & item:
c1)
1184 result.push_back(item);
1187 result.push_back(it.get_curr());
1189 if constexpr (uni_functional_detail::is_stl_container_v<Container2>)
1190 for (
const auto & item:
c2)
1191 result.push_back(item);
1194 result.push_back(it.get_curr());
1207 template <
typename Container>
1213 std::vector<T> result;
1215 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1217 for (
const auto & inner: c)
1219 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1220 for (
const auto & item: inner)
1221 result.push_back(item);
1224 result.push_back(it.get_curr());
1231 const auto & inner = it.get_curr();
1232 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1233 for (
const auto & item: inner)
1234 result.push_back(item);
1237 result.push_back(it2.get_curr());
1253 template <
typename Op,
typename Container>
1257 using InnerContainer = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>()))>;
1260 std::vector<R> result;
1263 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1265 for (
const auto & item: c)
1267 auto inner =
op_ref(item);
1268 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1273 result.push_back(it.get_curr());
1280 auto inner =
op_ref(it.get_curr());
1281 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1286 result.push_back(it2.get_curr());
1308 template <
typename Container>
1313 std::vector<T> result;
1315 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1317 for (
const auto & item: c)
1318 if (std::find(result.begin(), result.end(), item) == result.end())
1319 result.push_back(item);
1324 if (
const auto & item = it.get_curr(); std::find(result.begin(), result.end(), item) == result.end())
1325 result.push_back(item);
1340 template <
typename Key,
typename Container>
1344 using K = std::decay_t<decltype(std::forward<Key>(key)(std::declval<T>()))>;
1346 std::vector<std::pair<K, std::vector<T>>> result;
1349 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1351 for (
const auto & item: c)
1354 auto it = std::find_if(result.begin(), result.end(),
1355 [&
k](
const auto & p) { return p.first == k; });
1356 if (it != result.end())
1357 it->second.push_back(item);
1359 result.emplace_back(std::move(
k), std::vector<T>{item});
1366 const auto & item = it.get_curr();
1368 auto res_it = std::find_if(result.begin(), result.end(),
1369 [&
k](
const auto & p) { return p.first == k; });
1370 if (
res_it != result.end())
1371 res_it->second.push_back(item);
1373 result.emplace_back(std::move(
k), std::vector<T>{item});
1388 template <
typename Container>
1393 std::vector<std::pair<T, size_t>> result;
1395 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1397 for (
const auto & item: c)
1399 auto it = std::find_if(result.begin(), result.end(),
1400 [&item](
const auto & p) { return p.first == item; });
1401 if (it != result.end())
1404 result.emplace_back(item, 1);
1411 const auto & item = it.get_curr();
1412 auto res_it = std::find_if(result.begin(), result.end(),
1413 [&item](
const auto & p) { return p.first == item; });
1414 if (
res_it != result.end())
1417 result.emplace_back(item, 1);
1436 template <
typename Container>
1441 std::vector<T> result;
1443 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1445 result.reserve(c.size());
1446 for (
const auto & item: c)
1447 result.push_back(item);
1452 result.push_back(it.get_curr());
1473 template <
typename Container1,
typename Container2>
1476 constexpr bool c1_is_stl = uni_functional_detail::is_stl_container_v<Container1>;
1477 constexpr bool c2_is_stl = uni_functional_detail::is_stl_container_v<Container2>;
1482 auto it1 =
c1.begin();
1483 auto it2 =
c2.begin();
1484 for (; it1 !=
c1.end()
and it2 !=
c2.end(); ++it1, ++it2)
1485 if (
not (*it1 == *it2))
1487 return it1 ==
c1.end()
and it2 ==
c2.end();
1492 auto it1 =
c1.begin();
1494 for (; it1 !=
c1.end()
and it2.has_curr(); ++it1, it2.next_ne())
1495 if (
not (*it1 == it2.get_curr()))
1497 return it1 ==
c1.end()
and not it2.has_curr();
1503 auto it2 =
c2.begin();
1504 for (; it1.has_curr()
and it2 !=
c2.end(); it1.next_ne(), ++it2)
1505 if (
not (it1.get_curr() == *it2))
1507 return not it1.has_curr()
and it2 ==
c2.end();
1514 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1515 if (
not (it1.get_curr() == it2.get_curr()))
1517 return not it1.has_curr()
and not it2.has_curr();
1533 template <
typename Container1,
typename Container2>
1536 constexpr bool c1_is_stl = uni_functional_detail::is_stl_container_v<Container1>;
1537 constexpr bool c2_is_stl = uni_functional_detail::is_stl_container_v<Container2>;
1542 auto it1 =
c1.begin();
1543 auto it2 =
c2.begin();
1544 for (; it1 !=
c1.end()
and it2 !=
c2.end(); ++it1, ++it2)
1546 if (*it1 < *it2)
return -1;
1547 if (*it2 < *it1)
return 1;
1549 if (it1 ==
c1.end()
and it2 ==
c2.end())
return 0;
1550 return (it1 ==
c1.end()) ? -1 : 1;
1555 auto it1 =
c1.begin();
1557 for (; it1 !=
c1.end()
and it2.has_curr(); ++it1, it2.next_ne())
1559 if (*it1 < it2.get_curr())
return -1;
1560 if (it2.get_curr() < *it1)
return 1;
1562 if (it1 ==
c1.end()
and not it2.has_curr())
return 0;
1563 return (it1 ==
c1.end()) ? -1 : 1;
1569 auto it2 =
c2.begin();
1570 for (; it1.has_curr()
and it2 !=
c2.end(); it1.next_ne(), ++it2)
1572 if (it1.get_curr() < *it2)
return -1;
1573 if (*it2 < it1.get_curr())
return 1;
1575 if (
not it1.has_curr()
and it2 ==
c2.end())
return 0;
1576 return (
not it1.has_curr()) ? -1 : 1;
1583 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1585 if (it1.get_curr() < it2.get_curr())
return -1;
1586 if (it2.get_curr() < it1.get_curr())
return 1;
1588 if (
not it1.has_curr()
and not it2.has_curr())
return 0;
1589 return (
not it1.has_curr()) ? -1 : 1;
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
size_t size_t int32_t value
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 is_stl_container_v
auto aleph_iterator(const C &c)
constexpr bool is_aleph_only_v
typename container_value_type< std::decay_t< T > >::type value_t
Main namespace for Aleph-w library functions.
T uni_reduce(T init, Op &&op, const Container &c)
Alias for uni_foldl.
auto uni_distinct(const Container &c)
Remove all duplicates (keeps first occurrence).
bool uni_none(Pred &&pred, const Container &c)
Check if no element satisfies predicate.
auto uni_filter(Pred &&pred, const Container &c)
Filter elements satisfying predicate.
auto uni_nth(size_t n, const Container &c)
Get n-th element.
int uni_compare(const Container1 &c1, const Container2 &c2)
Compare two containers lexicographically.
bool uni_equal(const Container1 &c1, const Container2 &c2)
Check equality of two containers.
std::vector< T > uni_scan_left(T init, Op &&op, const Container &c)
Scan left - fold with all intermediate results.
size_t uni_length(const Container &c)
Get container length.
auto uni_tally(const Container &c)
Count occurrences of each element (frequency count).
auto uni_flatten(const Container &c)
Flatten a container of containers.
auto uni_flat_map(Op &&op, const Container &c)
Flat map - map then flatten.
auto uni_drop_while(Pred &&pred, const Container &c)
Drop elements while predicate is true, return the rest.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
auto uni_product(const Container &c)
Product of all elements.
auto uni_find(Pred &&pred, const Container &c)
Find first element satisfying predicate.
bool uni_mem(const T &target, const Container &c)
Check if element exists in container (mem in ML).
auto uni_group_by(Key &&key, const Container &c)
Group elements by key function.
auto uni_filteri(Pred &&pred, const Container &c)
Filter with index (filteri in ML).
auto uni_map(Op &&op, const Container &c)
Map operation - transform each element.
auto uni_concat(const Container1 &c1, const Container2 &c2)
Concatenate two containers.
auto uni_last(const Container &c)
Get last element.
auto uni_min_max(const Container &c)
Get both min and max in a single pass.
auto uni_min(const Container &c)
Get minimum element.
size_t uni_count(Pred &&pred, const Container &c)
Count elements satisfying predicate.
void uni_for_each_indexed(Op &&op, const Container &c)
Apply operation to each element with index.
T uni_foldl(T init, Op &&op, const Container &c)
Left fold (foldl) - reduce from left to right.
auto uni_drop(size_t n, const Container &c)
Drop first n elements, return the rest.
auto uni_max(const Container &c)
Get maximum element.
void uni_for_each(Op &&op, const Container &c)
Apply operation to each element (for_each).
auto uni_find_mapi(Op &&op, const Container &c)
Find and map with index (find_mapi in ML).
auto uni_take_while(Pred &&pred, const Container &c)
Take elements while predicate is true.
bool uni_all(Pred &&pred, const Container &c)
Check if all elements satisfy predicate.
auto uni_first(const Container &c)
Get first element.
auto uni_partition(Pred &&pred, const Container &c)
Partition elements by predicate.
static std::atomic< bool > init
auto uni_to_vector(const Container &c)
Convert container to std::vector.
auto uni_mapi(Op &&op, const Container &c)
Map with index (mapi in ML).
bool uni_any(Pred &&pred, const Container &c)
Alias for uni_exists.
auto uni_take(size_t n, const Container &c)
Take first n elements.
auto uni_sum(const Container &c)
Sum all elements.
bool uni_exists(Pred &&pred, const Container &c)
Check if any element satisfies predicate.
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.
std::optional< size_t > uni_find_index(Pred &&pred, const Container &c)
Find index of first element satisfying predicate.
typename T::value_type type
std::decay_t< typename T::Item_Type > type