//===-- Unittests for the FPBits class ------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/__support/FPUtil/fpbits_str.h"
#include "src/__support/big_int.h"
#include "src/__support/integer_literals.h"
#include "src/__support/macros/properties/types.h"
#include "src/__support/sign.h" // Sign
#include "test/UnitTest/Test.h"

using LIBC_NAMESPACE::Sign;
using LIBC_NAMESPACE::UInt;
using LIBC_NAMESPACE::fputil::FPBits;
using LIBC_NAMESPACE::fputil::FPType;
using LIBC_NAMESPACE::fputil::internal::FPRep;

using LIBC_NAMESPACE::operator""_u16;
using LIBC_NAMESPACE::operator""_u32;
using LIBC_NAMESPACE::operator""_u64;
using LIBC_NAMESPACE::operator""_u96;
using LIBC_NAMESPACE::operator""_u128;

TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary16) {
  using Rep = FPRep<FPType::IEEE754_Binary16>;
  using u16 = typename Rep::StorageType;

  EXPECT_EQ(0b0'00000'0000000000_u16, u16(Rep::zero()));
  EXPECT_EQ(0b0'01111'0000000000_u16, u16(Rep::one()));
  EXPECT_EQ(0b0'00000'0000000001_u16, u16(Rep::min_subnormal()));
  EXPECT_EQ(0b0'00000'1111111111_u16, u16(Rep::max_subnormal()));
  EXPECT_EQ(0b0'00001'0000000000_u16, u16(Rep::min_normal()));
  EXPECT_EQ(0b0'11110'1111111111_u16, u16(Rep::max_normal()));
  EXPECT_EQ(0b0'11111'0000000000_u16, u16(Rep::inf()));
  EXPECT_EQ(0b0'11111'0100000000_u16, u16(Rep::signaling_nan()));
  EXPECT_EQ(0b0'11111'1000000000_u16, u16(Rep::quiet_nan()));
}

TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary32) {
  using Rep = FPRep<FPType::IEEE754_Binary32>;
  using u32 = typename Rep::StorageType;

  EXPECT_EQ(0b0'00000000'00000000000000000000000_u32, u32(Rep::zero()));
  EXPECT_EQ(0b0'01111111'00000000000000000000000_u32, u32(Rep::one()));
  EXPECT_EQ(0b0'00000000'00000000000000000000001_u32,
            u32(Rep::min_subnormal()));
  EXPECT_EQ(0b0'00000000'11111111111111111111111_u32,
            u32(Rep::max_subnormal()));
  EXPECT_EQ(0b0'00000001'00000000000000000000000_u32, u32(Rep::min_normal()));
  EXPECT_EQ(0b0'11111110'11111111111111111111111_u32, u32(Rep::max_normal()));
  EXPECT_EQ(0b0'11111111'00000000000000000000000_u32, u32(Rep::inf()));
  EXPECT_EQ(0b0'11111111'01000000000000000000000_u32,
            u32(Rep::signaling_nan()));
  EXPECT_EQ(0b0'11111111'10000000000000000000000_u32, u32(Rep::quiet_nan()));
}

TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary64) {
  using Rep = FPRep<FPType::IEEE754_Binary64>;
  using u64 = typename Rep::StorageType;

  EXPECT_EQ(
      0b0'00000000000'0000000000000000000000000000000000000000000000000000_u64,
      u64(Rep::zero()));
  EXPECT_EQ(
      0b0'01111111111'0000000000000000000000000000000000000000000000000000_u64,
      u64(Rep::one()));
  EXPECT_EQ(
      0b0'00000000000'0000000000000000000000000000000000000000000000000001_u64,
      u64(Rep::min_subnormal()));
  EXPECT_EQ(
      0b0'00000000000'1111111111111111111111111111111111111111111111111111_u64,
      u64(Rep::max_subnormal()));
  EXPECT_EQ(
      0b0'00000000001'0000000000000000000000000000000000000000000000000000_u64,
      u64(Rep::min_normal()));
  EXPECT_EQ(
      0b0'11111111110'1111111111111111111111111111111111111111111111111111_u64,
      u64(Rep::max_normal()));
  EXPECT_EQ(
      0b0'11111111111'0000000000000000000000000000000000000000000000000000_u64,
      u64(Rep::inf()));
  EXPECT_EQ(
      0b0'11111111111'0100000000000000000000000000000000000000000000000000_u64,
      u64(Rep::signaling_nan()));
  EXPECT_EQ(
      0b0'11111111111'1000000000000000000000000000000000000000000000000000_u64,
      u64(Rep::quiet_nan()));
}

TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) {
  using Rep = FPRep<FPType::IEEE754_Binary128>;

  EXPECT_EQ(
      0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::zero()));
  EXPECT_EQ(
      0b0'011111111111111'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::one()));
  EXPECT_EQ(
      0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_u128,
      UInt128(Rep::min_subnormal()));
  EXPECT_EQ(
      0b0'000000000000000'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_u128,
      UInt128(Rep::max_subnormal()));
  EXPECT_EQ(
      0b0'000000000000001'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::min_normal()));
  EXPECT_EQ(
      0b0'111111111111110'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_u128,
      UInt128(Rep::max_normal()));
  EXPECT_EQ(
      0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::inf()));
  EXPECT_EQ(
      0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::signaling_nan()));
  EXPECT_EQ(
      0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::quiet_nan()));
}

#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) {
  using Rep = FPRep<FPType::X86_Binary80>;

#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(
      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::zero()));
  EXPECT_EQ(
      0b0'0111111111111111000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::one()));
  EXPECT_EQ(
      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000001_u128,
      UInt128(Rep::min_subnormal()));
  EXPECT_EQ(
      0b0'0000000000000000111111111111111111111111111111111111111111111111111111111111111_u128,
      UInt128(Rep::max_subnormal()));
  EXPECT_EQ(
      0b0'0000000000000011000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::min_normal()));
  EXPECT_EQ(
      0b0'1111111111111101111111111111111111111111111111111111111111111111111111111111111_u128,
      UInt128(Rep::max_normal()));
  EXPECT_EQ(
      0b0'1111111111111111000000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::inf()));
  EXPECT_EQ(
      0b0'1111111111111111010000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::signaling_nan()));
  EXPECT_EQ(
      0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u128,
      UInt128(Rep::quiet_nan()));
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(
      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::zero()));
  EXPECT_EQ(
      0b0'0111111111111111000000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::one()));
  EXPECT_EQ(
      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000001_u96,
      UInt<96>(Rep::min_subnormal()));
  EXPECT_EQ(
      0b0'0000000000000000111111111111111111111111111111111111111111111111111111111111111_u96,
      UInt<96>(Rep::max_subnormal()));
  EXPECT_EQ(
      0b0'0000000000000011000000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::min_normal()));
  EXPECT_EQ(
      0b0'1111111111111101111111111111111111111111111111111111111111111111111111111111111_u96,
      UInt<96>(Rep::max_normal()));
  EXPECT_EQ(
      0b0'1111111111111111000000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::inf()));
  EXPECT_EQ(
      0b0'1111111111111111010000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::signaling_nan()));
  EXPECT_EQ(
      0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u96,
      UInt<96>(Rep::quiet_nan()));
#else
#error "unhandled long double type"
#endif
}

TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) {
  using Rep = FPRep<FPType::X86_Binary80>;

#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_TRUE( // NAN : Pseudo-Infinity
      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Pseudo Not a Number
      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000001_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Pseudo Not a Number
      Rep(0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Signalling Not a Number
      Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000001_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Floating-point Indefinite
      Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Quiet Not a Number
      Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000001_u128)
          .is_nan());
  EXPECT_TRUE( // NAN : Unnormal
      Rep(0b0'111111111111110'0000000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_FALSE( // Zero
      Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_FALSE( // Subnormal
      Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000001_u128)
          .is_nan());
  EXPECT_FALSE( // Pseudo Denormal
      Rep(0b0'000000000000000'1000000000000000000000000000000000000000000000000000000000000001_u128)
          .is_nan());
  EXPECT_FALSE( // Infinity
      Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
  EXPECT_FALSE( // Normalized
      Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u128)
          .is_nan());
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_TRUE( // NAN : Pseudo-Infinity
      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Pseudo Not a Number
      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000001_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Pseudo Not a Number
      Rep(0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Signalling Not a Number
      Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000001_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Floating-point Indefinite
      Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Quiet Not a Number
      Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000001_u96)
          .is_nan());
  EXPECT_TRUE( // NAN : Unnormal
      Rep(0b0'111111111111110'0000000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_FALSE( // Zero
      Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_FALSE( // Subnormal
      Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000001_u96)
          .is_nan());
  EXPECT_FALSE( // Pseudo Denormal
      Rep(0b0'000000000000000'1000000000000000000000000000000000000000000000000000000000000001_u96)
          .is_nan());
  EXPECT_FALSE( // Infinity
      Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
  EXPECT_FALSE( // Normalized
      Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u96)
          .is_nan());
#else
#error "unhandled long double type"
#endif
}
#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80

enum class FP {
  ZERO,
  MIN_SUBNORMAL,
  MAX_SUBNORMAL,
  MIN_NORMAL,
  ONE,
  MAX_NORMAL,
  INF,
  SIGNALING_NAN,
  QUIET_NAN
};

constexpr FP all_fp_values[] = {
    FP::ZERO,       FP::MIN_SUBNORMAL, FP::MAX_SUBNORMAL,
    FP::MIN_NORMAL, FP::ONE,           FP::MAX_NORMAL,
    FP::INF,        FP::SIGNALING_NAN, FP::QUIET_NAN,
};

constexpr Sign all_signs[] = {Sign::POS, Sign::NEG};

using FPTypes = LIBC_NAMESPACE::testing::TypeList<
    FPRep<FPType::IEEE754_Binary16>, FPRep<FPType::IEEE754_Binary32>,
    FPRep<FPType::IEEE754_Binary64>, FPRep<FPType::IEEE754_Binary128>,
    FPRep<FPType::X86_Binary80>>;

template <typename T> constexpr auto make(Sign sign, FP fp) {
  switch (fp) {
  case FP::ZERO:
    return T::zero(sign);
  case FP::MIN_SUBNORMAL:
    return T::min_subnormal(sign);
  case FP::MAX_SUBNORMAL:
    return T::max_subnormal(sign);
  case FP::MIN_NORMAL:
    return T::min_normal(sign);
  case FP::ONE:
    return T::one(sign);
  case FP::MAX_NORMAL:
    return T::max_normal(sign);
  case FP::INF:
    return T::inf(sign);
  case FP::SIGNALING_NAN:
    return T::signaling_nan(sign);
  case FP::QUIET_NAN:
    return T::quiet_nan(sign);
  }
  __builtin_unreachable();
}

// Tests all properties for all types of float.
TYPED_TEST(LlvmLibcFPBitsTest, Properties, FPTypes) {
  for (Sign sign : all_signs) {
    for (FP fp : all_fp_values) {
      const T value = make<T>(sign, fp);
      // is_zero
      ASSERT_EQ(value.is_zero(), fp == FP::ZERO);
      // is_inf_or_nan
      ASSERT_EQ(value.is_inf_or_nan(), fp == FP::INF ||
                                           fp == FP::SIGNALING_NAN ||
                                           fp == FP::QUIET_NAN);
      // is_finite
      ASSERT_EQ(value.is_finite(), fp != FP::INF && fp != FP::SIGNALING_NAN &&
                                       fp != FP::QUIET_NAN);
      // is_inf
      ASSERT_EQ(value.is_inf(), fp == FP::INF);
      // is_nan
      ASSERT_EQ(value.is_nan(), fp == FP::SIGNALING_NAN || fp == FP::QUIET_NAN);
      // is_normal
      ASSERT_EQ(value.is_normal(),
                fp == FP::MIN_NORMAL || fp == FP::ONE || fp == FP::MAX_NORMAL);
      // is_quiet_nan
      ASSERT_EQ(value.is_quiet_nan(), fp == FP::QUIET_NAN);
      // is_signaling_nan
      ASSERT_EQ(value.is_signaling_nan(), fp == FP::SIGNALING_NAN);
      // is_subnormal
      ASSERT_EQ(value.is_subnormal(), fp == FP::ZERO ||
                                          fp == FP::MIN_SUBNORMAL ||
                                          fp == FP::MAX_SUBNORMAL);
      // is_pos
      ASSERT_EQ(value.is_pos(), sign == Sign::POS);
      ASSERT_EQ(value.sign().is_pos(), sign == Sign::POS);
      // is_neg
      ASSERT_EQ(value.is_neg(), sign == Sign::NEG);
      ASSERT_EQ(value.sign().is_neg(), sign == Sign::NEG);
    }
  }
}

#define ASSERT_SAME_REP(A, B) ASSERT_EQ(A.uintval(), B.uintval());

TYPED_TEST(LlvmLibcFPBitsTest, NextTowardInf, FPTypes) {
  struct {
    FP before, after;
  } TEST_CASES[] = {
      {FP::ZERO, FP::MIN_SUBNORMAL},          //
      {FP::MAX_SUBNORMAL, FP::MIN_NORMAL},    //
      {FP::MAX_NORMAL, FP::INF},              //
      {FP::INF, FP::INF},                     //
      {FP::QUIET_NAN, FP::QUIET_NAN},         //
      {FP::SIGNALING_NAN, FP::SIGNALING_NAN}, //
  };
  for (Sign sign : all_signs) {
    for (auto tc : TEST_CASES) {
      T val = make<T>(sign, tc.before);
      ASSERT_SAME_REP(val.next_toward_inf(), make<T>(sign, tc.after));
    }
  }
}

TEST(LlvmLibcFPBitsTest, FloatType) {
  using FloatBits = FPBits<float>;

  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::POS)).c_str(),
               "(+Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::NEG)).c_str(),
               "(-Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::signaling_nan()).c_str(),
               "(NaN)");

  FloatBits zero(0.0f);
  EXPECT_TRUE(zero.is_pos());
  EXPECT_EQ(zero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(zero.get_mantissa(), 0_u32);
  EXPECT_EQ(zero.uintval(), 0_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
               "0x00000000 = (S: 0, E: 0x0000, M: 0x00000000)");

  FloatBits negzero(-0.0f);
  EXPECT_TRUE(negzero.is_neg());
  EXPECT_EQ(negzero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(negzero.get_mantissa(), 0_u32);
  EXPECT_EQ(negzero.uintval(), 0x80000000_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
               "0x80000000 = (S: 1, E: 0x0000, M: 0x00000000)");

  FloatBits one(1.0f);
  EXPECT_TRUE(one.is_pos());
  EXPECT_EQ(one.get_biased_exponent(), 0x7F_u16);
  EXPECT_EQ(one.get_mantissa(), 0_u32);
  EXPECT_EQ(one.uintval(), 0x3F800000_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
               "0x3F800000 = (S: 0, E: 0x007F, M: 0x00000000)");

  FloatBits negone(-1.0f);
  EXPECT_TRUE(negone.is_neg());
  EXPECT_EQ(negone.get_biased_exponent(), 0x7F_u16);
  EXPECT_EQ(negone.get_mantissa(), 0_u32);
  EXPECT_EQ(negone.uintval(), 0xBF800000_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
               "0xBF800000 = (S: 1, E: 0x007F, M: 0x00000000)");

  FloatBits num(1.125f);
  EXPECT_TRUE(num.is_pos());
  EXPECT_EQ(num.get_biased_exponent(), 0x7F_u16);
  EXPECT_EQ(num.get_mantissa(), 0x00100000_u32);
  EXPECT_EQ(num.uintval(), 0x3F900000_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
               "0x3F900000 = (S: 0, E: 0x007F, M: 0x00100000)");

  FloatBits negnum(-1.125f);
  EXPECT_TRUE(negnum.is_neg());
  EXPECT_EQ(negnum.get_biased_exponent(), 0x7F_u16);
  EXPECT_EQ(negnum.get_mantissa(), 0x00100000_u32);
  EXPECT_EQ(negnum.uintval(), 0xBF900000_u32);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
               "0xBF900000 = (S: 1, E: 0x007F, M: 0x00100000)");

  FloatBits quiet_nan = FloatBits::quiet_nan();
  EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
}

TEST(LlvmLibcFPBitsTest, DoubleType) {
  using DoubleBits = FPBits<double>;

  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::POS)).c_str(),
               "(+Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::NEG)).c_str(),
               "(-Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::signaling_nan()).c_str(),
               "(NaN)");

  DoubleBits zero(0.0);
  EXPECT_TRUE(zero.is_pos());
  EXPECT_EQ(zero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(zero.get_mantissa(), 0_u64);
  EXPECT_EQ(zero.uintval(), 0_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
               "0x0000000000000000 = (S: 0, E: 0x0000, M: 0x0000000000000000)");

  DoubleBits negzero(-0.0);
  EXPECT_TRUE(negzero.is_neg());
  EXPECT_EQ(negzero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(negzero.get_mantissa(), 0_u64);
  EXPECT_EQ(negzero.uintval(), 0x8000000000000000_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
               "0x8000000000000000 = (S: 1, E: 0x0000, M: 0x0000000000000000)");

  DoubleBits one(1.0);
  EXPECT_TRUE(one.is_pos());
  EXPECT_EQ(one.get_biased_exponent(), 0x03FF_u16);
  EXPECT_EQ(one.get_mantissa(), 0_u64);
  EXPECT_EQ(one.uintval(), 0x3FF0000000000000_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
               "0x3FF0000000000000 = (S: 0, E: 0x03FF, M: 0x0000000000000000)");

  DoubleBits negone(-1.0);
  EXPECT_TRUE(negone.is_neg());
  EXPECT_EQ(negone.get_biased_exponent(), 0x03FF_u16);
  EXPECT_EQ(negone.get_mantissa(), 0_u64);
  EXPECT_EQ(negone.uintval(), 0xBFF0000000000000_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
               "0xBFF0000000000000 = (S: 1, E: 0x03FF, M: 0x0000000000000000)");

  DoubleBits num(1.125);
  EXPECT_TRUE(num.is_pos());
  EXPECT_EQ(num.get_biased_exponent(), 0x03FF_u16);
  EXPECT_EQ(num.get_mantissa(), 0x0002000000000000_u64);
  EXPECT_EQ(num.uintval(), 0x3FF2000000000000_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
               "0x3FF2000000000000 = (S: 0, E: 0x03FF, M: 0x0002000000000000)");

  DoubleBits negnum(-1.125);
  EXPECT_TRUE(negnum.is_neg());
  EXPECT_EQ(negnum.get_biased_exponent(), 0x03FF_u16);
  EXPECT_EQ(negnum.get_mantissa(), 0x0002000000000000_u64);
  EXPECT_EQ(negnum.uintval(), 0xBFF2000000000000_u64);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
               "0xBFF2000000000000 = (S: 1, E: 0x03FF, M: 0x0002000000000000)");

  DoubleBits quiet_nan = DoubleBits::quiet_nan();
  EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
}

#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
  using LongDoubleBits = FPBits<long double>;
  using Rep = FPRep<FPType::X86_Binary80>;

  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(),
               "(+Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(),
               "(-Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::signaling_nan()).c_str(),
               "(NaN)");

  LongDoubleBits zero(0.0l);
  EXPECT_TRUE(zero.is_pos());
  EXPECT_EQ(zero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(zero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero()));
  EXPECT_EQ(zero.uintval(), LongDoubleBits::StorageType(Rep::zero()));
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(zero).c_str(),
      "0x00000000000000000000000000000000 = "
      "(S: 0, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
               "0x000000000000000000000000 = "
               "(S: 0, E: 0x0000, I: 0, M: 0x000000000000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits negzero(-0.0l);
  EXPECT_TRUE(negzero.is_neg());
  EXPECT_EQ(negzero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(negzero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero()));
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u128);
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(negzero).c_str(),
      "0x00000000000080000000000000000000 = "
      "(S: 1, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u96);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
               "0x000080000000000000000000 = "
               "(S: 1, E: 0x0000, I: 0, M: 0x000000000000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits one(1.0l);
  EXPECT_TRUE(one.is_pos());
  EXPECT_EQ(one.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(one.get_mantissa(), LongDoubleBits::StorageType(Rep::zero()));
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u128);
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(one).c_str(),
      "0x0000000000003FFF8000000000000000 = "
      "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u96);
  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
               "0x00003FFF8000000000000000 = "
               "(S: 0, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits negone(-1.0l);
  EXPECT_TRUE(negone.is_neg());
  EXPECT_EQ(negone.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(negone.get_mantissa(), LongDoubleBits::StorageType(Rep::zero()));
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u128);
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(negone).c_str(),
      "0x000000000000BFFF8000000000000000 = "
      "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u96);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
               "0x0000BFFF8000000000000000 = "
               "(S: 1, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits num(1.125l);
  EXPECT_TRUE(num.is_pos());
  EXPECT_EQ(num.get_biased_exponent(), 0x3FFF_u16);
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u128);
  EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u128);
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(num).c_str(),
      "0x0000000000003FFF9000000000000000 = "
      "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u96);
  EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u96);
  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
               "0x00003FFF9000000000000000 = "
               "(S: 0, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits negnum(-1.125l);
  EXPECT_TRUE(negnum.is_neg());
  EXPECT_EQ(negnum.get_biased_exponent(), 0x3FFF_u16);
