[ci] Enable IRC notifications from travis
[xapian.git] / xapian-core / common / overflow.h
blob84f19d474b46efee4b085c1c6dbc6f6590783cb3
1 /** @file overflow.h
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.
7 */
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
28 #ifndef PACKAGE
29 # error config.h must be included first in each C++ source file
30 #endif
32 #include <type_traits>
34 /** Addition with overflow checking.
36 * Add @a a and @a b in infinite precision, and store the result in
37 * @a res.
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
45 * otherwise.
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);
54 #else
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
57 // it.
58 R r = R(a) + R(b);
59 res = r;
60 return (sizeof(R) <= sizeof(T1) || sizeof(R) <= sizeof(T2)) && r < R(b);
61 #endif
64 /** Multiplication with overflow checking.
66 * Multiply @a a and @a b in infinite precision, and store the result in
67 * @a res.
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
75 * otherwise.
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);
84 #else
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
87 // it.
88 R r = R(a) * R(b);
89 res = r;
90 return sizeof(R) < sizeof(T1) + sizeof(T2) && a != 0 && T2(r / R(a)) != b;
91 #endif
94 #endif // XAPIAN_INCLUDED_OVERFLOW_H