1#ifndef SANISIZER_PRODUCT_HPP
2#define SANISIZER_PRODUCT_HPP
24template<
typename Dest_,
typename First_,
typename Second_>
25constexpr bool needs_product_check() {
30 }
else if constexpr(first_maxed == 0) {
34 constexpr auto ratio = dest_maxed /
static_cast<Dest_
>(first_maxed);
39template<
typename Dest_,
typename First_,
typename Second_>
40constexpr bool does_product_overflow_ordered(First_ first, Second_ second) {
45 }
else if (first_val == 0) {
49 const auto ratio = dest_maxed /
static_cast<Dest_
>(first_val);
54template<
typename Dest_,
typename First_,
typename Second_>
55constexpr bool does_product_overflow(First_ first, Second_ second) {
58 return does_product_overflow_ordered<Dest_>(first, second);
62 return does_product_overflow_ordered<Dest_>(second, first);
66 return does_product_overflow_ordered<Dest_>(first, second);
71 return does_product_overflow_ordered<Dest_>(second, first);
75template<
typename Dest_,
typename First_,
typename Second_>
76constexpr auto product_protected(First_ first, Second_ second) {
77 static_assert(std::is_integral<Dest_>::value);
79 if constexpr(needs_product_check<Dest_, First_, Second_>()) {
80 if (does_product_overflow<Dest_>(first, second)) {
81 return std::optional<Dest_>();
84 return std::make_optional<Dest_>(
static_cast<Dest_
>(
get_value(first)) *
static_cast<Dest_
>(
get_value(second)));
92 return std::make_optional(Constant<Dest_, maxprod>());
94 return std::make_optional<Bounded<Dest_, maxprod> >(
static_cast<Dest_
>(
get_value(first)) *
static_cast<Dest_
>(
get_value(second)));
99template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
100constexpr auto product_protected(First_ first, Second_ second, Args_... more) {
101 const auto subproduct = product_protected<Dest_>(first, second);
102 if (subproduct.has_value()) {
103 return product_protected<Dest_>(*subproduct, more...);
105 return I<decltype(product_protected<Dest_>(*subproduct, more...))>();
133template<
typename Dest_,
typename First_,
typename ... Args_>
135 const auto res = product_protected<Dest_>(first, more...);
136 if (res.has_value()) {
137 return std::make_optional<Dest_>(
get_value(*res));
139 return std::optional<Dest_>();
165template<
typename Dest_,
typename First_,
typename ... Args_>
166constexpr Dest_
product(First_ first, Args_... more) {
168 if (!res.has_value()) {
169 throw std::overflow_error(
"detected " + failure<Dest_>() +
" during multiplication");
177template<
typename Dest_,
typename First_,
typename Second_>
178constexpr Dest_ product_unprotected(First_ left, Second_ right) {
179 static_assert(std::is_integral<Dest_>::value);
183template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
184constexpr Dest_ product_unprotected(First_ left, Second_ right, Args_... more) {
185 const auto subproduct = product_unprotected<Dest_>(left, right);
186 return product_unprotected<Dest_>(subproduct, more...);
208template<
typename Dest_,
typename First_,
typename ... Args_>
210 return product_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 auto get_max()
Definition generics.hpp:39
constexpr std::optional< Dest_ > product_maybe(First_ first, Args_... more)
Definition product.hpp:134
constexpr bool is_less_than_or_equal(Left_ left, Right_ right)
Definition comparisons.hpp:75
constexpr Dest_ product_unsafe(First_ first, Args_... more)
Definition product.hpp:209
constexpr Dest_ product(First_ first, Args_... more)
Definition product.hpp:166
static constexpr bool value
Definition Constant.hpp:50