RFFGen
 All Classes Namespaces Files Functions Typedefs Enumerations Groups
trace.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_TRACE_HH
22 #define RFFGEN_LINEAR_ALGEBRA_TRACE_HH
23 
24 #include <type_traits>
25 #include <utility>
26 
27 #include "dimension.hh"
28 #include "rowsAndCols.hh"
29 #include "../Util/base.hh"
30 #include "../Util/at.hh"
31 #include "../Util/exceptions.hh"
32 
33 namespace RFFGen
34 {
38  template <class> struct Chainer;
39  namespace Concepts { template <class> struct SymmetricMatrixConceptCheck; }
44  namespace LinearAlgebra
45  {
49  namespace Detail
50  {
54  template <int>
55  struct ComputeTrace
56  {
57  template <class Matrix>
58  static auto apply(const Matrix& A)
59  {
60  auto val = at(A,0,0);
61  for(int i = 1; i < rows<Matrix>(); ++i) val += at(A,i,i);
62  return val;
63  }
64  };
65 
67  template <>
68  struct ComputeTrace<2>
69  {
70  template <class Matrix>
71  static auto apply(const Matrix& A)
72  {
73  return at(A,0,0) + at(A,1,1) ;
74  }
75  };
76 
78  template <>
79  struct ComputeTrace<3>
80  {
81  template <class Matrix>
82  static auto apply(const Matrix& A)
83  {
84  return at(A,0,0) + at(A,1,1) + at(A,2,2);
85  }
86  };
87  }
88 
89 
94  template <class Matrix, class = Concepts::SymmetricMatrixConceptCheck<Matrix> >
95  struct ConstantSizeTrace : Base , Chainer< ConstantSizeTrace< Matrix , Concepts::SymmetricMatrixConceptCheck<Matrix> > >
96  {
97  using Chainer< ConstantSizeTrace< Matrix , Concepts::SymmetricMatrixConceptCheck<Matrix> > >::operator ();
99  ConstantSizeTrace() = default;
100 
105  explicit ConstantSizeTrace(const Matrix& A) { update(A); }
106 
108  void update(const Matrix& A)
109  {
110  trace = Detail::ComputeTrace<dimension<Matrix>()>::apply(A);
111  }
112 
114  const auto& operator()() const noexcept
115  {
116  return d0();
117  }
118 
120  const auto& operator()(const Matrix& A) const
121  {
122  update(A);
123  return d0();
124  }
125 
127  const auto& d0() const noexcept
128  {
129  return trace;
130  }
131 
133  template <int>
134  auto d1(const Matrix& dA) const
135  {
136  return Detail::ComputeTrace<dimension<Matrix>()>::apply(dA);
137  }
138 
139  private:
140  std::decay_t< at_t<Matrix> > trace = 0.;
141  };
142 
147  template <class Matrix/*, class = Concepts::SymmetricMatrixConceptCheck<Matrix> */>
148  struct DynamicSizeTrace : Base , Chainer< DynamicSizeTrace<Matrix> >
149  {
150  using Chainer< DynamicSizeTrace<Matrix> >::operator ();
152  DynamicSizeTrace() = default;
153 
158  explicit DynamicSizeTrace(const Matrix& A) { update(A); }
159 
161  void update(const Matrix& A)
162  {
163 #ifdef RFFGEN_ENABLE_EXCEPTIONS
164  if( rows(A) != cols(A) ) throw NonSymmetricMatrixException("DynamicSizeTrace",rows(A),cols(A),__FILE__,__LINE__);
165 #endif
166 
167  using Index = decltype(rows(std::declval<Matrix>()));
168  trace = 0.;
169  for(Index i = 0; i < rows(A); ++i) trace += at(A,i,i);
170  }
171 
173  const auto& operator()() const noexcept
174  {
175  return d0();
176  }
177 
179  const auto& operator()(const Matrix& A) const
180  {
181  update(A);
182  return d0();
183  }
184 
186  const auto& d0() const noexcept
187  {
188  return trace;
189  }
190 
192  template <int>
193  auto d1(const Matrix& dA) const
194  {
195  using Index = decltype(rows(std::declval<Matrix>()));
196  auto result = decltype(at(dA,0,0))(0.);
197  for(Index i = 0; i < rows(dA); ++i) result += at(dA,i,i);
198  return result;
199  }
200 
201  private:
202  std::decay_t< at_t<Matrix> > trace = 0.;
203  };
212  template< class Matrix >
213  using Trace = std::conditional_t< Checks::isConstantSizeMatrix<Matrix>() , ConstantSizeTrace<Matrix> , DynamicSizeTrace<Matrix> >;
214 
218  namespace Detail
219  {
220  template <bool>
221  struct TraceImpl
222  {
223  template <class Matrix>
224  static auto apply(const Matrix& A)
225  {
226  return Trace<Matrix>(A);
227  }
228  };
229 
230  template <>
231  struct TraceImpl<true>
232  {
233  template <class Function>
234  static auto apply(const Function& f)
235  {
236  return Trace< std::decay_t<decltype(f.d0())> >( f.d0() )( f );
237  }
238  };
239  }
249  template <class Arg>
250  auto trace(const Arg& arg)
251  {
252  return Detail::TraceImpl<std::is_base_of<Base,Arg>::value>::apply(arg);
253  }
254  }
255 }
256 
257 #endif // RFFGEN_LINEAR_ALGEBRA_TRACE_HH
auto trace(const Arg &arg)
Convenient generation of Trace<Matrix>.
Definition: trace.hh:250
std::conditional_t< Checks::isConstantSizeMatrix< Matrix >(), ConstantSizeTrace< Matrix >, DynamicSizeTrace< Matrix > > Trace
Trace of a matrix (sum of diagonal elements).
Definition: trace.hh:213