i128_division_ut.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #include <library/cpp/testing/unittest/registar.h>
  2. #include <library/cpp/int128/int128.h>
  3. #include <util/generic/cast.h>
  4. Y_UNIT_TEST_SUITE(I128DivisionBy1Suite) {
  5. Y_UNIT_TEST(I128Divide0By1) {
  6. i128 dividend = 0;
  7. i128 divider = 1;
  8. i128 expectedQuotient = 0;
  9. i128 expectedRemainder = 0;
  10. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  11. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  12. }
  13. Y_UNIT_TEST(I128Divide1By1) {
  14. i128 dividend = 1;
  15. i128 divider = 1;
  16. i128 expectedQuotient = 1;
  17. i128 expectedRemainder = 0;
  18. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  19. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  20. }
  21. Y_UNIT_TEST(I128Divide2By1) {
  22. i128 dividend = 2;
  23. i128 divider = 1;
  24. i128 expectedQuotient = 2;
  25. i128 expectedRemainder = 0;
  26. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  27. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  28. }
  29. Y_UNIT_TEST(I128Divide42By1) {
  30. i128 dividend = 42;
  31. i128 divider = 1;
  32. i128 expectedQuotient = 42;
  33. i128 expectedRemainder = 0;
  34. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  35. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  36. }
  37. Y_UNIT_TEST(I128DivideMaxUi64By1) {
  38. i128 dividend = std::numeric_limits<ui64>::max();
  39. i128 divider = 1;
  40. i128 expectedQuotient = std::numeric_limits<ui64>::max();
  41. i128 expectedRemainder = 0;
  42. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  43. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  44. }
  45. Y_UNIT_TEST(I128DivideMaxUi64Plus1By1) {
  46. i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{1};
  47. i128 divider = 1;
  48. i128 expectedQuotient = i128{std::numeric_limits<ui64>::max()} + i128{1};
  49. i128 expectedRemainder = 0;
  50. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  51. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  52. }
  53. Y_UNIT_TEST(I128DivideMaxUi64Plus42By1) {
  54. i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{42};
  55. i128 divider = 1;
  56. i128 expectedQuotient = i128{std::numeric_limits<ui64>::max()} + i128{42};
  57. i128 expectedRemainder = 0;
  58. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  59. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  60. }
  61. Y_UNIT_TEST(I128DivideMaxI128By1) {
  62. i128 dividend = std::numeric_limits<i128>::max();
  63. i128 divider = 1;
  64. i128 expectedQuotient = std::numeric_limits<i128>::max();
  65. i128 expectedRemainder = 0;
  66. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  67. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  68. }
  69. Y_UNIT_TEST(I128DivideMaxI128Minus1By1) {
  70. i128 dividend = std::numeric_limits<i128>::max() - 1;
  71. i128 divider = 1;
  72. i128 expectedQuotient = std::numeric_limits<i128>::max() - 1;
  73. i128 expectedRemainder = 0;
  74. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  75. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  76. }
  77. }
  78. Y_UNIT_TEST_SUITE(I128DivisionByEqualSuite) {
  79. Y_UNIT_TEST(I128Divide1ByEqual) {
  80. i128 dividend = 1;
  81. i128 divider = dividend;
  82. i128 expectedQuotient = 1;
  83. i128 expectedRemainder = 0;
  84. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  85. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  86. }
  87. Y_UNIT_TEST(I128Divide2ByEqual) {
  88. i128 dividend = 2;
  89. i128 divider = dividend;
  90. i128 expectedQuotient = 1;
  91. i128 expectedRemainder = 0;
  92. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  93. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  94. }
  95. Y_UNIT_TEST(I128Divide42ByEqual) {
  96. i128 dividend = 42;
  97. i128 divider = dividend;
  98. i128 expectedQuotient = 1;
  99. i128 expectedRemainder = 0;
  100. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  101. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  102. }
  103. Y_UNIT_TEST(I128DivideMaxUi64ByEqual) {
  104. i128 dividend = std::numeric_limits<ui64>::max();
  105. i128 divider = dividend;
  106. i128 expectedQuotient = 1;
  107. i128 expectedRemainder = 0;
  108. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  109. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  110. }
  111. Y_UNIT_TEST(I128DivideMaxUi64Plus1ByEqual) {
  112. i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{1};
  113. i128 divider = dividend;
  114. i128 expectedQuotient = 1;
  115. i128 expectedRemainder = 0;
  116. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  117. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  118. }
  119. Y_UNIT_TEST(I128DivideMaxUi64Plus42ByEqual) {
  120. i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{42};
  121. i128 divider = dividend;
  122. i128 expectedQuotient = 1;
  123. i128 expectedRemainder = 0;
  124. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  125. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  126. }
  127. Y_UNIT_TEST(I128DivideMaxI128ByEqual) {
  128. i128 dividend = std::numeric_limits<i128>::max();
  129. i128 divider = dividend;
  130. i128 expectedQuotient = 1;
  131. i128 expectedRemainder = 0;
  132. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  133. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  134. }
  135. Y_UNIT_TEST(I128DivideMaxI128Minus1ByEqual) {
  136. i128 dividend = std::numeric_limits<i128>::max() - 1;
  137. i128 divider = dividend;
  138. i128 expectedQuotient = 1;
  139. i128 expectedRemainder = 0;
  140. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  141. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  142. }
  143. }
  144. Y_UNIT_TEST_SUITE(I128DivisionLessByHigherSuite) {
  145. Y_UNIT_TEST(I128Divide42By84) {
  146. i128 dividend = 42;
  147. i128 divider = 84;
  148. i128 expectedQuotient = 0;
  149. i128 expectedRemainder = 42;
  150. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  151. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  152. }
  153. Y_UNIT_TEST(I128Divide42ByMaxUi64) {
  154. i128 dividend = 42;
  155. i128 divider = std::numeric_limits<ui64>::max();
  156. i128 expectedQuotient = 0;
  157. i128 expectedRemainder = 42;
  158. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  159. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  160. }
  161. Y_UNIT_TEST(I128Divide42ByMaxUi64Plus1) {
  162. i128 dividend = 42;
  163. i128 divider = i128{std::numeric_limits<ui64>::max()} + i128{1};
  164. i128 expectedQuotient = 0;
  165. i128 expectedRemainder = 42;
  166. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  167. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  168. }
  169. Y_UNIT_TEST(I128DivideMaxUi64ByMaxUi64Plus1) {
  170. i128 dividend = i128{std::numeric_limits<ui64>::max()};
  171. i128 divider = i128{std::numeric_limits<ui64>::max()} + i128{1};
  172. i128 expectedQuotient = 0;
  173. i128 expectedRemainder = i128{std::numeric_limits<ui64>::max()};
  174. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  175. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  176. }
  177. }
  178. Y_UNIT_TEST_SUITE(I128DivisionWithDifferentSigns) {
  179. Y_UNIT_TEST(DivisionPositiveByNegative) {
  180. i128 dividend = i128{100};
  181. i128 divider = i128{-33};
  182. i128 expectedQuotient = -3;
  183. i128 expectedRemainder = 1;
  184. i128 quotient = dividend / divider;
  185. i128 remainder = dividend % divider;
  186. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  187. UNIT_ASSERT_EQUAL(remainder, expectedRemainder);
  188. }
  189. Y_UNIT_TEST(DivisionNegativeByPositive) {
  190. i128 dividend = i128{-100};
  191. i128 divider = i128{33};
  192. i128 expectedQuotient = -3;
  193. i128 expectedRemainder = -1;
  194. i128 quotient = dividend / divider;
  195. i128 remainder = dividend % divider;
  196. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  197. UNIT_ASSERT_EQUAL(remainder, expectedRemainder);
  198. }
  199. Y_UNIT_TEST(DivisionNegativeByNegative) {
  200. i128 dividend = i128{-100};
  201. i128 divider = i128{-33};
  202. i128 expectedQuotient = 3;
  203. i128 expectedRemainder = -1;
  204. i128 quotient = dividend / divider;
  205. i128 remainder = dividend % divider;
  206. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  207. UNIT_ASSERT_EQUAL(remainder, expectedRemainder);
  208. }
  209. }
  210. Y_UNIT_TEST_SUITE(i128DivisionBigByBigSuite) {
  211. Y_UNIT_TEST(i128DivideBigByBig1) {
  212. i128 dividend = {64, 0};
  213. i128 divider = {1, 0};
  214. i128 expectedQuotient = 64;
  215. i128 expectedRemainder = 0;
  216. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  217. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  218. }
  219. Y_UNIT_TEST(i128DivideBigByBig1_PosByNeg) {
  220. i128 dividend = i128{64, 0};
  221. i128 divider = -i128{1, 0};
  222. i128 expectedQuotient = -i128{64};
  223. i128 expectedRemainder = 0;
  224. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  225. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  226. }
  227. Y_UNIT_TEST(i128DivideBigByBig1_NegByPos) {
  228. i128 dividend = -i128{64, 0};
  229. i128 divider = i128{1, 0};
  230. i128 expectedQuotient = -i128{64};
  231. i128 expectedRemainder = 0;
  232. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  233. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  234. }
  235. Y_UNIT_TEST(i128DivideBigByBig1_NegByNeg) {
  236. i128 dividend = -i128{64, 0};
  237. i128 divider = -i128{1, 0};
  238. i128 expectedQuotient = i128{64};
  239. i128 expectedRemainder = 0;
  240. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  241. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  242. }
  243. Y_UNIT_TEST(i128DivideBigByBig2) {
  244. i128 dividend = {64, 0};
  245. i128 divider = {12, 5};
  246. i128 expectedQuotient = 5;
  247. i128 expectedRemainder = i128{3, 18446744073709551591ull}; // plz don't ask
  248. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  249. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  250. }
  251. Y_UNIT_TEST(i128DivideBigByBig2_PosByNeg) {
  252. i128 dividend = i128{64, 0};
  253. i128 divider = -i128{12, 5};
  254. i128 expectedQuotient = -5;
  255. i128 expectedRemainder = i128{3, 18446744073709551591ull};
  256. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  257. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  258. }
  259. Y_UNIT_TEST(i128DivideBigByBig2_NegByPos) {
  260. i128 dividend = -i128{64, 0};
  261. i128 divider = i128{12, 5};
  262. i128 expectedQuotient = -5;
  263. i128 expectedRemainder = -i128{3, 18446744073709551591ull};
  264. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  265. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  266. }
  267. Y_UNIT_TEST(i128DivideBigByBig2_NegByNeg) {
  268. i128 dividend = -i128{64, 0};
  269. i128 divider = -i128{12, 5};
  270. i128 expectedQuotient = 5;
  271. i128 expectedRemainder = -i128{3, 18446744073709551591ull};
  272. UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient);
  273. UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder);
  274. }
  275. }
  276. Y_UNIT_TEST_SUITE(i128DivisionAlgo) {
  277. Y_UNIT_TEST(ii128DivideAlgoCheck_PosByPos) {
  278. /*
  279. 49672666804009505000000 / 10000000 == 4967266680400950
  280. 49672666804009505000000 % 10000000 == 5000000
  281. */
  282. i128 dividend = {2692ull, 14031757583392049728ull};
  283. i64 divider = 10000000;
  284. i128 expectedQuotient = {0, 4967266680400950ull};
  285. i128 expectedRemainder = {0, 5000000ull};
  286. i128 quotient = dividend / divider;
  287. i128 reminder = dividend % divider;
  288. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  289. UNIT_ASSERT_EQUAL(reminder, expectedRemainder);
  290. }
  291. Y_UNIT_TEST(ii128DivideAlgoCheck_PosByNeg) {
  292. /*
  293. 49672666804009505000000 / -10000000 == -4967266680400950
  294. 49672666804009505000000 % -10000000 == 5000000
  295. */
  296. i128 dividend = {2692ull, 14031757583392049728ull};
  297. i64 divider = -10000000;
  298. i128 expectedQuotient = -i128{0, 4967266680400950ull};
  299. i128 expectedRemainder = {0, 5000000ull};
  300. i128 quotient = dividend / divider;
  301. i128 reminder = dividend % divider;
  302. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  303. UNIT_ASSERT_EQUAL(reminder, expectedRemainder);
  304. }
  305. Y_UNIT_TEST(ii128DivideAlgoCheck_NegByPos) {
  306. /*
  307. -49672666804009505000000 / 10000000 == -4967266680400950
  308. -49672666804009505000000 % 10000000 == -5000000
  309. */
  310. i128 dividend = -i128{2692ull, 14031757583392049728ull};
  311. i64 divider = 10000000;
  312. i128 expectedQuotient = -i128{0, 4967266680400950ull};
  313. i128 expectedRemainder = -i128{0, 5000000ull};
  314. i128 quotient = dividend / divider;
  315. i128 reminder = dividend % divider;
  316. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  317. UNIT_ASSERT_EQUAL(reminder, expectedRemainder);
  318. }
  319. Y_UNIT_TEST(ii128DivideAlgoCheck_NegByNeg) {
  320. /*
  321. -49672666804009505000000 / -10000000 == 4967266680400950
  322. -49672666804009505000000 % -10000000 == -5000000
  323. */
  324. i128 dividend = -i128{2692ull, 14031757583392049728ull};
  325. i64 divider = -10000000;
  326. i128 expectedQuotient = {0, 4967266680400950ull};
  327. i128 expectedRemainder = -i128{0, 5000000ull};
  328. i128 quotient = dividend / divider;
  329. i128 reminder = dividend % divider;
  330. UNIT_ASSERT_EQUAL(quotient, expectedQuotient);
  331. UNIT_ASSERT_EQUAL(reminder, expectedRemainder);
  332. }
  333. }