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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H 10 #define _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H 11 12 #include <__config> 13 #include <cmath> 14 #include <limits> 15 #include <type_traits> 16 17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 18 # pragma GCC system_header 19 #endif 20 21 _LIBCPP_PUSH_MACROS 22 #include <__undef_macros> 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 template <class _IntT, class _FloatT, 27 bool _FloatBigger = (numeric_limits<_FloatT>::digits > numeric_limits<_IntT>::digits), 28 int _Bits = (numeric_limits<_IntT>::digits - numeric_limits<_FloatT>::digits)> 29 _LIBCPP_INLINE_VISIBILITY 30 _LIBCPP_CONSTEXPR _IntT __max_representable_int_for_float() _NOEXCEPT { 31 static_assert(is_floating_point<_FloatT>::value, "must be a floating point type"); 32 static_assert(is_integral<_IntT>::value, "must be an integral type"); 33 static_assert(numeric_limits<_FloatT>::radix == 2, "FloatT has incorrect radix"); 34 static_assert((_IsSame<_FloatT, float>::value || _IsSame<_FloatT, double>::value 35 || _IsSame<_FloatT,long double>::value), "unsupported floating point type"); 36 return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits); 37 } 38 39 // Convert a floating point number to the specified integral type after 40 // clamping to the integral type's representable range. 41 // 42 // The behavior is undefined if `__r` is NaN. 43 template <class _IntT, class _RealT> 44 _LIBCPP_INLINE_VISIBILITY 45 _IntT __clamp_to_integral(_RealT __r) _NOEXCEPT { 46 using _Lim = numeric_limits<_IntT>; 47 const _IntT _MaxVal = __max_representable_int_for_float<_IntT, _RealT>(); 48 if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) { 49 return _Lim::max(); 50 } else if (__r <= _Lim::lowest()) { 51 return _Lim::min(); 52 } 53 return static_cast<_IntT>(__r); 54 } 55 56 _LIBCPP_END_NAMESPACE_STD 57 58 _LIBCPP_POP_MACROS 59 60 #endif // _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H 61