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