Optional Two-phase heap tracing
[hiphop-php.git] / hphp / util / overflow.h
blob096c133c1fc6f303c07a30c8d3edfbb3337d9a81
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_UTIL_OVERFLOW_H
18 #define incl_HPHP_UTIL_OVERFLOW_H
20 namespace HPHP {
22 template<typename T>
23 typename std::enable_if<std::is_integral<T>::value, bool>::type
24 add_overflow(T a, T b) {
25 // Cast to unsigned so that ua + ub isn't undefined.
26 auto const ua = static_cast<typename std::make_unsigned<T>::type>(a);
27 auto const ub = static_cast<typename std::make_unsigned<T>::type>(b);
29 // Overflow if the inputs have the same sign, and the result of addition has
30 // the opposite sign.
31 return (~(ua ^ ub) & (ua ^ (ua + ub))) >> std::numeric_limits<T>::digits;
34 template<typename T>
35 typename std::enable_if<std::is_integral<T>::value, bool>::type
36 sub_overflow(T a, T b) {
37 if (b == std::numeric_limits<T>::min()) {
38 // a - (INT_MIN) --> a - (-huge) --> a + huge
39 return a >= 0;
41 return add_overflow(a, -b);
44 template<typename T>
45 typename std::enable_if<std::is_integral<T>::value, bool>::type
46 mul_overflow(T a, T b) {
47 auto max = std::numeric_limits<T>::max();
48 auto min = std::numeric_limits<T>::min();
50 // Handle bad div cases first.
51 if (a == 0 || b == 0) {
52 return false;
54 if ((a == min && b == -1) || (b == min && a == -1)) {
55 return true;
58 if (a > 0) {
59 if (b > 0) {
60 return a > max / b;
61 } else {
62 return b < min / a;
64 } else {
65 if (b < 0) {
66 return a < max / b;
67 } else {
68 return a < min / b;
75 #endif