VTK  9.1.20211024
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
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:226
@ type
Definition: vtkX3D.h:522
This struct determines a prior transform to input matrices, chaging 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