1#ifndef SANISIZER_SUM_HPP
2#define SANISIZER_SUM_HPP
24template<
typename Dest_,
typename First_,
typename Second_>
25constexpr bool needs_sum_check() {
31 constexpr Dest_ delta = dest_maxed -
static_cast<Dest_
>(first_maxed);
36template<
typename Dest_,
typename First_,
typename Second_>
37constexpr bool does_sum_overflow_ordered(First_ first, Second_ second) {
43 const Dest_ delta = dest_maxed -
static_cast<Dest_
>(first_val);
48template<
typename Dest_,
typename First_,
typename Second_>
49constexpr bool does_sum_overflow(First_ first, Second_ second) {
52 return does_sum_overflow_ordered<Dest_>(first, second);
56 return does_sum_overflow_ordered<Dest_>(second, first);
60 return does_sum_overflow_ordered<Dest_>(first, second);
65 return does_sum_overflow_ordered<Dest_>(second, first);
69template<
typename Dest_,
typename First_,
typename Second_>
70constexpr auto sum_protected(First_ first, Second_ second) {
71 static_assert(std::is_integral<Dest_>::value);
73 if constexpr(needs_sum_check<Dest_, First_, Second_>()) {
74 if (does_sum_overflow<Dest_>(first, second)) {
75 return std::optional<Dest_>();
78 return std::make_optional<Dest_>(
static_cast<Dest_
>(
get_value(first)) +
static_cast<Dest_
>(
get_value(second)));
86 return std::make_optional(Constant<Dest_, maxsum>());
88 return std::make_optional<Bounded<Dest_, maxsum> >(
static_cast<Dest_
>(
get_value(first)) +
static_cast<Dest_
>(
get_value(second)));
93template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
94constexpr auto sum_protected(First_ first, Second_ second, Args_... more) {
95 const auto subsum = sum_protected<Dest_>(first, second);
96 if (subsum.has_value()) {
97 return sum_protected<Dest_>(*subsum, more...);
99 return I<decltype(sum_protected<Dest_>(*subsum, more...))>();
124template<
typename Dest_,
typename First_,
typename ... Args_>
125constexpr std::optional<Dest_>
sum_maybe(First_ first, Args_... more) {
126 const auto res = sum_protected<Dest_>(first, more...);
127 if (res.has_value()) {
128 return std::make_optional<Dest_>(
get_value(*res));
130 return std::optional<Dest_>();
152template<
typename Dest_,
typename First_,
typename ... Args_>
153constexpr Dest_
sum(First_ first, Args_... more) {
155 if (!res.has_value()) {
156 throw std::overflow_error(
"detected " + failure<Dest_>() +
" during summation");
172template<
typename Dest_,
typename Value_>
188template<
typename Integer_>
197template<
typename Dest_,
typename First_,
typename Second_>
198constexpr Dest_ sum_unprotected(First_ first, Second_ second) {
199 static_assert(std::is_integral<Dest_>::value);
203template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
204constexpr Dest_ sum_unprotected(First_ first, Second_ second, Args_... more) {
205 const auto subsum = sum_unprotected<Dest_>(first, second);
206 return sum_unprotected<Dest_>(subsum, more...);
228template<
typename Dest_,
typename First_,
typename ... Args_>
230 return sum_unprotected<Dest_>(first, more...);
Specify compile-time bounds on integers.
Specify a constant integer.
Signedness-safe integer comparisons.
Generics for operating on integer representations.
Sanitize sizes to avoid integer overflow.
Definition Bounded.hpp:15
constexpr bool is_greater_than(Left_ left, Right_ right)
Definition comparisons.hpp:91
constexpr auto get_value(const Value_ x)
Definition generics.hpp:23
constexpr Dest_ sum_unsafe(First_ first, Args_... more)
Definition sum.hpp:229
constexpr auto get_max()
Definition generics.hpp:39
constexpr std::optional< Dest_ > sum_maybe(First_ first, Args_... more)
Definition sum.hpp:125
constexpr bool is_less_than_or_equal(Left_ left, Right_ right)
Definition comparisons.hpp:75
constexpr Dest_ sum(First_ first, Args_... more)
Definition sum.hpp:153
Dest_ plus_one(Value_ x)
Definition sum.hpp:173
Integer_ & increment(Integer_ &x)
Definition sum.hpp:189
Integer constant.
Definition Constant.hpp:24
static constexpr bool value
Definition Constant.hpp:50