[libc-commits] [libc] 9fb049c - [libc][math][c23] Add {f, d}mul{l, f128} and f16mul{, f, l, f128} C23 math functions (#98972)
via libc-commits
libc-commits at lists.llvm.org
Thu Jul 18 10:50:52 PDT 2024
Author: OverMighty
Date: 2024-07-18T19:50:49+02:00
New Revision: 9fb049c8c6a77026fa75a8d36b386a7f5a60613a
URL: https://github.com/llvm/llvm-project/commit/9fb049c8c6a77026fa75a8d36b386a7f5a60613a
DIFF: https://github.com/llvm/llvm-project/commit/9fb049c8c6a77026fa75a8d36b386a7f5a60613a.diff
LOG: [libc][math][c23] Add {f,d}mul{l,f128} and f16mul{,f,l,f128} C23 math functions (#98972)
Part of #93566.
Fixes #94833.
Added:
libc/src/__support/FPUtil/generic/mul.h
libc/src/math/dmulf128.h
libc/src/math/dmull.h
libc/src/math/f16mul.h
libc/src/math/f16mulf.h
libc/src/math/f16mulf128.h
libc/src/math/f16mull.h
libc/src/math/fmulf128.h
libc/src/math/fmull.h
libc/src/math/generic/dmulf128.cpp
libc/src/math/generic/dmull.cpp
libc/src/math/generic/f16mul.cpp
libc/src/math/generic/f16mulf.cpp
libc/src/math/generic/f16mulf128.cpp
libc/src/math/generic/f16mull.cpp
libc/src/math/generic/fmulf128.cpp
libc/src/math/generic/fmull.cpp
libc/test/src/math/MulTest.h
libc/test/src/math/dmull_test.cpp
libc/test/src/math/f16mul_test.cpp
libc/test/src/math/f16mulf_test.cpp
libc/test/src/math/f16mull_test.cpp
libc/test/src/math/fmull_test.cpp
libc/test/src/math/smoke/MulTest.h
libc/test/src/math/smoke/dmulf128_test.cpp
libc/test/src/math/smoke/dmull_test.cpp
libc/test/src/math/smoke/f16mul_test.cpp
libc/test/src/math/smoke/f16mulf128_test.cpp
libc/test/src/math/smoke/f16mulf_test.cpp
libc/test/src/math/smoke/f16mull_test.cpp
libc/test/src/math/smoke/fmulf128_test.cpp
libc/test/src/math/smoke/fmull_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/docs/math/index.rst
libc/spec/llvm_libc_ext.td
libc/spec/stdc.td
libc/src/__support/FPUtil/generic/CMakeLists.txt
libc/src/math/CMakeLists.txt
libc/src/math/generic/CMakeLists.txt
libc/src/math/generic/fmul.cpp
libc/test/src/math/CMakeLists.txt
libc/test/src/math/fmul_test.cpp
libc/test/src/math/smoke/CMakeLists.txt
libc/test/src/math/smoke/fmul_test.cpp
libc/utils/MPFRWrapper/MPFRUtils.cpp
libc/utils/MPFRWrapper/MPFRUtils.h
Removed:
libc/test/src/math/FMulTest.h
libc/test/src/math/smoke/FMulTest.h
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 9b718c3f81151..208889ba34a59 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -357,6 +357,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cosf
libc.src.math.coshf
libc.src.math.cospif
+ libc.src.math.dmull
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
@@ -411,6 +412,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmodf
libc.src.math.fmodl
libc.src.math.fmul
+ libc.src.math.fmull
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
@@ -531,6 +533,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16div
libc.src.math.f16divf
libc.src.math.f16fmaf
+ libc.src.math.f16mul
+ libc.src.math.f16mulf
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16sub
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 4d19a28f4a2b3..cbdee084aa199 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -382,6 +382,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.cosf
libc.src.math.coshf
libc.src.math.cospif
+ libc.src.math.dmull
libc.src.math.erff
libc.src.math.exp
libc.src.math.exp10
@@ -437,6 +438,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmodf
libc.src.math.fmodl
libc.src.math.fmul
+ libc.src.math.fmull
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
@@ -561,6 +563,9 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16fma
libc.src.math.f16fmaf
libc.src.math.f16fmal
+ libc.src.math.f16mul
+ libc.src.math.f16mulf
+ libc.src.math.f16mull
libc.src.math.f16sqrt
libc.src.math.f16sqrtf
libc.src.math.f16sqrtl
@@ -622,6 +627,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.f16addf128
libc.src.math.f16divf128
libc.src.math.f16fmaf128
+ libc.src.math.f16mulf128
libc.src.math.f16sqrtf128
libc.src.math.f16subf128
)
@@ -634,6 +640,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.canonicalizef128
libc.src.math.ceilf128
libc.src.math.copysignf128
+ libc.src.math.dmulf128
libc.src.math.fabsf128
libc.src.math.fdimf128
libc.src.math.floorf128
@@ -648,6 +655,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.fminimum_numf128
libc.src.math.fminimumf128
libc.src.math.fmodf128
+ libc.src.math.fmulf128
libc.src.math.frexpf128
libc.src.math.fromfpf128
libc.src.math.fromfpxf128
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index 205d14946535e..5fab9ce4df949 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -120,7 +120,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dfma | N/A | N/A | | N/A | | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| dmul | N/A | N/A | | N/A | | 7.12.14.3 | F.10.11 |
+| dmul | N/A | N/A | |check| | N/A | |check|\* | 7.12.14.3 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| dsub | N/A | N/A | | N/A | | 7.12.14.2 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
@@ -130,6 +130,8 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16fma | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.5 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| f16mul | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.5 | F.10.11 |
++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| f16sub | |check|\* | |check|\* | |check|\* | N/A | |check| | 7.12.14.2 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fabs | |check| | |check| | |check| | |check| | |check| | 7.12.7.3 | F.10.4.3 |
@@ -166,7 +168,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| fmod | |check| | |check| | |check| | |check| | |check| | 7.12.10.1 | F.10.7.1 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| fmul | N/A | |check| | | N/A | | 7.12.14.3 | F.10.11 |
+| fmul | N/A | |check| | |check| | N/A | |check|\* | 7.12.14.3 | F.10.11 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| frexp | |check| | |check| | |check| | |check| | |check| | 7.12.6.7 | F.10.3.7 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/spec/llvm_libc_ext.td b/libc/spec/llvm_libc_ext.td
index 86215029831ca..55b354cae74e0 100644
--- a/libc/spec/llvm_libc_ext.td
+++ b/libc/spec/llvm_libc_ext.td
@@ -65,6 +65,14 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16subl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"fmulf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ GuardedFunctionSpec<"dmulf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ GuardedFunctionSpec<"f16mul", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"f16mulf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
+ GuardedFunctionSpec<"f16mull", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
+
GuardedFunctionSpec<"f16div", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index a4c6b40b98388..18592e92d330a 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -475,8 +475,6 @@ def StdC : StandardSpec<"stdc"> {
GuardedFunctionSpec<"fminimum_mag_numf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
- FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
-
FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
@@ -733,6 +731,13 @@ def StdC : StandardSpec<"stdc"> {
GuardedFunctionSpec<"f16subf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+ FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ GuardedFunctionSpec<"f16mulf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
+
GuardedFunctionSpec<"f16divf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
GuardedFunctionSpec<"f16sqrtf128", RetValSpec<Float16Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128">,
diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index c73f68723e232..43096aa529fc3 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -84,3 +84,20 @@ add_header_library(
libc.src.__support.macros.attributes
libc.src.__support.macros.optimization
)
+
+add_header_library(
+ mul
+ HDRS
+ mul.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.CPP.bit
+ libc.src.__support.CPP.type_traits
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.macros.attributes
+ libc.src.__support.macros.optimization
+)
diff --git a/libc/src/__support/FPUtil/generic/mul.h b/libc/src/__support/FPUtil/generic/mul.h
new file mode 100644
index 0000000000000..02fc69c6cb1ba
--- /dev/null
+++ b/libc/src/__support/FPUtil/generic/mul.h
@@ -0,0 +1,105 @@
+//===-- Multiplication of IEEE 754 floating-point numbers -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil::generic {
+
+template <typename OutType, typename InType>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
+ cpp::is_floating_point_v<InType> &&
+ sizeof(OutType) <= sizeof(InType),
+ OutType>
+mul(InType x, InType y) {
+ using OutFPBits = FPBits<OutType>;
+ using OutStorageType = typename OutFPBits::StorageType;
+ using InFPBits = FPBits<InType>;
+ using InStorageType = typename InFPBits::StorageType;
+ // The product of two p-digit numbers is a 2p-digit number.
+ using DyadicFloat =
+ DyadicFloat<cpp::bit_ceil(2 * static_cast<size_t>(InFPBits::SIG_LEN))>;
+
+ InFPBits x_bits(x);
+ InFPBits y_bits(y);
+
+ Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
+
+ if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
+ x_bits.is_zero() || y_bits.is_zero())) {
+ if (x_bits.is_nan() || y_bits.is_nan()) {
+ if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+ raise_except_if_required(FE_INVALID);
+
+ if (x_bits.is_quiet_nan()) {
+ InStorageType x_payload = static_cast<InStorageType>(getpayload(x));
+ if ((x_payload & ~(OutFPBits::FRACTION_MASK >> 1)) == 0)
+ return OutFPBits::quiet_nan(x_bits.sign(),
+ static_cast<OutStorageType>(x_payload))
+ .get_val();
+ }
+
+ if (y_bits.is_quiet_nan()) {
+ InStorageType y_payload = static_cast<InStorageType>(getpayload(y));
+ if ((y_payload & ~(OutFPBits::FRACTION_MASK >> 1)) == 0)
+ return OutFPBits::quiet_nan(y_bits.sign(),
+ static_cast<OutStorageType>(y_payload))
+ .get_val();
+ }
+
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ if (x_bits.is_inf()) {
+ if (y_bits.is_zero()) {
+ set_errno_if_required(EDOM);
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ return OutFPBits::inf(result_sign).get_val();
+ }
+
+ if (y_bits.is_inf()) {
+ if (x_bits.is_zero()) {
+ set_errno_if_required(EDOM);
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ return OutFPBits::inf(result_sign).get_val();
+ }
+
+ // Now either x or y is zero, and the other one is finite.
+ return OutFPBits::zero(result_sign).get_val();
+ }
+
+ DyadicFloat xd(x);
+ DyadicFloat yd(y);
+
+ DyadicFloat result = quick_mul(xd, yd);
+ return result.template as<OutType, /*ShouldSignalExceptions=*/true>();
+}
+
+} // namespace fputil::generic
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_MUL_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index dc2339896f2bb..c4e33130e9090 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -86,6 +86,9 @@ add_math_entrypoint_object(cosh)
add_math_entrypoint_object(coshf)
add_math_entrypoint_object(cospif)
+add_math_entrypoint_object(dmull)
+add_math_entrypoint_object(dmulf128)
+
add_math_entrypoint_object(erf)
add_math_entrypoint_object(erff)
@@ -118,6 +121,11 @@ add_math_entrypoint_object(f16fmaf)
add_math_entrypoint_object(f16fmal)
add_math_entrypoint_object(f16fmaf128)
+add_math_entrypoint_object(f16mul)
+add_math_entrypoint_object(f16mulf)
+add_math_entrypoint_object(f16mull)
+add_math_entrypoint_object(f16mulf128)
+
add_math_entrypoint_object(f16sqrt)
add_math_entrypoint_object(f16sqrtf)
add_math_entrypoint_object(f16sqrtl)
@@ -210,6 +218,8 @@ add_math_entrypoint_object(fminimum_mag_numf16)
add_math_entrypoint_object(fminimum_mag_numf128)
add_math_entrypoint_object(fmul)
+add_math_entrypoint_object(fmull)
+add_math_entrypoint_object(fmulf128)
add_math_entrypoint_object(fmod)
add_math_entrypoint_object(fmodf)
diff --git a/libc/src/math/dmulf128.h b/libc/src/math/dmulf128.h
new file mode 100644
index 0000000000000..623f22c910a41
--- /dev/null
+++ b/libc/src/math/dmulf128.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for dmulf128 ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_DMULF128_H
+#define LLVM_LIBC_SRC_MATH_DMULF128_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+double dmulf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_DMULF128_H
diff --git a/libc/src/math/dmull.h b/libc/src/math/dmull.h
new file mode 100644
index 0000000000000..656776a603009
--- /dev/null
+++ b/libc/src/math/dmull.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for dmull -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_DMULL_H
+#define LLVM_LIBC_SRC_MATH_DMULL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+double dmull(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_DMULL_H
diff --git a/libc/src/math/f16mul.h b/libc/src/math/f16mul.h
new file mode 100644
index 0000000000000..89403cf219271
--- /dev/null
+++ b/libc/src/math/f16mul.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for f16mul ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_F16MUL_H
+#define LLVM_LIBC_SRC_MATH_F16MUL_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 f16mul(double x, double y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_F16MUL_H
diff --git a/libc/src/math/f16mulf.h b/libc/src/math/f16mulf.h
new file mode 100644
index 0000000000000..755886d6f14d0
--- /dev/null
+++ b/libc/src/math/f16mulf.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for f16mulf -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_F16MULF_H
+#define LLVM_LIBC_SRC_MATH_F16MULF_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 f16mulf(float x, float y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_F16MULF_H
diff --git a/libc/src/math/f16mulf128.h b/libc/src/math/f16mulf128.h
new file mode 100644
index 0000000000000..14371c57ca88c
--- /dev/null
+++ b/libc/src/math/f16mulf128.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for f16mulf128 --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_F16MULF128_H
+#define LLVM_LIBC_SRC_MATH_F16MULF128_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 f16mulf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_F16MULF128_H
diff --git a/libc/src/math/f16mull.h b/libc/src/math/f16mull.h
new file mode 100644
index 0000000000000..a3177cadc1306
--- /dev/null
+++ b/libc/src/math/f16mull.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for f16mull -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_F16MULL_H
+#define LLVM_LIBC_SRC_MATH_F16MULL_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 f16mull(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_F16MULL_H
diff --git a/libc/src/math/fmulf128.h b/libc/src/math/fmulf128.h
new file mode 100644
index 0000000000000..94137ae87eb1e
--- /dev/null
+++ b/libc/src/math/fmulf128.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for fmulf128 ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_FMULF128_H
+#define LLVM_LIBC_SRC_MATH_FMULF128_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float fmulf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_FMULF128_H
diff --git a/libc/src/math/fmull.h b/libc/src/math/fmull.h
new file mode 100644
index 0000000000000..46e6c77cc66a2
--- /dev/null
+++ b/libc/src/math/fmull.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for fmull -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_FMULL_H
+#define LLVM_LIBC_SRC_MATH_FMULL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float fmull(long double x, long double y);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_FMULL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 415ca3fbce796..9c86bac4a0cb7 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2633,11 +2633,32 @@ add_entrypoint_object(
HDRS
../fmul.h
DEPENDS
- libc.src.__support.FPUtil.basic_operations
- libc.src.__support.uint128
- libc.src.__support.CPP.bit
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fmull
+ SRCS
+ fmull.cpp
+ HDRS
+ ../fmull.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fmulf128
+ SRCS
+ fmulf128.cpp
+ HDRS
+ ../fmulf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)
@@ -4200,3 +4221,80 @@ add_entrypoint_object(
libc.src.__support.macros.optimization
libc.src.__support.integer_literals
)
+
+add_entrypoint_object(
+ dmull
+ SRCS
+ dmull.cpp
+ HDRS
+ ../dmull.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ dmulf128
+ SRCS
+ dmulf128.cpp
+ HDRS
+ ../dmulf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ f16mul
+ SRCS
+ f16mul.cpp
+ HDRS
+ ../f16mul.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ f16mulf
+ SRCS
+ f16mulf.cpp
+ HDRS
+ ../f16mulf.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ f16mull
+ SRCS
+ f16mull.cpp
+ HDRS
+ ../f16mull.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ f16mulf128
+ SRCS
+ f16mulf128.cpp
+ HDRS
+ ../f16mulf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.generic.mul
+ COMPILE_OPTIONS
+ -O3
+)
diff --git a/libc/src/math/generic/dmulf128.cpp b/libc/src/math/generic/dmulf128.cpp
new file mode 100644
index 0000000000000..7e6ef95362c09
--- /dev/null
+++ b/libc/src/math/generic/dmulf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of dmulf128 function -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/dmulf128.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(double, dmulf128, (float128 x, float128 y)) {
+ return fputil::generic::mul<double>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/dmull.cpp b/libc/src/math/generic/dmull.cpp
new file mode 100644
index 0000000000000..428caa84a9977
--- /dev/null
+++ b/libc/src/math/generic/dmull.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of dmull function ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/dmull.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(double, dmull, (long double x, long double y)) {
+ return fputil::generic::mul<double>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16mul.cpp b/libc/src/math/generic/f16mul.cpp
new file mode 100644
index 0000000000000..f7a5225b60f11
--- /dev/null
+++ b/libc/src/math/generic/f16mul.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of f16mul function ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/f16mul.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, f16mul, (double x, double y)) {
+ return fputil::generic::mul<float16>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16mulf.cpp b/libc/src/math/generic/f16mulf.cpp
new file mode 100644
index 0000000000000..2c04664f804ea
--- /dev/null
+++ b/libc/src/math/generic/f16mulf.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of f16mulf function --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/f16mulf.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, f16mulf, (float x, float y)) {
+ return fputil::generic::mul<float16>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16mulf128.cpp b/libc/src/math/generic/f16mulf128.cpp
new file mode 100644
index 0000000000000..7e2d6a0d194ae
--- /dev/null
+++ b/libc/src/math/generic/f16mulf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of f16mulf128 function -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/f16mulf128.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, f16mulf128, (float128 x, float128 y)) {
+ return fputil::generic::mul<float16>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16mull.cpp b/libc/src/math/generic/f16mull.cpp
new file mode 100644
index 0000000000000..fc66fba4d9f23
--- /dev/null
+++ b/libc/src/math/generic/f16mull.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of f16mull function --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/f16mull.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, f16mull, (long double x, long double y)) {
+ return fputil::generic::mul<float16>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 16fa11e93df09..64c27d6e2f956 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of fmul function------------------------------------===//
+//===-- Implementation of fmul function -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,123 +7,14 @@
//===----------------------------------------------------------------------===//
#include "src/math/fmul.h"
-#include "src/__support/CPP/bit.h"
-#include "src/__support/FPUtil/BasicOperations.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/uint128.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- auto x_bits = fputil::FPBits<double>(x);
-
- auto y_bits = fputil::FPBits<double>(y);
-
- auto output_sign = (x_bits.sign() != y_bits.sign()) ? Sign::NEG : Sign::POS;
-
- if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
- x_bits.is_zero() || y_bits.is_zero())) {
- if (x_bits.is_nan())
- return static_cast<float>(x);
- if (y_bits.is_nan())
- return static_cast<float>(y);
- if (x_bits.is_inf())
- return y_bits.is_zero()
- ? fputil::FPBits<float>::quiet_nan().get_val()
- : fputil::FPBits<float>::inf(output_sign).get_val();
- if (y_bits.is_inf())
- return x_bits.is_zero()
- ? fputil::FPBits<float>::quiet_nan().get_val()
- : fputil::FPBits<float>::inf(output_sign).get_val();
- // Now either x or y is zero, and the other one is finite.
- return fputil::FPBits<float>::zero(output_sign).get_val();
- }
-
- uint64_t mx, my;
-
- // Get mantissa and append the hidden bit if needed.
- mx = x_bits.get_explicit_mantissa();
- my = y_bits.get_explicit_mantissa();
-
- // Get the corresponding biased exponent.
- int ex = x_bits.get_explicit_exponent();
- int ey = y_bits.get_explicit_exponent();
-
- // Count the number of leading zeros of the explicit mantissas.
- int nx = cpp::countl_zero(mx);
- int ny = cpp::countl_zero(my);
- // Shift the leading 1 bit to the most significant bit.
- mx <<= nx;
- my <<= ny;
-
- // Adjust exponent accordingly: If x or y are normal, we will only need to
- // shift by (exponent length + sign bit = 11 bits. If x or y are denormal, we
- // will need to shift more than 11 bits.
- ex -= (nx - 11);
- ey -= (ny - 11);
-
- UInt128 product = static_cast<UInt128>(mx) * static_cast<UInt128>(my);
- int32_t dm1;
- uint64_t highs, lows;
- uint64_t g, hight, lowt;
- uint32_t m;
- uint32_t b;
- int c;
-
- highs = static_cast<uint64_t>(product >> 64);
- c = static_cast<int>(highs >= 0x8000000000000000);
- lows = static_cast<uint64_t>(product);
-
- lowt = (lows != 0);
-
- dm1 = ex + ey + c + fputil::FPBits<float>::EXP_BIAS;
-
- int round_mode = fputil::quick_get_round();
- if (dm1 >= 255) {
- if ((round_mode == FE_TOWARDZERO) ||
- (round_mode == FE_UPWARD && output_sign.is_neg()) ||
- (round_mode == FE_DOWNWARD && output_sign.is_pos())) {
- return fputil::FPBits<float>::max_normal(output_sign).get_val();
- }
- return fputil::FPBits<float>::inf().get_val();
- } else if (dm1 <= 0) {
-
- int m_shift = 40 + c - dm1;
- int g_shift = m_shift - 1;
- int h_shift = 64 - g_shift;
- m = (m_shift >= 64) ? 0 : static_cast<uint32_t>(highs >> m_shift);
-
- g = g_shift >= 64 ? 0 : (highs >> g_shift) & 1;
- hight = h_shift >= 64 ? highs : (highs << h_shift) != 0;
-
- dm1 = 0;
- } else {
- m = static_cast<uint32_t>(highs >> (39 + c));
- g = (highs >> (38 + c)) & 1;
- hight = (highs << (26 - c)) != 0;
- }
-
- if (round_mode == FE_TONEAREST) {
- b = g && ((hight && lowt) || ((m & 1) != 0));
- } else if ((output_sign.is_neg() && round_mode == FE_DOWNWARD) ||
- (output_sign.is_pos() && round_mode == FE_UPWARD)) {
- b = (g == 0 && (hight && lowt) == 0) ? 0 : 1;
- } else {
- b = 0;
- }
-
- uint32_t exp16 = (dm1 << 23);
-
- uint32_t m2 = m & fputil::FPBits<float>::FRACTION_MASK;
-
- uint32_t result = (exp16 + m2) + b;
-
- auto result_bits = fputil::FPBits<float>(result);
- result_bits.set_sign(output_sign);
- return result_bits.get_val();
+ return fputil::generic::mul<float>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fmulf128.cpp b/libc/src/math/generic/fmulf128.cpp
new file mode 100644
index 0000000000000..c0c55ace641b8
--- /dev/null
+++ b/libc/src/math/generic/fmulf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fmulf128 function -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/fmulf128.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, fmulf128, (float128 x, float128 y)) {
+ return fputil::generic::mul<float>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fmull.cpp b/libc/src/math/generic/fmull.cpp
new file mode 100644
index 0000000000000..41ab165e7d09d
--- /dev/null
+++ b/libc/src/math/generic/fmull.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fmull function ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/fmull.h"
+#include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, fmull, (long double x, long double y)) {
+ return fputil::generic::mul<float>(x, y);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 64b4d2c58fb6a..c28385f620cfd 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1847,10 +1847,28 @@ add_fp_unittest(
SRCS
fmul_test.cpp
HDRS
- FMulTest.h
+ MulTest.h
DEPENDS
libc.src.math.fmul
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
)
+
+add_fp_unittest(
+ fmull_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ fmull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.math.fmull
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
+)
+
add_fp_unittest(
asinhf_test
NEED_MPFR
@@ -2237,6 +2255,66 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ dmull_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ dmull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.math.dmull
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
+)
+
+add_fp_unittest(
+ f16mul_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ f16mul_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.math.f16mul
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
+)
+
+add_fp_unittest(
+ f16mulf_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ f16mulf_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.math.f16mulf
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
+)
+
+add_fp_unittest(
+ f16mull_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ f16mull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.math.f16mull
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
+)
+
add_subdirectory(generic)
add_subdirectory(smoke)
diff --git a/libc/test/src/math/FMulTest.h b/libc/test/src/math/FMulTest.h
deleted file mode 100644
index 8ca33ea71b712..0000000000000
--- a/libc/test/src/math/FMulTest.h
+++ /dev/null
@@ -1,121 +0,0 @@
-//===-- Utility class to test fmul[f|l] -------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_TEST_SRC_MATH_FMULTEST_H
-#define LLVM_LIBC_TEST_SRC_MATH_FMULTEST_H
-
-#include "src/__support/FPUtil/FPBits.h"
-#include "test/UnitTest/FEnvSafeTest.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-#include "utils/MPFRWrapper/MPFRUtils.h"
-
-namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
-
-template <typename OutType, typename InType>
-class FmulMPFRTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
-
- DECLARE_SPECIAL_CONSTANTS(InType)
-
-public:
- typedef OutType (*FMulFunc)(InType, InType);
-
- void testFMulMPFR(FMulFunc func) {
- constexpr int N = 10;
- mpfr::BinaryInput<InType> INPUTS[N] = {
- {3.0, 5.0},
- {0x1.0p1, 0x1.0p-131},
- {0x1.0p2, 0x1.0p-129},
- {1.0, 1.0},
- {-0.0, -0.0},
- {-0.0, 0.0},
- {0.0, -0.0},
- {0x1.0p100, 0x1.0p100},
- {1.0, 1.0 + 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150},
- {1.0, 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150}};
-
- for (int i = 0; i < N; ++i) {
- InType x = INPUTS[i].x;
- InType y = INPUTS[i].y;
- ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Fmul, INPUTS[i],
- func(x, y), 0.5);
- }
- }
-
- void testSpecialInputsMPFR(FMulFunc func) {
- constexpr int N = 27;
- mpfr::BinaryInput<InType> INPUTS[N] = {{inf, 0x1.0p-129},
- {0x1.0p-129, inf},
- {inf, 2.0},
- {3.0, inf},
- {0.0, 0.0},
- {neg_inf, aNaN},
- {aNaN, neg_inf},
- {neg_inf, neg_inf},
- {0.0, neg_inf},
- {neg_inf, 0.0},
- {neg_inf, 1.0},
- {1.0, neg_inf},
- {neg_inf, 0x1.0p-129},
- {0x1.0p-129, neg_inf},
- {0.0, 0x1.0p-129},
- {inf, 0.0},
- {0.0, inf},
- {0.0, aNaN},
- {2.0, aNaN},
- {0x1.0p-129, aNaN},
- {inf, aNaN},
- {aNaN, aNaN},
- {0.0, sNaN},
- {2.0, sNaN},
- {0x1.0p-129, sNaN},
- {inf, sNaN},
- {sNaN, sNaN}};
-
- for (int i = 0; i < N; ++i) {
- InType x = INPUTS[i].x;
- InType y = INPUTS[i].y;
- ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Fmul, INPUTS[i],
- func(x, y), 0.5);
- }
- }
-
- void testNormalRange(FMulFunc func) {
- using FPBits = LIBC_NAMESPACE::fputil::FPBits<InType>;
- using StorageType = typename FPBits::StorageType;
- static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
- static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
-
- constexpr StorageType COUNT = 10'001;
- constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
- for (int signs = 0; signs < 4; ++signs) {
- for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
- v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
- InType x = FPBits(v).get_val(), y = FPBits(w).get_val();
- if (signs % 2 == 1) {
- x = -x;
- }
- if (signs >= 2) {
- y = -y;
- }
-
- mpfr::BinaryInput<InType> input{x, y};
- ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Fmul, input, func(x, y),
- 0.5);
- }
- }
- }
-};
-
-#define LIST_FMUL_MPFR_TESTS(OutType, InType, func) \
- using LlvmLibcFmulTest = FmulMPFRTest<OutType, InType>; \
- TEST_F(LlvmLibcFmulTest, MulMpfr) { testFMulMPFR(&func); } \
- TEST_F(LlvmLibcFmulTest, NanInfMpfr) { testSpecialInputsMPFR(&func); } \
- TEST_F(LlvmLibcFmulTest, NormalRange) { testNormalRange(&func); }
-
-#endif // LLVM_LIBC_TEST_SRC_MATH_FMULTEST_H
diff --git a/libc/test/src/math/MulTest.h b/libc/test/src/math/MulTest.h
new file mode 100644
index 0000000000000..cb81a795be36b
--- /dev/null
+++ b/libc/test/src/math/MulTest.h
@@ -0,0 +1,95 @@
+//===-- Utility class to test
diff erent flavors of float mul ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TEST_SRC_MATH_MULTEST_H
+#define LLVM_LIBC_TEST_SRC_MATH_MULTEST_H
+
+#include "src/stdlib/rand.h"
+#include "src/stdlib/srand.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+template <typename OutType, typename InType>
+class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+ struct InConstants {
+ DECLARE_SPECIAL_CONSTANTS(InType)
+ };
+
+ using InFPBits = typename InConstants::FPBits;
+ using InStorageType = typename InConstants::StorageType;
+
+ static constexpr InStorageType IN_MAX_NORMAL_U =
+ InFPBits::max_normal().uintval();
+ static constexpr InStorageType IN_MIN_NORMAL_U =
+ InFPBits::min_normal().uintval();
+ static constexpr InStorageType IN_MAX_SUBNORMAL_U =
+ InFPBits::max_subnormal().uintval();
+ static constexpr InStorageType IN_MIN_SUBNORMAL_U =
+ InFPBits::min_subnormal().uintval();
+
+ InStorageType get_random_bit_pattern() {
+ InStorageType bits{0};
+ for (InStorageType i = 0; i < sizeof(InStorageType) / 2; ++i)
+ bits = (bits << 2) + static_cast<uint16_t>(LIBC_NAMESPACE::rand());
+ return bits;
+ }
+
+public:
+ using MulFunc = OutType (*)(InType, InType);
+
+ void test_subnormal_range(MulFunc func) {
+ constexpr InStorageType COUNT = 10'001;
+ constexpr InStorageType STEP =
+ (IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT;
+ LIBC_NAMESPACE::srand(1);
+ for (int signs = 0; signs < 4; signs++) {
+ for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
+ InType x = InFPBits(get_random_bit_pattern()).get_val();
+ InType y = InFPBits(v).get_val();
+ if ((signs & 1) != 0)
+ x = -x;
+ if ((signs & 2) != 0)
+ y = -y;
+ mpfr::BinaryInput<InType> input{x, y};
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y),
+ 0.5);
+ }
+ }
+ }
+
+ void test_normal_range(MulFunc func) {
+ constexpr InStorageType COUNT = 10'001;
+ constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT;
+ LIBC_NAMESPACE::srand(1);
+ for (int signs = 0; signs < 4; signs++) {
+ for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
+ InType x = InFPBits(get_random_bit_pattern()).get_val();
+ InType y = InFPBits(v).get_val();
+ if ((signs & 1) != 0)
+ x = -x;
+ if ((signs & 2) != 0)
+ y = -y;
+ mpfr::BinaryInput<InType> input{x, y};
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y),
+ 0.5);
+ }
+ }
+ }
+};
+
+#define LIST_MUL_TESTS(OutType, InType, func) \
+ using LlvmLibcMulTest = MulTest<OutType, InType>; \
+ TEST_F(LlvmLibcMulTest, SubnormalRange) { test_subnormal_range(&func); } \
+ TEST_F(LlvmLibcMulTest, NormalRange) { test_normal_range(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_MATH_MULTEST_H
diff --git a/libc/test/src/math/dmull_test.cpp b/libc/test/src/math/dmull_test.cpp
new file mode 100644
index 0000000000000..1b9c9c2c24ed3
--- /dev/null
+++ b/libc/test/src/math/dmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for dmull -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/dmull.h"
+
+LIST_MUL_TESTS(double, long double, LIBC_NAMESPACE::dmull)
diff --git a/libc/test/src/math/f16mul_test.cpp b/libc/test/src/math/f16mul_test.cpp
new file mode 100644
index 0000000000000..49b443870c483
--- /dev/null
+++ b/libc/test/src/math/f16mul_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mul ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mul.h"
+
+LIST_MUL_TESTS(float16, double, LIBC_NAMESPACE::f16mul)
diff --git a/libc/test/src/math/f16mulf_test.cpp b/libc/test/src/math/f16mulf_test.cpp
new file mode 100644
index 0000000000000..bf2530863621d
--- /dev/null
+++ b/libc/test/src/math/f16mulf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mulf ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mulf.h"
+
+LIST_MUL_TESTS(float16, float, LIBC_NAMESPACE::f16mulf)
diff --git a/libc/test/src/math/f16mull_test.cpp b/libc/test/src/math/f16mull_test.cpp
new file mode 100644
index 0000000000000..5292ddb87b7f4
--- /dev/null
+++ b/libc/test/src/math/f16mull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mull ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mull.h"
+
+LIST_MUL_TESTS(float16, long double, LIBC_NAMESPACE::f16mull)
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index 16eaa1a818daf..3f6df66456bac 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -1,13 +1,13 @@
-//===-- Unittests for fmul-------------------------------------------------===//
+//===-- Unittests for fmul ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#include "FMulTest.h"
+#include "MulTest.h"
#include "src/math/fmul.h"
-LIST_FMUL_MPFR_TESTS(float, double, LIBC_NAMESPACE::fmul)
+LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
diff --git a/libc/test/src/math/fmull_test.cpp b/libc/test/src/math/fmull_test.cpp
new file mode 100644
index 0000000000000..ef694063f20dc
--- /dev/null
+++ b/libc/test/src/math/fmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fmull -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/fmull.h"
+
+LIST_MUL_TESTS(float, long double, LIBC_NAMESPACE::fmull)
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 76d5919ad9156..c57aa9638ed30 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -2531,10 +2531,27 @@ add_fp_unittest(
SRCS
fmul_test.cpp
HDRS
- FMulTest.h
+ MulTest.h
DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
libc.src.math.fmul
- libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+ fmull_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fmull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.fmull
)
add_fp_unittest(
@@ -3981,3 +3998,78 @@ add_fp_unittest(
DEPENDS
libc.src.math.cbrt
)
+
+add_fp_unittest(
+ dmull_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ dmull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.dmull
+)
+
+add_fp_unittest(
+ f16mul_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ f16mul_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.f16mul
+)
+
+add_fp_unittest(
+ f16mulf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ f16mulf_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.f16mulf
+)
+
+add_fp_unittest(
+ f16mull_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ f16mull_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.f16mull
+)
+
+add_fp_unittest(
+ f16mulf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ f16mulf128_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.math.f16mulf128
+)
diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h
deleted file mode 100644
index 33fb82c8d2da1..0000000000000
--- a/libc/test/src/math/smoke/FMulTest.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===-- Utility class to test fmul[f|l] ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H
-#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H
-
-#include "test/UnitTest/FEnvSafeTest.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-
-template <typename T, typename R>
-class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
-
- DECLARE_SPECIAL_CONSTANTS(T)
-
-public:
- typedef T (*FMulFunc)(R, R);
-
- void testMul(FMulFunc func) {
-
- EXPECT_FP_EQ_ALL_ROUNDING(T(15.0), func(3.0, 5.0));
- EXPECT_FP_EQ_ALL_ROUNDING(T(0x1.0p-130), func(0x1.0p1, 0x1.0p-131));
- EXPECT_FP_EQ_ALL_ROUNDING(T(0x1.0p-127), func(0x1.0p2, 0x1.0p-129));
- EXPECT_FP_EQ_ALL_ROUNDING(T(1.0), func(1.0, 1.0));
-
- EXPECT_FP_EQ_ALL_ROUNDING(T(0.0), func(-0.0, -0.0));
- EXPECT_FP_EQ_ALL_ROUNDING(T(-0.0), func(0.0, -0.0));
- EXPECT_FP_EQ_ALL_ROUNDING(T(-0.0), func(-0.0, 0.0));
-
- EXPECT_FP_EQ_ROUNDING_NEAREST(inf, func(0x1.0p100, 0x1.0p100));
- EXPECT_FP_EQ_ROUNDING_UPWARD(inf, func(0x1.0p100, 0x1.0p100));
- EXPECT_FP_EQ_ROUNDING_DOWNWARD(max_normal, func(0x1.0p100, 0x1.0p100));
- EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(max_normal, func(0x1.0p100, 0x1.0p100));
-
- EXPECT_FP_EQ_ROUNDING_NEAREST(
- 0x1p0, func(1.0, 1.0 + 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_DOWNWARD(
- 0x1p0, func(1.0, 1.0 + 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(
- 0x1p0, func(1.0, 1.0 + 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_UPWARD(
- 0x1p0, func(1.0, 1.0 + 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
-
- EXPECT_FP_EQ_ROUNDING_NEAREST(
- 0x1.0p-128f + 0x1.0p-148f,
- func(1.0, 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_UPWARD(
- 0x1.0p-128f + 0x1.0p-148f,
- func(1.0, 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_DOWNWARD(
- 0x1.0p-128f + 0x1.0p-149f,
- func(1.0, 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(
- 0x1.0p-128f + 0x1.0p-149f,
- func(1.0, 0x1.0p-128 + 0x1.0p-149 + 0x1.0p-150));
- }
-
- void testSpecialInputs(FMulFunc func) {
- EXPECT_FP_EQ_ALL_ROUNDING(inf, func(inf, 0x1.0p-129));
- EXPECT_FP_EQ_ALL_ROUNDING(inf, func(0x1.0p-129, inf));
- EXPECT_FP_EQ_ALL_ROUNDING(inf, func(inf, 2.0));
- EXPECT_FP_EQ_ALL_ROUNDING(inf, func(3.0, inf));
- EXPECT_FP_EQ_ALL_ROUNDING(0.0, func(0.0, 0.0));
-
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(neg_inf, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(aNaN, neg_inf));
- EXPECT_FP_EQ_ALL_ROUNDING(inf, func(neg_inf, neg_inf));
-
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0.0, neg_inf));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(neg_inf, 0.0));
-
- EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf, 1.0));
- EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(1.0, neg_inf));
-
- EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf, 0x1.0p-129));
- EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(0x1.0p-129, neg_inf));
-
- EXPECT_FP_EQ_ALL_ROUNDING(0.0, func(0.0, 0x1.0p-129));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(inf, 0.0));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0.0, inf));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0.0, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(2.0, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0x1.0p-129, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(inf, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(aNaN, aNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0.0, sNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(2.0, sNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(0x1.0p-129, sNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(inf, sNaN));
- EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(sNaN, sNaN));
- }
-};
-
-#define LIST_FMUL_TESTS(T, R, func) \
- using LlvmLibcFmulTest = FmulTest<T, R>; \
- TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } \
- TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func); }
-
-#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
new file mode 100644
index 0000000000000..e2298eaeeb216
--- /dev/null
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -0,0 +1,171 @@
+//===-- Utility class to test
diff erent flavors of float mul ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H
+#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename OutType, typename InType>
+class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+ DECLARE_SPECIAL_CONSTANTS(OutType)
+
+ struct InConstants {
+ DECLARE_SPECIAL_CONSTANTS(InType)
+ };
+
+ using InFPBits = typename InConstants::FPBits;
+ using InStorageType = typename InConstants::StorageType;
+
+ InConstants in;
+
+public:
+ using MulFunc = OutType (*)(InType, InType);
+
+ void test_special_numbers(MulFunc func) {
+ EXPECT_FP_IS_NAN(func(aNaN, aNaN));
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);
+
+ InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
+ EXPECT_FP_EQ(InType(0x42.0p+0),
+ LIBC_NAMESPACE::fputil::getpayload(func(qnan_42, zero)));
+ EXPECT_FP_EQ(InType(0x42.0p+0),
+ LIBC_NAMESPACE::fputil::getpayload(func(zero, qnan_42)));
+
+ if constexpr (sizeof(OutType) < sizeof(InType)) {
+ InStorageType max_payload = InFPBits::FRACTION_MASK >> 1;
+ InType qnan_max = InFPBits::quiet_nan(Sign::POS, max_payload).get_val();
+ EXPECT_FP_EQ(zero,
+ LIBC_NAMESPACE::fputil::getpayload(func(qnan_max, zero)));
+ EXPECT_FP_EQ(zero,
+ LIBC_NAMESPACE::fputil::getpayload(func(zero, qnan_max)));
+ EXPECT_FP_EQ(InType(0x42.0p+0),
+ LIBC_NAMESPACE::fputil::getpayload(func(qnan_max, qnan_42)));
+ EXPECT_FP_EQ(InType(0x42.0p+0),
+ LIBC_NAMESPACE::fputil::getpayload(func(qnan_42, qnan_max)));
+ }
+
+ EXPECT_FP_EQ(inf, func(inf, InType(1.0)));
+ EXPECT_FP_EQ(neg_inf, func(neg_inf, InType(1.0)));
+ EXPECT_FP_EQ(neg_inf, func(inf, InType(-1.0)));
+ EXPECT_FP_EQ(inf, func(neg_inf, InType(-1.0)));
+
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, func(zero, zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, func(neg_zero, neg_zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(zero, neg_zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero, zero));
+
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(1.0), func(1.0, 1.0));
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(15.0), func(3.0, 5.0));
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-13), func(0x1.0p+1, 0x1.0p-14));
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-10), func(0x1.0p+2, 0x1.0p-12));
+ }
+
+ void test_invalid_operations(MulFunc func) {
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, neg_zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, neg_zero), FE_INVALID);
+ }
+
+ void test_range_errors(MulFunc func) {
+ using namespace LIBC_NAMESPACE::fputil::testing;
+
+ if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ }
+
+ if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
+ func(neg_max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ }
+
+ if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
+ func(in.neg_min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ }
+
+ if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
+ func(neg_max_normal, max_normal),
+ FE_OVERFLOW | FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
+ func(in.min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.min_denormal),
+ FE_UNDERFLOW | FE_INEXACT);
+ EXPECT_MATH_ERRNO(ERANGE);
+ }
+ }
+
+ void test_inexact_results(MulFunc func) {
+ InFPBits x_bits = InFPBits::one();
+ x_bits.set_mantissa(InFPBits::SIG_MASK);
+ InType x = x_bits.get_val();
+ func(x, x);
+ EXPECT_FP_EXCEPTION(FE_INEXACT);
+ }
+};
+
+#define LIST_MUL_TESTS(OutType, InType, func) \
+ using LlvmLibcMulTest = MulTest<OutType, InType>; \
+ TEST_F(LlvmLibcMulTest, SpecialNumbers) { test_special_numbers(&func); } \
+ TEST_F(LlvmLibcMulTest, InvalidOperations) { \
+ test_invalid_operations(&func); \
+ } \
+ TEST_F(LlvmLibcMulTest, RangeErrors) { test_range_errors(&func); } \
+ TEST_F(LlvmLibcMulTest, InexactResults) { test_inexact_results(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H
diff --git a/libc/test/src/math/smoke/dmulf128_test.cpp b/libc/test/src/math/smoke/dmulf128_test.cpp
new file mode 100644
index 0000000000000..2ee2d10b9a19b
--- /dev/null
+++ b/libc/test/src/math/smoke/dmulf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for dmulf128 --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/dmulf128.h"
+
+LIST_MUL_TESTS(double, float128, LIBC_NAMESPACE::dmulf128)
diff --git a/libc/test/src/math/smoke/dmull_test.cpp b/libc/test/src/math/smoke/dmull_test.cpp
new file mode 100644
index 0000000000000..1b9c9c2c24ed3
--- /dev/null
+++ b/libc/test/src/math/smoke/dmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for dmull -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/dmull.h"
+
+LIST_MUL_TESTS(double, long double, LIBC_NAMESPACE::dmull)
diff --git a/libc/test/src/math/smoke/f16mul_test.cpp b/libc/test/src/math/smoke/f16mul_test.cpp
new file mode 100644
index 0000000000000..49b443870c483
--- /dev/null
+++ b/libc/test/src/math/smoke/f16mul_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mul ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mul.h"
+
+LIST_MUL_TESTS(float16, double, LIBC_NAMESPACE::f16mul)
diff --git a/libc/test/src/math/smoke/f16mulf128_test.cpp b/libc/test/src/math/smoke/f16mulf128_test.cpp
new file mode 100644
index 0000000000000..46e52cf068a7b
--- /dev/null
+++ b/libc/test/src/math/smoke/f16mulf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mulf128 ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mulf128.h"
+
+LIST_MUL_TESTS(float16, float128, LIBC_NAMESPACE::f16mulf128)
diff --git a/libc/test/src/math/smoke/f16mulf_test.cpp b/libc/test/src/math/smoke/f16mulf_test.cpp
new file mode 100644
index 0000000000000..bf2530863621d
--- /dev/null
+++ b/libc/test/src/math/smoke/f16mulf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mulf ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mulf.h"
+
+LIST_MUL_TESTS(float16, float, LIBC_NAMESPACE::f16mulf)
diff --git a/libc/test/src/math/smoke/f16mull_test.cpp b/libc/test/src/math/smoke/f16mull_test.cpp
new file mode 100644
index 0000000000000..5292ddb87b7f4
--- /dev/null
+++ b/libc/test/src/math/smoke/f16mull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for f16mull ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/f16mull.h"
+
+LIST_MUL_TESTS(float16, long double, LIBC_NAMESPACE::f16mull)
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index 0eb664f7411ee..3f6df66456bac 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -1,13 +1,13 @@
-//===-- Unittests for fmul-------------------------------------------------===//
+//===-- Unittests for fmul ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#include "FMulTest.h"
+#include "MulTest.h"
#include "src/math/fmul.h"
-LIST_FMUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
+LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
diff --git a/libc/test/src/math/smoke/fmulf128_test.cpp b/libc/test/src/math/smoke/fmulf128_test.cpp
new file mode 100644
index 0000000000000..37c8d1cf9908d
--- /dev/null
+++ b/libc/test/src/math/smoke/fmulf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fmulf128 --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/fmulf128.h"
+
+LIST_MUL_TESTS(float, float128, LIBC_NAMESPACE::fmulf128)
diff --git a/libc/test/src/math/smoke/fmull_test.cpp b/libc/test/src/math/smoke/fmull_test.cpp
new file mode 100644
index 0000000000000..ef694063f20dc
--- /dev/null
+++ b/libc/test/src/math/smoke/fmull_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fmull -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MulTest.h"
+
+#include "src/math/fmull.h"
+
+LIST_MUL_TESTS(float, long double, LIBC_NAMESPACE::fmull)
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index b67a9da40bd7b..bb63e0b9f4de0 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -539,7 +539,7 @@ class MPFRNumber {
return result;
}
- MPFRNumber fmul(const MPFRNumber &b) {
+ MPFRNumber mul(const MPFRNumber &b) {
MPFRNumber result(*this);
mpfr_mul(result.value, value, b.value, mpfr_rounding);
return result;
@@ -800,12 +800,12 @@ binary_operation_one_output(Operation op, InputType x, InputType y,
return inputX.fmod(inputY);
case Operation::Hypot:
return inputX.hypot(inputY);
+ case Operation::Mul:
+ return inputX.mul(inputY);
case Operation::Pow:
return inputX.pow(inputY);
case Operation::Sub:
return inputX.sub(inputY);
- case Operation::Fmul:
- return inputX.fmul(inputY);
default:
__builtin_unreachable();
}
@@ -1013,15 +1013,18 @@ void explain_binary_operation_one_output_error(
template void
explain_binary_operation_one_output_error(Operation, const BinaryInput<float> &,
float, double, RoundingMode);
+template void explain_binary_operation_one_output_error(
+ Operation, const BinaryInput<double> &, float, double, RoundingMode);
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<double> &, double, double, RoundingMode);
+template void explain_binary_operation_one_output_error(
+ Operation, const BinaryInput<long double> &, float, double, RoundingMode);
+template void explain_binary_operation_one_output_error(
+ Operation, const BinaryInput<long double> &, double, double, RoundingMode);
template void
explain_binary_operation_one_output_error(Operation,
const BinaryInput<long double> &,
long double, double, RoundingMode);
-
-template void explain_binary_operation_one_output_error(
- Operation, const BinaryInput<double> &, float, double, RoundingMode);
#ifdef LIBC_TYPES_HAS_FLOAT16
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<float16> &, float16, double, RoundingMode);
@@ -1195,6 +1198,12 @@ template bool compare_binary_operation_one_output(Operation,
const BinaryInput<double> &,
double, double, RoundingMode);
template bool
+compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
+ float, double, RoundingMode);
+template bool
+compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
+ double, double, RoundingMode);
+template bool
compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
long double, double, RoundingMode);
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index 28390af9ee6d8..8d51fa4e47726 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -79,9 +79,9 @@ enum class Operation : int {
Div,
Fmod,
Hypot,
+ Mul,
Pow,
Sub,
- Fmul,
EndBinaryOperationsSingleOutput,
// Operations which take two floating point numbers of the same type as
More information about the libc-commits
mailing list