//===- llvm/unittest/ADT/APFloat.cpp - APFloat unit tests ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
#include <ostream>
#include <string>
using namespace llvm;
static double convertToDoubleFromString(const char *Str) {
llvm::APFloat F(0.0);
F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven);
return F.convertToDouble();
}
static std::string convertToString(double d, unsigned Prec, unsigned Pad) {
llvm::SmallVector<char, 100> Buffer;
llvm::APFloat F(d);
F.toString(Buffer, Prec, Pad);
return std::string(Buffer.data(), Buffer.size());
}
namespace {
TEST(APFloatTest, FMA) {
APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
{
APFloat f1(14.5f);
APFloat f2(-14.5f);
APFloat f3(225.0f);
f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
EXPECT_EQ(14.75f, f1.convertToFloat());
}
{
APFloat Val2(2.0f);
APFloat f1((float)1.17549435e-38F);
APFloat f2((float)1.17549435e-38F);
f1.divide(Val2, rdmd);
f2.divide(Val2, rdmd);
APFloat f3(12.0f);
f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
EXPECT_EQ(12.0f, f1.convertToFloat());
}
}
TEST(APFloatTest, Denormal) {
APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
// Test single precision
{
const char *MinNormalStr = "1.17549435082228750797e-38";
EXPECT_FALSE(APFloat(APFloat::IEEEsingle, MinNormalStr).isDenormal());
EXPECT_FALSE(APFloat(APFloat::IEEEsingle, 0.0).isDenormal());
APFloat Val2(APFloat::IEEEsingle, 2.0e0);
APFloat T(APFloat::IEEEsingle, MinNormalStr);
T.divide(Val2, rdmd);
EXPECT_TRUE(T.isDenormal());
}
// Test double precision
{
const char *MinNormalStr = "2.22507385850720138309e-308";
EXPECT_FALSE(APFloat(APFloat::IEEEdouble, MinNormalStr).isDenormal());
EXPECT_FALSE(APFloat(APFloat::IEEEdouble, 0.0).isDenormal());
APFloat Val2(APFloat::IEEEdouble, 2.0e0);
APFloat T(APFloat::IEEEdouble, MinNormalStr);
T.divide(Val2, rdmd);
EXPECT_TRUE(T.isDenormal());
}
// Test Intel double-ext
{
const char *MinNormalStr = "3.36210314311209350626e-4932";
EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended, MinNormalStr).isDenormal());
EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended, 0.0).isDenormal());
APFloat Val2(APFloat::x87DoubleExtended, 2.0e0);
APFloat T(APFloat::x87DoubleExtended, MinNormalStr);
T.divide(Val2, rdmd);
EXPECT_TRUE(T.isDenormal());
}
// Test quadruple precision
{
const char *MinNormalStr = "3.36210314311209350626267781732175260e-4932";
EXPECT_FALSE(APFloat(APFloat::IEEEquad, MinNormalStr).isDenormal());
EXPECT_FALSE(APFloat(APFloat::IEEEquad, 0.0).isDenormal());
APFloat Val2(APFloat::IEEEquad, 2.0e0);
APFloat T(APFloat::IEEEquad, MinNormalStr);
T.divide(Val2, rdmd);
EXPECT_TRUE(T.isDenormal());
}
}
TEST(APFloatTest, Zero) {
EXPECT_EQ(0.0f, APFloat(0.0f).convertToFloat());
EXPECT_EQ(-0.0f, APFloat(-0.0f).convertToFloat());
EXPECT_TRUE(APFloat(-0.0f).isNegative());
EXPECT_EQ(0.0, APFloat(0.0).convertToDouble());
EXPECT_EQ(-0.0, APFloat(-0.0).convertToDouble());
EXPECT_TRUE(APFloat(-0.0).isNegative());
}
TEST(APFloatTest, fromZeroDecimalString) {
EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0").convertToDouble());
EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0").convertToDouble());
EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0").convertToDouble());
EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.").convertToDouble());
EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.").convertToDouble());
EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.").convertToDouble());
EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, ".0").convertToDouble());
EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.0").convertToDouble());
EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0").convertToDouble());
EXPECT_EQ( 0.0, APFloat(APFloat::