Path: blob/main/contrib/llvm-project/libcxx/include/__numeric/saturation_arithmetic.h
35233 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___NUMERIC_SATURATION_ARITHMETIC_H10#define _LIBCPP___NUMERIC_SATURATION_ARITHMETIC_H1112#include <__assert>13#include <__concepts/arithmetic.h>14#include <__config>15#include <__utility/cmp.h>16#include <limits>1718#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)19# pragma GCC system_header20#endif2122_LIBCPP_PUSH_MACROS23#include <__undef_macros>2425_LIBCPP_BEGIN_NAMESPACE_STD2627#if _LIBCPP_STD_VER >= 202829template <__libcpp_integer _Tp>30_LIBCPP_HIDE_FROM_ABI constexpr _Tp __add_sat(_Tp __x, _Tp __y) noexcept {31if (_Tp __sum; !__builtin_add_overflow(__x, __y, &__sum))32return __sum;33// Handle overflow34if constexpr (__libcpp_unsigned_integer<_Tp>) {35return std::numeric_limits<_Tp>::max();36} else {37// Signed addition overflow38if (__x > 0)39// Overflows if (x > 0 && y > 0)40return std::numeric_limits<_Tp>::max();41else42// Overflows if (x < 0 && y < 0)43return std::numeric_limits<_Tp>::min();44}45}4647template <__libcpp_integer _Tp>48_LIBCPP_HIDE_FROM_ABI constexpr _Tp __sub_sat(_Tp __x, _Tp __y) noexcept {49if (_Tp __sub; !__builtin_sub_overflow(__x, __y, &__sub))50return __sub;51// Handle overflow52if constexpr (__libcpp_unsigned_integer<_Tp>) {53// Overflows if (x < y)54return std::numeric_limits<_Tp>::min();55} else {56// Signed subtration overflow57if (__x >= 0)58// Overflows if (x >= 0 && y < 0)59return std::numeric_limits<_Tp>::max();60else61// Overflows if (x < 0 && y > 0)62return std::numeric_limits<_Tp>::min();63}64}6566template <__libcpp_integer _Tp>67_LIBCPP_HIDE_FROM_ABI constexpr _Tp __mul_sat(_Tp __x, _Tp __y) noexcept {68if (_Tp __mul; !__builtin_mul_overflow(__x, __y, &__mul))69return __mul;70// Handle overflow71if constexpr (__libcpp_unsigned_integer<_Tp>) {72return std::numeric_limits<_Tp>::max();73} else {74// Signed multiplication overflow75if ((__x > 0 && __y > 0) || (__x < 0 && __y < 0))76return std::numeric_limits<_Tp>::max();77// Overflows if (x < 0 && y > 0) || (x > 0 && y < 0)78return std::numeric_limits<_Tp>::min();79}80}8182template <__libcpp_integer _Tp>83_LIBCPP_HIDE_FROM_ABI constexpr _Tp __div_sat(_Tp __x, _Tp __y) noexcept {84_LIBCPP_ASSERT_UNCATEGORIZED(__y != 0, "Division by 0 is undefined");85if constexpr (__libcpp_unsigned_integer<_Tp>) {86return __x / __y;87} else {88// Handle signed division overflow89if (__x == std::numeric_limits<_Tp>::min() && __y == _Tp{-1})90return std::numeric_limits<_Tp>::max();91return __x / __y;92}93}9495template <__libcpp_integer _Rp, __libcpp_integer _Tp>96_LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturate_cast(_Tp __x) noexcept {97// Saturation is impossible edge case when ((min _Rp) < (min _Tp) && (max _Rp) > (max _Tp)) and it is expected to be98// optimized out by the compiler.99100// Handle overflow101if (std::cmp_less(__x, std::numeric_limits<_Rp>::min()))102return std::numeric_limits<_Rp>::min();103if (std::cmp_greater(__x, std::numeric_limits<_Rp>::max()))104return std::numeric_limits<_Rp>::max();105// No overflow106return static_cast<_Rp>(__x);107}108109#endif // _LIBCPP_STD_VER >= 20110111#if _LIBCPP_STD_VER >= 26112113template <__libcpp_integer _Tp>114_LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept {115return std::__add_sat(__x, __y);116}117118template <__libcpp_integer _Tp>119_LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept {120return std::__sub_sat(__x, __y);121}122123template <__libcpp_integer _Tp>124_LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept {125return std::__mul_sat(__x, __y);126}127128template <__libcpp_integer _Tp>129_LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept {130return std::__div_sat(__x, __y);131}132133template <__libcpp_integer _Rp, __libcpp_integer _Tp>134_LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept {135return std::__saturate_cast<_Rp>(__x);136}137138#endif // _LIBCPP_STD_VER >= 26139140_LIBCPP_END_NAMESPACE_STD141142_LIBCPP_POP_MACROS143144#endif // _LIBCPP___NUMERIC_SATURATION_ARITHMETIC_H145146147