diff --git a/test/geo_transformations.cpp b/test/geo_transformations.cpp index a9eb87e25..99ec9a5fb 100644 --- a/test/geo_transformations.cpp +++ b/test/geo_transformations.cpp @@ -224,10 +224,14 @@ void transformations() { t4 *= aa3; VERIFY_IS_APPROX(t3.matrix(), t4.matrix()); - do { - v3 = Vector3::Random(); - dont_over_optimize(v3); - } while (v3.cwiseAbs().minCoeff() < NumTraits::epsilon()); + { + int guard = 0; + do { + v3 = Vector3::Random(); + dont_over_optimize(v3); + } while (v3.cwiseAbs().minCoeff() < NumTraits::epsilon() && (++guard) < 100); + VERIFY(guard < 100); + } Translation3 tv3(v3); Transform3 t5(tv3); t4 = tv3; @@ -381,9 +385,13 @@ void transformations() { // test transform inversion t0.setIdentity(); t0.translate(v0); - do { - t0.linear().setRandom(); - } while (t0.linear().jacobiSvd().singularValues()(2) < test_precision()); + { + int guard = 0; + do { + t0.linear().setRandom(); + } while (t0.linear().jacobiSvd().singularValues()(2) < test_precision() && (++guard) < 100); + VERIFY(guard < 100); + } Matrix4 t044 = Matrix4::Zero(); t044(3, 3) = 1; t044.block(0, 0, t0.matrix().rows(), 4) = t0.matrix(); diff --git a/test/integer_types.cpp b/test/integer_types.cpp index a3be74998..142854cf2 100644 --- a/test/integer_types.cpp +++ b/test/integer_types.cpp @@ -26,16 +26,24 @@ void signed_integer_type_tests(const MatrixType& m) { MatrixType m1(rows, cols), m2 = MatrixType::Random(rows, cols), mzero = MatrixType::Zero(rows, cols); - do { - m1 = MatrixType::Random(rows, cols); - } while (m1 == mzero || m1 == m2); + { + int guard = 0; + do { + m1 = MatrixType::Random(rows, cols); + } while ((m1 == mzero || m1 == m2) && (++guard) < 100); + VERIFY(guard < 100); + } // check linear structure Scalar s1; - do { - s1 = internal::random(); - } while (s1 == 0); + { + int guard = 0; + do { + s1 = internal::random(); + } while (s1 == 0 && (++guard) < 100); + VERIFY(guard < 100); + } VERIFY_IS_EQUAL(-(-m1), m1); VERIFY_IS_EQUAL(-m2 + m1 + m2, m1); @@ -63,13 +71,21 @@ void integer_type_tests(const MatrixType& m) { SquareMatrixType identity = SquareMatrixType::Identity(rows, rows), square = SquareMatrixType::Random(rows, rows); VectorType v1(rows), v2 = VectorType::Random(rows), vzero = VectorType::Zero(rows); - do { - m1 = MatrixType::Random(rows, cols); - } while (m1 == mzero || m1 == m2); + { + int guard = 0; + do { + m1 = MatrixType::Random(rows, cols); + } while ((m1 == mzero || m1 == m2) && (++guard) < 100); + VERIFY(guard < 100); + } - do { - v1 = VectorType::Random(rows); - } while (v1 == vzero || v1 == v2); + { + int guard = 0; + do { + v1 = VectorType::Random(rows); + } while ((v1 == vzero || v1 == v2) && (++guard) < 100); + VERIFY(guard < 100); + } VERIFY_IS_APPROX(v1, v1); VERIFY_IS_NOT_APPROX(v1, 2 * v1); diff --git a/test/lu.cpp b/test/lu.cpp index b20bcfc80..7946c0b4d 100644 --- a/test/lu.cpp +++ b/test/lu.cpp @@ -106,10 +106,10 @@ void lu_invertible() { MatrixType m1(size, size), m2(size, size), m3(size, size); FullPivLU lu; lu.setThreshold(RealScalar(0.01)); - do { - m1 = MatrixType::Random(size, size); - lu.compute(m1); - } while (!lu.isInvertible()); + // Create a random diagonally dominant (thus invertible) matrix. + m1 = MatrixType::Random(size, size); + m1.diagonal().array() += RealScalar(2 * size); + lu.compute(m1); VERIFY_IS_APPROX(m1, lu.reconstructedMatrix()); VERIFY(0 == lu.dimensionOfKernel()); diff --git a/test/prec_inverse_4x4.cpp b/test/prec_inverse_4x4.cpp index 157afa7f2..3864ecf8b 100644 --- a/test/prec_inverse_4x4.cpp +++ b/test/prec_inverse_4x4.cpp @@ -28,12 +28,9 @@ void inverse_general_4x4(int repeat) { typedef typename MatrixType::Scalar Scalar; double error_sum = 0., error_max = 0.; for (int i = 0; i < repeat; ++i) { - MatrixType m; - bool is_invertible; - do { - m = MatrixType::Random(); - is_invertible = Eigen::FullPivLU(m).isInvertible(); - } while (!is_invertible); + // Create a random diagonally dominant (thus invertible) matrix. + MatrixType m = MatrixType::Random(); + m.diagonal().array() += Scalar(8); // 2 * 4 for a 4x4 matrix. MatrixType inv = m.inverse(); double error = double((m * inv - MatrixType::Identity()).norm()); error_sum += error; diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp index c821304dd..5824dc6b5 100644 --- a/test/qr_colpivoting.cpp +++ b/test/qr_colpivoting.cpp @@ -154,10 +154,10 @@ void qr() { { MatrixType m2, m3; Index size = rows; - do { - m1 = MatrixType::Random(size, size); - qr.compute(m1); - } while (!qr.isInvertible()); + // Create a random diagonally dominant (thus invertible) matrix. + m1 = MatrixType::Random(size, size); + m1.diagonal().array() += Scalar(2 * size); + qr.compute(m1); MatrixType m1_inv = qr.inverse(); m3 = m1 * MatrixType::Random(size, cols2); m2 = qr.solve(m3); diff --git a/test/qr_fullpivoting.cpp b/test/qr_fullpivoting.cpp index 2b6ecc5b8..d3dd2d159 100644 --- a/test/qr_fullpivoting.cpp +++ b/test/qr_fullpivoting.cpp @@ -56,10 +56,10 @@ void qr() { { MatrixType m2, m3; Index size = rows; - do { - m1 = MatrixType::Random(size, size); - qr.compute(m1); - } while (!qr.isInvertible()); + // Create a random diagonally dominant (thus invertible) matrix. + m1 = MatrixType::Random(size, size); + m1.diagonal().array() += Scalar(2 * size); + qr.compute(m1); MatrixType m1_inv = qr.inverse(); m3 = m1 * MatrixType::Random(size, cols2); m2 = qr.solve(m3); diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp index e9ed3d5f7..567c862df 100644 --- a/test/stable_norm.cpp +++ b/test/stable_norm.cpp @@ -52,13 +52,11 @@ void stable_norm(const MatrixType& m) { Index rows = m.rows(); Index cols = m.cols(); - // get a non-zero random factor - Scalar factor = internal::random(); - while (numext::abs2(factor) < RealScalar(1e-4)) factor = internal::random(); + // Get a random factor bounded away from zero: |factor| >= 0.1. + Scalar factor = internal::random(Scalar(RealScalar(0.1)), Scalar(RealScalar(1))); Scalar big = factor * ((std::numeric_limits::max)() * RealScalar(1e-4)); - factor = internal::random(); - while (numext::abs2(factor) < RealScalar(1e-4)) factor = internal::random(); + factor = internal::random(Scalar(RealScalar(0.1)), Scalar(RealScalar(1))); Scalar small = factor * ((std::numeric_limits::min)() * RealScalar(1e4)); Scalar one(1); @@ -217,12 +215,11 @@ void test_empty() { template void test_hypot() { typedef typename NumTraits::Real RealScalar; - Scalar factor = internal::random(); - while (numext::abs2(factor) < RealScalar(1e-4)) factor = internal::random(); + // Get a random factor bounded away from zero: |factor| >= 0.1. + Scalar factor = internal::random(Scalar(RealScalar(0.1)), Scalar(RealScalar(1))); Scalar big = factor * ((std::numeric_limits::max)() * RealScalar(1e-4)); - factor = internal::random(); - while (numext::abs2(factor) < RealScalar(1e-4)) factor = internal::random(); + factor = internal::random(Scalar(RealScalar(0.1)), Scalar(RealScalar(1))); Scalar small = factor * ((std::numeric_limits::min)() * RealScalar(1e4)); Scalar one(1), zero(0), sqrt2(std::sqrt(2)), nan(std::numeric_limits::quiet_NaN()); diff --git a/test/svd_common.h b/test/svd_common.h index 82c61a579..0421d66b3 100644 --- a/test/svd_common.h +++ b/test/svd_common.h @@ -177,8 +177,8 @@ void svd_min_norm(const MatrixType& m) { int guard = 0; do { m2.setRandom(); - } while (SVD_FOR_MIN_NORM(MatrixType2)(m2).setThreshold(test_precision()).rank() != rank && (++guard) < 10); - VERIFY(guard < 10); + } while (SVD_FOR_MIN_NORM(MatrixType2)(m2).setThreshold(test_precision()).rank() != rank && (++guard) < 100); + VERIFY(guard < 100); RhsType2 rhs2 = RhsType2::Random(rank); // use QR to find a reference minimal norm solution diff --git a/test/threads_eventcount.cpp b/test/threads_eventcount.cpp index bd6e9a8f8..ebac0919f 100644 --- a/test/threads_eventcount.cpp +++ b/test/threads_eventcount.cpp @@ -74,7 +74,7 @@ const int TestQueue::kQueueSize; // fake queues. Ensure that it does not crash, consumers don't deadlock and // number of blocked and unblocked threads match. static void test_stress_eventcount() { - const int kThreads = std::thread::hardware_concurrency(); + const int kThreads = (std::min)(static_cast(std::thread::hardware_concurrency()), 16); static const int kEvents = 1 << 16; static const int kQueues = 10; diff --git a/test/threads_non_blocking_thread_pool.cpp b/test/threads_non_blocking_thread_pool.cpp index e805cf2c4..09990a051 100644 --- a/test/threads_non_blocking_thread_pool.cpp +++ b/test/threads_non_blocking_thread_pool.cpp @@ -12,6 +12,18 @@ #include "main.h" #include "Eigen/ThreadPool" +// Spin-wait with yielding until the condition is met, or fail after a timeout. +// Returns true if the condition was met before the deadline. +template +static bool spin_wait(Cond cond, int timeout_seconds = 60) { + auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout_seconds); + while (!cond()) { + if (std::chrono::steady_clock::now() > deadline) return false; + std::this_thread::yield(); + } + return true; +} + static void test_create_destroy_empty_pool() { // Just create and destroy the pool. This will wind up and tear down worker // threads. Ensure there are no issues in that logic. @@ -38,12 +50,12 @@ static void test_parallelism(bool allow_spinning) { VERIFY_LE(thread_id, kThreads - 1); running++; while (phase < 1) { + std::this_thread::yield(); } done++; }); } - while (running != kThreads) { - } + VERIFY(spin_wait([&] { return running == kThreads; })); running = 0; phase = 1; // Now, while the previous tasks exit, schedule another kThreads tasks and @@ -52,6 +64,7 @@ static void test_parallelism(bool allow_spinning) { tp.Schedule([&, i]() { running++; while (phase < 2) { + std::this_thread::yield(); } // When all tasks are running, half of tasks exit, quarter of tasks // continue running and quarter of tasks schedule another 2 tasks each. @@ -62,6 +75,7 @@ static void test_parallelism(bool allow_spinning) { } else if (i < 3 * kThreads / 4) { running++; while (phase < 3) { + std::this_thread::yield(); } done++; } else { @@ -69,6 +83,7 @@ static void test_parallelism(bool allow_spinning) { tp.Schedule([&]() { running++; while (phase < 3) { + std::this_thread::yield(); } done++; }); @@ -77,23 +92,21 @@ static void test_parallelism(bool allow_spinning) { done++; }); } - while (running != kThreads) { - } + VERIFY(spin_wait([&] { return running == kThreads; })); running = 0; phase = 2; for (int i = 0; i < kThreads / 4; ++i) { tp.Schedule([&]() { running++; while (phase < 3) { + std::this_thread::yield(); } done++; }); } - while (running != kThreads) { - } + VERIFY(spin_wait([&] { return running == kThreads; })); phase = 3; - while (done != 3 * kThreads) { - } + VERIFY(spin_wait([&] { return done == 3 * kThreads; })); } } @@ -136,12 +149,12 @@ static void test_pool_partitions() { VERIFY_LE(thread_id, kThreads - 1); ++running; while (phase < 1) { + std::this_thread::yield(); } ++done; }); } - while (running != kThreads) { - } + VERIFY(spin_wait([&] { return running == kThreads; })); // Schedule each closure to only run on thread 'i' and verify that it does. for (int i = 0; i < kThreads; ++i) { tp.ScheduleWithHint( @@ -150,6 +163,7 @@ static void test_pool_partitions() { const int thread_id = tp.CurrentThreadId(); VERIFY_IS_EQUAL(thread_id, i); while (phase < 2) { + std::this_thread::yield(); } ++done; }, @@ -157,8 +171,7 @@ static void test_pool_partitions() { } running = 0; phase = 1; - while (running != kThreads) { - } + VERIFY(spin_wait([&] { return running == kThreads; })); running = 0; phase = 2; }