blob: 0a9874020f2796274ef53b5648a406b0884bc4f6 [file]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Unittests for bitwise operations on floating-point numbers.
///
//===----------------------------------------------------------------------===//
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/FPUtil/fp_bitwise.h"
#include "src/__support/macros/properties/types.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
using LIBC_NAMESPACE::fputil::BFloat16;
using LIBC_NAMESPACE::fputil::fp_and;
using LIBC_NAMESPACE::fputil::fp_andnot;
using LIBC_NAMESPACE::fputil::fp_not;
using LIBC_NAMESPACE::fputil::fp_or;
using LIBC_NAMESPACE::fputil::fp_xor;
using LIBC_NAMESPACE::fputil::FPBits;
using LIBC_NAMESPACE::fputil::scale_exp2;
template <typename T>
class LlvmLibcFPBitwiseTest : public LIBC_NAMESPACE::testing::Test {
DECLARE_SPECIAL_CONSTANTS(T)
static constexpr T pos_val = T(1.5);
static constexpr T neg_val = T(-1.5);
static constexpr T other_val = T(1.75);
static constexpr StorageType bits_of(T x) { return FPBits(x).uintval(); }
public:
void test_and() {
EXPECT_EQ(bits_of(fp_and(pos_val, zero)), bits_of(zero));
EXPECT_EQ(bits_of(fp_and(neg_val, zero)), bits_of(zero));
EXPECT_EQ(bits_of(fp_and(pos_val, neg_zero)), bits_of(zero));
EXPECT_EQ(bits_of(fp_and(neg_val, neg_zero)), bits_of(neg_zero));
EXPECT_EQ(bits_of(fp_and(pos_val, pos_val)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_and(neg_val, neg_val)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_and(neg_val, pos_val)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_and(pos_val, other_val)),
static_cast<StorageType>(bits_of(pos_val) & bits_of(other_val)));
}
void test_or() {
EXPECT_EQ(bits_of(fp_or(pos_val, zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_or(neg_val, zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_or(pos_val, neg_zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_or(neg_val, neg_zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_or(pos_val, pos_val)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_or(pos_val, other_val)),
static_cast<StorageType>(bits_of(pos_val) | bits_of(other_val)));
}
void test_xor() {
EXPECT_EQ(bits_of(fp_xor(pos_val, zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_xor(neg_val, zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_xor(pos_val, neg_zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_xor(neg_val, neg_zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_xor(neg_val, pos_val)), bits_of(neg_zero));
EXPECT_EQ(bits_of(fp_xor(pos_val, pos_val)), bits_of(zero));
EXPECT_EQ(bits_of(fp_xor(neg_val, neg_val)), bits_of(zero));
EXPECT_EQ(bits_of(fp_xor(pos_val, other_val)),
static_cast<StorageType>(bits_of(pos_val) ^ bits_of(other_val)));
}
void test_andnot() {
EXPECT_EQ(bits_of(fp_andnot(pos_val, zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_andnot(neg_val, zero)), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_andnot(pos_val, neg_zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_andnot(neg_val, neg_zero)), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_andnot(pos_val, pos_val)), bits_of(zero));
EXPECT_EQ(bits_of(fp_andnot(neg_val, neg_val)), bits_of(zero));
EXPECT_EQ(bits_of(fp_andnot(other_val, pos_val)),
static_cast<StorageType>(bits_of(other_val) & ~bits_of(pos_val)));
}
void test_not() {
EXPECT_EQ(bits_of(fp_not(fp_not(zero))), bits_of(zero));
EXPECT_EQ(bits_of(fp_not(fp_not(neg_zero))), bits_of(neg_zero));
EXPECT_EQ(bits_of(fp_not(fp_not(pos_val))), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_not(fp_not(neg_val))), bits_of(neg_val));
EXPECT_EQ(bits_of(fp_and(pos_val, fp_not(pos_val))), bits_of(zero));
EXPECT_EQ(bits_of(fp_and(neg_val, fp_not(neg_zero))), bits_of(pos_val));
EXPECT_EQ(bits_of(fp_andnot(pos_val, other_val)),
bits_of(fp_and(pos_val, fp_not(other_val))));
}
void test_scale_exp2() {
EXPECT_EQ(bits_of(scale_exp2(pos_val, 0)), bits_of(pos_val));
EXPECT_EQ(bits_of(scale_exp2(neg_val, 0)), bits_of(neg_val));
EXPECT_EQ(bits_of(scale_exp2(pos_val, 2)), bits_of(T(6.0)));
EXPECT_EQ(bits_of(scale_exp2(neg_val, 2)), bits_of(T(-6.0)));
EXPECT_EQ(bits_of(scale_exp2(pos_val, -2)), bits_of(T(0.375)));
EXPECT_EQ(bits_of(scale_exp2(neg_val, -2)), bits_of(T(-0.375)));
}
};
using FPBitwiseTypes = LIBC_NAMESPACE::testing::TypeList<float, double,
#ifdef LIBC_TYPES_HAS_FLOAT16
float16,
#endif // LIBC_TYPES_HAS_FLOAT16
#ifdef LIBC_TYPES_HAS_NATIVE_FLOAT128
float128,
#endif // LIBC_TYPES_HAS_NATIVE_FLOAT128
BFloat16>;
TYPED_TEST_F(LlvmLibcFPBitwiseTest, And, FPBitwiseTypes) { this->test_and(); }
TYPED_TEST_F(LlvmLibcFPBitwiseTest, Or, FPBitwiseTypes) { this->test_or(); }
TYPED_TEST_F(LlvmLibcFPBitwiseTest, Xor, FPBitwiseTypes) { this->test_xor(); }
TYPED_TEST_F(LlvmLibcFPBitwiseTest, AndNot, FPBitwiseTypes) {
this->test_andnot();
}
TYPED_TEST_F(LlvmLibcFPBitwiseTest, Not, FPBitwiseTypes) { this->test_not(); }
TYPED_TEST_F(LlvmLibcFPBitwiseTest, ScaleExp2, FPBitwiseTypes) {
this->test_scale_exp2();
}
TEST(LlvmLibcFPBitwiseConstexprTest, ConstexprEval) {
static_assert(FPBits<double>(fp_xor(-1.5, 1.5)).uintval() ==
FPBits<double>::SIGN_MASK);
static_assert(FPBits<double>(fp_andnot(-1.5, -0.0)).uintval() ==
FPBits<double>(1.5).uintval());
static_assert(FPBits<double>(fp_or(1.5, -0.0)).uintval() ==
FPBits<double>(-1.5).uintval());
static_assert(FPBits<double>(fp_and(-1.5, -0.0)).uintval() ==
FPBits<double>::SIGN_MASK);
static_assert(FPBits<double>(fp_not(fp_not(1.5))).uintval() ==
FPBits<double>(1.5).uintval());
static_assert(FPBits<double>(scale_exp2(1.5, 2)).uintval() ==
FPBits<double>(6.0).uintval());
static_assert(FPBits<double>(scale_exp2(1.5, -2)).uintval() ==
FPBits<double>(0.375).uintval());
static_assert(FPBits<float>(fp_xor(-1.5f, 1.5f)).uintval() ==
FPBits<float>::SIGN_MASK);
static_assert(FPBits<float>(fp_andnot(-1.5f, -0.0f)).uintval() ==
FPBits<float>(1.5f).uintval());
static_assert(FPBits<float>(scale_exp2(1.5f, 2)).uintval() ==
FPBits<float>(6.0f).uintval());
static_assert(FPBits<float>(scale_exp2(1.5f, -2)).uintval() ==
FPBits<float>(0.375f).uintval());
}