Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-11 10:26:10

0001 //========================================================================
0002 //
0003 // GooCheckedOps.h
0004 //
0005 // This file is licensed under the GPLv2 or later
0006 //
0007 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
0008 // Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
0009 // Copyright (C) 2019-2021 Albert Astals Cid <aacid@kde.org>
0010 //
0011 //========================================================================
0012 
0013 #ifndef GOO_CHECKED_OPS_H
0014 #define GOO_CHECKED_OPS_H
0015 
0016 #include <limits>
0017 #include <type_traits>
0018 
0019 template<typename T>
0020 inline bool checkedAssign(long long lz, T *z)
0021 {
0022     static_assert((std::numeric_limits<long long>::max)() > (std::numeric_limits<T>::max)(), "The max of long long type must be larger to perform overflow checks.");
0023     static_assert((std::numeric_limits<long long>::min)() < (std::numeric_limits<T>::min)(), "The min of long long type must be smaller to perform overflow checks.");
0024 
0025     if (lz > (std::numeric_limits<T>::max)() || lz < (std::numeric_limits<T>::min)()) {
0026         return true;
0027     }
0028 
0029     *z = static_cast<T>(lz);
0030     return false;
0031 }
0032 
0033 #ifndef __has_builtin
0034 #    define __has_builtin(x) 0
0035 #endif
0036 
0037 template<typename T>
0038 inline bool checkedAdd(T x, T y, T *z)
0039 {
0040 // The __GNUC__ checks can not be removed until we depend on GCC >= 10.1
0041 // which is the first version that returns true for __has_builtin(__builtin_add_overflow)
0042 #if __GNUC__ >= 5 || __has_builtin(__builtin_add_overflow)
0043     return __builtin_add_overflow(x, y, z);
0044 #else
0045     const auto lz = static_cast<long long>(x) + static_cast<long long>(y);
0046     return checkedAssign(lz, z);
0047 #endif
0048 }
0049 
0050 template<>
0051 inline bool checkedAdd<long long>(long long x, long long y, long long *z)
0052 {
0053 #if __GNUC__ >= 5 || __has_builtin(__builtin_add_overflow)
0054     return __builtin_add_overflow(x, y, z);
0055 #else
0056     if (x > 0 && y > 0) {
0057         if (x > (std::numeric_limits<long long>::max)() - y) {
0058             return true;
0059         }
0060     } else if (x < 0 && y < 0) {
0061         if (x < (std::numeric_limits<long long>::min)() - y) {
0062             return true;
0063         }
0064     }
0065     *z = x + y;
0066     return false;
0067 #endif
0068 }
0069 
0070 template<typename T>
0071 inline bool checkedSubtraction(T x, T y, T *z)
0072 {
0073 #if __GNUC__ >= 5 || __has_builtin(__builtin_sub_overflow)
0074     return __builtin_sub_overflow(x, y, z);
0075 #else
0076     const auto lz = static_cast<long long>(x) - static_cast<long long>(y);
0077     return checkedAssign(lz, z);
0078 #endif
0079 }
0080 
0081 template<typename T>
0082 inline bool checkedMultiply(T x, T y, T *z)
0083 {
0084 #if __GNUC__ >= 5 || __has_builtin(__builtin_mul_overflow)
0085     return __builtin_mul_overflow(x, y, z);
0086 #else
0087     const auto lz = static_cast<long long>(x) * static_cast<long long>(y);
0088     return checkedAssign(lz, z);
0089 #endif
0090 }
0091 
0092 template<>
0093 inline bool checkedMultiply<long long>(long long x, long long y, long long *z)
0094 {
0095 #if __GNUC__ >= 5 || __has_builtin(__builtin_mul_overflow)
0096     return __builtin_mul_overflow(x, y, z);
0097 #else
0098     if (x != 0 && (std::numeric_limits<long long>::max)() / x < y) {
0099         return true;
0100     }
0101 
0102     *z = x * y;
0103     return false;
0104 #endif
0105 }
0106 
0107 template<typename T>
0108 inline T safeAverage(T a, T b)
0109 {
0110     static_assert((std::numeric_limits<long long>::max)() > (std::numeric_limits<T>::max)(), "The max of long long type must be larger to perform overflow checks.");
0111     static_assert((std::numeric_limits<long long>::min)() < (std::numeric_limits<T>::min)(), "The min of long long type must be smaller to perform overflow checks.");
0112 
0113     return static_cast<T>((static_cast<long long>(a) + static_cast<long long>(b)) / 2);
0114 }
0115 
0116 #endif // GOO_CHECKED_OPS_H