1#include "flang/Evaluate/integer.h"
2#include "testing.h"
3#include <cstdio>
4#include <string>
5
6using Fortran::evaluate::Ordering;
7using Fortran::evaluate::value::Integer;
8
9template <int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
10 std::uint64_t maxUnsignedValue{(std::uint64_t{1} << BITS) - 1};
11 std::int64_t maxPositiveSignedValue{(std::int64_t{1} << (BITS - 1)) - 1};
12 std::int64_t mostNegativeSignedValue{-(std::int64_t{1} << (BITS - 1))};
13 char desc[64];
14 std::snprintf(s: desc, maxlen: sizeof desc,
15 format: "BITS=%d, PARTBITS=%d, sizeof(Part)=%d, LE=%d", BITS, INT::partBits,
16 static_cast<int>(sizeof(typename INT::Part)), INT::littleEndian);
17
18 MATCH(BITS, INT::bits)(desc);
19 MATCH(maxPositiveSignedValue, INT::HUGE().ToUInt64())(desc);
20 INT zero;
21 TEST(zero.IsZero())(desc);
22 MATCH(0, zero.ToUInt64())(desc);
23 MATCH(0, zero.ToInt64())(desc);
24
25 for (std::uint64_t x{0}; x <= maxUnsignedValue; ++x) {
26 unsigned long long ullx = x;
27 INT a{x};
28 MATCH(x, a.ToUInt64())(desc);
29 INT copy{a};
30 MATCH(x, copy.ToUInt64())(desc);
31 copy = a;
32 MATCH(x, copy.ToUInt64())(desc);
33 MATCH(x == 0, a.IsZero())("%s, x=0x%llx", desc, x);
34 char buffer[64];
35 std::snprintf(s: buffer, maxlen: sizeof buffer, format: " %llu", ullx);
36 const char *p{buffer};
37 auto readcheck{INT::Read(p)};
38 TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
39 MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
40 TEST(!*p)("%s, x=0x%llx", desc, x);
41 std::snprintf(s: buffer, maxlen: sizeof buffer, format: "%llx", ullx);
42 p = buffer;
43 readcheck = INT::Read(p, 16);
44 TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
45 MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
46 TEST(!*p)("%s, x=0x%llx", desc, x);
47 std::string udec{a.UnsignedDecimal()};
48 p = udec.data();
49 readcheck = INT::Read(p);
50 TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
51 MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
52 TEST(!*p)("%s, x=0x%llx", desc, x);
53 std::string hex{a.Hexadecimal()};
54 p = hex.data();
55 readcheck = INT::Read(p, 16);
56 TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
57 MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
58 TEST(!*p)("%s, x=0x%llx", desc, x);
59 INT t{a.NOT()};
60 MATCH(x ^ maxUnsignedValue, t.ToUInt64())("%s, x=0x%llx", desc, x);
61 auto negated{a.Negate()};
62 MATCH(x == std::uint64_t{1} << (BITS - 1), negated.overflow)
63 ("%s, x=0x%llx", desc, x);
64 MATCH(-x & maxUnsignedValue, negated.value.ToUInt64())
65 ("%s, x=0x%llx", desc, x);
66 auto abs{a.ABS()};
67 MATCH(x == std::uint64_t{1} << (BITS - 1), abs.overflow)
68 ("%s, x=0x%llx", desc, x);
69 MATCH(x >> (BITS - 1) ? -x & maxUnsignedValue : x, abs.value.ToUInt64())
70 ("%s, x=0x%llx", desc, x);
71 int lzbc{a.LEADZ()};
72 COMPARE(lzbc, >=, 0)("%s, x=0x%llx", desc, x);
73 COMPARE(lzbc, <=, BITS)("%s, x=0x%llx", desc, x);
74 MATCH(x == 0, lzbc == BITS)("%s, x=0x%llx, lzbc=%d", desc, x, lzbc);
75 std::uint64_t lzcheck{std::uint64_t{1} << (BITS - lzbc)};
76 COMPARE(x, <, lzcheck)("%s, x=0x%llx, lzbc=%d", desc, x, lzbc);
77 COMPARE(x + x + !x, >=, lzcheck)("%s, x=0x%llx, lzbc=%d", desc, x, lzbc);
78 int popcheck{0};
79 for (int j{0}; j < BITS; ++j) {
80 popcheck += (x >> j) & 1;
81 }
82 MATCH(popcheck, a.POPCNT())("%s, x=0x%llx", desc, x);
83 MATCH(popcheck & 1, a.POPPAR())("%s, x=0x%llx", desc, x);
84 int trailcheck{0};
85 for (; trailcheck < BITS; ++trailcheck) {
86 if ((x >> trailcheck) & 1) {
87 break;
88 }
89 }
90 MATCH(trailcheck, a.TRAILZ())("%s, x=0x%llx", desc, x);
91 for (int j{0}; j < BITS; ++j) {
92 MATCH((x >> j) & 1, a.BTEST(j))
93 ("%s, x=0x%llx, bit %d", desc, x, j);
94 }
95 // TODO test DIM, MODULO, ISHFTC, DSHIFTL/R
96 // TODO test IBCLR, IBSET, IBITS, MAX, MIN, MERGE_BITS, RANGE, SIGN
97
98 Ordering ord{Ordering::Equal};
99 std::int64_t sx = x;
100 if (x + x > maxUnsignedValue) {
101 TEST(a.IsNegative())("%s, x=0x%llx", desc, x);
102 sx = x | (~std::uint64_t{0} << BITS);
103 TEST(sx < 0)("%s, x=0x%llx %lld", desc, x, sx);
104 ord = Ordering::Less;
105 } else {
106 TEST(!a.IsNegative())("%s, x=0x%llx", desc, x);
107 TEST(sx >= 0)("%s, x=0x%llx %lld", desc, x, sx);
108 if (sx > 0) {
109 ord = Ordering::Greater;
110 } else {
111 ord = Ordering::Equal;
112 }
113 }
114
115 TEST(sx == a.ToInt64())("%s, x=0x%llx %lld", desc, x, sx);
116 TEST(a.CompareToZeroSigned() == ord)("%s, x=0x%llx %lld", desc, x, sx);
117 for (int count{0}; count <= BITS + 1; ++count) {
118 t = a.SHIFTL(count);
119 MATCH((x << count) & maxUnsignedValue, t.ToUInt64())
120 ("%s, x=0x%llx, count=%d", desc, x, count);
121 t = a.ISHFT(count);
122 MATCH((x << count) & maxUnsignedValue, t.ToUInt64())
123 ("%s, x=0x%llx, count=%d", desc, x, count);
124 t = a.SHIFTR(count);
125 MATCH(x >> count, t.ToUInt64())
126 ("%s, x=0x%llx, count=%d", desc, x, count);
127 t = a.ISHFT(-count);
128 MATCH(x >> count, t.ToUInt64())("%s, x=0x%llx, count=%d", desc, x, count);
129 t = a.SHIFTA(count);
130 std::uint64_t fill{-(x >> (BITS - 1))};
131 std::uint64_t sra{
132 count >= BITS ? fill : (x >> count) | (fill << (BITS - count))};
133 MATCH(sra, t.ToInt64())
134 ("%s, x=0x%llx, count=%d", desc, x, count);
135 }
136
137 for (std::uint64_t y{0}; y <= maxUnsignedValue; ++y) {
138 std::int64_t sy = y;
139 if (y + y > maxUnsignedValue) {
140 sy = y | (~std::uint64_t{0} << BITS);
141 }
142 INT b{y};
143 if (x < y) {
144 ord = Ordering::Less;
145 } else if (x > y) {
146 ord = Ordering::Greater;
147 } else {
148 ord = Ordering::Equal;
149 }
150 TEST(a.CompareUnsigned(b) == ord)("%s, x=0x%llx, y=0x%llx", desc, x, y);
151 MATCH(x >= y, a.BGE(b))("%s, x=0x%llx, y=0x%llx", desc, x, y);
152 MATCH(x > y, a.BGT(b))("%s, x=0x%llx, y=0x%llx", desc, x, y);
153 MATCH(x <= y, a.BLE(b))("%s, x=0x%llx, y=0x%llx", desc, x, y);
154 MATCH(x < y, a.BLT(b))("%s, x=0x%llx, y=0x%llx", desc, x, y);
155 if (sx < sy) {
156 ord = Ordering::Less;
157 } else if (sx > sy) {
158 ord = Ordering::Greater;
159 } else {
160 ord = Ordering::Equal;
161 }
162 TEST(a.CompareSigned(b) == ord)
163 ("%s, x=0x%llx %lld %d, y=0x%llx %lld %d", desc, x, sx, a.IsNegative(), y,
164 sy, b.IsNegative());
165
166 t = a.IAND(b);
167 MATCH(x & y, t.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
168 t = a.IOR(b);
169 MATCH(x | y, t.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
170 t = a.IEOR(b);
171 MATCH(x ^ y, t.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
172 auto sum{a.AddUnsigned(b)};
173 COMPARE(
174 x + y, ==, sum.value.ToUInt64() + (std::uint64_t{sum.carry} << BITS))
175 ("%s, x=0x%llx, y=0x%llx, carry=%d", desc, x, y, sum.carry);
176 auto ssum{a.AddSigned(b)};
177 MATCH((sx + sy) & maxUnsignedValue, ssum.value.ToUInt64())
178 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
179 MATCH(
180 sx + sy < mostNegativeSignedValue || sx + sy > maxPositiveSignedValue,
181 ssum.overflow)
182 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
183 auto diff{a.SubtractSigned(b)};
184 MATCH((sx - sy) & maxUnsignedValue, diff.value.ToUInt64())
185 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
186 MATCH(
187 sx - sy < mostNegativeSignedValue || sx - sy > maxPositiveSignedValue,
188 diff.overflow)
189 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
190 auto product{a.MultiplyUnsigned(b)};
191 MATCH(
192 x * y, (product.upper.ToUInt64() << BITS) ^ product.lower.ToUInt64())
193 ("%s, x=0x%llx, y=0x%llx, lower=0x%llx, upper=0x%llx", desc, x, y,
194 product.lower.ToUInt64(), product.upper.ToUInt64());
195 product = a.MultiplySigned(b);
196 MATCH((sx * sy) & maxUnsignedValue, product.lower.ToUInt64())
197 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
198 MATCH(((sx * sy) >> BITS) & maxUnsignedValue, product.upper.ToUInt64())
199 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
200 auto quot{a.DivideUnsigned(b)};
201 MATCH(y == 0, quot.divisionByZero)("%s, x=0x%llx, y=0x%llx", desc, x, y);
202 if (y == 0) {
203 MATCH(maxUnsignedValue, quot.quotient.ToUInt64())
204 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
205 MATCH(0, quot.remainder.ToUInt64())
206 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
207 } else {
208 MATCH(x / y, quot.quotient.ToUInt64())
209 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
210 MATCH(x % y, quot.remainder.ToUInt64())
211 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
212 }
213 quot = a.DivideSigned(b);
214 bool badCase{sx == mostNegativeSignedValue &&
215 ((sy == -1 && sx != sy) || (BITS == 1 && sx == sy))};
216 MATCH(y == 0, quot.divisionByZero)("%s, x=0x%llx, y=0x%llx", desc, x, y);
217 MATCH(badCase, quot.overflow)("%s, x=0x%llx, y=0x%llx", desc, x, y);
218 if (y == 0) {
219 if (sx >= 0) {
220 MATCH(maxPositiveSignedValue, quot.quotient.ToInt64())
221 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
222 } else {
223 MATCH(mostNegativeSignedValue, quot.quotient.ToInt64())
224 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
225 }
226 MATCH(0, quot.remainder.ToUInt64())
227 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
228 } else if (badCase) {
229 MATCH(x, quot.quotient.ToUInt64())
230 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
231 MATCH(0, quot.remainder.ToUInt64())
232 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
233 } else {
234 MATCH(sx / sy, quot.quotient.ToInt64())
235 ("%s, x=0x%llx %lld, y=0x%llx %lld; unsigned 0x%llx", desc, x, sx, y,
236 sy, quot.quotient.ToUInt64());
237 MATCH(sx - sy * (sx / sy), quot.remainder.ToInt64())
238 ("%s, x=0x%llx, y=0x%llx", desc, x, y);
239 }
240 }
241 }
242}
243
244int main() {
245 TEST(Reverse(Ordering::Less) == Ordering::Greater);
246 TEST(Reverse(Ordering::Greater) == Ordering::Less);
247 TEST(Reverse(Ordering::Equal) == Ordering::Equal);
248 TEST(Integer<128>{123456789}.UnsignedDecimal() == "123456789");
249 TEST(Integer<128>{123456789}.SignedDecimal() == "123456789");
250 TEST(Integer<128>{-123456789}.SignedDecimal() == "-123456789");
251 std::uint64_t big{0x123456789abcdef};
252 TEST(Integer<128>{big}.Hexadecimal() == "123456789abcdef");
253 exhaustiveTesting<1>();
254 exhaustiveTesting<2>();
255 exhaustiveTesting<7>();
256 exhaustiveTesting<8>();
257 exhaustiveTesting<9>();
258 exhaustiveTesting<9, Integer<9, true, 1>>();
259 exhaustiveTesting<9, Integer<9, true, 1, std::uint8_t, std::uint16_t>>();
260 exhaustiveTesting<9, Integer<9, true, 2>>();
261 exhaustiveTesting<9, Integer<9, true, 2, std::uint8_t, std::uint16_t>>();
262 exhaustiveTesting<9, Integer<9, true, 8, std::uint8_t, std::uint16_t>>();
263 exhaustiveTesting<9, Integer<9, false, 8, std::uint8_t, std::uint16_t>>();
264 return testing::Complete();
265}
266

source code of flang/unittests/Evaluate/integer.cpp