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