ScaledNumberTest.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. //===- llvm/unittest/Support/ScaledNumberTest.cpp - ScaledPair tests -----==//
  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. #include "llvm/Support/ScaledNumber.h"
  9. #include "llvm/Support/DataTypes.h"
  10. #include "gtest/gtest.h"
  11. using namespace llvm;
  12. using namespace llvm::ScaledNumbers;
  13. namespace {
  14. template <class UIntT> struct ScaledPair {
  15. UIntT D;
  16. int S;
  17. ScaledPair(const std::pair<UIntT, int16_t> &F) : D(F.first), S(F.second) {}
  18. ScaledPair(UIntT D, int S) : D(D), S(S) {}
  19. bool operator==(const ScaledPair<UIntT> &X) const {
  20. return D == X.D && S == X.S;
  21. }
  22. };
  23. template <class UIntT>
  24. bool operator==(const std::pair<UIntT, int16_t> &L,
  25. const ScaledPair<UIntT> &R) {
  26. return ScaledPair<UIntT>(L) == R;
  27. }
  28. template <class UIntT>
  29. void PrintTo(const ScaledPair<UIntT> &F, ::std::ostream *os) {
  30. *os << F.D << "*2^" << F.S;
  31. }
  32. typedef ScaledPair<uint32_t> SP32;
  33. typedef ScaledPair<uint64_t> SP64;
  34. TEST(ScaledNumberHelpersTest, getRounded) {
  35. EXPECT_EQ(getRounded32(0, 0, false), SP32(0, 0));
  36. EXPECT_EQ(getRounded32(0, 0, true), SP32(1, 0));
  37. EXPECT_EQ(getRounded32(20, 21, true), SP32(21, 21));
  38. EXPECT_EQ(getRounded32(UINT32_MAX, 0, false), SP32(UINT32_MAX, 0));
  39. EXPECT_EQ(getRounded32(UINT32_MAX, 0, true), SP32(1 << 31, 1));
  40. EXPECT_EQ(getRounded64(0, 0, false), SP64(0, 0));
  41. EXPECT_EQ(getRounded64(0, 0, true), SP64(1, 0));
  42. EXPECT_EQ(getRounded64(20, 21, true), SP64(21, 21));
  43. EXPECT_EQ(getRounded64(UINT32_MAX, 0, false), SP64(UINT32_MAX, 0));
  44. EXPECT_EQ(getRounded64(UINT32_MAX, 0, true), SP64(UINT64_C(1) << 32, 0));
  45. EXPECT_EQ(getRounded64(UINT64_MAX, 0, false), SP64(UINT64_MAX, 0));
  46. EXPECT_EQ(getRounded64(UINT64_MAX, 0, true), SP64(UINT64_C(1) << 63, 1));
  47. }
  48. TEST(ScaledNumberHelpersTest, getAdjusted) {
  49. const uint64_t Max32In64 = UINT32_MAX;
  50. EXPECT_EQ(getAdjusted32(0), SP32(0, 0));
  51. EXPECT_EQ(getAdjusted32(0, 5), SP32(0, 5));
  52. EXPECT_EQ(getAdjusted32(UINT32_MAX), SP32(UINT32_MAX, 0));
  53. EXPECT_EQ(getAdjusted32(Max32In64 << 1), SP32(UINT32_MAX, 1));
  54. EXPECT_EQ(getAdjusted32(Max32In64 << 1, 1), SP32(UINT32_MAX, 2));
  55. EXPECT_EQ(getAdjusted32(Max32In64 << 31), SP32(UINT32_MAX, 31));
  56. EXPECT_EQ(getAdjusted32(Max32In64 << 32), SP32(UINT32_MAX, 32));
  57. EXPECT_EQ(getAdjusted32(Max32In64 + 1), SP32(1u << 31, 1));
  58. EXPECT_EQ(getAdjusted32(UINT64_MAX), SP32(1u << 31, 33));
  59. EXPECT_EQ(getAdjusted64(0), SP64(0, 0));
  60. EXPECT_EQ(getAdjusted64(0, 5), SP64(0, 5));
  61. EXPECT_EQ(getAdjusted64(UINT32_MAX), SP64(UINT32_MAX, 0));
  62. EXPECT_EQ(getAdjusted64(Max32In64 << 1), SP64(Max32In64 << 1, 0));
  63. EXPECT_EQ(getAdjusted64(Max32In64 << 1, 1), SP64(Max32In64 << 1, 1));
  64. EXPECT_EQ(getAdjusted64(Max32In64 << 31), SP64(Max32In64 << 31, 0));
  65. EXPECT_EQ(getAdjusted64(Max32In64 << 32), SP64(Max32In64 << 32, 0));
  66. EXPECT_EQ(getAdjusted64(Max32In64 + 1), SP64(Max32In64 + 1, 0));
  67. EXPECT_EQ(getAdjusted64(UINT64_MAX), SP64(UINT64_MAX, 0));
  68. }
  69. TEST(ScaledNumberHelpersTest, getProduct) {
  70. // Zero.
  71. EXPECT_EQ(SP32(0, 0), getProduct32(0, 0));
  72. EXPECT_EQ(SP32(0, 0), getProduct32(0, 1));
  73. EXPECT_EQ(SP32(0, 0), getProduct32(0, 33));
  74. // Basic.
  75. EXPECT_EQ(SP32(6, 0), getProduct32(2, 3));
  76. EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0),
  77. getProduct32(UINT16_MAX / 3, UINT16_MAX / 5 * 2));
  78. // Overflow, no loss of precision.
  79. // ==> 0xf00010 * 0x1001
  80. // ==> 0xf00f00000 + 0x10010
  81. // ==> 0xf00f10010
  82. // ==> 0xf00f1001 * 2^4
  83. EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0xf00010, 0x1001));
  84. // Overflow, loss of precision, rounds down.
  85. // ==> 0xf000070 * 0x1001
  86. // ==> 0xf00f000000 + 0x70070
  87. // ==> 0xf00f070070
  88. // ==> 0xf00f0700 * 2^8
  89. EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0xf000070, 0x1001));
  90. // Overflow, loss of precision, rounds up.
  91. // ==> 0xf000080 * 0x1001
  92. // ==> 0xf00f000000 + 0x80080
  93. // ==> 0xf00f080080
  94. // ==> 0xf00f0801 * 2^8
  95. EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0xf000080, 0x1001));
  96. // Reverse operand order.
  97. EXPECT_EQ(SP32(0, 0), getProduct32(1, 0));
  98. EXPECT_EQ(SP32(0, 0), getProduct32(33, 0));
  99. EXPECT_EQ(SP32(6, 0), getProduct32(3, 2));
  100. EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0),
  101. getProduct32(UINT16_MAX / 5 * 2, UINT16_MAX / 3));
  102. EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0x1001, 0xf00010));
  103. EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0x1001, 0xf000070));
  104. EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0x1001, 0xf000080));
  105. // Round to overflow.
  106. EXPECT_EQ(SP64(UINT64_C(1) << 63, 64),
  107. getProduct64(UINT64_C(10376293541461622786),
  108. UINT64_C(16397105843297379211)));
  109. // Big number with rounding.
  110. EXPECT_EQ(SP64(UINT64_C(9223372036854775810), 64),
  111. getProduct64(UINT64_C(18446744073709551556),
  112. UINT64_C(9223372036854775840)));
  113. }
  114. TEST(ScaledNumberHelpersTest, getQuotient) {
  115. // Zero.
  116. EXPECT_EQ(SP32(0, 0), getQuotient32(0, 0));
  117. EXPECT_EQ(SP32(0, 0), getQuotient32(0, 1));
  118. EXPECT_EQ(SP32(0, 0), getQuotient32(0, 73));
  119. EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(1, 0));
  120. EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(6, 0));
  121. // Powers of two.
  122. EXPECT_EQ(SP32(1u << 31, -31), getQuotient32(1, 1));
  123. EXPECT_EQ(SP32(1u << 31, -30), getQuotient32(2, 1));
  124. EXPECT_EQ(SP32(1u << 31, -33), getQuotient32(4, 16));
  125. EXPECT_EQ(SP32(7u << 29, -29), getQuotient32(7, 1));
  126. EXPECT_EQ(SP32(7u << 29, -30), getQuotient32(7, 2));
  127. EXPECT_EQ(SP32(7u << 29, -33), getQuotient32(7, 16));
  128. // Divide evenly.
  129. EXPECT_EQ(SP32(3u << 30, -30), getQuotient32(9, 3));
  130. EXPECT_EQ(SP32(9u << 28, -28), getQuotient32(63, 7));
  131. // Divide unevenly.
  132. EXPECT_EQ(SP32(0xaaaaaaab, -33), getQuotient32(1, 3));
  133. EXPECT_EQ(SP32(0xd5555555, -31), getQuotient32(5, 3));
  134. // 64-bit division is hard to test, since divide64 doesn't canonicalize its
  135. // output. However, this is the algorithm the implementation uses:
  136. //
  137. // - Shift divisor right.
  138. // - If we have 1 (power of 2), return early -- not canonicalized.
  139. // - Shift dividend left.
  140. // - 64-bit integer divide.
  141. // - If there's a remainder, continue with long division.
  142. //
  143. // TODO: require less knowledge about the implementation in the test.
  144. // Zero.
  145. EXPECT_EQ(SP64(0, 0), getQuotient64(0, 0));
  146. EXPECT_EQ(SP64(0, 0), getQuotient64(0, 1));
  147. EXPECT_EQ(SP64(0, 0), getQuotient64(0, 73));
  148. EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(1, 0));
  149. EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(6, 0));
  150. // Powers of two.
  151. EXPECT_EQ(SP64(1, 0), getQuotient64(1, 1));
  152. EXPECT_EQ(SP64(2, 0), getQuotient64(2, 1));
  153. EXPECT_EQ(SP64(4, -4), getQuotient64(4, 16));
  154. EXPECT_EQ(SP64(7, 0), getQuotient64(7, 1));
  155. EXPECT_EQ(SP64(7, -1), getQuotient64(7, 2));
  156. EXPECT_EQ(SP64(7, -4), getQuotient64(7, 16));
  157. // Divide evenly.
  158. EXPECT_EQ(SP64(UINT64_C(3) << 60, -60), getQuotient64(9, 3));
  159. EXPECT_EQ(SP64(UINT64_C(9) << 58, -58), getQuotient64(63, 7));
  160. // Divide unevenly.
  161. EXPECT_EQ(SP64(0xaaaaaaaaaaaaaaab, -65), getQuotient64(1, 3));
  162. EXPECT_EQ(SP64(0xd555555555555555, -63), getQuotient64(5, 3));
  163. }
  164. TEST(ScaledNumberHelpersTest, getLg) {
  165. EXPECT_EQ(0, getLg(UINT32_C(1), 0));
  166. EXPECT_EQ(1, getLg(UINT32_C(1), 1));
  167. EXPECT_EQ(1, getLg(UINT32_C(2), 0));
  168. EXPECT_EQ(3, getLg(UINT32_C(1), 3));
  169. EXPECT_EQ(3, getLg(UINT32_C(7), 0));
  170. EXPECT_EQ(3, getLg(UINT32_C(8), 0));
  171. EXPECT_EQ(3, getLg(UINT32_C(9), 0));
  172. EXPECT_EQ(3, getLg(UINT32_C(64), -3));
  173. EXPECT_EQ(31, getLg((UINT32_MAX >> 1) + 2, 0));
  174. EXPECT_EQ(32, getLg(UINT32_MAX, 0));
  175. EXPECT_EQ(-1, getLg(UINT32_C(1), -1));
  176. EXPECT_EQ(-1, getLg(UINT32_C(2), -2));
  177. EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), -1));
  178. EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 0));
  179. EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 1));
  180. EXPECT_EQ(0, getLg(UINT64_C(1), 0));
  181. EXPECT_EQ(1, getLg(UINT64_C(1), 1));
  182. EXPECT_EQ(1, getLg(UINT64_C(2), 0));
  183. EXPECT_EQ(3, getLg(UINT64_C(1), 3));
  184. EXPECT_EQ(3, getLg(UINT64_C(7), 0));
  185. EXPECT_EQ(3, getLg(UINT64_C(8), 0));
  186. EXPECT_EQ(3, getLg(UINT64_C(9), 0));
  187. EXPECT_EQ(3, getLg(UINT64_C(64), -3));
  188. EXPECT_EQ(63, getLg((UINT64_MAX >> 1) + 2, 0));
  189. EXPECT_EQ(64, getLg(UINT64_MAX, 0));
  190. EXPECT_EQ(-1, getLg(UINT64_C(1), -1));
  191. EXPECT_EQ(-1, getLg(UINT64_C(2), -2));
  192. EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), -1));
  193. EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 0));
  194. EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 1));
  195. }
  196. TEST(ScaledNumberHelpersTest, getLgFloor) {
  197. EXPECT_EQ(0, getLgFloor(UINT32_C(1), 0));
  198. EXPECT_EQ(1, getLgFloor(UINT32_C(1), 1));
  199. EXPECT_EQ(1, getLgFloor(UINT32_C(2), 0));
  200. EXPECT_EQ(2, getLgFloor(UINT32_C(7), 0));
  201. EXPECT_EQ(3, getLgFloor(UINT32_C(1), 3));
  202. EXPECT_EQ(3, getLgFloor(UINT32_C(8), 0));
  203. EXPECT_EQ(3, getLgFloor(UINT32_C(9), 0));
  204. EXPECT_EQ(3, getLgFloor(UINT32_C(64), -3));
  205. EXPECT_EQ(31, getLgFloor((UINT32_MAX >> 1) + 2, 0));
  206. EXPECT_EQ(31, getLgFloor(UINT32_MAX, 0));
  207. EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), -1));
  208. EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 0));
  209. EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 1));
  210. EXPECT_EQ(0, getLgFloor(UINT64_C(1), 0));
  211. EXPECT_EQ(1, getLgFloor(UINT64_C(1), 1));
  212. EXPECT_EQ(1, getLgFloor(UINT64_C(2), 0));
  213. EXPECT_EQ(2, getLgFloor(UINT64_C(7), 0));
  214. EXPECT_EQ(3, getLgFloor(UINT64_C(1), 3));
  215. EXPECT_EQ(3, getLgFloor(UINT64_C(8), 0));
  216. EXPECT_EQ(3, getLgFloor(UINT64_C(9), 0));
  217. EXPECT_EQ(3, getLgFloor(UINT64_C(64), -3));
  218. EXPECT_EQ(63, getLgFloor((UINT64_MAX >> 1) + 2, 0));
  219. EXPECT_EQ(63, getLgFloor(UINT64_MAX, 0));
  220. EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), -1));
  221. EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 0));
  222. EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 1));
  223. }
  224. TEST(ScaledNumberHelpersTest, getLgCeiling) {
  225. EXPECT_EQ(0, getLgCeiling(UINT32_C(1), 0));
  226. EXPECT_EQ(1, getLgCeiling(UINT32_C(1), 1));
  227. EXPECT_EQ(1, getLgCeiling(UINT32_C(2), 0));
  228. EXPECT_EQ(3, getLgCeiling(UINT32_C(1), 3));
  229. EXPECT_EQ(3, getLgCeiling(UINT32_C(7), 0));
  230. EXPECT_EQ(3, getLgCeiling(UINT32_C(8), 0));
  231. EXPECT_EQ(3, getLgCeiling(UINT32_C(64), -3));
  232. EXPECT_EQ(4, getLgCeiling(UINT32_C(9), 0));
  233. EXPECT_EQ(32, getLgCeiling(UINT32_MAX, 0));
  234. EXPECT_EQ(32, getLgCeiling((UINT32_MAX >> 1) + 2, 0));
  235. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), -1));
  236. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 0));
  237. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 1));
  238. EXPECT_EQ(0, getLgCeiling(UINT64_C(1), 0));
  239. EXPECT_EQ(1, getLgCeiling(UINT64_C(1), 1));
  240. EXPECT_EQ(1, getLgCeiling(UINT64_C(2), 0));
  241. EXPECT_EQ(3, getLgCeiling(UINT64_C(1), 3));
  242. EXPECT_EQ(3, getLgCeiling(UINT64_C(7), 0));
  243. EXPECT_EQ(3, getLgCeiling(UINT64_C(8), 0));
  244. EXPECT_EQ(3, getLgCeiling(UINT64_C(64), -3));
  245. EXPECT_EQ(4, getLgCeiling(UINT64_C(9), 0));
  246. EXPECT_EQ(64, getLgCeiling((UINT64_MAX >> 1) + 2, 0));
  247. EXPECT_EQ(64, getLgCeiling(UINT64_MAX, 0));
  248. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), -1));
  249. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 0));
  250. EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 1));
  251. }
  252. TEST(ScaledNumberHelpersTest, compare) {
  253. EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 1));
  254. EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), -10));
  255. EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 20));
  256. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(64), -3));
  257. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(32), -2));
  258. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(16), -1));
  259. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(8), 0));
  260. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(4), 1));
  261. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(2), 2));
  262. EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(1), 3));
  263. EXPECT_EQ(-1, compare(UINT32_C(0), 0, UINT32_C(1), 3));
  264. EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(1), 3));
  265. EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(64), -3));
  266. EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(1), 3));
  267. EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(64), -3));
  268. EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(0), 0));
  269. EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 1));
  270. EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), -10));
  271. EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 20));
  272. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(64), -3));
  273. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(32), -2));
  274. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(16), -1));
  275. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(8), 0));
  276. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(4), 1));
  277. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(2), 2));
  278. EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(1), 3));
  279. EXPECT_EQ(-1, compare(UINT64_C(0), 0, UINT64_C(1), 3));
  280. EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(1), 3));
  281. EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(64), -3));
  282. EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(1), 3));
  283. EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(64), -3));
  284. EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(0), 0));
  285. EXPECT_EQ(-1, compare(UINT64_MAX, 0, UINT64_C(1), 64));
  286. }
  287. TEST(ScaledNumberHelpersTest, matchScales) {
  288. #define MATCH_SCALES(T, LDIn, LSIn, RDIn, RSIn, LDOut, RDOut, SOut) \
  289. do { \
  290. T LDx = LDIn; \
  291. T RDx = RDIn; \
  292. T LDy = LDOut; \
  293. T RDy = RDOut; \
  294. int16_t LSx = LSIn; \
  295. int16_t RSx = RSIn; \
  296. int16_t Sy = SOut; \
  297. \
  298. EXPECT_EQ(SOut, matchScales(LDx, LSx, RDx, RSx)); \
  299. EXPECT_EQ(LDy, LDx); \
  300. EXPECT_EQ(RDy, RDx); \
  301. if (LDy) { \
  302. EXPECT_EQ(Sy, LSx); \
  303. } \
  304. if (RDy) { \
  305. EXPECT_EQ(Sy, RSx); \
  306. } \
  307. } while (false)
  308. MATCH_SCALES(uint32_t, 0, 0, 0, 0, 0, 0, 0);
  309. MATCH_SCALES(uint32_t, 0, 50, 7, 1, 0, 7, 1);
  310. MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 1, 9, 0, UINT32_C(1) << 31, 4, 1);
  311. MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 2, 9, 0, UINT32_C(1) << 31, 2, 2);
  312. MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 3, 9, 0, UINT32_C(1) << 31, 1, 3);
  313. MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 4, 9, 0, UINT32_C(1) << 31, 0, 4);
  314. MATCH_SCALES(uint32_t, UINT32_C(1) << 30, 4, 9, 0, UINT32_C(1) << 31, 1, 3);
  315. MATCH_SCALES(uint32_t, UINT32_C(1) << 29, 4, 9, 0, UINT32_C(1) << 31, 2, 2);
  316. MATCH_SCALES(uint32_t, UINT32_C(1) << 28, 4, 9, 0, UINT32_C(1) << 31, 4, 1);
  317. MATCH_SCALES(uint32_t, UINT32_C(1) << 27, 4, 9, 0, UINT32_C(1) << 31, 9, 0);
  318. MATCH_SCALES(uint32_t, 7, 1, 0, 50, 7, 0, 1);
  319. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 1, 4, UINT32_C(1) << 31, 1);
  320. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 2, 2, UINT32_C(1) << 31, 2);
  321. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 3, 1, UINT32_C(1) << 31, 3);
  322. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 4, 0, UINT32_C(1) << 31, 4);
  323. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 30, 4, 1, UINT32_C(1) << 31, 3);
  324. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 29, 4, 2, UINT32_C(1) << 31, 2);
  325. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 28, 4, 4, UINT32_C(1) << 31, 1);
  326. MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 27, 4, 9, UINT32_C(1) << 31, 0);
  327. MATCH_SCALES(uint64_t, 0, 0, 0, 0, 0, 0, 0);
  328. MATCH_SCALES(uint64_t, 0, 100, 7, 1, 0, 7, 1);
  329. MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 1, 9, 0, UINT64_C(1) << 63, 4, 1);
  330. MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 2, 9, 0, UINT64_C(1) << 63, 2, 2);
  331. MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 3, 9, 0, UINT64_C(1) << 63, 1, 3);
  332. MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 4, 9, 0, UINT64_C(1) << 63, 0, 4);
  333. MATCH_SCALES(uint64_t, UINT64_C(1) << 62, 4, 9, 0, UINT64_C(1) << 63, 1, 3);
  334. MATCH_SCALES(uint64_t, UINT64_C(1) << 61, 4, 9, 0, UINT64_C(1) << 63, 2, 2);
  335. MATCH_SCALES(uint64_t, UINT64_C(1) << 60, 4, 9, 0, UINT64_C(1) << 63, 4, 1);
  336. MATCH_SCALES(uint64_t, UINT64_C(1) << 59, 4, 9, 0, UINT64_C(1) << 63, 9, 0);
  337. MATCH_SCALES(uint64_t, 7, 1, 0, 100, 7, 0, 1);
  338. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 1, 4, UINT64_C(1) << 63, 1);
  339. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 2, 2, UINT64_C(1) << 63, 2);
  340. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 3, 1, UINT64_C(1) << 63, 3);
  341. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 4, 0, UINT64_C(1) << 63, 4);
  342. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 62, 4, 1, UINT64_C(1) << 63, 3);
  343. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 61, 4, 2, UINT64_C(1) << 63, 2);
  344. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 60, 4, 4, UINT64_C(1) << 63, 1);
  345. MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 59, 4, 9, UINT64_C(1) << 63, 0);
  346. }
  347. TEST(ScaledNumberHelpersTest, getSum) {
  348. // Zero.
  349. EXPECT_EQ(SP32(1, 0), getSum32(0, 0, 1, 0));
  350. EXPECT_EQ(SP32(8, -3), getSum32(0, 0, 8, -3));
  351. EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(0, 0, UINT32_MAX, 0));
  352. // Basic.
  353. EXPECT_EQ(SP32(2, 0), getSum32(1, 0, 1, 0));
  354. EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 2, 0));
  355. EXPECT_EQ(SP32(67, 0), getSum32(7, 0, 60, 0));
  356. // Different scales.
  357. EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 1, 1));
  358. EXPECT_EQ(SP32(4, 0), getSum32(2, 0, 1, 1));
  359. // Loss of precision.
  360. EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 32, 1, 0));
  361. EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, -32, 1, 0));
  362. // Not quite loss of precision.
  363. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 32, 1, 1));
  364. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -32, 1, -1));
  365. // Overflow.
  366. EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, UINT32_MAX, 0));
  367. // Reverse operand order.
  368. EXPECT_EQ(SP32(1, 0), getSum32(1, 0, 0, 0));
  369. EXPECT_EQ(SP32(8, -3), getSum32(8, -3, 0, 0));
  370. EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(UINT32_MAX, 0, 0, 0));
  371. EXPECT_EQ(SP32(3, 0), getSum32(2, 0, 1, 0));
  372. EXPECT_EQ(SP32(67, 0), getSum32(60, 0, 7, 0));
  373. EXPECT_EQ(SP32(3, 0), getSum32(1, 1, 1, 0));
  374. EXPECT_EQ(SP32(4, 0), getSum32(1, 1, 2, 0));
  375. EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, 1, 32));
  376. EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, 0, 1, -32));
  377. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 1, 1, 32));
  378. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -1, 1, -32));
  379. EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(UINT32_MAX, 0, 1, 0));
  380. // Zero.
  381. EXPECT_EQ(SP64(1, 0), getSum64(0, 0, 1, 0));
  382. EXPECT_EQ(SP64(8, -3), getSum64(0, 0, 8, -3));
  383. EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(0, 0, UINT64_MAX, 0));
  384. // Basic.
  385. EXPECT_EQ(SP64(2, 0), getSum64(1, 0, 1, 0));
  386. EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 2, 0));
  387. EXPECT_EQ(SP64(67, 0), getSum64(7, 0, 60, 0));
  388. // Different scales.
  389. EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 1, 1));
  390. EXPECT_EQ(SP64(4, 0), getSum64(2, 0, 1, 1));
  391. // Loss of precision.
  392. EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 64, 1, 0));
  393. EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, -64, 1, 0));
  394. // Not quite loss of precision.
  395. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 64, 1, 1));
  396. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -64, 1, -1));
  397. // Overflow.
  398. EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, UINT64_MAX, 0));
  399. // Reverse operand order.
  400. EXPECT_EQ(SP64(1, 0), getSum64(1, 0, 0, 0));
  401. EXPECT_EQ(SP64(8, -3), getSum64(8, -3, 0, 0));
  402. EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(UINT64_MAX, 0, 0, 0));
  403. EXPECT_EQ(SP64(3, 0), getSum64(2, 0, 1, 0));
  404. EXPECT_EQ(SP64(67, 0), getSum64(60, 0, 7, 0));
  405. EXPECT_EQ(SP64(3, 0), getSum64(1, 1, 1, 0));
  406. EXPECT_EQ(SP64(4, 0), getSum64(1, 1, 2, 0));
  407. EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, 1, 64));
  408. EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, 0, 1, -64));
  409. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 1, 1, 64));
  410. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -1, 1, -64));
  411. EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(UINT64_MAX, 0, 1, 0));
  412. }
  413. TEST(ScaledNumberHelpersTest, getDifference) {
  414. // Basic.
  415. EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 0));
  416. EXPECT_EQ(SP32(1, 0), getDifference32(2, 0, 1, 0));
  417. EXPECT_EQ(SP32(53, 0), getDifference32(60, 0, 7, 0));
  418. // Equals "0", different scales.
  419. EXPECT_EQ(SP32(0, 0), getDifference32(2, 0, 1, 1));
  420. // Subtract "0".
  421. EXPECT_EQ(SP32(1, 0), getDifference32(1, 0, 0, 0));
  422. EXPECT_EQ(SP32(8, -3), getDifference32(8, -3, 0, 0));
  423. EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(UINT32_MAX, 0, 0, 0));
  424. // Loss of precision.
  425. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1),
  426. getDifference32((UINT32_C(1) << 31) + 1, 1, 1, 0));
  427. EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -31),
  428. getDifference32((UINT32_C(1) << 31) + 1, -31, 1, -32));
  429. // Not quite loss of precision.
  430. EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(1, 32, 1, 0));
  431. EXPECT_EQ(SP32(UINT32_MAX, -32), getDifference32(1, 0, 1, -32));
  432. // Saturate to "0".
  433. EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 1, 0));
  434. EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 8, -3));
  435. EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, UINT32_MAX, 0));
  436. EXPECT_EQ(SP32(0, 0), getDifference32(7, 0, 60, 0));
  437. EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 1));
  438. EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, 0));
  439. EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, -1));
  440. // Regression tests for cases that failed during bringup.
  441. EXPECT_EQ(SP32(UINT32_C(1) << 26, -31),
  442. getDifference32(1, 0, UINT32_C(31) << 27, -32));
  443. // Basic.
  444. EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 0));
  445. EXPECT_EQ(SP64(1, 0), getDifference64(2, 0, 1, 0));
  446. EXPECT_EQ(SP64(53, 0), getDifference64(60, 0, 7, 0));
  447. // Equals "0", different scales.
  448. EXPECT_EQ(SP64(0, 0), getDifference64(2, 0, 1, 1));
  449. // Subtract "0".
  450. EXPECT_EQ(SP64(1, 0), getDifference64(1, 0, 0, 0));
  451. EXPECT_EQ(SP64(8, -3), getDifference64(8, -3, 0, 0));
  452. EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(UINT64_MAX, 0, 0, 0));
  453. // Loss of precision.
  454. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1),
  455. getDifference64((UINT64_C(1) << 63) + 1, 1, 1, 0));
  456. EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -63),
  457. getDifference64((UINT64_C(1) << 63) + 1, -63, 1, -64));
  458. // Not quite loss of precision.
  459. EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(1, 64, 1, 0));
  460. EXPECT_EQ(SP64(UINT64_MAX, -64), getDifference64(1, 0, 1, -64));
  461. // Saturate to "0".
  462. EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 1, 0));
  463. EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 8, -3));
  464. EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, UINT64_MAX, 0));
  465. EXPECT_EQ(SP64(0, 0), getDifference64(7, 0, 60, 0));
  466. EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 1));
  467. EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, 0));
  468. EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, -1));
  469. }
  470. TEST(ScaledNumberHelpersTest, arithmeticOperators) {
  471. EXPECT_EQ(ScaledNumber<uint32_t>(10, 0),
  472. ScaledNumber<uint32_t>(1, 3) + ScaledNumber<uint32_t>(1, 1));
  473. EXPECT_EQ(ScaledNumber<uint32_t>(6, 0),
  474. ScaledNumber<uint32_t>(1, 3) - ScaledNumber<uint32_t>(1, 1));
  475. EXPECT_EQ(ScaledNumber<uint32_t>(2, 3),
  476. ScaledNumber<uint32_t>(1, 3) * ScaledNumber<uint32_t>(1, 1));
  477. EXPECT_EQ(ScaledNumber<uint32_t>(1, 2),
  478. ScaledNumber<uint32_t>(1, 3) / ScaledNumber<uint32_t>(1, 1));
  479. EXPECT_EQ(ScaledNumber<uint32_t>(1, 2), ScaledNumber<uint32_t>(1, 3) >> 1);
  480. EXPECT_EQ(ScaledNumber<uint32_t>(1, 4), ScaledNumber<uint32_t>(1, 3) << 1);
  481. EXPECT_EQ(ScaledNumber<uint64_t>(10, 0),
  482. ScaledNumber<uint64_t>(1, 3) + ScaledNumber<uint64_t>(1, 1));
  483. EXPECT_EQ(ScaledNumber<uint64_t>(6, 0),
  484. ScaledNumber<uint64_t>(1, 3) - ScaledNumber<uint64_t>(1, 1));
  485. EXPECT_EQ(ScaledNumber<uint64_t>(2, 3),
  486. ScaledNumber<uint64_t>(1, 3) * ScaledNumber<uint64_t>(1, 1));
  487. EXPECT_EQ(ScaledNumber<uint64_t>(1, 2),
  488. ScaledNumber<uint64_t>(1, 3) / ScaledNumber<uint64_t>(1, 1));
  489. EXPECT_EQ(ScaledNumber<uint64_t>(1, 2), ScaledNumber<uint64_t>(1, 3) >> 1);
  490. EXPECT_EQ(ScaledNumber<uint64_t>(1, 4), ScaledNumber<uint64_t>(1, 3) << 1);
  491. }
  492. TEST(ScaledNumberHelpersTest, toIntBug) {
  493. ScaledNumber<uint32_t> n(1, 0);
  494. EXPECT_EQ(1u, (n * n).toInt<uint32_t>());
  495. }
  496. static_assert(is_trivially_copyable<ScaledNumber<uint32_t>>::value,
  497. "trivially copyable");
  498. } // end namespace