1 #include "flang/Evaluate/integer.h" 2 #include "testing.h" 3 #include <cstdio> 4 #include <string> 5 6 using Fortran::evaluate::Ordering; 7 using Fortran::evaluate::value::Integer; 8 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))}; 13 char desc[64]; 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); 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(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); 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 244 int 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