VTK  9.1.0
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//=============================================================================
39struct 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
57namespace detail
58{
59// Extracting for STL-like containers
60template <int ContainerTypeT, class ContainerT>
62{
63 typedef typename ContainerT::value_type value_type;
64 static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
65 "value_type is not a numeric type");
66};
67
68// Extracting for C++ arrays
69template <class ContainerT>
70struct ScalarTypeExtractor<1, ContainerT>
71{
72 typedef typename std::remove_pointer<
73 typename std::remove_all_extents<typename std::remove_pointer<ContainerT>::type>::type>::type
75 static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
76 "value_type is not a numeric type");
77};
78} // namespace detail
79
80//=============================================================================
89template <class ContainerT>
91{
92private:
93 typedef typename std::remove_reference<ContainerT>::type DerefContainer;
94
95public:
96 typedef typename detail::ScalarTypeExtractor<
97 // This parameter equals 0 or 1
98 std::is_array<DerefContainer>::value || std::is_pointer<DerefContainer>::value,
100 static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
101 "value_type is not a numeric type");
102};
103
104//-----------------------------------------------------------------------------
109template <class MatrixT>
110static constexpr bool MatrixIs2DArray()
111{
112 typedef typename std::remove_extent<MatrixT>::type Row;
113 typedef typename std::remove_extent<Row>::type Value;
114 return std::is_array<MatrixT>::value && std::is_array<Row>::value && !std::is_array<Value>::value;
115}
116
117//-----------------------------------------------------------------------------
122template <class MatrixT>
123static constexpr bool MatrixIsPointerToPointer()
124{
125 typedef typename std::remove_pointer<MatrixT>::type Row;
126 typedef typename std::remove_pointer<Row>::type Value;
127 return std::is_pointer<MatrixT>::value && std::is_pointer<Row>::value &&
128 !std::is_pointer<Value>::value;
129}
130
131//-----------------------------------------------------------------------------
136template <class MatrixT>
137static 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;
145 return ((std::is_array<RowPointer>::value && !std::is_same<RowPointer, MatrixT>::value) ||
146 std::is_pointer<RowPointer>::value || std::is_array<RowArray>::value ||
147 (std::is_pointer<RowArray>::value && !std::is_same<RowArray, MatrixT>::value)) &&
148 (!std::is_array<ValuePointerPointer>::value || !std::is_pointer<ValuePointerPointer>::value) &&
149 (!std::is_array<ValueArrayPointer>::value || !std::is_pointer<ValueArrayPointer>::value) &&
150 (!std::is_array<ValuePointerArray>::value || !std::is_pointer<ValuePointerArray>::value) &&
151 (!std::is_array<ValueArrayArray>::value || !std::is_pointer<ValueArrayArray>::value);
152}
153
154namespace detail
155{
156// Class actually implementing matrix mapping.
157template <int RowsT, int ColsT, class LayoutT>
158struct Mapper;
159
160// Specialization of the matrix mapper for when the layout is the identity
161template <int RowsT, int ColsT>
162struct 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
173template <int RowsT, int ColsT>
174struct 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//=============================================================================
198template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
199struct 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
208namespace detail
209{
210// Class implementing matrix wrapping.
211template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
213
214// Specializaion of matrix wrapping for matrices stored as 1D arrays
215// in row-wise order
216template <int RowsT, int ColsT, class MatrixT, class LayoutT>
217class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
218{
219private:
221
222public:
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
237template <int RowsT, int ColsT, class MatrixT>
238class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
239{
240private:
242
243public:
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.
258template <int RowsT, int ColsT, class MatrixT>
259class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
260{
261private:
263
264public:
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.
280template <int RowsT, int ColsT, class MatrixT>
281class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
282{
283private:
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
302public:
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//=============================================================================
332template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
334{
335private:
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
341public:
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.
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< typenamestd::remove_all_extents< typenamestd::remove_pointer< ContainerT >::type >::type >::type value_type