xref: /llvm-project/llvm/unittests/ADT/DynamicAPIntTest.cpp (revision 1a0e67d73023e7ad9e7e79f66afb43a6f2561d04)
1*1a0e67d7SRamkumar Ramachandra //===- MPIntTest.cpp - Tests for MPInt ------------------------------------===//
2*1a0e67d7SRamkumar Ramachandra //
3*1a0e67d7SRamkumar Ramachandra // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*1a0e67d7SRamkumar Ramachandra // See https://llvm.org/LICENSE.txt for license information.
5*1a0e67d7SRamkumar Ramachandra // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*1a0e67d7SRamkumar Ramachandra //
7*1a0e67d7SRamkumar Ramachandra //===----------------------------------------------------------------------===//
8*1a0e67d7SRamkumar Ramachandra 
9*1a0e67d7SRamkumar Ramachandra #include "llvm/ADT/DynamicAPInt.h"
10*1a0e67d7SRamkumar Ramachandra #include "llvm/ADT/SlowDynamicAPInt.h"
11*1a0e67d7SRamkumar Ramachandra #include "gtest/gtest.h"
12*1a0e67d7SRamkumar Ramachandra 
13*1a0e67d7SRamkumar Ramachandra using namespace llvm;
14*1a0e67d7SRamkumar Ramachandra 
15*1a0e67d7SRamkumar Ramachandra namespace {
16*1a0e67d7SRamkumar Ramachandra // googletest boilerplate to run the same tests with both MPInt and SlowMPInt.
17*1a0e67d7SRamkumar Ramachandra template <typename> class IntTest : public testing::Test {};
18*1a0e67d7SRamkumar Ramachandra using TypeList = testing::Types<DynamicAPInt, detail::SlowDynamicAPInt>;
19*1a0e67d7SRamkumar Ramachandra 
20*1a0e67d7SRamkumar Ramachandra // This is for pretty-printing the test name with the name of the class in use.
21*1a0e67d7SRamkumar Ramachandra class TypeNames {
22*1a0e67d7SRamkumar Ramachandra public:
23*1a0e67d7SRamkumar Ramachandra   template <typename T>
GetName(int)24*1a0e67d7SRamkumar Ramachandra   static std::string GetName(int) { // NOLINT; gtest mandates this name.
25*1a0e67d7SRamkumar Ramachandra     if (std::is_same<T, DynamicAPInt>())
26*1a0e67d7SRamkumar Ramachandra       return "MPInt";
27*1a0e67d7SRamkumar Ramachandra     if (std::is_same<T, detail::SlowDynamicAPInt>())
28*1a0e67d7SRamkumar Ramachandra       return "SlowMPInt";
29*1a0e67d7SRamkumar Ramachandra     llvm_unreachable("Unknown class!");
30*1a0e67d7SRamkumar Ramachandra   }
31*1a0e67d7SRamkumar Ramachandra };
32*1a0e67d7SRamkumar Ramachandra TYPED_TEST_SUITE(IntTest, TypeList, TypeNames);
33*1a0e67d7SRamkumar Ramachandra 
TYPED_TEST(IntTest,ops)34*1a0e67d7SRamkumar Ramachandra TYPED_TEST(IntTest, ops) {
35*1a0e67d7SRamkumar Ramachandra   TypeParam Two(2), Five(5), Seven(7), Ten(10);
36*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five + Five, Ten);
37*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * Five, 2 * Ten + Five);
38*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * Five, 3 * Ten - Five);
39*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * Two, Ten);
40*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five / Two, Two);
41*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five % Two, Two / Two);
42*1a0e67d7SRamkumar Ramachandra 
43*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(-Ten % Seven, -10 % 7);
44*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten % -Seven, 10 % -7);
45*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(-Ten % -Seven, -10 % -7);
46*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten % Seven, 10 % 7);
47*1a0e67d7SRamkumar Ramachandra 
48*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(-Ten / Seven, -10 / 7);
49*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten / -Seven, 10 / -7);
50*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(-Ten / -Seven, -10 / -7);
51*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten / Seven, 10 / 7);
52*1a0e67d7SRamkumar Ramachandra 
53*1a0e67d7SRamkumar Ramachandra   TypeParam X = Ten;
54*1a0e67d7SRamkumar Ramachandra   X += Five;
55*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 15);
56*1a0e67d7SRamkumar Ramachandra   X *= Two;
57*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 30);
58*1a0e67d7SRamkumar Ramachandra   X /= Seven;
59*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 4);
60*1a0e67d7SRamkumar Ramachandra   X -= Two * 10;
61*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, -16);
62*1a0e67d7SRamkumar Ramachandra   X *= 2 * Two;
63*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, -64);
64*1a0e67d7SRamkumar Ramachandra   X /= Two / -2;
65*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 64);
66*1a0e67d7SRamkumar Ramachandra 
67*1a0e67d7SRamkumar Ramachandra   EXPECT_LE(Ten, Ten);
68*1a0e67d7SRamkumar Ramachandra   EXPECT_GE(Ten, Ten);
69*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten, Ten);
70*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten != Ten);
71*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten < Ten);
72*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten > Ten);
73*1a0e67d7SRamkumar Ramachandra   EXPECT_LT(Five, Ten);
74*1a0e67d7SRamkumar Ramachandra   EXPECT_GT(Ten, Five);
75*1a0e67d7SRamkumar Ramachandra }
76*1a0e67d7SRamkumar Ramachandra 
TYPED_TEST(IntTest,ops64Overloads)77*1a0e67d7SRamkumar Ramachandra TYPED_TEST(IntTest, ops64Overloads) {
78*1a0e67d7SRamkumar Ramachandra   TypeParam Two(2), Five(5), Seven(7), Ten(10);
79*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five + 5, Ten);
80*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five + 5, 5 + Five);
81*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * 5, 2 * Ten + 5);
82*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * 5, 3 * Ten - 5);
83*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five * Two, Ten);
84*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(5 / Two, 2);
85*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Five / 2, 2);
86*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(2 % Two, 0);
87*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(2 - Two, 0);
88*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(2 % Two, Two % 2);
89*1a0e67d7SRamkumar Ramachandra 
90*1a0e67d7SRamkumar Ramachandra   TypeParam X = Ten;
91*1a0e67d7SRamkumar Ramachandra   X += 5;
92*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 15);
93*1a0e67d7SRamkumar Ramachandra   X *= 2;
94*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 30);
95*1a0e67d7SRamkumar Ramachandra   X /= 7;
96*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 4);
97*1a0e67d7SRamkumar Ramachandra   X -= 20;
98*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, -16);
99*1a0e67d7SRamkumar Ramachandra   X *= 4;
100*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, -64);
101*1a0e67d7SRamkumar Ramachandra   X /= -1;
102*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, 64);
103*1a0e67d7SRamkumar Ramachandra 
104*1a0e67d7SRamkumar Ramachandra   EXPECT_LE(Ten, 10);
105*1a0e67d7SRamkumar Ramachandra   EXPECT_GE(Ten, 10);
106*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Ten, 10);
107*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten != 10);
108*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten < 10);
109*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(Ten > 10);
110*1a0e67d7SRamkumar Ramachandra   EXPECT_LT(Five, 10);
111*1a0e67d7SRamkumar Ramachandra   EXPECT_GT(Ten, 5);
112*1a0e67d7SRamkumar Ramachandra 
113*1a0e67d7SRamkumar Ramachandra   EXPECT_LE(10, Ten);
114*1a0e67d7SRamkumar Ramachandra   EXPECT_GE(10, Ten);
115*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(10, Ten);
116*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(10 != Ten);
117*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(10 < Ten);
118*1a0e67d7SRamkumar Ramachandra   EXPECT_FALSE(10 > Ten);
119*1a0e67d7SRamkumar Ramachandra   EXPECT_LT(5, Ten);
120*1a0e67d7SRamkumar Ramachandra   EXPECT_GT(10, Five);
121*1a0e67d7SRamkumar Ramachandra }
122*1a0e67d7SRamkumar Ramachandra 
TYPED_TEST(IntTest,overflows)123*1a0e67d7SRamkumar Ramachandra TYPED_TEST(IntTest, overflows) {
124*1a0e67d7SRamkumar Ramachandra   TypeParam X(1ll << 60);
125*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ((X * X - X * X * X * X) / (X * X * X), 1 - (1ll << 60));
126*1a0e67d7SRamkumar Ramachandra   TypeParam Y(1ll << 62);
127*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ((Y + Y + Y + Y + Y + Y) / Y, 6);
128*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(-(2 * (-Y)), 2 * Y); // -(-2^63) overflow.
129*1a0e67d7SRamkumar Ramachandra   X *= X;
130*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(X, (Y * Y) / 16);
131*1a0e67d7SRamkumar Ramachandra   Y += Y;
132*1a0e67d7SRamkumar Ramachandra   Y += Y;
133*1a0e67d7SRamkumar Ramachandra   Y += Y;
134*1a0e67d7SRamkumar Ramachandra   Y /= 8;
135*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Y, 1ll << 62);
136*1a0e67d7SRamkumar Ramachandra 
137*1a0e67d7SRamkumar Ramachandra   TypeParam Min(std::numeric_limits<int64_t>::min());
138*1a0e67d7SRamkumar Ramachandra   TypeParam One(1);
139*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(floorDiv(Min, -One), -Min);
140*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(ceilDiv(Min, -One), -Min);
141*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(abs(Min), -Min);
142*1a0e67d7SRamkumar Ramachandra 
143*1a0e67d7SRamkumar Ramachandra   TypeParam Z = Min;
144*1a0e67d7SRamkumar Ramachandra   Z /= -1;
145*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(Z, -Min);
146*1a0e67d7SRamkumar Ramachandra   TypeParam W(Min);
147*1a0e67d7SRamkumar Ramachandra   --W;
148*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(W, TypeParam(Min) - 1);
149*1a0e67d7SRamkumar Ramachandra   TypeParam U(Min);
150*1a0e67d7SRamkumar Ramachandra   U -= 1;
151*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(U, W);
152*1a0e67d7SRamkumar Ramachandra 
153*1a0e67d7SRamkumar Ramachandra   TypeParam Max(std::numeric_limits<int64_t>::max());
154*1a0e67d7SRamkumar Ramachandra   TypeParam V = Max;
155*1a0e67d7SRamkumar Ramachandra   ++V;
156*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(V, Max + 1);
157*1a0e67d7SRamkumar Ramachandra   TypeParam T = Max;
158*1a0e67d7SRamkumar Ramachandra   T += 1;
159*1a0e67d7SRamkumar Ramachandra   EXPECT_EQ(T, V);
160*1a0e67d7SRamkumar Ramachandra }
161*1a0e67d7SRamkumar Ramachandra 
TYPED_TEST(IntTest,floorCeilModAbsLcmGcd)162*1a0e67d7SRamkumar Ramachandra TYPED_TEST(IntTest, floorCeilModAbsLcmGcd) {
163*1a0e67d7SRamkumar Ramachandra   TypeParam X(1ll << 50), One(1), Two(2), Three(3);
164*1a0e67d7SRamkumar Ramachandra 
165*1a0e67d7SRamkumar Ramachandra   // Run on small values and large values.
166*1a0e67d7SRamkumar Ramachandra   for (const TypeParam &Y : {X, X * X}) {
167*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y, Three), Y);
168*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y, Three), Y);
169*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y - 1, Three), Y - 1);
170*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y - 1, Three), Y);
171*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y - 2, Three), Y - 1);
172*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y - 2, Three), Y);
173*1a0e67d7SRamkumar Ramachandra 
174*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y, Three), 0);
175*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y + 1, Three), One);
176*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y + 2, Three), Two);
177*1a0e67d7SRamkumar Ramachandra 
178*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y, Y), 3);
179*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y, Y), 3);
180*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y - 1, Y), 2);
181*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y - 1, Y), 3);
182*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(floorDiv(3 * Y - 2, Y), 2);
183*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(ceilDiv(3 * Y - 2, Y), 3);
184*1a0e67d7SRamkumar Ramachandra 
185*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y, Y), 0);
186*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y + 1, Y), 1);
187*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(mod(3 * Y + 2, Y), 2);
188*1a0e67d7SRamkumar Ramachandra 
189*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(abs(Y), Y);
190*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(abs(-Y), Y);
191*1a0e67d7SRamkumar Ramachandra 
192*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(gcd(3 * Y, Three), Three);
193*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(lcm(Y, Three), 3 * Y);
194*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(gcd(2 * Y, 3 * Y), Y);
195*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(lcm(2 * Y, 3 * Y), 6 * Y);
196*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(gcd(15 * Y, 6 * Y), 3 * Y);
197*1a0e67d7SRamkumar Ramachandra     EXPECT_EQ(lcm(15 * Y, 6 * Y), 30 * Y);
198*1a0e67d7SRamkumar Ramachandra   }
199*1a0e67d7SRamkumar Ramachandra }
200*1a0e67d7SRamkumar Ramachandra } // namespace
201