forked from OSchip/llvm-project
[libc] Add implementation of fabs and fabsf.
Reviewers: phosek Differential Revision: https://reviews.llvm.org/D79725
This commit is contained in:
parent
ddacd370c5
commit
4a39a33d44
|
@ -150,6 +150,8 @@ def MathAPI : PublicAPI<"math.h"> {
|
|||
];
|
||||
let Functions = [
|
||||
"cosf",
|
||||
"fabs",
|
||||
"fabsf",
|
||||
"round",
|
||||
"sincosf",
|
||||
"sinf",
|
||||
|
|
|
@ -48,6 +48,8 @@ add_entrypoint_library(
|
|||
DEPENDS
|
||||
# math.h entrypoints
|
||||
libc.src.math.cosf
|
||||
libc.src.math.fabs
|
||||
libc.src.math.fabsf
|
||||
libc.src.math.round
|
||||
libc.src.math.sincosf
|
||||
libc.src.math.sinf
|
||||
|
|
|
@ -182,6 +182,9 @@ def StdC : StandardSpec<"stdc"> {
|
|||
],
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
|
||||
FunctionSpec<"fabsf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
|
||||
|
||||
FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
|
||||
FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
|
||||
|
||||
|
|
|
@ -68,3 +68,23 @@ add_entrypoint_object(
|
|||
libc.include.math
|
||||
libc.src.errno.__errno_location
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fabs
|
||||
SRCS
|
||||
fabs.cpp
|
||||
HDRS
|
||||
fabs.h
|
||||
DEPENDS
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fabsf
|
||||
SRCS
|
||||
fabsf.cpp
|
||||
HDRS
|
||||
fabsf.h
|
||||
DEPENDS
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
//===-- Implementation of fabs 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(fabs)(double x) { return fputil::abs(x); }
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for fabs --------------------------*- 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_FABS_H
|
||||
#define LLVM_LIBC_SRC_MATH_FABS_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
double fabs(double x);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_FABS_H
|
|
@ -0,0 +1,16 @@
|
|||
//===-- Implementation of fabsf 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(fabsf)(float x) { return fputil::abs(x); }
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for fabsf -------------------------*- 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_FABSF_H
|
||||
#define LLVM_LIBC_SRC_MATH_FABSF_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
float fabsf(float x);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_FABSF_H
|
|
@ -70,3 +70,29 @@ add_math_unittest(
|
|||
libc.utils.CPP.standalone_cpp
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
||||
add_math_unittest(
|
||||
fabs_test
|
||||
NEED_MPFR
|
||||
SUITE
|
||||
libc_math_unittests
|
||||
SRCS
|
||||
fabs_test.cpp
|
||||
DEPENDS
|
||||
libc.include.math
|
||||
libc.src.math.fabs
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
||||
add_math_unittest(
|
||||
fabsf_test
|
||||
NEED_MPFR
|
||||
SUITE
|
||||
libc_math_unittests
|
||||
SRCS
|
||||
fabsf_test.cpp
|
||||
DEPENDS
|
||||
libc.include.math
|
||||
libc.src.math.fabsf
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
//===-- Unittests for fabs ------------------------------------------------===//
|
||||
//
|
||||
// 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/fabs.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(FabsTest, SpecialNumbers) {
|
||||
EXPECT_EQ(
|
||||
BitPatterns::aQuietNaN,
|
||||
valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::aQuietNaN))));
|
||||
EXPECT_EQ(BitPatterns::aQuietNaN, valueAsBits(__llvm_libc::fabs(valueFromBits(
|
||||
BitPatterns::aNegativeQuietNaN))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::aSignallingNaN,
|
||||
valueAsBits(
|
||||
__llvm_libc::fabs(valueFromBits(BitPatterns::aSignallingNaN))));
|
||||
EXPECT_EQ(BitPatterns::aSignallingNaN,
|
||||
valueAsBits(__llvm_libc::fabs(
|
||||
valueFromBits(BitPatterns::aNegativeSignallingNaN))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::inf,
|
||||
valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::inf))));
|
||||
EXPECT_EQ(BitPatterns::inf,
|
||||
valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::negInf))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::zero,
|
||||
valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::zero))));
|
||||
EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::fabs(
|
||||
valueFromBits(BitPatterns::negZero))));
|
||||
}
|
||||
|
||||
TEST(FabsTest, 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::OP_Abs, x, __llvm_libc::fabs(x), tolerance);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//===-- Unittests for fabsf -----------------------------------------------===//
|
||||
//
|
||||
// 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/fabsf.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(FabsfTest, SpecialNumbers) {
|
||||
EXPECT_EQ(
|
||||
BitPatterns::aQuietNaN,
|
||||
valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::aQuietNaN))));
|
||||
EXPECT_EQ(BitPatterns::aQuietNaN,
|
||||
valueAsBits(__llvm_libc::fabsf(
|
||||
valueFromBits(BitPatterns::aNegativeQuietNaN))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::aSignallingNaN,
|
||||
valueAsBits(__llvm_libc::fabsf(
|
||||
valueFromBits(BitPatterns::aSignallingNaN))));
|
||||
EXPECT_EQ(BitPatterns::aSignallingNaN,
|
||||
valueAsBits(__llvm_libc::fabsf(
|
||||
valueFromBits(BitPatterns::aNegativeSignallingNaN))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::inf,
|
||||
valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::inf))));
|
||||
EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::fabsf(
|
||||
valueFromBits(BitPatterns::negInf))));
|
||||
|
||||
EXPECT_EQ(BitPatterns::zero,
|
||||
valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::zero))));
|
||||
EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::fabsf(
|
||||
valueFromBits(BitPatterns::negZero))));
|
||||
}
|
||||
|
||||
TEST(FabsfTest, 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::OP_Abs, x, __llvm_libc::fabsf(x), tolerance);
|
||||
}
|
||||
}
|
|
@ -96,6 +96,13 @@ static inline bool isNegativeQuietNaN(T x) {
|
|||
((bits & Properties::quietNaNMask) != 0);
|
||||
}
|
||||
|
||||
// Return the absolute value of x.
|
||||
template <typename T,
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
|
||||
static inline T abs(T x) {
|
||||
return valueFromBits(absBits(x));
|
||||
}
|
||||
|
||||
} // namespace fputil
|
||||
} // namespace __llvm_libc
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ public:
|
|||
mpfr_init2(value, mpfrPrecision);
|
||||
MPFRNumber mpfrInput(rawValue);
|
||||
switch (op) {
|
||||
case OP_Abs:
|
||||
mpfr_abs(value, mpfrInput.value, MPFR_RNDN);
|
||||
break;
|
||||
case OP_Cos:
|
||||
mpfr_cos(value, mpfrInput.value, MPFR_RNDN);
|
||||
break;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct Tolerance {
|
|||
};
|
||||
|
||||
enum Operation {
|
||||
OP_Abs,
|
||||
OP_Cos,
|
||||
OP_Sin,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue