| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright 2021 Minoru Sekine | ||
| 3 | // | ||
| 4 | // This file is part of libsatop. | ||
| 5 | // | ||
| 6 | // libsatop is free software: you can redistribute it and/or modify | ||
| 7 | // it under the terms of the GNU Lesser General Public License as published by | ||
| 8 | // the Free Software Foundation, either version 3 of the License, or | ||
| 9 | // (at your option) any later version. | ||
| 10 | // | ||
| 11 | // libsatop is distributed in the hope that it will be useful, | ||
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | // GNU Lesser General Public License for more details. | ||
| 15 | // | ||
| 16 | // You should have received a copy of the GNU Lesser General Public License | ||
| 17 | // along with libsatop. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | #ifndef INCLUDE_SATOP_SUB_PRIV_H_ | ||
| 20 | #define INCLUDE_SATOP_SUB_PRIV_H_ | ||
| 21 | |||
| 22 | #ifndef SATOP_INTERNAL | ||
| 23 | #error Do not include this file directly, libsatop.h instead. | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #include <limits> | ||
| 27 | #include <type_traits> | ||
| 28 | |||
| 29 | namespace saturated { | ||
| 30 | |||
| 31 | namespace impl { | ||
| 32 | |||
| 33 | template <typename T> | ||
| 34 | 72 | constexpr bool is_sub_underflow( | |
| 35 | T x, | ||
| 36 | typename std::enable_if<std::is_signed<T>::value, T>::type y) { | ||
| 37 | return ((x < 0) | ||
| 38 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 11 times.
|
42 | && (y > 0) |
| 39 |
4/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 15 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 5 times.
|
114 | && (x < std::numeric_limits<T>::lowest() + y)); |
| 40 | } | ||
| 41 | |||
| 42 | template <typename T> | ||
| 43 | 24 | constexpr bool is_sub_underflow( | |
| 44 | T x, | ||
| 45 | typename std::enable_if<std::is_unsigned<T>::value, T>::type y) { | ||
| 46 | 24 | return (x < y); | |
| 47 | } | ||
| 48 | |||
| 49 | template <typename T> | ||
| 50 | 80 | constexpr bool is_sub_overflow(T x, T y) { | |
| 51 | return ((x > 0) | ||
| 52 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
18 | && (y < 0) |
| 53 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 2 times.
|
98 | && (x > std::numeric_limits<T>::max() + y)); |
| 54 | } | ||
| 55 | |||
| 56 | } // namespace impl | ||
| 57 | |||
| 58 | /// @addtogroup libsatop | ||
| 59 | /// | ||
| 60 | /// @{ | ||
| 61 | |||
| 62 | /// Subtract 2 values with saturation. | ||
| 63 | /// | ||
| 64 | /// @tparam T Type of arguments and the return value | ||
| 65 | /// | ||
| 66 | /// @param x Subtract from this value | ||
| 67 | /// @param y Subtract this value | ||
| 68 | /// | ||
| 69 | /// | ||
| 70 | /// @return If subtraction results causes overflow, returns max of T. | ||
| 71 | /// If underflow, returns min(lowest) of T. | ||
| 72 | /// If no overflow and no underflow, returns x - y. | ||
| 73 | template <typename T> | ||
| 74 | 48 | constexpr T sub(T x, T y) { | |
| 75 | 48 | return (impl::is_sub_underflow(x, y) | |
| 76 | 88 | ? std::numeric_limits<T>::lowest() | |
| 77 | 40 | : (impl::is_sub_overflow(x, y) | |
| 78 | 40 | ? std::numeric_limits<T>::max() | |
| 79 | 56 | : static_cast<T>(x - y))); | |
| 80 | } | ||
| 81 | |||
| 82 | /// @} | ||
| 83 | |||
| 84 | } // namespace saturated | ||
| 85 | |||
| 86 | #endif // INCLUDE_SATOP_SUB_PRIV_H_ | ||
| 87 |