BlockHouseholder.h (4784B)
1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2010 Vincent Lejeune 5 // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_BLOCK_HOUSEHOLDER_H 12 #define EIGEN_BLOCK_HOUSEHOLDER_H 13 14 // This file contains some helper function to deal with block householder reflectors 15 16 namespace Eigen { 17 18 namespace internal { 19 20 /** \internal */ 21 // template<typename TriangularFactorType,typename VectorsType,typename CoeffsType> 22 // void make_block_householder_triangular_factor(TriangularFactorType& triFactor, const VectorsType& vectors, const CoeffsType& hCoeffs) 23 // { 24 // typedef typename VectorsType::Scalar Scalar; 25 // const Index nbVecs = vectors.cols(); 26 // eigen_assert(triFactor.rows() == nbVecs && triFactor.cols() == nbVecs && vectors.rows()>=nbVecs); 27 // 28 // for(Index i = 0; i < nbVecs; i++) 29 // { 30 // Index rs = vectors.rows() - i; 31 // // Warning, note that hCoeffs may alias with vectors. 32 // // It is then necessary to copy it before modifying vectors(i,i). 33 // typename CoeffsType::Scalar h = hCoeffs(i); 34 // // This hack permits to pass trough nested Block<> and Transpose<> expressions. 35 // Scalar *Vii_ptr = const_cast<Scalar*>(vectors.data() + vectors.outerStride()*i + vectors.innerStride()*i); 36 // Scalar Vii = *Vii_ptr; 37 // *Vii_ptr = Scalar(1); 38 // triFactor.col(i).head(i).noalias() = -h * vectors.block(i, 0, rs, i).adjoint() 39 // * vectors.col(i).tail(rs); 40 // *Vii_ptr = Vii; 41 // // FIXME add .noalias() once the triangular product can work inplace 42 // triFactor.col(i).head(i) = triFactor.block(0,0,i,i).template triangularView<Upper>() 43 // * triFactor.col(i).head(i); 44 // triFactor(i,i) = hCoeffs(i); 45 // } 46 // } 47 48 /** \internal */ 49 // This variant avoid modifications in vectors 50 template<typename TriangularFactorType,typename VectorsType,typename CoeffsType> 51 void make_block_householder_triangular_factor(TriangularFactorType& triFactor, const VectorsType& vectors, const CoeffsType& hCoeffs) 52 { 53 const Index nbVecs = vectors.cols(); 54 eigen_assert(triFactor.rows() == nbVecs && triFactor.cols() == nbVecs && vectors.rows()>=nbVecs); 55 56 for(Index i = nbVecs-1; i >=0 ; --i) 57 { 58 Index rs = vectors.rows() - i - 1; 59 Index rt = nbVecs-i-1; 60 61 if(rt>0) 62 { 63 triFactor.row(i).tail(rt).noalias() = -hCoeffs(i) * vectors.col(i).tail(rs).adjoint() 64 * vectors.bottomRightCorner(rs, rt).template triangularView<UnitLower>(); 65 66 // FIXME use the following line with .noalias() once the triangular product can work inplace 67 // triFactor.row(i).tail(rt) = triFactor.row(i).tail(rt) * triFactor.bottomRightCorner(rt,rt).template triangularView<Upper>(); 68 for(Index j=nbVecs-1; j>i; --j) 69 { 70 typename TriangularFactorType::Scalar z = triFactor(i,j); 71 triFactor(i,j) = z * triFactor(j,j); 72 if(nbVecs-j-1>0) 73 triFactor.row(i).tail(nbVecs-j-1) += z * triFactor.row(j).tail(nbVecs-j-1); 74 } 75 76 } 77 triFactor(i,i) = hCoeffs(i); 78 } 79 } 80 81 /** \internal 82 * if forward then perform mat = H0 * H1 * H2 * mat 83 * otherwise perform mat = H2 * H1 * H0 * mat 84 */ 85 template<typename MatrixType,typename VectorsType,typename CoeffsType> 86 void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vectors, const CoeffsType& hCoeffs, bool forward) 87 { 88 enum { TFactorSize = MatrixType::ColsAtCompileTime }; 89 Index nbVecs = vectors.cols(); 90 Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize, RowMajor> T(nbVecs,nbVecs); 91 92 if(forward) make_block_householder_triangular_factor(T, vectors, hCoeffs); 93 else make_block_householder_triangular_factor(T, vectors, hCoeffs.conjugate()); 94 const TriangularView<const VectorsType, UnitLower> V(vectors); 95 96 // A -= V T V^* A 97 Matrix<typename MatrixType::Scalar,VectorsType::ColsAtCompileTime,MatrixType::ColsAtCompileTime, 98 (VectorsType::MaxColsAtCompileTime==1 && MatrixType::MaxColsAtCompileTime!=1)?RowMajor:ColMajor, 99 VectorsType::MaxColsAtCompileTime,MatrixType::MaxColsAtCompileTime> tmp = V.adjoint() * mat; 100 // FIXME add .noalias() once the triangular product can work inplace 101 if(forward) tmp = T.template triangularView<Upper>() * tmp; 102 else tmp = T.template triangularView<Upper>().adjoint() * tmp; 103 mat.noalias() -= V * tmp; 104 } 105 106 } // end namespace internal 107 108 } // end namespace Eigen 109 110 #endif // EIGEN_BLOCK_HOUSEHOLDER_H