// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINTRANK2UPTADE_H #define EIGEN_SELFADJOINTRANK2UPTADE_H // IWYU pragma: private #include "../InternalHeaderCheck.h" namespace Eigen { namespace internal { /* Optimized selfadjoint matrix += alpha * uv' + conj(alpha)*vu' * It corresponds to the Level2 syr2 BLAS routine */ template struct selfadjoint_rank2_update_selector; template struct selfadjoint_rank2_update_selector { static EIGEN_DEVICE_FUNC void run(Scalar* mat, Index stride, const UType& u, const VType& v, const Scalar& alpha) { const Index size = u.size(); for (Index i = 0; i < size; ++i) { Map>(mat + stride * i + i, size - i) += (numext::conj(alpha) * numext::conj(u.coeff(i))) * v.tail(size - i) + (alpha * numext::conj(v.coeff(i))) * u.tail(size - i); } } }; template struct selfadjoint_rank2_update_selector { static void run(Scalar* mat, Index stride, const UType& u, const VType& v, const Scalar& alpha) { const Index size = u.size(); for (Index i = 0; i < size; ++i) Map>(mat + stride * i, i + 1) += (numext::conj(alpha) * numext::conj(u.coeff(i))) * v.head(i + 1) + (alpha * numext::conj(v.coeff(i))) * u.head(i + 1); } }; template using conj_expr_if = std::conditional::Scalar>, T>>; } // end namespace internal template template EIGEN_DEVICE_FUNC SelfAdjointView& SelfAdjointView::rankUpdate( const MatrixBase& u, const MatrixBase& v, const Scalar& alpha) { typedef internal::blas_traits UBlasTraits; typedef typename UBlasTraits::DirectLinearAccessType ActualUType; typedef internal::remove_all_t ActualUType_; internal::add_const_on_value_type_t actualU = UBlasTraits::extract(u.derived()); typedef internal::blas_traits VBlasTraits; typedef typename VBlasTraits::DirectLinearAccessType ActualVType; typedef internal::remove_all_t ActualVType_; internal::add_const_on_value_type_t actualV = VBlasTraits::extract(v.derived()); // If MatrixType is row major, then we use the routine for lower triangular in the upper triangular case and // vice versa, and take the complex conjugate of all coefficients and vector entries. enum { IsRowMajor = (internal::traits::Flags & RowMajorBit) ? 1 : 0 }; Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u.derived()) * numext::conj(VBlasTraits::extractScalarFactor(v.derived())); if (IsRowMajor) actualAlpha = numext::conj(actualAlpha); typedef internal::remove_all_t< typename internal::conj_expr_if::type> UType; typedef internal::remove_all_t< typename internal::conj_expr_if::type> VType; internal::selfadjoint_rank2_update_selector::run(_expression().const_cast_derived().data(), _expression().outerStride(), UType(actualU), VType(actualV), actualAlpha); return *this; } } // end namespace Eigen #endif // EIGEN_SELFADJOINTRANK2UPTADE_H