[libc-commits] [libc] [libc][math][c23] fmul correcly rounded to all rounding modes (PR #91537)
Job Henandez Lara via libc-commits
libc-commits at lists.llvm.org
Thu Jun 6 17:06:46 PDT 2024
https://github.com/Jobhdez updated https://github.com/llvm/llvm-project/pull/91537
>From 9f16ac2f1d4b31aa0af88300dd70738fa8b95b44 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Wed, 8 May 2024 14:27:15 -0700
Subject: [PATCH 01/25] 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<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+ FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+ FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+
FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
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<float>(x * y);
+}
+
+LIBC_INLINE float fmull(long double x, long double y) {
+ return static_cast<float>(x * y);
+}
+
+LIBC_INLINE double dmull(long double x, long double y) {
+ return static_cast<double>(x * y);
+}
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, 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 <typename T, typename R>
+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<T,R>; \
+ 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 <hj93 at protonmail.com>
Date: Wed, 8 May 2024 14:27:55 -0700
Subject: [PATCH 02/25] 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<float>(x * y);
-}
+
+LIBC_INLINE float fmul(double x, double y) { return static_cast<float>(x * y); }
LIBC_INLINE float fmull(long double x, long double y) {
return static_cast<float>(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<T,R>; \
- TEST_F(LlvmLibcFmulTest, Mul) { testMul(&func); }
+#define LIST_FMUL_TESTS(T, R, func) \
+ using LlvmLibcFmulTest = FmulTest<T, R>; \
+ 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 <hj93 at protonmail.com>
Date: Sat, 1 Jun 2024 09:19:25 -0700
Subject: [PATCH 03/25] 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<float>(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<uint64_t>(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<uint64_t>(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<double>(x);
+ uint64_t x_u = x_bits.uintval();
+
+ auto y_bits = FPBits<double>(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<uint32_t>(exponent_x);
+ int32_t eyint = static_cast<uint32_t>(exponent_y);
+ int32_t cint = static_cast<uint32_t>(c);
+ dm1 = ((exint + eyint) - 1919) + cint;
+
+ if (dm1 >= 255) {
+ dm1 = 255;
+
+ m = 0;
+ }
+ else if (dm1<=0) {
+ m = static_cast<uint32_t>((highs >> (39 + c)) >> (1 - dm1));
+ dm1 = 0;
+ morlowt = m | lowt;
+ b = g & (morlowt | hight);
+ }
+ else {
+ m = static_cast<uint32_t>(highs >> (39 + c));
+ morlowt = m | lowt;
+ b = g & (morlowt | hight);
+ }
+
+ uint32_t sr = static_cast<uint32_t>((x_u ^ y_u) & 0x8000000000000000);
+
+
+ uint32_t exp16 = sr | (static_cast<uint32_t>(dm1) << 23);
+ if (dm1 == 0) {
+ uint32_t m2 = static_cast<uint32_t>(m);
+ uint32_t result = (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
+
+ float result32 = cpp::bit_cast<float>(result);
+
+ return result32;
+
+ } else {
+ constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111;
+ uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
+
+ uint32_t result = (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
+ float result16 = cpp::bit_cast<float>(result);
+ // std::memcpy(&result16, &result, sizeof(result16));
+ //result = *reinterpret_cast<_Float16*>(&result);
+
+ return result16;
+ }
+}
+ /*
+LIBC_INLINE float fmul(double x, double y){
+ FPBits<double> 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<float>(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 <hj93 at protonmail.com>
Date: Sat, 1 Jun 2024 09:20:02 -0700
Subject: [PATCH 04/25] 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<uint64_t>(product >> 64);
+ __uint128_t product =
+ static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b);
+ return static_cast<uint64_t>(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<uint64_t>(product);
+ __uint128_t product =
+ static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b);
+ return static_cast<uint64_t>(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<double>(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<uint32_t>((highs >> (39 + c)) >> (1 - dm1));
dm1 = 0;
morlowt = m | lowt;
b = g & (morlowt | hight);
- }
- else {
+ } else {
m = static_cast<uint32_t>(highs >> (39 + c));
morlowt = m | lowt;
b = g & (morlowt | hight);
}
uint32_t sr = static_cast<uint32_t>((x_u ^ y_u) & 0x8000000000000000);
-
uint32_t exp16 = sr | (static_cast<uint32_t>(dm1) << 23);
if (dm1 == 0) {
uint32_t m2 = static_cast<uint32_t>(m);
- uint32_t result = (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
-
-
+ uint32_t result =
+ (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
float result32 = cpp::bit_cast<float>(result);
-
+
return result32;
-
- } else {
- constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111;
- uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
-
- uint32_t result = (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
-
- float result16 = cpp::bit_cast<float>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
+
+ uint32_t result =
+ (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
+ float result16 = cpp::bit_cast<float>(result);
+ // std::memcpy(&result16, &result, sizeof(result16));
+ // result = *reinterpret_cast<_Float16*>(&result);
+
+ return result16;
+ }
}
- /*
+/*
LIBC_INLINE float fmul(double x, double y){
- FPBits<double> 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<double> 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<float>(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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 12:28:39 -0700
Subject: [PATCH 05/25] 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<uint64_t>(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<uint64_t>(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<double>(x);
- uint64_t x_u = x_bits.uintval();
-
- auto y_bits = FPBits<double>(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<uint32_t>(exponent_x);
- int32_t eyint = static_cast<uint32_t>(exponent_y);
- int32_t cint = static_cast<uint32_t>(c);
- dm1 = ((exint + eyint) - 1919) + cint;
-
- if (dm1 >= 255) {
- dm1 = 255;
-
- m = 0;
- } else if (dm1 <= 0) {
- m = static_cast<uint32_t>((highs >> (39 + c)) >> (1 - dm1));
- dm1 = 0;
- morlowt = m | lowt;
- b = g & (morlowt | hight);
- } else {
- m = static_cast<uint32_t>(highs >> (39 + c));
- morlowt = m | lowt;
- b = g & (morlowt | hight);
- }
-
- uint32_t sr = static_cast<uint32_t>((x_u ^ y_u) & 0x8000000000000000);
-
- uint32_t exp16 = sr | (static_cast<uint32_t>(dm1) << 23);
- if (dm1 == 0) {
- uint32_t m2 = static_cast<uint32_t>(m);
- uint32_t result =
- (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
-
- float result32 = cpp::bit_cast<float>(result);
-
- return result32;
-
- } else {
- constexpr uint32_t FLOAT32_MANTISSA_MASK =
- 0b00000000011111111111111111111111;
- uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
-
- uint32_t result =
- (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
-
- float result16 = cpp::bit_cast<float>(result);
- // std::memcpy(&result16, &result, sizeof(result16));
- // result = *reinterpret_cast<_Float16*>(&result);
-
- return result16;
- }
-}
-/*
-LIBC_INLINE float fmul(double x, double y){
-FPBits<double> 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<float>(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<uint64_t>(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<uint64_t>(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<double>(x);
+ uint64_t x_u = x_bits.uintval();
+
+ auto y_bits = fputil::FPBits<double>(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<int32_t>(exponent_x);
+ int32_t eyint = static_cast<int32_t>(exponent_y);
+ int32_t cint = static_cast<int32_t>(c);
+ dm1 = ((exint + eyint) - 1919) + cint;
+
+ if (dm1 >= 255) {
+ dm1 = 255;
+
+ m = 0;
+ } else if (dm1 <= 0) {
+ m = static_cast<uint32_t>((highs >> (39 + c)) >> (1 - dm1));
+ dm1 = 0;
+ morlowt = m | lowt;
+ b = g & (morlowt | hight);
+ } else {
+ m = static_cast<uint32_t>(highs >> (39 + c));
+ morlowt = m | lowt;
+ b = g & (morlowt | hight);
+ }
+
+ uint32_t sr = static_cast<uint32_t>((x_u ^ y_u) & 0x8000000000000000);
+
+ uint32_t exp16 = sr | (dm1 << 23);
+ if (dm1 == 0) {
+ uint32_t m2 = static_cast<uint32_t>(m);
+ uint32_t result =
+ (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
+ float result32 = cpp::bit_cast<float>(result);
+
+ return result32;
+
+ } else {
+ constexpr uint32_t FLOAT32_MANTISSA_MASK =
+ 0b00000000011111111111111111111111;
+ uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
+
+ uint32_t result =
+ (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+
+ float result16 = cpp::bit_cast<float>(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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 12:28:54 -0700
Subject: [PATCH 06/25] 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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 12:29:39 -0700
Subject: [PATCH 07/25] 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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 17:16:53 -0700
Subject: [PATCH 08/25] 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<double>(x);
uint64_t x_u = x_bits.uintval();
auto y_bits = fputil::FPBits<double>(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<float>::quiet_nan().get_val();
+ if (y_bits.is_inf() && x_bits.is_zero())
+ return fputil::FPBits<float>::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<float>::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<float>::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 <typename T, typename R>
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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 17:17:33 -0700
Subject: [PATCH 09/25] 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<double>(x);
uint64_t x_u = x_bits.uintval();
@@ -82,11 +81,15 @@ float fmul(double x, double y) {
return fputil::FPBits<float>::quiet_nan().get_val();
if (y_bits.is_inf() && x_bits.is_zero())
return fputil::FPBits<float>::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<float>::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<float>::quiet_nan().get_val();
}
>From 4cb0426fd9df7c8b028b359644adb36ccfbcb1d4 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 19:05:43 -0700
Subject: [PATCH 10/25] 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<double>(y);
uint64_t y_u = y_bits.uintval();
+ if (x_bits.is_inf() && y_bits.is_zero())
+ return fputil::FPBits<float>::quiet_nan().get_val();
+
+ if (y_bits.is_inf() && x_bits.is_zero())
+ return fputil::FPBits<float>::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<float>::quiet_nan().get_val();
- if (y_bits.is_inf() && x_bits.is_zero())
- return fputil::FPBits<float>::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<float>::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<float>::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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 19:06:08 -0700
Subject: [PATCH 11/25] 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<float>::quiet_nan().get_val();
-
+
if (y_bits.is_inf() && x_bits.is_zero())
return fputil::FPBits<float>::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<float>::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<float>::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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 20:05:09 -0700
Subject: [PATCH 12/25] 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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 20:05:25 -0700
Subject: [PATCH 13/25] 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<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"fmul", RetValSpec<FloatType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
- FunctionSpec<"fmull", RetValSpec<FloatType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
- FunctionSpec<"dmull", RetValSpec<DoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
-
+
FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
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<float>(x * y);
-}
-
-LIBC_INLINE double dmull(long double x, long double y) {
- return static_cast<double>(x * y);
-}
-
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE int canonicalize(T &cx, const T &x) {
FPBits<T> 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<float>::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 <hj93 at protonmail.com>
Date: Sun, 2 Jun 2024 20:05:52 -0700
Subject: [PATCH 14/25] 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<float>::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 <hj93 at protonmail.com>
Date: Tue, 4 Jun 2024 23:24:16 -0700
Subject: [PATCH 15/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(c);
dm1 = ((exint + eyint) - 1919) + cint;
+ uint32_t sr = static_cast<uint32_t>((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<float>::max_normal(prod_sign).get_val();
+ }
+ return fputil::FPBits<float>::inf().get_val();
} else if (dm1 <= 0) {
m = static_cast<uint32_t>((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<uint32_t>(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<uint32_t>((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<uint32_t>(m);
- uint32_t result =
- (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
-
- float result32 = cpp::bit_cast<float>(result);
-
- return result32;
-
- } else {
+
+
constexpr uint32_t FLOAT32_MANTISSA_MASK =
0b00000000011111111111111111111111;
uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- float result16 = cpp::bit_cast<float>(result);
+ //float result16 = cpp::bit_cast<float>(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<float>(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 <hj93 at protonmail.com>
Date: Tue, 4 Jun 2024 23:24:37 -0700
Subject: [PATCH 16/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(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<float>::max_normal(prod_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
@@ -147,48 +146,44 @@ float fmul(double x, double y) {
m = static_cast<uint32_t>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- //float result16 = cpp::bit_cast<float>(result);
+ // float result16 = cpp::bit_cast<float>(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<float>(result);
+ float result32 = cpp::bit_cast<float>(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 <hj93 at protonmail.com>
Date: Wed, 5 Jun 2024 18:30:34 -0700
Subject: [PATCH 17/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(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<float>::max_normal(prod_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
} else if (dm1 <= 0) {
m = static_cast<uint32_t>((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<uint32_t>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- // float result16 = cpp::bit_cast<float>(result);
+ //float result16 = cpp::bit_cast<float>(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<float>(result);
+ float result32 = cpp::bit_cast<float>(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 <hj93 at protonmail.com>
Date: Wed, 5 Jun 2024 18:31:00 -0700
Subject: [PATCH 18/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(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<float>::max_normal(prod_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
@@ -147,50 +146,47 @@ float fmul(double x, double y) {
m = static_cast<uint32_t>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- //float result16 = cpp::bit_cast<float>(result);
+ // float result16 = cpp::bit_cast<float>(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<float>(result);
+ float result32 = cpp::bit_cast<float>(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 <hj93 at protonmail.com>
Date: Wed, 5 Jun 2024 19:06:13 -0700
Subject: [PATCH 19/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(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<float>::max_normal(prod_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
} else if (dm1 <= 0) {
- m = static_cast<uint32_t>((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<uint32_t>((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<uint32_t>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- // float result16 = cpp::bit_cast<float>(result);
+ //float result16 = cpp::bit_cast<float>(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<float>(result);
+ float result32 = cpp::bit_cast<float>(result);
- return result32;
+ return result32;
}
} // namespace Fmul
>From 94bd87779b75dc0dfaa1ba2140ce4d7b99069e06 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Wed, 5 Jun 2024 19:07:04 -0700
Subject: [PATCH 20/25] 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<float>::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<int32_t>(exponent_x);
int32_t eyint = static_cast<int32_t>(exponent_y);
int32_t cint = static_cast<int32_t>(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<float>::max_normal(prod_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
} else if (dm1 <= 0) {
- m = 40 + c - dm1 >= 64 ? 0 : static_cast<uint32_t>((highs >> (39 + c)) >> (1 - dm1));
+ m = 40 + c - dm1 >= 64
+ ? 0
+ : static_cast<uint32_t>((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<uint32_t>(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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
+ uint32_t result =
(static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- //float result16 = cpp::bit_cast<float>(result);
+ // float result16 = cpp::bit_cast<float>(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<float>(result);
+ float result32 = cpp::bit_cast<float>(result);
- return result32;
+ return result32;
}
} // namespace Fmul
>From bc958c2171ae5a6d989e8c32a6480869569d4139 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Thu, 6 Jun 2024 08:21:18 -0700
Subject: [PATCH 21/25] 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<float>(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 <hj93 at protonmail.com>
Date: Thu, 6 Jun 2024 08:21:41 -0700
Subject: [PATCH 22/25] 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 <hj93 at protonmail.com>
Date: Thu, 6 Jun 2024 16:35:07 -0700
Subject: [PATCH 23/25] 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<double>(y);
uint64_t y_u = y_bits.uintval();
+
+ if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_nan())
+ return fputil::FPBits<float>::quiet_nan().get_val();
+
+ if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_nan())
+ return fputil::FPBits<float>::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<float>::quiet_nan().get_val();
+
+
+ if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_zero())
+ return fputil::FPBits<float>::quiet_nan().get_val();
+
if (x_bits.is_inf() && y_bits.is_zero())
return fputil::FPBits<float>::quiet_nan().get_val();
if (y_bits.is_inf() && x_bits.is_zero())
return fputil::FPBits<float>::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<T, R>; \
- 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 <hj93 at protonmail.com>
Date: Thu, 6 Jun 2024 16:39:09 -0700
Subject: [PATCH 24/25] 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<double>(y);
uint64_t y_u = y_bits.uintval();
-
if ((x_bits.is_inf() && x_bits.is_neg()) && y_bits.is_nan())
return fputil::FPBits<float>::quiet_nan().get_val();
if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_nan())
return fputil::FPBits<float>::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<float>::quiet_nan().get_val();
-
if ((y_bits.is_inf() && y_bits.is_neg()) && x_bits.is_zero())
return fputil::FPBits<float>::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<float>::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<T, R>; \
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 <hj93 at protonmail.com>
Date: Thu, 6 Jun 2024 17:06:09 -0700
Subject: [PATCH 25/25] 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<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
+ constexpr uint32_t FLOAT32_MANTISSA_MASK = 0b00000000011111111111111111111111;
+ uint32_t m2 = static_cast<uint32_t>(m) & FLOAT32_MANTISSA_MASK;
- uint32_t result =
- (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
+ uint32_t result =
+ (static_cast<uint32_t>(exp16) + m2) + static_cast<uint32_t>(b);
- // float result16 = cpp::bit_cast<float>(result);
+ // float result16 = cpp::bit_cast<float>(result);
- // return result16;
+ // return result16;
- float result32 = cpp::bit_cast<float>(result);
+ float result32 = cpp::bit_cast<float>(result);
- return result32;
+ return result32;
}
} // namespace Fmul
More information about the libc-commits
mailing list