VTK  9.3.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 
23 {
24 VTK_ABI_NAMESPACE_BEGIN
25 //=============================================================================
30 struct Layout
31 {
35  struct Identity;
36  /*
37  * Input matrix is transposed, i.e. sorted in column-wise ordered.
38  */
39  struct Transpose;
40 
45  struct Diag;
46 };
47 
48 namespace detail
49 {
50 // Extracting for STL-like containers
51 template <int ContainerTypeT, class ContainerT>
53 {
54  typedef typename ContainerT::value_type value_type;
56  "value_type is not a numeric type");
57 };
58 
59 // Extracting for C++ arrays
60 template <class ContainerT>
61 struct ScalarTypeExtractor<1, ContainerT>
62 {
63  typedef typename std::remove_pointer<
67  "value_type is not a numeric type");
68 };
69 } // namespace detail
70 
71 //=============================================================================
80 template <class ContainerT>
82 {
83 private:
84  typedef typename std::remove_reference<ContainerT>::type DerefContainer;
85 
86 public:
87  typedef typename detail::ScalarTypeExtractor<
88  // This parameter equals 0 or 1
92  "value_type is not a numeric type");
93 };
94 
95 //-----------------------------------------------------------------------------
100 template <class MatrixT>
101 static constexpr bool MatrixIs2DArray()
102 {
103  typedef typename std::remove_extent<MatrixT>::type Row;
104  typedef typename std::remove_extent<Row>::type Value;
106 }
107 
108 //-----------------------------------------------------------------------------
113 template <class MatrixT>
114 static constexpr bool MatrixIsPointerToPointer()
115 {
116  typedef typename std::remove_pointer<MatrixT>::type Row;
117  typedef typename std::remove_pointer<Row>::type Value;
120 }
121 
122 //-----------------------------------------------------------------------------
127 template <class MatrixT>
128 static constexpr bool MatrixLayoutIs2D()
129 {
130  typedef typename std::remove_pointer<MatrixT>::type RowPointer;
131  typedef typename std::remove_extent<MatrixT>::type RowArray;
132  typedef typename std::remove_pointer<MatrixT>::type ValuePointerPointer;
133  typedef typename std::remove_extent<MatrixT>::type ValuePointerArray;
134  typedef typename std::remove_pointer<MatrixT>::type ValueArrayPointer;
135  typedef typename std::remove_extent<MatrixT>::type ValueArrayArray;
143 }
144 
145 namespace detail
146 {
147 // Class actually implementing matrix mapping.
148 template <int RowsT, int ColsT, class LayoutT>
149 struct Mapper;
150 
151 // Specialization of the matrix mapper for when the layout is the identity
152 template <int RowsT, int ColsT>
153 struct Mapper<RowsT, ColsT, Layout::Identity>
154 {
155  template <int RowT, int ColT>
156  static constexpr int GetIndex()
157  {
158  static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
159  static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
160  return ColsT * RowT + ColT;
161  }
162 };
163 
164 template <int RowsT, int ColsT>
165 struct Mapper<RowsT, ColsT, Layout::Transpose>
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 RowsT * ColT + RowT;
173  }
174 };
175 } // namespace detail
176 
177 //=============================================================================
189 template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
190 struct Mapper
191 {
192  template <int RowT, int ColT>
193  static constexpr int GetIndex()
194  {
195  return detail::Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>();
196  }
197 };
198 
199 namespace detail
200 {
201 // Class implementing matrix wrapping.
202 template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
203 class Wrapper;
204 
205 // Specializaion of matrix wrapping for matrices stored as 1D arrays
206 // in row-wise order
207 template <int RowsT, int ColsT, class MatrixT, class LayoutT>
208 class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
209 {
210 private:
212 
213 public:
214  template <int RowT, int ColT>
215  static const Scalar& Get(const MatrixT& M)
216  {
217  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
218  }
219 
220  template <int RowT, int ColT>
221  static Scalar& Get(MatrixT& M)
222  {
223  return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
224  }
225 };
226 
227 // Specialization for matrices stored as 2D arrays with an unchanged layout
228 template <int RowsT, int ColsT, class MatrixT>
229 class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
230 {
231 private:
233 
234 public:
235  template <int RowT, int ColT>
236  static const Scalar& Get(const MatrixT& M)
237  {
238  return M[RowT][ColT];
239  }
240 
241  template <int RowT, int ColT>
242  static Scalar& Get(MatrixT& M)
243  {
244  return M[RowT][ColT];
245  }
246 };
247 
248 // Specialization for matrices stored as 2D arrays read as its transposed self.
249 template <int RowsT, int ColsT, class MatrixT>
250 class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
251 {
252 private:
254 
255 public:
256  template <int RowT, int ColT>
257  static const Scalar& Get(const MatrixT& M)
258  {
259  return M[ColT][RowT];
260  }
261 
262  template <int RowT, int ColT>
263  static Scalar& Get(MatrixT& M)
264  {
265  return M[ColT][RowT];
266  }
267 };
268 
269 // Specialization for diagonal matrices.
270 // Note: a diagonal matrix has to be stored in a 1D array.
271 template <int RowsT, int ColsT, class MatrixT>
272 class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
273 {
274 private:
276 
277  template <int RowT, int ColT>
278  struct Helper
279  {
280  static constexpr Scalar ZERO = Scalar(0);
281 
282  static Scalar& Get(const MatrixT&) { return ZERO; }
283  };
284 
285  template <int RowT>
286  struct Helper<RowT, RowT>
287  {
288  static Scalar& Get(MatrixT& M) { return M[RowT]; }
289 
290  static const Scalar& Get(const MatrixT& M) { return M[RowT]; }
291  };
292 
293 public:
294  template <int RowT, int ColT>
295  const Scalar& Get(const MatrixT& M)
296  {
297  return Helper<RowT, ColT>::Get(M);
298  }
299 
300  template <int RowT, int ColT>
301  Scalar& Get(MatrixT& M)
302  {
303  return Helper<RowT, ColT>::Get(M);
304  }
305 };
306 } // namespace detail
307 
308 //=============================================================================
323 template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
324 class Wrapper
325 {
326 private:
327  using Scalar = typename ScalarTypeExtractor<MatrixT>::value_type;
328 
329  static_assert(!MatrixLayoutIs2D<MatrixT>() || !std::is_same<LayoutT, Layout::Diag>::value,
330  "A diagonal matrix cannot be a 2D array");
331 
332 public:
333  template <int RowT, int ColT>
334  static const Scalar& Get(const MatrixT& M)
335  {
336  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
337  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
338  }
339 
340  template <int RowT, int ColT>
341  static Scalar& Get(MatrixT& M)
342  {
343  return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
344  MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
345  }
346 };
347 VTK_ABI_NAMESPACE_END
348 } // namespace vtkMatrixUtilities
349 #endif
350 
351 // 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()