cxx11_tensor_uint128.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "main.h"
  10. #include <Eigen/CXX11/Tensor>
  11. #if EIGEN_COMP_MSVC || !defined(__SIZEOF_INT128__)
  12. #define EIGEN_NO_INT128
  13. #else
  14. typedef __uint128_t uint128_t;
  15. #endif
  16. // Only run the test on compilers that support 128bit integers natively
  17. #ifndef EIGEN_NO_INT128
  18. using Eigen::internal::TensorUInt128;
  19. using Eigen::internal::static_val;
  20. void VERIFY_EQUAL(TensorUInt128<uint64_t, uint64_t> actual, uint128_t expected) {
  21. bool matchl = actual.lower() == static_cast<uint64_t>(expected);
  22. bool matchh = actual.upper() == static_cast<uint64_t>(expected >> 64);
  23. if (!matchl || !matchh) {
  24. const char* testname = g_test_stack.back().c_str();
  25. std::cerr << "Test " << testname << " failed in " << __FILE__
  26. << " (" << __LINE__ << ")"
  27. << std::endl;
  28. abort();
  29. }
  30. }
  31. void test_add() {
  32. uint64_t incr = internal::random<uint64_t>(1, 9999999999);
  33. for (uint64_t i1 = 0; i1 < 100; ++i1) {
  34. for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
  35. TensorUInt128<uint64_t, uint64_t> i(i1, i2);
  36. uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
  37. for (uint64_t j1 = 0; j1 < 100; ++j1) {
  38. for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
  39. TensorUInt128<uint64_t, uint64_t> j(j1, j2);
  40. uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
  41. TensorUInt128<uint64_t, uint64_t> actual = i + j;
  42. uint128_t expected = a + b;
  43. VERIFY_EQUAL(actual, expected);
  44. }
  45. }
  46. }
  47. }
  48. }
  49. void test_sub() {
  50. uint64_t incr = internal::random<uint64_t>(1, 9999999999);
  51. for (uint64_t i1 = 0; i1 < 100; ++i1) {
  52. for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
  53. TensorUInt128<uint64_t, uint64_t> i(i1, i2);
  54. uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
  55. for (uint64_t j1 = 0; j1 < 100; ++j1) {
  56. for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
  57. TensorUInt128<uint64_t, uint64_t> j(j1, j2);
  58. uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
  59. TensorUInt128<uint64_t, uint64_t> actual = i - j;
  60. uint128_t expected = a - b;
  61. VERIFY_EQUAL(actual, expected);
  62. }
  63. }
  64. }
  65. }
  66. }
  67. void test_mul() {
  68. uint64_t incr = internal::random<uint64_t>(1, 9999999999);
  69. for (uint64_t i1 = 0; i1 < 100; ++i1) {
  70. for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
  71. TensorUInt128<uint64_t, uint64_t> i(i1, i2);
  72. uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
  73. for (uint64_t j1 = 0; j1 < 100; ++j1) {
  74. for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
  75. TensorUInt128<uint64_t, uint64_t> j(j1, j2);
  76. uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
  77. TensorUInt128<uint64_t, uint64_t> actual = i * j;
  78. uint128_t expected = a * b;
  79. VERIFY_EQUAL(actual, expected);
  80. }
  81. }
  82. }
  83. }
  84. }
  85. void test_div() {
  86. uint64_t incr = internal::random<uint64_t>(1, 9999999999);
  87. for (uint64_t i1 = 0; i1 < 100; ++i1) {
  88. for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
  89. TensorUInt128<uint64_t, uint64_t> i(i1, i2);
  90. uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
  91. for (uint64_t j1 = 0; j1 < 100; ++j1) {
  92. for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
  93. TensorUInt128<uint64_t, uint64_t> j(j1, j2);
  94. uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
  95. TensorUInt128<uint64_t, uint64_t> actual = i / j;
  96. uint128_t expected = a / b;
  97. VERIFY_EQUAL(actual, expected);
  98. }
  99. }
  100. }
  101. }
  102. }
  103. void test_misc1() {
  104. uint64_t incr = internal::random<uint64_t>(1, 9999999999);
  105. for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
  106. TensorUInt128<static_val<0>, uint64_t> i(0, i2);
  107. uint128_t a = static_cast<uint128_t>(i2);
  108. for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
  109. TensorUInt128<static_val<0>, uint64_t> j(0, j2);
  110. uint128_t b = static_cast<uint128_t>(j2);
  111. uint64_t actual = (i * j).upper();
  112. uint64_t expected = (a * b) >> 64;
  113. VERIFY_IS_EQUAL(actual, expected);
  114. }
  115. }
  116. }
  117. void test_misc2() {
  118. int64_t incr = internal::random<int64_t>(1, 100);
  119. for (int64_t log_div = 0; log_div < 63; ++log_div) {
  120. for (int64_t divider = 1; divider <= 1000000 * incr; divider += incr) {
  121. uint64_t expected = (static_cast<uint128_t>(1) << (64+log_div)) / static_cast<uint128_t>(divider) - (static_cast<uint128_t>(1) << 64) + 1;
  122. uint64_t shift = 1ULL << log_div;
  123. TensorUInt128<uint64_t, uint64_t> result = (TensorUInt128<uint64_t, static_val<0> >(shift, 0) / TensorUInt128<static_val<0>, uint64_t>(divider) - TensorUInt128<static_val<1>, static_val<0> >(1, 0) + TensorUInt128<static_val<0>, static_val<1> >(1));
  124. uint64_t actual = static_cast<uint64_t>(result);
  125. VERIFY_IS_EQUAL(actual, expected);
  126. }
  127. }
  128. }
  129. #endif
  130. EIGEN_DECLARE_TEST(cxx11_tensor_uint128)
  131. {
  132. #ifdef EIGEN_NO_INT128
  133. // Skip the test on compilers that don't support 128bit integers natively
  134. return;
  135. #else
  136. CALL_SUBTEST_1(test_add());
  137. CALL_SUBTEST_2(test_sub());
  138. CALL_SUBTEST_3(test_mul());
  139. CALL_SUBTEST_4(test_div());
  140. CALL_SUBTEST_5(test_misc1());
  141. CALL_SUBTEST_6(test_misc2());
  142. #endif
  143. }