File: vtkMatrixUtilities.h

package info (click to toggle)
paraview 5.11.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 497,236 kB
  • sloc: cpp: 3,171,290; ansic: 1,315,072; python: 134,290; xml: 103,324; sql: 65,887; sh: 5,286; javascript: 4,901; yacc: 4,383; java: 3,977; perl: 2,363; lex: 1,909; f90: 1,255; objc: 143; makefile: 119; tcl: 59; pascal: 50; fortran: 29
file content (363 lines) | stat: -rw-r--r-- 11,850 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMathPrivate.hxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/**
 * @class   vtkMathPrivate
 * @brief   Internal toolkit used in some vtkMath methods.
 *
 * vtkMatrixUtilities provides matrix indexing / wrapping tools. One can use
 * this utility to wrap a 1D array into a matrix shape, index it at compile
 * time.
 * @sa
 * vtkMath
 * vtkMathPrivate
 */

#ifndef vtkMatrixUtilities_h
#define vtkMatrixUtilities_h

#include "vtkABINamespace.h"

#include <type_traits> // for type traits

namespace vtkMatrixUtilities
{
VTK_ABI_NAMESPACE_BEGIN
//=============================================================================
/**
 * This struct determines a prior transform to input matrices, changing the
 * way they are indexed
 */
struct Layout
{
  /**
   * Input matrix is unchanged, i.e. sorted row-wise ordered
   */
  struct Identity;
  /*
   * Input matrix is transposed, i.e. sorted in column-wise ordered.
   */
  struct Transpose;

  /**
   * Input matrix is considered diagonal, and value at index idx points
   * to component of coordinates (idx, idx) in the diagonal matrix.
   */
  struct Diag;
};

namespace detail
{
// Extracting for STL-like containers
template <int ContainerTypeT, class ContainerT>
struct ScalarTypeExtractor
{
  typedef typename ContainerT::value_type value_type;
  static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
    "value_type is not a numeric type");
};

// Extracting for C++ arrays
template <class ContainerT>
struct ScalarTypeExtractor<1, ContainerT>
{
  typedef typename std::remove_pointer<
    typename std::remove_all_extents<typename std::remove_pointer<ContainerT>::type>::type>::type
    value_type;
  static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
    "value_type is not a numeric type");
};
} // namespace detail

//=============================================================================
/**
 * This class extract the underlying value type of containers. It works on
 * multi-dimensional C++ arrays as well as with STL container like that
 * have a value_type typedef.
 *
 * One can access the value type by fetching
 * ScalarTypeExtractor<ContainerT>::value_type.
 */
template <class ContainerT>
struct ScalarTypeExtractor
{
private:
  typedef typename std::remove_reference<ContainerT>::type DerefContainer;

public:
  typedef typename detail::ScalarTypeExtractor<
    // This parameter equals 0 or 1
    std::is_array<DerefContainer>::value || std::is_pointer<DerefContainer>::value,
    ContainerT>::value_type value_type;
  static_assert(std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
    "value_type is not a numeric type");
};

//-----------------------------------------------------------------------------
/**
 * At compile time, returns `true` if the templated parameter is a 2D array
 * (`double[3][3]` for instance), false otherwise.
 */
template <class MatrixT>
static constexpr bool MatrixIs2DArray()
{
  typedef typename std::remove_extent<MatrixT>::type Row;
  typedef typename std::remove_extent<Row>::type Value;
  return std::is_array<MatrixT>::value && std::is_array<Row>::value && !std::is_array<Value>::value;
}

//-----------------------------------------------------------------------------
/**
 * At compile time, returns `true` if the templated parameter is a pointer to
 * pointer (`double**` for instance), false otherwise.
 */
template <class MatrixT>
static constexpr bool MatrixIsPointerToPointer()
{
  typedef typename std::remove_pointer<MatrixT>::type Row;
  typedef typename std::remove_pointer<Row>::type Value;
  return std::is_pointer<MatrixT>::value && std::is_pointer<Row>::value &&
    !std::is_pointer<Value>::value;
}

