21template<
typename Dest_,
typename First_,
typename Second_>
22constexpr bool needs_sum_check() {
23 constexpr Dest_ dest_maxed = std::numeric_limits<Dest_>::max();
25 if constexpr(as_unsigned(first_maxed) > as_unsigned(dest_maxed)) {
28 constexpr Dest_ delta = dest_maxed -
static_cast<Dest_
>(first_maxed);
30 return as_unsigned(second_maxed) > as_unsigned(delta);
34template<
typename Dest_,
typename First_,
typename Second_>
35constexpr auto sum_protected(First_ first, Second_ second) {
40 const Dest_ second_val =
get_value(second);
42 if constexpr(needs_sum_check<Dest_, First_, Second_>()) {
43 static_assert(std::is_integral<Dest_>::value);
44 constexpr Dest_ dest_maxed = std::numeric_limits<Dest_>::max();
45 if (
static_cast<Dest_
>(dest_maxed - first_val) < second_val) {
46 throw std::overflow_error(
"overflow detected in sanisizer::sum");
56template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
57constexpr auto sum_protected(First_ first, Second_ second, Args_... more) {
58 const auto subsum = sum_protected<Dest_>(first, second);
59 return sum_protected<Dest_>(subsum, more...);
62template<
typename Dest_,
typename First_,
typename Second_>
63constexpr Dest_ sum_unprotected(First_ first, Second_ second) {
64 static_assert(std::is_integral<Dest_>::value);
65 static_assert(std::is_integral<First_>::value);
66 static_assert(std::is_integral<Second_>::value);
67 return static_cast<Dest_
>(first) +
static_cast<Dest_
>(second);
70template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
71constexpr Dest_ sum_unprotected(First_ first, Second_ second, Args_... more) {
72 const auto subsum = sum_unprotected<Dest_>(first, second);
73 return sum_unprotected<Dest_>(subsum, more...);
95template<
typename Dest_,
typename First_,
typename ... Args_>
96constexpr Dest_
sum(First_ first, Args_... more) {
97 return get_value(sum_protected<Dest_>(first, more...));
113template<
typename Dest_,
typename First_,
typename ... Args_>
115 return sum_unprotected<Dest_>(first, more...);
121template<
typename Dest_,
typename First_,
typename Second_>
122constexpr bool needs_product_check() {
123 constexpr Dest_ dest_maxed = std::numeric_limits<Dest_>::max();
125 if constexpr(as_unsigned(first_maxed) > as_unsigned(dest_maxed)) {
127 }
else if constexpr(first_maxed == 0) {
130 constexpr auto ratio = dest_maxed / first_maxed;
132 return as_unsigned(second_maxed) > as_unsigned(ratio);
136template<
typename Dest_,
typename First_,
typename Second_>
137constexpr auto product_protected(First_ first, Second_ second) {
139 const Dest_ first_val =
get_value(first);
142 const Dest_ second_val =
get_value(second);
144 if constexpr(needs_product_check<Dest_, First_, Second_>()) {
145 static_assert(std::is_integral<Dest_>::value);
146 constexpr Dest_ dest_maxed = std::numeric_limits<Dest_>::max();
147 if (first_val &&
static_cast<Dest_
>(dest_maxed / first_val) < second_val) {
148 throw std::overflow_error(
"overflow detected in sanisizer::product");
150 return Attestation<Dest_, dest_maxed>(
static_cast<Dest_
>(first_val * second_val));
154 return Attestation<Dest_, maxprod>(
static_cast<Dest_
>(first_val * second_val));
158template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
159constexpr auto product_protected(First_ first, Second_ second, Args_... more) {
160 const auto subproduct = product_protected<Dest_>(first, second);
161 return product_protected<Dest_>(subproduct, more...);
164template<
typename Dest_,
typename First_,
typename Second_>
165constexpr Dest_ product_unprotected(First_ left, Second_ right) {
166 static_assert(std::is_integral<Dest_>::value);
167 static_assert(std::is_integral<First_>::value);
168 static_assert(std::is_integral<Second_>::value);
169 return static_cast<Dest_
>(left) *
static_cast<Dest_
>(right);
172template<
typename Dest_,
typename First_,
typename Second_,
typename ... Args_>
173constexpr Dest_ product_unprotected(First_ left, Second_ right, Args_... more) {
174 const auto subproduct = product_unprotected<Dest_>(left, right);
175 return product_unprotected<Dest_>(subproduct, more...);
201template<
typename Dest_,
typename First_,
typename ... Args_>
202constexpr Dest_
product(First_ first, Args_... more) {
203 return get_value(product_protected<Dest_>(first, more...));
218template<
typename Dest_,
typename First_,
typename ... Args_>
220 return product_unprotected<Dest_>(first, more...);