266 lines · cpp
1#include "flang/Evaluate/integer.h"2#include "flang/Testing/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(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/R96 // TODO test IBCLR, IBSET, IBITS, MAX, MIN, MERGE_BITS, RANGE, SIGN97 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