blob: f07e5bcedd0725a71d1cb48f655f1aa6a24fa0f0 [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include "main.h"
#include <Eigen/Core>
template <typename ProductType, typename Mat>
void check_scaled_product(const ProductType& product, const Mat& expected) {
Mat actual = product;
VERIFY_IS_EQUAL(actual, expected);
actual = product + Mat::Zero(expected.rows(), expected.cols());
VERIFY_IS_EQUAL(actual, expected);
actual.setZero();
actual.noalias() += product;
VERIFY_IS_EQUAL(actual, expected);
actual.noalias() -= product;
VERIFY_IS_EQUAL(actual, Mat::Zero(expected.rows(), expected.cols()));
Mat triangle = Mat::Constant(expected.rows(), expected.cols(), typename Mat::Scalar(7));
Mat triangleExpected = triangle;
triangle.template triangularView<Upper>() = product;
triangleExpected.template triangularView<Upper>() = expected;
VERIFY_IS_EQUAL(triangle, triangleExpected);
triangle.template triangularView<Lower>() = product;
triangleExpected.template triangularView<Lower>() = expected;
VERIFY_IS_EQUAL(triangle, triangleExpected);
}
template <typename Scalar, int Mode, int Order>
void scaled_unit_triangular_product() {
using Mat = Matrix<Scalar, 3, 3, Order>;
Mat matrix;
matrix << 9, 2, 3, 4, 9, 6, 7, 8, 9;
const Mat rhs = Mat::Constant(2);
const Matrix<Scalar, 3, 1> diagonal = Matrix<Scalar, 3, 1>::Constant(2);
Mat expected = Mat::Zero(), expectedDiagonal = Mat::Zero();
for (Index j = 0; j < 3; ++j) {
for (Index i = 0; i < 3; ++i) {
for (Index k = 0; k < 3; ++k) {
const bool stored = Mode == UnitLower ? i > k : i < k;
const Scalar value = i == k ? Scalar(1) : stored ? matrix(i, k) : Scalar(0);
expected(i, j) += Scalar(3) * value * rhs(k, j);
}
const bool stored = Mode == UnitLower ? i > j : i < j;
expectedDiagonal(i, j) = Scalar(3) * (i == j ? Scalar(1) : stored ? matrix(i, j) : Scalar(0)) * diagonal(j);
}
}
check_scaled_product(Scalar(3) * (matrix.template triangularView<Mode>() * rhs), expected);
check_scaled_product(Scalar(3) * (matrix.template triangularView<Mode>() * diagonal.asDiagonal()), expectedDiagonal);
Mat aliased = matrix;
aliased = Scalar(3) * (aliased.template triangularView<Mode>() * rhs);
VERIFY_IS_EQUAL(aliased, expected);
}
template <typename Scalar, int Order>
void scaled_permutation_product() {
using Mat = Matrix<Scalar, 3, 3, Order>;
Mat matrix;
matrix << 1, 2, 3, 4, 5, 6, 7, 8, 9;
PermutationMatrix<3> permutation;
permutation.indices() << 2, 0, 1;
Mat expected;
for (Index j = 0; j < 3; ++j)
for (Index i = 0; i < 3; ++i) expected(permutation.indices()(i), j) = Scalar(3) * matrix(i, j);
check_scaled_product(Scalar(3) * (permutation * matrix), expected);
Mat aliased = matrix;
aliased = Scalar(3) * (permutation * aliased);
VERIFY_IS_EQUAL(aliased, expected);
for (Index j = 0; j < 3; ++j)
for (Index i = 0; i < 3; ++i) expected(i, j) = Scalar(3) * matrix(permutation.indices()(i), j);
check_scaled_product(Scalar(3) * (permutation.inverse() * matrix), expected);
}
template <int Order>
void scaled_structured_product() {
using Scalar = std::complex<double>;
using Mat = Matrix<Scalar, 3, 3, Order>;
Mat matrix;
matrix << Scalar(1), Scalar(2, 1), Scalar(3, 2), Scalar(4, 3), Scalar(5), Scalar(6, 4), Scalar(7, 5), Scalar(8, 6),
Scalar(9);
const Scalar alpha(2, 3);
const Mat rhs = Mat::Constant(Scalar(2, 1));
const Matrix<Scalar, 3, 1> diagonal = Matrix<Scalar, 3, 1>::Constant(Scalar(3, 2));
Mat expected;
for (Index j = 0; j < 3; ++j)
for (Index i = 0; i < 3; ++i) expected(i, j) = alpha * (diagonal(i) * matrix(i, j));
check_scaled_product(alpha * (diagonal.asDiagonal() * matrix), expected);
const DiagonalMatrix<Scalar, 3> ownedDiagonal(diagonal);
check_scaled_product(alpha * (ownedDiagonal * matrix), expected);
expected.setZero();
for (Index j = 0; j < 3; ++j)
for (Index i = 0; i < 3; ++i)
for (Index k = 0; k <= i; ++k) expected(i, j) += alpha * (matrix(i, k) * rhs(k, j));
check_scaled_product(alpha * (matrix.template triangularView<Lower>() * rhs), expected);
expected.setZero();
for (Index j = 0; j < 3; ++j)
for (Index i = 0; i < 3; ++i)
for (Index k = 0; k < 3; ++k) {
const Scalar value = i >= k ? matrix(i, k) : numext::conj(matrix(k, i));
expected(i, j) += alpha * (value * rhs(k, j));
}
check_scaled_product(alpha * (matrix.template selfadjointView<Lower>() * rhs), expected);
}
template <int Mode, int Order>
void scaled_selfadjoint_diagonal_product() {
using Scalar = std::complex<double>;
using Mat = Matrix<Scalar, 3, 3, Order>;
Mat matrix;
matrix << Scalar(1), Scalar(2, 1), Scalar(3, 2), Scalar(4, 3), Scalar(5), Scalar(6, 4), Scalar(7, 5), Scalar(8, 6),
Scalar(9);
Matrix<Scalar, 3, 1> diagonal;
diagonal << Scalar(1, -1), Scalar(2, 3), Scalar(-4, 2);
const Scalar alpha(2, 3);
Mat expected, expectedLeft;
for (Index j = 0; j < 3; ++j) {
for (Index i = 0; i < 3; ++i) {
const bool stored = Mode == Lower ? i >= j : i <= j;
const Scalar value = stored ? matrix(i, j) : numext::conj(matrix(j, i));
expected(i, j) = alpha * (value * diagonal(j));
expectedLeft(i, j) = alpha * (diagonal(i) * value);
}
}
check_scaled_product(alpha * (matrix.template selfadjointView<Mode>() * diagonal.asDiagonal()), expected);
const DiagonalMatrix<Scalar, 3> ownedDiagonal(diagonal);
check_scaled_product(alpha * (matrix.template selfadjointView<Mode>() * ownedDiagonal), expected);
check_scaled_product(alpha * (diagonal.asDiagonal() * matrix.template selfadjointView<Mode>()), expectedLeft);
Mat aliased = matrix;
aliased = alpha * (aliased.template selfadjointView<Mode>() * diagonal.asDiagonal()) + Mat::Zero();
VERIFY_IS_EQUAL(aliased, expected);
}
EIGEN_DECLARE_TEST(product_evaluators) {
for (int repeat = 0; repeat < g_repeat; ++repeat) {
CALL_SUBTEST_1((scaled_unit_triangular_product<double, UnitLower, ColMajor>()));
CALL_SUBTEST_1((scaled_unit_triangular_product<double, UnitLower, RowMajor>()));
CALL_SUBTEST_1((scaled_unit_triangular_product<double, UnitUpper, ColMajor>()));
CALL_SUBTEST_1((scaled_unit_triangular_product<double, UnitUpper, RowMajor>()));
CALL_SUBTEST_1((scaled_unit_triangular_product<std::complex<double>, UnitLower, ColMajor>()));
CALL_SUBTEST_1((scaled_unit_triangular_product<std::complex<double>, UnitUpper, RowMajor>()));
CALL_SUBTEST_2((scaled_permutation_product<double, ColMajor>()));
CALL_SUBTEST_2((scaled_permutation_product<double, RowMajor>()));
CALL_SUBTEST_2((scaled_permutation_product<std::complex<double>, ColMajor>()));
CALL_SUBTEST_2((scaled_permutation_product<std::complex<double>, RowMajor>()));
CALL_SUBTEST_3((scaled_structured_product<ColMajor>()));
CALL_SUBTEST_3((scaled_structured_product<RowMajor>()));
CALL_SUBTEST_3((scaled_selfadjoint_diagonal_product<Lower, ColMajor>()));
CALL_SUBTEST_3((scaled_selfadjoint_diagonal_product<Lower, RowMajor>()));
CALL_SUBTEST_3((scaled_selfadjoint_diagonal_product<Upper, ColMajor>()));
CALL_SUBTEST_3((scaled_selfadjoint_diagonal_product<Upper, RowMajor>()));
}
}