RFFGen
 All Classes Namespaces Files Functions Typedefs Enumerations Groups
determinant.hh
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the C++-library RFFGen. */
4 /* Copyright 2015 Lars Lubkoll */
5 /* */
6 /* RFFGen is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* RFFGen is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with RFFGen. If not, see <http://www.gnu.org/licenses/>. */
18 /* */
19 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20 
21 #ifndef RFFGEN_LINEAR_ALGEBRA_DETERMINANT_HH
22 #define RFFGEN_LINEAR_ALGEBRA_DETERMINANT_HH
23 
24 #include <type_traits>
25 #include <utility>
26 
27 #include "dimension.hh"
28 #include "rowsAndCols.hh"
29 #include "../Util/at.hh"
30 #include "../Util/base.hh"
31 #include "../Util/chainer.hh"
32 #include "../Util/exceptions.hh"
33 
34 namespace RFFGen
35 {
39  namespace Concepts { template <class> struct SymmetricMatrixConceptCheck; }
44  namespace LinearAlgebra
45  {
49  namespace Detail
50  {
51  template < class Matrix >
52  inline auto composeResult(Matrix const& A, Matrix const& B)
53  {
54  return at(A,0,0) * at(B,1,1) + at(A,1,1) * at(B,0,0) - ( at(A,0,1) * at(B,1,0) + at(A,1,0) * at(B,0,1) );
55  }
56 
57  template < class Matrix >
58  inline auto composeResult(Matrix const& dA, Matrix const& dB, Matrix const& dC)
59  {
60  return at(dB,1,1) * ( at(dA,0,0) * at(dC,2,2) - at(dA,2,0) * at(dC,0,2) ) +
61  at(dB,1,2) * ( at(dA,0,1) * at(dC,2,0) - at(dA,2,1) * at(dC,0,0) ) +
62  at(dB,1,0) * ( at(dA,0,2) * at(dC,2,1) - at(dA,2,2) * at(dC,0,1) );
63  }
64 
65  template < class Matrix >
66  inline auto composeSemiSymmetricResult(Matrix const& dA, Matrix const& dB, Matrix const& dC)
67  {
68  return at(dB,1,1) * ( at(dA,0,0) * at(dC,2,2) + at(dA,2,2) * at(dC,0,0) - at(dA,2,0) * at(dC,0,2) - at(dA,0,2) * at(dC,2,0) ) +
69  at(dB,1,2) * ( at(dA,0,1) * at(dC,2,0) + at(dA,2,0) * at(dC,0,1) - at(dA,2,1) * at(dC,0,0) - at(dA,0,0) * at(dC,2,1) ) +
70  at(dB,1,0) * ( at(dA,0,2) * at(dC,2,1) + at(dA,2,1) * at(dC,0,2) - at(dA,2,2) * at(dC,0,1) - at(dA,0,1) * at(dC,2,2) );
71  }
72 
73  template <class Matrix, int dim, class = Concepts::SymmetricMatrixConceptCheck<Matrix> >
74  class DeterminantImpl;
75 
76  template<class Matrix>
77  class DeterminantImpl< Matrix , 2 , Concepts::SymmetricMatrixConceptCheck<Matrix> >
78  : public Base , public Chainer< DeterminantImpl<Matrix,2,Concepts::SymmetricMatrixConceptCheck<Matrix> > >
79  {
80  public:
81  DeterminantImpl() = default;
82 
83  explicit DeterminantImpl(Matrix const& A_) { update(A_); }
84 
85  void update(Matrix const& A_)
86  {
87  A = A_;
88  resultOfD0 = at(A,0,0) * at(A,1,1) - at(A,0,1) * at(A,1,0);//A[0][0] * A[1][1] - A[0][1] * A[1][0];
89  }
90 
91  auto d0() const
92  {
93  return resultOfD0;
94  }
95 
96  template <int>
97  auto d1(Matrix const& dA1) const
98  {
99  return composeResult(A, dA1);
100  }
101 
102  template <int,int>
103  auto d2(Matrix const& dA1, Matrix const& dA2) const
104  {
105  return composeResult(dA2,dA1);
106  }
107 
108  private:
109  Matrix A;
110  std::decay_t< at_t<Matrix> > resultOfD0 = 0.;
111  };
112 
113  template <class Matrix>
114  class DeterminantImpl<Matrix,3,Concepts::SymmetricMatrixConceptCheck<Matrix> >
115  : public Base , public Chainer< DeterminantImpl<Matrix,3,Concepts::SymmetricMatrixConceptCheck<Matrix> > >
116  {
117  public:
118  DeterminantImpl() = default;
119 
120  DeterminantImpl(Matrix const& A_) { update(A_); }
121 
122  void update(Matrix const& A_)
123  {
124  A = A_;
125  resultOfD0 = composeResult(A,A,A);
126  }
127 
128  auto d0() const { return resultOfD0; }
129 
130  template <int>
131  auto d1(Matrix const& dA1) const
132  {
133  return composeResult(dA1,A,A) + composeResult(A,dA1,A) + composeResult(A,A,dA1);
134  }
135 
136  template <int,int>
137  auto d2(Matrix const& dA1, Matrix const& dA2) const
138  {
139  return composeSemiSymmetricResult(A,dA2,dA1) + composeSemiSymmetricResult(dA1,A,dA2) + composeSemiSymmetricResult(A,dA1,dA2);
140  }
141 
142  template <int,int,int>
143  auto d3(Matrix const& dA1, Matrix const& dA2, Matrix const& dA3) const
144  {
145  return composeSemiSymmetricResult(dA1,dA2,dA3) + composeSemiSymmetricResult(dA1,dA3,dA2) + composeSemiSymmetricResult(dA2,dA1,dA3);
146  }
147 
148  private:
149  Matrix A;
150  std::decay_t< at_t<Matrix> > resultOfD0 = 0.;
151  };
152  }
161  template <class Matrix>
162  using ConstantSizeDeterminant = Detail::DeterminantImpl<Matrix,dimension<Matrix>()>;
163 
168  template <class Matrix>
170  public Base , public Chainer< DynamicSizeDeterminant<Matrix> >
171  {
172  public:
173  DynamicSizeDeterminant() = default;
174 
176  DynamicSizeDeterminant(Matrix const& A) : dim(rows(A))
177  {
178  update(A);
179  }
180 
182  void update(Matrix const& A)
183  {
184 #ifdef RFFGEN_ENABLE_EXCEPTIONS
185  if( rows(A) != cols(A) ) throw NonSymmetricMatrixException("DynamicSizeDeterminant",rows(A),cols(A),__FILE__,__LINE__);
186 #endif
187  dim = rows(A);
188  if( dim == 2 ) det2D.update(A);
189  if( dim == 3 ) det3D.update(A);
190  }
191 
193  auto d0() const { return ( dim==2 ) ? det2D.d0() : det3D.d0(); }
194 
196  template <int id>
197  auto d1(Matrix const& dA1) const
198  {
199  return ( dim==2 ) ? det2D.template d1<id>(dA1) : det3D.template d1<id>(dA1) ;
200  }
201 
203  template < int idx , int idy >
204  auto d2(Matrix const& dA1, Matrix const& dA2) const
205  {
206  return ( dim==2 ) ? det2D.template d2<idx,idy>(dA1,dA2) : det3D.template d2<idx,idy>(dA1,dA2);
207  }
208 
210  template < int idx , int idy , int idz >
211  auto d3(Matrix const& dA1, Matrix const& dA2, Matrix const& dA3) const
212  {
213  return ( dim==2 ) ? 0 : det3D.template d3<idx,idy,idz>(dA1,dA2,dA3);
214  }
215 
216  private:
217  int dim = 0;
218  Detail::DeterminantImpl<Matrix,2> det2D;
219  Detail::DeterminantImpl<Matrix,3> det3D;
220  };
229  template < class Matrix >
230  using Determinant = std::conditional_t< Checks::isConstantSizeMatrix<Matrix>() , ConstantSizeDeterminant<Matrix> , DynamicSizeDeterminant<Matrix> >;
231 
236  template<class Matrix>
237  auto det(Matrix const& A)
238  {
239  return Determinant<Matrix>(A);
240  }
241 
246  template<class Matrix>
247  auto determinant(Matrix const& A)
248  {
249  return Determinant<Matrix>(A)();
250  }
251  }
252 }
253 
254 #endif // RFFGEN_LINEAR_ALGEBRA_DETERMINANT_HH
auto det(Matrix const &A)
Convenient generation of Determinant<Matrix>(A).
Definition: determinant.hh:237
auto d2(Matrix const &dA1, Matrix const &dA2) const
Second (directional) derivative.
Definition: determinant.hh:204
Exception for non-symmetric matrices if symmetric matrices are required.
Definition: exceptions.hh:62
Base class for functions satisfying FunctionConcept. Required for enabling the operators in generate...
Definition: base.hh:27
Determinant of dynamic size matrix with first three derivatives.
Definition: determinant.hh:169
void update(Matrix const &A)
Reset point of evaluation.
Definition: determinant.hh:182
auto d3(Matrix const &dA1, Matrix const &dA2, Matrix const &dA3) const
Third (directional) derivative.
Definition: determinant.hh:211
auto determinant(Matrix const &A)
Convenient computation of .
Definition: determinant.hh:247
Detail::DeterminantImpl< Matrix, dimension< Matrix >()> ConstantSizeDeterminant
Determinant of constant size matrix with first three derivatives.
Definition: determinant.hh:162
auto d1(Matrix const &dA1) const
First (directional) derivative.
Definition: determinant.hh:197
DynamicSizeDeterminant(Matrix const &A)
Constructor.
Definition: determinant.hh:176
std::conditional_t< Checks::isConstantSizeMatrix< Matrix >(), ConstantSizeDeterminant< Matrix >, DynamicSizeDeterminant< Matrix > > Determinant
Determinant with first three derivatives.
Definition: determinant.hh:230
auto d0() const
Function value.
Definition: determinant.hh:193