[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
This commit is contained in:
Siva Chandra Reddy 2020-06-02 14:04:57 -07:00
parent 269d843720
commit 118c13c691
34 changed files with 1503 additions and 10 deletions

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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>]>,

View File

@ -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
)

View File

@ -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

18
libc/src/math/copysign.h Normal file
View File

@ -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

View File

@ -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

18
libc/src/math/copysignf.h Normal file
View File

@ -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

18
libc/src/math/frexp.cpp Normal file
View File

@ -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

18
libc/src/math/frexp.h Normal file
View File

@ -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

18
libc/src/math/frexpf.cpp Normal file
View File

@ -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

18
libc/src/math/frexpf.h Normal file
View File

@ -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

16
libc/src/math/logb.cpp Normal file
View File

@ -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

18
libc/src/math/logb.h Normal file
View File

@ -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

16
libc/src/math/logbf.cpp Normal file
View File

@ -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

18
libc/src/math/logbf.h Normal file
View File

@ -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

18
libc/src/math/modf.cpp Normal file
View File

@ -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

18
libc/src/math/modf.h Normal file
View File

@ -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

18
libc/src/math/modff.cpp Normal file
View File

@ -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

18
libc/src/math/modff.h Normal file
View File

@ -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

View File

@ -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
)

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -4,6 +4,7 @@ add_header_library(
BitPatterns.h
FloatOperations.h
FloatProperties.h
ManipulationFunctions.h
DEPS
libc.utils.CPP.standalone_cpp
)

View File

@ -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) {

View File

@ -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