diff --git a/unsupported/Eigen/src/Tensor/TensorUInt128.h b/unsupported/Eigen/src/Tensor/TensorUInt128.h index 99e51c577..1ba582c67 100644 --- a/unsupported/Eigen/src/Tensor/TensorUInt128.h +++ b/unsupported/Eigen/src/Tensor/TensorUInt128.h @@ -200,14 +200,13 @@ static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorUInt128 o // calculate the biggest power of 2 times rhs that's less than or equal to lhs TensorUInt128 power2(1); TensorUInt128 d(rhs); - TensorUInt128 tmp(lhs - d); while (lhs >= d) { - tmp = tmp - d; + if (d.high >> 63) break; // next doubling would overflow 128 bits d = d + d; power2 = power2 + power2; } - tmp = TensorUInt128(lhs.high, lhs.low); + TensorUInt128 tmp(lhs.high, lhs.low); TensorUInt128 result(0); while (power2 != TensorUInt128, static_val<0>>(0)) { if (tmp >= d) { diff --git a/unsupported/test/cxx11_tensor_uint128.cpp b/unsupported/test/cxx11_tensor_uint128.cpp index 739b4596d..8ce602c67 100644 --- a/unsupported/test/cxx11_tensor_uint128.cpp +++ b/unsupported/test/cxx11_tensor_uint128.cpp @@ -124,6 +124,26 @@ void test_misc1() { } } +void test_div_overflow() { + // Regression test for infinite loop when lhs > 2^127 (issue #3012). + // Division would overflow d during doubling, causing an infinite loop. + TensorUInt128 a(1ULL << 63, 1); + TensorUInt128 b(2); + uint128_t expected = ((static_cast(1ULL << 63) << 64) + 1) / 2; + VERIFY_EQUAL(a / b, expected); + + // Also test with high bits in both operands + TensorUInt128 c(UINT64_MAX, UINT64_MAX); + TensorUInt128 d(1); + uint128_t c128 = (static_cast(UINT64_MAX) << 64) | UINT64_MAX; + VERIFY_EQUAL(c / d, c128); + + TensorUInt128 e(UINT64_MAX, UINT64_MAX); + TensorUInt128 f(0, 3); + uint128_t e128 = (static_cast(UINT64_MAX) << 64) | UINT64_MAX; + VERIFY_EQUAL(e / f, e128 / 3); +} + void test_misc2() { int64_t incr = internal::random(1, 100); for (int64_t log_div = 0; log_div < 63; ++log_div) { @@ -153,5 +173,6 @@ EIGEN_DECLARE_TEST(cxx11_tensor_uint128) { CALL_SUBTEST_4(test_div()); CALL_SUBTEST_5(test_misc1()); CALL_SUBTEST_6(test_misc2()); + CALL_SUBTEST_7(test_div_overflow()); #endif }