1 //===-- Conversion between floating-point types -----------------*- C++ -*-===// 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 LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H 10 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H 11 12 #include "FPBits.h" 13 #include "dyadic_float.h" 14 #include "hdr/fenv_macros.h" 15 #include "src/__support/CPP/algorithm.h" 16 #include "src/__support/CPP/type_traits.h" 17 #include "src/__support/macros/properties/types.h" 18 19 namespace LIBC_NAMESPACE::fputil { 20 21 template <typename OutType, typename InType> 22 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> && 23 cpp::is_floating_point_v<InType>, 24 OutType> cast(InType x)25cast(InType x) { 26 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION) 27 if constexpr (cpp::is_same_v<OutType, float16> || 28 cpp::is_same_v<InType, float16>) { 29 using InFPBits = FPBits<InType>; 30 using InStorageType = typename InFPBits::StorageType; 31 using OutFPBits = FPBits<OutType>; 32 using OutStorageType = typename OutFPBits::StorageType; 33 34 InFPBits x_bits(x); 35 36 if (x_bits.is_nan()) { 37 if (x_bits.is_signaling_nan()) { 38 raise_except_if_required(FE_INVALID); 39 return OutFPBits::quiet_nan().get_val(); 40 } 41 42 InStorageType x_mant = x_bits.get_mantissa(); 43 if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN) 44 x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN; 45 return OutFPBits::quiet_nan(x_bits.sign(), 46 static_cast<OutStorageType>(x_mant)) 47 .get_val(); 48 } 49 50 if (x_bits.is_inf()) 51 return OutFPBits::inf(x_bits.sign()).get_val(); 52 53 constexpr size_t MAX_FRACTION_LEN = 54 cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN); 55 DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x); 56 return xd.template as<OutType, /*ShouldSignalExceptions=*/true>(); 57 } 58 #endif 59 60 return static_cast<OutType>(x); 61 } 62 63 } // namespace LIBC_NAMESPACE::fputil 64 65 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H 66