10 #include <catch2/catch_test_macros.hpp>
16 #include "Eigen/Dense"
19 using namespace nmodl;
20 using namespace Eigen;
25 template <
typename DerivedA,
typename DerivedB>
26 bool allclose(
const Eigen::DenseBase<DerivedA>& a,
27 const Eigen::DenseBase<DerivedB>& b,
28 const typename DerivedA::RealScalar&
rtol =
29 Eigen::NumTraits<typename DerivedA::RealScalar>::dummy_precision(),
30 const typename DerivedA::RealScalar& atol =
31 Eigen::NumTraits<typename DerivedA::RealScalar>::epsilon()) {
32 return ((a.derived() - b.derived()).array().abs() <= (atol +
rtol * b.derived().array().abs()))
39 std::random_device rd;
41 std::mt19937 mt(seed);
42 std::uniform_real_distribution<T> nums(-1e3, 1e3);
44 std::chrono::duration<double> eigen_timing(std::chrono::duration<double>::zero());
45 std::chrono::duration<double> crout_timing(std::chrono::duration<double>::zero());
47 auto t1 = std::chrono::high_resolution_clock::now();
48 auto t2 = std::chrono::high_resolution_clock::now();
50 for (
int mat_size = 5; mat_size < 15; mat_size++) {
56 for (
int repetitions = 0; repetitions < static_cast<int>(1e3); ++repetitions) {
59 for (
int r = 0; r < mat_size; r++) {
60 for (
int c = 0;
c < mat_size;
c++) {
61 A_ColMajor(r,
c) = nums(mt);
62 A_RowMajor(r,
c) = A_ColMajor(r,
c);
66 }
while (!A_ColMajor.fullPivLu().isInvertible());
68 t1 = std::chrono::high_resolution_clock::now();
71 eigen_x_ColMajor = A_ColMajor.partialPivLu().solve(b);
75 eigen_x_RowMajor = A_RowMajor.partialPivLu().solve(b);
76 t2 = std::chrono::high_resolution_clock::now();
77 eigen_timing += (t2 - t1);
79 if (!
allclose(eigen_x_ColMajor, eigen_x_RowMajor,
rtol, atol)) {
80 cerr <<
"eigen_x_ColMajor vs eigen_x_RowMajor (issue) / seed = " << seed << endl;
84 t1 = std::chrono::high_resolution_clock::now();
87 if (!A_ColMajor.IsRowMajor)
88 A_ColMajor.transposeInPlace();
91 crout::Crout<T>(mat_size, A_ColMajor.data(), pivot.data(), rowmax.data());
93 mat_size, A_ColMajor.data(), b.data(), crout_x_ColMajor.data(), pivot.data());
97 crout::Crout<T>(mat_size, A_RowMajor.data(), pivot.data(), rowmax.data());
99 mat_size, A_RowMajor.data(), b.data(), crout_x_RowMajor.data(), pivot.data());
100 t2 = std::chrono::high_resolution_clock::now();
101 crout_timing += (t2 - t1);
103 if (!
allclose(eigen_x_ColMajor, crout_x_ColMajor,
rtol, atol)) {
104 cerr <<
"eigen_x_ColMajor vs crout_x_ColMajor (issue) / seed = " << seed << endl;
108 if (!
allclose(eigen_x_RowMajor, crout_x_RowMajor,
rtol, atol)) {
109 cerr <<
"eigen_x_RowMajor vs crout_x_RowMajor (issue) / seed = " << seed << endl;
115 std::cout <<
"eigen_timing [ms] : " << eigen_timing.count() * 1e3 << std::endl;
116 std::cout <<
"crout_timing [ms] : " << crout_timing.count() * 1e3 << std::endl;
123 GIVEN(
"crout (double)") {
124 constexpr
double rtol = 1e-8;
125 constexpr
double atol = 1e-8;
127 auto test = test_Crout_correctness<double>(
rtol, atol);
129 THEN(
"run tests & compare") {
bool test_Crout_correctness(T rtol=1e-8, T atol=1e-8)
SCENARIO("Compare Crout solver with Eigen")
bool allclose(const Eigen::DenseBase< DerivedA > &a, const Eigen::DenseBase< DerivedB > &b, const typename DerivedA::RealScalar &rtol=Eigen::NumTraits< typename DerivedA::RealScalar >::dummy_precision(), const typename DerivedA::RealScalar &atol=Eigen::NumTraits< typename DerivedA::RealScalar >::epsilon())
https://stackoverflow.com/questions/15051367/how-to-compare-vectors-approximately-in-eigen
Implementation of Crout matrix decomposition (LU decomposition) followed by Forward/Backward substitu...
static double rtol(void *v)
encapsulates code generation backend implementations