VTK  9.3.20240419
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:
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
Matrix wrapping class.
static ComponentType Get(MatrixTT &&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:220
@ type
Definition: vtkX3D.h:516
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.
typename detail::ExtractRawComponentType< ContainerT >::Type RawComponentType
RawComponentType is the type given by operator[] for 1D containers, or operator[][] for 2D containers...
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
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
std::decay< typename std::decay< ContainerT >::type::value_type >::type value_type