//-----------------------------------------------------------------------------
/**
 * At compile time, returns `true` if the templated parameter layout is 2D,
 * i.e. elements can be accessed using the operator `[][]`. It returns false otherwise.
 */
template <class MatrixT>
static constexpr bool MatrixLayoutIs2D()
{
  typedef typename std::remove_pointer<MatrixT>::type RowPointer;
  typedef typename std::remove_extent<MatrixT>::type RowArray;
  typedef typename std::remove_pointer<MatrixT>::type ValuePointerPointer;
  typedef typename std::remove_extent<MatrixT>::type ValuePointerArray;
  typedef typename std::remove_pointer<MatrixT>::type ValueArrayPointer;
  typedef typename std::remove_extent<MatrixT>::type ValueArrayArray;
  return ((std::is_array<RowPointer>::value && !std::is_same<RowPointer, MatrixT>::value) ||
           std::is_pointer<RowPointer>::value || std::is_array<RowArray>::value ||
           (std::is_pointer<RowArray>::value && !std::is_same<RowArray, MatrixT>::value)) &&
    (!std::is_array<ValuePointerPointer>::value || !std::is_pointer<ValuePointerPointer>::value) &&
    (!std::is_array<ValueArrayPointer>::value || !std::is_pointer<ValueArrayPointer>::value) &&
    (!std::is_array<ValuePointerArray>::value || !std::is_pointer<ValuePointerArray>::value) &&
    (!std::is_array<ValueArrayArray>::value || !std::is_pointer<ValueArrayArray>::value);
}

namespace detail
{
// Class actually implementing matrix mapping.
template <int RowsT, int ColsT, class LayoutT>
struct Mapper;

// Specialization of the matrix mapper for when the layout is the identity
template <int RowsT, int ColsT>
struct Mapper<RowsT, ColsT, Layout::Identity>
{
  template <int RowT, int ColT>
  static constexpr int GetIndex()
  {
    static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
    static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
    return ColsT * RowT + ColT;
  }
};

template <int RowsT, int ColsT>
struct Mapper<RowsT, ColsT, Layout::Transpose>
{
  template <int RowT, int ColT>
  static constexpr int GetIndex()
  {
    static_assert(RowT >= 0 && RowT < RowsT, "RowT out of bounds");
    static_assert(ColT >= 0 && ColT < ColsT, "ColT out of bounds");
    return RowsT * ColT + RowT;
  }
};
} // namespace detail

//=============================================================================
/**
 * This class is a helper class to compute at compile time the index of a matrix
 * stored as a 1D array from its 2D coordinates. This class maps matrices of
 * dimension RowsT x ColsT. The LayoutT template parameter permits to switch to
 * the indexing of the transpose of the matrix. LayoutT can be set to
 * Layout::Identity for a row-wise ordering, or to Layout::Transpose for a
 * column-wise ordering
 *
 * @warning This mapper does not work with matrices stored as 2D arrays, or with
 * diagonal matrices.
 */
template <int RowsT, int ColsT, class LayoutT = Layout::Identity>
struct Mapper
{
  template <int RowT, int ColT>
  static constexpr int GetIndex()
  {
    return detail::Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>();
  }
};

namespace detail
{
// Class implementing matrix wrapping.
template <int RowsT, int ColsT, class MatrixT, class LayoutT, bool MatrixLayoutIs2DT>
class Wrapper;

// Specializaion of matrix wrapping for matrices stored as 1D arrays
// in row-wise order
template <int RowsT, int ColsT, class MatrixT, class LayoutT>
class Wrapper<RowsT, ColsT, MatrixT, LayoutT, false>
{
private:
  using Scalar = typename vtkMatrixUtilities::ScalarTypeExtractor<MatrixT>::value_type;

public:
  template <int RowT, int ColT>
  static const Scalar& Get(const MatrixT& M)
  {
    return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
  }

