00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_SPARSETRIANGULARSOLVER_H
00026 #define EIGEN_SPARSETRIANGULARSOLVER_H
00027
00028
00029 template<typename Lhs, typename Rhs>
00030 struct ei_solve_triangular_selector<Lhs,Rhs,LowerTriangular,RowMajor|IsSparse>
00031 {
00032 typedef typename Rhs::Scalar Scalar;
00033 static void run(const Lhs& lhs, Rhs& other)
00034 {
00035 for(int col=0 ; col<other.cols() ; ++col)
00036 {
00037 for(int i=0; i<lhs.rows(); ++i)
00038 {
00039 Scalar tmp = other.coeff(i,col);
00040 Scalar lastVal = 0;
00041 int lastIndex = 0;
00042 for(typename Lhs::InnerIterator it(lhs, i); it; ++it)
00043 {
00044 lastVal = it.value();
00045 lastIndex = it.index();
00046 if(lastIndex == i)
00047 break;
00048 tmp -= lastVal * other.coeff(lastIndex,col);
00049 }
00050
00051 if (Lhs::Flags & UnitDiagBit)
00052 other.coeffRef(i,col) = tmp;
00053 else
00054 {
00055 ei_assert(lastIndex==i);
00056 other.coeffRef(i,col) = tmp/lastVal;
00057 }
00058 }
00059 }
00060 }
00061 };
00062
00063
00064 template<typename Lhs, typename Rhs>
00065 struct ei_solve_triangular_selector<Lhs,Rhs,UpperTriangular,RowMajor|IsSparse>
00066 {
00067 typedef typename Rhs::Scalar Scalar;
00068 static void run(const Lhs& lhs, Rhs& other)
00069 {
00070 for(int col=0 ; col<other.cols() ; ++col)
00071 {
00072 for(int i=lhs.rows()-1 ; i>=0 ; --i)
00073 {
00074 Scalar tmp = other.coeff(i,col);
00075 typename Lhs::InnerIterator it(lhs, i);
00076 if (it.index() == i)
00077 ++it;
00078 for(; it; ++it)
00079 {
00080 tmp -= it.value() * other.coeff(it.index(),col);
00081 }
00082
00083 if (Lhs::Flags & UnitDiagBit)
00084 other.coeffRef(i,col) = tmp;
00085 else
00086 {
00087 typename Lhs::InnerIterator it(lhs, i);
00088 ei_assert(it.index() == i);
00089 other.coeffRef(i,col) = tmp/it.value();
00090 }
00091 }
00092 }
00093 }
00094 };
00095
00096
00097 template<typename Lhs, typename Rhs>
00098 struct ei_solve_triangular_selector<Lhs,Rhs,LowerTriangular,ColMajor|IsSparse>
00099 {
00100 typedef typename Rhs::Scalar Scalar;
00101 static void run(const Lhs& lhs, Rhs& other)
00102 {
00103 for(int col=0 ; col<other.cols() ; ++col)
00104 {
00105 for(int i=0; i<lhs.cols(); ++i)
00106 {
00107 typename Lhs::InnerIterator it(lhs, i);
00108 if(!(Lhs::Flags & UnitDiagBit))
00109 {
00110
00111 ei_assert(it.index()==i);
00112 other.coeffRef(i,col) /= it.value();
00113 }
00114 Scalar tmp = other.coeffRef(i,col);
00115 if (it.index()==i)
00116 ++it;
00117 for(; it; ++it)
00118 other.coeffRef(it.index(), col) -= tmp * it.value();
00119 }
00120 }
00121 }
00122 };
00123
00124
00125 template<typename Lhs, typename Rhs>
00126 struct ei_solve_triangular_selector<Lhs,Rhs,UpperTriangular,ColMajor|IsSparse>
00127 {
00128 typedef typename Rhs::Scalar Scalar;
00129 static void run(const Lhs& lhs, Rhs& other)
00130 {
00131 for(int col=0 ; col<other.cols() ; ++col)
00132 {
00133 for(int i=lhs.cols()-1; i>=0; --i)
00134 {
00135 if(!(Lhs::Flags & UnitDiagBit))
00136 {
00137
00138
00139 other.coeffRef(i,col) /= lhs.coeff(i,i);
00140 }
00141 Scalar tmp = other.coeffRef(i,col);
00142 typename Lhs::InnerIterator it(lhs, i);
00143 for(; it && it.index()<i; ++it)
00144 other.coeffRef(it.index(), col) -= tmp * it.value();
00145 }
00146 }
00147 }
00148 };
00149
00150 template<typename Derived>
00151 template<typename OtherDerived>
00152 void SparseMatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
00153 {
00154 ei_assert(derived().cols() == derived().rows());
00155 ei_assert(derived().cols() == other.rows());
00156 ei_assert(!(Flags & ZeroDiagBit));
00157 ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
00158
00159 enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
00160
00161 typedef typename ei_meta_if<copy,
00162 typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
00163 OtherCopy otherCopy(other.derived());
00164
00165 ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
00166
00167 if (copy)
00168 other = otherCopy;
00169 }
00170
00171 template<typename Derived>
00172 template<typename OtherDerived>
00173 typename ei_plain_matrix_type_column_major<OtherDerived>::type
00174 SparseMatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
00175 {
00176 typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
00177 solveTriangularInPlace(res);
00178 return res;
00179 }
00180
00181 #endif // EIGEN_SPARSETRIANGULARSOLVER_H