| //===- llvm/unittest/ADT/APFloat.cpp - APFloat unit tests ---------------------===// |
| // |
| // 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 "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/APSInt.h" |
| #include "llvm/ADT/Hashing.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Support/FormatVariadic.h" |
| #include "gtest/gtest.h" |
| #include <cmath> |
| #include <ostream> |
| #include <string> |
| #include <tuple> |
| |
| using namespace llvm; |
| |
| static std::string convertToErrorFromString(StringRef Str) { |
| llvm::APFloat F(0.0); |
| auto StatusOrErr = |
| F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven); |
| EXPECT_TRUE(!StatusOrErr); |
| return toString(StatusOrErr.takeError()); |
| } |
| |
| static double convertToDoubleFromString(StringRef Str) { |
| llvm::APFloat F(0.0); |
| auto StatusOrErr = |
| F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven); |
| EXPECT_FALSE(!StatusOrErr); |
| consumeError(StatusOrErr.takeError()); |
| return F.convertToDouble(); |
| } |
| |
| static std::string convertToString(double d, unsigned Prec, unsigned Pad, |
| bool Tr = true) { |
| llvm::SmallVector<char, 100> Buffer; |
| llvm::APFloat F(d); |
| F.toString(Buffer, Prec, Pad, Tr); |
| return std::string(Buffer.data(), Buffer.size()); |
| } |
| |
| namespace { |
| |
| TEST(APFloatTest, isSignaling) { |
| // We test qNaN, -qNaN, +sNaN, -sNaN with and without payloads. *NOTE* The |
| // positive/negative distinction is included only since the getQNaN/getSNaN |
| // API provides the option. |
| APInt payload = APInt::getOneBitSet(4, 2); |
| APFloat QNan = APFloat::getQNaN(APFloat::IEEEsingle(), false); |
| EXPECT_FALSE(QNan.isSignaling()); |
| EXPECT_EQ(fcQNan, QNan.classify()); |
| |
| EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true).isSignaling()); |
| EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), false, &payload).isSignaling()); |
| EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true, &payload).isSignaling()); |
| |
| APFloat SNan = APFloat::getSNaN(APFloat::IEEEsingle(), false); |
| EXPECT_TRUE(SNan.isSignaling()); |
| EXPECT_EQ(fcSNan, SNan.classify()); |
| |
| EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isSignaling()); |
| EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false, &payload).isSignaling()); |
| EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true, &payload).isSignaling()); |
| } |
| |
| TEST(APFloatTest, next) { |
| |
| APFloat test(APFloat::IEEEquad(), APFloat::uninitialized); |
| APFloat expected(APFloat::IEEEquad(), APFloat::uninitialized); |
| |
| // 1. Test Special Cases Values. |
| // |
| // Test all special values for nextUp and nextDown perscribed by IEEE-754R |
| // 2008. These are: |
| // 1. +inf |
| // 2. -inf |
| // 3. getLargest() |
| // 4. -getLargest() |
| // 5. getSmallest() |
| // 6. -getSmallest() |
| // 7. qNaN |
| // 8. sNaN |
| // 9. +0 |
| // 10. -0 |
| |
| // nextUp(+inf) = +inf. |
| test = APFloat::getInf(APFloat::IEEEquad(), false); |
| expected = APFloat::getInf(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isInfinity()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+inf) = -nextUp(-inf) = -(-getLargest()) = getLargest() |
| test = APFloat::getInf(APFloat::IEEEquad(), false); |
| expected = APFloat::getLargest(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-inf) = -getLargest() |
| test = APFloat::getInf(APFloat::IEEEquad(), true); |
| expected = APFloat::getLargest(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-inf) = -nextUp(+inf) = -(+inf) = -inf. |
| test = APFloat::getInf(APFloat::IEEEquad(), true); |
| expected = APFloat::getInf(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isInfinity() && test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(getLargest()) = +inf |
| test = APFloat::getLargest(APFloat::IEEEquad(), false); |
| expected = APFloat::getInf(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isInfinity() && !test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(getLargest()) = -nextUp(-getLargest()) |
| // = -(-getLargest() + inc) |
| // = getLargest() - inc. |
| test = APFloat::getLargest(APFloat::IEEEquad(), false); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.fffffffffffffffffffffffffffep+16383"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(!test.isInfinity() && !test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-getLargest()) = -getLargest() + inc. |
| test = APFloat::getLargest(APFloat::IEEEquad(), true); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.fffffffffffffffffffffffffffep+16383"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-getLargest()) = -nextUp(getLargest()) = -(inf) = -inf. |
| test = APFloat::getLargest(APFloat::IEEEquad(), true); |
| expected = APFloat::getInf(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isInfinity() && test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(getSmallest()) = getSmallest() + inc. |
| test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x0.0000000000000000000000000002p-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(getSmallest()) = -nextUp(-getSmallest()) = -(-0) = +0. |
| test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382"); |
| expected = APFloat::getZero(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isPosZero()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-getSmallest()) = -0. |
| test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382"); |
| expected = APFloat::getZero(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isNegZero()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-getSmallest()) = -nextUp(getSmallest()) = -getSmallest() - inc. |
| test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x0.0000000000000000000000000002p-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(qNaN) = qNaN |
| test = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| expected = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(qNaN) = qNaN |
| test = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| expected = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(sNaN) = qNaN |
| test = APFloat::getSNaN(APFloat::IEEEquad(), false); |
| expected = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opInvalidOp); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(sNaN) = qNaN |
| test = APFloat::getSNaN(APFloat::IEEEquad(), false); |
| expected = APFloat::getQNaN(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(true), APFloat::opInvalidOp); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(+0) = +getSmallest() |
| test = APFloat::getZero(APFloat::IEEEquad(), false); |
| expected = APFloat::getSmallest(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+0) = -nextUp(-0) = -getSmallest() |
| test = APFloat::getZero(APFloat::IEEEquad(), false); |
| expected = APFloat::getSmallest(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-0) = +getSmallest() |
| test = APFloat::getZero(APFloat::IEEEquad(), true); |
| expected = APFloat::getSmallest(APFloat::IEEEquad(), false); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-0) = -nextUp(0) = -getSmallest() |
| test = APFloat::getZero(APFloat::IEEEquad(), true); |
| expected = APFloat::getSmallest(APFloat::IEEEquad(), true); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // 2. Binade Boundary Tests. |
| |
| // 2a. Test denormal <-> normal binade boundaries. |
| // * nextUp(+Largest Denormal) -> +Smallest Normal. |
| // * nextDown(-Largest Denormal) -> -Smallest Normal. |
| // * nextUp(-Smallest Normal) -> -Largest Denormal. |
| // * nextDown(+Smallest Normal) -> +Largest Denormal. |
| |
| // nextUp(+Largest Denormal) -> +Smallest Normal. |
| test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.0000000000000000000000000000p-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-Largest Denormal) -> -Smallest Normal. |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.0000000000000000000000000000p-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-Smallest Normal) -> -LargestDenormal. |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x1.0000000000000000000000000000p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffffffffp-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+Smallest Normal) -> +Largest Denormal. |
| test = APFloat(APFloat::IEEEquad(), |
| "+0x1.0000000000000000000000000000p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "+0x0.ffffffffffffffffffffffffffffp-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // 2b. Test normal <-> normal binade boundaries. |
| // * nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1. |
| // * nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1. |
| // * nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary. |
| // * nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary. |
| |
| // nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1. |
| test = APFloat(APFloat::IEEEquad(), "-0x1p+1"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffffffffp+0"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1. |
| test = APFloat(APFloat::IEEEquad(), "0x1p+1"); |
| expected = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary. |
| test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0"); |
| expected = APFloat(APFloat::IEEEquad(), "0x1p+1"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary. |
| test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp+0"); |
| expected = APFloat(APFloat::IEEEquad(), "-0x1p+1"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // 2c. Test using next at binade boundaries with a direction away from the |
| // binade boundary. Away from denormal <-> normal boundaries. |
| // |
| // This is to make sure that even though we are at a binade boundary, since |
| // we are rounding away, we do not trigger the binade boundary code. Thus we |
| // test: |
| // * nextUp(-Largest Denormal) -> -Largest Denormal + inc. |
| // * nextDown(+Largest Denormal) -> +Largest Denormal - inc. |
| // * nextUp(+Smallest Normal) -> +Smallest Normal + inc. |
| // * nextDown(-Smallest Normal) -> -Smallest Normal - inc. |
| |
| // nextUp(-Largest Denormal) -> -Largest Denormal + inc. |
| test = APFloat(APFloat::IEEEquad(), "-0x0.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x0.fffffffffffffffffffffffffffep-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+Largest Denormal) -> +Largest Denormal - inc. |
| test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x0.fffffffffffffffffffffffffffep-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(+Smallest Normal) -> +Smallest Normal + inc. |
| test = APFloat(APFloat::IEEEquad(), "0x1.0000000000000000000000000000p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.0000000000000000000000000001p-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-Smallest Normal) -> -Smallest Normal - inc. |
| test = APFloat(APFloat::IEEEquad(), "-0x1.0000000000000000000000000000p-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.0000000000000000000000000001p-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // 2d. Test values which cause our exponent to go to min exponent. This |
| // is to ensure that guards in the code to check for min exponent |
| // trigger properly. |
| // * nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382 |
| // * nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) -> |
| // -0x1p-16381 |
| // * nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16382 |
| // * nextDown(0x1p-16382) -> 0x1.ffffffffffffffffffffffffffffp-16382 |
| |
| // nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382 |
| test = APFloat(APFloat::IEEEquad(), "-0x1p-16381"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffffffffp-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) -> |
| // -0x1p-16381 |
| test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), "-0x1p-16381"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16381 |
| test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), "0x1p-16381"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(0x1p-16381) -> 0x1.ffffffffffffffffffffffffffffp-16382 |
| test = APFloat(APFloat::IEEEquad(), "0x1p-16381"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.ffffffffffffffffffffffffffffp-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // 3. Now we test both denormal/normal computation which will not cause us |
| // to go across binade boundaries. Specifically we test: |
| // * nextUp(+Denormal) -> +Denormal. |
| // * nextDown(+Denormal) -> +Denormal. |
| // * nextUp(-Denormal) -> -Denormal. |
| // * nextDown(-Denormal) -> -Denormal. |
| // * nextUp(+Normal) -> +Normal. |
| // * nextDown(+Normal) -> +Normal. |
| // * nextUp(-Normal) -> -Normal. |
| // * nextDown(-Normal) -> -Normal. |
| |
| // nextUp(+Denormal) -> +Denormal. |
| test = APFloat(APFloat::IEEEquad(), |
| "0x0.ffffffffffffffffffffffff000cp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x0.ffffffffffffffffffffffff000dp-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+Denormal) -> +Denormal. |
| test = APFloat(APFloat::IEEEquad(), |
| "0x0.ffffffffffffffffffffffff000cp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x0.ffffffffffffffffffffffff000bp-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-Denormal) -> -Denormal. |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffff000cp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffff000bp-16382"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-Denormal) -> -Denormal |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffff000cp-16382"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x0.ffffffffffffffffffffffff000dp-16382"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(+Normal) -> +Normal. |
| test = APFloat(APFloat::IEEEquad(), |
| "0x1.ffffffffffffffffffffffff000cp-16000"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.ffffffffffffffffffffffff000dp-16000"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(+Normal) -> +Normal. |
| test = APFloat(APFloat::IEEEquad(), |
| "0x1.ffffffffffffffffffffffff000cp-16000"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "0x1.ffffffffffffffffffffffff000bp-16000"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextUp(-Normal) -> -Normal. |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffff000cp-16000"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffff000bp-16000"); |
| EXPECT_EQ(test.next(false), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| // nextDown(-Normal) -> -Normal. |
| test = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffff000cp-16000"); |
| expected = APFloat(APFloat::IEEEquad(), |
| "-0x1.ffffffffffffffffffffffff000dp-16000"); |
| EXPECT_EQ(test.next(true), APFloat::opOK); |
| EXPECT_TRUE(!test.isDenormal()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| } |
| |
| 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 for correct zero sign when answer is exactly zero. |
| // fma(1.0, -1.0, 1.0) -> +ve 0. |
| { |
| APFloat f1(1.0); |
| APFloat f2(-1.0); |
| APFloat f3(1.0); |
| f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); |
| EXPECT_TRUE(!f1.isNegative() && f1.isZero()); |
| } |
| |
| // Test for correct zero sign when answer is exactly zero and rounding towards |
| // negative. |
| // fma(1.0, -1.0, 1.0) -> +ve 0. |
| { |
| APFloat f1(1.0); |
| APFloat f2(-1.0); |
| APFloat f3(1.0); |
| f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative); |
| EXPECT_TRUE(f1.isNegative() && f1.isZero()); |
| } |
| |
| // Test for correct (in this case -ve) sign when adding like signed zeros. |
| // Test fma(0.0, -0.0, -0.0) -> -ve 0. |
| { |
| APFloat f1(0.0); |
| APFloat f2(-0.0); |
| APFloat f3(-0.0); |
| f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); |
| EXPECT_TRUE(f1.isNegative() && f1.isZero()); |
| } |
| |
| // Test -ve sign preservation when small negative results underflow. |
| { |
| APFloat f1(APFloat::IEEEdouble(), "-0x1p-1074"); |
| APFloat f2(APFloat::IEEEdouble(), "+0x1p-1074"); |
| APFloat f3(0.0); |
| f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); |
| EXPECT_TRUE(f1.isNegative() && f1.isZero()); |
| } |
| |
| // Test x87 extended precision case from http://llvm.org/PR20728. |
| { |
| APFloat M1(APFloat::x87DoubleExtended(), 1); |
| APFloat M2(APFloat::x87DoubleExtended(), 1); |
| APFloat A(APFloat::x87DoubleExtended(), 3); |
| |
| bool losesInfo = false; |
| M1.fusedMultiplyAdd(M1, A, APFloat::rmNearestTiesToEven); |
| M1.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_FALSE(losesInfo); |
| EXPECT_EQ(4.0f, M1.convertToFloat()); |
| } |
| |
| // Regression test that failed an assertion. |
| { |
| APFloat f1(-8.85242279E-41f); |
| APFloat f2(2.0f); |
| APFloat f3(8.85242279E-41f); |
| f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(-8.85242279E-41f, f1.convertToFloat()); |
| } |
| |
| // Test using only a single instance of APFloat. |
| { |
| APFloat F(1.5); |
| |
| F.fusedMultiplyAdd(F, F, APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(3.75, F.convertToDouble()); |
| } |
| } |
| |
| TEST(APFloatTest, MinNum) { |
| APFloat f1(1.0); |
| APFloat f2(2.0); |
| APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); |
| |
| EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble()); |
| EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble()); |
| EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble()); |
| EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); |
| } |
| |
| TEST(APFloatTest, MaxNum) { |
| APFloat f1(1.0); |
| APFloat f2(2.0); |
| APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); |
| |
| EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble()); |
| EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble()); |
| EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble()); |
| EXPECT_EQ(1.0, maxnum(nan, f1).convertToDouble()); |
| } |
| |
| TEST(APFloatTest, Minimum) { |
| APFloat f1(1.0); |
| APFloat f2(2.0); |
| APFloat zp(0.0); |
| APFloat zn(-0.0); |
| APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); |
| |
| EXPECT_EQ(1.0, minimum(f1, f2).convertToDouble()); |
| EXPECT_EQ(1.0, minimum(f2, f1).convertToDouble()); |
| EXPECT_EQ(-0.0, minimum(zp, zn).convertToDouble()); |
| EXPECT_EQ(-0.0, minimum(zn, zp).convertToDouble()); |
| EXPECT_TRUE(std::isnan(minimum(f1, nan).convertToDouble())); |
| EXPECT_TRUE(std::isnan(minimum(nan, f1).convertToDouble())); |
| } |
| |
| TEST(APFloatTest, Maximum) { |
| APFloat f1(1.0); |
| APFloat f2(2.0); |
| APFloat zp(0.0); |
| APFloat zn(-0.0); |
| APFloat nan = APFloat::getNaN(APFloat::IEEEdouble()); |
| |
| EXPECT_EQ(2.0, maximum(f1, f2).convertToDouble()); |
| EXPECT_EQ(2.0, maximum(f2, f1).convertToDouble()); |
| EXPECT_EQ(0.0, maximum(zp, zn).convertToDouble()); |
| EXPECT_EQ(0.0, maximum(zn, zp).convertToDouble()); |
| EXPECT_TRUE(std::isnan(maximum(f1, nan).convertToDouble())); |
| EXPECT_TRUE(std::isnan(maximum(nan, f1).convertToDouble())); |
| } |
| |
| 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).isDenormal()); |
| |
| APFloat Val2(APFloat::IEEEsingle(), 2); |
| APFloat T(APFloat::IEEEsingle(), MinNormalStr); |
| T.divide(Val2, rdmd); |
| EXPECT_TRUE(T.isDenormal()); |
| EXPECT_EQ(fcPosSubnormal, T.classify()); |
| |
| |
| const char *NegMinNormalStr = "-1.17549435082228750797e-38"; |
| EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), NegMinNormalStr).isDenormal()); |
| APFloat NegT(APFloat::IEEEsingle(), NegMinNormalStr); |
| NegT.divide(Val2, rdmd); |
| EXPECT_TRUE(NegT.isDenormal()); |
| EXPECT_EQ(fcNegSubnormal, NegT.classify()); |
| } |
| |
| // Test double precision |
| { |
| const char *MinNormalStr = "2.22507385850720138309e-308"; |
| EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), MinNormalStr).isDenormal()); |
| EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), 0).isDenormal()); |
| |
| APFloat Val2(APFloat::IEEEdouble(), 2); |
| APFloat T(APFloat::IEEEdouble(), MinNormalStr); |
| T.divide(Val2, rdmd); |
| EXPECT_TRUE(T.isDenormal()); |
| EXPECT_EQ(fcPosSubnormal, T.classify()); |
| } |
| |
| // Test Intel double-ext |
| { |
| const char *MinNormalStr = "3.36210314311209350626e-4932"; |
| EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), MinNormalStr).isDenormal()); |
| EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), 0).isDenormal()); |
| |
| APFloat Val2(APFloat::x87DoubleExtended(), 2); |
| APFloat T(APFloat::x87DoubleExtended(), MinNormalStr); |
| T.divide(Val2, rdmd); |
| EXPECT_TRUE(T.isDenormal()); |
| EXPECT_EQ(fcPosSubnormal, T.classify()); |
| } |
| |
| // Test quadruple precision |
| { |
| const char *MinNormalStr = "3.36210314311209350626267781732175260e-4932"; |
| EXPECT_FALSE(APFloat(APFloat::IEEEquad(), MinNormalStr).isDenormal()); |
| EXPECT_FALSE(APFloat(APFloat::IEEEquad(), 0).isDenormal()); |
| |
| APFloat Val2(APFloat::IEEEquad(), 2); |
| APFloat T(APFloat::IEEEquad(), MinNormalStr); |
| T.divide(Val2, rdmd); |
| EXPECT_TRUE(T.isDenormal()); |
| EXPECT_EQ(fcPosSubnormal, T.classify()); |
| } |
| |
| // Test TF32 |
| { |
| const char *MinNormalStr = "1.17549435082228750797e-38"; |
| EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal()); |
| EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal()); |
| |
| APFloat Val2(APFloat::FloatTF32(), 2); |
| APFloat T(APFloat::FloatTF32(), MinNormalStr); |
| T.divide(Val2, rdmd); |
| EXPECT_TRUE(T.isDenormal()); |
| EXPECT_EQ(fcPosSubnormal, T.classify()); |
| |
| const char *NegMinNormalStr = "-1.17549435082228750797e-38"; |
| EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal()); |
| APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr); |
| NegT.divide(Val2, rdmd); |
| EXPECT_TRUE(NegT.isDenormal()); |
| EXPECT_EQ(fcNegSubnormal, NegT.classify()); |
| } |
| } |
| |
| TEST(APFloatTest, IsSmallestNormalized) { |
| for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) { |
| const fltSemantics &Semantics = |
| APFloat::EnumToSemantics(static_cast<APFloat::Semantics>(I)); |
| |
| EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized()); |
| EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized()); |
| |
| EXPECT_FALSE(APFloat::getInf(Semantics, false).isSmallestNormalized()); |
| EXPECT_FALSE(APFloat::getInf(Semantics, true).isSmallestNormalized()); |
| |
| EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized()); |
| EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized()); |
| |
| EXPECT_FALSE(APFloat::getLargest(Semantics).isSmallestNormalized()); |
| EXPECT_FALSE(APFloat::getLargest(Semantics, true).isSmallestNormalized()); |
| |
| EXPECT_FALSE(APFloat::getSmallest(Semantics).isSmallestNormalized()); |
| EXPECT_FALSE(APFloat::getSmallest(Semantics, true).isSmallestNormalized()); |
| |
| EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized()); |
| |
| APFloat PosSmallestNormalized = |
| APFloat::getSmallestNormalized(Semantics, false); |
| APFloat NegSmallestNormalized = |
| APFloat::getSmallestNormalized(Semantics, true); |
| EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized()); |
| EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized()); |
| EXPECT_EQ(fcPosNormal, PosSmallestNormalized.classify()); |
| EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify()); |
| |
| for (APFloat *Val : {&PosSmallestNormalized, &NegSmallestNormalized}) { |
| bool OldSign = Val->isNegative(); |
| |
| // Step down, make sure it's still not smallest normalized. |
| EXPECT_EQ(APFloat::opOK, Val->next(false)); |
| EXPECT_EQ(OldSign, Val->isNegative()); |
| EXPECT_FALSE(Val->isSmallestNormalized()); |
| EXPECT_EQ(OldSign, Val->isNegative()); |
| |
| // Step back up should restore it to being smallest normalized. |
| EXPECT_EQ(APFloat::opOK, Val->next(true)); |
| EXPECT_TRUE(Val->isSmallestNormalized()); |
| EXPECT_EQ(OldSign, Val->isNegative()); |
| |
| // Step beyond should no longer smallest normalized. |
| EXPECT_EQ(APFloat::opOK, Val->next(true)); |
| EXPECT_FALSE(Val->isSmallestNormalized()); |
| EXPECT_EQ(OldSign, Val->isNegative()); |
| } |
| } |
| } |
| |
| 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()); |
| |
| EXPECT_EQ(fcPosZero, APFloat(0.0).classify()); |
| EXPECT_EQ(fcNegZero, APFloat(-0.0).classify()); |
| } |
| |
| TEST(APFloatTest, DecimalStringsWithoutNullTerminators) { |
| // Make sure that we can parse strings without null terminators. |
| // rdar://14323230. |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0.00", 3)), 0.0); |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0.01", 3)), 0.0); |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0.09", 3)), 0.0); |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0.095", 4)), 0.09); |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0.00e+3", 7)), 0.00); |
| EXPECT_EQ(convertToDoubleFromString(StringRef("0e+3", 4)), 0.00); |
| } |
| |
| 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::IEEEdouble(), "0.0").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "00000.").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+00000.").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-00000.").convertToDouble()); |
| |
| EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), ".00000").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.00000").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.00000").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0000.00000").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0000.00000").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0000.00000").convertToDouble()); |
| } |
| |
| TEST(APFloatTest, fromZeroDecimalSingleExponentString) { |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e-1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+000.0000e+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-000.0000e+1").convertToDouble()); |
| } |
| |
| TEST(APFloatTest, fromZeroDecimalLargeExponentString) { |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1234").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1234").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1234").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1234").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1234").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1234").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1234").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1234").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1234").convertToDouble()); |
| |
| EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1234").convertToDouble()); |
| EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e-1234").convertToDouble()); |
| |
| EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), StringRef("0e1234" "\0" "2", 6)).convertToDouble()); |
| } |
| |
| TEST(APFloatTest, fromZeroHexadecimalString) { |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p+1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p+1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p-1").convertToDouble()); |
| EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p-1").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1234").convertToDouble()); |
| EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1234").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1234").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1234").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1234").convertToDouble()); |
| EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1234").convertToDouble()); |
| } |
| |
| TEST(APFloatTest, fromDecimalString) { |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1").convertToDouble()); |
| EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble()); |
| EXPECT_EQ(0.5, APFloat(APFloat::IEEEdouble(), ".5").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0").convertToDouble()); |
| EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-2").convertToDouble()); |
| EXPECT_EQ(-4.0, APFloat(APFloat::IEEEdouble(), "-4.").convertToDouble()); |
| EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-.5").convertToDouble()); |
| EXPECT_EQ(-1.5, APFloat(APFloat::IEEEdouble(), "-1.5").convertToDouble()); |
| EXPECT_EQ(1.25e12, APFloat(APFloat::IEEEdouble(), "1.25e12").convertToDouble()); |
| EXPECT_EQ(1.25e+12, APFloat(APFloat::IEEEdouble(), "1.25e+12").convertToDouble()); |
| EXPECT_EQ(1.25e-12, APFloat(APFloat::IEEEdouble(), "1.25e-12").convertToDouble()); |
| EXPECT_EQ(1024.0, APFloat(APFloat::IEEEdouble(), "1024.").convertToDouble()); |
| EXPECT_EQ(1024.05, APFloat(APFloat::IEEEdouble(), "1024.05000").convertToDouble()); |
| EXPECT_EQ(0.05, APFloat(APFloat::IEEEdouble(), ".05000").convertToDouble()); |
| EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble()); |
| EXPECT_EQ(2.0e2, APFloat(APFloat::IEEEdouble(), "2.e2").convertToDouble()); |
| EXPECT_EQ(2.0e+2, APFloat(APFloat::IEEEdouble(), "2.e+2").convertToDouble()); |
| EXPECT_EQ(2.0e-2, APFloat(APFloat::IEEEdouble(), "2.e-2").convertToDouble()); |
| EXPECT_EQ(2.05e2, APFloat(APFloat::IEEEdouble(), "002.05000e2").convertToDouble()); |
| EXPECT_EQ(2.05e+2, APFloat(APFloat::IEEEdouble(), "002.05000e+2").convertToDouble()); |
| EXPECT_EQ(2.05e-2, APFloat(APFloat::IEEEdouble(), "002.05000e-2").convertToDouble()); |
| EXPECT_EQ(2.05e12, APFloat(APFloat::IEEEdouble(), "002.05000e12").convertToDouble()); |
| EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble(), "002.05000e+12").convertToDouble()); |
| EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble(), "002.05000e-12").convertToDouble()); |
| |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1e").convertToDouble()); |
| EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1e").convertToDouble()); |
| |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.e").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1.e").convertToDouble()); |
| EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1.e").convertToDouble()); |
| |
| EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble()); |
| EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), "+.1e").convertToDouble()); |
| EXPECT_EQ(-0.1, APFloat(APFloat::IEEEdouble(), "-.1e").convertToDouble()); |
| |
| EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "1.1e").convertToDouble()); |
| EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "+1.1e").convertToDouble()); |
| EXPECT_EQ(-1.1, APFloat(APFloat::IEEEdouble(), "-1.1e").convertToDouble()); |
| |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e+").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e-").convertToDouble()); |
| |
| EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble()); |
| EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e+").convertToDouble()); |
| EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e-").convertToDouble()); |
| |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e+").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e-").convertToDouble()); |
| |
| // These are "carefully selected" to overflow the fast log-base |
| // calculations in APFloat.cpp |
| EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "99e99999").isInfinity()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-99e99999").isInfinity()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "1e-99999").isPosZero()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-1e-99999").isNegZero()); |
| |
| EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828")); |
| } |
| |
| TEST(APFloatTest, fromStringSpecials) { |
| const fltSemantics &Sem = APFloat::IEEEdouble(); |
| const unsigned Precision = 53; |
| const unsigned PayloadBits = Precision - 2; |
| uint64_t PayloadMask = (uint64_t(1) << PayloadBits) - uint64_t(1); |
| |
| uint64_t NaNPayloads[] = { |
| 0, |
| 1, |
| 123, |
| 0xDEADBEEF, |
| uint64_t(-2), |
| uint64_t(1) << PayloadBits, // overflow bit |
| uint64_t(1) << (PayloadBits - 1), // signaling bit |
| uint64_t(1) << (PayloadBits - 2) // highest possible bit |
| }; |
| |
| // Convert payload integer to decimal string representation. |
| std::string NaNPayloadDecStrings[std::size(NaNPayloads)]; |
| for (size_t I = 0; I < std::size(NaNPayloads); ++I) |
| NaNPayloadDecStrings[I] = utostr(NaNPayloads[I]); |
| |
| // Convert payload integer to hexadecimal string representation. |
| std::string NaNPayloadHexStrings[std::size(NaNPayloads)]; |
| for (size_t I = 0; I < std::size(NaNPayloads); ++I) |
| NaNPayloadHexStrings[I] = "0x" + utohexstr(NaNPayloads[I]); |
| |
| // Fix payloads to expected result. |
| for (uint64_t &Payload : NaNPayloads) |
| Payload &= PayloadMask; |
| |
| // Signaling NaN must have a non-zero payload. In case a zero payload is |
| // requested, a default arbitrary payload is set instead. Save this payload |
| // for testing. |
| const uint64_t SNaNDefaultPayload = |
| APFloat::getSNaN(Sem).bitcastToAPInt().getZExtValue() & PayloadMask; |
| |
| // Negative sign prefix (or none - for positive). |
| const char Signs[] = {0, '-'}; |
| |
| // "Signaling" prefix (or none - for "Quiet"). |
| const char NaNTypes[] = {0, 's', 'S'}; |
| |
| const StringRef NaNStrings[] = {"nan", "NaN"}; |
| for (StringRef NaNStr : NaNStrings) |
| for (char TypeChar : NaNTypes) { |
| bool Signaling = (TypeChar == 's' || TypeChar == 'S'); |
| |
| for (size_t J = 0; J < std::size(NaNPayloads); ++J) { |
| uint64_t Payload = (Signaling && !NaNPayloads[J]) ? SNaNDefaultPayload |
| : NaNPayloads[J]; |
| std::string &PayloadDec = NaNPayloadDecStrings[J]; |
| std::string &PayloadHex = NaNPayloadHexStrings[J]; |
| |
| for (char SignChar : Signs) { |
| bool Negative = (SignChar == '-'); |
| |
| std::string TestStrings[5]; |
| size_t NumTestStrings = 0; |
| |
| std::string Prefix; |
| if (SignChar) |
| Prefix += SignChar; |
| if (TypeChar) |
| Prefix += TypeChar; |
| Prefix += NaNStr; |
| |
| // Test without any paylod. |
| if (!Payload) |
| TestStrings[NumTestStrings++] = Prefix; |
| |
| // Test with the payload as a suffix. |
| TestStrings[NumTestStrings++] = Prefix + PayloadDec; |
| TestStrings[NumTestStrings++] = Prefix + PayloadHex; |
| |
| // Test with the payload inside parentheses. |
| TestStrings[NumTestStrings++] = Prefix + '(' + PayloadDec + ')'; |
| TestStrings[NumTestStrings++] = Prefix + '(' + PayloadHex + ')'; |
| |
| for (size_t K = 0; K < NumTestStrings; ++K) { |
| StringRef TestStr = TestStrings[K]; |
| |
| APFloat F(Sem); |
| bool HasError = !F.convertFromString( |
| TestStr, llvm::APFloat::rmNearestTiesToEven); |
| EXPECT_FALSE(HasError); |
| EXPECT_TRUE(F.isNaN()); |
| EXPECT_EQ(Signaling, F.isSignaling()); |
| EXPECT_EQ(Negative, F.isNegative()); |
| uint64_t PayloadResult = |
| F.bitcastToAPInt().getZExtValue() & PayloadMask; |
| EXPECT_EQ(Payload, PayloadResult); |
| } |
| } |
| } |
| } |
| |
| const StringRef InfStrings[] = {"inf", "INFINITY", "+Inf", |
| "-inf", "-INFINITY", "-Inf"}; |
| for (StringRef InfStr : InfStrings) { |
| bool Negative = InfStr.front() == '-'; |
| |
| APFloat F(Sem); |
| bool HasError = |
| !F.convertFromString(InfStr, llvm::APFloat::rmNearestTiesToEven); |
| EXPECT_FALSE(HasError); |
| EXPECT_TRUE(F.isInfinity()); |
| EXPECT_EQ(Negative, F.isNegative()); |
| uint64_t PayloadResult = F.bitcastToAPInt().getZExtValue() & PayloadMask; |
| EXPECT_EQ(UINT64_C(0), PayloadResult); |
| } |
| } |
| |
| TEST(APFloatTest, fromToStringSpecials) { |
| auto expects = [] (const char *first, const char *second) { |
| std::string roundtrip = convertToString(convertToDoubleFromString(second), 0, 3); |
| EXPECT_STREQ(first, roundtrip.c_str()); |
| }; |
| expects("+Inf", "+Inf"); |
| expects("+Inf", "INFINITY"); |
| expects("+Inf", "inf"); |
| expects("-Inf", "-Inf"); |
| expects("-Inf", "-INFINITY"); |
| expects("-Inf", "-inf"); |
| expects("NaN", "NaN"); |
| expects("NaN", "nan"); |
| expects("NaN", "-NaN"); |
| expects("NaN", "-nan"); |
| } |
| |
| TEST(APFloatTest, fromHexadecimalString) { |
| EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble()); |
| EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p0").convertToDouble()); |
| EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p0").convertToDouble()); |
| |
| EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p+0").convertToDouble()); |
| EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p+0").convertToDouble()); |
| EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p+0").convertToDouble()); |
| |
| EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p-0").convertToDouble()); |
| EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p-0").convertToDouble()); |
| EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p-0").convertToDouble()); |
| |
| |
| EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p1").convertToDouble()); |
| EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p1").convertToDouble()); |
| EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p1").convertToDouble()); |
| |
| EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p+1").convertToDouble()); |
| EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p+1").convertToDouble()); |
| EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.5, APFloat(APFloat::IEEEdouble(), "0x1p-1").convertToDouble()); |
| EXPECT_EQ(+0.5, APFloat(APFloat::IEEEdouble(), "+0x1p-1").convertToDouble()); |
| EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-0x1p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p1").convertToDouble()); |
| EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p1").convertToDouble()); |
| EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p1").convertToDouble()); |
| |
| EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p+1").convertToDouble()); |
| EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p+1").convertToDouble()); |
| EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p+1").convertToDouble()); |
| |
| EXPECT_EQ( 0.75, APFloat(APFloat::IEEEdouble(), "0x1.8p-1").convertToDouble()); |
| EXPECT_EQ(+0.75, APFloat(APFloat::IEEEdouble(), "+0x1.8p-1").convertToDouble()); |
| EXPECT_EQ(-0.75, APFloat(APFloat::IEEEdouble(), "-0x1.8p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p1").convertToDouble()); |
| EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p1").convertToDouble()); |
| EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p1").convertToDouble()); |
| |
| EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p+1").convertToDouble()); |
| EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p+1").convertToDouble()); |
| EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p+1").convertToDouble()); |
| |
| EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p-1").convertToDouble()); |
| EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p-1").convertToDouble()); |
| EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p1").convertToDouble()); |
| EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p1").convertToDouble()); |
| EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p1").convertToDouble()); |
| |
| EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p+1").convertToDouble()); |
| EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p+1").convertToDouble()); |
| EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p+1").convertToDouble()); |
| |
| EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000p-1").convertToDouble()); |
| EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000p-1").convertToDouble()); |
| EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000p-1").convertToDouble()); |
| |
| |
| EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p10").convertToDouble()); |
| EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p10").convertToDouble()); |
| EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p10").convertToDouble()); |
| |
| EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p+10").convertToDouble()); |
| EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p+10").convertToDouble()); |
| EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p+10").convertToDouble()); |
| |
| EXPECT_EQ( 0.015625, APFloat(APFloat::IEEEdouble(), "0x10p-10").convertToDouble()); |
| EXPECT_EQ(+0.015625, APFloat(APFloat::IEEEdouble(), "+0x10p-10").convertToDouble()); |
| EXPECT_EQ(-0.015625, APFloat(APFloat::IEEEdouble(), "-0x10p-10").convertToDouble()); |
| |
| EXPECT_EQ(1.0625, APFloat(APFloat::IEEEdouble(), "0x1.1p0").convertToDouble()); |
| EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble()); |
| |
| EXPECT_EQ(convertToDoubleFromString("0x1p-150"), |
| convertToDoubleFromString("+0x800000000000000001.p-221")); |
| EXPECT_EQ(2251799813685248.5, |
| convertToDoubleFromString("0x80000000000004000000.010p-28")); |
| } |
| |
| TEST(APFloatTest, toString) { |
| ASSERT_EQ("10", convertToString(10.0, 6, 3)); |
| ASSERT_EQ("1.0E+1", convertToString(10.0, 6, 0)); |
| ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2)); |
| ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2)); |
| ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1)); |
| ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2)); |
| ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2)); |
| ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1)); |
| ASSERT_EQ("0.78539816339744828", convertToString(0.78539816339744830961, 0, 3)); |
| ASSERT_EQ("4.9406564584124654E-324", convertToString(4.9406564584124654e-324, 0, 3)); |
| ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1)); |
| ASSERT_EQ("8.7318340000000001E+2", convertToString(873.1834, 0, 0)); |
| ASSERT_EQ("1.7976931348623157E+308", convertToString(1.7976931348623157E+308, 0, 0)); |
| ASSERT_EQ("10", convertToString(10.0, 6, 3, false)); |
| ASSERT_EQ("1.000000e+01", convertToString(10.0, 6, 0, false)); |
| ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2, false)); |
| ASSERT_EQ("1.0100e+04", convertToString(1.01E+4, 4, 2, false)); |
| ASSERT_EQ("1.01000e+04", convertToString(1.01E+4, 5, 1, false)); |
| ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2, false)); |
| ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2, false)); |
| ASSERT_EQ("1.01000e-02", convertToString(1.01E-2, 5, 1, false)); |
| ASSERT_EQ("0.78539816339744828", |
| convertToString(0.78539816339744830961, 0, 3, false)); |
| ASSERT_EQ("4.94065645841246540e-324", |
| convertToString(4.9406564584124654e-324, 0, 3, false)); |
| ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1, false)); |
| ASSERT_EQ("8.73183400000000010e+02", convertToString(873.1834, 0, 0, false)); |
| ASSERT_EQ("1.79769313486231570e+308", |
| convertToString(1.7976931348623157E+308, 0, 0, false)); |
| |
| { |
| SmallString<64> Str; |
| APFloat UnnormalZero(APFloat::x87DoubleExtended(), APInt(80, {0, 1})); |
| UnnormalZero.toString(Str); |
| ASSERT_EQ("NaN", Str); |
| } |
| } |
| |
| TEST(APFloatTest, toInteger) { |
| bool isExact = false; |
| APSInt result(5, /*isUnsigned=*/true); |
| |
| EXPECT_EQ(APFloat::opOK, |
| APFloat(APFloat::IEEEdouble(), "10") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_TRUE(isExact); |
| EXPECT_EQ(APSInt(APInt(5, 10), true), result); |
| |
| EXPECT_EQ(APFloat::opInvalidOp, |
| APFloat(APFloat::IEEEdouble(), "-10") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_FALSE(isExact); |
| EXPECT_EQ(APSInt::getMinValue(5, true), result); |
| |
| EXPECT_EQ(APFloat::opInvalidOp, |
| APFloat(APFloat::IEEEdouble(), "32") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_FALSE(isExact); |
| EXPECT_EQ(APSInt::getMaxValue(5, true), result); |
| |
| EXPECT_EQ(APFloat::opInexact, |
| APFloat(APFloat::IEEEdouble(), "7.9") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_FALSE(isExact); |
| EXPECT_EQ(APSInt(APInt(5, 7), true), result); |
| |
| result.setIsUnsigned(false); |
| EXPECT_EQ(APFloat::opOK, |
| APFloat(APFloat::IEEEdouble(), "-10") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_TRUE(isExact); |
| EXPECT_EQ(APSInt(APInt(5, -10, true), false), result); |
| |
| EXPECT_EQ(APFloat::opInvalidOp, |
| APFloat(APFloat::IEEEdouble(), "-17") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_FALSE(isExact); |
| EXPECT_EQ(APSInt::getMinValue(5, false), result); |
| |
| EXPECT_EQ(APFloat::opInvalidOp, |
| APFloat(APFloat::IEEEdouble(), "16") |
| .convertToInteger(result, APFloat::rmTowardZero, &isExact)); |
| EXPECT_FALSE(isExact); |
| EXPECT_EQ(APSInt::getMaxValue(5, false), result); |
| } |
| |
| static APInt nanbitsFromAPInt(const fltSemantics &Sem, bool SNaN, bool Negative, |
| uint64_t payload) { |
| APInt appayload(64, payload); |
| if (SNaN) |
| return APFloat::getSNaN(Sem, Negative, &appayload).bitcastToAPInt(); |
| else |
| return APFloat::getQNaN(Sem, Negative, &appayload).bitcastToAPInt(); |
| } |
| |
| TEST(APFloatTest, makeNaN) { |
| const struct { |
| uint64_t expected; |
| const fltSemantics &semantics; |
| bool SNaN; |
| bool Negative; |
| uint64_t payload; |
| } tests[] = { |
| // clang-format off |
| /* expected semantics SNaN Neg payload */ |
| { 0x7fc00000ULL, APFloat::IEEEsingle(), false, false, 0x00000000ULL }, |
| { 0xffc00000ULL, APFloat::IEEEsingle(), false, true, 0x00000000ULL }, |
| { 0x7fc0ae72ULL, APFloat::IEEEsingle(), false, false, 0x0000ae72ULL }, |
| { 0x7fffae72ULL, APFloat::IEEEsingle(), false, false, 0xffffae72ULL }, |
| { 0x7fdaae72ULL, APFloat::IEEEsingle(), false, false, 0x00daae72ULL }, |
| { 0x7fa00000ULL, APFloat::IEEEsingle(), true, false, 0x00000000ULL }, |
| { 0xffa00000ULL, APFloat::IEEEsingle(), true, true, 0x00000000ULL }, |
| { 0x7f80ae72ULL, APFloat::IEEEsingle(), true, false, 0x0000ae72ULL }, |
| { 0x7fbfae72ULL, APFloat::IEEEsingle(), true, false, 0xffffae72ULL }, |
| { 0x7f9aae72ULL, APFloat::IEEEsingle(), true, false, 0x001aae72ULL }, |
| { 0x7ff8000000000000ULL, APFloat::IEEEdouble(), false, false, 0x0000000000000000ULL }, |
| { 0xfff8000000000000ULL, APFloat::IEEEdouble(), false, true, 0x0000000000000000ULL }, |
| { 0x7ff800000000ae72ULL, APFloat::IEEEdouble(), false, false, 0x000000000000ae72ULL }, |
| { 0x7fffffffffffae72ULL, APFloat::IEEEdouble(), false, false, 0xffffffffffffae72ULL }, |
| { 0x7ffdaaaaaaaaae72ULL, APFloat::IEEEdouble(), false, false, 0x000daaaaaaaaae72ULL }, |
| { 0x7ff4000000000000ULL, APFloat::IEEEdouble(), true, false, 0x0000000000000000ULL }, |
| { 0xfff4000000000000ULL, APFloat::IEEEdouble(), true, true, 0x0000000000000000ULL }, |
| { 0x7ff000000000ae72ULL, APFloat::IEEEdouble(), true, false, 0x000000000000ae72ULL }, |
| { 0x7ff7ffffffffae72ULL, APFloat::IEEEdouble(), true, false, 0xffffffffffffae72ULL }, |
| { 0x7ff1aaaaaaaaae72ULL, APFloat::IEEEdouble(), true, false, 0x0001aaaaaaaaae72ULL }, |
| { 0x80ULL, APFloat::Float8E5M2FNUZ(), false, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E5M2FNUZ(), false, true, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E5M2FNUZ(), true, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E5M2FNUZ(), true, true, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3FNUZ(), false, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3FNUZ(), false, true, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3FNUZ(), true, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3FNUZ(), true, true, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, true, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, false, 0xaaULL }, |
| { 0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, true, 0xaaULL }, |
| { 0x3fe00ULL, APFloat::FloatTF32(), false, false, 0x00000000ULL }, |
| { 0x7fe00ULL, APFloat::FloatTF32(), false, true, 0x00000000ULL }, |
| { 0x3feaaULL, APFloat::FloatTF32(), false, false, 0xaaULL }, |
| { 0x3ffaaULL, APFloat::FloatTF32(), false, false, 0xdaaULL }, |
| { 0x3ffaaULL, APFloat::FloatTF32(), false, false, 0xfdaaULL }, |
| { 0x3fd00ULL, APFloat::FloatTF32(), true, false, 0x00000000ULL }, |
| { 0x7fd00ULL, APFloat::FloatTF32(), true, true, 0x00000000ULL }, |
| { 0x3fcaaULL, APFloat::FloatTF32(), true, false, 0xaaULL }, |
| { 0x3fdaaULL, APFloat::FloatTF32(), true, false, 0xfaaULL }, |
| { 0x3fdaaULL, APFloat::FloatTF32(), true, false, 0x1aaULL }, |
| // clang-format on |
| }; |
| |
| for (const auto &t : tests) { |
| ASSERT_EQ(t.expected, nanbitsFromAPInt(t.semantics, t.SNaN, t.Negative, t.payload)); |
| } |
| } |
| |
| #ifdef GTEST_HAS_DEATH_TEST |
| #ifndef NDEBUG |
| TEST(APFloatTest, SemanticsDeath) { |
| EXPECT_DEATH(APFloat(APFloat::IEEEquad(), 0).convertToDouble(), |
| "Float semantics is not representable by IEEEdouble"); |
| EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(), |
| "Float semantics is not representable by IEEEsingle"); |
| } |
| #endif |
| #endif |
| |
| TEST(APFloatTest, StringDecimalError) { |
| EXPECT_EQ("Invalid string length", convertToErrorFromString("")); |
| EXPECT_EQ("String has no digits", convertToErrorFromString("+")); |
| EXPECT_EQ("String has no digits", convertToErrorFromString("-")); |
| |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("\0", 1))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1\0", 2))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2", 3))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2e1", 5))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e\0", 3))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1\0", 4))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1" "\0" "2", 5))); |
| |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString("1.0f")); |
| |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("..")); |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("..0")); |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("1.0.0")); |
| } |
| |
| TEST(APFloatTest, StringDecimalSignificandError) { |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.")); |
| |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e1")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e1")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e1")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e1")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e1")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e1")); |
| |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e")); |
| } |
| |
| TEST(APFloatTest, StringHexadecimalError) { |
| EXPECT_EQ("Invalid string", convertToErrorFromString( "0x")); |
| EXPECT_EQ("Invalid string", convertToErrorFromString("+0x")); |
| EXPECT_EQ("Invalid string", convertToErrorFromString("-0x")); |
| |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0")); |
| |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0.")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0.")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0.")); |
| |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x.0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x.0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x.0")); |
| |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0.0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0.0")); |
| EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0.0")); |
| |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x\0", 3))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1\0", 4))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2", 5))); |
| EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2p1", 7))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p\0", 5))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1\0", 6))); |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1" "\0" "2", 7))); |
| |
| EXPECT_EQ("Invalid character in exponent", convertToErrorFromString("0x1p0f")); |
| |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..p1")); |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..0p1")); |
| EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x1.0.0p1")); |
| } |
| |
| TEST(APFloatTest, StringHexadecimalSignificandError) { |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp+")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp+")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp+")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp-")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp-")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp-")); |
| |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p+")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p+")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p+")); |
| |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p-")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p-")); |
| EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p-")); |
| } |
| |
| TEST(APFloatTest, StringHexadecimalExponentError) { |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p+")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p-")); |
| |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p+")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p-")); |
| |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p+")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p-")); |
| |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p+")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p+")); |
| |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p-")); |
| EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p-")); |
| } |
| |
| TEST(APFloatTest, exactInverse) { |
| APFloat inv(0.0f); |
| |
| // Trivial operation. |
| EXPECT_TRUE(APFloat(2.0).getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5))); |
| EXPECT_TRUE(APFloat(2.0f).getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5f))); |
| EXPECT_TRUE(APFloat(APFloat::IEEEquad(), "2.0").getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::IEEEquad(), "0.5"))); |
| EXPECT_TRUE(APFloat(APFloat::PPCDoubleDouble(), "2.0").getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::PPCDoubleDouble(), "0.5"))); |
| EXPECT_TRUE(APFloat(APFloat::x87DoubleExtended(), "2.0").getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::x87DoubleExtended(), "0.5"))); |
| |
| // FLT_MIN |
| EXPECT_TRUE(APFloat(1.17549435e-38f).getExactInverse(&inv)); |
| EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(8.5070592e+37f))); |
| |
| // Large float, inverse is a denormal. |
| EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(nullptr)); |
| // Zero |
| EXPECT_FALSE(APFloat(0.0).getExactInverse(nullptr)); |
| // Denormalized float |
| EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(nullptr)); |
| } |
| |
| TEST(APFloatTest, roundToIntegral) { |
| APFloat T(-0.5), S(3.14), R(APFloat::getLargest(APFloat::IEEEdouble())), P(0.0); |
| |
| P = T; |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(-0.0, P.convertToDouble()); |
| P = T; |
| P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_EQ(-1.0, P.convertToDouble()); |
| P = T; |
| P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_EQ(-0.0, P.convertToDouble()); |
| P = T; |
| P.roundToIntegral(APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(-0.0, P.convertToDouble()); |
| |
| P = S; |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(3.0, P.convertToDouble()); |
| P = S; |
| P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_EQ(3.0, P.convertToDouble()); |
| P = S; |
| P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_EQ(4.0, P.convertToDouble()); |
| P = S; |
| P.roundToIntegral(APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(3.0, P.convertToDouble()); |
| |
| P = R; |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); |
| P = R; |
| P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); |
| P = R; |
| P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); |
| P = R; |
| P.roundToIntegral(APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); |
| |
| P = APFloat::getZero(APFloat::IEEEdouble()); |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(0.0, P.convertToDouble()); |
| P = APFloat::getZero(APFloat::IEEEdouble(), true); |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(-0.0, P.convertToDouble()); |
| P = APFloat::getNaN(APFloat::IEEEdouble()); |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(std::isnan(P.convertToDouble())); |
| P = APFloat::getInf(APFloat::IEEEdouble()); |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() > 0.0); |
| P = APFloat::getInf(APFloat::IEEEdouble(), true); |
| P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() < 0.0); |
| |
| APFloat::opStatus St; |
| |
| P = APFloat::getNaN(APFloat::IEEEdouble()); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isNaN()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getNaN(APFloat::IEEEdouble(), true); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isNaN()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getSNaN(APFloat::IEEEdouble()); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isNaN()); |
| EXPECT_FALSE(P.isSignaling()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opInvalidOp, St); |
| |
| P = APFloat::getSNaN(APFloat::IEEEdouble(), true); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isNaN()); |
| EXPECT_FALSE(P.isSignaling()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opInvalidOp, St); |
| |
| P = APFloat::getInf(APFloat::IEEEdouble()); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isInfinity()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getInf(APFloat::IEEEdouble(), true); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isInfinity()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getZero(APFloat::IEEEdouble(), false); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getZero(APFloat::IEEEdouble(), false); |
| St = P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getZero(APFloat::IEEEdouble(), true); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat::getZero(APFloat::IEEEdouble(), true); |
| St = P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat(1E-100); |
| St = P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(1E-100); |
| St = P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_EQ(1.0, P.convertToDouble()); |
| EXPECT_FALSE(P.isNegative()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(-1E-100); |
| St = P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(-1.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(-1E-100); |
| St = P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_TRUE(P.isZero()); |
| EXPECT_TRUE(P.isNegative()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(10.0); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(10.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opOK, St); |
| |
| P = APFloat(10.5); |
| St = P.roundToIntegral(APFloat::rmTowardZero); |
| EXPECT_EQ(10.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(10.5); |
| St = P.roundToIntegral(APFloat::rmTowardPositive); |
| EXPECT_EQ(11.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(10.5); |
| St = P.roundToIntegral(APFloat::rmTowardNegative); |
| EXPECT_EQ(10.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(10.5); |
| St = P.roundToIntegral(APFloat::rmNearestTiesToAway); |
| EXPECT_EQ(11.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| |
| P = APFloat(10.5); |
| St = P.roundToIntegral(APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(10.0, P.convertToDouble()); |
| EXPECT_EQ(APFloat::opInexact, St); |
| } |
| |
| TEST(APFloatTest, isInteger) { |
| APFloat T(-0.0); |
| EXPECT_TRUE(T.isInteger()); |
| T = APFloat(3.14159); |
| EXPECT_FALSE(T.isInteger()); |
| T = APFloat::getNaN(APFloat::IEEEdouble()); |
| EXPECT_FALSE(T.isInteger()); |
| T = APFloat::getInf(APFloat::IEEEdouble()); |
| EXPECT_FALSE(T.isInteger()); |
| T = APFloat::getInf(APFloat::IEEEdouble(), true); |
| EXPECT_FALSE(T.isInteger()); |
| T = APFloat::getLargest(APFloat::IEEEdouble()); |
| EXPECT_TRUE(T.isInteger()); |
| } |
| |
| TEST(DoubleAPFloatTest, isInteger) { |
| APFloat F1(-0.0); |
| APFloat F2(-0.0); |
| llvm::detail::DoubleAPFloat T(APFloat::PPCDoubleDouble(), std::move(F1), |
| std::move(F2)); |
| EXPECT_TRUE(T.isInteger()); |
| APFloat F3(3.14159); |
| APFloat F4(-0.0); |
| llvm::detail::DoubleAPFloat T2(APFloat::PPCDoubleDouble(), std::move(F3), |
| std::move(F4)); |
| EXPECT_FALSE(T2.isInteger()); |
| APFloat F5(-0.0); |
| APFloat F6(3.14159); |
| llvm::detail::DoubleAPFloat T3(APFloat::PPCDoubleDouble(), std::move(F5), |
| std::move(F6)); |
| EXPECT_FALSE(T3.isInteger()); |
| } |
| |
| TEST(APFloatTest, getLargest) { |
| EXPECT_EQ(3.402823466e+38f, APFloat::getLargest(APFloat::IEEEsingle()).convertToFloat()); |
| EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble()).convertToDouble()); |
| EXPECT_EQ(448, APFloat::getLargest(APFloat::Float8E4M3FN()).convertToDouble()); |
| EXPECT_EQ(240, |
| APFloat::getLargest(APFloat::Float8E4M3FNUZ()).convertToDouble()); |
| EXPECT_EQ(57344, |
| APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble()); |
| EXPECT_EQ( |
| 30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble()); |
| EXPECT_EQ(3.40116213421e+38f, |
| APFloat::getLargest(APFloat::FloatTF32()).convertToFloat()); |
| } |
| |
| TEST(APFloatTest, getSmallest) { |
| APFloat test = APFloat::getSmallest(APFloat::IEEEsingle(), false); |
| APFloat expected = APFloat(APFloat::IEEEsingle(), "0x0.000002p-126"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::IEEEsingle(), true); |
| expected = APFloat(APFloat::IEEEsingle(), "-0x0.000002p-126"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::IEEEquad(), false); |
| expected = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::IEEEquad(), true); |
| expected = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::Float8E5M2FNUZ(), false); |
| expected = APFloat(APFloat::Float8E5M2FNUZ(), "0x0.4p-15"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::Float8E4M3FNUZ(), false); |
| expected = APFloat(APFloat::Float8E4M3FNUZ(), "0x0.2p-7"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::Float8E4M3B11FNUZ(), false); |
| expected = APFloat(APFloat::Float8E4M3B11FNUZ(), "0x0.2p-10"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| |
| test = APFloat::getSmallest(APFloat::FloatTF32(), true); |
| expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_TRUE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| } |
| |
| TEST(APFloatTest, getSmallestNormalized) { |
| APFloat test = APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false); |
| APFloat expected = APFloat(APFloat::IEEEsingle(), "0x1p-126"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true); |
| expected = APFloat(APFloat::IEEEsingle(), "-0x1p-126"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false); |
| expected = APFloat(APFloat::IEEEdouble(), "0x1p-1022"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true); |
| expected = APFloat(APFloat::IEEEdouble(), "-0x1p-1022"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), false); |
| expected = APFloat(APFloat::IEEEquad(), "0x1p-16382"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), true); |
| expected = APFloat(APFloat::IEEEquad(), "-0x1p-16382"); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::Float8E5M2FNUZ(), false); |
| expected = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.0p-15"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::Float8E4M3FNUZ(), false); |
| expected = APFloat(APFloat::Float8E4M3FNUZ(), "0x1.0p-7"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::Float8E4M3B11FNUZ(), false); |
| expected = APFloat(APFloat::Float8E4M3B11FNUZ(), "0x1.0p-10"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| |
| test = APFloat::getSmallestNormalized(APFloat::FloatTF32(), false); |
| expected = APFloat(APFloat::FloatTF32(), "0x1p-126"); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(test.isFiniteNonZero()); |
| EXPECT_FALSE(test.isDenormal()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| EXPECT_TRUE(test.isSmallestNormalized()); |
| } |
| |
| TEST(APFloatTest, getZero) { |
| struct { |
| const fltSemantics *semantics; |
| const bool sign; |
| const bool signedZero; |
| const unsigned long long bitPattern[2]; |
| const unsigned bitPatternLength; |
| } const GetZeroTest[] = { |
| {&APFloat::IEEEhalf(), false, true, {0, 0}, 1}, |
| {&APFloat::IEEEhalf(), true, true, {0x8000ULL, 0}, 1}, |
| {&APFloat::IEEEsingle(), false, true, {0, 0}, 1}, |
| {&APFloat::IEEEsingle(), true, true, {0x80000000ULL, 0}, 1}, |
| {&APFloat::IEEEdouble(), false, true, {0, 0}, 1}, |
| {&APFloat::IEEEdouble(), true, true, {0x8000000000000000ULL, 0}, 1}, |
| {&APFloat::IEEEquad(), false, true, {0, 0}, 2}, |
| {&APFloat::IEEEquad(), true, true, {0, 0x8000000000000000ULL}, 2}, |
| {&APFloat::PPCDoubleDouble(), false, true, {0, 0}, 2}, |
| {&APFloat::PPCDoubleDouble(), true, true, {0x8000000000000000ULL, 0}, 2}, |
| {&APFloat::x87DoubleExtended(), false, true, {0, 0}, 2}, |
| {&APFloat::x87DoubleExtended(), true, true, {0, 0x8000ULL}, 2}, |
| {&APFloat::Float8E5M2(), false, true, {0, 0}, 1}, |
| {&APFloat::Float8E5M2(), true, true, {0x80ULL, 0}, 1}, |
| {&APFloat::Float8E5M2FNUZ(), false, false, {0, 0}, 1}, |
| {&APFloat::Float8E5M2FNUZ(), true, false, {0, 0}, 1}, |
| {&APFloat::Float8E4M3FN(), false, true, {0, 0}, 1}, |
| {&APFloat::Float8E4M3FN(), true, true, {0x80ULL, 0}, 1}, |
| {&APFloat::Float8E4M3FNUZ(), false, false, {0, 0}, 1}, |
| {&APFloat::Float8E4M3FNUZ(), true, false, {0, 0}, 1}, |
| {&APFloat::Float8E4M3B11FNUZ(), false, false, {0, 0}, 1}, |
| {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1}, |
| {&APFloat::FloatTF32(), false, true, {0, 0}, 1}, |
| {&APFloat::FloatTF32(), true, true, {0x40000ULL, 0}, 1}}; |
| const unsigned NumGetZeroTests = std::size(GetZeroTest); |
| for (unsigned i = 0; i < NumGetZeroTests; ++i) { |
| APFloat test = APFloat::getZero(*GetZeroTest[i].semantics, |
| GetZeroTest[i].sign); |
| const char *pattern = GetZeroTest[i].sign? "-0x0p+0" : "0x0p+0"; |
| APFloat expected = APFloat(*GetZeroTest[i].semantics, |
| pattern); |
| EXPECT_TRUE(test.isZero()); |
| if (GetZeroTest[i].signedZero) |
| EXPECT_TRUE(GetZeroTest[i].sign ? test.isNegative() : !test.isNegative()); |
| else |
| EXPECT_TRUE(!test.isNegative()); |
| EXPECT_TRUE(test.bitwiseIsEqual(expected)); |
| for (unsigned j = 0, je = GetZeroTest[i].bitPatternLength; j < je; ++j) { |
| EXPECT_EQ(GetZeroTest[i].bitPattern[j], |
| test.bitcastToAPInt().getRawData()[j]); |
| } |
| } |
| } |
| |
| TEST(APFloatTest, copySign) { |
| EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( |
| APFloat::copySign(APFloat(42.0), APFloat(-1.0)))); |
| EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( |
| APFloat::copySign(APFloat(-42.0), APFloat(1.0)))); |
| EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( |
| APFloat::copySign(APFloat(-42.0), APFloat(-1.0)))); |
| EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( |
| APFloat::copySign(APFloat(42.0), APFloat(1.0)))); |
| // For floating-point formats with unsigned 0, copySign() to a zero is a noop |
| for (APFloat::Semantics S : |
| {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) { |
| const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S); |
| EXPECT_TRUE(APFloat::getZero(Sem).bitwiseIsEqual( |
| APFloat::copySign(APFloat::getZero(Sem), APFloat(-1.0)))); |
| EXPECT_TRUE(APFloat::getNaN(Sem, true).bitwiseIsEqual( |
| APFloat::copySign(APFloat::getNaN(Sem, true), APFloat(1.0)))); |
| } |
| } |
| |
| TEST(APFloatTest, convert) { |
| bool losesInfo; |
| APFloat test(APFloat::IEEEdouble(), "1.0"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(1.0f, test.convertToFloat()); |
| EXPECT_FALSE(losesInfo); |
| |
| test = APFloat(APFloat::x87DoubleExtended(), "0x1p-53"); |
| test.add(APFloat(APFloat::x87DoubleExtended(), "1.0"), APFloat::rmNearestTiesToEven); |
| test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(1.0, test.convertToDouble()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEquad(), "0x1p-53"); |
| test.add(APFloat(APFloat::IEEEquad(), "1.0"), APFloat::rmNearestTiesToEven); |
| test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(1.0, test.convertToDouble()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::x87DoubleExtended(), "0xf.fffffffp+28"); |
| test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(4294967295.0, test.convertToDouble()); |
| EXPECT_FALSE(losesInfo); |
| |
| test = APFloat::getSNaN(APFloat::IEEEsingle()); |
| APFloat::opStatus status = test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven, &losesInfo); |
| // Conversion quiets the SNAN, so now 2 bits of the 64-bit significand should be set. |
| APInt topTwoBits(64, 0x6000000000000000); |
| EXPECT_TRUE(test.bitwiseIsEqual(APFloat::getQNaN(APFloat::x87DoubleExtended(), false, &topTwoBits))); |
| EXPECT_FALSE(losesInfo); |
| EXPECT_EQ(status, APFloat::opInvalidOp); |
| |
| test = APFloat::getQNaN(APFloat::IEEEsingle()); |
| APFloat X87QNaN = APFloat::getQNaN(APFloat::x87DoubleExtended()); |
| test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven, |
| &losesInfo); |
| EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN)); |
| EXPECT_FALSE(losesInfo); |
| |
| test = APFloat::getSNaN(APFloat::x87DoubleExtended()); |
| test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven, |
| &losesInfo); |
| APFloat X87SNaN = APFloat::getSNaN(APFloat::x87DoubleExtended()); |
| EXPECT_TRUE(test.bitwiseIsEqual(X87SNaN)); |
| EXPECT_FALSE(losesInfo); |
| |
| test = APFloat::getQNaN(APFloat::x87DoubleExtended()); |
| test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven, |
| &losesInfo); |
| EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN)); |
| EXPECT_FALSE(losesInfo); |
| |
| // The payload is lost in truncation, but we retain NaN by setting the quiet bit. |
| APInt payload(52, 1); |
| test = APFloat::getSNaN(APFloat::IEEEdouble(), false, &payload); |
| status = test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0x7fc00000, test.bitcastToAPInt()); |
| EXPECT_TRUE(losesInfo); |
| EXPECT_EQ(status, APFloat::opInvalidOp); |
| |
| // The payload is lost in truncation. QNaN remains QNaN. |
| test = APFloat::getQNaN(APFloat::IEEEdouble(), false, &payload); |
| status = test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0x7fc00000, test.bitcastToAPInt()); |
| EXPECT_TRUE(losesInfo); |
| EXPECT_EQ(status, APFloat::opOK); |
| |
| // Test that subnormals are handled correctly in double to float conversion |
| test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000000p-1022"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000001p-1022"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEdouble(), "-0x0.0000010000001p-1022"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000000p-1022"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000001p-1022"); |
| test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| // Test subnormal conversion to bfloat |
| test = APFloat(APFloat::IEEEsingle(), "0x0.01p-126"); |
| test.convert(APFloat::BFloat(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0.0f, test.convertToFloat()); |
| EXPECT_TRUE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEsingle(), "0x0.02p-126"); |
| test.convert(APFloat::BFloat(), APFloat::rmNearestTiesToEven, &losesInfo); |
| EXPECT_EQ(0x01, test.bitcastToAPInt()); |
| EXPECT_FALSE(losesInfo); |
| |
| test = APFloat(APFloat::IEEEsingle(), "0x0.01p-126"); |
| test.convert(APFloat::BFloat(), APFloat::rmNearestTiesToAway, &losesInfo); |
| EXPECT_EQ(0x01, test.bitcastToAPInt()); |
| EXPECT_TRUE(losesInfo); |
| } |
| |
| TEST(APFloatTest, Float8UZConvert) { |
| bool losesInfo = false; |
| std::pair<APFloat, APFloat::opStatus> toNaNTests[] = { |
| {APFloat::getQNaN(APFloat::IEEEsingle(), false), APFloat::opOK}, |
| {APFloat::getQNaN(APFloat::IEEEsingle(), true), APFloat::opOK}, |
| {APFloat::getSNaN(APFloat::IEEEsingle(), false), APFloat::opInvalidOp}, |
| {APFloat::getSNaN(APFloat::IEEEsingle(), true), APFloat::opInvalidOp}, |
| {APFloat::getInf(APFloat::IEEEsingle(), false), APFloat::opInexact}, |
| {APFloat::getInf(APFloat::IEEEsingle(), true), APFloat::opInexact}}; |
| for (APFloat::Semantics S : |
| {APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ, |
| APFloat::S_Float8E4M3B11FNUZ}) { |
| const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S); |
| SCOPED_TRACE("Semantics = " + std::to_string(S)); |
| for (auto [toTest, expectedRes] : toNaNTests) { |
| llvm::SmallString<16> value; |
| toTest.toString(value); |
| SCOPED_TRACE("toTest = " + value); |
| losesInfo = false; |
| APFloat test = toTest; |
| EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo), |
| expectedRes); |
| EXPECT_TRUE(test.isNaN()); |
| EXPECT_TRUE(test.isNegative()); |
| EXPECT_FALSE(test.isSignaling()); |
| EXPECT_FALSE(test.isInfinity()); |
| EXPECT_EQ(0x80, test.bitcastToAPInt()); |
| EXPECT_TRUE(losesInfo); |
| } |
| |
| // Negative zero conversions are information losing. |
| losesInfo = false; |
| APFloat test = APFloat::getZero(APFloat::IEEEsingle(), true); |
| EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo), |
| APFloat::opInexact); |
| EXPECT_TRUE(test.isZero()); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_TRUE(losesInfo); |
| EXPECT_EQ(0x0, test.bitcastToAPInt()); |
| |
| losesInfo = true; |
| test = APFloat::getZero(APFloat::IEEEsingle(), false); |
| EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo), |
| APFloat::opOK); |
| EXPECT_TRUE(test.isZero()); |
| EXPECT_FALSE(test.isNegative()); |
| EXPECT_FALSE(losesInfo); |
| EXPECT_EQ(0x0, test.bitcastToAPInt()); |
| |
| // Except in casts between ourselves. |
| losesInfo = true; |
| test = APFloat::getZero(Sem); |
| EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo), |
| APFloat::opOK); |
| EXPECT_FALSE(losesInfo); |
| EXPECT_EQ(0x0, test.bitcastToAPInt()); |
| } |
| } |
| |
| TEST(APFloatTest, PPCDoubleDouble) { |
| APFloat test(APFloat::PPCDoubleDouble(), "1.0"); |
| EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]); |
| EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]); |
| |
| // LDBL_MAX |
| test = APFloat(APFloat::PPCDoubleDouble(), "1.79769313486231580793728971405301e+308"); |
| EXPECT_EQ(0x7fefffffffffffffull, test.bitcastToAPInt().getRawData()[0]); |
| EXPECT_EQ(0x7c8ffffffffffffeull, test.bitcastToAPInt().getRawData()[1]); |
| |
| // LDBL_MIN |
| test = APFloat(APFloat::PPCDoubleDouble(), "2.00416836000897277799610805135016e-292"); |
| EXPECT_EQ(0x0360000000000000ull, test.bitcastToAPInt().getRawData()[0]); |
| EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]); |
| |
| // PR30869 |
| { |
| auto Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") + |
| APFloat(APFloat::PPCDoubleDouble(), "1.0"); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| |
| Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") - |
| APFloat(APFloat::PPCDoubleDouble(), "1.0"); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| |
| Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") * |
| APFloat(APFloat::PPCDoubleDouble(), "1.0"); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| |
| Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") / |
| APFloat(APFloat::PPCDoubleDouble(), "1.0"); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| |
| int Exp; |
| Result = frexp(APFloat(APFloat::PPCDoubleDouble(), "1.0"), Exp, |
| APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| |
| Result = scalbn(APFloat(APFloat::PPCDoubleDouble(), "1.0"), 1, |
| APFloat::rmNearestTiesToEven); |
| EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics()); |
| } |
| } |
| |
| TEST(APFloatTest, isNegative) { |
| APFloat t(APFloat::IEEEsingle(), "0x1p+0"); |
| EXPECT_FALSE(t.isNegative()); |
| t = APFloat(APFloat::IEEEsingle(), "-0x1p+0"); |
| EXPECT_TRUE(t.isNegative()); |
| |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNegative()); |
| EXPECT_TRUE(APFloat::getInf(APFloat::IEEEsingle(), true).isNegative()); |
| |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNegative()); |
| EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), true).isNegative()); |
| |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNegative()); |
| EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), true).isNegative()); |
| |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNegative()); |
| EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isNegative()); |
| } |
| |
| TEST(APFloatTest, isNormal) { |
| APFloat t(APFloat::IEEEsingle(), "0x1p+0"); |
| EXPECT_TRUE(t.isNormal()); |
| |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNormal()); |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNormal()); |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNormal()); |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNormal()); |
| EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNormal()); |
| } |
| |
| TEST(APFloatTest, isFinite) { |
| APFloat t(APFloat::IEEEsingle(), "0x1p+0"); |
| EXPECT_TRUE(t.isFinite()); |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFinite()); |
| EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), false).isFinite()); |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFinite()); |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFinite()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFinite()); |
| } |
| |
| TEST(APFloatTest, isInfinity) { |
| APFloat t(APFloat::IEEEsingle(), "0x1p+0"); |
| EXPECT_FALSE(t.isInfinity()); |
| |
| APFloat PosInf = APFloat::getInf(APFloat::IEEEsingle(), false); |
| APFloat NegInf = APFloat::getInf(APFloat::IEEEsingle(), true); |
| |
| EXPECT_TRUE(PosInf.isInfinity()); |
| EXPECT_TRUE(PosInf.isPosInfinity()); |
| EXPECT_FALSE(PosInf.isNegInfinity()); |
| EXPECT_EQ(fcPosInf, PosInf.classify()); |
| |
| EXPECT_TRUE(NegInf.isInfinity()); |
| EXPECT_FALSE(NegInf.isPosInfinity()); |
| EXPECT_TRUE(NegInf.isNegInfinity()); |
| EXPECT_EQ(fcNegInf, NegInf.classify()); |
| |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isInfinity()); |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isInfinity()); |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isInfinity()); |
| EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isInfinity()); |
| } |
| |
| TEST(APFloatTest, isNaN) { |
| APFloat t(APFloat::IEEEsingle(), "0x1p+0"); |
| EXPECT_FALSE(t.isNaN()); |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNaN()); |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNaN()); |
| EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNaN()); |
| EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNaN()); |
| EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNaN()); |
| } |
| |
| TEST(APFloatTest, isFiniteNonZero) { |
| // Test positive/negative normal value. |
| EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p+0").isFiniteNonZero()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p+0").isFiniteNonZero()); |
| |
| // Test positive/negative denormal value. |
| EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFiniteNonZero()); |
| EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p-149").isFiniteNonZero()); |
| |
| // Test +/- Infinity. |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFiniteNonZero()); |
| EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), true).isFiniteNonZero()); |
| |
| // Test +/- Zero. |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isFiniteNonZero()); |
| EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), true).isFiniteNonZero()); |
| |
| // Test +/- qNaN. +/- dont mean anything with qNaN but paranoia can't hurt in |
| // this instance. |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFiniteNonZero()); |
| EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), true).isFiniteNonZero()); |
| |
| // Test +/- sNaN. +/- dont mean anything with sNaN but paranoia can't hurt in |
| // this instance. |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFiniteNonZero()); |
| EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isFiniteNonZero()); |
| } |
| |
| TEST(APFloatTest, add) { |
| // Test Special Cases against each other and normal values. |
| |
| APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false); |
| APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true); |
| APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false); |
| APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true); |
| APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false); |
| APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123"); |
| APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0"); |
| APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0"); |
| APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false); |
| APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true); |
| APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false); |
| APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true); |
| APFloat PSmallestNormalized = |
| APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false); |
| APFloat MSmallestNormalized = |
| APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true); |
| |
| const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact; |
| |
| struct { |
| APFloat x; |
| APFloat y; |
| const char *result; |
| int status; |
| int category; |
| } SpecialCaseTests[] = { |
| { PInf, PInf, "inf", APFloat::opOK, APFloat::fcInfinity }, |
| { PInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, |
| { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity }, |
| { |