VTK  9.7.1
vtkMatrixUtilities.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
15 #ifndef vtkMatrixUtilities_h
16 #define vtkMatrixUtilities_h
17 
18 #include "vtkABINamespace.h"
19 
20 #include <type_traits> // for type traits
21 #include <utility> // for std::forward
22 
24 {
25 VTK_ABI_NAMESPACE_BEGIN
26 //=============================================================================
31 struct Layout
32 {
36  struct Identity;
37  /*
38  * Input matrix is transposed, i.e. sorted in column-wise ordered.
39  */
40  struct Transpose;
41 
46  struct Diag;
47 };
48 
49 namespace detail
50 {
51 // Extracting for STL-like containers
52 template <int ContainerTypeT, class ContainerT>
54 {
55  typedef typename std::decay<typename std::decay<ContainerT>::type::value_type>::type value_type;
57  "value_type is not a numeric type");
58 };
59 
60 // Extracting for C++ arrays
61 template <class ContainerT>
62 struct ScalarTypeExtractor<1, ContainerT>
63 {
64 private:
65  typedef typename std::remove_reference<ContainerT>::type DerefContainer;
66 
67 public:
68  typedef typename std::decay<typename std::remove_pointer<typename std::remove_all_extents<
70 
72  "value_type is not a numeric type");
73 };
74 
75 //=============================================================================
76 template <class MatrixT, int Depth = 0>
78 {
79  static constexpr int Value = Depth;
80 };
81 
82 //=============================================================================
83 template <class MatrixT, int Depth>
84 struct ArrayOrPointerDepth<MatrixT[], Depth>
85 {
87 };
88 
89 //=============================================================================
90 template <class MatrixT, int N, int Depth>
91 struct ArrayOrPointerDepth<MatrixT[N], Depth>
92 {
94 };
95 
96 //=============================================================================
97 template <class MatrixT, int Depth>
98 struct ArrayOrPointerDepth<MatrixT*, Depth>
99 {
101 };
102 
103 //=============================================================================
104 template <class MatrixT, int Depth>
105 struct ArrayOrPointerDepth<MatrixT&, Depth>
106 {
107  static constexpr int Value = ArrayOrPointerDepth<MatrixT, Depth>::Value;
108 };
109 } // namespace detail
110 
111 //-----------------------------------------------------------------------------
116 template <class MatrixT>
117 static constexpr bool MatrixIs2DArray()
118 {
120 }
121 
122 namespace detail
123 {
124 //=============================================================================
125 template <class MatrixT, class = void>
127 
128 //=============================================================================
129 template <class MatrixT>
130 struct ExtractRawComponentType<MatrixT, typename std::enable_if<MatrixIs2DArray<MatrixT>()>::type>
131 {
132  using Type = decltype(std::declval<MatrixT>()[0][0]);
133 };
134 
135 //=============================================================================
136 template <class MatrixT>
137 struct ExtractRawComponentType<MatrixT, typename std::enable_if<!MatrixIs2DArray<MatrixT>()>::type>
138 {
139  using Type = decltype(std::declval<MatrixT>()[0]);
140 };
141 } // namespace detail
142 
143 //=============================================================================
152 template <class ContainerT>
154 {
155 private:
156  typedef typename std::remove_reference<ContainerT>::type DerefContainer;
157 
158 public:
162  using value_type = typename detail::ScalarTypeExtractor<
163  // This parameter equals 0 or 1
165  ContainerT>::value_type;
167  "value_type is not a numeric type");
168 
174 
180 };
181 
182 //-----------------------------------------------------------------------------
187 template <class MatrixT>
188 static constexpr bool MatrixIsPointerToPointer()
189 {
190  typedef typename std::remove_pointer<MatrixT>::type Row;
191  typedef typename std::remove_pointer<Row>::type Value;
194 }
195 
196 //-----------------------------------------------------------------------------
201 template <class MatrixT>
202 static constexpr bool MatrixLayoutIs2D()
203 {
204  return MatrixIs2DArray<MatrixT>();
205 }
206 
207 namespace detail
208 {
209 // Class actually implementing matrix mapping.
210 template <int RowsT, int ColsT, class LayoutT>
211 struct Mapper;
212 
213 // Specialization of the matrix mapper for when the layout is the identity
214 template <int RowsT, int ColsT>
215 struct Mapper<RowsT, ColsT, Layout::Identity>
216 {
217  template <int RowT, int ColT>
218  static constexpr int GetIndex()
219  {
220  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
221  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
222  return ColsT * RowT + ColT;
223  }
224 };
225 
226 template <int RowsT, int ColsT>
227 struct Mapper<RowsT, ColsT, Layout::Transpose>
228 {
229  template <int RowT, int ColT>
230  static constexpr int GetIndex()
231  {
232  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
233  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
234  return RowsT * ColT + RowT;
235  }
236 };
237 } // namespace detail
238 
239 //=============================================================================
251 template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
252 struct Mapper
253 {
254  template <int RowT, int ColT>
255  static constexpr int GetIndex()
256  {
257  return detail::Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>();
258  }
259 };
260 
261 namespace detail
262 {
263 // Class implementing matrix wrapping.
264 template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
265 class Wrapper;
266 
267 // Specializaion of matrix wrapping for matrices stored as 1D arrays
268 // in row-wise order
269 template <int RowsT, int ColsT, class MatrixT, class LayoutT>
270 class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
271 {
272 private:
274 
275 public:
276  template <int RowT, int ColT, class MatrixTT>
277  static ComponentType Get(MatrixTT&& M)
278  {
279  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
280  }
281 };
282 
283 // Specialization for matrices stored as 2D arrays with an unchanged layout
284 template <int RowsT, int ColsT, class MatrixT>
285 class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
286 {
287 private:
289 
290 public:
291  template <int RowT, int ColT, class MatrixTT>
292  static ComponentType Get(MatrixTT&& M)
293  {
294  return M[RowT][ColT];
295  }
296 };
297 
298 // Specialization for matrices stored as 2D arrays read as its transposed self.
299 template <int RowsT, int ColsT, class MatrixT>
300 class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
301 {
302 private:
304 
305 public:
306  template <int RowT, int ColT, class MatrixTT>
307  static ComponentType Get(MatrixTT&& M)
308  {
309  return M[ColT][RowT];
310  }
311 };
312 
313 // Specialization for diagonal matrices.
314 // Note: a diagonal matrix has to be stored in a 1D array.
315 template <int RowsT, int ColsT, class MatrixT>
316 class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
317 {
318 private:
321 
322  template <int RowT, int ColT>
323  struct Helper
324  {
325  static constexpr Scalar ZERO = Scalar(0);
326 
327  template <class MatrixTT>
328  static ComponentType Get(MatrixTT&&)
329  {
330  return ZERO;
331  }
332  };
333 
334  template <int RowT>
335  struct Helper<RowT, RowT>
336  {
337  template <class MatrixTT>
338  static ComponentType Get(MatrixTT&& M)
339  {
340  return M[RowT];
341  }
342  };
343 
344 public:
345  template <int RowT, int ColT, class MatrixTT>
346  ComponentType Get(MatrixTT& M)
347  {
348  return Helper<RowT, ColT>::Get(std::forward<MatrixTT>(M));
349  }
350 };
351 } // namespace detail
352 
353 //=============================================================================
368 template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
369 class Wrapper
370 {
371 private:
372  using Scalar = typename ScalarTypeExtractor<MatrixT>::value_type;
374 
375  static_assert(!MatrixLayoutIs2D<MatrixT>() || !std::is_same<LayoutT, Layout::Diag>::value,
376  "A diagonal matrix cannot be a 2D array");
377 
378 public:
379  template <int RowT, int ColT, class MatrixTT>
380  static ComponentType Get(MatrixTT&& M)
381  {
382  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
383  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(std::forward<MatrixTT>(M));
384  }
385 };
386 VTK_ABI_NAMESPACE_END
387 } // namespace vtkMatrixUtilities
388 #endif
389 
390 // 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 ComponentType Get(MatrixTT &&M)
typename detail::ExtractRawComponentType< ContainerT >::Type RawComponentType
RawComponentType is the type given by operator[] for 1D containers, or operator[][] for 2D containers...
static constexpr bool MatrixIsPointerToPointer()
At compile time, returns true if the templated parameter is a pointer to pointer (double** for instan...
This struct determines a prior transform to input matrices, changing the way they are indexed...
std::decay< typename std::decay< ContainerT >::type::value_type >::type value_type
typename detail::ScalarTypeExtractor< std::is_array< DerefContainer >::value||std::is_pointer< DerefContainer >::value, ContainerT >::value_type value_type
value_type is the underlying arithmetic type held in ContainerT
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...
const RealT ZERO
Definition: PyrC2Basis.h:1
typename std::conditional< std::is_rvalue_reference< RawComponentType >::value, typename std::remove_reference< RawComponentType >::type, RawComponentType >::type ComponentType
ComponentType is the RawComponentType dereferenced if it was an rvalue reference. ...
std::decay< typename std::remove_pointer< typename std::remove_all_extents< typename std::remove_pointer< DerefContainer >::type >::type >::type >::type value_type
Matrix wrapping class.
static constexpr int GetIndex()