| // SPDX-FileCopyrightText: The Eigen Authors |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| #define EIGEN_RUNTIME_NO_MALLOC |
| #include "main.h" |
| #include <Eigen/Core> |
| |
| template <unsigned int UpLo, bool Hessenberg, typename Derived> |
| void check_structured_abs_sum(const MatrixBase<Derived>& matrix) { |
| using RealScalar = typename Derived::RealScalar; |
| long double expected = 0; |
| for (Index row = 0; row < matrix.rows(); ++row) { |
| for (Index col = 0; col < matrix.cols(); ++col) { |
| if (UpLo == Upper ? row - col <= Index(Hessenberg) : col - row <= Index(Hessenberg)) { |
| const long double real = static_cast<long double>(numext::real(matrix(row, col))); |
| const long double imag = static_cast<long double>(numext::imag(matrix(row, col))); |
| expected += std::sqrt(real * real + imag * imag); |
| } |
| } |
| } |
| internal::set_is_malloc_allowed(false); |
| const RealScalar actual = |
| Hessenberg ? internal::hessenberg_abs_sum<UpLo>(matrix) : internal::triangular_abs_sum<UpLo>(matrix); |
| internal::set_is_malloc_allowed(true); |
| // Each magnitude and addition contributes O(eps); the reference accumulates in long double. |
| const long double bound = 8 * static_cast<long double>(matrix.size()) * |
| static_cast<long double>(NumTraits<RealScalar>::epsilon()) * expected; |
| VERIFY((numext::isfinite)(actual)); |
| VERIFY(std::abs(static_cast<long double>(actual) - expected) <= bound); |
| } |
| |
| template <typename Derived> |
| void check_structured_abs_sums(const MatrixBase<Derived>& matrix) { |
| check_structured_abs_sum<Upper, false>(matrix); |
| check_structured_abs_sum<Lower, false>(matrix); |
| check_structured_abs_sum<Upper, true>(matrix); |
| check_structured_abs_sum<Lower, true>(matrix); |
| } |
| |
| template <typename Scalar, int StorageOrder> |
| void structured_abs_sums() { |
| using Mat = Matrix<Scalar, Dynamic, Dynamic, StorageOrder>; |
| const Matrix<Scalar, 3, 5, StorageOrder> fixed = Matrix<Scalar, 3, 5, StorageOrder>::Random(); |
| check_structured_abs_sums(fixed); |
| check_structured_abs_sums(fixed.transpose()); |
| for (Index rows : {0, 1, 2, 7, 16, 17, 33}) { |
| for (Index cols : {0, 1, 2, 7, 16, 17, 33}) { |
| Mat matrix = Mat::Random(rows, cols); |
| check_structured_abs_sums(matrix); |
| check_structured_abs_sums(matrix.transpose()); |
| check_structured_abs_sums(matrix * Scalar(2)); |
| Mat storage = Mat::Random(rows + 2, cols + 3); |
| check_structured_abs_sums(storage.block(1, 2, rows, cols)); |
| using StridedMap = Map<const Mat, Unaligned, Stride<Dynamic, 2>>; |
| Mat stridedStorage = Mat::Random(2 * (rows + 1), 2 * (cols + 1)); |
| StridedMap strided(stridedStorage.data(), rows, cols, Stride<Dynamic, 2>(stridedStorage.outerStride(), 2)); |
| check_structured_abs_sums(strided); |
| } |
| } |
| |
| using RealScalar = typename NumTraits<Scalar>::Real; |
| const Scalar nan((std::numeric_limits<RealScalar>::quiet_NaN)()); |
| for (Index extra : {0, 1}) { |
| Mat matrix = Mat::Random(17, 17); |
| for (Index row = 0; row < matrix.rows(); ++row) |
| for (Index col = 0; col + extra < row; ++col) matrix(row, col) = nan; |
| if (extra == 0) { |
| check_structured_abs_sum<Upper, false>(matrix); |
| check_structured_abs_sum<Lower, false>(matrix.transpose()); |
| } else { |
| check_structured_abs_sum<Upper, true>(matrix); |
| check_structured_abs_sum<Lower, true>(matrix.transpose()); |
| } |
| } |
| |
| Mat matrix = Mat::Zero(17, 17); |
| matrix(0, 0) = nan; |
| VERIFY((numext::isnan)(internal::triangular_abs_sum<Upper>(matrix))); |
| VERIFY((numext::isnan)(internal::hessenberg_abs_sum<Lower>(matrix))); |
| matrix(0, 0) = Scalar((std::numeric_limits<RealScalar>::infinity)()); |
| VERIFY((numext::isinf)(internal::triangular_abs_sum<Lower>(matrix))); |
| VERIFY((numext::isinf)(internal::hessenberg_abs_sum<Upper>(matrix))); |
| } |
| |
| EIGEN_DECLARE_TEST(structured_norm) { |
| CALL_SUBTEST_1((structured_abs_sums<float, ColMajor>())); |
| CALL_SUBTEST_1((structured_abs_sums<float, RowMajor>())); |
| CALL_SUBTEST_2((structured_abs_sums<double, ColMajor>())); |
| CALL_SUBTEST_2((structured_abs_sums<double, RowMajor>())); |
| CALL_SUBTEST_3((structured_abs_sums<std::complex<float>, ColMajor>())); |
| CALL_SUBTEST_3((structured_abs_sums<std::complex<float>, RowMajor>())); |
| CALL_SUBTEST_4((structured_abs_sums<std::complex<double>, ColMajor>())); |
| CALL_SUBTEST_4((structured_abs_sums<std::complex<double>, RowMajor>())); |
| CALL_SUBTEST_5((structured_abs_sums<long double, ColMajor>())); |
| CALL_SUBTEST_5((structured_abs_sums<long double, RowMajor>())); |
| } |