1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_SOLVETRIANGULAR_H
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_SOLVETRIANGULAR_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Forward declarations:
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// The following two routines are implemented in the products/TriangularSolver*.h files
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename LhsScalar, typename RhsScalar, typename Index, int Side, int Mode, bool Conjugate, int StorageOrder>
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solve_vector;
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate <typename Scalar, typename Index, int Side, int Mode, bool Conjugate, int TriStorageOrder, int OtherStorageOrder>
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solve_matrix;
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// small helper struct extracting some traits on the underlying solver operation
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs, int Side>
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass trsolve_traits
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  private:
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    enum {
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      RhsIsVectorAtCompileTime = (Side==OnTheLeft ? Rhs::ColsAtCompileTime : Rhs::RowsAtCompileTime)==1
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    };
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    enum {
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Unrolling   = (RhsIsVectorAtCompileTime && Rhs::SizeAtCompileTime != Dynamic && Rhs::SizeAtCompileTime <= 8)
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                  ? CompleteUnrolling : NoUnrolling,
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      RhsVectors  = RhsIsVectorAtCompileTime ? 1 : Dynamic
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    };
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs,
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int Side, // can be OnTheLeft/OnTheRight
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int Mode, // can be Upper/Lower | UnitDiag
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int Unrolling = trsolve_traits<Lhs,Rhs,Side>::Unrolling,
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int RhsVectors = trsolve_traits<Lhs,Rhs,Side>::RhsVectors
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  >
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_selector;
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs, int Side, int Mode>
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,1>
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Lhs::Scalar LhsScalar;
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Rhs::Scalar RhsScalar;
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef blas_traits<Lhs> LhsProductTraits;
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename LhsProductTraits::ExtractType ActualLhsType;
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Map<Matrix<RhsScalar,Dynamic,1>, Aligned> MappedRhs;
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs& lhs, Rhs& rhs)
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ActualLhsType actualLhs = LhsProductTraits::extract(lhs);
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // FIXME find a way to allow an inner stride if packet_traits<Scalar>::size==1
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    bool useRhsDirectly = Rhs::InnerStrideAtCompileTime==1 || rhs.innerStride()==1;
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhs,rhs.size(),
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                                                  (useRhsDirectly ? rhs.data() : 0));
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if(!useRhsDirectly)
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      MappedRhs(actualRhs,rhs.size()) = rhs;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    triangular_solve_vector<LhsScalar, RhsScalar, Index, Side, Mode, LhsProductTraits::NeedToConjugate,
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                            (int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor>
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ::run(actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhs);
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if(!useRhsDirectly)
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      rhs = MappedRhs(actualRhs, rhs.size());
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// the rhs is a matrix
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs, int Side, int Mode>
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,Dynamic>
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Rhs::Scalar Scalar;
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef blas_traits<Lhs> LhsProductTraits;
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename LhsProductTraits::DirectLinearAccessType ActualLhsType;
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs& lhs, Rhs& rhs)
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typename internal::add_const_on_value_type<ActualLhsType>::type actualLhs = LhsProductTraits::extract(lhs);
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index size = lhs.rows();
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index othersize = Side==OnTheLeft? rhs.cols() : rhs.rows();
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef internal::gemm_blocking_space<(Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar,
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              Rhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxRowsAtCompileTime,4> BlockingType;
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    BlockingType blocking(rhs.rows(), rhs.cols(), size, 1, false);
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    triangular_solve_matrix<Scalar,Index,Side,Mode,LhsProductTraits::NeedToConjugate,(int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor,
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                               (Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor>
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride(), blocking);
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/***************************************************************************
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* meta-unrolling implementation
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<typename Lhs, typename Rhs, int Mode, int LoopIndex, int Size,
1112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang         bool Stop = LoopIndex==Size>
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_unroller;
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<typename Lhs, typename Rhs, int Mode, int LoopIndex, int Size>
1152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstruct triangular_solver_unroller<Lhs,Rhs,Mode,LoopIndex,Size,false> {
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum {
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    IsLower = ((Mode&Lower)==Lower),
1182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    DiagIndex  = IsLower ? LoopIndex : Size - LoopIndex - 1,
1192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    StartIndex = IsLower ? 0         : DiagIndex+1
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  };
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs& lhs, Rhs& rhs)
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
1232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    if (LoopIndex>0)
1242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      rhs.coeffRef(DiagIndex) -= lhs.row(DiagIndex).template segment<LoopIndex>(StartIndex).transpose()
1252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang                                .cwiseProduct(rhs.template segment<LoopIndex>(StartIndex)).sum();
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if(!(Mode & UnitDiag))
1282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      rhs.coeffRef(DiagIndex) /= lhs.coeff(DiagIndex,DiagIndex);
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    triangular_solver_unroller<Lhs,Rhs,Mode,LoopIndex+1,Size>::run(lhs,rhs);
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<typename Lhs, typename Rhs, int Mode, int LoopIndex, int Size>
1352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstruct triangular_solver_unroller<Lhs,Rhs,Mode,LoopIndex,Size,true> {
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs&, Rhs&) {}
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs, int Mode>
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_selector<Lhs,Rhs,OnTheLeft,Mode,CompleteUnrolling,1> {
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs& lhs, Rhs& rhs)
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  { triangular_solver_unroller<Lhs,Rhs,Mode,0,Rhs::SizeAtCompileTime>::run(lhs,rhs); }
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Lhs, typename Rhs, int Mode>
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct triangular_solver_selector<Lhs,Rhs,OnTheRight,Mode,CompleteUnrolling,1> {
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void run(const Lhs& lhs, Rhs& rhs)
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Transpose<const Lhs> trLhs(lhs);
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Transpose<Rhs> trRhs(rhs);
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    triangular_solver_unroller<Transpose<const Lhs>,Transpose<Rhs>,
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                              ((Mode&Upper)==Upper ? Lower : Upper) | (Mode&UnitDiag),
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath                              0,Rhs::SizeAtCompileTime>::run(trLhs,trRhs);
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace internal
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/***************************************************************************
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath* TriangularView methods
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath***************************************************************************/
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#ifndef EIGEN_PARSED_BY_DOXYGEN
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, unsigned int Mode>
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<int Side, typename OtherDerived>
1672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangvoid TriangularViewImpl<MatrixType,Mode,Dense>::solveInPlace(const MatrixBase<OtherDerived>& _other) const
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  OtherDerived& other = _other.const_cast_derived();
1702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_assert( derived().cols() == derived().rows() && ((Side==OnTheLeft && derived().cols() == other.rows()) || (Side==OnTheRight && derived().cols() == other.cols())) );
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  eigen_assert((!(Mode & ZeroDiag)) && bool(Mode & (Upper|Lower)));
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  enum { copy = (internal::traits<OtherDerived>::Flags & RowMajorBit)  && OtherDerived::IsVectorAtCompileTime && OtherDerived::SizeAtCompileTime!=1};
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename internal::conditional<copy,
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typename internal::plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::type OtherCopy;
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  OtherCopy otherCopy(other);
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  internal::triangular_solver_selector<MatrixType, typename internal::remove_reference<OtherCopy>::type,
1792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Side, Mode>::run(derived().nestedExpression(), otherCopy);
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (copy)
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    other = otherCopy;
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived, unsigned int Mode>
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<int Side, typename Other>
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathconst internal::triangular_solve_retval<Side,TriangularView<Derived,Mode>,Other>
1882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao WangTriangularViewImpl<Derived,Mode,Dense>::solve(const MatrixBase<Other>& other) const
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
1902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  return internal::triangular_solve_retval<Side,TriangularViewType,Other>(derived(), other.derived());
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
1922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<int Side, typename TriangularType, typename Rhs>
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct traits<triangular_solve_retval<Side, TriangularType, Rhs> >
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename internal::plain_matrix_type_column_major<Rhs>::type ReturnType;
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<int Side, typename TriangularType, typename Rhs> struct triangular_solve_retval
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath : public ReturnByValue<triangular_solve_retval<Side, TriangularType, Rhs> >
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename remove_all<typename Rhs::Nested>::type RhsNestedCleaned;
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef ReturnByValue<triangular_solve_retval> Base;
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  triangular_solve_retval(const TriangularType& tri, const Rhs& rhs)
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    : m_triangularMatrix(tri), m_rhs(rhs)
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {}
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline Index rows() const { return m_rhs.rows(); }
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline Index cols() const { return m_rhs.cols(); }
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  template<typename Dest> inline void evalTo(Dest& dst) const
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
2182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    if(!is_same_dense(dst,m_rhs))
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      dst = m_rhs;
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_triangularMatrix.template solveInPlace<Side>(dst);
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const TriangularType& m_triangularMatrix;
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typename Rhs::Nested m_rhs;
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // namespace internal
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_SOLVETRIANGULAR_H
233