2 * @brief Arithmetic operations with overflow checks
4 * The operations are implemented with compiler builtins or equivalent where
5 * possible, so the overflow check will typically just require a check of the
6 * processor's overflow or carry flag.
8 /* Copyright (C) 2018 Olly Betts
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #ifndef XAPIAN_INCLUDED_OVERFLOW_H
26 #define XAPIAN_INCLUDED_OVERFLOW_H
29 # error config.h must be included first in each C++ source file
32 #include <type_traits>
34 /** Addition with overflow checking.
36 * Add @a a and @a b in infinite precision, and store the result in
39 * Where possible, compiler built-ins or intrinsics are used to try to ensure
40 * minimal overhead from the overflow check.
42 * Currently only supported when types involved are unsigned.
44 * @return true if the result can be represented exactly in @a res, false
47 template<typename T1
, typename T2
, typename R
>
48 typename
std::enable_if
<std::is_unsigned
<T1
>::value
&&
49 std::is_unsigned
<T2
>::value
&&
50 std::is_unsigned
<R
>::value
, bool>::type
51 add_overflows(T1 a
, T2 b
, R
& res
) {
52 #if HAVE_DECL___BUILTIN_ADD_OVERFLOW
53 return __builtin_add_overflow(a
, b
, &res
);
55 // Use a local variable to test for overflow so we don't need to worry if
56 // res could be modified by another thread between us setting and testing
60 return (sizeof(R
) <= sizeof(T1
) || sizeof(R
) <= sizeof(T2
)) && r
< R(b
);
64 /** Multiplication with overflow checking.
66 * Multiply @a a and @a b in infinite precision, and store the result in
69 * Where possible, compiler built-ins or intrinsics are used to try to ensure
70 * minimal overhead from the overflow check.
72 * Currently only supported when types involved are unsigned.
74 * @return true if the result can be represented exactly in @a res, false
77 template<typename T1
, typename T2
, typename R
>
78 typename
std::enable_if
<std::is_unsigned
<T1
>::value
&&
79 std::is_unsigned
<T2
>::value
&&
80 std::is_unsigned
<R
>::value
, bool>::type
81 mul_overflows(T1 a
, T2 b
, R
& res
) {
82 #if HAVE_DECL___BUILTIN_MUL_OVERFLOW
83 return __builtin_mul_overflow(a
, b
, &res
);
85 // Use a local variable to test for overflow so we don't need to worry if
86 // res could be modified by another thread between us setting and testing
90 return sizeof(R
) < sizeof(T1
) + sizeof(T2
) && a
!= 0 && T2(r
/ R(a
)) != b
;
94 #endif // XAPIAN_INCLUDED_OVERFLOW_H