#if __SIZEOF_LONG_DOUBLE__ == 16
  EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u128);
  EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u128);
  EXPECT_STREQ(
      LIBC_NAMESPACE::str(negnum).c_str(),
      "0x000000000000BFFF9000000000000000 = "
      "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
#elif __SIZEOF_LONG_DOUBLE__ == 12
  EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u96);
  EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u96);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
               "0x0000BFFF9000000000000000 = "
               "(S: 1, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)");
#else
#error "unhandled long double type"
#endif

  LongDoubleBits quiet_nan = LongDoubleBits::quiet_nan();
  EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
}
#else
TEST(LlvmLibcFPBitsTest, LongDoubleType) {
#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
  return; // The tests for the "double" type cover for this case.
#else
  using LongDoubleBits = FPBits<long double>;

  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(),
               "(+Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(),
               "(-Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::signaling_nan()).c_str(),
               "(NaN)");

  LongDoubleBits zero(0.0l);
  EXPECT_TRUE(zero.is_pos());
  EXPECT_EQ(zero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(zero.get_mantissa(), 0_u128);
  EXPECT_EQ(zero.uintval(), 0_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
               "0x00000000000000000000000000000000 = "
               "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");

  LongDoubleBits negzero(-0.0l);
  EXPECT_TRUE(negzero.is_neg());
  EXPECT_EQ(negzero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(negzero.get_mantissa(), 0_u128);
  EXPECT_EQ(negzero.uintval(), 0x80000000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
               "0x80000000000000000000000000000000 = "
               "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");

  LongDoubleBits one(1.0l);
  EXPECT_TRUE(one.is_pos());
  EXPECT_EQ(one.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(one.get_mantissa(), 0_u128);
  EXPECT_EQ(one.uintval(), 0x3FFF0000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
               "0x3FFF0000000000000000000000000000 = "
               "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");

  LongDoubleBits negone(-1.0l);
  EXPECT_TRUE(negone.is_neg());
  EXPECT_EQ(negone.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(negone.get_mantissa(), 0_u128);
  EXPECT_EQ(negone.uintval(), 0xBFFF0000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
               "0xBFFF0000000000000000000000000000 = "
               "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");

  LongDoubleBits num(1.125l);
  EXPECT_TRUE(num.is_pos());
  EXPECT_EQ(num.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(num.get_mantissa(), 0x2000'00000000'00000000'00000000_u128);
  EXPECT_EQ(num.uintval(), 0x3FFF2000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
               "0x3FFF2000000000000000000000000000 = "
               "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");

  LongDoubleBits negnum(-1.125l);
  EXPECT_TRUE(negnum.is_neg());
  EXPECT_EQ(negnum.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(negnum.get_mantissa(), 0x2000'00000000'00000000'00000000_u128);
  EXPECT_EQ(negnum.uintval(), 0xBFFF2000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
               "0xBFFF2000000000000000000000000000 = "
               "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");

  LongDoubleBits quiet_nan = LongDoubleBits::quiet_nan();
  EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
#endif
}
#endif

#if defined(LIBC_TYPES_HAS_FLOAT128)
TEST(LlvmLibcFPBitsTest, Float128Type) {
  using Float128Bits = FPBits<float128>;

  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::POS)).c_str(),
               "(+Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::NEG)).c_str(),
               "(-Infinity)");
  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::signaling_nan()).c_str(),
               "(NaN)");

  Float128Bits zero = Float128Bits::zero(Sign::POS);
  EXPECT_TRUE(zero.is_pos());
  EXPECT_EQ(zero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(zero.get_mantissa(), 0_u128);
  EXPECT_EQ(zero.uintval(), 0_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
               "0x00000000000000000000000000000000 = "
               "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");

  Float128Bits negzero = Float128Bits::zero(Sign::NEG);
  EXPECT_TRUE(negzero.is_neg());
  EXPECT_EQ(negzero.get_biased_exponent(), 0_u16);
  EXPECT_EQ(negzero.get_mantissa(), 0_u128);
  EXPECT_EQ(negzero.uintval(), 0x80000000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
               "0x80000000000000000000000000000000 = "
               "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");

  Float128Bits one(float128(1.0));
  EXPECT_TRUE(one.is_pos());
  EXPECT_EQ(one.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(one.get_mantissa(), 0_u128);
  EXPECT_EQ(one.uintval(), 0x3FFF0000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
               "0x3FFF0000000000000000000000000000 = "
               "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");

  Float128Bits negone(float128(-1.0));
  EXPECT_TRUE(negone.is_neg());
  EXPECT_EQ(negone.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(negone.get_mantissa(), 0_u128);
  EXPECT_EQ(negone.uintval(), 0xBFFF0000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
               "0xBFFF0000000000000000000000000000 = "
               "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");

  Float128Bits num(float128(1.125));
  EXPECT_TRUE(num.is_pos());
  EXPECT_EQ(num.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(num.get_mantissa(), 0x2000'00000000'00000000'00000000_u128);
  EXPECT_EQ(num.uintval(), 0x3FFF2000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
               "0x3FFF2000000000000000000000000000 = "
               "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");

  Float128Bits negnum(float128(-1.125));
  EXPECT_TRUE(negnum.is_neg());
  EXPECT_EQ(negnum.get_biased_exponent(), 0x3FFF_u16);
  EXPECT_EQ(negnum.get_mantissa(), 0x2000'00000000'00000000'00000000_u128);
  EXPECT_EQ(negnum.uintval(), 0xBFFF2000'00000000'00000000'00000000_u128);
  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
               "0xBFFF2000000000000000000000000000 = "
               "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");

  Float128Bits quiet_nan = Float128Bits::quiet_nan();
  EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
}
#endif // LIBC_TYPES_HAS_FLOAT128
