VTK  9.3.0
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
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: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.
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