-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[APFloat] add power #122889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[APFloat] add power #122889
Changes from all commits
10da74e
eb093a1
38468c9
eb07e2a
09ad4eb
8f6da4e
7ce4955
35beb61
b13601b
33beb56
101dfb5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1536,6 +1536,26 @@ inline APFloat abs(APFloat X) { | |
return X; | ||
} | ||
|
||
/// Returns X^N for N >= 0. | ||
inline APFloat powi(const APFloat &X, int64_t N) { | ||
APFloat Acc = APFloat::getOne(X.getSemantics()); | ||
if (N == 0) { | ||
return Acc; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should canonicalize the value There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For N==0? Can you explain? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All paths through the function, but yes this one too. Signaling nans should be quieted |
||
} | ||
assert(N >= 0 && "negative exponents not supported."); | ||
APFloat Base = X; | ||
int64_t RemainingExponent = N; | ||
while (RemainingExponent > 0) { | ||
while (RemainingExponent % 2 == 0) { | ||
Base = Base * Base; | ||
RemainingExponent /= 2; | ||
} | ||
--RemainingExponent; | ||
Acc = Acc * Base; | ||
ImanHosseini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return Acc; | ||
} | ||
|
||
/// Returns the negated value of the argument. | ||
inline APFloat neg(APFloat X) { | ||
X.changeSign(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3793,6 +3793,71 @@ TEST(APFloatTest, abs) { | |
EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized))); | ||
} | ||
|
||
TEST(APFloatTest, powi) { | ||
|
||
// Simple cases. | ||
APFloat One = APFloat::getOne(APFloat::IEEEsingle(), false); | ||
APFloat Two = APFloat(APFloat::IEEEsingle(), "2.0"); | ||
APFloat NegTwo = APFloat(APFloat::IEEEsingle(), "-2.0"); | ||
APFloat Four = APFloat(APFloat::IEEEsingle(), "4.0"); | ||
APFloat Eight = APFloat(APFloat::IEEEsingle(), "8.0"); | ||
APFloat NegEight = APFloat(APFloat::IEEEsingle(), "-8.0"); | ||
|
||
EXPECT_TRUE(One.bitwiseIsEqual(powi(One, 0))); | ||
EXPECT_TRUE(One.bitwiseIsEqual(powi(One, 3))); | ||
EXPECT_TRUE(Four.bitwiseIsEqual(powi(Two, 2))); | ||
EXPECT_TRUE(Eight.bitwiseIsEqual(powi(Two, 3))); | ||
|
||
// See page 63 of IEEE 754-2019. | ||
APFloat PosInf = APFloat::getInf(APFloat::IEEEsingle(), false); | ||
APFloat NegInf = APFloat::getInf(APFloat::IEEEsingle(), true); | ||
APFloat PosZero = APFloat::getZero(APFloat::IEEEsingle(), false); | ||
APFloat NegZero = APFloat::getZero(APFloat::IEEEsingle(), true); | ||
APFloat PosQNaN = APFloat::getNaN(APFloat::IEEEsingle(), false, 0x1337); | ||
APFloat NegQNaN = APFloat::getNaN(APFloat::IEEEsingle(), true, 0x1337); | ||
APInt Payload(64, 0x1337); | ||
APFloat PosSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false, &Payload); | ||
APFloat NegSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), true, &Payload); | ||
|
||
EXPECT_TRUE(One.bitwiseIsEqual(powi(PosInf, 0))); | ||
EXPECT_TRUE(NegEight.bitwiseIsEqual(powi(NegTwo, 3))); | ||
EXPECT_TRUE(PosZero.bitwiseIsEqual(powi(PosZero, 3))); | ||
EXPECT_TRUE(NegZero.bitwiseIsEqual(powi(NegZero, 5))); | ||
EXPECT_TRUE(PosZero.bitwiseIsEqual(powi(NegZero, 6))); | ||
EXPECT_TRUE(NegInf.bitwiseIsEqual(powi(NegInf, 3))); | ||
EXPECT_TRUE(PosInf.bitwiseIsEqual(powi(NegInf, 4))); | ||
EXPECT_TRUE(PosInf.bitwiseIsEqual(powi(PosInf, 3))); | ||
|
||
// Nans | ||
EXPECT_TRUE(PosQNaN.bitwiseIsEqual(powi(PosQNaN, 1))); | ||
EXPECT_TRUE(NegQNaN.bitwiseIsEqual(powi(NegQNaN, 1))); | ||
// Check signaling NaN is quieted for n == 1. | ||
EXPECT_TRUE(PosQNaN.bitwiseIsEqual(powi(PosSNaN, 1))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @arsenm there are now tests for quieting SNaNs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gcc's |
||
EXPECT_TRUE(NegQNaN.bitwiseIsEqual(powi(NegSNaN, 1))); | ||
|
||
APFloat LargestDenormalF64(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023"); | ||
APFloat NegLargestDenormalF64(APFloat::IEEEdouble(), | ||
"-0x1.ffffffffffffep-1023"); | ||
APFloat Smallest = APFloat::getSmallest(APFloat::IEEEsingle(), false); | ||
APFloat NegSmallest = APFloat::getSmallest(APFloat::IEEEsingle(), true); | ||
APFloat Largest = APFloat::getLargest(APFloat::IEEEsingle(), false); | ||
APFloat NegLargest = APFloat::getLargest(APFloat::IEEEsingle(), true); | ||
|
||
EXPECT_TRUE(LargestDenormalF64.bitwiseIsEqual(powi(LargestDenormalF64, 1))); | ||
EXPECT_TRUE( | ||
NegLargestDenormalF64.bitwiseIsEqual(powi(NegLargestDenormalF64, 1))); | ||
EXPECT_TRUE(Smallest.bitwiseIsEqual(powi(Smallest, 1))); | ||
EXPECT_TRUE(NegSmallest.bitwiseIsEqual(powi(NegSmallest, 1))); | ||
EXPECT_TRUE(Largest.bitwiseIsEqual(powi(Largest, 1))); | ||
EXPECT_TRUE(NegLargest.bitwiseIsEqual(powi(NegLargest, 1))); | ||
|
||
EXPECT_TRUE(PosZero.bitwiseIsEqual(powi(Smallest, 2))); | ||
EXPECT_TRUE(NegZero.bitwiseIsEqual(powi(NegSmallest, 3))); | ||
EXPECT_TRUE(powi(Largest, 2).isInfinity()); | ||
EXPECT_TRUE(powi(NegLargest, 2).isInfinity()); | ||
EXPECT_TRUE(powi(NegLargest, 3).isNegative()); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test the zeroes, the infinities, nan (particularly that signaling nan is quieted with payload preserved in the no-op case). Also largest denormal / smallest normal, largest normal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anything left out? I've added tests covering these. |
||
TEST(APFloatTest, neg) { | ||
APFloat One = APFloat(APFloat::IEEEsingle(), "1.0"); | ||
APFloat NegOne = APFloat(APFloat::IEEEsingle(), "-1.0"); | ||
|
Uh oh!
There was an error while loading. Please reload this page.