mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 13:26:45 +00:00
[libc] Add implementations of ceil[f], floor[f] and trunc[f] from math.h.
Reviewers: abrachet Differential Revision: https://reviews.llvm.org/D80612
This commit is contained in:
parent
26c78e3095
commit
1caedd0c55
@ -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(
|
||||
|
@ -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
|
||||
|
16
libc/src/math/ceil.cpp
Normal file
16
libc/src/math/ceil.cpp
Normal file
@ -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
|
18
libc/src/math/ceil.h
Normal file
18
libc/src/math/ceil.h
Normal file
@ -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
|
16
libc/src/math/ceilf.cpp
Normal file
16
libc/src/math/ceilf.cpp
Normal file
@ -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
|
18
libc/src/math/ceilf.h
Normal file
18
libc/src/math/ceilf.h
Normal file
@ -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
|
16
libc/src/math/floor.cpp
Normal file
16
libc/src/math/floor.cpp
Normal file
@ -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
|
18
libc/src/math/floor.h
Normal file
18
libc/src/math/floor.h
Normal file
@ -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
|
16
libc/src/math/floorf.cpp
Normal file
16
libc/src/math/floorf.cpp
Normal file
@ -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
|
18
libc/src/math/floorf.h
Normal file
18
libc/src/math/floorf.h
Normal file
@ -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
|
16
libc/src/math/trunc.cpp
Normal file
16
libc/src/math/trunc.cpp
Normal file
@ -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
|
18
libc/src/math/trunc.h
Normal file
18
libc/src/math/trunc.h
Normal file
@ -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
|
16
libc/src/math/truncf.cpp
Normal file
16
libc/src/math/truncf.cpp
Normal file
@ -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
|
18
libc/src/math/truncf.h
Normal file
18
libc/src/math/truncf.h
Normal file
@ -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
|
@ -97,6 +97,84 @@ add_math_unittest(
|
||||
libc.utils.FPUtil.fputil
|
||||
)
|
||||
|
||||
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
|
||||
|
75
libc/test/src/math/ceil_test.cpp
Normal file
75
libc/test/src/math/ceil_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
75
libc/test/src/math/ceilf_test.cpp
Normal file
75
libc/test/src/math/ceilf_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
75
libc/test/src/math/floor_test.cpp
Normal file
75
libc/test/src/math/floor_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
76
libc/test/src/math/floorf_test.cpp
Normal file
76
libc/test/src/math/floorf_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
75
libc/test/src/math/trunc_test.cpp
Normal file
75
libc/test/src/math/trunc_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
77
libc/test/src/math/truncf_test.cpp
Normal file
77
libc/test/src/math/truncf_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user