1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once


#include <functional><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <utility>
#include <type_traits><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <optional><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "internal/dev_env.hpp"
#include "internal/type_traits.hpp"

#include "utility/internal/functional_base.hpp"

#include "numeric/internal/mod.hpp"
#include "numeric/arithmetic.hpp"

#include "global/constants.hpp"


namespace uni {

namespace internal {


template<class T> constexpr T plus(const T a, const T b) noexcept(NO_EXCEPT) { return std::plus<T>{}(a, b); }
template<class T> constexpr T minus(const T a, const T b) noexcept(NO_EXCEPT) { return std::minus<T>{}(a, b); }

template<class T> constexpr T bit_xor(const T a, const T b) noexcept(NO_EXCEPT) { return a xor b; }


} // namespace internal


template<class T, class U> inline auto to_optional_if_equal(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> {
    return v == ill ? std::optional<T>{} : std::optional<T>(v);
}
template<class T, class U> inline auto to_optional_if_over(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> {
    return v > ill ? std::optional<T>{} : std::optional<T>(v);
}
template<class T, class U> inline auto to_optional_if_or_over(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> {
    return v >= ill ? std::optional<T>{} : std::optional<T>(v);
}
template<class T, class U> inline auto to_optional_if_under(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> {
    return v < ill ? std::optional<T>{} : std::optional<T>(v);
}
template<class T, class U> inline auto to_optional_if_or_under(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> {
    return v <= ill ? std::optional<T>{} : std::optional<T>(v);
}

template<class T, class F> inline auto to_optional_if(const T& v, F&& f) noexcept(NO_EXCEPT) -> decltype(f(v), std::optional<T>{}){
    return f(v) ? std::optional<T>{} : std::optional<T>(v);
}

template<class T, class U> inline bool chmin(T &a, const U& b) noexcept(NO_EXCEPT) { return (a>b ? a=b, true : false); }
template<class T, class U> inline bool chmax(T &a, const U& b) noexcept(NO_EXCEPT) { return (a<b ? a=b, true : false); }

template<class T, class... Ts> inline bool chmin(T &a, Ts... b) noexcept(NO_EXCEPT) { return chmin(a, min(b...)); }
template<class T, class... Ts> inline bool chmax(T &a, Ts... b) noexcept(NO_EXCEPT) { return chmax(a, max(b...)); }

template<class... Ts>
inline constexpr std::common_type_t<Ts...> tuple_sum(const std::tuple<Ts...>& tuple, const std::common_type_t<Ts...>& base = std::common_type_t<Ts...>()) noexcept(NO_EXCEPT) {
    std::common_type_t<Ts...> res = base;
    tuple_for_each(tuple, [&](const auto& v) constexpr { res += v; });
    return res;
}

template<class... Ts>
inline constexpr std::common_type_t<Ts...> min_element(const std::tuple<Ts...>& tuple) noexcept(NO_EXCEPT) {
    return std::apply([&](auto&&... v) constexpr { return min(v...); }, tuple);
}


template<class... Ts>
inline constexpr std::common_type_t<Ts...> max_element(const std::tuple<Ts...>& tuple) noexcept(NO_EXCEPT) {;
    return std::apply([&](auto&&... v) constexpr { return max(v...); }, tuple);
}


template<interval_notation INTERVAL, class T0, class T1, class T2>
inline constexpr bool in_range(const T0& x, const T1& l, const T2& r) noexcept(NO_EXCEPT) {
    if constexpr(INTERVAL == interval_notation::right_open) return l <= x and x < r;
    else if constexpr(INTERVAL == interval_notation::left_open) return l < x and x <= r;
    else if constexpr(INTERVAL == interval_notation::open) return l < x and x < r;
    return l <= x and x <= r;
}

template<class F, class Tuple>
constexpr void tuple_for_each(F&& f, Tuple&& tuple) {
    std::apply(
        [&]<class... Ts>(Ts&&... elems) {
            (std::invoke(f, std::forward<Ts>(elems)), ...);
        },
        std::forward<Tuple>(tuple)
    );
}


template<class F, class Tuple>
constexpr auto tuple_transform(F&& f, Tuple&& tuple) {
    return std::apply(
        [&]<class...Ts>(Ts&&... elems) {
            return internal::tuple_or_pair_t<std::invoke_result_t<F&,Ts>...>(
                std::invoke(f, std::forward<Ts>(elems))...
            );
        },
        std::forward<Tuple>(tuple)
    );
}


} // namespace uni