VTK  9.2.20220926
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 "vtkABINamespace.h"
31 
32 #include <type_traits> // for type traits
33 
35 {
36 VTK_ABI_NAMESPACE_BEGIN
37 //=============================================================================
42 struct Layout
43 {
47  struct Identity;
48  /*
49  * Input matrix is transposed, i.e. sorted in column-wise ordered.
50  */
51  struct Transpose;
52 
57  struct Diag;
58 };
59 
60 namespace detail
61 {
62 // Extracting for STL-like containers
63 template <int ContainerTypeT, class ContainerT>
65 {
66  typedef typename ContainerT::value_type value_type;
68  "value_type is not a numeric type");
69 };
70 
71 // Extracting for C++ arrays
72 template <class ContainerT>
73 struct ScalarTypeExtractor<1, ContainerT>
74 {
75  typedef typename std::remove_pointer<
79  "value_type is not a numeric type");
80 };
81 } // namespace detail
82 
83 //=============================================================================
92 template <class ContainerT>
94 {
95 private:
96  typedef typename std::remove_reference<ContainerT>::type DerefContainer;
97 
98 public:
99  typedef typename detail::ScalarTypeExtractor<
100  // This parameter equals 0 or 1
104  "value_type is not a numeric type");
105 };
106 
107 //-----------------------------------------------------------------------------
112 template <class MatrixT>
113 static constexpr bool MatrixIs2DArray()
114 {
115  typedef typename std::remove_extent<MatrixT>::type Row;
116  typedef typename std::remove_extent<Row>::type Value;
118 }
119 
120 //-----------------------------------------------------------------------------
125 template <class MatrixT>
126 static constexpr bool MatrixIsPointerToPointer()
127 {
128  typedef typename std::remove_pointer<MatrixT>::type Row;
129  typedef typename std::remove_pointer<Row>::type Value;
132 }
133 
134 //-----------------------------------------------------------------------------
139 template <class MatrixT>
140 static constexpr bool MatrixLayoutIs2D()
141 {
142  typedef typename std::remove_pointer<MatrixT>::type RowPointer;
143  typedef typename std::remove_extent<MatrixT>::type RowArray;
144  typedef typename std::remove_pointer<MatrixT>::type ValuePointerPointer;
145  typedef typename std::remove_extent<MatrixT>::type ValuePointerArray;
146  typedef typename std::remove_pointer<MatrixT>::type ValueArrayPointer;
147  typedef typename std::remove_extent<MatrixT>::type ValueArrayArray;
155 }
156 
157 namespace detail
158 {
159 // Class actually implementing matrix mapping.
160 template <int RowsT, int ColsT, class LayoutT>
161 struct Mapper;
162 
163 // Specialization of the matrix mapper for when the layout is the identity
164 template <int RowsT, int ColsT>
165 struct Mapper<RowsT, ColsT, Layout::Identity>
166 {
167  template <int RowT, int ColT>
168  static constexpr int GetIndex()
169  {
170  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
171  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
172  return ColsT * RowT + ColT;
173  }
174 };
175 
176 template <int RowsT, int ColsT>
177 struct Mapper<RowsT, ColsT, Layout::Transpose>
178 {
179  template <int RowT, int ColT>
180  static constexpr int GetIndex()
181  {
182  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
183  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
184  return RowsT * ColT + RowT;
185  }
186 };
187 } // namespace detail
188 
189 //=============================================================================
201 template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
202 struct Mapper
203 {
204  template <int RowT, int ColT>
205  static constexpr int GetIndex()
206  {
207  return detail::Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>();
208  }
209 };
210 
211 namespace detail
212 {
213 // Class implementing matrix wrapping.
214 template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
215 class Wrapper;
216 
217 // Specializaion of matrix wrapping for matrices stored as 1D arrays
218 // in row-wise order
219 template <int RowsT, int ColsT, class MatrixT, class LayoutT>
220 class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
221 {
222 private:
224 
225 public:
226  template <int RowT, int ColT>
227  static const Scalar& Get(const MatrixT& M)
228  {
229  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
230  }
231 
232  template <int RowT, int ColT>
233  static Scalar& Get(MatrixT& M)
234  {
235  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
236  }
237 };
238 
239 // Specialization for matrices stored as 2D arrays with an unchanged layout
240 template <int RowsT, int ColsT, class MatrixT>
241 class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
242 {
243 private:
245 
246 public:
247  template <int RowT, int ColT>
248  static const Scalar& Get(const MatrixT& M)
249  {
250  return M[RowT][ColT];
251  }
252 
253  template <int RowT, int ColT>
254  static Scalar& Get(MatrixT& M)
255  {
256  return M[RowT][ColT];
257  }
258 };
259 
260 // Specialization for matrices stored as 2D arrays read as its transposed self.
261 template <int RowsT, int ColsT, class MatrixT>
262 class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
263 {
264 private:
266 
267 public:
268  template <int RowT, int ColT>
269  static const Scalar& Get(const MatrixT& M)
270  {
271  return M[ColT][RowT];
272  }
273 
274  template <int RowT, int ColT>
275  static Scalar& Get(MatrixT& M)
276  {
277  return M[ColT][RowT];
278  }
279 };
280 
281 // Specialization for diagonal matrices.
282 // Note: a diagonal matrix has to be stored in a 1D array.
283 template <int RowsT, int ColsT, class MatrixT>
284 class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
285 {
286 private:
288 
289  template <int RowT, int ColT>
290  struct Helper
291  {
292  static constexpr Scalar ZERO = Scalar(0);
293 
294  static Scalar& Get(const MatrixT&) { return ZERO; }
295  };
296 
297  template <int RowT>
298  struct Helper<RowT, RowT>
299  {
300  static Scalar& Get(MatrixT& M) { return M[RowT]; }
301 
302  static const Scalar& Get(const MatrixT& M) { return M[RowT]; }
303  };
304 
305 public:
306  template <int RowT, int ColT>
307  const Scalar& Get(const MatrixT& M)
308  {
309  return Helper<RowT, ColT>::Get(M);
310  }
311 
312  template <int RowT, int ColT>
313  Scalar& Get(MatrixT& M)
314  {
315  return Helper<RowT, ColT>::Get(M);
316  }
317 };
318 } // namespace detail
319 
320 //=============================================================================
335 template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
336 class Wrapper
337 {
338 private:
339  using Scalar = typename ScalarTypeExtractor<MatrixT>::value_type;
340 
341  static_assert(!MatrixLayoutIs2D<MatrixT>() || !std::is_same<LayoutT, Layout::Diag>::value,
342  "A diagonal matrix cannot be a 2D array");
343 
344 public:
345  template <int RowT, int ColT>
346  static const Scalar& Get(const MatrixT& M)
347  {
348  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
349  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
350  }
351 
352  template <int RowT, int ColT>
353  static Scalar& Get(MatrixT& M)
354  {
355  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
356  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
357  }
358 };
360 } // namespace vtkMatrixUtilities
361 #endif
362 
363 // VTK-HeaderTest-Exclude: vtkMatrixUtilities.h
Matrix wrapping class.
static const Scalar & Get(const MatrixT &M)
static Scalar & Get(MatrixT &M)
static constexpr bool MatrixIsPointerToPointer()
At compile time, returns true if the templated parameter is a pointer to pointer (double** for instan...
static constexpr bool MatrixIs2DArray()
At compile time, returns true if the templated parameter is a 2D array (double[3][3] for instance),...
static constexpr bool MatrixLayoutIs2D()
At compile time, returns true if the templated parameter layout is 2D, i.e.
@ value
Definition: vtkX3D.h:232
@ type
Definition: vtkX3D.h:528
This struct determines a prior transform to input matrices, changing the way they are indexed.
This class is a helper class to compute at compile time the index of a matrix stored as a 1D array fr...
static constexpr int GetIndex()
This class extract the underlying value type of containers.
detail::ScalarTypeExtractor< std::is_array< DerefContainer >::value||std::is_pointer< DerefContainer >::value, ContainerT >::value_type value_type
std::remove_pointer< typename std::remove_all_extents< typename std::remove_pointer< ContainerT >::type >::type >::type value_type