Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2020-05-19 01:06:01 +0300
committerSiva Chandra Reddy <sivachandra@google.com>2020-06-01 18:36:59 +0300
commit1caedd0c550646557d8d2feb97b3cbba8c48b2d7 (patch)
treef0992458fcbbfe66de36b50ee07e01d527cf9ede /libc
parent26c78e3095f42c066804cf517339002a1028ed61 (diff)
[libc] Add implementations of ceil[f], floor[f] and trunc[f] from math.h.
Reviewers: abrachet Differential Revision: https://reviews.llvm.org/D80612
Diffstat (limited to 'libc')
-rw-r--r--libc/lib/CMakeLists.txt6
-rw-r--r--libc/src/math/CMakeLists.txt60
-rw-r--r--libc/src/math/ceil.cpp16
-rw-r--r--libc/src/math/ceil.h18
-rw-r--r--libc/src/math/ceilf.cpp16
-rw-r--r--libc/src/math/ceilf.h18
-rw-r--r--libc/src/math/floor.cpp16
-rw-r--r--libc/src/math/floor.h18
-rw-r--r--libc/src/math/floorf.cpp16
-rw-r--r--libc/src/math/floorf.h18
-rw-r--r--libc/src/math/trunc.cpp16
-rw-r--r--libc/src/math/trunc.h18
-rw-r--r--libc/src/math/truncf.cpp16
-rw-r--r--libc/src/math/truncf.h18
-rw-r--r--libc/test/src/math/CMakeLists.txt78
-rw-r--r--libc/test/src/math/ceil_test.cpp75
-rw-r--r--libc/test/src/math/ceilf_test.cpp75
-rw-r--r--libc/test/src/math/floor_test.cpp75
-rw-r--r--libc/test/src/math/floorf_test.cpp76
-rw-r--r--libc/test/src/math/trunc_test.cpp75
-rw-r--r--libc/test/src/math/truncf_test.cpp77
-rw-r--r--libc/utils/FPUtil/FloatOperations.h125
-rw-r--r--libc/utils/FPUtil/FloatProperties.h6
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.cpp12
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.h12
25 files changed, 948 insertions, 8 deletions
diff --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index 51f587a2a70a..e0921d93d410 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -50,14 +50,20 @@ add_entrypoint_library(
llvmlibm
DEPENDS
# math.h entrypoints
+ libc.src.math.ceil
+ libc.src.math.ceilf
libc.src.math.cosf
libc.src.math.fabs
libc.src.math.fabsf
+ libc.src.math.floor
+ libc.src.math.floorf
libc.src.math.expf
libc.src.math.exp2f
libc.src.math.round
libc.src.math.sincosf
libc.src.math.sinf
+ libc.src.math.trunc
+ libc.src.math.truncf
)
add_redirector_library(
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 41a20b31996f..a3b1b4f6ec01 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -91,6 +91,66 @@ add_entrypoint_object(
libc.utils.FPUtil.fputil
)
+add_entrypoint_object(
+ trunc
+ SRCS
+ trunc.cpp
+ HDRS
+ trunc.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ truncf
+ SRCS
+ truncf.cpp
+ HDRS
+ truncf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ ceil
+ SRCS
+ ceil.cpp
+ HDRS
+ ceil.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ ceilf
+ SRCS
+ ceilf.cpp
+ HDRS
+ ceilf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ floor
+ SRCS
+ floor.cpp
+ HDRS
+ floor.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ floorf
+ SRCS
+ floorf.cpp
+ HDRS
+ floorf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
add_object_library(
exp_utils
HDRS
diff --git a/libc/src/math/ceil.cpp b/libc/src/math/ceil.cpp
new file mode 100644
index 000000000000..c9af520d1f1f
--- /dev/null
+++ b/libc/src/math/ceil.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of ceil 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(ceil)(double x) { return fputil::ceil(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/ceil.h b/libc/src/math/ceil.h
new file mode 100644
index 000000000000..98188de20e40
--- /dev/null
+++ b/libc/src/math/ceil.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ceil --------------------------*- 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_CEIL_H
+#define LLVM_LIBC_SRC_MATH_CEIL_H
+
+namespace __llvm_libc {
+
+double ceil(double x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_CEIL_H
diff --git a/libc/src/math/ceilf.cpp b/libc/src/math/ceilf.cpp
new file mode 100644
index 000000000000..2d2fb90c47fd
--- /dev/null
+++ b/libc/src/math/ceilf.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of ceilf 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(ceilf)(float x) { return fputil::ceil(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/ceilf.h b/libc/src/math/ceilf.h
new file mode 100644
index 000000000000..e8e64565052a
--- /dev/null
+++ b/libc/src/math/ceilf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ceilf -------------------------*- 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_CEILF_H
+#define LLVM_LIBC_SRC_MATH_CEILF_H
+
+namespace __llvm_libc {
+
+float ceilf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_CEILF_H
diff --git a/libc/src/math/floor.cpp b/libc/src/math/floor.cpp
new file mode 100644
index 000000000000..b2d5f872b453
--- /dev/null
+++ b/libc/src/math/floor.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of floor 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(floor)(double x) { return fputil::floor(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/floor.h b/libc/src/math/floor.h
new file mode 100644
index 000000000000..88a76ebf7d80
--- /dev/null
+++ b/libc/src/math/floor.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for floor -------------------------*- 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_FLOOR_H
+#define LLVM_LIBC_SRC_MATH_FLOOR_H
+
+namespace __llvm_libc {
+
+double floor(double x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FLOOR_H
diff --git a/libc/src/math/floorf.cpp b/libc/src/math/floorf.cpp
new file mode 100644
index 000000000000..397602eacf98
--- /dev/null
+++ b/libc/src/math/floorf.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of floorf 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(floorf)(float x) { return fputil::floor(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/floorf.h b/libc/src/math/floorf.h
new file mode 100644
index 000000000000..029df3ac5c9f
--- /dev/null
+++ b/libc/src/math/floorf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for floorf ------------------------*- 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_FLOORF_H
+#define LLVM_LIBC_SRC_MATH_FLOORF_H
+
+namespace __llvm_libc {
+
+float floorf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FLOORF_H
diff --git a/libc/src/math/trunc.cpp b/libc/src/math/trunc.cpp
new file mode 100644
index 000000000000..7e42fe47d2e7
--- /dev/null
+++ b/libc/src/math/trunc.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of trunc 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(trunc)(double x) { return fputil::trunc(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/trunc.h b/libc/src/math/trunc.h
new file mode 100644
index 000000000000..f7fed01f30d2
--- /dev/null
+++ b/libc/src/math/trunc.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for trunc -------------------------*- 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_TRUNC_H
+#define LLVM_LIBC_SRC_MATH_TRUNC_H
+
+namespace __llvm_libc {
+
+double trunc(double x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_TRUNC_H
diff --git a/libc/src/math/truncf.cpp b/libc/src/math/truncf.cpp
new file mode 100644
index 000000000000..c567865f7227
--- /dev/null
+++ b/libc/src/math/truncf.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of truncf 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(truncf)(float x) { return fputil::trunc(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/truncf.h b/libc/src/math/truncf.h
new file mode 100644
index 000000000000..b4f1cd7ea72f
--- /dev/null
+++ b/libc/src/math/truncf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for truncf ------------------------*- 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_TRUNCF_H
+#define LLVM_LIBC_SRC_MATH_TRUNCF_H
+
+namespace __llvm_libc {
+
+float truncf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_TRUNCF_H
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ed36faaee4d8..3568b20a537c 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -98,6 +98,84 @@ add_math_unittest(
)
add_math_unittest(
+ trunc_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ trunc_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.trunc
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ truncf_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ truncf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.truncf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ ceil_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ ceil_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.ceil
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ ceilf_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ ceilf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.ceilf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ floor_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ floor_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.floor
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ floorf_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ floorf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.floorf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
expf_test
NEED_MPFR
SUITE
diff --git a/libc/test/src/math/ceil_test.cpp b/libc/test/src/math/ceil_test.cpp
new file mode 100644
index 000000000000..fdb45a81db97
--- /dev/null
+++ b/libc/test/src/math/ceil_test.cpp
@@ -0,0 +1,75 @@
+//===-- Unittests for ceil ------------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/ceil.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<double>;
+using Properties = __llvm_libc::fputil::FloatProperties<double>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(ceilTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::ceil(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::ceil(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(
+ __llvm_libc::ceil(valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::ceil(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::ceil(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf,
+ valueAsBits(__llvm_libc::ceil(valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::ceil(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::ceil(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(ceilTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::ceil(1.0)));
+ EXPECT_EQ(valueAsBits(-1.0), valueAsBits(__llvm_libc::ceil(-1.0)));
+ EXPECT_EQ(valueAsBits(10.0), valueAsBits(__llvm_libc::ceil(10.0)));
+ EXPECT_EQ(valueAsBits(-10.0), valueAsBits(__llvm_libc::ceil(-10.0)));
+ EXPECT_EQ(valueAsBits(12345.0), valueAsBits(__llvm_libc::ceil(12345.0)));
+ EXPECT_EQ(valueAsBits(-12345.0), valueAsBits(__llvm_libc::ceil(-12345.0)));
+}
+
+TEST(ceilTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT64_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Ceil, x, __llvm_libc::ceil(x),
+ tolerance);
+ }
+}
diff --git a/libc/test/src/math/ceilf_test.cpp b/libc/test/src/math/ceilf_test.cpp
new file mode 100644
index 000000000000..7bfb2ac15b6a
--- /dev/null
+++ b/libc/test/src/math/ceilf_test.cpp
@@ -0,0 +1,75 @@
+//===-- Unittests for ceilf -----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/ceilf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<float>;
+using Properties = __llvm_libc::fputil::FloatProperties<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(CeilfTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::ceilf(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::ceilf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::ceilf(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::ceilf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::ceilf(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::ceilf(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::ceilf(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::ceilf(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(ceilfTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::ceilf(1.0f)));
+ EXPECT_EQ(valueAsBits(-1.0f), valueAsBits(__llvm_libc::ceilf(-1.0f)));
+ EXPECT_EQ(valueAsBits(10.0f), valueAsBits(__llvm_libc::ceilf(10.0f)));
+ EXPECT_EQ(valueAsBits(-10.0f), valueAsBits(__llvm_libc::ceilf(-10.0f)));
+ EXPECT_EQ(valueAsBits(12345.0f), valueAsBits(__llvm_libc::ceilf(12345.0f)));
+ EXPECT_EQ(valueAsBits(-12345.0f), valueAsBits(__llvm_libc::ceilf(-12345.0f)));
+}
+
+TEST(ceilfTest, InFloatRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Ceil, x, __llvm_libc::ceilf(x),
+ tolerance);
+ }
+}
diff --git a/libc/test/src/math/floor_test.cpp b/libc/test/src/math/floor_test.cpp
new file mode 100644
index 000000000000..a45d75710b8a
--- /dev/null
+++ b/libc/test/src/math/floor_test.cpp
@@ -0,0 +1,75 @@
+//===-- Unittests for floor -----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/floor.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<double>;
+using Properties = __llvm_libc::fputil::FloatProperties<double>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(FloorTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::floor(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::floor(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::floor(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::floor(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::floor(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::floor(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::floor(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::floor(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(floorTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::floor(1.0)));
+ EXPECT_EQ(valueAsBits(-1.0), valueAsBits(__llvm_libc::floor(-1.0)));
+ EXPECT_EQ(valueAsBits(10.0), valueAsBits(__llvm_libc::floor(10.0)));
+ EXPECT_EQ(valueAsBits(-10.0), valueAsBits(__llvm_libc::floor(-10.0)));
+ EXPECT_EQ(valueAsBits(12345.0), valueAsBits(__llvm_libc::floor(12345.0)));
+ EXPECT_EQ(valueAsBits(-12345.0), valueAsBits(__llvm_libc::floor(-12345.0)));
+}
+
+TEST(floorTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT64_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Floor, x, __llvm_libc::floor(x),
+ tolerance);
+ }
+}
diff --git a/libc/test/src/math/floorf_test.cpp b/libc/test/src/math/floorf_test.cpp
new file mode 100644
index 000000000000..c25014da1257
--- /dev/null
+++ b/libc/test/src/math/floorf_test.cpp
@@ -0,0 +1,76 @@
+//===-- Unittests for floorf ----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/floorf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<float>;
+using Properties = __llvm_libc::fputil::FloatProperties<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(FloorfTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::floorf(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::floorf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::floorf(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::floorf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::floorf(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::floorf(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::floorf(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::floorf(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(floorfTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::floorf(1.0f)));
+ EXPECT_EQ(valueAsBits(-1.0f), valueAsBits(__llvm_libc::floorf(-1.0f)));
+ EXPECT_EQ(valueAsBits(10.0f), valueAsBits(__llvm_libc::floorf(10.0f)));
+ EXPECT_EQ(valueAsBits(-10.0f), valueAsBits(__llvm_libc::floorf(-10.0f)));
+ EXPECT_EQ(valueAsBits(12345.0f), valueAsBits(__llvm_libc::floorf(12345.0f)));
+ EXPECT_EQ(valueAsBits(-12345.0f),
+ valueAsBits(__llvm_libc::floorf(-12345.0f)));
+}
+
+TEST(floorfTest, InFloatRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Floor, x, __llvm_libc::floorf(x),
+ tolerance);
+ }
+}
diff --git a/libc/test/src/math/trunc_test.cpp b/libc/test/src/math/trunc_test.cpp
new file mode 100644
index 000000000000..55f34a649e9f
--- /dev/null
+++ b/libc/test/src/math/trunc_test.cpp
@@ -0,0 +1,75 @@
+//===-- Unittests for trunc -----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/trunc.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<double>;
+using Properties = __llvm_libc::fputil::FloatProperties<double>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(TruncTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::trunc(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::trunc(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::trunc(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::trunc(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::trunc(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::trunc(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::trunc(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::trunc(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(TruncTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::trunc(1.0)));
+ EXPECT_EQ(valueAsBits(-1.0), valueAsBits(__llvm_libc::trunc(-1.0)));
+ EXPECT_EQ(valueAsBits(10.0), valueAsBits(__llvm_libc::trunc(10.0)));
+ EXPECT_EQ(valueAsBits(-10.0), valueAsBits(__llvm_libc::trunc(-10.0)));
+ EXPECT_EQ(valueAsBits(12345.0), valueAsBits(__llvm_libc::trunc(12345.0)));
+ EXPECT_EQ(valueAsBits(-12345.0), valueAsBits(__llvm_libc::trunc(-12345.0)));
+}
+
+TEST(truncTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT64_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Trunc, x, __llvm_libc::trunc(x),
+ tolerance);
+ }
+}
diff --git a/libc/test/src/math/truncf_test.cpp b/libc/test/src/math/truncf_test.cpp
new file mode 100644
index 000000000000..90fc84a5b5f9
--- /dev/null
+++ b/libc/test/src/math/truncf_test.cpp
@@ -0,0 +1,77 @@
+//===-- Unittests for truncf ----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/truncf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<float>;
+using Properties = __llvm_libc::fputil::FloatProperties<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::floatPrecision, 0,
+ 0};
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+TEST(TruncfTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::truncf(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::truncf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::truncf(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::truncf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::truncf(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::truncf(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::truncf(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::truncf(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(TruncTest, RoundedNumbers) {
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::truncf(1.0f)));
+ EXPECT_EQ(valueAsBits(-1.0f), valueAsBits(__llvm_libc::truncf(-1.0f)));
+ EXPECT_EQ(valueAsBits(10.0f), valueAsBits(__llvm_libc::truncf(10.0f)));
+ EXPECT_EQ(valueAsBits(-10.0f), valueAsBits(__llvm_libc::truncf(-10.0f)));
+ EXPECT_EQ(valueAsBits(12345.0f), valueAsBits(__llvm_libc::truncf(12345.0f)));
+ EXPECT_EQ(valueAsBits(-12345.0f),
+ valueAsBits(__llvm_libc::truncf(-12345.0f)));
+}
+
+TEST(truncfTest, InFloatRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Trunc, x, __llvm_libc::truncf(x),
+ tolerance);
+ }
+}
diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h
index ff7604bc8102..a378903c38b4 100644
--- a/libc/utils/FPUtil/FloatOperations.h
+++ b/libc/utils/FPUtil/FloatOperations.h
@@ -40,18 +40,23 @@ static inline typename FloatProperties<T>::BitsType absBits(T x) {
return valueAsBits(x) & (~FloatProperties<T>::signMask);
}
-// Return the zero adjusted exponent value of x.
-template <typename T,
- cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
-int getExponent(T x) {
- using Properties = FloatProperties<T>;
- using BitsType = typename Properties::BitsType;
- BitsType bits = absBits(x);
+template <typename BitsType>
+static inline int getExponentFromBits(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ using Properties = FloatProperties<FPType>;
+ bits &= Properties::exponentMask;
int e = (bits >> Properties::mantissaWidth); // Shift out the mantissa.
e -= Properties::exponentOffset; // Zero adjust.
return e;
}
+// Return the zero adjusted exponent value of x.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline int getExponent(T x) {
+ return getExponentFromBits(valueAsBits(x));
+}
+
// Return true if x is infinity (positive or negative.)
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
@@ -74,6 +79,24 @@ static inline bool isNaN(T x) {
((bits & Properties::mantissaMask) != 0);
}
+template <typename BitsType> static inline bool bitsAreInfOrNaN(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return (bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf;
+}
+
+template <typename BitsType> static inline bool bitsAreZero(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return (bits == BitPatterns<FPType>::zero) ||
+ (bits == BitPatterns<FPType>::negZero);
+}
+
+// Return true if x is any kind of NaN or infinity.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline bool isInfOrNaN(T x) {
+ return bitsAreInfOrNaN(valueAsBits(x));
+}
+
// Return true if x is a quiet NAN.
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
@@ -103,6 +126,94 @@ static inline T abs(T x) {
return valueFromBits(absBits(x));
}
+// Return the trucated value of x. If x is non-negative, then the return value
+// is greatest integer less than or equal to x. Otherwise, return the smallest
+// integer greater than or equal to x. That is, return the integer value rounded
+// toward zero.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T trunc(T x) {
+ using Properties = FloatProperties<T>;
+ using BitsType = typename FloatProperties<T>::BitsType;
+
+ BitsType bits = valueAsBits(x);
+
+ // If x is infinity, NaN or zero, return it.
+ if (bitsAreInfOrNaN(bits) || bitsAreZero(bits))
+ return x;
+
+ int exponent = getExponentFromBits(bits);
+
+ // If the exponent is greater than the most negative mantissa
+ // exponent, then x is already an integer.
+ if (exponent >= static_cast<int>(Properties::mantissaWidth))
+ return x;
+
+ // If the exponent is such that abs(x) is less than 1, then return 0.
+ if (exponent <= -1) {
+ if (Properties::signMask & bits)
+ return T(-0.0);
+ else
+ return T(0.0);
+ }
+
+ uint32_t trimSize = Properties::mantissaWidth - exponent;
+ return valueFromBits((bits >> trimSize) << trimSize);
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T ceil(T x) {
+ using Properties = FloatProperties<T>;
+ using BitsType = typename FloatProperties<T>::BitsType;
+
+ BitsType bits = valueAsBits(x);
+
+ // If x is infinity NaN or zero, return it.
+ if (bitsAreInfOrNaN(bits) || bitsAreZero(bits))
+ return x;
+
+ bool isNeg = bits & Properties::signMask;
+ int exponent = getExponentFromBits(bits);
+
+ // If the exponent is greater than the most negative mantissa
+ // exponent, then x is already an integer.
+ if (exponent >= static_cast<int>(Properties::mantissaWidth))
+ return x;
+
+ if (exponent <= -1) {
+ if (isNeg)
+ return T(-0.0);
+ else
+ return T(1.0);
+ }
+
+ uint32_t trimSize = Properties::mantissaWidth - exponent;
+ // If x is already an integer, return it.
+ if ((bits << (Properties::bitWidth - trimSize)) == 0)
+ return x;
+
+ BitsType truncBits = (bits >> trimSize) << trimSize;
+ T truncValue = valueFromBits(truncBits);
+
+ // If x is negative, the ceil operation is equivalent to the trunc operation.
+ if (isNeg)
+ return truncValue;
+
+ return truncValue + T(1.0);
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T floor(T x) {
+ auto bits = valueAsBits(x);
+ if (FloatProperties<T>::signMask & bits) {
+ return -ceil(-x);
+ } else {
+ return trunc(x);
+ }
+}
+
} // namespace fputil
} // namespace __llvm_libc
diff --git a/libc/utils/FPUtil/FloatProperties.h b/libc/utils/FPUtil/FloatProperties.h
index a9584c7428a1..fb0917259b91 100644
--- a/libc/utils/FPUtil/FloatProperties.h
+++ b/libc/utils/FPUtil/FloatProperties.h
@@ -21,9 +21,12 @@ template <> struct FloatProperties<float> {
static_assert(sizeof(BitsType) == sizeof(float),
"Unexpected size of 'float' type.");
+ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
+
static constexpr uint32_t mantissaWidth = 23;
static constexpr BitsType mantissaMask = 0x007fffffU;
static constexpr BitsType signMask = 0x80000000U;
+ static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentOffset = 127;
// If a number x is a NAN, then it is a quiet NAN if:
@@ -37,9 +40,12 @@ template <> struct FloatProperties<double> {
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");
+ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
+
static constexpr uint32_t mantissaWidth = 52;
static constexpr BitsType mantissaMask = 0x000fffffffffffffU;
static constexpr BitsType signMask = 0x8000000000000000ULL;
+ static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentOffset = 1023;
// If a number x is a NAN, then it is a quiet NAN if:
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 51c8c3759292..1bbc84d554c0 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -89,6 +89,9 @@ public:
case Operation::Abs:
mpfr_abs(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Ceil:
+ mpfr_ceil(value, mpfrInput.value);
+ break;
case Operation::Cos:
mpfr_cos(value, mpfrInput.value, MPFR_RNDN);
break;
@@ -98,9 +101,18 @@ public:
case Operation::Exp2:
mpfr_exp2(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Floor:
+ mpfr_floor(value, mpfrInput.value);
+ break;
+ case Operation::Round:
+ mpfr_round(value, mpfrInput.value);
+ break;
case Operation::Sin:
mpfr_sin(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Trunc:
+ mpfr_trunc(value, mpfrInput.value);
+ break;
}
}
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index e39ed91281a9..562816565332 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -39,7 +39,17 @@ struct Tolerance {
uint32_t bits;
};
-enum class Operation : int { Abs, Cos, Exp, Exp2, Sin };
+enum class Operation : int {
+ Abs,
+ Ceil,
+ Cos,
+ Exp,
+ Exp2,
+ Floor,
+ Round,
+ Sin,
+ Trunc
+};
namespace internal {