
This PR introduces a constructor for `DynamicAPInt` that takes an `APInt` object as input to simplifies the creation of a large numbers.
211 lines
5.4 KiB
C++
211 lines
5.4 KiB
C++
//===- MPIntTest.cpp - Tests for MPInt ------------------------------------===//
|
|
//
|
|
// 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/DynamicAPInt.h"
|
|
#include "llvm/ADT/SlowDynamicAPInt.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
// googletest boilerplate to run the same tests with both MPInt and SlowMPInt.
|
|
template <typename> class IntTest : public testing::Test {};
|
|
using TypeList = testing::Types<DynamicAPInt, detail::SlowDynamicAPInt>;
|
|
|
|
// This is for pretty-printing the test name with the name of the class in use.
|
|
class TypeNames {
|
|
public:
|
|
template <typename T>
|
|
static std::string GetName(int) { // NOLINT; gtest mandates this name.
|
|
if (std::is_same<T, DynamicAPInt>())
|
|
return "MPInt";
|
|
if (std::is_same<T, detail::SlowDynamicAPInt>())
|
|
return "SlowMPInt";
|
|
llvm_unreachable("Unknown class!");
|
|
}
|
|
};
|
|
TYPED_TEST_SUITE(IntTest, TypeList, TypeNames);
|
|
|
|
TYPED_TEST(IntTest, ValueInit) {
|
|
APInt Large(65, 0, true);
|
|
Large.setBit(64);
|
|
TypeParam DynLarge(1ll << 63);
|
|
EXPECT_EQ(TypeParam(Large), DynLarge + DynLarge);
|
|
APInt Small(64, -1, true);
|
|
TypeParam DynSmall(Small.getSExtValue());
|
|
EXPECT_EQ(TypeParam(Small), DynSmall);
|
|
}
|
|
|
|
TYPED_TEST(IntTest, ops) {
|
|
TypeParam Two(2), Five(5), Seven(7), Ten(10);
|
|
EXPECT_EQ(Five + Five, Ten);
|
|
EXPECT_EQ(Five * Five, 2 * Ten + Five);
|
|
EXPECT_EQ(Five * Five, 3 * Ten - Five);
|
|
EXPECT_EQ(Five * Two, Ten);
|
|
EXPECT_EQ(Five / Two, Two);
|
|
EXPECT_EQ(Five % Two, Two / Two);
|
|
|
|
EXPECT_EQ(-Ten % Seven, -10 % 7);
|
|
EXPECT_EQ(Ten % -Seven, 10 % -7);
|
|
EXPECT_EQ(-Ten % -Seven, -10 % -7);
|
|
EXPECT_EQ(Ten % Seven, 10 % 7);
|
|
|
|
EXPECT_EQ(-Ten / Seven, -10 / 7);
|
|
EXPECT_EQ(Ten / -Seven, 10 / -7);
|
|
EXPECT_EQ(-Ten / -Seven, -10 / -7);
|
|
EXPECT_EQ(Ten / Seven, 10 / 7);
|
|
|
|
TypeParam X = Ten;
|
|
X += Five;
|
|
EXPECT_EQ(X, 15);
|
|
X *= Two;
|
|
EXPECT_EQ(X, 30);
|
|
X /= Seven;
|
|
EXPECT_EQ(X, 4);
|
|
X -= Two * 10;
|
|
EXPECT_EQ(X, -16);
|
|
X *= 2 * Two;
|
|
EXPECT_EQ(X, -64);
|
|
X /= Two / -2;
|
|
EXPECT_EQ(X, 64);
|
|
|
|
EXPECT_LE(Ten, Ten);
|
|
EXPECT_GE(Ten, Ten);
|
|
EXPECT_EQ(Ten, Ten);
|
|
EXPECT_FALSE(Ten != Ten);
|
|
EXPECT_FALSE(Ten < Ten);
|
|
EXPECT_FALSE(Ten > Ten);
|
|
EXPECT_LT(Five, Ten);
|
|
EXPECT_GT(Ten, Five);
|
|
}
|
|
|
|
TYPED_TEST(IntTest, ops64Overloads) {
|
|
TypeParam Two(2), Five(5), Seven(7), Ten(10);
|
|
EXPECT_EQ(Five + 5, Ten);
|
|
EXPECT_EQ(Five + 5, 5 + Five);
|
|
EXPECT_EQ(Five * 5, 2 * Ten + 5);
|
|
EXPECT_EQ(Five * 5, 3 * Ten - 5);
|
|
EXPECT_EQ(Five * Two, Ten);
|
|
EXPECT_EQ(5 / Two, 2);
|
|
EXPECT_EQ(Five / 2, 2);
|
|
EXPECT_EQ(2 % Two, 0);
|
|
EXPECT_EQ(2 - Two, 0);
|
|
EXPECT_EQ(2 % Two, Two % 2);
|
|
|
|
TypeParam X = Ten;
|
|
X += 5;
|
|
EXPECT_EQ(X, 15);
|
|
X *= 2;
|
|
EXPECT_EQ(X, 30);
|
|
X /= 7;
|
|
EXPECT_EQ(X, 4);
|
|
X -= 20;
|
|
EXPECT_EQ(X, -16);
|
|
X *= 4;
|
|
EXPECT_EQ(X, -64);
|
|
X /= -1;
|
|
EXPECT_EQ(X, 64);
|
|
|
|
EXPECT_LE(Ten, 10);
|
|
EXPECT_GE(Ten, 10);
|
|
EXPECT_EQ(Ten, 10);
|
|
EXPECT_FALSE(Ten != 10);
|
|
EXPECT_FALSE(Ten < 10);
|
|
EXPECT_FALSE(Ten > 10);
|
|
EXPECT_LT(Five, 10);
|
|
EXPECT_GT(Ten, 5);
|
|
|
|
EXPECT_LE(10, Ten);
|
|
EXPECT_GE(10, Ten);
|
|
EXPECT_EQ(10, Ten);
|
|
EXPECT_FALSE(10 != Ten);
|
|
EXPECT_FALSE(10 < Ten);
|
|
EXPECT_FALSE(10 > Ten);
|
|
EXPECT_LT(5, Ten);
|
|
EXPECT_GT(10, Five);
|
|
}
|
|
|
|
TYPED_TEST(IntTest, overflows) {
|
|
TypeParam X(1ll << 60);
|
|
EXPECT_EQ((X * X - X * X * X * X) / (X * X * X), 1 - (1ll << 60));
|
|
TypeParam Y(1ll << 62);
|
|
EXPECT_EQ((Y + Y + Y + Y + Y + Y) / Y, 6);
|
|
EXPECT_EQ(-(2 * (-Y)), 2 * Y); // -(-2^63) overflow.
|
|
X *= X;
|
|
EXPECT_EQ(X, (Y * Y) / 16);
|
|
Y += Y;
|
|
Y += Y;
|
|
Y += Y;
|
|
Y /= 8;
|
|
EXPECT_EQ(Y, 1ll << 62);
|
|
|
|
TypeParam Min(std::numeric_limits<int64_t>::min());
|
|
TypeParam One(1);
|
|
EXPECT_EQ(floorDiv(Min, -One), -Min);
|
|
EXPECT_EQ(ceilDiv(Min, -One), -Min);
|
|
EXPECT_EQ(abs(Min), -Min);
|
|
|
|
TypeParam Z = Min;
|
|
Z /= -1;
|
|
EXPECT_EQ(Z, -Min);
|
|
TypeParam W(Min);
|
|
--W;
|
|
EXPECT_EQ(W, TypeParam(Min) - 1);
|
|
TypeParam U(Min);
|
|
U -= 1;
|
|
EXPECT_EQ(U, W);
|
|
|
|
TypeParam Max(std::numeric_limits<int64_t>::max());
|
|
TypeParam V = Max;
|
|
++V;
|
|
EXPECT_EQ(V, Max + 1);
|
|
TypeParam T = Max;
|
|
T += 1;
|
|
EXPECT_EQ(T, V);
|
|
}
|
|
|
|
TYPED_TEST(IntTest, floorCeilModAbsLcmGcd) {
|
|
TypeParam X(1ll << 50), One(1), Two(2), Three(3);
|
|
|
|
// Run on small values and large values.
|
|
for (const TypeParam &Y : {X, X * X}) {
|
|
EXPECT_EQ(floorDiv(3 * Y, Three), Y);
|
|
EXPECT_EQ(ceilDiv(3 * Y, Three), Y);
|
|
EXPECT_EQ(floorDiv(3 * Y - 1, Three), Y - 1);
|
|
EXPECT_EQ(ceilDiv(3 * Y - 1, Three), Y);
|
|
EXPECT_EQ(floorDiv(3 * Y - 2, Three), Y - 1);
|
|
EXPECT_EQ(ceilDiv(3 * Y - 2, Three), Y);
|
|
|
|
EXPECT_EQ(mod(3 * Y, Three), 0);
|
|
EXPECT_EQ(mod(3 * Y + 1, Three), One);
|
|
EXPECT_EQ(mod(3 * Y + 2, Three), Two);
|
|
|
|
EXPECT_EQ(floorDiv(3 * Y, Y), 3);
|
|
EXPECT_EQ(ceilDiv(3 * Y, Y), 3);
|
|
EXPECT_EQ(floorDiv(3 * Y - 1, Y), 2);
|
|
EXPECT_EQ(ceilDiv(3 * Y - 1, Y), 3);
|
|
EXPECT_EQ(floorDiv(3 * Y - 2, Y), 2);
|
|
EXPECT_EQ(ceilDiv(3 * Y - 2, Y), 3);
|
|
|
|
EXPECT_EQ(mod(3 * Y, Y), 0);
|
|
EXPECT_EQ(mod(3 * Y + 1, Y), 1);
|
|
EXPECT_EQ(mod(3 * Y + 2, Y), 2);
|
|
|
|
EXPECT_EQ(abs(Y), Y);
|
|
EXPECT_EQ(abs(-Y), Y);
|
|
|
|
EXPECT_EQ(gcd(3 * Y, Three), Three);
|
|
EXPECT_EQ(lcm(Y, Three), 3 * Y);
|
|
EXPECT_EQ(gcd(2 * Y, 3 * Y), Y);
|
|
EXPECT_EQ(lcm(2 * Y, 3 * Y), 6 * Y);
|
|
EXPECT_EQ(gcd(15 * Y, 6 * Y), 3 * Y);
|
|
EXPECT_EQ(lcm(15 * Y, 6 * Y), 30 * Y);
|
|
}
|
|
}
|
|
} // namespace
|