  template <int RowT, int ColT>
  static Scalar& Get(MatrixT& M)
  {
    return M[Mapper<RowsT, ColsT, LayoutT>::template GetIndex<RowT, ColT>()];
  }
};

// Specialization for matrices stored as 2D arrays with an unchanged layout
template <int RowsT, int ColsT, class MatrixT>
class Wrapper<RowsT, ColsT, MatrixT, Layout::Identity, true>
{
private:
  using Scalar = typename vtkMatrixUtilities::ScalarTypeExtractor<MatrixT>::value_type;

public:
  template <int RowT, int ColT>
  static const Scalar& Get(const MatrixT& M)
  {
    return M[RowT][ColT];
  }

  template <int RowT, int ColT>
  static Scalar& Get(MatrixT& M)
  {
    return M[RowT][ColT];
  }
};

// Specialization for matrices stored as 2D arrays read as its transposed self.
template <int RowsT, int ColsT, class MatrixT>
class Wrapper<RowsT, ColsT, MatrixT, Layout::Transpose, true>
{
private:
  using Scalar = typename vtkMatrixUtilities::ScalarTypeExtractor<MatrixT>::value_type;

public:
  template <int RowT, int ColT>
  static const Scalar& Get(const MatrixT& M)
  {
    return M[ColT][RowT];
  }

  template <int RowT, int ColT>
  static Scalar& Get(MatrixT& M)
  {
    return M[ColT][RowT];
  }
};

// Specialization for diagonal matrices.
// Note: a diagonal matrix has to be stored in a 1D array.
template <int RowsT, int ColsT, class MatrixT>
class Wrapper<RowsT, ColsT, MatrixT, Layout::Diag, false>
{
private:
  using Scalar = typename vtkMatrixUtilities::ScalarTypeExtractor<MatrixT>::value_type;

  template <int RowT, int ColT>
  struct Helper
  {
    static constexpr Scalar ZERO = Scalar(0);

    static Scalar& Get(const MatrixT&) { return ZERO; }
  };

  template <int RowT>
  struct Helper<RowT, RowT>
  {
    static Scalar& Get(MatrixT& M) { return M[RowT]; }

    static const Scalar& Get(const MatrixT& M) { return M[RowT]; }
  };

public:
  template <int RowT, int ColT>
  const Scalar& Get(const MatrixT& M)
  {
    return Helper<RowT, ColT>::Get(M);
  }

  template <int RowT, int ColT>
  Scalar& Get(MatrixT& M)
  {
    return Helper<RowT, ColT>::Get(M);
  }
};
} // namespace detail

//=============================================================================
/**
 * Matrix wrapping class. This class implements a getter templated on the
 * coordinates of the wanted element. A matrix can be a 2D C++ array, a 1D C++
 * array row-wise ordered, or any STL-like container implementing operator[] and
 * having a value_type typedef.
 *
 * This class wraps a RowsT x ColsT matrix stored in the container MatrixT. The
 * LayoutT template parameter permits to reindex at compile-time the matrix. If
 * it is set to Layout::Identity, the matrix is assumed to be row-wised ordered.
 * If it is set to Layout::Transpose, the matrix is assumed to be column-wise ordered.
 * One can also convert a 1D input array into a diagonal matrix by setting
 * LayoutT to Layout::Diag. In ths particular case, method Get will return a
 * read-only zero on elements outside of the diagonal.
 */
template <int RowsT, int ColsT, class MatrixT, class LayoutT = Layout::Identity>
class Wrapper
{
private:
  using Scalar = typename ScalarTypeExtractor<MatrixT>::value_type;

  static_assert(!MatrixLayoutIs2D<MatrixT>() || !std::is_same<LayoutT, Layout::Diag>::value,
    "A diagonal  matrix cannot be a 2D array");

public:
  template <int RowT, int ColT>
  static const Scalar& Get(const MatrixT& M)
  {
    return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
      MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
  }

  template <int RowT, int ColT>
  static Scalar& Get(MatrixT& M)
  {
    return detail::Wrapper<RowsT, ColsT, MatrixT, LayoutT,
      MatrixLayoutIs2D<MatrixT>()>::template Get<RowT, ColT>(M);
  }
};
VTK_ABI_NAMESPACE_END
} // namespace vtkMatrixUtilities
#endif

// VTK-HeaderTest-Exclude: vtkMatrixUtilities.h