From 9f16ac2f1d4b31aa0af88300dd70738fa8b95b44 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 8 May 2024 14:27:15 -0700 Subject: [PATCH 01/44] start fmul template --- libc/config/linux/aarch64/entrypoints.txt | 3 ++ libc/config/linux/arm/entrypoints.txt | 3 ++ libc/config/linux/riscv/entrypoints.txt | 3 ++ libc/config/linux/x86_64/entrypoints.txt | 3 ++ libc/config/windows/entrypoints.txt | 3 ++ libc/spec/stdc.td | 5 +++ libc/src/__support/FPUtil/BasicOperations.h | 12 +++++++ libc/src/math/CMakeLists.txt | 4 +++ libc/src/math/dmull.h | 18 ++++++++++ libc/src/math/fmul.h | 18 ++++++++++ libc/src/math/fmull.h | 18 ++++++++++ libc/src/math/generic/CMakeLists.txt | 36 +++++++++++++++++++ libc/src/math/generic/dmull.cpp | 19 ++++++++++ libc/src/math/generic/fmul.cpp | 19 ++++++++++ libc/src/math/generic/fmull.cpp | 19 ++++++++++ libc/test/src/math/smoke/CMakeLists.txt | 40 ++++++++++++++++++++- libc/test/src/math/smoke/FMulTest.h | 32 +++++++++++++++++ libc/test/src/math/smoke/dmull_test.cpp | 13 +++++++ libc/test/src/math/smoke/fmul_test.cpp | 13 +++++++ libc/test/src/math/smoke/fmull_test.cpp | 13 +++++++ 20 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 libc/src/math/dmull.h create mode 100644 libc/src/math/fmul.h create mode 100644 libc/src/math/fmull.h create mode 100644 libc/src/math/generic/dmull.cpp create mode 100644 libc/src/math/generic/fmul.cpp create mode 100644 libc/src/math/generic/fmull.cpp create mode 100644 libc/test/src/math/smoke/FMulTest.h create mode 100644 libc/test/src/math/smoke/dmull_test.cpp create mode 100644 libc/test/src/math/smoke/fmul_test.cpp create mode 100644 libc/test/src/math/smoke/fmull_test.cpp diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index ad50b6f59cdcc..c92d238f14f7d 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -394,6 +394,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_num libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl + libc.src.math.fmul + libc.src.math.fmull + libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 335981ff7dc7c..c3bb9bf666764 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -261,6 +261,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_num libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl + libc.src.math.fmul + libc.src.math.fmull + libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.frexp diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 479af40b5b26b..8b4744445ae01 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -402,6 +402,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_num libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl + libc.src.math.fmul + libc.src.math.fmull + libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 5e3ddd34fb4dc..9623f0b967c40 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -421,6 +421,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_num libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl + libc.src.math.fmul + libc.src.math.fmull + libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 71216530c4041..199ce9bc91cd9 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -180,6 +180,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_num libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl + libc.src.math.fmul + libc.src.math.fmull + libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index eb67c9b0b009b..0130ace283a55 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -457,6 +457,11 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"fminimum_mag_numl", RetValSpec, [ArgSpec, ArgSpec]>, GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"fmul", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"fmull", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"dmull", RetValSpec, [ArgSpec, ArgSpec]>, + + FunctionSpec<"fma", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"fmaf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index e5ac101fedc0e..e75b4b9391bb8 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -176,6 +176,18 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } + +LIBC_INLINE float fmul(double x, double y) { + return static_cast(x * y); +} + +LIBC_INLINE float fmull(long double x, long double y) { + return static_cast(x * y); +} + +LIBC_INLINE double dmull(long double x, long double y) { + return static_cast(x * y); +} template , int> = 0> LIBC_INLINE int canonicalize(T &cx, const T &x) { diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index c34c58575441d..dd26109d9db4d 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -164,6 +164,10 @@ add_math_entrypoint_object(fminimum_mag_numf) add_math_entrypoint_object(fminimum_mag_numl) add_math_entrypoint_object(fminimum_mag_numf128) +add_math_entrypoint_object(fmul) +add_math_entrypoint_object(fmull) +add_math_entrypoint_object(dmull) + add_math_entrypoint_object(fmod) add_math_entrypoint_object(fmodf) add_math_entrypoint_object(fmodl) diff --git a/libc/src/math/dmull.h b/libc/src/math/dmull.h new file mode 100644 index 0000000000000..556eb1559d535 --- /dev/null +++ b/libc/src/math/dmull.h @@ -0,0 +1,18 @@ +//===-- 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 + +namespace LIBC_NAMESPACE { + +double dmull(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_DMULL_H diff --git a/libc/src/math/fmul.h b/libc/src/math/fmul.h new file mode 100644 index 0000000000000..fbc1069db733e --- /dev/null +++ b/libc/src/math/fmul.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fmul --------------------------*- 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_FMUL_H +#define LLVM_LIBC_SRC_MATH_FMUL_H + +namespace LIBC_NAMESPACE { + +float fmul(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMUL_H diff --git a/libc/src/math/fmull.h b/libc/src/math/fmull.h new file mode 100644 index 0000000000000..aebf52a9b0c0a --- /dev/null +++ b/libc/src/math/fmull.h @@ -0,0 +1,18 @@ +//===-- 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 + +namespace LIBC_NAMESPACE { + +float fmull(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMULL_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index daaf505008ca1..3554ec088c49f 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -2042,6 +2042,42 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + fmul + SRCS + fmul.cpp + HDRS + ../fmul.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmull + SRCS + fmull.cpp + HDRS + ../fmull.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + dmull + SRCS + dmull.cpp + HDRS + ../dmull.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + add_entrypoint_object( sqrt SRCS diff --git a/libc/src/math/generic/dmull.cpp b/libc/src/math/generic/dmull.cpp new file mode 100644 index 0000000000000..2c70841dc2d28 --- /dev/null +++ b/libc/src/math/generic/dmull.cpp @@ -0,0 +1,19 @@ +//===-- 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/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, dmull, (long double x, long double y)) { + return fputil::dmull(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp new file mode 100644 index 0000000000000..77452013951d7 --- /dev/null +++ b/libc/src/math/generic/fmul.cpp @@ -0,0 +1,19 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmul.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { + return fputil::fmul(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmull.cpp b/libc/src/math/generic/fmull.cpp new file mode 100644 index 0000000000000..f0d0e0d8da22a --- /dev/null +++ b/libc/src/math/generic/fmull.cpp @@ -0,0 +1,19 @@ +//===-- 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/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmull, (long double x, long double y)) { + return fputil::fmull(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 112b2985829ca..30e6a3cb98184 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1911,7 +1911,6 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) - add_fp_unittest( fminimum_mag_numf_test SUITE @@ -1964,6 +1963,45 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + fmul_test + SUITE + libc-math-smoke-tests + SRCS + fmul_test.cpp + HDRS + FMulTest.h + DEPENDS + 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 + FMulTest.h + DEPENDS + libc.src.math.fmull + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + dmull_test + SUITE + libc-math-smoke-tests + SRCS + dmull_test.cpp + HDRS + FMulTest.h + DEPENDS + libc.src.math.dmull + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( sqrtf_test SUITE diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h new file mode 100644 index 0000000000000..d217dc369ef81 --- /dev/null +++ b/libc/test/src/math/smoke/FMulTest.h @@ -0,0 +1,32 @@ +//===-- 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 +class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + +public: + typedef T (*FMulFunc)(R, R); + + void testMul(FMulFunc func) { + EXPECT_FP_EQ(T(1.0), func(1.0, 1.0)); + } + +}; + +#define LIST_FMUL_TESTS(T, R, func) \ + using LlvmLibcFmulTest = FmulTest; \ + TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H 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..f094b2578158f --- /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 "FMulTest.h" + +#include "src/math/dmull.h" + +LIST_FMUL_TESTS(double, long double, LIBC_NAMESPACE::dmull) diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp new file mode 100644 index 0000000000000..0eb664f7411ee --- /dev/null +++ b/libc/test/src/math/smoke/fmul_test.cpp @@ -0,0 +1,13 @@ +//===-- 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 "src/math/fmul.h" + +LIST_FMUL_TESTS(float, double, LIBC_NAMESPACE::fmul) 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..d1151e298c0b6 --- /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 "FMulTest.h" + +#include "src/math/fmull.h" + +LIST_FMUL_TESTS(float, long double, LIBC_NAMESPACE::fmull) From 92d66d8a93d33599ff8ba286f6860838899f494b Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 8 May 2024 14:27:55 -0700 Subject: [PATCH 02/44] format code --- libc/src/__support/FPUtil/BasicOperations.h | 6 ++---- libc/test/src/math/smoke/FMulTest.h | 11 ++++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index e75b4b9391bb8..e3581910e9799 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -176,10 +176,8 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } - -LIBC_INLINE float fmul(double x, double y) { - return static_cast(x * y); -} + +LIBC_INLINE float fmul(double x, double y) { return static_cast(x * y); } LIBC_INLINE float fmull(long double x, long double y) { return static_cast(x * y); diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index d217dc369ef81..412d9eedf1f7c 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -19,14 +19,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { public: typedef T (*FMulFunc)(R, R); - void testMul(FMulFunc func) { - EXPECT_FP_EQ(T(1.0), func(1.0, 1.0)); - } - + void testMul(FMulFunc func) { EXPECT_FP_EQ(T(1.0), func(1.0, 1.0)); } }; -#define LIST_FMUL_TESTS(T, R, func) \ - using LlvmLibcFmulTest = FmulTest; \ - TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } +#define LIST_FMUL_TESTS(T, R, func) \ + using LlvmLibcFmulTest = FmulTest; \ + TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H From f00264caf86d1ba451f669d2c51c81a681df8f3e Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sat, 1 Jun 2024 09:19:25 -0700 Subject: [PATCH 03/44] make actual llvm impl. --- libc/src/__support/FPUtil/BasicOperations.h | 154 +++++++++++++++++++- libc/test/src/math/smoke/FMulTest.h | 6 +- 2 files changed, 158 insertions(+), 2 deletions(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index e3581910e9799..58dc5c7276edc 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -13,6 +13,7 @@ #include "FPBits.h" #include "FEnvImpl.h" +#include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -177,8 +178,159 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } -LIBC_INLINE float fmul(double x, double y) { return static_cast(x * y); } +// helpers for fmul +uint64_t maxu(uint64_t A, uint64_t B) { + return A > B ? A : B; +} + +uint64_t mul(uint64_t a, uint64_t b) { + __uint128_t product = static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product >> 64); +} + + +uint64_t mullow(uint64_t a, uint64_t b) { + __uint128_t product = static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product); +} + + +uint64_t nlz(uint64_t x) { + uint64_t z = 0; + + if (x == 0) return 64; + if (x <= 0x00000000FFFFFFFF) { + z = z + 32; + x = x << 32; + } + if (x <= 0x0000FFFFFFFFFFFF) { + z = z + 16; + x = x << 16; + } + if (x <= 0x00FFFFFFFFFFFFFF) { + z = z + 8; + x = x << 8; + } + if (x <= 0x0FFFFFFFFFFFFFFF) { + z = z + 4; + x = x << 4; + } + if (x <= 0x3FFFFFFFFFFFFFFF) { + z = z + 2; + x = x << 2; + } + if (x <= 0x7FFFFFFFFFFFFFFF) { + z = z + 1; + } + return z; +} + +LIBC_INLINE float fmul(double x, double y) { + + + auto x_bits = FPBits(x); + uint64_t x_u = x_bits.uintval(); + + auto y_bits = FPBits(y); + uint64_t y_u = y_bits.uintval(); + + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; + uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; + + uint64_t exponent_x = absx >> 52; + uint64_t exponent_y = absy >> 52; + + //uint64_t x_normal_bit = absx >= 0x10000000000000; + //uint64_t y_normal_bit = absy >= 0x10000000000000; + + uint64_t mx, my; + + mx = maxu(nlz(absx), 11); + + //lambdax = mx - 11; + + my = maxu(nlz(absy), 11); + + //lambday = my - 11; + + int32_t dm1; + uint64_t mpx, mpy, highs,lows, b; + uint64_t g, hight, lowt, morlowt, c, m; + mpx = (x_u << mx) | 0x8000000000000000; + mpy = (y_u << my) | 0x8000000000000000; + highs = mul(mpx, mpy); + c = highs >= 0x8000000000000000; + lows = mullow(mpx, mpy); + + lowt = (lows != 0); + + g = (highs >> (38 + c)) & 1; + hight = (highs << (55 - c)) != 0; + + int32_t exint = static_cast(exponent_x); + int32_t eyint = static_cast(exponent_y); + int32_t cint = static_cast(c); + dm1 = ((exint + eyint) - 1919) + cint; + + if (dm1 >= 255) { + dm1 = 255; + + m = 0; + } + else if (dm1<=0) { + m = static_cast((highs >> (39 + c)) >> (1 - dm1)); + dm1 = 0; + morlowt = m | lowt; + b = g & (morlowt | hight); + } + else { + m = static_cast(highs >> (39 + c)); + morlowt = m | lowt; + b = g & (morlowt | hight); + } + + uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + + + uint32_t exp16 = sr | (static_cast(dm1) << 23); + if (dm1 == 0) { + uint32_t m2 = static_cast(m); + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); + + + float result32 = cpp::bit_cast(result); + + return result32; + + } else { + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); + + float result16 = cpp::bit_cast(result); + // std::memcpy(&result16, &result, sizeof(result16)); + //result = *reinterpret_cast<_Float16*>(&result); + + return result16; + } +} + /* +LIBC_INLINE float fmul(double x, double y){ + FPBits bitx(x), bity(y); + + long long int product; + long long int p; + + if (bitx.is_normal() && bity.is_normal()) { + product = bitx.get_mantissa() * bity.get_mantissa(); + p = product & ((1ULL << 24) -1); + sr = bitx.sign() ^ bity.sign(); + return pow(-1, sr) * pow(p, p.biased_exponent()); + } +} + */ LIBC_INLINE float fmull(long double x, long double y) { return static_cast(x * y); } diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 412d9eedf1f7c..afaca64d866c1 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -19,7 +19,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { public: typedef T (*FMulFunc)(R, R); - void testMul(FMulFunc func) { EXPECT_FP_EQ(T(1.0), func(1.0, 1.0)); } + void testMul(FMulFunc func) { + EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); + EXPECT_FP_EQ(T(7.34684e-40), func(0x1.0p1,0x1.0p-131)); + EXPECT_FP_EQ(T(5.87747e-39), func(0x1.0p2, 0x1.0p-129)); +} }; #define LIST_FMUL_TESTS(T, R, func) \ From beaea4eca07ab2ffb4ea19fbdbdb39a35072dec4 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sat, 1 Jun 2024 09:20:02 -0700 Subject: [PATCH 04/44] format code --- libc/src/__support/FPUtil/BasicOperations.h | 117 ++++++++++---------- libc/test/src/math/smoke/FMulTest.h | 4 +- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index 58dc5c7276edc..1926659e5f78f 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -180,26 +180,25 @@ LIBC_INLINE T fdim(T x, T y) { // helpers for fmul -uint64_t maxu(uint64_t A, uint64_t B) { - return A > B ? A : B; -} +uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } uint64_t mul(uint64_t a, uint64_t b) { - __uint128_t product = static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product >> 64); + __uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product >> 64); } - uint64_t mullow(uint64_t a, uint64_t b) { - __uint128_t product = static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product); + __uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product); } - uint64_t nlz(uint64_t x) { uint64_t z = 0; - if (x == 0) return 64; + if (x == 0) + return 64; if (x <= 0x00000000FFFFFFFF) { z = z + 32; x = x << 32; @@ -225,10 +224,9 @@ uint64_t nlz(uint64_t x) { } return z; } - + LIBC_INLINE float fmul(double x, double y) { - - + auto x_bits = FPBits(x); uint64_t x_u = x_bits.uintval(); @@ -241,26 +239,26 @@ LIBC_INLINE float fmul(double x, double y) { uint64_t exponent_x = absx >> 52; uint64_t exponent_y = absy >> 52; - //uint64_t x_normal_bit = absx >= 0x10000000000000; - //uint64_t y_normal_bit = absy >= 0x10000000000000; + // uint64_t x_normal_bit = absx >= 0x10000000000000; + // uint64_t y_normal_bit = absy >= 0x10000000000000; uint64_t mx, my; - - mx = maxu(nlz(absx), 11); - //lambdax = mx - 11; + mx = maxu(nlz(absx), 11); + + // lambdax = mx - 11; my = maxu(nlz(absy), 11); - //lambday = my - 11; + // lambday = my - 11; int32_t dm1; - uint64_t mpx, mpy, highs,lows, b; - uint64_t g, hight, lowt, morlowt, c, m; + uint64_t mpx, mpy, highs, lows, b; + uint64_t g, hight, lowt, morlowt, c, m; mpx = (x_u << mx) | 0x8000000000000000; - mpy = (y_u << my) | 0x8000000000000000; - highs = mul(mpx, mpy); - c = highs >= 0x8000000000000000; + mpy = (y_u << my) | 0x8000000000000000; + highs = mul(mpx, mpy); + c = highs >= 0x8000000000000000; lows = mullow(mpx, mpy); lowt = (lows != 0); @@ -275,62 +273,61 @@ LIBC_INLINE float fmul(double x, double y) { if (dm1 >= 255) { dm1 = 255; - + m = 0; - } - else if (dm1<=0) { + } else if (dm1 <= 0) { m = static_cast((highs >> (39 + c)) >> (1 - dm1)); dm1 = 0; morlowt = m | lowt; b = g & (morlowt | hight); - } - else { + } else { m = static_cast(highs >> (39 + c)); morlowt = m | lowt; b = g & (morlowt | hight); } uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); - uint32_t exp16 = sr | (static_cast(dm1) << 23); if (dm1 == 0) { uint32_t m2 = static_cast(m); - uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - - + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); + float result32 = cpp::bit_cast(result); - + return result32; - - } else { - constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - - uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - - float result16 = cpp::bit_cast(result); - // std::memcpy(&result16, &result, sizeof(result16)); - //result = *reinterpret_cast<_Float16*>(&result); - - return result16; - } + + } else { + constexpr uint32_t FLOAT32_MANTISSA_MASK = + 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); + + float result16 = cpp::bit_cast(result); + // std::memcpy(&result16, &result, sizeof(result16)); + // result = *reinterpret_cast<_Float16*>(&result); + + return result16; + } } - /* +/* LIBC_INLINE float fmul(double x, double y){ - FPBits bitx(x), bity(y); - - long long int product; - long long int p; - - if (bitx.is_normal() && bity.is_normal()) { - product = bitx.get_mantissa() * bity.get_mantissa(); - p = product & ((1ULL << 24) -1); - sr = bitx.sign() ^ bity.sign(); - return pow(-1, sr) * pow(p, p.biased_exponent()); - } +FPBits bitx(x), bity(y); + +long long int product; +long long int p; + +if (bitx.is_normal() && bity.is_normal()) { + product = bitx.get_mantissa() * bity.get_mantissa(); + p = product & ((1ULL << 24) -1); + sr = bitx.sign() ^ bity.sign(); + return pow(-1, sr) * pow(p, p.biased_exponent()); +} } - */ +*/ LIBC_INLINE float fmull(long double x, long double y) { return static_cast(x * y); } diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index afaca64d866c1..44cab1e2560a7 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -21,9 +21,9 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { void testMul(FMulFunc func) { EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); - EXPECT_FP_EQ(T(7.34684e-40), func(0x1.0p1,0x1.0p-131)); + EXPECT_FP_EQ(T(7.34684e-40), func(0x1.0p1, 0x1.0p-131)); EXPECT_FP_EQ(T(5.87747e-39), func(0x1.0p2, 0x1.0p-129)); -} + } }; #define LIST_FMUL_TESTS(T, R, func) \ From 54dee21e4a904ae331b45dd41e66ae24ed458c79 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 12:28:39 -0700 Subject: [PATCH 05/44] move fmul function to generic/fmul.cpp --- libc/src/__support/FPUtil/BasicOperations.h | 150 -------------------- libc/src/math/generic/fmul.cpp | 130 ++++++++++++++++- 2 files changed, 129 insertions(+), 151 deletions(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index 1926659e5f78f..c63f4d35eaa61 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -178,156 +178,6 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } -// helpers for fmul - -uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } - -uint64_t mul(uint64_t a, uint64_t b) { - __uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product >> 64); -} - -uint64_t mullow(uint64_t a, uint64_t b) { - __uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product); -} - -uint64_t nlz(uint64_t x) { - uint64_t z = 0; - - if (x == 0) - return 64; - if (x <= 0x00000000FFFFFFFF) { - z = z + 32; - x = x << 32; - } - if (x <= 0x0000FFFFFFFFFFFF) { - z = z + 16; - x = x << 16; - } - if (x <= 0x00FFFFFFFFFFFFFF) { - z = z + 8; - x = x << 8; - } - if (x <= 0x0FFFFFFFFFFFFFFF) { - z = z + 4; - x = x << 4; - } - if (x <= 0x3FFFFFFFFFFFFFFF) { - z = z + 2; - x = x << 2; - } - if (x <= 0x7FFFFFFFFFFFFFFF) { - z = z + 1; - } - return z; -} - -LIBC_INLINE float fmul(double x, double y) { - - auto x_bits = FPBits(x); - uint64_t x_u = x_bits.uintval(); - - auto y_bits = FPBits(y); - uint64_t y_u = y_bits.uintval(); - - uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; - uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; - - uint64_t exponent_x = absx >> 52; - uint64_t exponent_y = absy >> 52; - - // uint64_t x_normal_bit = absx >= 0x10000000000000; - // uint64_t y_normal_bit = absy >= 0x10000000000000; - - uint64_t mx, my; - - mx = maxu(nlz(absx), 11); - - // lambdax = mx - 11; - - my = maxu(nlz(absy), 11); - - // lambday = my - 11; - - int32_t dm1; - uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, morlowt, c, m; - mpx = (x_u << mx) | 0x8000000000000000; - mpy = (y_u << my) | 0x8000000000000000; - highs = mul(mpx, mpy); - c = highs >= 0x8000000000000000; - lows = mullow(mpx, mpy); - - lowt = (lows != 0); - - g = (highs >> (38 + c)) & 1; - hight = (highs << (55 - c)) != 0; - - int32_t exint = static_cast(exponent_x); - int32_t eyint = static_cast(exponent_y); - int32_t cint = static_cast(c); - dm1 = ((exint + eyint) - 1919) + cint; - - if (dm1 >= 255) { - dm1 = 255; - - m = 0; - } else if (dm1 <= 0) { - m = static_cast((highs >> (39 + c)) >> (1 - dm1)); - dm1 = 0; - morlowt = m | lowt; - b = g & (morlowt | hight); - } else { - m = static_cast(highs >> (39 + c)); - morlowt = m | lowt; - b = g & (morlowt | hight); - } - - uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); - - uint32_t exp16 = sr | (static_cast(dm1) << 23); - if (dm1 == 0) { - uint32_t m2 = static_cast(m); - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - - float result32 = cpp::bit_cast(result); - - return result32; - - } else { - constexpr uint32_t FLOAT32_MANTISSA_MASK = - 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - - float result16 = cpp::bit_cast(result); - // std::memcpy(&result16, &result, sizeof(result16)); - // result = *reinterpret_cast<_Float16*>(&result); - - return result16; - } -} -/* -LIBC_INLINE float fmul(double x, double y){ -FPBits bitx(x), bity(y); - -long long int product; -long long int p; - -if (bitx.is_normal() && bity.is_normal()) { - product = bitx.get_mantissa() * bity.get_mantissa(); - p = product & ((1ULL << 24) -1); - sr = bitx.sign() ^ bity.sign(); - return pow(-1, sr) * pow(p, p.biased_exponent()); -} -} -*/ LIBC_INLINE float fmull(long double x, long double y) { return static_cast(x * y); } diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 77452013951d7..f618a168bb42b 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -8,12 +8,140 @@ #include "src/math/fmul.h" #include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/FPBits.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { +namespace Fmul { +uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } + +uint64_t mul(uint64_t a, uint64_t b) { + __uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product >> 64); +} + +uint64_t mullow(uint64_t a, uint64_t b) { + __uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); + return static_cast(product); +} + +uint64_t nlz(uint64_t x) { + uint64_t z = 0; + + if (x == 0) + return 64; + if (x <= 0x00000000FFFFFFFF) { + z = z + 32; + x = x << 32; + } + if (x <= 0x0000FFFFFFFFFFFF) { + z = z + 16; + x = x << 16; + } + if (x <= 0x00FFFFFFFFFFFFFF) { + z = z + 8; + x = x << 8; + } + if (x <= 0x0FFFFFFFFFFFFFFF) { + z = z + 4; + x = x << 4; + } + if (x <= 0x3FFFFFFFFFFFFFFF) { + z = z + 2; + x = x << 2; + } + if (x <= 0x7FFFFFFFFFFFFFFF) { + z = z + 1; + } + return z; +} + +float fmul(double x, double y) { + + auto x_bits = fputil::FPBits(x); + uint64_t x_u = x_bits.uintval(); + + auto y_bits = fputil::FPBits(y); + uint64_t y_u = y_bits.uintval(); + + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; + uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; + + uint64_t exponent_x = absx >> 52; + uint64_t exponent_y = absy >> 52; + + uint64_t mx, my; + + mx = maxu(nlz(absx), 11); + + my = maxu(nlz(absy), 11); + + int32_t dm1; + uint64_t mpx, mpy, highs, lows, b; + uint64_t g, hight, lowt, morlowt, c, m; + mpx = (x_u << mx) | 0x8000000000000000; + mpy = (y_u << my) | 0x8000000000000000; + highs = mul(mpx, mpy); + c = highs >= 0x8000000000000000; + lows = mullow(mpx, mpy); + + lowt = (lows != 0); + + g = (highs >> (38 + c)) & 1; + hight = (highs << (55 - c)) != 0; + + int32_t exint = static_cast(exponent_x); + int32_t eyint = static_cast(exponent_y); + int32_t cint = static_cast(c); + dm1 = ((exint + eyint) - 1919) + cint; + + if (dm1 >= 255) { + dm1 = 255; + + m = 0; + } else if (dm1 <= 0) { + m = static_cast((highs >> (39 + c)) >> (1 - dm1)); + dm1 = 0; + morlowt = m | lowt; + b = g & (morlowt | hight); + } else { + m = static_cast(highs >> (39 + c)); + morlowt = m | lowt; + b = g & (morlowt | hight); + } + + uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + + uint32_t exp16 = sr | (dm1 << 23); + if (dm1 == 0) { + uint32_t m2 = static_cast(m); + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); + + float result32 = cpp::bit_cast(result); + + return result32; + + } else { + constexpr uint32_t FLOAT32_MANTISSA_MASK = + 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); + + float result16 = cpp::bit_cast(result); + + return result16; + } +} +} + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { - return fputil::fmul(x, y); + return Fmul::fmul(x, y); } } // namespace LIBC_NAMESPACE From 3bf640d06c04698ce5b7f98d6e1add86d76d50a8 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 12:28:54 -0700 Subject: [PATCH 06/44] fix tests --- libc/test/src/math/smoke/FMulTest.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 44cab1e2560a7..881ed00c8bd67 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -21,8 +21,9 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { void testMul(FMulFunc func) { EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); - EXPECT_FP_EQ(T(7.34684e-40), func(0x1.0p1, 0x1.0p-131)); - EXPECT_FP_EQ(T(5.87747e-39), func(0x1.0p2, 0x1.0p-129)); + EXPECT_FP_EQ(T(0x1.0p-130), func(0x1.0p1, 0x1.0p-131)); + EXPECT_FP_EQ(T(0x1.0p-127), func(0x1.0p2, 0x1.0p-129)); + } }; From 0c290cef9a0024d27885c81582da76e254c2ebb0 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 12:29:39 -0700 Subject: [PATCH 07/44] clang format --- libc/src/math/generic/fmul.cpp | 4 ++-- libc/test/src/math/smoke/FMulTest.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index f618a168bb42b..e543888b0dc93 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -13,7 +13,7 @@ namespace LIBC_NAMESPACE { -namespace Fmul { +namespace Fmul { uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } uint64_t mul(uint64_t a, uint64_t b) { @@ -138,7 +138,7 @@ float fmul(double x, double y) { return result16; } } -} +} // namespace Fmul LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { return Fmul::fmul(x, y); diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 881ed00c8bd67..6bfb66eaaf869 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -23,7 +23,6 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); EXPECT_FP_EQ(T(0x1.0p-130), func(0x1.0p1, 0x1.0p-131)); EXPECT_FP_EQ(T(0x1.0p-127), func(0x1.0p2, 0x1.0p-129)); - } }; From c33af75640da42b54d588e2b83af8ce16d5b23a9 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 17:16:53 -0700 Subject: [PATCH 08/44] add more test cases --- libc/src/math/generic/fmul.cpp | 23 +++++++++++++++++++++++ libc/test/src/math/smoke/FMulTest.h | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index e543888b0dc93..6aaeb1b32141c 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -61,12 +61,35 @@ uint64_t nlz(uint64_t x) { float fmul(double x, double y) { + auto x_bits = fputil::FPBits(x); uint64_t x_u = x_bits.uintval(); auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_inf()) + return y_bits.inf().get_val(); + if (x_bits.is_inf() && (y_bits.is_subnormal() || y_bits.is_normal())) + return x_bits.inf().get_val(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) + return y_bits.zero().get_val(); + if (x_bits.is_zero() && (y_bits.is_subnormal() || y_bits.is_normal())) + return x_bits.zero().get_val(); + if (x_bits.is_zero() && y_bits.is_zero()) + return x_bits.zero().get_val(); + if (x_bits.is_inf() && y_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + if (y_bits.is_inf() && x_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || x_bits.is_inf()) && y_bits.is_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return fputil::FPBits::quiet_nan().get_val(); + } + if ((y_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || x_bits.is_inf()) && x_bits.is_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return fputil::FPBits::quiet_nan().get_val(); + } uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 6bfb66eaaf869..c0e5650f53dc4 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -16,6 +16,8 @@ template class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + DECLARE_SPECIAL_CONSTANTS(T) + public: typedef T (*FMulFunc)(R, R); @@ -23,6 +25,12 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); EXPECT_FP_EQ(T(0x1.0p-130), func(0x1.0p1, 0x1.0p-131)); EXPECT_FP_EQ(T(0x1.0p-127), func(0x1.0p2, 0x1.0p-129)); + EXPECT_FP_EQ(inf, func(inf, 0x1.0p-129)); + EXPECT_FP_EQ(inf, func(0x1.0p-129, inf)); + EXPECT_FP_EQ(inf, func(inf, 2.0)); + EXPECT_FP_EQ(inf, func(3.0, inf)); + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(0.0, 0x1.0p-129)); } }; From 7f6ca5af43311ebf7bf324e857f53b0242b49b6b Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 17:17:33 -0700 Subject: [PATCH 09/44] format code --- libc/src/math/generic/fmul.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 6aaeb1b32141c..4dbaa96b4ea08 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -61,7 +61,6 @@ uint64_t nlz(uint64_t x) { float fmul(double x, double y) { - auto x_bits = fputil::FPBits(x); uint64_t x_u = x_bits.uintval(); @@ -82,11 +81,15 @@ float fmul(double x, double y) { return fputil::FPBits::quiet_nan().get_val(); if (y_bits.is_inf() && x_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || x_bits.is_inf()) && y_bits.is_nan()) { + if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || + x_bits.is_inf()) && + y_bits.is_nan()) { fputil::raise_except_if_required(FE_INVALID); return fputil::FPBits::quiet_nan().get_val(); } - if ((y_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || x_bits.is_inf()) && x_bits.is_nan()) { + if ((y_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || + x_bits.is_inf()) && + x_bits.is_nan()) { fputil::raise_except_if_required(FE_INVALID); return fputil::FPBits::quiet_nan().get_val(); } From 4cb0426fd9df7c8b028b359644adb36ccfbcb1d4 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 19:05:43 -0700 Subject: [PATCH 10/44] add more test cases --- libc/src/math/generic/fmul.cpp | 30 ++++++++++++++++------------- libc/test/src/math/smoke/FMulTest.h | 12 ++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 4dbaa96b4ea08..91eba559ee286 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -67,32 +67,36 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); + if (x_bits.is_inf() && y_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + + if (y_bits.is_inf() && x_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_inf()) return y_bits.inf().get_val(); + if (x_bits.is_inf() && (y_bits.is_subnormal() || y_bits.is_normal())) return x_bits.inf().get_val(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) return y_bits.zero().get_val(); + if (x_bits.is_zero() && (y_bits.is_subnormal() || y_bits.is_normal())) return x_bits.zero().get_val(); + if (x_bits.is_zero() && y_bits.is_zero()) return x_bits.zero().get_val(); - if (x_bits.is_inf() && y_bits.is_zero()) - return fputil::FPBits::quiet_nan().get_val(); - if (y_bits.is_inf() && x_bits.is_zero()) - return fputil::FPBits::quiet_nan().get_val(); + if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || - x_bits.is_inf()) && - y_bits.is_nan()) { - fputil::raise_except_if_required(FE_INVALID); + x_bits.is_inf() || x_bits.is_nan()) && + y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - } - if ((y_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || - x_bits.is_inf()) && - x_bits.is_nan()) { - fputil::raise_except_if_required(FE_INVALID); + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || + y_bits.is_inf() || y_bits.is_nan()) && + x_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - } + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index c0e5650f53dc4..00fade9e1c442 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -31,6 +31,18 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { EXPECT_FP_EQ(inf, func(3.0, inf)); EXPECT_FP_EQ(0.0, func(0.0, 0.0)); EXPECT_FP_EQ(0.0, func(0.0, 0x1.0p-129)); + EXPECT_FP_EQ(aNaN, func(inf, 0.0)); + EXPECT_FP_EQ(aNaN, func(0.0, inf)); + EXPECT_FP_EQ(aNaN, func(0.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(2.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(0x1.0p-129, aNaN)); + EXPECT_FP_EQ(aNaN, func(inf, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); + EXPECT_FP_EQ(aNaN, func(0.0, sNaN)); + EXPECT_FP_EQ(aNaN, func(2.0, sNaN)); + EXPECT_FP_EQ(aNaN, func(0x1.0p-129, sNaN)); + EXPECT_FP_EQ(aNaN, func(inf, sNaN)); + EXPECT_FP_EQ(aNaN, func(sNaN, sNaN)); } }; From 0433ad034305be64f66b8db5ca4ee4d4a89c02da Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 19:06:08 -0700 Subject: [PATCH 11/44] format code --- libc/src/math/generic/fmul.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 91eba559ee286..0c01340011b7a 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -69,34 +69,34 @@ float fmul(double x, double y) { if (x_bits.is_inf() && y_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - + if (y_bits.is_inf() && x_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_inf()) return y_bits.inf().get_val(); - + if (x_bits.is_inf() && (y_bits.is_subnormal() || y_bits.is_normal())) return x_bits.inf().get_val(); - + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) return y_bits.zero().get_val(); - + if (x_bits.is_zero() && (y_bits.is_subnormal() || y_bits.is_normal())) return x_bits.zero().get_val(); - + if (x_bits.is_zero() && y_bits.is_zero()) return x_bits.zero().get_val(); - + if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || x_bits.is_inf() || x_bits.is_nan()) && - y_bits.is_nan()) + y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && - x_bits.is_nan()) + x_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; From 5b7da13e5e909a39e00c6674100c5b836e5d8aa0 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 20:05:09 -0700 Subject: [PATCH 12/44] delete dmull and fmull stuff --- libc/src/math/dmull.h | 18 ------------------ libc/src/math/fmull.h | 18 ------------------ libc/src/math/generic/dmull.cpp | 19 ------------------- libc/src/math/generic/fmull.cpp | 19 ------------------- libc/test/src/math/smoke/dmull_test.cpp | 13 ------------- libc/test/src/math/smoke/fmull_test.cpp | 13 ------------- 6 files changed, 100 deletions(-) delete mode 100644 libc/src/math/dmull.h delete mode 100644 libc/src/math/fmull.h delete mode 100644 libc/src/math/generic/dmull.cpp delete mode 100644 libc/src/math/generic/fmull.cpp delete mode 100644 libc/test/src/math/smoke/dmull_test.cpp delete mode 100644 libc/test/src/math/smoke/fmull_test.cpp diff --git a/libc/src/math/dmull.h b/libc/src/math/dmull.h deleted file mode 100644 index 556eb1559d535..0000000000000 --- a/libc/src/math/dmull.h +++ /dev/null @@ -1,18 +0,0 @@ -//===-- 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 - -namespace LIBC_NAMESPACE { - -double dmull(long double x, long double y); - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC_MATH_DMULL_H diff --git a/libc/src/math/fmull.h b/libc/src/math/fmull.h deleted file mode 100644 index aebf52a9b0c0a..0000000000000 --- a/libc/src/math/fmull.h +++ /dev/null @@ -1,18 +0,0 @@ -//===-- 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 - -namespace LIBC_NAMESPACE { - -float fmull(long double x, long double y); - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC_MATH_FMULL_H diff --git a/libc/src/math/generic/dmull.cpp b/libc/src/math/generic/dmull.cpp deleted file mode 100644 index 2c70841dc2d28..0000000000000 --- a/libc/src/math/generic/dmull.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===-- 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/BasicOperations.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(double, dmull, (long double x, long double y)) { - return fputil::dmull(x, y); -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmull.cpp b/libc/src/math/generic/fmull.cpp deleted file mode 100644 index f0d0e0d8da22a..0000000000000 --- a/libc/src/math/generic/fmull.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===-- 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/BasicOperations.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(float, fmull, (long double x, long double y)) { - return fputil::fmull(x, y); -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/math/smoke/dmull_test.cpp b/libc/test/src/math/smoke/dmull_test.cpp deleted file mode 100644 index f094b2578158f..0000000000000 --- a/libc/test/src/math/smoke/dmull_test.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//===-- 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 "FMulTest.h" - -#include "src/math/dmull.h" - -LIST_FMUL_TESTS(double, long double, LIBC_NAMESPACE::dmull) diff --git a/libc/test/src/math/smoke/fmull_test.cpp b/libc/test/src/math/smoke/fmull_test.cpp deleted file mode 100644 index d1151e298c0b6..0000000000000 --- a/libc/test/src/math/smoke/fmull_test.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//===-- 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 "FMulTest.h" - -#include "src/math/fmull.h" - -LIST_FMUL_TESTS(float, long double, LIBC_NAMESPACE::fmull) From 4e3bc6087cd180913e97d102b8dffab6e418cd31 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 20:05:25 -0700 Subject: [PATCH 13/44] update --- libc/config/linux/aarch64/entrypoints.txt | 2 -- libc/config/linux/arm/entrypoints.txt | 2 -- libc/config/linux/riscv/entrypoints.txt | 2 -- libc/config/linux/x86_64/entrypoints.txt | 2 -- libc/config/windows/entrypoints.txt | 2 -- libc/spec/stdc.td | 4 +--- libc/src/__support/FPUtil/BasicOperations.h | 9 ------- libc/src/math/CMakeLists.txt | 2 -- libc/src/math/generic/CMakeLists.txt | 24 ------------------- libc/src/math/generic/fmul.cpp | 1 + libc/test/src/math/smoke/CMakeLists.txt | 26 --------------------- 11 files changed, 2 insertions(+), 74 deletions(-) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index c92d238f14f7d..806f487524c3c 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -395,8 +395,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl libc.src.math.fmul - libc.src.math.fmull - libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index c3bb9bf666764..d4f932416bd9f 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -262,8 +262,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl libc.src.math.fmul - libc.src.math.fmull - libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.frexp diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 8b4744445ae01..67abf851b4d50 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -403,8 +403,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl libc.src.math.fmul - libc.src.math.fmull - libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 9623f0b967c40..fe2daa526f69d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -422,8 +422,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl libc.src.math.fmul - libc.src.math.fmull - libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 199ce9bc91cd9..a4898724daf86 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -181,8 +181,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminimum_mag_numf libc.src.math.fminimum_mag_numl libc.src.math.fmul - libc.src.math.fmull - libc.src.math.dmull libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 0130ace283a55..906d71a20774a 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -458,9 +458,7 @@ def StdC : StandardSpec<"stdc"> { GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"fmul", RetValSpec, [ArgSpec, ArgSpec]>, - FunctionSpec<"fmull", RetValSpec, [ArgSpec, ArgSpec]>, - FunctionSpec<"dmull", RetValSpec, [ArgSpec, ArgSpec]>, - + FunctionSpec<"fma", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"fmaf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index c63f4d35eaa61..e5ac101fedc0e 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -13,7 +13,6 @@ #include "FPBits.h" #include "FEnvImpl.h" -#include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -178,14 +177,6 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } -LIBC_INLINE float fmull(long double x, long double y) { - return static_cast(x * y); -} - -LIBC_INLINE double dmull(long double x, long double y) { - return static_cast(x * y); -} - template , int> = 0> LIBC_INLINE int canonicalize(T &cx, const T &x) { FPBits sx(x); diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index dd26109d9db4d..1516cefe7fc01 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -165,8 +165,6 @@ add_math_entrypoint_object(fminimum_mag_numl) add_math_entrypoint_object(fminimum_mag_numf128) add_math_entrypoint_object(fmul) -add_math_entrypoint_object(fmull) -add_math_entrypoint_object(dmull) add_math_entrypoint_object(fmod) add_math_entrypoint_object(fmodf) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 3554ec088c49f..1a6d8233407e1 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -2054,30 +2054,6 @@ add_entrypoint_object( -O2 ) -add_entrypoint_object( - fmull - SRCS - fmull.cpp - HDRS - ../fmull.h - DEPENDS - libc.src.__support.FPUtil.basic_operations - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - dmull - SRCS - dmull.cpp - HDRS - ../dmull.h - DEPENDS - libc.src.__support.FPUtil.basic_operations - COMPILE_OPTIONS - -O2 -) - add_entrypoint_object( sqrt SRCS diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 0c01340011b7a..cfe313ddf8b95 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -92,6 +92,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 30e6a3cb98184..1593e5da76e96 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1976,32 +1976,6 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) -add_fp_unittest( - fmull_test - SUITE - libc-math-smoke-tests - SRCS - fmull_test.cpp - HDRS - FMulTest.h - DEPENDS - libc.src.math.fmull - libc.src.__support.FPUtil.fp_bits -) - -add_fp_unittest( - dmull_test - SUITE - libc-math-smoke-tests - SRCS - dmull_test.cpp - HDRS - FMulTest.h - DEPENDS - libc.src.math.dmull - libc.src.__support.FPUtil.fp_bits -) - add_fp_unittest( sqrtf_test SUITE From 6eba32357c52ffb8fcd68e10972790658a139370 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Sun, 2 Jun 2024 20:05:52 -0700 Subject: [PATCH 14/44] format code --- libc/src/math/generic/fmul.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index cfe313ddf8b95..e2b23c25dc497 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -92,7 +92,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) From 6970e8a0ff7a8046486bb304cae0ca4fbb76107c Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Tue, 4 Jun 2024 23:24:16 -0700 Subject: [PATCH 15/44] make the b formula --- libc/src/math/generic/fmul.cpp | 73 +++++++++++++++++++---------- libc/test/src/math/smoke/FMulTest.h | 54 ++++++++++++--------- 2 files changed, 80 insertions(+), 47 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index e2b23c25dc497..1a6f27b24a4fc 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -9,6 +9,7 @@ #include "src/math/fmul.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -92,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -112,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, morlowt, c, m; + uint64_t g, hight, lowt, c, m; //morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -121,53 +122,73 @@ float fmul(double x, double y) { lowt = (lows != 0); - g = (highs >> (38 + c)) & 1; - hight = (highs << (55 - c)) != 0; int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); dm1 = ((exint + eyint) - 1919) + cint; + uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + Sign prod_sign = (sr == 1) ? Sign::NEG : Sign::POS; + int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { - dm1 = 255; - - m = 0; + if ((round_mode == FE_TOWARDZERO) || + (round_mode == FE_UPWARD && prod_sign.is_neg())|| + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + return fputil::FPBits::max_normal(prod_sign).get_val(); + } + return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { m = static_cast((highs >> (39 + c)) >> (1 - dm1)); + g = (highs >> (39 + c)) & 1; + hight = (highs << (26 - c)) != 0; dm1 = 0; - morlowt = m | lowt; - b = g & (morlowt | hight); } else { m = static_cast(highs >> (39 + c)); - morlowt = m | lowt; - b = g & (morlowt | hight); - } + g = (highs >> (38 + c)) & 1; + hight = (highs << (55 - c)) != 0; - uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + } + // morlowt = m | lowt; + + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO || FE_DOWNWARD) { + b = 0; + } else if (round_mode == FE_UPWARD) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } + + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - if (dm1 == 0) { - uint32_t m2 = static_cast(m); - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - - float result32 = cpp::bit_cast(result); - - return result32; - - } else { + + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - float result16 = cpp::bit_cast(result); + //float result16 = cpp::bit_cast(result); - return result16; + //return result16; + + + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; } + + float result32 = cpp::bit_cast(result); + + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 00fade9e1c442..6fc75412055d6 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -22,27 +22,39 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { typedef T (*FMulFunc)(R, R); void testMul(FMulFunc func) { - EXPECT_FP_EQ(T(15.0), func(3.0, 5.0)); - EXPECT_FP_EQ(T(0x1.0p-130), func(0x1.0p1, 0x1.0p-131)); - EXPECT_FP_EQ(T(0x1.0p-127), func(0x1.0p2, 0x1.0p-129)); - EXPECT_FP_EQ(inf, func(inf, 0x1.0p-129)); - EXPECT_FP_EQ(inf, func(0x1.0p-129, inf)); - EXPECT_FP_EQ(inf, func(inf, 2.0)); - EXPECT_FP_EQ(inf, func(3.0, inf)); - EXPECT_FP_EQ(0.0, func(0.0, 0.0)); - EXPECT_FP_EQ(0.0, func(0.0, 0x1.0p-129)); - EXPECT_FP_EQ(aNaN, func(inf, 0.0)); - EXPECT_FP_EQ(aNaN, func(0.0, inf)); - EXPECT_FP_EQ(aNaN, func(0.0, aNaN)); - EXPECT_FP_EQ(aNaN, func(2.0, aNaN)); - EXPECT_FP_EQ(aNaN, func(0x1.0p-129, aNaN)); - EXPECT_FP_EQ(aNaN, func(inf, aNaN)); - EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); - EXPECT_FP_EQ(aNaN, func(0.0, sNaN)); - EXPECT_FP_EQ(aNaN, func(2.0, sNaN)); - EXPECT_FP_EQ(aNaN, func(0x1.0p-129, sNaN)); - EXPECT_FP_EQ(aNaN, func(inf, sNaN)); - EXPECT_FP_EQ(aNaN, func(sNaN, sNaN)); + + 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(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(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)); + + 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(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)); + } }; From 48b34609910de494f9cd6fe8964feb2aa83f2ac8 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Tue, 4 Jun 2024 23:24:37 -0700 Subject: [PATCH 16/44] format code --- libc/src/math/generic/fmul.cpp | 59 +++++++++++++---------------- libc/test/src/math/smoke/FMulTest.h | 27 +++++++------ 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 1a6f27b24a4fc..5720934a869a4 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -93,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -113,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; //morlowt + uint64_t g, hight, lowt, c, m; // morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -122,7 +122,6 @@ float fmul(double x, double y) { lowt = (lows != 0); - int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); @@ -133,8 +132,8 @@ float fmul(double x, double y) { int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg())|| - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + (round_mode == FE_UPWARD && prod_sign.is_neg()) || + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { return fputil::FPBits::max_normal(prod_sign).get_val(); } return fputil::FPBits::inf().get_val(); @@ -147,48 +146,44 @@ float fmul(double x, double y) { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; - } // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { - b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO || FE_DOWNWARD) { - b = 0; - } else if (round_mode == FE_UPWARD) { - b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; - } - - - // b = g & (morlowt | hight); + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO || FE_DOWNWARD) { + b = 0; + } else if (round_mode == FE_UPWARD) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - - + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - //float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - //return result16; - + // return result16; - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; + } - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 6fc75412055d6..1458fa8fbb419 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -22,7 +22,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -44,17 +44,22 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); - - 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(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)); + 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(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)); } }; From 378e6be8ec82fc3d82d24291d7dd1506cf66e817 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 5 Jun 2024 18:30:34 -0700 Subject: [PATCH 17/44] make the tests pass --- libc/src/math/generic/fmul.cpp | 65 ++++++++++++++++------------- libc/test/src/math/smoke/FMulTest.h | 27 +++++------- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 5720934a869a4..eed3d6caee2f9 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -93,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -113,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; // morlowt + uint64_t g, hight, lowt, c, m; //morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -122,6 +122,7 @@ float fmul(double x, double y) { lowt = (lows != 0); + int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); @@ -132,58 +133,64 @@ float fmul(double x, double y) { int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg()) || - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + (round_mode == FE_UPWARD && prod_sign.is_neg())|| + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { return fputil::FPBits::max_normal(prod_sign).get_val(); } return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { m = static_cast((highs >> (39 + c)) >> (1 - dm1)); - g = (highs >> (39 + c)) & 1; - hight = (highs << (26 - c)) != 0; + g = (highs >> ((39 + c) - dm1)) & 1; + hight = (highs << (64 - ((39 + c) - dm1))) != 0; dm1 = 0; } else { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; - } - // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { - b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO || FE_DOWNWARD) { - b = 0; - } else if (round_mode == FE_UPWARD) { - b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; } + // morlowt = m | lowt; - // b = g & (morlowt | hight); + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO) { + b = 0; + } else if ((sr != 0 && round_mode == FE_DOWNWARD) || (sr == 1 && round_mode == FE_UPWARD)) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } else { + b = 0; + } + + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - + + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - // float result16 = cpp::bit_cast(result); + //float result16 = cpp::bit_cast(result); - // return result16; + //return result16; + - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; + } - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 1458fa8fbb419..4e4f933c80b59 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -22,7 +22,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -44,22 +44,17 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); + + 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(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)); - 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(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)); } }; From 6d2b55d56879324b405cc8267f02c3eefe9d6fe4 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 5 Jun 2024 18:31:00 -0700 Subject: [PATCH 18/44] format code --- libc/src/math/generic/fmul.cpp | 64 ++++++++++++++--------------- libc/test/src/math/smoke/FMulTest.h | 29 ++++++++----- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index eed3d6caee2f9..233034a278fb5 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -93,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -113,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; //morlowt + uint64_t g, hight, lowt, c, m; // morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -122,7 +122,6 @@ float fmul(double x, double y) { lowt = (lows != 0); - int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); @@ -133,8 +132,8 @@ float fmul(double x, double y) { int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg())|| - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + (round_mode == FE_UPWARD && prod_sign.is_neg()) || + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { return fputil::FPBits::max_normal(prod_sign).get_val(); } return fputil::FPBits::inf().get_val(); @@ -147,50 +146,47 @@ float fmul(double x, double y) { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; - } // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { - b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO) { - b = 0; - } else if ((sr != 0 && round_mode == FE_DOWNWARD) || (sr == 1 && round_mode == FE_UPWARD)) { - b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; - } else { - b = 0; - } - - - // b = g & (morlowt | hight); + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO) { + b = 0; + } else if ((sr != 0 && round_mode == FE_DOWNWARD) || + (sr == 1 && round_mode == FE_UPWARD)) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } else { + b = 0; + } + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - - + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - //float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - //return result16; - + // return result16; - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; + } - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 4e4f933c80b59..76bbbbeb58151 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -22,7 +22,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -44,17 +44,24 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); - - 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(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)); + 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( + 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)); } }; From bc080c5435675aeffee56ca60d880e388a5d6773 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 5 Jun 2024 19:06:13 -0700 Subject: [PATCH 19/44] check for undefined behavior --- libc/src/math/generic/fmul.cpp | 70 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 233034a278fb5..55c1ef2eb0209 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -93,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -113,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; // morlowt + uint64_t g, hight, lowt, c, m; //morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -122,6 +122,7 @@ float fmul(double x, double y) { lowt = (lows != 0); + int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); @@ -132,61 +133,64 @@ float fmul(double x, double y) { int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg()) || - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + (round_mode == FE_UPWARD && prod_sign.is_neg())|| + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { return fputil::FPBits::max_normal(prod_sign).get_val(); } return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { - m = static_cast((highs >> (39 + c)) >> (1 - dm1)); - g = (highs >> ((39 + c) - dm1)) & 1; - hight = (highs << (64 - ((39 + c) - dm1))) != 0; + m = 40 + c - dm1 >= 64 ? 0 : static_cast((highs >> (39 + c)) >> (1 - dm1)); + g = 39 + c - dm1 >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; + hight = (64 - ((39 + c) - dm1)) >= 64 ? highs : (highs << (64 - ((39 + c) - dm1))) != 0; dm1 = 0; } else { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; - } - // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { - b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO) { - b = 0; - } else if ((sr != 0 && round_mode == FE_DOWNWARD) || - (sr == 1 && round_mode == FE_UPWARD)) { - b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; - } else { - b = 0; } + // morlowt = m | lowt; - // b = g & (morlowt | hight); + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO) { + b = 0; + } else if ((sr != 0 && round_mode == FE_DOWNWARD) || (sr == 1 && round_mode == FE_UPWARD)) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } else { + b = 0; + } + + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - + + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - // float result16 = cpp::bit_cast(result); + //float result16 = cpp::bit_cast(result); - // return result16; + //return result16; + - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; + } - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From 94bd87779b75dc0dfaa1ba2140ce4d7b99069e06 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Wed, 5 Jun 2024 19:07:04 -0700 Subject: [PATCH 20/44] format code --- libc/src/math/generic/fmul.cpp | 72 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 55c1ef2eb0209..4fd995ea90880 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -93,7 +93,7 @@ float fmul(double x, double y) { x_bits.is_inf() || x_bits.is_nan()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - + if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || y_bits.is_inf() || y_bits.is_nan()) && x_bits.is_nan()) @@ -113,7 +113,7 @@ float fmul(double x, double y) { int32_t dm1; uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; //morlowt + uint64_t g, hight, lowt, c, m; // morlowt mpx = (x_u << mx) | 0x8000000000000000; mpy = (y_u << my) | 0x8000000000000000; highs = mul(mpx, mpy); @@ -122,7 +122,6 @@ float fmul(double x, double y) { lowt = (lows != 0); - int32_t exint = static_cast(exponent_x); int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); @@ -133,64 +132,65 @@ float fmul(double x, double y) { int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg())|| - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { + (round_mode == FE_UPWARD && prod_sign.is_neg()) || + (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { return fputil::FPBits::max_normal(prod_sign).get_val(); } return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { - m = 40 + c - dm1 >= 64 ? 0 : static_cast((highs >> (39 + c)) >> (1 - dm1)); + m = 40 + c - dm1 >= 64 + ? 0 + : static_cast((highs >> (39 + c)) >> (1 - dm1)); g = 39 + c - dm1 >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = (64 - ((39 + c) - dm1)) >= 64 ? highs : (highs << (64 - ((39 + c) - dm1))) != 0; + hight = (64 - ((39 + c) - dm1)) >= 64 + ? highs + : (highs << (64 - ((39 + c) - dm1))) != 0; dm1 = 0; } else { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; - } // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { - b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO) { - b = 0; - } else if ((sr != 0 && round_mode == FE_DOWNWARD) || (sr == 1 && round_mode == FE_UPWARD)) { - b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; - } else { - b = 0; - } - - - // b = g & (morlowt | hight); + if (round_mode == FE_TONEAREST) { + b = g && ((hight && lowt) || ((m & 1) != 0)); + } else if (round_mode == FE_TOWARDZERO) { + b = 0; + } else if ((sr != 0 && round_mode == FE_DOWNWARD) || + (sr == 1 && round_mode == FE_UPWARD)) { + b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; + } else { + b = 0; + } + + // b = g & (morlowt | hight); uint32_t exp16 = sr | (dm1 << 23); - - + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = + uint32_t result = (static_cast(exp16) + m2) + static_cast(b); - //float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - //return result16; - + // return result16; - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } + if (round_mode == FE_TONEAREST) { + if (g && ((hight && lowt) || ((result & 1) != 0))) + ++result; + } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || + (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { + if (g || (hight && lowt)) + ++result; + } - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From bc958c2171ae5a6d989e8c32a6480869569d4139 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 08:21:18 -0700 Subject: [PATCH 21/44] fix bug and add tests --- libc/src/math/generic/fmul.cpp | 14 +------ libc/test/src/math/smoke/FMulTest.h | 57 ++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 4fd995ea90880..94dae14f7ed38 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -152,13 +152,12 @@ float fmul(double x, double y) { hight = (highs << (55 - c)) != 0; } // morlowt = m | lowt; - if (round_mode == FE_TONEAREST) { b = g && ((hight && lowt) || ((m & 1) != 0)); } else if (round_mode == FE_TOWARDZERO) { b = 0; - } else if ((sr != 0 && round_mode == FE_DOWNWARD) || - (sr == 1 && round_mode == FE_UPWARD)) { + } else if ((sr == 1 && round_mode == FE_DOWNWARD) || + (sr == 0 && round_mode == FE_UPWARD)) { b = (g == 0 && (hight && lowt) == 0) ? 0 : 1; } else { b = 0; @@ -179,15 +178,6 @@ float fmul(double x, double y) { // return result16; - if (round_mode == FE_TONEAREST) { - if (g && ((hight && lowt) || ((result & 1) != 0))) - ++result; - } else if ((round_mode == FE_UPWARD && prod_sign.is_pos()) || - (round_mode == FE_DOWNWARD && prod_sign.is_neg())) { - if (g || (hight && lowt)) - ++result; - } - float result32 = cpp::bit_cast(result); return result32; diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 76bbbbeb58151..6cbd63361172f 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,11 +26,50 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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_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(aNaN, 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)); @@ -44,24 +83,6 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); - - 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( - 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)); } }; From 8af1658383198c654314aa5a79e2f139372c891b Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 08:21:41 -0700 Subject: [PATCH 22/44] format code --- libc/test/src/math/smoke/FMulTest.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 6cbd63361172f..184dc8532d797 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,23 +26,28 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(1.0), func(1.0, 1.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( + 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_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)); @@ -68,8 +73,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); From d557571ff196682900a012685c8bb8c10bec0f20 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 16:35:07 -0700 Subject: [PATCH 23/44] add special input test suite --- libc/src/math/generic/fmul.cpp | 37 ++++++++++++++++++++++++++--- libc/test/src/math/smoke/FMulTest.h | 31 ++++++++++++------------ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 94dae14f7ed38..b9b6285a66da2 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -68,18 +68,49 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); + + if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_nan()) + return fputil::FPBits::quiet_nan().get_val(); + + if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_nan()) + return fputil::FPBits::quiet_nan().get_val(); + + if ((x_bits.is_inf() && x_bits.is_neg()) && (y_bits.is_inf() && y_bits.is_neg())) + return x_bits.inf().get_val(); + + + if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + + + if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_zero()) + return fputil::FPBits::quiet_nan().get_val(); + if (x_bits.is_inf() && y_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); if (y_bits.is_inf() && x_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_inf()) - return y_bits.inf().get_val(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && (y_bits.is_inf() && y_bits.is_neg())) + return y_bits.inf(Sign::NEG).get_val(); - if (x_bits.is_inf() && (y_bits.is_subnormal() || y_bits.is_normal())) + if ((x_bits.is_inf() && x_bits.is_neg()) && (y_bits.is_subnormal() || y_bits.is_normal())) + return x_bits.inf(Sign::NEG).get_val(); + + if (x_bits.is_inf() && (y_bits.is_normal() || y_bits.is_subnormal())) return x_bits.inf().get_val(); + if (y_bits.is_inf() && (x_bits.is_normal() || x_bits.is_subnormal())) + return y_bits.inf().get_val(); + + + if (((x_bits.is_subnormal() && x_bits.is_neg()) || (x_bits.is_normal() && x_bits.is_neg())) && (y_bits.is_inf() && y_bits.is_neg())) + return y_bits.inf().get_val(); + + if (((y_bits.is_subnormal() && y_bits.is_neg()) || (y_bits.is_normal() && y_bits.is_neg())) && (x_bits.is_inf() && x_bits.is_neg())) + return y_bits.inf().get_val(); + if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) return y_bits.zero().get_val(); diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 184dc8532d797..3257125faeb14 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,28 +26,23 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(1.0), func(1.0,1.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(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_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)); @@ -62,9 +57,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(aNaN, func(neg_inf, 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)); @@ -73,7 +70,8 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -92,6 +90,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { #define LIST_FMUL_TESTS(T, R, func) \ using LlvmLibcFmulTest = FmulTest; \ - TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } + TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } \ + TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func);} #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H From f0cdabe7054025c17b3a99753e45c9d7eacd1891 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 16:39:09 -0700 Subject: [PATCH 24/44] add tests --- libc/src/math/generic/fmul.cpp | 23 ++++++++++++---------- libc/test/src/math/smoke/FMulTest.h | 30 ++++++++++++++++------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index b9b6285a66da2..8b2a2da26ab72 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -68,21 +68,19 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); - if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - if ((x_bits.is_inf() && x_bits.is_neg()) && (y_bits.is_inf() && y_bits.is_neg())) + if ((x_bits.is_inf() && x_bits.is_neg()) && + (y_bits.is_inf() && y_bits.is_neg())) return x_bits.inf().get_val(); - if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); @@ -92,23 +90,28 @@ float fmul(double x, double y) { if (y_bits.is_inf() && x_bits.is_zero()) return fputil::FPBits::quiet_nan().get_val(); - if ((x_bits.is_subnormal() || x_bits.is_normal()) && (y_bits.is_inf() && y_bits.is_neg())) + if ((x_bits.is_subnormal() || x_bits.is_normal()) && + (y_bits.is_inf() && y_bits.is_neg())) return y_bits.inf(Sign::NEG).get_val(); - if ((x_bits.is_inf() && x_bits.is_neg()) && (y_bits.is_subnormal() || y_bits.is_normal())) + if ((x_bits.is_inf() && x_bits.is_neg()) && + (y_bits.is_subnormal() || y_bits.is_normal())) return x_bits.inf(Sign::NEG).get_val(); - if (x_bits.is_inf() && (y_bits.is_normal() || y_bits.is_subnormal())) + if (x_bits.is_inf() && (y_bits.is_normal() || y_bits.is_subnormal())) return x_bits.inf().get_val(); if (y_bits.is_inf() && (x_bits.is_normal() || x_bits.is_subnormal())) return y_bits.inf().get_val(); - - if (((x_bits.is_subnormal() && x_bits.is_neg()) || (x_bits.is_normal() && x_bits.is_neg())) && (y_bits.is_inf() && y_bits.is_neg())) + if (((x_bits.is_subnormal() && x_bits.is_neg()) || + (x_bits.is_normal() && x_bits.is_neg())) && + (y_bits.is_inf() && y_bits.is_neg())) return y_bits.inf().get_val(); - if (((y_bits.is_subnormal() && y_bits.is_neg()) || (y_bits.is_normal() && y_bits.is_neg())) && (x_bits.is_inf() && x_bits.is_neg())) + if (((y_bits.is_subnormal() && y_bits.is_neg()) || + (y_bits.is_normal() && y_bits.is_neg())) && + (x_bits.is_inf() && x_bits.is_neg())) return y_bits.inf().get_val(); if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 3257125faeb14..596995f727da3 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,23 +26,28 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(1.0), func(1.0, 1.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( + 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_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)); @@ -57,11 +62,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -70,8 +75,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -91,6 +95,6 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { #define LIST_FMUL_TESTS(T, R, func) \ using LlvmLibcFmulTest = FmulTest; \ TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } \ - TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func);} + TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func); } #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H From 18fbdb6a1cfde824fb127c675aa11bf6579bef7e Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 17:06:09 -0700 Subject: [PATCH 25/44] format code --- libc/src/math/generic/fmul.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 8b2a2da26ab72..625525b614751 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -201,20 +201,19 @@ float fmul(double x, double y) { uint32_t exp16 = sr | (dm1 << 23); - constexpr uint32_t FLOAT32_MANTISSA_MASK = - 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); - // float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - // return result16; + // return result16; - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From c3be5691b986f4559e4a1bde596aec382f6e95c7 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 19:09:39 -0700 Subject: [PATCH 26/44] refactor --- libc/src/math/generic/fmul.cpp | 114 ++++++++++++++------------------- 1 file changed, 48 insertions(+), 66 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 625525b614751..b1d9b855284a1 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -68,71 +68,52 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); - if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_nan()) - return fputil::FPBits::quiet_nan().get_val(); - - if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_nan()) - return fputil::FPBits::quiet_nan().get_val(); - - if ((x_bits.is_inf() && x_bits.is_neg()) && - (y_bits.is_inf() && y_bits.is_neg())) - return x_bits.inf().get_val(); + - if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_zero()) + if (x_bits.is_nan() || y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); - if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_zero()) - return fputil::FPBits::quiet_nan().get_val(); - - if (x_bits.is_inf() && y_bits.is_zero()) - return fputil::FPBits::quiet_nan().get_val(); - - if (y_bits.is_inf() && x_bits.is_zero()) - return fputil::FPBits::quiet_nan().get_val(); - - if ((x_bits.is_subnormal() || x_bits.is_normal()) && - (y_bits.is_inf() && y_bits.is_neg())) - return y_bits.inf(Sign::NEG).get_val(); - - if ((x_bits.is_inf() && x_bits.is_neg()) && - (y_bits.is_subnormal() || y_bits.is_normal())) - return x_bits.inf(Sign::NEG).get_val(); - - if (x_bits.is_inf() && (y_bits.is_normal() || y_bits.is_subnormal())) - return x_bits.inf().get_val(); - - if (y_bits.is_inf() && (x_bits.is_normal() || x_bits.is_subnormal())) - return y_bits.inf().get_val(); - - if (((x_bits.is_subnormal() && x_bits.is_neg()) || - (x_bits.is_normal() && x_bits.is_neg())) && - (y_bits.is_inf() && y_bits.is_neg())) - return y_bits.inf().get_val(); - - if (((y_bits.is_subnormal() && y_bits.is_neg()) || - (y_bits.is_normal() && y_bits.is_neg())) && - (x_bits.is_inf() && x_bits.is_neg())) - return y_bits.inf().get_val(); - - if ((x_bits.is_subnormal() || x_bits.is_normal()) && y_bits.is_zero()) - return y_bits.zero().get_val(); - - if (x_bits.is_zero() && (y_bits.is_subnormal() || y_bits.is_normal())) - return x_bits.zero().get_val(); + if (x_bits.is_zero()) { + if (y_bits.is_inf() || (y_bits.is_inf() && y_bits.is_neg())) + return fputil::FPBits::quiet_nan().get_val(); + if (y_bits.is_neg()) + return fputil::FPBits::zero(Sign::NEG).get_val(); + return fputil::FPBits::zero().get_val(); + } - if (x_bits.is_zero() && y_bits.is_zero()) - return x_bits.zero().get_val(); + if (y_bits.is_zero()) { + if (x_bits.is_inf() || (x_bits.is_inf() && x_bits.is_neg())) + return fputil::FPBits::quiet_nan().get_val(); + if (x_bits.is_neg()) + return fputil::FPBits::zero(Sign::NEG).get_val(); + return fputil::FPBits::zero().get_val(); + } + + if ((y_bits.is_inf() && y_bits.is_neg())) { + if (x_bits.is_neg()) + return fputil::FPBits::inf().get_val(); + return fputil::FPBits::inf(Sign::NEG).get_val(); + } - if ((x_bits.is_zero() || x_bits.is_normal() || x_bits.is_subnormal() || - x_bits.is_inf() || x_bits.is_nan()) && - y_bits.is_nan()) - return fputil::FPBits::quiet_nan().get_val(); + if ((x_bits.is_inf() && x_bits.is_neg())) { + if (y_bits.is_neg()) + return fputil::FPBits::inf().get_val(); + return fputil::FPBits::inf(Sign::NEG).get_val(); + } - if ((y_bits.is_zero() || y_bits.is_normal() || y_bits.is_subnormal() || - y_bits.is_inf() || y_bits.is_nan()) && - x_bits.is_nan()) - return fputil::FPBits::quiet_nan().get_val(); + if (x_bits.is_inf()) { + if (y_bits.is_neg()) + return fputil::FPBits::inf(Sign::NEG).get_val(); + return fputil::FPBits::inf().get_val(); + } + if (y_bits.is_inf()) { + if (x_bits.is_neg()) + return fputil::FPBits::inf(Sign::NEG).get_val(); + return fputil::FPBits::inf().get_val(); + } + + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; @@ -201,19 +182,20 @@ float fmul(double x, double y) { uint32_t exp16 = sr | (dm1 << 23); - constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + constexpr uint32_t FLOAT32_MANTISSA_MASK = + 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); - // float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - // return result16; + // return result16; - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From 9c3e7a728092c66976fbb6ca3ee54446897e4ace Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 19:10:05 -0700 Subject: [PATCH 27/44] format code --- libc/src/math/generic/fmul.cpp | 38 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index b1d9b855284a1..713789405c0f7 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -68,8 +68,6 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); - - if (x_bits.is_nan() || y_bits.is_nan()) return fputil::FPBits::quiet_nan().get_val(); @@ -88,15 +86,15 @@ float fmul(double x, double y) { return fputil::FPBits::zero(Sign::NEG).get_val(); return fputil::FPBits::zero().get_val(); } - + if ((y_bits.is_inf() && y_bits.is_neg())) { - if (x_bits.is_neg()) + if (x_bits.is_neg()) return fputil::FPBits::inf().get_val(); return fputil::FPBits::inf(Sign::NEG).get_val(); } - if ((x_bits.is_inf() && x_bits.is_neg())) { - if (y_bits.is_neg()) + if ((x_bits.is_inf() && x_bits.is_neg())) { + if (y_bits.is_neg()) return fputil::FPBits::inf().get_val(); return fputil::FPBits::inf(Sign::NEG).get_val(); } @@ -107,13 +105,12 @@ float fmul(double x, double y) { return fputil::FPBits::inf().get_val(); } - if (y_bits.is_inf()) { - if (x_bits.is_neg()) - return fputil::FPBits::inf(Sign::NEG).get_val(); - return fputil::FPBits::inf().get_val(); + if (y_bits.is_inf()) { + if (x_bits.is_neg()) + return fputil::FPBits::inf(Sign::NEG).get_val(); + return fputil::FPBits::inf().get_val(); } - - + uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; @@ -182,20 +179,19 @@ float fmul(double x, double y) { uint32_t exp16 = sr | (dm1 << 23); - constexpr uint32_t FLOAT32_MANTISSA_MASK = - 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; + uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + uint32_t result = + (static_cast(exp16) + m2) + static_cast(b); - // float result16 = cpp::bit_cast(result); + // float result16 = cpp::bit_cast(result); - // return result16; + // return result16; - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From 2c51d27654f1ffd2ade9bfba205e33380ad7d02b Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 23:10:00 -0700 Subject: [PATCH 28/44] refactor --- libc/src/math/generic/CMakeLists.txt | 4 +- libc/src/math/generic/fmul.cpp | 118 +++++++++++---------------- libc/test/src/math/smoke/FMulTest.h | 32 ++++---- 3 files changed, 68 insertions(+), 86 deletions(-) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 1a6d8233407e1..7d23114b5088d 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -2050,8 +2050,10 @@ add_entrypoint_object( ../fmul.h DEPENDS libc.src.__support.FPUtil.basic_operations + libc.src.__support.uint128 + libc.src.__support.CPP.bit COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 713789405c0f7..dd6cca8fcfc73 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -10,13 +10,15 @@ #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/rounding_mode.h" +#include "src/__support/uint128.h" #include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { namespace Fmul { uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } - + /* uint64_t mul(uint64_t a, uint64_t b) { __uint128_t product = static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); @@ -28,7 +30,8 @@ uint64_t mullow(uint64_t a, uint64_t b) { static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); return static_cast(product); } - + */ + /* uint64_t nlz(uint64_t x) { uint64_t z = 0; @@ -59,6 +62,7 @@ uint64_t nlz(uint64_t x) { } return z; } + */ float fmul(double x, double y) { @@ -68,76 +72,57 @@ float fmul(double x, double y) { auto y_bits = fputil::FPBits(y); uint64_t y_u = y_bits.uintval(); - if (x_bits.is_nan() || y_bits.is_nan()) - return fputil::FPBits::quiet_nan().get_val(); - - if (x_bits.is_zero()) { - if (y_bits.is_inf() || (y_bits.is_inf() && y_bits.is_neg())) - return fputil::FPBits::quiet_nan().get_val(); - if (y_bits.is_neg()) - return fputil::FPBits::zero(Sign::NEG).get_val(); - return fputil::FPBits::zero().get_val(); - } - - if (y_bits.is_zero()) { - if (x_bits.is_inf() || (x_bits.is_inf() && x_bits.is_neg())) - return fputil::FPBits::quiet_nan().get_val(); - if (x_bits.is_neg()) - return fputil::FPBits::zero(Sign::NEG).get_val(); - return fputil::FPBits::zero().get_val(); - } - - if ((y_bits.is_inf() && y_bits.is_neg())) { - if (x_bits.is_neg()) - return fputil::FPBits::inf().get_val(); - return fputil::FPBits::inf(Sign::NEG).get_val(); - } - - if ((x_bits.is_inf() && x_bits.is_neg())) { - if (y_bits.is_neg()) - return fputil::FPBits::inf().get_val(); - return fputil::FPBits::inf(Sign::NEG).get_val(); - } - - if (x_bits.is_inf()) { - if (y_bits.is_neg()) - return fputil::FPBits::inf(Sign::NEG).get_val(); - return fputil::FPBits::inf().get_val(); - } - - if (y_bits.is_inf()) { - if (x_bits.is_neg()) - return fputil::FPBits::inf(Sign::NEG).get_val(); - return fputil::FPBits::inf().get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + // Now either x or y is zero, and the other one is finite. + return fputil::FPBits::zero(output_sign).get_val(); } + + uint64_t mx, my; - uint64_t absx = x_u & 0x7FFFFFFFFFFFFFFF; - uint64_t absy = y_u & 0x7FFFFFFFFFFFFFFF; + // Get mantissa and append the hidden bit if needed. + mx = x_bits.get_explicit_mantissa(); + my = y_bits.get_explicit_mantissa(); - uint64_t exponent_x = absx >> 52; - uint64_t exponent_y = absy >> 52; + // Get the corresponding biased exponent. + int ex = x_bits.get_explicit_exponent(); + int ey = y_bits.get_explicit_exponent(); - uint64_t mx, my; + // Count the number of leading zeros of the explicit mantissas. + int nx = cpp::countl_zero(mx); + int ny = cpp::countl_zero(my); - mx = maxu(nlz(absx), 11); - - my = maxu(nlz(absy), 11); + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t mpx, mpy, highs, lows, b; - uint64_t g, hight, lowt, c, m; // morlowt - mpx = (x_u << mx) | 0x8000000000000000; - mpy = (y_u << my) | 0x8000000000000000; - highs = mul(mpx, mpy); + uint64_t highs, lows, b; + uint64_t g, hight, lowt, m; + bool c; + + highs = static_cast(product >> 64); c = highs >= 0x8000000000000000; - lows = mullow(mpx, mpy); + lows = static_cast(product); lowt = (lows != 0); - int32_t exint = static_cast(exponent_x); - int32_t eyint = static_cast(exponent_y); int32_t cint = static_cast(c); - dm1 = ((exint + eyint) - 1919) + cint; + dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); Sign prod_sign = (sr == 1) ? Sign::NEG : Sign::POS; @@ -163,7 +148,7 @@ float fmul(double x, double y) { g = (highs >> (38 + c)) & 1; hight = (highs << (55 - c)) != 0; } - // morlowt = m | lowt; + if (round_mode == FE_TONEAREST) { b = g && ((hight && lowt) || ((m & 1) != 0)); } else if (round_mode == FE_TOWARDZERO) { @@ -175,23 +160,18 @@ float fmul(double x, double y) { b = 0; } - // b = g & (morlowt | hight); - uint32_t exp16 = sr | (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - - // float result16 = cpp::bit_cast(result); + (static_cast(exp16) + m2) + static_cast(b); - // return result16; - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index 596995f727da3..a9348812c5e0a 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,28 +26,27 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(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(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_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)); @@ -62,11 +61,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -75,7 +74,8 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -95,6 +95,6 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { #define LIST_FMUL_TESTS(T, R, func) \ using LlvmLibcFmulTest = FmulTest; \ TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } \ - TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func); } + TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func);} #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H From b483faa0fceac44b8bcc3753f07a3a7482b8b7d6 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 23:10:22 -0700 Subject: [PATCH 29/44] format code --- libc/src/math/generic/fmul.cpp | 120 +++++++++++++++------------- libc/test/src/math/smoke/FMulTest.h | 30 ++++--- 2 files changed, 80 insertions(+), 70 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index dd6cca8fcfc73..2fbbd8f197dfa 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,62 +7,62 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { namespace Fmul { uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } - /* +/* uint64_t mul(uint64_t a, uint64_t b) { - __uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product >> 64); +__uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); +return static_cast(product >> 64); } uint64_t mullow(uint64_t a, uint64_t b) { - __uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); - return static_cast(product); +__uint128_t product = + static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); +return static_cast(product); } - */ - /* +*/ +/* uint64_t nlz(uint64_t x) { - uint64_t z = 0; +uint64_t z = 0; - if (x == 0) - return 64; - if (x <= 0x00000000FFFFFFFF) { - z = z + 32; - x = x << 32; - } - if (x <= 0x0000FFFFFFFFFFFF) { - z = z + 16; - x = x << 16; - } - if (x <= 0x00FFFFFFFFFFFFFF) { - z = z + 8; - x = x << 8; - } - if (x <= 0x0FFFFFFFFFFFFFFF) { - z = z + 4; - x = x << 4; - } - if (x <= 0x3FFFFFFFFFFFFFFF) { - z = z + 2; - x = x << 2; - } - if (x <= 0x7FFFFFFFFFFFFFFF) { - z = z + 1; - } - return z; +if (x == 0) + return 64; +if (x <= 0x00000000FFFFFFFF) { + z = z + 32; + x = x << 32; } - */ +if (x <= 0x0000FFFFFFFFFFFF) { + z = z + 16; + x = x << 16; +} +if (x <= 0x00FFFFFFFFFFFFFF) { + z = z + 8; + x = x << 8; +} +if (x <= 0x0FFFFFFFFFFFFFFF) { + z = z + 4; + x = x << 4; +} +if (x <= 0x3FFFFFFFFFFFFFFF) { + z = z + 2; + x = x << 2; +} +if (x <= 0x7FFFFFFFFFFFFFFF) { + z = z + 1; +} +return z; +} +*/ float fmul(double x, double y) { @@ -74,19 +74,24 @@ float fmul(double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -105,13 +110,15 @@ float fmul(double x, double y) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -166,12 +173,11 @@ float fmul(double x, double y) { uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - + (static_cast(exp16) + m2) + static_cast(b); - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul diff --git a/libc/test/src/math/smoke/FMulTest.h b/libc/test/src/math/smoke/FMulTest.h index a9348812c5e0a..33fb82c8d2da1 100644 --- a/libc/test/src/math/smoke/FMulTest.h +++ b/libc/test/src/math/smoke/FMulTest.h @@ -26,27 +26,32 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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(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( + 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_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)); @@ -61,11 +66,11 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -74,8 +79,7 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 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)); @@ -95,6 +99,6 @@ class FmulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { #define LIST_FMUL_TESTS(T, R, func) \ using LlvmLibcFmulTest = FmulTest; \ TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); } \ - TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func);} + TEST_F(LlvmLibcFmulTest, NaNInf) { testSpecialInputs(&func); } #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMULTEST_H From fa2d429b66c8236f2e58b6e28591a7bdddd33fc3 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 23:15:02 -0700 Subject: [PATCH 30/44] clean code --- libc/src/math/generic/fmul.cpp | 95 ++++++++-------------------------- 1 file changed, 21 insertions(+), 74 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 2fbbd8f197dfa..691ecddc2bbcc 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,63 +7,17 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { namespace Fmul { -uint64_t maxu(uint64_t A, uint64_t B) { return A > B ? A : B; } -/* -uint64_t mul(uint64_t a, uint64_t b) { -__uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); -return static_cast(product >> 64); -} - -uint64_t mullow(uint64_t a, uint64_t b) { -__uint128_t product = - static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b); -return static_cast(product); -} -*/ -/* -uint64_t nlz(uint64_t x) { -uint64_t z = 0; - -if (x == 0) - return 64; -if (x <= 0x00000000FFFFFFFF) { - z = z + 32; - x = x << 32; -} -if (x <= 0x0000FFFFFFFFFFFF) { - z = z + 16; - x = x << 16; -} -if (x <= 0x00FFFFFFFFFFFFFF) { - z = z + 8; - x = x << 8; -} -if (x <= 0x0FFFFFFFFFFFFFFF) { - z = z + 4; - x = x << 4; -} -if (x <= 0x3FFFFFFFFFFFFFFF) { - z = z + 2; - x = x << 2; -} -if (x <= 0x7FFFFFFFFFFFFFFF) { - z = z + 1; -} -return z; -} -*/ - + float fmul(double x, double y) { auto x_bits = fputil::FPBits(x); @@ -74,24 +28,19 @@ float fmul(double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -105,20 +54,17 @@ float fmul(double x, double y) { // 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -173,11 +119,12 @@ float fmul(double x, double y) { uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); + - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From 5acf04db85e1f107cf46d4f06d03c67de8ac5095 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Thu, 6 Jun 2024 23:15:23 -0700 Subject: [PATCH 31/44] format code --- libc/src/math/generic/fmul.cpp | 48 +++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 691ecddc2bbcc..e4f7e2a9407a1 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,17 +7,17 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { namespace Fmul { - + float fmul(double x, double y) { auto x_bits = fputil::FPBits(x); @@ -28,19 +28,24 @@ float fmul(double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -58,13 +63,15 @@ float fmul(double x, double y) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -119,12 +126,11 @@ float fmul(double x, double y) { uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - + (static_cast(exp16) + m2) + static_cast(b); - float result32 = cpp::bit_cast(result); + float result32 = cpp::bit_cast(result); - return result32; + return result32; } } // namespace Fmul From c41adb2e70b263a9847e0e69254be295191ed635 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 15:00:50 -0700 Subject: [PATCH 32/44] refactor --- libc/src/math/generic/fmul.cpp | 69 +++++++++++++--------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index e4f7e2a9407a1..a0f4c65da0f2b 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,19 +7,16 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - -namespace Fmul { - -float fmul(double x, double y) { - + +LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); uint64_t x_u = x_bits.uintval(); @@ -28,24 +25,19 @@ float fmul(double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -63,15 +55,13 @@ float fmul(double x, double y) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -85,13 +75,12 @@ float fmul(double x, double y) { dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); - Sign prod_sign = (sr == 1) ? Sign::NEG : Sign::POS; int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || - (round_mode == FE_UPWARD && prod_sign.is_neg()) || - (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { - return fputil::FPBits::max_normal(prod_sign).get_val(); + (round_mode == FE_UPWARD && output_sign.is_neg()) || + (round_mode == FE_DOWNWARD && output_sign.is_pos())) { + return fputil::FPBits::max_normal(output_sign).get_val(); } return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { @@ -113,29 +102,23 @@ float fmul(double x, double y) { b = g && ((hight && lowt) || ((m & 1) != 0)); } else if (round_mode == FE_TOWARDZERO) { b = 0; - } else if ((sr == 1 && round_mode == FE_DOWNWARD) || - (sr == 0 && round_mode == FE_UPWARD)) { + } 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 = sr | (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); - - float result32 = cpp::bit_cast(result); + (static_cast(exp16) + m2) + static_cast(b); - return result32; -} -} // namespace Fmul - -LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { - return Fmul::fmul(x, y); + return cpp::bit_cast(result); } } // namespace LIBC_NAMESPACE From ad6c2cf81dd2f65b663e13196cd21693ede01db4 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 15:01:08 -0700 Subject: [PATCH 33/44] format --- libc/src/math/generic/fmul.cpp | 44 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index a0f4c65da0f2b..c013cad211434 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); uint64_t x_u = x_bits.uintval(); @@ -25,19 +25,24 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -55,13 +60,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -109,14 +116,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = sr | (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); return cpp::bit_cast(result); } From a12fc67267c3e1d5e090f429bb913495fec37319 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 18:38:05 -0700 Subject: [PATCH 34/44] update --- libc/src/math/generic/fmul.cpp | 55 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index c013cad211434..432453eda6c2f 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,42 +7,37 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); - uint64_t x_u = x_bits.uintval(); + //uint64_t x_u = x_bits.uintval(); auto y_bits = fputil::FPBits(y); - uint64_t y_u = y_bits.uintval(); + //uint64_t y_u = y_bits.uintval(); 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -60,15 +55,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -81,7 +74,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int32_t cint = static_cast(c); dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; - uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + //uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || @@ -116,15 +109,17 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = sr | (dm1 << 23); + + uint32_t exp16 = (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); - return cpp::bit_cast(result); + auto result_bits = fputil::FPBits(result).set_sign(output_sign); + return result_bits.get_val(); } } // namespace LIBC_NAMESPACE From a27e3aabb15ae8ece64f813f4f035eb89a7e9403 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 18:38:22 -0700 Subject: [PATCH 35/44] format code --- libc/src/math/generic/fmul.cpp | 50 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 432453eda6c2f..fdf298b076c75 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,37 +7,42 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); - //uint64_t x_u = x_bits.uintval(); + // uint64_t x_u = x_bits.uintval(); auto y_bits = fputil::FPBits(y); - //uint64_t y_u = y_bits.uintval(); + // uint64_t y_u = y_bits.uintval(); 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -55,13 +60,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -74,7 +81,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int32_t cint = static_cast(c); dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; - //uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); + // uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || @@ -109,14 +116,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); auto result_bits = fputil::FPBits(result).set_sign(output_sign); return result_bits.get_val(); From a877230d3de9bd66a972706bfb38189886e4e6a5 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 18:49:06 -0700 Subject: [PATCH 36/44] refactor --- libc/src/math/generic/fmul.cpp | 50 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index fdf298b076c75..901e9a8b4834d 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,42 +7,35 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); - // uint64_t x_u = x_bits.uintval(); auto y_bits = fputil::FPBits(y); - // uint64_t y_u = y_bits.uintval(); 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -60,15 +53,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -81,7 +72,6 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int32_t cint = static_cast(c); dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; - // uint32_t sr = static_cast((x_u ^ y_u) & 0x8000000000000000); int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { if ((round_mode == FE_TOWARDZERO) || @@ -116,15 +106,17 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } + uint32_t exp16 = (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); - auto result_bits = fputil::FPBits(result).set_sign(output_sign); + auto result_bits = fputil::FPBits(result); + result_bits.set_sign(output_sign); return result_bits.get_val(); } From eee370b54c190d68a98561c94cd301ae8adb0fce Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 18:49:23 -0700 Subject: [PATCH 37/44] format code --- libc/src/math/generic/fmul.cpp | 44 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 901e9a8b4834d..769448115ff04 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,19 +23,24 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -53,13 +58,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; bool c; @@ -106,14 +113,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = (dm1 << 23); constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); auto result_bits = fputil::FPBits(result); result_bits.set_sign(output_sign); From d54dfd29603ff232e120a0155beb07c8459049d8 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 19:36:05 -0700 Subject: [PATCH 38/44] update math docs --- libc/docs/math/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 28503e1d13ab5..5d1ad2d829466 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -158,7 +158,7 @@ Basic Operations +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | fmod | |check| | |check| | |check| | | |check| | 7.12.10.1 | F.10.7.1 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| fmul | N/A | | | N/A | | 7.12.14.3 | F.10.11 | +| fmul | N/A | |check| | | N/A | | 7.12.14.3 | F.10.11 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | frexp | |check| | |check| | |check| | | |check| | 7.12.6.7 | F.10.3.7 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ From 3ded17668925027598d09c4f97c9bdd5e04247eb Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 19:36:20 -0700 Subject: [PATCH 39/44] address review --- libc/src/math/generic/fmul.cpp | 72 ++++++++++++++++------------------ 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 769448115ff04..8a5b6e47691da 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,24 +23,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -58,26 +53,23 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; - bool c; + int c; highs = static_cast(product >> 64); - c = highs >= 0x8000000000000000; + c = static_cast(highs >= 0x8000000000000000); lows = static_cast(product); lowt = (lows != 0); - int32_t cint = static_cast(c); - dm1 = ex + ey + cint + fputil::FPBits::EXP_BIAS; + dm1 = ex + ey + c + fputil::FPBits::EXP_BIAS; int round_mode = fputil::quick_get_round(); if (dm1 >= 255) { @@ -88,13 +80,17 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { } return fputil::FPBits::inf().get_val(); } else if (dm1 <= 0) { - m = 40 + c - dm1 >= 64 - ? 0 - : static_cast((highs >> (39 + c)) >> (1 - dm1)); - g = 39 + c - dm1 >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = (64 - ((39 + c) - dm1)) >= 64 + + 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(highs >> m_shift); + + g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; + hight = h_shift >= 64 ? highs - : (highs << (64 - ((39 + c) - dm1))) != 0; + : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); @@ -104,8 +100,6 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { if (round_mode == FE_TONEAREST) { b = g && ((hight && lowt) || ((m & 1) != 0)); - } else if (round_mode == FE_TOWARDZERO) { - b = 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; @@ -113,13 +107,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } + uint32_t exp16 = (dm1 << 23); - constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111; - uint32_t m2 = static_cast(m) & FLOAT32_MANTISSA_MASK; + uint32_t m2 = static_cast(m) & fputil::FPBits::FRACTION_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); auto result_bits = fputil::FPBits(result); result_bits.set_sign(output_sign); From c6f9ef9eb16c472e316980f636b5f66c7a8b4b68 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 19:36:46 -0700 Subject: [PATCH 40/44] format code --- libc/src/math/generic/fmul.cpp | 52 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 8a5b6e47691da..0f451099b8665 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,19 +23,24 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -53,13 +58,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; + uint64_t highs, lows, b; uint64_t g, hight, lowt, m; int c; @@ -85,12 +92,10 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int g_shift = m_shift - 1; int h_shift = 64 - g_shift; m = (m_shift >= 64) ? 0 : static_cast(highs >> m_shift); - + g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = h_shift >= 64 - ? highs - : (highs << h_shift) != 0; - + hight = h_shift >= 64 ? highs : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); @@ -107,13 +112,12 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = (dm1 << 23); uint32_t m2 = static_cast(m) & fputil::FPBits::FRACTION_MASK; uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + (static_cast(exp16) + m2) + static_cast(b); auto result_bits = fputil::FPBits(result); result_bits.set_sign(output_sign); From 44a2778e8b1be475b883fe80b835ff5474dac0e1 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 20:05:20 -0700 Subject: [PATCH 41/44] address review --- libc/src/math/generic/CMakeLists.txt | 2 + libc/src/math/generic/fmul.cpp | 59 +++++++++++++--------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 7d23114b5088d..9cd1d2c060894 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -2052,6 +2052,8 @@ add_entrypoint_object( 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 COMPILE_OPTIONS -O3 ) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 0f451099b8665..154c1ec5d7fa6 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,24 +23,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -58,16 +53,16 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows, b; - uint64_t g, hight, lowt, m; + uint64_t highs, lows; + uint64_t g, hight, lowt; + uint32_t m; + uint32_t b; int c; highs = static_cast(product >> 64); @@ -92,10 +87,12 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int g_shift = m_shift - 1; int h_shift = 64 - g_shift; m = (m_shift >= 64) ? 0 : static_cast(highs >> m_shift); - + g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = h_shift >= 64 ? highs : (highs << h_shift) != 0; - + hight = h_shift >= 64 + ? highs + : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); @@ -112,12 +109,12 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } + uint32_t exp16 = (dm1 << 23); - uint32_t m2 = static_cast(m) & fputil::FPBits::FRACTION_MASK; + uint32_t m2 = m & fputil::FPBits::FRACTION_MASK; - uint32_t result = - (static_cast(exp16) + m2) + static_cast(b); + uint32_t result = (exp16 + m2) + b; auto result_bits = fputil::FPBits(result); result_bits.set_sign(output_sign); From 8a14205995d1c3d36489dfa1bbd2683e206fcf82 Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 20:05:46 -0700 Subject: [PATCH 42/44] format code --- libc/src/math/generic/fmul.cpp | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index 154c1ec5d7fa6..cdf013e6f7e66 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,19 +23,24 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -53,13 +58,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows; + uint64_t highs, lows; uint64_t g, hight, lowt; uint32_t m; uint32_t b; @@ -87,12 +94,10 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int g_shift = m_shift - 1; int h_shift = 64 - g_shift; m = (m_shift >= 64) ? 0 : static_cast(highs >> m_shift); - + g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = h_shift >= 64 - ? highs - : (highs << h_shift) != 0; - + hight = h_shift >= 64 ? highs : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); @@ -109,7 +114,6 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = (dm1 << 23); uint32_t m2 = m & fputil::FPBits::FRACTION_MASK; From 6dba1c9fec93b4fcf9f4f417013117da0fd07a3b Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 20:45:52 -0700 Subject: [PATCH 43/44] address review --- libc/src/math/generic/fmul.cpp | 54 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index cdf013e6f7e66..bbf6914f38a62 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/common.h" #include "src/__support/uint128.h" +#include "src/__support/common.h" +#include "src/__support/CPP/bit.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,24 +23,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() - ? fputil::FPBits::quiet_nan().get_val() - : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -58,15 +53,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows; + uint64_t highs, lows; uint64_t g, hight, lowt; uint32_t m; uint32_t b; @@ -94,15 +87,17 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int g_shift = m_shift - 1; int h_shift = 64 - g_shift; m = (m_shift >= 64) ? 0 : static_cast(highs >> m_shift); - - g = g_shift >= 64 ? 0 : (highs >> ((39 + c) - dm1)) & 1; - hight = h_shift >= 64 ? highs : (highs << h_shift) != 0; - + + g = g_shift >= 64 ? 0 : (highs >> g_shift) & 1; + hight = h_shift >= 64 + ? highs + : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); g = (highs >> (38 + c)) & 1; - hight = (highs << (55 - c)) != 0; + hight = (highs << (26 - c)) != 0; } if (round_mode == FE_TONEAREST) { @@ -114,6 +109,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } + uint32_t exp16 = (dm1 << 23); uint32_t m2 = m & fputil::FPBits::FRACTION_MASK; From 0e5f8890713898c7442babe3658354ab549c252f Mon Sep 17 00:00:00 2001 From: Job Hernandez Date: Fri, 7 Jun 2024 20:46:11 -0700 Subject: [PATCH 44/44] format code --- libc/src/math/generic/fmul.cpp | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp index bbf6914f38a62..40af20466a665 100644 --- a/libc/src/math/generic/fmul.cpp +++ b/libc/src/math/generic/fmul.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #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/uint128.h" #include "src/__support/common.h" -#include "src/__support/CPP/bit.h" +#include "src/__support/uint128.h" namespace LIBC_NAMESPACE { - + LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { auto x_bits = fputil::FPBits(x); @@ -23,19 +23,24 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, 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(x); - if (y_bits.is_nan()) - return static_cast(y); - if (x_bits.is_inf()) - return y_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); - if (y_bits.is_inf()) - return x_bits.is_zero() ? fputil::FPBits::quiet_nan().get_val() : fputil::FPBits::inf(output_sign).get_val(); + 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(x); + if (y_bits.is_nan()) + return static_cast(y); + if (x_bits.is_inf()) + return y_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); + if (y_bits.is_inf()) + return x_bits.is_zero() + ? fputil::FPBits::quiet_nan().get_val() + : fputil::FPBits::inf(output_sign).get_val(); // Now either x or y is zero, and the other one is finite. - return fputil::FPBits::zero(output_sign).get_val(); + return fputil::FPBits::zero(output_sign).get_val(); } - + uint64_t mx, my; // Get mantissa and append the hidden bit if needed. @@ -53,13 +58,15 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { 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. + // 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(mx) * static_cast(my); int32_t dm1; - uint64_t highs, lows; + uint64_t highs, lows; uint64_t g, hight, lowt; uint32_t m; uint32_t b; @@ -87,12 +94,10 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { int g_shift = m_shift - 1; int h_shift = 64 - g_shift; m = (m_shift >= 64) ? 0 : static_cast(highs >> m_shift); - + g = g_shift >= 64 ? 0 : (highs >> g_shift) & 1; - hight = h_shift >= 64 - ? highs - : (highs << h_shift) != 0; - + hight = h_shift >= 64 ? highs : (highs << h_shift) != 0; + dm1 = 0; } else { m = static_cast(highs >> (39 + c)); @@ -109,7 +114,6 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) { b = 0; } - uint32_t exp16 = (dm1 << 23); uint32_t m2 = m & fputil::FPBits::FRACTION_MASK;