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 25template <class _IntT, 26 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_HIDE_FROM_ABI _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( 34 (_IsSame<_FloatT, float>::value || _IsSame<_FloatT, double>::value || _IsSame<_FloatT, long double>::value), 35 "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. 43template <class _IntT, class _RealT> 44_LIBCPP_HIDE_FROM_ABI _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