Skip to content

Commit

Permalink
[APFloat] Enlarge ExponentType to 32bit integer
Browse files Browse the repository at this point in the history
Enlarge the size of ExponentType from 16bit integer to 32bit. This is
required to prevent exponent overflow/underflow.

Note that IEEEFloat size and alignment don't change in 64bit or 32bit
compilation targets (and in turn, neither does APFloat).

Fixes PR34851.

Differential Revision: https://reviews.llvm.org/D69771
  • Loading branch information
ekatz committed Nov 22, 2019
1 parent 8ca7871 commit 8606d01
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 16 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/ADT/APFloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ struct APFloatBase {
static const unsigned integerPartWidth = APInt::APINT_BITS_PER_WORD;

/// A signed type to represent a floating point numbers unbiased exponent.
typedef signed short ExponentType;
typedef int32_t ExponentType;

/// \name Floating Point Semantics.
/// @{
Expand Down
132 changes: 117 additions & 15 deletions llvm/unittests/ADT/APFloatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2335,21 +2335,28 @@ TEST(APFloatTest, multiply) {
APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
APFloat PSmallestNormalized =
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
APFloat MSmallestNormalized =
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);

APFloat MaxQuad(APFloat::IEEEquad(),
"0x1.ffffffffffffffffffffffffffffp+16383");
APFloat MinQuad(APFloat::IEEEquad(),
"0x0.0000000000000000000000000001p-16382");
APFloat NMinQuad(APFloat::IEEEquad(),
"-0x0.0000000000000000000000000001p-16382");

const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;

const unsigned NumTests = 169;
struct {
APFloat x;
APFloat y;
const char *result;
int status;
int category;
} SpecialCaseTests[NumTests] = {
APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
} SpecialCaseTests[] = {
{ PInf, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
Expand Down Expand Up @@ -2587,15 +2594,70 @@ TEST(APFloatTest, multiply) {
{ MSmallestNormalized, PSmallestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
{ MSmallestNormalized, MSmallestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
{ MSmallestNormalized, PSmallestNormalized, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
{ MSmallestNormalized, MSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero }
{ MSmallestNormalized, MSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero },

{MaxQuad, MinQuad, "0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmNearestTiesToEven},
{MaxQuad, MinQuad, "0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardPositive},
{MaxQuad, MinQuad, "0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardNegative},
{MaxQuad, MinQuad, "0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, MinQuad, "0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmNearestTiesToAway},

{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmNearestTiesToEven},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardPositive},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardNegative},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp-111", APFloat::opOK,
APFloat::fcNormal, APFloat::rmNearestTiesToAway},

{MaxQuad, MaxQuad, "inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToEven},
{MaxQuad, MaxQuad, "inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmTowardPositive},
{MaxQuad, MaxQuad, "0x1.ffffffffffffffffffffffffffffp+16383",
APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardNegative},
{MaxQuad, MaxQuad, "0x1.ffffffffffffffffffffffffffffp+16383",
APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, MaxQuad, "inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToAway},

{MinQuad, MinQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToEven},
{MinQuad, MinQuad, "0x0.0000000000000000000000000001p-16382",
UnderflowStatus, APFloat::fcNormal, APFloat::rmTowardPositive},
{MinQuad, MinQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardNegative},
{MinQuad, MinQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardZero},
{MinQuad, MinQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToAway},

{MinQuad, NMinQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToEven},
{MinQuad, NMinQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardPositive},
{MinQuad, NMinQuad, "-0x0.0000000000000000000000000001p-16382",
UnderflowStatus, APFloat::fcNormal, APFloat::rmTowardNegative},
{MinQuad, NMinQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardZero},
{MinQuad, NMinQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToAway},
};

for (size_t i = 0; i < NumTests; ++i) {
for (size_t i = 0; i < array_lengthof(SpecialCaseTests); ++i) {
APFloat x(SpecialCaseTests[i].x);
APFloat y(SpecialCaseTests[i].y);
APFloat::opStatus status = x.multiply(y, APFloat::rmNearestTiesToEven);
APFloat::opStatus status = x.multiply(y, SpecialCaseTests[i].roundingMode);

APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
APFloat result(x.getSemantics(), SpecialCaseTests[i].result);

EXPECT_TRUE(result.bitwiseIsEqual(x));
EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
Expand Down Expand Up @@ -2624,21 +2686,28 @@ TEST(APFloatTest, divide) {
APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
APFloat PSmallestNormalized =
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
APFloat MSmallestNormalized =
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);

APFloat MaxQuad(APFloat::IEEEquad(),
"0x1.ffffffffffffffffffffffffffffp+16383");
APFloat MinQuad(APFloat::IEEEquad(),
"0x0.0000000000000000000000000001p-16382");
APFloat NMinQuad(APFloat::IEEEquad(),
"-0x0.0000000000000000000000000001p-16382");

const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;

const unsigned NumTests = 169;
struct {
APFloat x;
APFloat y;
const char *result;
int status;
int category;
} SpecialCaseTests[NumTests] = {
APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
} SpecialCaseTests[] = {
{ PInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
{ PInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
{ PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity },
Expand Down Expand Up @@ -2877,14 +2946,47 @@ TEST(APFloatTest, divide) {
{ MSmallestNormalized, MSmallestValue, "0x1p+23", APFloat::opOK, APFloat::fcNormal },
{ MSmallestNormalized, PSmallestNormalized, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ MSmallestNormalized, MSmallestNormalized, "0x1p+0", APFloat::opOK, APFloat::fcNormal },

{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToEven},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp+16383",
APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardPositive},
{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmTowardNegative},
{MaxQuad, NMinQuad, "-0x1.ffffffffffffffffffffffffffffp+16383",
APFloat::opInexact, APFloat::fcNormal, APFloat::rmTowardZero},
{MaxQuad, NMinQuad, "-inf", OverflowStatus, APFloat::fcInfinity,
APFloat::rmNearestTiesToAway},

{MinQuad, MaxQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToEven},
{MinQuad, MaxQuad, "0x0.0000000000000000000000000001p-16382",
UnderflowStatus, APFloat::fcNormal, APFloat::rmTowardPositive},
{MinQuad, MaxQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardNegative},
{MinQuad, MaxQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardZero},
{MinQuad, MaxQuad, "0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToAway},

{NMinQuad, MaxQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToEven},
{NMinQuad, MaxQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardPositive},
{NMinQuad, MaxQuad, "-0x0.0000000000000000000000000001p-16382",
UnderflowStatus, APFloat::fcNormal, APFloat::rmTowardNegative},
{NMinQuad, MaxQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmTowardZero},
{NMinQuad, MaxQuad, "-0", UnderflowStatus, APFloat::fcZero,
APFloat::rmNearestTiesToAway},
};

for (size_t i = 0; i < NumTests; ++i) {
for (size_t i = 0; i < array_lengthof(SpecialCaseTests); ++i) {
APFloat x(SpecialCaseTests[i].x);
APFloat y(SpecialCaseTests[i].y);
APFloat::opStatus status = x.divide(y, APFloat::rmNearestTiesToEven);
APFloat::opStatus status = x.divide(y, SpecialCaseTests[i].roundingMode);

APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
APFloat result(x.getSemantics(), SpecialCaseTests[i].result);

EXPECT_TRUE(result.bitwiseIsEqual(x));
EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
Expand Down

0 comments on commit 8606d01

Please sign in to comment.