[libc-commits] [libc] 118c13c - [libc] Add implementation of few floating point manipulation functions.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Thu Jun 11 12:23:21 PDT 2020
Author: Siva Chandra Reddy
Date: 2020-06-11T12:23:11-07:00
New Revision: 118c13c691a5b3b0c5760061a89d5ef7a319c15b
URL: https://github.com/llvm/llvm-project/commit/118c13c691a5b3b0c5760061a89d5ef7a319c15b
DIFF: https://github.com/llvm/llvm-project/commit/118c13c691a5b3b0c5760061a89d5ef7a319c15b.diff
LOG: [libc] Add implementation of few floating point manipulation functions.
Implementations of copysign[f], frexp[f], logb[f], and modf[f] are added.
Reviewers: asteinhauser
Differential Revision: https://reviews.llvm.org/D81134
Added:
libc/src/math/copysign.cpp
libc/src/math/copysign.h
libc/src/math/copysignf.cpp
libc/src/math/copysignf.h
libc/src/math/frexp.cpp
libc/src/math/frexp.h
libc/src/math/frexpf.cpp
libc/src/math/frexpf.h
libc/src/math/logb.cpp
libc/src/math/logb.h
libc/src/math/logbf.cpp
libc/src/math/logbf.h
libc/src/math/modf.cpp
libc/src/math/modf.h
libc/src/math/modff.cpp
libc/src/math/modff.h
libc/test/src/math/copysign_test.cpp
libc/test/src/math/copysignf_test.cpp
libc/test/src/math/frexp_test.cpp
libc/test/src/math/frexpf_test.cpp
libc/test/src/math/logb_test.cpp
libc/test/src/math/logbf_test.cpp
libc/test/src/math/modf_test.cpp
libc/test/src/math/modff_test.cpp
libc/utils/FPUtil/ManipulationFunctions.h
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/api.td
libc/config/linux/x86_64/entrypoints.txt
libc/spec/stdc.td
libc/src/math/CMakeLists.txt
libc/test/src/math/CMakeLists.txt
libc/utils/FPUtil/BitPatterns.h
libc/utils/FPUtil/CMakeLists.txt
libc/utils/FPUtil/FloatOperations.h
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index ca3157b295e8..044b0b5ae0ec 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -8,6 +8,8 @@ set(TARGET_LIBC_ENTRYPOINTS
set(TARGET_LIBM_ENTRYPOINTS
# math.h entrypoints
+ libc.src.math.copysign
+ libc.src.math.copysignf
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.cosf
@@ -17,6 +19,12 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fabsf
libc.src.math.floor
libc.src.math.floorf
+ libc.src.math.frexp
+ libc.src.math.frexpf
+ libc.src.math.logb
+ libc.src.math.logbf
+ libc.src.math.modf
+ libc.src.math.modff
libc.src.math.round
libc.src.math.roundf
libc.src.math.sincosf
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 1d20c5fd12b0..f2b7050661d3 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -150,6 +150,8 @@ def MathAPI : PublicAPI<"math.h"> {
FloatT,
];
let Functions = [
+ "copysign",
+ "copysignf",
"ceil",
"ceilf",
"cosf",
@@ -157,6 +159,12 @@ def MathAPI : PublicAPI<"math.h"> {
"fabsf",
"floor",
"floorf",
+ "frexp",
+ "frexpf",
+ "logb",
+ "logbf",
+ "modf",
+ "modff",
"expf",
"exp2f",
"round",
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a6bc492ac67e..93b0dfdcb3f3 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -45,6 +45,8 @@ set(TARGET_LIBC_ENTRYPOINTS
set(TARGET_LIBM_ENTRYPOINTS
# math.h entrypoints
+ libc.src.math.copysign
+ libc.src.math.copysignf
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.cosf
@@ -54,6 +56,12 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fabsf
libc.src.math.floor
libc.src.math.floorf
+ libc.src.math.frexp
+ libc.src.math.frexpf
+ libc.src.math.logb
+ libc.src.math.logbf
+ libc.src.math.modf
+ libc.src.math.modff
libc.src.math.round
libc.src.math.roundf
libc.src.math.sincosf
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index a9bdfbd710ae..b31f89d3d73a 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -20,6 +20,8 @@ def StdC : StandardSpec<"stdc"> {
PtrType ThrdTTypePtr = PtrType<ThrdTType>;
PtrType IntPtr = PtrType<IntType>;
+ PtrType FloatPtr = PtrType<FloatType>;
+ PtrType DoublePtr = PtrType<DoubleType>;
NamedType SigHandlerT = NamedType<"__sighandler_t">;
@@ -187,6 +189,9 @@ def StdC : StandardSpec<"stdc"> {
],
[], // Enumerations
[
+ FunctionSpec<"copysign", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
+ FunctionSpec<"copysignf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
+
FunctionSpec<"ceil", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
@@ -196,6 +201,15 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"floor", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
FunctionSpec<"floorf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ FunctionSpec<"frexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,
+ FunctionSpec<"frexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntPtr>]>,
+
+ FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
+ FunctionSpec<"modf", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoublePtr>]>,
+ FunctionSpec<"modff", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatPtr>]>,
+
FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 701ee6eb0448..c74e7e4ab5ff 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -189,3 +189,83 @@ add_entrypoint_object(
.math_utils
libc.include.math
)
+
+add_entrypoint_object(
+ copysign
+ SRCS
+ copysign.cpp
+ HDRS
+ copysign.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ copysignf
+ SRCS
+ copysignf.cpp
+ HDRS
+ copysignf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ frexp
+ SRCS
+ frexp.cpp
+ HDRS
+ frexp.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ frexpf
+ SRCS
+ frexpf.cpp
+ HDRS
+ frexpf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ logb
+ SRCS
+ logb.cpp
+ HDRS
+ logb.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ logbf
+ SRCS
+ logbf.cpp
+ HDRS
+ logbf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ modf
+ SRCS
+ modf.cpp
+ HDRS
+ modf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ modff
+ SRCS
+ modff.cpp
+ HDRS
+ modff.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
diff --git a/libc/src/math/copysign.cpp b/libc/src/math/copysign.cpp
new file mode 100644
index 000000000000..5eee71f98123
--- /dev/null
+++ b/libc/src/math/copysign.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of copysign 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(copysign)(double x, double y) {
+ return fputil::copysign(x, y);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/copysign.h b/libc/src/math/copysign.h
new file mode 100644
index 000000000000..edffe1b082fe
--- /dev/null
+++ b/libc/src/math/copysign.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for copysign ----------------------*- 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_COPYSIGN_H
+#define LLVM_LIBC_SRC_MATH_COPYSIGN_H
+
+namespace __llvm_libc {
+
+double copysign(double x, double y);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_COPYSIGN_H
diff --git a/libc/src/math/copysignf.cpp b/libc/src/math/copysignf.cpp
new file mode 100644
index 000000000000..c730dd37b7ae
--- /dev/null
+++ b/libc/src/math/copysignf.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of copysignf 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(copysignf)(float x, float y) {
+ return fputil::copysign(x, y);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/copysignf.h b/libc/src/math/copysignf.h
new file mode 100644
index 000000000000..5b7f1132252d
--- /dev/null
+++ b/libc/src/math/copysignf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for copysignf ---------------------*- 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_COPYSIGNF_H
+#define LLVM_LIBC_SRC_MATH_COPYSIGNF_H
+
+namespace __llvm_libc {
+
+float copysignf(float x, float y);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_COPYSIGNF_H
diff --git a/libc/src/math/frexp.cpp b/libc/src/math/frexp.cpp
new file mode 100644
index 000000000000..8449929347bb
--- /dev/null
+++ b/libc/src/math/frexp.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of frexp 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(frexp)(double x, int *exp) {
+ return fputil::frexp(x, *exp);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/frexp.h b/libc/src/math/frexp.h
new file mode 100644
index 000000000000..925824318836
--- /dev/null
+++ b/libc/src/math/frexp.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for frexp -------------------------*- 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_FREXP_H
+#define LLVM_LIBC_SRC_MATH_FREXP_H
+
+namespace __llvm_libc {
+
+double frexp(double x, int *exp);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FREXP_H
diff --git a/libc/src/math/frexpf.cpp b/libc/src/math/frexpf.cpp
new file mode 100644
index 000000000000..94dac9f59030
--- /dev/null
+++ b/libc/src/math/frexpf.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of frexpf 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(frexpf)(float x, int *exp) {
+ return fputil::frexp(x, *exp);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/frexpf.h b/libc/src/math/frexpf.h
new file mode 100644
index 000000000000..ed303d2c76dd
--- /dev/null
+++ b/libc/src/math/frexpf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for frexpf ------------------------*- 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_FREXPF_H
+#define LLVM_LIBC_SRC_MATH_FREXPF_H
+
+namespace __llvm_libc {
+
+float frexpf(float x, int *exp);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FREXPF_H
diff --git a/libc/src/math/logb.cpp b/libc/src/math/logb.cpp
new file mode 100644
index 000000000000..7475785ebf7e
--- /dev/null
+++ b/libc/src/math/logb.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of logb 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(logb)(double x) { return fputil::logb(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/logb.h b/libc/src/math/logb.h
new file mode 100644
index 000000000000..b875dcd702ba
--- /dev/null
+++ b/libc/src/math/logb.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for logb --------------------------*- 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_LOGB_H
+#define LLVM_LIBC_SRC_MATH_LOGB_H
+
+namespace __llvm_libc {
+
+double logb(double x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_LOGB_H
diff --git a/libc/src/math/logbf.cpp b/libc/src/math/logbf.cpp
new file mode 100644
index 000000000000..bfe8e8590b97
--- /dev/null
+++ b/libc/src/math/logbf.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of logbf 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(logbf)(float x) { return fputil::logb(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/logbf.h b/libc/src/math/logbf.h
new file mode 100644
index 000000000000..46dcd3c91d62
--- /dev/null
+++ b/libc/src/math/logbf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for logbf -------------------------*- 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_LOGBF_H
+#define LLVM_LIBC_SRC_MATH_LOGBF_H
+
+namespace __llvm_libc {
+
+float logbf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_LOGBF_H
diff --git a/libc/src/math/modf.cpp b/libc/src/math/modf.cpp
new file mode 100644
index 000000000000..51466004111b
--- /dev/null
+++ b/libc/src/math/modf.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of modf 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(modf)(double x, double *iptr) {
+ return fputil::modf(x, *iptr);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/modf.h b/libc/src/math/modf.h
new file mode 100644
index 000000000000..1dc732f6e89a
--- /dev/null
+++ b/libc/src/math/modf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for modf --------------------------*- 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_MODF_H
+#define LLVM_LIBC_SRC_MATH_MODF_H
+
+namespace __llvm_libc {
+
+double modf(double x, double *iptr);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_MODF_H
diff --git a/libc/src/math/modff.cpp b/libc/src/math/modff.cpp
new file mode 100644
index 000000000000..4847fe24a9ec
--- /dev/null
+++ b/libc/src/math/modff.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of modf 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/ManipulationFunctions.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(modff)(float x, float *iptr) {
+ return fputil::modf(x, *iptr);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/modff.h b/libc/src/math/modff.h
new file mode 100644
index 000000000000..21457e0d2e81
--- /dev/null
+++ b/libc/src/math/modff.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for modff -------------------------*- 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_MODFF_H
+#define LLVM_LIBC_SRC_MATH_MODFF_H
+
+namespace __llvm_libc {
+
+float modff(float x, float *iptr);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_MODFF_H
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index c381ea8a2e81..ebc03d3452cc 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -228,3 +228,99 @@ add_math_unittest(
libc.src.math.exp2f
libc.utils.FPUtil.fputil
)
+
+add_math_unittest(
+ copysign_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ copysign_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.copysign
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ copysignf_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ copysignf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.copysignf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ frexp_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ frexp_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.frexp
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ frexpf_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ frexpf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.frexpf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ logb_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ logb_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.logb
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ logbf_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ logbf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.logbf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ modf_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ modf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.modf
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ modff_test
+ SUITE
+ libc_math_unittests
+ SRCS
+ modff_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.modff
+ libc.utils.FPUtil.fputil
+)
diff --git a/libc/test/src/math/copysign_test.cpp b/libc/test/src/math/copysign_test.cpp
new file mode 100644
index 000000000000..e0638467c5b9
--- /dev/null
+++ b/libc/test/src/math/copysign_test.cpp
@@ -0,0 +1,63 @@
+//===-- Unittests for copysign --------------------------------------------===//
+//
+// 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/copysign.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.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>;
+
+TEST(CopySignTest, SpecialNumbers) {
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::aQuietNaN), -1.0)));
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), 1.0)));
+
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::aSignallingNaN), -1.0)));
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), 1.0)));
+
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::inf), -1.0)));
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::negInf), 1.0)));
+
+ EXPECT_EQ(BitPatterns::negZero, valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::zero), -1.0)));
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::copysign(
+ valueFromBits(BitPatterns::negZero), 1.0)));
+}
+
+TEST(CopySignTest, 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) || x == 0)
+ continue;
+
+ double res1 = __llvm_libc::copysign(x, -x);
+ ASSERT_TRUE(res1 == -x);
+
+ double res2 = __llvm_libc::copysign(x, x);
+ ASSERT_TRUE(res2 == x);
+ }
+}
diff --git a/libc/test/src/math/copysignf_test.cpp b/libc/test/src/math/copysignf_test.cpp
new file mode 100644
index 000000000000..cb2cf518bde2
--- /dev/null
+++ b/libc/test/src/math/copysignf_test.cpp
@@ -0,0 +1,65 @@
+//===-- Unittests for copysignf
+//--------------------------------------------===//
+//
+// 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/copysignf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.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>;
+
+TEST(CopySignFTest, SpecialNumbers) {
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::aQuietNaN), -1.0f)));
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), 1.0f)));
+
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::aSignallingNaN), -1.0f)));
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), 1.0f)));
+
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::inf), -1.0f)));
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::negInf), 1.0f)));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::copysignf(valueFromBits(BitPatterns::zero),
+ -1.0f)));
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::copysignf(
+ valueFromBits(BitPatterns::negZero), 1.0f)));
+}
+
+TEST(CopySignFTest, InDoubleRange) {
+ 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) {
+ float x = valueFromBits(v);
+ if (isnan(x) || isinf(x) || x == 0)
+ continue;
+
+ float res1 = __llvm_libc::copysignf(x, -x);
+ ASSERT_TRUE(res1 == -x);
+
+ float res2 = __llvm_libc::copysignf(x, x);
+ ASSERT_TRUE(res2 == x);
+ }
+}
diff --git a/libc/test/src/math/frexp_test.cpp b/libc/test/src/math/frexp_test.cpp
new file mode 100644
index 000000000000..a7fb953fb4fb
--- /dev/null
+++ b/libc/test/src/math/frexp_test.cpp
@@ -0,0 +1,141 @@
+//===-- Unittests for frexp -----------------------------------------------===//
+//
+// 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/frexp.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.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>;
+
+TEST(FrexpTest, SpecialNumbers) {
+ int exponent;
+
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::frexp(
+ valueFromBits(BitPatterns::aQuietNaN), &exponent)));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::frexp(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), &exponent)));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::frexp(
+ valueFromBits(BitPatterns::aSignallingNaN), &exponent)));
+ EXPECT_EQ(
+ BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::frexp(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), &exponent)));
+
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::frexp(
+ valueFromBits(BitPatterns::inf), &exponent)));
+ EXPECT_EQ(BitPatterns::negInf,
+ valueAsBits(__llvm_libc::frexp(valueFromBits(BitPatterns::negInf),
+ &exponent)));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::frexp(valueFromBits(BitPatterns::zero),
+ &exponent)));
+ EXPECT_EQ(exponent, 0);
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::frexp(valueFromBits(BitPatterns::negZero),
+ &exponent)));
+ EXPECT_EQ(exponent, 0);
+}
+
+TEST(FrexpTest, PowersOfTwo) {
+ int exponent;
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(1.0, &exponent)));
+ EXPECT_EQ(exponent, 1);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-1.0, &exponent)));
+ EXPECT_EQ(exponent, 1);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(2.0, &exponent)));
+ EXPECT_EQ(exponent, 2);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-2.0, &exponent)));
+ EXPECT_EQ(exponent, 2);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(4.0, &exponent)));
+ EXPECT_EQ(exponent, 3);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-4.0, &exponent)));
+ EXPECT_EQ(exponent, 3);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(8.0, &exponent)));
+ EXPECT_EQ(exponent, 4);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-8.0, &exponent)));
+ EXPECT_EQ(exponent, 4);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(16.0, &exponent)));
+ EXPECT_EQ(exponent, 5);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-16.0, &exponent)));
+ EXPECT_EQ(exponent, 5);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(32.0, &exponent)));
+ EXPECT_EQ(exponent, 6);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-32.0, &exponent)));
+ EXPECT_EQ(exponent, 6);
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::frexp(64.0, &exponent)));
+ EXPECT_EQ(exponent, 7);
+ EXPECT_EQ(valueAsBits(-0.5),
+ valueAsBits(__llvm_libc::frexp(-64.0, &exponent)));
+ EXPECT_EQ(exponent, 7);
+}
+
+TEST(FrexpTest, SomeIntegers) {
+ int exponent;
+
+ EXPECT_EQ(valueAsBits(0.75),
+ valueAsBits(__llvm_libc::frexp(24.0, &exponent)));
+ EXPECT_EQ(exponent, 5);
+ EXPECT_EQ(valueAsBits(-0.75),
+ valueAsBits(__llvm_libc::frexp(-24.0, &exponent)));
+ EXPECT_EQ(exponent, 5);
+
+ EXPECT_EQ(valueAsBits(0.625),
+ valueAsBits(__llvm_libc::frexp(40.0, &exponent)));
+ EXPECT_EQ(exponent, 6);
+ EXPECT_EQ(valueAsBits(-0.625),
+ valueAsBits(__llvm_libc::frexp(-40.0, &exponent)));
+ EXPECT_EQ(exponent, 6);
+
+ EXPECT_EQ(valueAsBits(0.78125),
+ valueAsBits(__llvm_libc::frexp(800.0, &exponent)));
+ EXPECT_EQ(exponent, 10);
+ EXPECT_EQ(valueAsBits(-0.78125),
+ valueAsBits(__llvm_libc::frexp(-800.0, &exponent)));
+ EXPECT_EQ(exponent, 10);
+}
+
+TEST(FrexpTest, 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) || x == 0.0)
+ continue;
+ int exponent;
+ double frac = __llvm_libc::frexp(x, &exponent);
+
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) < 1.0);
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) >= 0.5);
+ }
+}
diff --git a/libc/test/src/math/frexpf_test.cpp b/libc/test/src/math/frexpf_test.cpp
new file mode 100644
index 000000000000..d90532b63436
--- /dev/null
+++ b/libc/test/src/math/frexpf_test.cpp
@@ -0,0 +1,150 @@
+//===-- Unittests for frexpf
+//-----------------------------------------------===//
+//
+// 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/frexpf.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>;
+
+TEST(FrexpfTest, SpecialNumbers) {
+ int exponent;
+
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::frexpf(
+ valueFromBits(BitPatterns::aQuietNaN), &exponent)));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::frexpf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), &exponent)));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::frexpf(
+ valueFromBits(BitPatterns::aSignallingNaN), &exponent)));
+ EXPECT_EQ(
+ BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::frexpf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), &exponent)));
+
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::frexpf(
+ valueFromBits(BitPatterns::inf), &exponent)));
+ EXPECT_EQ(BitPatterns::negInf,
+ valueAsBits(__llvm_libc::frexpf(valueFromBits(BitPatterns::negInf),
+ &exponent)));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::frexpf(valueFromBits(BitPatterns::zero),
+ &exponent)));
+ EXPECT_EQ(exponent, 0);
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::frexpf(valueFromBits(BitPatterns::negZero),
+ &exponent)));
+ EXPECT_EQ(exponent, 0);
+}
+
+TEST(FrexpfTest, PowersOfTwo) {
+ int exponent;
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(1.0f, &exponent)));
+ EXPECT_EQ(exponent, 1);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-1.0f, &exponent)));
+ EXPECT_EQ(exponent, 1);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(2.0f, &exponent)));
+ EXPECT_EQ(exponent, 2);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-2.0f, &exponent)));
+ EXPECT_EQ(exponent, 2);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(4.0f, &exponent)));
+ EXPECT_EQ(exponent, 3);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-4.0f, &exponent)));
+ EXPECT_EQ(exponent, 3);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(8.0f, &exponent)));
+ EXPECT_EQ(exponent, 4);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-8.0f, &exponent)));
+ EXPECT_EQ(exponent, 4);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(16.0f, &exponent)));
+ EXPECT_EQ(exponent, 5);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-16.0f, &exponent)));
+ EXPECT_EQ(exponent, 5);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(32.0f, &exponent)));
+ EXPECT_EQ(exponent, 6);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-32.0f, &exponent)));
+ EXPECT_EQ(exponent, 6);
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::frexpf(64.0f, &exponent)));
+ EXPECT_EQ(exponent, 7);
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::frexpf(-64.0f, &exponent)));
+ EXPECT_EQ(exponent, 7);
+}
+
+TEST(FrexpTest, SomeIntegers) {
+ int exponent;
+
+ EXPECT_EQ(valueAsBits(0.75f),
+ valueAsBits(__llvm_libc::frexpf(24.0f, &exponent)));
+ EXPECT_EQ(exponent, 5);
+ EXPECT_EQ(valueAsBits(-0.75f),
+ valueAsBits(__llvm_libc::frexpf(-24.0f, &exponent)));
+ EXPECT_EQ(exponent, 5);
+
+ EXPECT_EQ(valueAsBits(0.625f),
+ valueAsBits(__llvm_libc::frexpf(40.0f, &exponent)));
+ EXPECT_EQ(exponent, 6);
+ EXPECT_EQ(valueAsBits(-0.625f),
+ valueAsBits(__llvm_libc::frexpf(-40.0f, &exponent)));
+ EXPECT_EQ(exponent, 6);
+
+ EXPECT_EQ(valueAsBits(0.78125f),
+ valueAsBits(__llvm_libc::frexpf(800.0f, &exponent)));
+ EXPECT_EQ(exponent, 10);
+ EXPECT_EQ(valueAsBits(-0.78125f),
+ valueAsBits(__llvm_libc::frexpf(-800.0f, &exponent)));
+ EXPECT_EQ(exponent, 10);
+}
+
+TEST(FrexpfTest, 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) {
+ float x = valueFromBits(v);
+ if (isnan(x) || isinf(x) || x == 0.0)
+ continue;
+ int exponent;
+ float frac = __llvm_libc::frexpf(x, &exponent);
+
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) < 1.0f);
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) >= 0.5f);
+ }
+}
diff --git a/libc/test/src/math/logb_test.cpp b/libc/test/src/math/logb_test.cpp
new file mode 100644
index 000000000000..5f8e75387489
--- /dev/null
+++ b/libc/test/src/math/logb_test.cpp
@@ -0,0 +1,99 @@
+//===-- Unittests for logb ------------------------------------------------===//
+//
+// 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/logb.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/FPUtil/ManipulationFunctions.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>;
+
+TEST(LogbTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::logb(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::logb(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(
+ __llvm_libc::logb(valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::logb(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::logb(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::logb(valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::negInf,
+ valueAsBits(__llvm_libc::logb(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::logb(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(LogbTest, PowersOfTwo) {
+ EXPECT_EQ(valueAsBits(0.0), valueAsBits(__llvm_libc::logb(1.0)));
+ EXPECT_EQ(valueAsBits(0.0), valueAsBits(__llvm_libc::logb(-1.0)));
+
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::logb(2.0)));
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::logb(-2.0)));
+
+ EXPECT_EQ(valueAsBits(2.0), valueAsBits(__llvm_libc::logb(4.0)));
+ EXPECT_EQ(valueAsBits(2.0), valueAsBits(__llvm_libc::logb(-4.0)));
+
+ EXPECT_EQ(valueAsBits(3.0), valueAsBits(__llvm_libc::logb(8.0)));
+ EXPECT_EQ(valueAsBits(3.0), valueAsBits(__llvm_libc::logb(-8.0)));
+
+ EXPECT_EQ(valueAsBits(4.0), valueAsBits(__llvm_libc::logb(16.0)));
+ EXPECT_EQ(valueAsBits(4.0), valueAsBits(__llvm_libc::logb(-16.0)));
+
+ EXPECT_EQ(valueAsBits(5.0), valueAsBits(__llvm_libc::logb(32.0)));
+ EXPECT_EQ(valueAsBits(5.0), valueAsBits(__llvm_libc::logb(-32.0)));
+}
+
+TEST(LogbTest, SomeIntegers) {
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::logb(3.0)));
+ EXPECT_EQ(valueAsBits(1.0), valueAsBits(__llvm_libc::logb(-3.0)));
+
+ EXPECT_EQ(valueAsBits(2.0), valueAsBits(__llvm_libc::logb(7.0)));
+ EXPECT_EQ(valueAsBits(2.0), valueAsBits(__llvm_libc::logb(-7.0)));
+
+ EXPECT_EQ(valueAsBits(3.0), valueAsBits(__llvm_libc::logb(10.0)));
+ EXPECT_EQ(valueAsBits(3.0), valueAsBits(__llvm_libc::logb(-10.0)));
+
+ EXPECT_EQ(valueAsBits(4.0), valueAsBits(__llvm_libc::logb(31.0)));
+ EXPECT_EQ(valueAsBits(4.0), valueAsBits(__llvm_libc::logb(-31.0)));
+
+ EXPECT_EQ(valueAsBits(5.0), valueAsBits(__llvm_libc::logb(55.0)));
+ EXPECT_EQ(valueAsBits(5.0), valueAsBits(__llvm_libc::logb(-55.0)));
+}
+
+TEST(LogbTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 10000000;
+ 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) || x == 0.0)
+ continue;
+
+ int exponent;
+ __llvm_libc::fputil::frexp(x, exponent);
+ ASSERT_TRUE(double(exponent) == __llvm_libc::logb(x) + 1.0);
+ }
+}
diff --git a/libc/test/src/math/logbf_test.cpp b/libc/test/src/math/logbf_test.cpp
new file mode 100644
index 000000000000..7cd690ce3869
--- /dev/null
+++ b/libc/test/src/math/logbf_test.cpp
@@ -0,0 +1,99 @@
+//===-- Unittests for logbf -----------------------------------------------===//
+//
+// 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/logbf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/FPUtil/ManipulationFunctions.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>;
+
+TEST(LogbfTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::logbf(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::logbf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::logbf(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::logbf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::logbf(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::logbf(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::negInf,
+ valueAsBits(__llvm_libc::logbf(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::negInf, valueAsBits(__llvm_libc::logbf(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(LogbfTest, PowersOfTwo) {
+ EXPECT_EQ(valueAsBits(0.0f), valueAsBits(__llvm_libc::logbf(1.0f)));
+ EXPECT_EQ(valueAsBits(0.0f), valueAsBits(__llvm_libc::logbf(-1.0f)));
+
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::logbf(2.0f)));
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::logbf(-2.0f)));
+
+ EXPECT_EQ(valueAsBits(2.0f), valueAsBits(__llvm_libc::logbf(4.0f)));
+ EXPECT_EQ(valueAsBits(2.0f), valueAsBits(__llvm_libc::logbf(-4.0f)));
+
+ EXPECT_EQ(valueAsBits(3.0f), valueAsBits(__llvm_libc::logbf(8.0f)));
+ EXPECT_EQ(valueAsBits(3.0f), valueAsBits(__llvm_libc::logbf(-8.0f)));
+
+ EXPECT_EQ(valueAsBits(4.0f), valueAsBits(__llvm_libc::logbf(16.0f)));
+ EXPECT_EQ(valueAsBits(4.0f), valueAsBits(__llvm_libc::logbf(-16.0f)));
+
+ EXPECT_EQ(valueAsBits(5.0f), valueAsBits(__llvm_libc::logbf(32.0f)));
+ EXPECT_EQ(valueAsBits(5.0f), valueAsBits(__llvm_libc::logbf(-32.0f)));
+}
+
+TEST(LogbTest, SomeIntegers) {
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::logbf(3.0f)));
+ EXPECT_EQ(valueAsBits(1.0f), valueAsBits(__llvm_libc::logbf(-3.0f)));
+
+ EXPECT_EQ(valueAsBits(2.0f), valueAsBits(__llvm_libc::logbf(7.0f)));
+ EXPECT_EQ(valueAsBits(2.0f), valueAsBits(__llvm_libc::logbf(-7.0f)));
+
+ EXPECT_EQ(valueAsBits(3.0f), valueAsBits(__llvm_libc::logbf(10.0f)));
+ EXPECT_EQ(valueAsBits(3.0f), valueAsBits(__llvm_libc::logbf(-10.0f)));
+
+ EXPECT_EQ(valueAsBits(4.0f), valueAsBits(__llvm_libc::logbf(31.0f)));
+ EXPECT_EQ(valueAsBits(4.0f), valueAsBits(__llvm_libc::logbf(-31.0f)));
+
+ EXPECT_EQ(valueAsBits(5.0f), valueAsBits(__llvm_libc::logbf(55.0f)));
+ EXPECT_EQ(valueAsBits(5.0f), valueAsBits(__llvm_libc::logbf(-55.0f)));
+}
+
+TEST(LogbfTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 10000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ float x = valueFromBits(v);
+ if (isnan(x) || isinf(x) || x == 0.0)
+ continue;
+
+ int exponent;
+ __llvm_libc::fputil::frexp(x, exponent);
+ ASSERT_TRUE(float(exponent) == __llvm_libc::logbf(x) + 1.0);
+ }
+}
diff --git a/libc/test/src/math/modf_test.cpp b/libc/test/src/math/modf_test.cpp
new file mode 100644
index 000000000000..fa4436d64151
--- /dev/null
+++ b/libc/test/src/math/modf_test.cpp
@@ -0,0 +1,130 @@
+//===-- Unittests for modf ------------------------------------------------===//
+//
+// 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/modf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.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>;
+
+TEST(ModfTest, SpecialNumbers) {
+ double integral;
+
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::modf(valueFromBits(BitPatterns::aQuietNaN),
+ &integral)));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::modf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), &integral)));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::modf(
+ valueFromBits(BitPatterns::aSignallingNaN), &integral)));
+ EXPECT_EQ(
+ BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::modf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), &integral)));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(
+ __llvm_libc::modf(valueFromBits(BitPatterns::inf), &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::inf);
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modf(valueFromBits(BitPatterns::negInf),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::negInf);
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modf(valueFromBits(BitPatterns::zero),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::zero);
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modf(valueFromBits(BitPatterns::negZero),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::negZero);
+}
+
+TEST(ModfTest, Integers) {
+ double integral;
+
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::modf(1.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(1.0));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modf(-1.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-1.0));
+
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::modf(10.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(10.0));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modf(-10.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-10.0));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modf(12345.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(12345.0));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modf(-12345.0, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-12345.0));
+}
+
+TEST(ModfTest, Fractions) {
+ double integral;
+
+ EXPECT_EQ(valueAsBits(0.5), valueAsBits(__llvm_libc::modf(1.5, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(1.0));
+
+ EXPECT_EQ(valueAsBits(-0.5), valueAsBits(__llvm_libc::modf(-1.5, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-1.0));
+
+ EXPECT_EQ(valueAsBits(0.75),
+ valueAsBits(__llvm_libc::modf(10.75, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(10.0));
+
+ EXPECT_EQ(valueAsBits(-0.75),
+ valueAsBits(__llvm_libc::modf(-10.75, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-10.0));
+
+ EXPECT_EQ(valueAsBits(0.125),
+ valueAsBits(__llvm_libc::modf(100.125, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(100.0));
+
+ EXPECT_EQ(valueAsBits(-0.125),
+ valueAsBits(__llvm_libc::modf(-100.125, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-100.0));
+}
+
+TEST(ModfTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 10000000;
+ 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) || x == 0.0) {
+ // These conditions have been tested in other tests.
+ continue;
+ }
+
+ double integral;
+ double frac = __llvm_libc::modf(x, &integral);
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) < 1.0);
+ ASSERT_TRUE(__llvm_libc::fputil::trunc(x) == integral);
+ ASSERT_TRUE(integral + frac == x);
+ }
+}
diff --git a/libc/test/src/math/modff_test.cpp b/libc/test/src/math/modff_test.cpp
new file mode 100644
index 000000000000..db3b7c801212
--- /dev/null
+++ b/libc/test/src/math/modff_test.cpp
@@ -0,0 +1,135 @@
+//===-- Unittests for modfff
+//-----------------------------------------------===//
+//
+// 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/modff.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.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>;
+
+TEST(ModffTest, SpecialNumbers) {
+ float integral;
+
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::modff(
+ valueFromBits(BitPatterns::aQuietNaN), &integral)));
+ EXPECT_EQ(BitPatterns::aNegativeQuietNaN,
+ valueAsBits(__llvm_libc::modff(
+ valueFromBits(BitPatterns::aNegativeQuietNaN), &integral)));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::modff(
+ valueFromBits(BitPatterns::aSignallingNaN), &integral)));
+ EXPECT_EQ(
+ BitPatterns::aNegativeSignallingNaN,
+ valueAsBits(__llvm_libc::modff(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN), &integral)));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modff(valueFromBits(BitPatterns::inf),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::inf);
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modff(valueFromBits(BitPatterns::negInf),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::negInf);
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modff(valueFromBits(BitPatterns::zero),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::zero);
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modff(valueFromBits(BitPatterns::negZero),
+ &integral)));
+ EXPECT_EQ(valueAsBits(integral), BitPatterns::negZero);
+}
+
+TEST(ModffTest, Integers) {
+ float integral;
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modff(1.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(1.0f));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modff(-1.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-1.0f));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modff(10.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(10.0f));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modff(-10.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-10.0f));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::modff(12345.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(12345.0f));
+
+ EXPECT_EQ(BitPatterns::negZero,
+ valueAsBits(__llvm_libc::modff(-12345.0f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-12345.0f));
+}
+
+TEST(ModfTest, Fractions) {
+ float integral;
+
+ EXPECT_EQ(valueAsBits(0.5f),
+ valueAsBits(__llvm_libc::modff(1.5f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(1.0f));
+
+ EXPECT_EQ(valueAsBits(-0.5f),
+ valueAsBits(__llvm_libc::modff(-1.5f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-1.0f));
+
+ EXPECT_EQ(valueAsBits(0.75f),
+ valueAsBits(__llvm_libc::modff(10.75f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(10.0f));
+
+ EXPECT_EQ(valueAsBits(-0.75f),
+ valueAsBits(__llvm_libc::modff(-10.75f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-10.0f));
+
+ EXPECT_EQ(valueAsBits(0.125f),
+ valueAsBits(__llvm_libc::modff(100.125f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(100.0f));
+
+ EXPECT_EQ(valueAsBits(-0.125f),
+ valueAsBits(__llvm_libc::modff(-100.125f, &integral)));
+ EXPECT_EQ(valueAsBits(integral), valueAsBits(-100.0f));
+}
+
+TEST(ModffTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 10000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ float x = valueFromBits(v);
+ if (isnan(x) || isinf(x) || x == 0.0f) {
+ // These conditions have been tested in other tests.
+ continue;
+ }
+
+ float integral;
+ float frac = __llvm_libc::modff(x, &integral);
+ ASSERT_TRUE(__llvm_libc::fputil::abs(frac) < 1.0f);
+ ASSERT_TRUE(__llvm_libc::fputil::trunc(x) == integral);
+ ASSERT_TRUE(integral + frac == x);
+ }
+}
diff --git a/libc/utils/FPUtil/BitPatterns.h b/libc/utils/FPUtil/BitPatterns.h
index 35c58a43d906..439ccbcdcb92 100644
--- a/libc/utils/FPUtil/BitPatterns.h
+++ b/libc/utils/FPUtil/BitPatterns.h
@@ -11,6 +11,12 @@
#include "FloatProperties.h"
+#include <float.h>
+
+static_assert(
+ FLT_RADIX == 2,
+ "LLVM libc only supports radix 2 IEEE 754 floating point formats.");
+
namespace __llvm_libc {
namespace fputil {
diff --git a/libc/utils/FPUtil/CMakeLists.txt b/libc/utils/FPUtil/CMakeLists.txt
index b50ede179fcf..21013ee1771f 100644
--- a/libc/utils/FPUtil/CMakeLists.txt
+++ b/libc/utils/FPUtil/CMakeLists.txt
@@ -4,6 +4,7 @@ add_header_library(
BitPatterns.h
FloatOperations.h
FloatProperties.h
+ ManipulationFunctions.h
DEPS
libc.utils.CPP.standalone_cpp
)
diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h
index d841237176a5..b599aad37f41 100644
--- a/libc/utils/FPUtil/FloatOperations.h
+++ b/libc/utils/FPUtil/FloatOperations.h
@@ -57,26 +57,30 @@ static inline int getExponent(T x) {
return getExponentFromBits(valueAsBits(x));
}
+template <typename BitsType> static inline bool bitsAreInf(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return ((bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf) &&
+ ((bits & FloatProperties<FPType>::mantissaMask) == 0);
+}
+
// Return true if x is infinity (positive or negative.)
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline bool isInf(T x) {
- using Properties = FloatProperties<T>;
- using BitsType = typename FloatProperties<T>::BitsType;
- BitsType bits = valueAsBits(x);
- return ((bits & BitPatterns<T>::inf) == BitPatterns<T>::inf) &&
- ((bits & Properties::mantissaMask) == 0);
+ return bitsAreInf(valueAsBits(x));
+}
+
+template <typename BitsType> static inline bool bitsAreNaN(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return ((bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf) &&
+ ((bits & FloatProperties<FPType>::mantissaMask) != 0);
}
// Return true if x is a NAN (quiet or signalling.)
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline bool isNaN(T x) {
- using Properties = FloatProperties<T>;
- using BitsType = typename FloatProperties<T>::BitsType;
- BitsType bits = valueAsBits(x);
- return ((bits & BitPatterns<T>::inf) == BitPatterns<T>::inf) &&
- ((bits & Properties::mantissaMask) != 0);
+ return bitsAreNaN(valueAsBits(x));
}
template <typename BitsType> static inline bool bitsAreInfOrNaN(BitsType bits) {
diff --git a/libc/utils/FPUtil/ManipulationFunctions.h b/libc/utils/FPUtil/ManipulationFunctions.h
new file mode 100644
index 000000000000..a59c0a7e4cf9
--- /dev/null
+++ b/libc/utils/FPUtil/ManipulationFunctions.h
@@ -0,0 +1,102 @@
+//===-- Common operations on floating point numbers -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "BitPatterns.h"
+#include "FloatOperations.h"
+#include "FloatProperties.h"
+
+#include "utils/CPP/TypeTraits.h"
+
+#ifndef LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
+#define LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
+
+namespace __llvm_libc {
+namespace fputil {
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T frexp(T x, int &exp) {
+ using Properties = FloatProperties<T>;
+ using BitsType = typename Properties::BitsType;
+
+ auto bits = valueAsBits(x);
+ if (bitsAreInfOrNaN(bits))
+ return x;
+ if (bitsAreZero(bits)) {
+ exp = 0;
+ return x;
+ }
+
+ exp = getExponentFromBits(bits) + 1;
+
+ static constexpr BitsType resultExponent =
+ Properties::exponentOffset - BitsType(1);
+ // Capture the sign and mantissa part.
+ bits &= (Properties::mantissaMask | Properties::signMask);
+ // Insert the new exponent.
+ bits |= (resultExponent << Properties::mantissaWidth);
+
+ return valueFromBits(bits);
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T modf(T x, T &iptr) {
+ auto bits = valueAsBits(x);
+ if (bitsAreZero(bits) || bitsAreNaN(bits)) {
+ iptr = x;
+ return x;
+ } else if (bitsAreInf(bits)) {
+ iptr = x;
+ return bits & FloatProperties<T>::signMask
+ ? valueFromBits(BitPatterns<T>::negZero)
+ : valueFromBits(BitPatterns<T>::zero);
+ } else {
+ iptr = trunc(x);
+ if (x == iptr) {
+ // If x is already an integer value, then return zero with the right
+ // sign.
+ return bits & FloatProperties<T>::signMask
+ ? valueFromBits(BitPatterns<T>::negZero)
+ : valueFromBits(BitPatterns<T>::zero);
+ } else {
+ return x - iptr;
+ }
+ }
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T copysign(T x, T y) {
+ constexpr auto signMask = FloatProperties<T>::signMask;
+ auto xbits = valueAsBits(x);
+ auto ybits = valueAsBits(y);
+ return valueFromBits((xbits & ~signMask) | (ybits & signMask));
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T logb(T x) {
+ auto bits = valueAsBits(x);
+ if (bitsAreZero(bits)) {
+ // TODO(Floating point exception): Raise div-by-zero exception.
+ // TODO(errno): POSIX requires setting errno to ERANGE.
+ return valueFromBits(BitPatterns<T>::negInf);
+ } else if (bitsAreInf(bits)) {
+ return valueFromBits(BitPatterns<T>::inf);
+ } else if (bitsAreNaN(bits)) {
+ return x;
+ } else {
+ return getExponentFromBits(bits);
+ }
+}
+
+} // namespace fputil
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
More information about the libc-commits
mailing list