1 #include "flang/Evaluate/integer.h"
6 using Fortran::evaluate::Ordering
;
7 using Fortran::evaluate::value::Integer
;
9 template <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))};
14 std::snprintf(desc
, sizeof desc
,
15 "BITS=%d, PARTBITS=%d, sizeof(Part)=%d, LE=%d", BITS
, INT::partBits
,
16 static_cast<int>(sizeof(typename
INT::Part
)), INT::littleEndian
);
18 MATCH(BITS
, INT::bits
)(desc
);
19 MATCH(maxPositiveSignedValue
, INT::HUGE().ToUInt64())(desc
);
21 TEST(zero
.IsZero())(desc
);
22 MATCH(0, zero
.ToUInt64())(desc
);
23 MATCH(0, zero
.ToInt64())(desc
);
25 for (std::uint64_t x
{0}; x
<= maxUnsignedValue
; ++x
) {
26 unsigned long long ullx
= x
;
28 MATCH(x
, a
.ToUInt64())(desc
);
30 MATCH(x
, copy
.ToUInt64())(desc
);
32 MATCH(x
, copy
.ToUInt64())(desc
);
33 MATCH(x
== 0, a
.IsZero())("%s, x=0x%llx", desc
, x
);
35 std::snprintf(buffer
, sizeof buffer
, " %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(buffer
, sizeof buffer
, "%llx", ullx
);
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()};
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()};
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
);
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
);
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
);
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
);
79 for (int j
{0}; j
< BITS
; ++j
) {
80 popcheck
+= (x
>> j
) & 1;
82 MATCH(popcheck
, a
.POPCNT())("%s, x=0x%llx", desc
, x
);
83 MATCH(popcheck
& 1, a
.POPPAR())("%s, x=0x%llx", desc
, x
);
85 for (; trailcheck
< BITS
; ++trailcheck
) {
86 if ((x
>> trailcheck
) & 1) {
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
);
95 // TODO test DIM, MODULO, ISHFTC, DSHIFTL/R
96 // TODO test IBCLR, IBSET, IBITS, MAX, MIN, MERGE_BITS, RANGE, SIGN
98 Ordering ord
{Ordering::Equal
};
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
;
106 TEST(!a
.IsNegative())("%s, x=0x%llx", desc
, x
);
107 TEST(sx
>= 0)("%s, x=0x%llx %lld", desc
, x
, sx
);
109 ord
= Ordering::Greater
;
111 ord
= Ordering::Equal
;
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
) {
119 MATCH((x
<< count
) & maxUnsignedValue
, t
.ToUInt64())
120 ("%s, x=0x%llx, count=%d", desc
, x
, count
);
122 MATCH((x
<< count
) & maxUnsignedValue
, t
.ToUInt64())
123 ("%s, x=0x%llx, count=%d", desc
, x
, count
);
125 MATCH(x
>> count
, t
.ToUInt64())
126 ("%s, x=0x%llx, count=%d", desc
, x
, count
);
128 MATCH(x
>> count
, t
.ToUInt64())("%s, x=0x%llx, count=%d", desc
, x
, count
);
130 std::uint64_t fill
{-(x
>> (BITS
- 1))};
132 count
>= BITS
? fill
: (x
>> count
) | (fill
<< (BITS
- count
))};
133 MATCH(sra
, t
.ToInt64())
134 ("%s, x=0x%llx, count=%d", desc
, x
, count
);
137 for (std::uint64_t y
{0}; y
<= maxUnsignedValue
; ++y
) {
139 if (y
+ y
> maxUnsignedValue
) {
140 sy
= y
| (~std::uint64_t{0} << BITS
);
144 ord
= Ordering::Less
;
146 ord
= Ordering::Greater
;
148 ord
= Ordering::Equal
;
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
);
156 ord
= Ordering::Less
;
157 } else if (sx
> sy
) {
158 ord
= Ordering::Greater
;
160 ord
= Ordering::Equal
;
162 TEST(a
.CompareSigned(b
) == ord
)
163 ("%s, x=0x%llx %lld %d, y=0x%llx %lld %d", desc
, x
, sx
, a
.IsNegative(), y
,
167 MATCH(x
& y
, t
.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
169 MATCH(x
| y
, t
.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
171 MATCH(x
^ y
, t
.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
172 auto sum
{a
.AddUnsigned(b
)};
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
);
180 sx
+ sy
< mostNegativeSignedValue
|| sx
+ sy
> maxPositiveSignedValue
,
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
);
187 sx
- sy
< mostNegativeSignedValue
|| sx
- sy
> maxPositiveSignedValue
,
189 ("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
190 auto product
{a
.MultiplyUnsigned(b
)};
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
);
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
);
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
);
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
);
220 MATCH(maxPositiveSignedValue
, quot
.quotient
.ToInt64())
221 ("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
223 MATCH(mostNegativeSignedValue
, quot
.quotient
.ToInt64())
224 ("%s, x=0x%llx, y=0x%llx", desc
, x
, y
);
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
);
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
);
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();