VTK  9.2.6
vtkMatrixUtilities.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkMathPrivate.hxx
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
27 #ifndef vtkMatrixUtilities_h
28 #define vtkMatrixUtilities_h
29 
30 #include <type_traits> // for type traits
31 
33 {
34 //=============================================================================
39 struct Layout
40 {
44  struct Identity;
45  /*
46  * Input matrix is transposed, i.e. sorted in column-wise ordered.
47  */
48  struct Transpose;
49 
54  struct Diag;
55 };
56 
57 namespace detail
58 {
59 // Extracting for STL-like containers
60 template <int ContainerTypeT, class ContainerT>
62 {
63  typedef typename ContainerT::value_type value_type;
65  "value_type is not a numeric type");
66 };
67 
68 // Extracting for C++ arrays
69 template <class ContainerT>
70 struct ScalarTypeExtractor<1, ContainerT>
71 {
72  typedef typename std::remove_pointer<
76  "value_type is not a numeric type");
77 };
78 } // namespace detail
79 
80 //=============================================================================
89 template <class ContainerT>
91 {
92 private:
93  typedef typename std::remove_reference<ContainerT>::type DerefContainer;
94 
95 public:
96  typedef typename detail::ScalarTypeExtractor<
97  // This parameter equals 0 or 1
101  "value_type is not a numeric type");
102 };
103 
104 //-----------------------------------------------------------------------------
109 template <class MatrixT>
110 static constexpr bool MatrixIs2DArray()
111 {
112  typedef typename std::remove_extent<MatrixT>::type Row;
113  typedef typename std::remove_extent<Row>::type Value;
115 }
116 
117 //-----------------------------------------------------------------------------
122 template <class MatrixT>
123 static constexpr bool MatrixIsPointerToPointer()
124 {
125  typedef typename std::remove_pointer<MatrixT>::type Row;
126  typedef typename std::remove_pointer<Row>::type Value;
129 }
130 
131 //-----------------------------------------------------------------------------
136 template <class MatrixT>
137 static constexpr bool MatrixLayoutIs2D()
138 {
139  typedef typename std::remove_pointer<MatrixT>::type RowPointer;
140  typedef typename std::remove_extent<MatrixT>::type RowArray;
141  typedef typename std::remove_pointer<MatrixT>::type ValuePointerPointer;
142  typedef typename std::remove_extent<MatrixT>::type ValuePointerArray;
143  typedef typename std::remove_pointer<MatrixT>::type ValueArrayPointer;
144  typedef typename std::remove_extent<MatrixT>::type ValueArrayArray;
152 }
153 
154 namespace detail
155 {
156 // Class actually implementing matrix mapping.
157 template <int RowsT, int ColsT, class LayoutT>
158 struct Mapper;
159 
160 // Specialization of the matrix mapper for when the layout is the identity
161 template <int RowsT, int ColsT>
162 struct Mapper<RowsT, ColsT, Layout::Identity>
163 {
164  template <int RowT, int ColT>
165  static constexpr int GetIndex()
166  {
167  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
168  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
169  return ColsT * RowT + ColT;
170  }
171 };
172 
173 template <int RowsT, int ColsT>
174 struct Mapper<RowsT, ColsT, Layout::Transpose>
175 {
176  template <int RowT, int ColT>
177  static constexpr int GetIndex()
178  {
179  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
180  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
181  return RowsT * ColT + RowT;
182  }
183 };
184 } // namespace detail
185 
186 //=============================================================================
198 template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
199 struct Mapper
200 {
201  template <int RowT, int ColT>
202  static constexpr int GetIndex()
203  {
204  return detail::Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>();
205  }
206 };
207 
208 namespace detail
209 {
210 // Class implementing matrix wrapping.
211 template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
212 class Wrapper;
213 
214 // Specializaion of matrix wrapping for matrices stored as 1D arrays
215 // in row-wise order
216 template <int RowsT, int ColsT, class MatrixT, class LayoutT>
217 class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
218 {
219 private:
221 
222 public:
223  template <int RowT, int ColT>
224  static const Scalar& Get(const MatrixT& M)
225  {
226  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
227  }
228 
229  template <int RowT, int ColT>
230  static Scalar& Get(MatrixT& M)
231  {
232  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
233  }
234 };
235 
236 // Specialization for matrices stored as 2D arrays with an unchanged layout
237 template <int RowsT, int ColsT, class MatrixT>
238 class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
239 {
240 private:
242 
243 public:
244  template <int RowT, int ColT>
245  static const Scalar& Get(const MatrixT& M)
246  {
247  return M[RowT][ColT];
248  }
249 
250  template <int RowT, int ColT>
251  static Scalar& Get(MatrixT& M)
252  {
253  return M[RowT][ColT];
254  }
255 };
256 
257 // Specialization for matrices stored as 2D arrays read as its transposed self.
258 template <int RowsT, int ColsT, class MatrixT>
259 class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
260 {
261 private:
263 
264 public:
265  template <int RowT, int ColT>
266  static const Scalar& Get(const MatrixT& M)
267  {
268  return M[ColT][RowT];
269  }
270 
271  template <int RowT, int ColT>
272  static Scalar& Get(MatrixT& M)
273  {
274  return M[ColT][RowT];
275  }
276 };
277 
278 // Specialization for diagonal matrices.
279 // Note: a diagonal matrix has to be stored in a 1D array.
280 template <int RowsT, int ColsT, class MatrixT>
281 class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
282 {
283 private:
285 
286  template <int RowT, int ColT>
287  struct Helper
288  {
289  static constexpr Scalar ZERO = Scalar(0);
290 
291  static Scalar& Get(const MatrixT&) { return ZERO; }
292  };
293 
294  template <int RowT>
295  struct Helper<RowT, RowT>
296  {
297  static Scalar& Get(MatrixT& M) { return M[RowT]; }
298 
299  static const Scalar& Get(const MatrixT& M) { return M[RowT]; }
300  };
301 
302 public:
303  template <int RowT, int ColT>
304  const Scalar& Get(const MatrixT& M)
305  {
306  return Helper<RowT, ColT>::Get(M);
307  }
308 
309  template <int RowT, int ColT>
310  Scalar& Get(MatrixT& M)
311  {
312  return Helper<RowT, ColT>::Get(M);
313  }
314 };
315 } // namespace detail
316 
317 //=============================================================================
332 template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
333 class Wrapper
334 {
335 private:
336  using Scalar = typename ScalarTypeExtractor<MatrixT>::value_type;
337 
338  static_assert(!MatrixLayoutIs2D<MatrixT>() || !std::is_same<LayoutT, Layout::Diag>::value,
339  "A diagonal matrix cannot be a 2D array");
340 
341 public:
342  template <int RowT, int ColT>
343  static const Scalar& Get(const MatrixT& M)
344  {
345  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
346  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
347  }
348 
349  template <int RowT, int ColT>
350  static Scalar& Get(MatrixT& M)
351  {
352  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
353  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
354  }
355 };
356 } // namespace vtkMatrixUtilities
357 #endif
358 
359 // VTK-HeaderTest-Exclude: vtkMatrixUtilities.h
static constexpr bool MatrixIs2DArray()
At compile time, returns true if the templated parameter is a 2D array (double[3][3] for instance)...
static const Scalar & Get(const MatrixT &M)
std::remove_pointer< typename std::remove_all_extents< typename std::remove_pointer< ContainerT >::type >::type >::type value_type
static constexpr bool MatrixIsPointerToPointer()
At compile time, returns true if the templated parameter is a pointer to pointer (double** for instan...
detail::ScalarTypeExtractor< std::is_array< DerefContainer >::value||std::is_pointer< DerefContainer >::value, ContainerT >::value_type value_type
This struct determines a prior transform to input matrices, changing the way they are indexed...
static constexpr bool MatrixLayoutIs2D()
At compile time, returns true if the templated parameter layout is 2D, i.e.
This class extract the underlying value type of containers.
This class is a helper class to compute at compile time the index of a matrix stored as a 1D array fr...
static Scalar & Get(MatrixT &M)
Matrix wrapping class.
static constexpr int GetIndex()