18 changes: 18 additions & 0 deletions libc/src/math/logbf.h
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions libc/src/math/modf.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions libc/src/math/modf.h
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions libc/src/math/modff.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions libc/src/math/modff.h
Original file line number Diff line number Diff line change
@@ -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
96 changes: 96 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
63 changes: 63 additions & 0 deletions libc/test/src/math/copysign_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
65 changes: 65 additions & 0 deletions libc/test/src/math/copysignf_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
141 changes: 141 additions & 0 deletions libc/test/src/math/frexp_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
150 changes: 150 additions & 0 deletions libc/test/src/math/frexpf_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
99 changes: 99 additions & 0 deletions libc/test/src/math/logb_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
99 changes: 99 additions & 0 deletions libc/test/src/math/logbf_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
130 changes: 130 additions & 0 deletions libc/test/src/math/modf_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
135 changes: 135 additions & 0 deletions libc/test/src/math/modff_test.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
6 changes: 6 additions & 0 deletions libc/utils/FPUtil/BitPatterns.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
1 change: 1 addition & 0 deletions libc/utils/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_header_library(
BitPatterns.h
FloatOperations.h
FloatProperties.h
ManipulationFunctions.h
DEPS
libc.utils.CPP.standalone_cpp
)
24 changes: 14 additions & 10 deletions libc/utils/FPUtil/FloatOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
102 changes: 102 additions & 0 deletions libc/utils/FPUtil/ManipulationFunctions.h
Original file line number Diff line number Diff line change
@@ -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