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_SOLVETRIANGULAR_H
00026 #define EIGEN_SOLVETRIANGULAR_H
00027
00028 template<typename XprType> struct ei_is_part { enum {value=false}; };
00029 template<typename XprType, unsigned int Mode> struct ei_is_part<Part<XprType,Mode> > { enum {value=true}; };
00030
00031 template<typename Lhs, typename Rhs,
00032 int TriangularPart = (int(Lhs::Flags) & LowerTriangularBit)
00033 ? LowerTriangular
00034 : (int(Lhs::Flags) & UpperTriangularBit)
00035 ? UpperTriangular
00036 : -1,
00037 int StorageOrder = ei_is_part<Lhs>::value ? -1
00038 : int(Lhs::Flags) & int(RowMajorBit|SparseBit)
00039 >
00040 struct ei_solve_triangular_selector;
00041
00042
00043 template<typename Lhs, unsigned int LhsMode, typename Rhs, int UpLo, int StorageOrder>
00044 struct ei_solve_triangular_selector<Part<Lhs,LhsMode>,Rhs,UpLo,StorageOrder>
00045 {
00046 static void run(const Part<Lhs,LhsMode>& lhs, Rhs& other)
00047 {
00048 ei_solve_triangular_selector<Flagged<Lhs,LhsMode,0>,Rhs>::run(lhs._expression(), other);
00049 }
00050 };
00051
00052
00053 template<typename Lhs, typename Rhs, int UpLo>
00054 struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
00055 {
00056 typedef typename Rhs::Scalar Scalar;
00057 static void run(const Lhs& lhs, Rhs& other)
00058 {
00059 const bool IsLowerTriangular = (UpLo==LowerTriangular);
00060 const int size = lhs.cols();
00061
00062
00063
00064
00065 int blockyStart = (std::max(size-5,0)/4)*4;
00066 if (IsLowerTriangular)
00067 blockyStart = size - blockyStart;
00068 else
00069 blockyStart -= 1;
00070 for(int c=0 ; c<other.cols() ; ++c)
00071 {
00072
00073 if(!(Lhs::Flags & UnitDiagBit))
00074 {
00075 if (IsLowerTriangular)
00076 other.coeffRef(0,c) = other.coeff(0,c)/lhs.coeff(0, 0);
00077 else
00078 other.coeffRef(size-1,c) = other.coeff(size-1, c)/lhs.coeff(size-1, size-1);
00079 }
00080 for(int i=(IsLowerTriangular ? 1 : size-2); IsLowerTriangular ? i<blockyStart : i>blockyStart; i += (IsLowerTriangular ? 1 : -1) )
00081 {
00082 Scalar tmp = other.coeff(i,c)
00083 - (IsLowerTriangular ? ((lhs.row(i).start(i)) * other.col(c).start(i)).coeff(0,0)
00084 : ((lhs.row(i).end(size-i-1)) * other.col(c).end(size-i-1)).coeff(0,0));
00085 if (Lhs::Flags & UnitDiagBit)
00086 other.coeffRef(i,c) = tmp;
00087 else
00088 other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
00089 }
00090
00091
00092 for(int i=blockyStart; IsLowerTriangular ? i<size : i>0; )
00093 {
00094 int startBlock = i;
00095 int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
00096
00097
00098
00099 Matrix<Scalar,Dynamic,1> btmp(4);
00100 if (IsLowerTriangular)
00101 btmp = lhs.block(startBlock,0,4,i) * other.col(c).start(i);
00102 else
00103 btmp = lhs.block(i-3,i+1,4,size-1-i) * other.col(c).end(size-1-i);
00104
00105
00106
00107
00108 {
00109 Scalar tmp = other.coeff(startBlock,c)-btmp.coeff(IsLowerTriangular?0:3);
00110 if (Lhs::Flags & UnitDiagBit)
00111 other.coeffRef(i,c) = tmp;
00112 else
00113 other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
00114 }
00115
00116 i += IsLowerTriangular ? 1 : -1;
00117 for (;IsLowerTriangular ? i<endBlock : i>endBlock; i += IsLowerTriangular ? 1 : -1)
00118 {
00119 int remainingSize = IsLowerTriangular ? i-startBlock : startBlock-i;
00120 Scalar tmp = other.coeff(i,c)
00121 - btmp.coeff(IsLowerTriangular ? remainingSize : 3-remainingSize)
00122 - ( lhs.row(i).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)
00123 * other.col(c).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)).coeff(0,0);
00124
00125 if (Lhs::Flags & UnitDiagBit)
00126 other.coeffRef(i,c) = tmp;
00127 else
00128 other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
00129 }
00130 }
00131 }
00132 }
00133 };
00134
00135
00136
00137
00138
00139
00140 template<typename Lhs, typename Rhs, int UpLo>
00141 struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
00142 {
00143 typedef typename Rhs::Scalar Scalar;
00144 typedef typename ei_packet_traits<Scalar>::type Packet;
00145 enum { PacketSize = ei_packet_traits<Scalar>::size };
00146
00147 static void run(const Lhs& lhs, Rhs& other)
00148 {
00149 static const bool IsLowerTriangular = (UpLo==LowerTriangular);
00150 const int size = lhs.cols();
00151 for(int c=0 ; c<other.cols() ; ++c)
00152 {
00153
00154
00155
00156
00157 int blockyEnd = (std::max(size-5,0)/4)*4;
00158 if (!IsLowerTriangular)
00159 blockyEnd = size-1 - blockyEnd;
00160 for(int i=IsLowerTriangular ? 0 : size-1; IsLowerTriangular ? i<blockyEnd : i>blockyEnd;)
00161 {
00162
00163
00164
00165 int startBlock = i;
00166 int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
00167 Matrix<Scalar,4,1> btmp;
00168 for (;IsLowerTriangular ? i<endBlock : i>endBlock;
00169 i += IsLowerTriangular ? 1 : -1)
00170 {
00171 if(!(Lhs::Flags & UnitDiagBit))
00172 other.coeffRef(i,c) /= lhs.coeff(i,i);
00173 int remainingSize = IsLowerTriangular ? endBlock-i-1 : i-endBlock-1;
00174 if (remainingSize>0)
00175 other.col(c).segment((IsLowerTriangular ? i : endBlock) + 1, remainingSize) -=
00176 other.coeffRef(i,c)
00177 * Block<Lhs,Dynamic,1>(lhs, (IsLowerTriangular ? i : endBlock) + 1, i, remainingSize, 1);
00178 btmp.coeffRef(IsLowerTriangular ? i-startBlock : remainingSize) = -other.coeffRef(i,c);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 ei_cache_friendly_product_colmajor_times_vector(
00190 IsLowerTriangular ? size-endBlock : endBlock+1,
00191 &(lhs.const_cast_derived().coeffRef(IsLowerTriangular ? endBlock : 0, IsLowerTriangular ? startBlock : endBlock+1)),
00192 lhs.stride(),
00193 btmp, &(other.coeffRef(IsLowerTriangular ? endBlock : 0, c)));
00194
00195
00196
00197
00198
00199
00200 }
00201
00202
00203 int i;
00204 for(i=blockyEnd; IsLowerTriangular ? i<size-1 : i>0; i += (IsLowerTriangular ? 1 : -1) )
00205 {
00206 if(!(Lhs::Flags & UnitDiagBit))
00207 other.coeffRef(i,c) /= lhs.coeff(i,i);
00208
00209
00210
00211
00212 if(IsLowerTriangular)
00213 other.col(c).end(size-i-1) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, i+1,i, size-i-1,1);
00214 else
00215 other.col(c).start(i) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, 0,i, i, 1);
00216 }
00217 if(!(Lhs::Flags & UnitDiagBit))
00218 other.coeffRef(i,c) /= lhs.coeff(i,i);
00219 }
00220 }
00221 };
00222
00232 template<typename Derived>
00233 template<typename OtherDerived>
00234 void MatrixBase<Derived>::solveTriangularInPlace(const MatrixBase<OtherDerived>& _other) const
00235 {
00236 MatrixBase<OtherDerived>& other = _other.const_cast_derived();
00237 ei_assert(derived().cols() == derived().rows());
00238 ei_assert(derived().cols() == other.rows());
00239 ei_assert(!(Flags & ZeroDiagBit));
00240 ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
00241
00242 enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
00243
00244 typedef typename ei_meta_if<copy,
00245 typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
00246 OtherCopy otherCopy(other.derived());
00247
00248 ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
00249
00250 if (copy)
00251 other = otherCopy;
00252 }
00253
00287 template<typename Derived>
00288 template<typename OtherDerived>
00289 typename ei_plain_matrix_type_column_major<OtherDerived>::type
00290 MatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
00291 {
00292 typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
00293 solveTriangularInPlace(res);
00294 return res;
00295 }
00296
00297 #endif // EIGEN_SOLVETRIANGULAR_H