19fb049c8SOverMighty //===-- Multiplication of IEEE 754 floating-point numbers -------*- C++ -*-===// 29fb049c8SOverMighty // 39fb049c8SOverMighty // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49fb049c8SOverMighty // See https://llvm.org/LICENSE.txt for license information. 59fb049c8SOverMighty // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69fb049c8SOverMighty // 79fb049c8SOverMighty //===----------------------------------------------------------------------===// 89fb049c8SOverMighty 99fb049c8SOverMighty #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H 109fb049c8SOverMighty #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H 119fb049c8SOverMighty 129fb049c8SOverMighty #include "hdr/errno_macros.h" 139fb049c8SOverMighty #include "hdr/fenv_macros.h" 149fb049c8SOverMighty #include "src/__support/CPP/bit.h" 159fb049c8SOverMighty #include "src/__support/CPP/type_traits.h" 169fb049c8SOverMighty #include "src/__support/FPUtil/BasicOperations.h" 179fb049c8SOverMighty #include "src/__support/FPUtil/FEnvImpl.h" 189fb049c8SOverMighty #include "src/__support/FPUtil/FPBits.h" 199fb049c8SOverMighty #include "src/__support/FPUtil/dyadic_float.h" 209fb049c8SOverMighty #include "src/__support/macros/attributes.h" 219fb049c8SOverMighty #include "src/__support/macros/config.h" 229fb049c8SOverMighty #include "src/__support/macros/optimization.h" 239fb049c8SOverMighty 249fb049c8SOverMighty namespace LIBC_NAMESPACE_DECL { 259fb049c8SOverMighty namespace fputil::generic { 269fb049c8SOverMighty 279fb049c8SOverMighty template <typename OutType, typename InType> 289fb049c8SOverMighty LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> && 299fb049c8SOverMighty cpp::is_floating_point_v<InType> && 309fb049c8SOverMighty sizeof(OutType) <= sizeof(InType), 319fb049c8SOverMighty OutType> 329fb049c8SOverMighty mul(InType x, InType y) { 339fb049c8SOverMighty using OutFPBits = FPBits<OutType>; 349fb049c8SOverMighty using OutStorageType = typename OutFPBits::StorageType; 359fb049c8SOverMighty using InFPBits = FPBits<InType>; 369fb049c8SOverMighty using InStorageType = typename InFPBits::StorageType; 379fb049c8SOverMighty // The product of two p-digit numbers is a 2p-digit number. 389fb049c8SOverMighty using DyadicFloat = 399fb049c8SOverMighty DyadicFloat<cpp::bit_ceil(2 * static_cast<size_t>(InFPBits::SIG_LEN))>; 409fb049c8SOverMighty 419fb049c8SOverMighty InFPBits x_bits(x); 429fb049c8SOverMighty InFPBits y_bits(y); 439fb049c8SOverMighty 449fb049c8SOverMighty Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG; 459fb049c8SOverMighty 469fb049c8SOverMighty if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() || 479fb049c8SOverMighty x_bits.is_zero() || y_bits.is_zero())) { 489fb049c8SOverMighty if (x_bits.is_nan() || y_bits.is_nan()) { 499fb049c8SOverMighty if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan()) 509fb049c8SOverMighty raise_except_if_required(FE_INVALID); 519fb049c8SOverMighty 529fb049c8SOverMighty if (x_bits.is_quiet_nan()) { 53*74a1ca50Slntue InStorageType x_payload = x_bits.get_mantissa(); 54*74a1ca50Slntue x_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN; 559fb049c8SOverMighty return OutFPBits::quiet_nan(x_bits.sign(), 569fb049c8SOverMighty static_cast<OutStorageType>(x_payload)) 579fb049c8SOverMighty .get_val(); 589fb049c8SOverMighty } 599fb049c8SOverMighty 609fb049c8SOverMighty if (y_bits.is_quiet_nan()) { 61*74a1ca50Slntue InStorageType y_payload = y_bits.get_mantissa(); 62*74a1ca50Slntue y_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN; 639fb049c8SOverMighty return OutFPBits::quiet_nan(y_bits.sign(), 649fb049c8SOverMighty static_cast<OutStorageType>(y_payload)) 659fb049c8SOverMighty .get_val(); 669fb049c8SOverMighty } 679fb049c8SOverMighty 689fb049c8SOverMighty return OutFPBits::quiet_nan().get_val(); 699fb049c8SOverMighty } 709fb049c8SOverMighty 719fb049c8SOverMighty if (x_bits.is_inf()) { 729fb049c8SOverMighty if (y_bits.is_zero()) { 739fb049c8SOverMighty set_errno_if_required(EDOM); 749fb049c8SOverMighty raise_except_if_required(FE_INVALID); 759fb049c8SOverMighty return OutFPBits::quiet_nan().get_val(); 769fb049c8SOverMighty } 779fb049c8SOverMighty 789fb049c8SOverMighty return OutFPBits::inf(result_sign).get_val(); 799fb049c8SOverMighty } 809fb049c8SOverMighty 819fb049c8SOverMighty if (y_bits.is_inf()) { 829fb049c8SOverMighty if (x_bits.is_zero()) { 839fb049c8SOverMighty set_errno_if_required(EDOM); 849fb049c8SOverMighty raise_except_if_required(FE_INVALID); 859fb049c8SOverMighty return OutFPBits::quiet_nan().get_val(); 869fb049c8SOverMighty } 879fb049c8SOverMighty 889fb049c8SOverMighty return OutFPBits::inf(result_sign).get_val(); 899fb049c8SOverMighty } 909fb049c8SOverMighty 919fb049c8SOverMighty // Now either x or y is zero, and the other one is finite. 929fb049c8SOverMighty return OutFPBits::zero(result_sign).get_val(); 939fb049c8SOverMighty } 949fb049c8SOverMighty 959fb049c8SOverMighty DyadicFloat xd(x); 969fb049c8SOverMighty DyadicFloat yd(y); 979fb049c8SOverMighty 989fb049c8SOverMighty DyadicFloat result = quick_mul(xd, yd); 999fb049c8SOverMighty return result.template as<OutType, /*ShouldSignalExceptions=*/true>(); 1009fb049c8SOverMighty } 1019fb049c8SOverMighty 1029fb049c8SOverMighty } // namespace fputil::generic 1039fb049c8SOverMighty } // namespace LIBC_NAMESPACE_DECL 1049fb049c8SOverMighty 1059fb049c8SOverMighty #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H 106