4.1. Advanced Types
Chapter 2.1 (Base Types) introduced some of the base data types defined for use in VTK‑m. However, for simplicity Chapter Chapter 2.1 (Base Types) just briefly touched the high-level concepts of these types. In this chapter we dive into much greater depth and introduce several more types.
4.1.1. Single Number Types
As described in Chapter Chapter 2.1 (Base Types), VTK‑m provides aliases for all the base C types to ensure the representation matches the variable use.
When a specific type width is not required, then the most common types to use are vtkm::FloatDefault for floating-point numbers, vtkm::Id for array and similar indices, and vtkm::IdComponent for shorter-width vector indices.
If a specific type width is desired, then one of the following is used to clearly declare the type and width.
bytes |
floating point |
signed integer |
unsigned integer |
|---|---|---|---|
1 |
|||
2 |
|||
4 |
|||
8 |
These VTK‑m–defined types should be preferred over basic C types like int or float.
4.1.2. Vector Types
Visualization algorithms also often require operations on short vectors.
Arrays indexed in up to three dimensions are common.
Data are often defined in 2-space and 3-space, and transformations are typically done in homogeneous coordinates of length 4.
To simplify these types of operations, VTK‑m provides the vtkm::Vec templated type, which is essentially a fixed length array of a given type.
-
template<typename T, vtkm::IdComponent Size>
class Vec : public vtkm::detail::VecBase<T, Size, Vec<T, Size>> A short fixed-length array.
The
Vectemplated class holds a short array of values of a size and type specified by the template arguments.The
Vecclass is most often used to represent vectors in the mathematical sense as a quantity with a magnitude and direction. Vectors are, of course, used extensively in computational geometry as well as physical simulations. TheVecclass can be (and is) repurposed for more general usage of holding a fixed-length sequence of objects.There is no real limit to the size of the sequence (other than the largest number representable by vtkm::IdComponent), but the
Vecclass is really designed for small sequences (seldom more than 10).Subclassed by vtkm::VecFlat< T, false >
The default constructor of vtkm::Vec objects leaves the values uninitialized.
All vectors have a constructor with one argument that is used to initialize all components.
All vtkm::Vec objects also have a constructor that allows you to set the individual components (one per argument).
All vtkm::Vec objects with a size that is greater than 4 are constructed at run time and support an arbitrary number of initial values.
Likewise, there is a vtkm::make_Vec() convenience function that builds initialized vector types with an arbitrary number of components.
Once created, you can use the bracket operator to get and set component values with the same syntax as an array.
1 vtkm::Vec3f_32 A{ 1 }; // A is (1, 1, 1)
2 A[1] = 2; // A is now (1, 2, 1)
3 vtkm::Vec3f_32 B{ 1, 2, 3 }; // B is (1, 2, 3)
4 vtkm::Vec3f_32 C = vtkm::make_Vec(3, 4, 5); // C is (3, 4, 5)
5 // Longer Vecs specified with template.
6 vtkm::Vec<vtkm::Float32, 5> D{ 1 }; // D is (1, 1, 1, 1, 1)
7 vtkm::Vec<vtkm::Float32, 5> E{ 1, 2, 3, 4, 5 }; // E is (1, 2, 3, 4, 5)
8 vtkm::Vec<vtkm::Float32, 5> F = { 6, 7, 8, 9, 10 }; // F is (6, 7, 8, 9, 10)
9 auto G = vtkm::make_Vec(1, 3, 5, 7, 9); // G is (1, 3, 5, 7, 9)
-
template<typename T, typename ...Ts>
constexpr vtkm::Vec<T, vtkm::IdComponent(sizeof...(Ts) + 1)> vtkm::make_Vec(T value0, Ts&&... args) Initializes and returns a Vec containing all the arguments.
The arguments should all be the same type or compile issues will occur.
The types vtkm::Id2, vtkm::Id3, and vtkm::Id4 are type aliases of vtkm::Vec<vtkm::Id,2>, vtkm::Vec<vtkm::Id,3>, and vtkm::Vec<vtkm::Id,4>, respectively.
These are used to index arrays of 2, 3, and 4 dimensions, which is common.
Likewise, vtkm::IdComponent2, vtkm::IdComponent3, and vtkm::IdComponent4 are type aliases of vtkm::Vec<vtkm::IdComponent,2>, vtkm::Vec<vtkm::IdComponent,3>, and vtkm::Vec<vtkm::IdComponent,4>, respectively.
Because declaring vtkm::Vec with all of its template parameters can be cumbersome, VTK‑m provides easy to use aliases for small vectors of base types.
As introduced in Section 2.1.3 (Vector Types), the following type aliases are available.
bytes |
size |
floating point |
signed integer |
unsigned integer |
|---|---|---|---|---|
1 |
2 |
|||
3 |
||||
4 |
||||
2 |
2 |
|||
3 |
||||
4 |
||||
4 |
2 |
|||
3 |
||||
4 |
||||
8 |
2 |
|||
3 |
||||
4 |
vtkm::Vec supports component-wise arithmetic using the operators for plus (+), minus (-), multiply (*), and divide (/).
It also supports scalar to vector multiplication with the multiply operator.
The comparison operators equal (==) is true if every pair of corresponding components are true and not equal (!=) is true otherwise.
A special vtkm::Dot() function is overloaded to provide a dot product for every type of vector.
1 vtkm::Vec3f_32 A{ 1, 2, 3 };
2 vtkm::Vec3f_32 B{ 4, 5, 6.5 };
3 vtkm::Vec3f_32 C = A + B; // C is (5, 7, 9.5)
4 vtkm::Vec3f_32 D = 2.0f * C; // D is (10, 14, 19)
5 vtkm::Float32 s = vtkm::Dot(A, B); // s is 33.5
6 bool b1 = (A == B); // b1 is false
7 bool b2 = (A == vtkm::make_Vec(1, 2, 3)); // b2 is true
8
9 vtkm::Vec<vtkm::Float32, 5> E{ 1, 2.5, 3, 4, 5 }; // E is (1, 2, 3, 4, 5)
10 vtkm::Vec<vtkm::Float32, 5> F{ 6, 7, 8.5, 9, 10.5 }; // F is (6, 7, 8, 9, 10)
11 vtkm::Vec<vtkm::Float32, 5> G = E + F; // G is (7, 9.5, 11.5, 13, 15.5)
12 bool b3 = (E == F); // b3 is false
13 bool b4 = (G == vtkm::make_Vec(7.f, 9.5f, 11.5f, 13.f, 15.5f)); // b4 is true
These operators, of course, only work if they are also defined for the component type of the vtkm::Vec.
For example, the multiply operator will work fine on objects of type vtkm::Vec<char,3>, but the multiply operator will not work on objects of type vtkm::Vec<std::string,3> because you cannot multiply objects of type std::string.
In addition to generalizing vector operations and making arbitrarily long vectors, vtkm::Vec can be repurposed for creating any sequence of homogeneous objects.
Here is a simple example of using vtkm::Vec to hold the state of a polygon.
1 vtkm::Vec<vtkm::Vec2f_32, 3> equilateralTriangle = { { 0.0f, 0.0f },
2 { 1.0f, 0.0f },
3 { 0.5f, 0.8660254f } };
4.1.2.1. Vec-like Types
The vtkm::Vec class provides a convenient structure for holding and passing small vectors of data.
However, there are times when using vtkm::Vec is inconvenient or inappropriate.
For example, the size of vtkm::Vec must be known at compile time, but there may be need for a vector whose size is unknown until compile time.
Also, the data populating a vtkm::Vec might come from a source that makes it inconvenient or less efficient to construct a vtkm::Vec.
For this reason, VTK‑m also provides several Vec-like objects that behave much like vtkm::Vec but are a different class.
These Vec-like objects have the same interface as vtkm::Vec except that the NUM_COMPONENTS constant is not available on those that are sized at run time.
Vec-like objects also come with a CopyInto method that will take their contents and copy them into a standard vtkm::Vec class.
(The standard vtkm::Vec class also has a vtkm::Vec::CopyInto() method for consistency.)
4.1.2.1.1. C-Array Vec Wrapper
The first Vec-like object is vtkm::VecC, which exposes a C-type array as a vtkm::Vec.
-
template<typename T>
class VecC : public vtkm::detail::VecCBase<T, VecC<T>> A Vec-like representation for short arrays.
The
VecCclass takes a short array of values and provides an interface that mimicsVec. This provides a mechanism to treat C arrays like aVec. It is useful in situations where you want to use aVecbut the data must come from elsewhere or in certain situations where the size cannot be determined at compile time. In particular,Vecobjects of different sizes can potentially all be converted to aVecCof the same type.Note that
VecCholds a reference to an outside array given to it. If that array gets destroyed (for example because the source goes out of scope), the behavior becomes undefined.You cannot use
VecCwith a const type in its template argument. For example, you cannot declareVecC<const vtkm::Id>. If you want a non-mutableVecC, theVecCConstclass (e.g.VecCConst<vtkm::Id>).
The constructor for vtkm::VecC takes a C array and a size of that array.
There is also a constant version of vtkm::VecC named vtkm::VecCConst, which takes a constant array and cannot be mutated.
-
template<typename T>
class VecCConst : public vtkm::detail::VecCBase<T, VecCConst<T>> A const version of VecC.
VecCConstis a non-mutable form ofVecC. It can be used in place ofVecCwhen a constant array is available.A
VecCcan be automatically converted to aVecCConst, but not vice versa, so function arguments should useVecCConstwhen the data do not need to be changed.
The vtkm/Types.h header defines both vtkm::VecC and vtkm::VecCConst as well as multiple versions of vtkm::make_VecC() to easily convert a C array to either a vtkm::VecC or vtkm::VecCConst.
-
template<typename T>
static inline vtkm::VecC<T> vtkm::make_VecC(T *array, vtkm::IdComponent size) Creates a
VecCfrom an input array.
-
template<typename T>
static inline vtkm::VecCConst<T> vtkm::make_VecC(const T *array, vtkm::IdComponent size) Creates a
VecCConstfrom a constant input array.
The following example demonstrates converting values from a constant table into a vtkm::VecCConst for further consumption.
The table and associated methods define how 8 points come together to form a hexahedron.
1VTKM_EXEC vtkm::VecCConst<vtkm::IdComponent> HexagonIndexToIJK(vtkm::IdComponent index)
2{
3 static const vtkm::IdComponent HexagonIndexToIJKTable[8][3] = {
4 { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
5 { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }
6 };
7
8 return vtkm::make_VecC(HexagonIndexToIJKTable[index], 3);
9}
10
11VTKM_EXEC vtkm::IdComponent HexagonIJKToIndex(vtkm::VecCConst<vtkm::IdComponent> ijk)
12{
13 static const vtkm::IdComponent HexagonIJKToIndexTable[2][2][2] = { {
14 // i=0
15 { 0, 4 }, // j=0
16 { 3, 7 }, // j=1
17 },
18 {
19 // i=1
20 { 1, 5 }, // j=0
21 { 2, 6 }, // j=1
22 } };
23
24 return HexagonIJKToIndexTable[ijk[0]][ijk[1]][ijk[2]];
25}
Common Errors
The vtkm::VecC and vtkm::VecCConst classes only hold a pointer to a buffer that contains the data.
They do not manage the memory holding the data.
Thus, if the pointer given to vtkm::VecC or vtkm::VecCConst becomes invalid, then using the object becomes invalid.
Make sure that the scope of the vtkm::VecC or vtkm::VecCConst does not outlive the scope of the data it points to.
4.1.2.1.2. Variable-Sized Vec
The next Vec-like object is vtkm::VecVariable, which provides a Vec-like object that can be resized at run time to a maximum value.
Unlike vtkm::VecC, vtkm::VecVariable holds its own memory, which makes it a bit safer to use.
But also unlike vtkm::VecC, you must define the maximum size of vtkm::VecVariable at compile time.
Thus, vtkm::VecVariable is really only appropriate to use when there is a predetermined limit to the vector size that is fairly small.
-
template<typename T, vtkm::IdComponent MaxSize>
class VecVariable A short variable-length array with maximum length.
The
VecVariableclass is a Vec-like class that holds a short array of some maximum length. To avoid dynamic allocations, the maximum length is specified at compile time. Internally,VecVariableholds aVecof the maximum length and exposes a subsection of it.
The following example uses a vtkm::VecVariable to store the trace of edges within a hexahedron.
This example uses the methods defined in Example 4.5.
1vtkm::VecVariable<vtkm::IdComponent, 4> HexagonShortestPath(vtkm::IdComponent startPoint,
2 vtkm::IdComponent endPoint)
3{
4 vtkm::VecCConst<vtkm::IdComponent> startIJK = HexagonIndexToIJK(startPoint);
5 vtkm::VecCConst<vtkm::IdComponent> endIJK = HexagonIndexToIJK(endPoint);
6
7 vtkm::IdComponent3 currentIJK;
8 startIJK.CopyInto(currentIJK);
9
10 vtkm::VecVariable<vtkm::IdComponent, 4> path;
11 path.Append(startPoint);
12 for (vtkm::IdComponent dimension = 0; dimension < 3; dimension++)
13 {
14 if (currentIJK[dimension] != endIJK[dimension])
15 {
16 currentIJK[dimension] = endIJK[dimension];
17 path.Append(HexagonIJKToIndex(currentIJK));
18 }
19 }
20
21 return path;
22}
4.1.2.1.3. Vecs from Portals
VTK‑m provides further examples of Vec-like objects as well.
For example, the vtkm::VecFromPortal and vtkm::VecFromPortalPermute objects allow you to treat a subsection of an arbitrarily large array as a vtkm::Vec.
These objects work by attaching to array portals, which are described in
Section 3.2.4 (Array Portals).
-
template<typename PortalType>
class VecFromPortal A short variable-length array from a window in an ArrayPortal.
The
VecFromPortalclass is a Vec-like class that holds an array portal and exposes a small window of that portal as if it were aVec.
-
template<typename IndexVecType, typename PortalType>
class VecFromPortalPermute A short vector from an ArrayPortal and a vector of indices.
The
VecFromPortalPermuteclass is a Vec-like class that holds an array portal and a second Vec-like containing indices into the array. Each value of this vector is the value from the array with the respective index.
4.1.2.1.4. Point Coordinate Vec
Another example of a Vec-like object is vtkm::VecRectilinearPointCoordinates, which efficiently represents the point coordinates in an axis-aligned hexahedron.
Such shapes are common in structured grids.
These and other data sets are described in Chapter 2.4 (Data Sets).
4.1.3. Range
VTK‑m provides a convenience structure named vtkm::Range to help manage a range of values.
The vtkm::Range struct contains two data members, vtkm::Range::Min and vtkm::Range::Max, which represent the ends of the range of numbers.
vtkm::Range::Min and vtkm::Range::Max are both of type vtkm::Float64.
vtkm::Range::Min and vtkm::Range::Max can be directly accessed, but vtkm::Range also comes with several helper functions to make it easier to build and use ranges.
Note that all of these functions treat the minimum and maximum value as inclusive to the range.
-
struct Range
Represent a continuous scalar range of values.
vtkm::Rangeis a helper class for representing a range of floating point values from a minimum value to a maximum value. This is specified simply enough with aMinandMaxvalue.Rangealso contains several helper functions for computing and maintaining the range.Public Functions
-
inline Range()
Construct a range with a given minimum and maximum.
If no minimum or maximum is given, the range will be empty.
-
inline bool IsNonEmpty() const
Determine if the range is valid (i.e.
has at least one valid point).
IsNonEmptyreturn true if the range contains some valid values betweenMinandMax. IfMaxis less thanMin, then no values satisfy the range andIsNonEmptyreturns false. Otherwise, return true.IsNonEmptyassumesMinandMaxare inclusive. That is, if they are equal then true is returned.
-
template<typename T>
inline bool Contains(const T &value) const Determines if a value is within the range.
Containsreturns true if the give value is within the range, false otherwise.Containstreats the min and max as inclusive. That is, if the value is exactly the min or max, true is returned.
-
inline vtkm::Float64 Length() const
Returns the length of the range.
Lengthcomputes the distance between the min and max. If the range is empty, 0 is returned.
-
inline vtkm::Float64 Center() const
Returns the center of the range.
Centercomputes the middle value of the range. If the range is empty, NaN is returned.
-
template<typename T>
inline void Include(const T &value) Expand range to include a value.
This version of
Includeexpands the range just enough to include the given value. If the range already includes this value, then nothing is done.
-
inline void Include(const vtkm::Range &range)
Expand range to include other range.
This version of
Includeexpands this range just enough to include that of another range. Essentially it is the union of the two ranges.
-
inline vtkm::Range Union(const vtkm::Range &otherRange) const
Return the union of this and another range.
This is a nondestructive form of
Include.
-
inline Range()
The following example demonstrates the operation of vtkm::Range.
1 vtkm::Range range; // default constructor is empty range
2 bool b1 = range.IsNonEmpty(); // b1 is false
3
4 range.Include(0.5); // range now is [0.5 .. 0.5]
5 bool b2 = range.IsNonEmpty(); // b2 is true
6 bool b3 = range.Contains(0.5); // b3 is true
7 bool b4 = range.Contains(0.6); // b4 is false
8
9 range.Include(2.0); // range is now [0.5 .. 2]
10 bool b5 = range.Contains(0.5); // b3 is true
11 bool b6 = range.Contains(0.6); // b4 is true
12
13 range.Include(vtkm::Range(-1, 1)); // range is now [-1 .. 2]
14
15 range.Include(vtkm::Range(3, 4)); // range is now [-1 .. 4]
16
17 vtkm::Float64 lower = range.Min; // lower is -1
18 vtkm::Float64 upper = range.Max; // upper is 4
19 vtkm::Float64 length = range.Length(); // length is 5
20 vtkm::Float64 center = range.Center(); // center is 1.5
4.1.4. Bounds
VTK‑m provides a convenience structure named vtkm::Bounds to help manage
an axis-aligned region in 3D space. Among other things, this structure is
often useful for representing a bounding box for geometry. The
vtkm::Bounds struct contains three data members,
vtkm::Bounds::X, vtkm::Bounds::Y, and vtkm::Bounds::Z, which represent the range of
the bounds along each respective axis. All three of these members are of
type vtkm::Range, which is discussed previously in Section 4.1.3 (Range).
vtkm::Bounds::X, vtkm::Bounds::Y, and vtkm::Bounds::Z can
be directly accessed, but vtkm::Bounds also comes with the
following helper functions to make it easier to build and use ranges.
-
struct Bounds
Represent an axis-aligned 3D bounds in space.
vtkm::Boundsis a helper class for representing the axis-aligned box representing some region in space. The typical use of this class is to express the containing box of some geometry. The box is specified as ranges in the x, y, and z directions.Boundsalso contains several helper functions for computing and maintaining the bounds.Public Functions
-
inline Bounds()
Construct an empty bounds.
The bounds will represent no space until otherwise modified.
-
inline Bounds(const vtkm::Range &xRange, const vtkm::Range &yRange, const vtkm::Range &zRange)
Construct a bounds with a given range in the x, y, and z dimensions.
-
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
inline Bounds(const T1 &minX, const T2 &maxX, const T3 &minY, const T4 &maxY, const T5 &minZ, const T6 &maxZ) Construct a bounds with the minimum and maximum coordinates in the x, y, and z directions.
-
template<typename T>
inline explicit Bounds(const T bounds[6]) Initialize bounds with an array of 6 values in the order xmin, xmax, ymin, ymax, zmin, zmax.
-
template<typename T>
inline Bounds(const vtkm::Vec<T, 3> &minPoint, const vtkm::Vec<T, 3> &maxPoint) Initialize bounds with the minimum corner point and the maximum corner point.
-
inline bool IsNonEmpty() const
Determine if the bounds are valid (i.e.
has at least one valid point).
IsNonEmptyreturns true if the bounds contain some valid points. If the bounds are any real region, even if a single point or it expands to infinity, true is returned.
-
template<typename T>
inline bool Contains(const vtkm::Vec<T, 3> &point) const Determines if a point coordinate is within the bounds.
-
inline vtkm::Float64 Volume() const
Returns the volume of the bounds.
Volumecomputes the product of the lengths of the ranges in each dimension. If the bounds are empty, 0 is returned.
-
inline vtkm::Float64 Area() const
Returns the area of the bounds in the X-Y-plane.
Areacomputes the product of the lengths of the ranges in dimensions X and Y. If the bounds are empty, 0 is returned.
-
inline vtkm::Vec3f_64 Center() const
Returns the center of the range.
Centercomputes the point at the middle of the bounds. If the bounds are empty, the results are undefined.
-
inline vtkm::Vec3f_64 MinCorner() const
Returns the min point of the bounds
MinCorderreturns the minium point of the bounds.If the bounds are empty, the results are undefined.
-
inline vtkm::Vec3f_64 MaxCorner() const
Returns the max point of the bounds
MaxCorderreturns the minium point of the bounds.If the bounds are empty, the results are undefined.
-
template<typename T>
inline void Include(const vtkm::Vec<T, 3> &point) Expand bounds to include a point.
This version of
Includeexpands the bounds just enough to include the given point coordinates. If the bounds already include this point, then nothing is done.
-
inline void Include(const vtkm::Bounds &bounds)
Expand bounds to include other bounds.
This version of
Includeexpands these bounds just enough to include that of another bounds. Essentially it is the union of the two bounds.
-
inline vtkm::Bounds Union(const vtkm::Bounds &otherBounds) const
Return the union of this and another bounds.
This is a nondestructive form of
Include.
Public Members
-
vtkm::Range X
The range of values in the X direction.
The
vtkm::Rangestruct provides the minimum and maximum along that axis.
-
vtkm::Range Y
The range of values in the Y direction.
The
vtkm::Rangestruct provides the minimum and maximum along that axis.
-
vtkm::Range Z
The range of values in the Z direction.
The
vtkm::Rangestruct provides the minimum and maximum along that axis.
-
inline Bounds()
The following example demonstrates the operation of vtkm::Bounds.
1 vtkm::Bounds bounds; // default constructor makes empty
2 bool b1 = bounds.IsNonEmpty(); // b1 is false
3
4 bounds.Include(vtkm::make_Vec(0.5, 2.0, 0.0)); // bounds contains only
5 // the point [0.5, 2, 0]
6 bool b2 = bounds.IsNonEmpty(); // b2 is true
7 bool b3 = bounds.Contains(vtkm::make_Vec(0.5, 2.0, 0.0)); // b3 is true
8 bool b4 = bounds.Contains(vtkm::make_Vec(1, 1, 1)); // b4 is false
9 bool b5 = bounds.Contains(vtkm::make_Vec(0, 0, 0)); // b5 is false
10
11 bounds.Include(vtkm::make_Vec(4, -1, 2)); // bounds is region [0.5 .. 4] in X,
12 // [-1 .. 2] in Y,
13 // and [0 .. 2] in Z
14 bool b6 = bounds.Contains(vtkm::make_Vec(0.5, 2.0, 0.0)); // b6 is true
15 bool b7 = bounds.Contains(vtkm::make_Vec(1, 1, 1)); // b7 is true
16 bool b8 = bounds.Contains(vtkm::make_Vec(0, 0, 0)); // b8 is false
17
18 vtkm::Bounds otherBounds(vtkm::make_Vec(0, 0, 0), vtkm::make_Vec(3, 3, 3));
19 // otherBounds is region [0 .. 3] in X, Y, and Z
20 bounds.Include(otherBounds); // bounds is now region [0 .. 4] in X,
21 // [-1 .. 3] in Y,
22 // and [0 .. 3] in Z
23
24 vtkm::Vec3f_64 lower(bounds.X.Min, bounds.Y.Min, bounds.Z.Min);
25 // lower is [0, -1, 0]
26 vtkm::Vec3f_64 upper(bounds.X.Max, bounds.Y.Max, bounds.Z.Max);
27 // upper is [4, 3, 3]
28
29 vtkm::Vec3f_64 center = bounds.Center(); // center is [2, 1, 1.5]
4.1.5. Index Ranges
Just as it is sometimes necessary to track a range of real values, there are times when code has to specify a continuous range of values in an index sequence like an array.
For this purpose, VTK‑m provides RangeId, which behaves similarly to Range except for integer values.
-
struct RangeId
Represent a range of vtkm::Id values.
vtkm::RangeIdis a helper class for representing a range of vtkm::Id values. This is specified simply with aMinandMaxvalue, whereMaxis exclusive.RangeIdalso contains several helper functions for computing and maintaining the range.Public Functions
-
inline RangeId()
Construct a range with no indices.
-
inline RangeId(vtkm::Id min, vtkm::Id max)
Construct a range with the given minimum (inclusive) and maximum (exclusive) indices.
-
inline bool IsNonEmpty() const
Determine if the range is valid.
IsNonEmptyreturn true if the range contains some valid values betweenMinandMax. IfMax<=Min, then no values satisfy the range andIsNonEmptyreturns false. Otherwise, return true.
-
inline bool Contains(vtkm::Id value) const
Determines if a value is within the range.
Containsreturns true if the give value is within the range, false otherwise.
-
inline vtkm::Id Length() const
Returns the length of the range.
Lengthcomputes the distance between the min and max. If the range is empty, 0 is returned.
-
inline vtkm::Id Center() const
Returns the center of the range.
Centercomputes the middle value of the range.
-
inline void Include(vtkm::Id value)
Expand range to include a value.
This version of
Includeexpands the range just enough to include the given value. If the range already includes this value, then nothing is done.
-
inline void Include(const vtkm::RangeId &range)
Expand range to include other range.
This version of
Includeexpands this range just enough to include that of another range. Essentially it is the union of the two ranges.
-
inline RangeId()
VTK‑m also often must operate on 2D and 3D arrays (particularly for structured cell sets).
For these use cases, RangeId2 and RangeId3 are provided.
-
struct RangeId2
Represent 2D integer range.
vtkm::RangeId2is a helper class for representing a 2D range of integer values. The typical use of this class is to express a box of indices in the x and y directions.RangeId2also contains several helper functions for computing and maintaining the range.Public Functions
-
RangeId2() = default
Construct an empty 2D range.
-
inline RangeId2(const vtkm::RangeId &xrange, const vtkm::RangeId &yrange)
Construct a range with the given x and y directions.
-
inline RangeId2(vtkm::Id minX, vtkm::Id maxX, vtkm::Id minY, vtkm::Id maxY)
Construct a range with the given minimum (inclusive) and maximum (exclusive) points.
-
inline explicit RangeId2(const vtkm::Id range[4])
Initialize range with an array of 4 values in the order xmin, xmax, ymin, ymax.
-
inline RangeId2(const vtkm::Id2 &min, const vtkm::Id2 &max)
Initialize range with the minimum and the maximum corners.
-
inline bool IsNonEmpty() const
Determine if the range is non-empty.
IsNonEmptyreturns true if the range is non-empty.
-
inline vtkm::Id2 Center() const
Returns the center of the range.
Centercomputes the middle of the range.
-
template<typename T>
inline void Include(const vtkm::Vec<T, 2> &point) Expand range to include a value.
This version of
Includeexpands the range just enough to include the given value. If the range already include this value, then nothing is done.
-
inline void Include(const vtkm::RangeId2 &range)
Expand range to include other range.
This version of
Includeexpands the range just enough to include the other range. Essentially it is the union of the two ranges.
Public Members
-
vtkm::RangeId X
The range of values in the X direction.
The
vtkm::RangeIdstruct provides the minimum and maximum along that axis.
-
vtkm::RangeId Y
The range of values in the Y direction.
The
vtkm::RangeIdstruct provides the minimum and maximum along that axis.
-
RangeId2() = default
-
struct RangeId3
Represent 3D integer range.
vtkm::RangeId3is a helper class for representing a 3D range of integer values. The typical use of this class is to express a box of indices in the x, y, and z directions.RangeId3also contains several helper functions for computing and maintaining the range.Public Functions
-
RangeId3() = default
Construct an empty 3D range.
-
inline RangeId3(const vtkm::RangeId &xrange, const vtkm::RangeId &yrange, const vtkm::RangeId &zrange)
Construct a range with the given x, y, and z directions.
-
inline RangeId3(vtkm::Id minX, vtkm::Id maxX, vtkm::Id minY, vtkm::Id maxY, vtkm::Id minZ, vtkm::Id maxZ)
Construct a range with the given minimum (inclusive) and maximum (exclusive) points.
-
inline explicit RangeId3(const vtkm::Id range[6])
Initialize range with an array of 6 values in the order xmin, xmax, ymin, ymax, zmin, zmax.
-
inline RangeId3(const vtkm::Id3 &min, const vtkm::Id3 &max)
Initialize range with the minimum and the maximum corners.
-
inline bool IsNonEmpty() const
Determine if the range is non-empty.
IsNonEmptyreturns true if the range is non-empty.
-
inline vtkm::Id3 Center() const
Returns the center of the range.
Centercomputes the middle of the range.
-
template<typename T>
inline void Include(const vtkm::Vec<T, 3> &point) Expand range to include a value.
This version of
Includeexpands the range just enough to include the given value. If the range already include this value, then nothing is done.
-
inline void Include(const vtkm::RangeId3 &range)
Expand range to include other range.
This version of
Includeexpands the range just enough to include the other range. Essentially it is the union of the two ranges.
Public Members
-
vtkm::RangeId X
The range of values in the X direction.
The
vtkm::RangeIdstruct provides the minimum and maximum along that axis.
-
vtkm::RangeId Y
The range of values in the Y direction.
The
vtkm::RangeIdstruct provides the minimum and maximum along that axis.
-
vtkm::RangeId Z
The range of values in the Z direction.
The
vtkm::RangeIdstruct provides the minimum and maximum along that axis.
-
RangeId3() = default
4.1.6. Traits
When using templated types, it is often necessary to get information about the type or specialize code based on general properties of the type. VTK‑m uses traits classes to publish and retrieve information about types. A traits class is simply a templated structure that provides type aliases for tag structures, empty types used for identification. The traits classes might also contain constant numbers and helpful static functions. See Effective C++ Third Edition by Scott Meyers for a description of traits classes and their uses.
4.1.6.1. Type Traits
The vtkm::TypeTraits templated class provides basic information about a core type.
These type traits are available for all the basic C++ types as well as the core VTK‑m types described in Chapter 2.1 (Base Types).
vtkm::TypeTraits contains the following elements.
-
template<typename T>
class TypeTraits The TypeTraits class provides helpful compile-time information about the basic types used in VTKm (and a few others for convenience).
The majority of TypeTraits contents are typedefs to tags that can be used to easily override behavior of called functions.
Subclassed by vtkm::TypeTraits< const T >
Public Types
-
using NumericTag = vtkm::TypeTraitsUnknownTag
A tag to determine whether the type is integer or real.
This tag is either TypeTraitsRealTag or TypeTraitsIntegerTag.
-
using DimensionalityTag = vtkm::TypeTraitsUnknownTag
A tag to determine whether the type has multiple components.
This tag is either TypeTraitsScalarTag or TypeTraitsVectorTag. Scalars can also be treated as vectors with VecTraits.
-
using NumericTag = vtkm::TypeTraitsUnknownTag
The vtkm::TypeTraits::NumericTag will be an alias for one of the following tags.
-
struct TypeTraitsRealTag
Tag used to identify types that store real (floating-point) numbers.
A TypeTraits class will typedef this class to NumericTag if it stores real numbers (or vectors of real numbers).
-
struct TypeTraitsIntegerTag
Tag used to identify types that store integer numbers.
A TypeTraits class will typedef this class to NumericTag if it stores integer numbers (or vectors of integers).
The vtkm::TypeTraits::DimensionalityTag will be an alias for one of the following tags.
-
struct TypeTraitsScalarTag
Tag used to identify 0 dimensional types (scalars).
Scalars can also be treated like vectors when used with VecTraits. A TypeTraits class will typedef this class to DimensionalityTag.
-
struct TypeTraitsVectorTag
Tag used to identify 1 dimensional types (vectors).
A TypeTraits class will typedef this class to DimensionalityTag.
If for some reason one of these tags do not apply, vtkm::TypeTraitsUnknownTag will be used.
-
struct TypeTraitsUnknownTag
Tag used to identify types that aren’t Real, Integer, Scalar or Vector.
The definition of vtkm::TypeTraits for vtkm::Float32 could like something like this.
1namespace vtkm {
2
3template<>
4struct TypeTraits<vtkm::Float32>
5{
6 using NumericTag = vtkm::TypeTraitsRealTag;
7 using DimensionalityTag = vtkm::TypeTraitsScalarTag;
8
9 VTKM_EXEC_CONT
10 static vtkm::Float32 ZeroInitialization() { return vtkm::Float32(0); }
11};
12
13}
Here is a simple example of using vtkm::TypeTraits to implement a generic function that behaves like the remainder operator (%) for all types including floating points and vectors.
1#include <vtkm/TypeTraits.h>
2
3#include <vtkm/Math.h>
4
5template<typename T>
6T AnyRemainder(const T& numerator, const T& denominator);
7
8namespace detail
9{
10
11template<typename T>
12T AnyRemainderImpl(const T& numerator,
13 const T& denominator,
14 vtkm::TypeTraitsIntegerTag,
15 vtkm::TypeTraitsScalarTag)
16{
17 return numerator % denominator;
18}
19
20template<typename T>
21T AnyRemainderImpl(const T& numerator,
22 const T& denominator,
23 vtkm::TypeTraitsRealTag,
24 vtkm::TypeTraitsScalarTag)
25{
26 // The VTK-m math library contains a Remainder function that operates on
27 // floating point numbers.
28 return vtkm::Remainder(numerator, denominator);
29}
30
31template<typename T, typename NumericTag>
32T AnyRemainderImpl(const T& numerator,
33 const T& denominator,
34 NumericTag,
35 vtkm::TypeTraitsVectorTag)
36{
37 T result;
38 for (int componentIndex = 0; componentIndex < T::NUM_COMPONENTS; componentIndex++)
39 {
40 result[componentIndex] =
41 AnyRemainder(numerator[componentIndex], denominator[componentIndex]);
42 }
43 return result;
44}
45
46} // namespace detail
47
48template<typename T>
49T AnyRemainder(const T& numerator, const T& denominator)
50{
51 return detail::AnyRemainderImpl(numerator,
52 denominator,
53 typename vtkm::TypeTraits<T>::NumericTag(),
54 typename vtkm::TypeTraits<T>::DimensionalityTag());
55}
4.1.6.2. Vector Traits
The templated vtkm::Vec class contains several items for introspection (such as the component type and its size).
However, there are other types that behave similarly to vtkm::Vec objects but have different ways to perform this introspection.
For example, VTK‑m contains Vec-like objects that essentially behave the same but might have different features.
Also, there may be reason to interchangeably use basic scalar values, like an integer or floating point number, with vectors.
To provide a consistent interface to access these multiple types that represents vectors, the vtkm::VecTraits templated class provides information and accessors to vector types.It contains the following elements.
-
template<class T>
struct VecTraits Traits that can be queried to treat any type as a
Vec.The VecTraits class gives several static members that define how to use a given type as a vector. This is useful for templated functions and methods that have a parameter that could be either a standard scalar type or a
Vecor some otherVec-like object. When using this class, scalar objects are treated like aVecof size 1.The default implementation of this template treats the type as a scalar. Types that actually behave like vectors should specialize this template to provide the proper information.
Subclassed by vtkm::VecTraits< T & >, vtkm::VecTraits< T * >, vtkm::VecTraits< const T & >, vtkm::VecTraits< const T >, vtkm::internal::SafeVecTraits< T >
Public Types
-
using ComponentType = T
Type of the components in the vector.
If the type is really a scalar, then the component type is the same as the scalar type.
-
using BaseComponentType = T
Base component type in the vector.
Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it returns the base scalar type at the end of the composition (T in this example).
-
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent
A tag specifying whether this vector has multiple components (i.e.
is a “real” vector).
This type is set to either
vtkm::VecTraitsTagSingleComponentif the vector length is size 1 orvtkm::VecTraitsTagMultipleComponentsotherwise. This tag can be useful for creating specialized functions when a vector is really just a scalar. If the vector type is of variable size (that is,IsSizeStaticisvtkm::VecTraitsTagSizeVariable), thenHasMultipleComponentsmight bevtkm::VecTraitsTagMultipleComponentseven when at run time there is only one component.
-
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic
A tag specifying whether the size of this vector is known at compile time.
If set to
VecTraitsTagSizeStatic, thenNUM_COMPONENTSis set. If set toVecTraitsTagSizeVariable, then the number of components is not known at compile time and must be queried withGetNumberOfComponents.
-
template<typename NewComponentType>
using ReplaceComponentType = NewComponentType Get a vector of the same type but with a different component.
This type resolves to another vector with a different component type. For example,
vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2>isvtkm::Vec<T2, N>. This replacement is not recursive. SoVecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>isvtkm::Vec<T2, N>.
-
template<typename NewComponentType>
using ReplaceBaseComponentType = NewComponentType Get a vector of the same type but with a different base component.
This type resolves to another vector with a different base component type. The replacement is recursive for nested types. For example,
VecTraits<Vec<Vec<T, M>, N>::ReplaceBaseComponentType<T2>isVec<Vec<T2, M>, N>.
Public Static Functions
-
static inline constexpr vtkm::IdComponent GetNumberOfComponents(const T&)
Returns the number of components in the given vector.
The result of
GetNumberOfComponents()is the same value ofNUM_COMPONENTSfor vector types that have a static size (that is,IsSizeStaticisvtkm::VecTraitsTagSizeStatic). But unlikeNUM_COMPONENTS,GetNumberOfComponents()works for vectors of any type.
-
static inline const ComponentType &GetComponent(const T &vector, vtkm::IdComponent)
Returns the value in a given component of the vector.
-
static inline ComponentType &GetComponent(T &vector, vtkm::IdComponent)
Returns the value in a given component of the vector.
-
static inline void SetComponent(T &vector, vtkm::IdComponent, ComponentType value)
Changes the value in a given component of the vector.
-
template<vtkm::IdComponent destSize>
static inline void CopyInto(const T &src, vtkm::Vec<ComponentType, destSize> &dest) Copies the components in the given vector into a given Vec object.
Public Static Attributes
-
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1
Number of components in the vector.
This is only defined for vectors of a static size. That is,
NUM_COMPONENTSis not available whenIsSizeStaticis set tovtkm::VecTraitsTagSizeVariable.
-
using ComponentType = T
The vtkm::VecTraits::HasMultipleComponents could be one of the following tags.
-
struct VecTraitsTagMultipleComponents
A tag for vectors that are “true” vectors (i.e.
have more than one component).
-
struct VecTraitsTagSingleComponent
A tag for vectors that are really just scalars (i.e.
have only one component)
The vtkm::VecTraits::IsSizeStatic could be one of the following tags.
-
struct VecTraitsTagSizeStatic
A tag for vectors where the number of components are known at compile time.
-
struct VecTraitsTagSizeVariable
A tag for vectors where the number of components are not determined until run time.
The definition of vtkm::VecTraits for vtkm::Id3 could look something like this.
1namespace vtkm {
2
3template<>
4struct VecTraits<vtkm::Id3>
5{
6 using ComponentType = vtkm::Id;
7 using BaseComponentType = vtkm::Id;
8 static const int NUM_COMPONENTS = 3;
9 using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
10 using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
11
12 VTKM_EXEC_CONT
13 static vtkm::IdComponent GetNumberOfComponents(const vtkm::Id3&)
14 {
15 return NUM_COMPONENTS;
16 }
17
18 VTKM_EXEC_CONT
19 static const vtkm::Id& GetComponent(const vtkm::Id3& vector, int component)
20 {
21 return vector[component];
22 }
23 VTKM_EXEC_CONT
24 static vtkm::Id& GetComponent(vtkm::Id3& vector, int component)
25 {
26 return vector[component];
27 }
28
29 VTKM_EXEC_CONT
30 static void SetComponent(vtkm::Id3& vector, int component, vtkm::Id value)
31 {
32 vector[component] = value;
33 }
34
35 template<typename NewComponentType>
36 using ReplaceComponentType = vtkm::Vec<NewComponentType, 3>;
37
38 template<typename NewComponentType>
39 using ReplaceBaseComponentType = vtkm::Vec<NewComponentType, 3>;
40
41 template<vtkm::IdComponent DestSize>
42 VTKM_EXEC_CONT static void CopyInto(const vtkm::Id3& src,
43 vtkm::Vec<vtkm::Id, DestSize>& dest)
44 {
45 for (vtkm::IdComponent index = 0; (index < NUM_COMPONENTS) && (index < DestSize);
46 index++)
47 {
48 dest[index] = src[index];
49 }
50 }
51};
52
53} // namespace vtkm
The real power of vector traits is that they simplify creating generic operations on any type that can look like a vector. This includes operations on scalar values as if they were vectors of size one. The following code uses vector traits to simplify the implementation of less functors that define an ordering that can be used for sorting and other operations.
1#include <vtkm/VecTraits.h>
2
3// This functor provides a total ordering of vectors. Every compared vector
4// will be either less, greater, or equal (assuming all the vector components
5// also have a total ordering).
6template<typename T>
7struct LessTotalOrder
8{
9 VTKM_EXEC_CONT
10 bool operator()(const T& left, const T& right)
11 {
12 for (int index = 0; index < vtkm::VecTraits<T>::NUM_COMPONENTS; index++)
13 {
14 using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
15 const ComponentType& leftValue = vtkm::VecTraits<T>::GetComponent(left, index);
16 const ComponentType& rightValue = vtkm::VecTraits<T>::GetComponent(right, index);
17 if (leftValue < rightValue)
18 {
19 return true;
20 }
21 if (rightValue < leftValue)
22 {
23 return false;
24 }
25 }
26 // If we are here, the vectors are equal (or at least equivalent).
27 return false;
28 }
29};
30
31// This functor provides a partial ordering of vectors. It returns true if and
32// only if all components satisfy the less operation. It is possible for
33// vectors to be neither less, greater, nor equal, but the transitive closure
34// is still valid.
35template<typename T>
36struct LessPartialOrder
37{
38 VTKM_EXEC_CONT
39 bool operator()(const T& left, const T& right)
40 {
41 for (int index = 0; index < vtkm::VecTraits<T>::NUM_COMPONENTS; index++)
42 {
43 using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
44 const ComponentType& leftValue = vtkm::VecTraits<T>::GetComponent(left, index);
45 const ComponentType& rightValue = vtkm::VecTraits<T>::GetComponent(right, index);
46 if (!(leftValue < rightValue))
47 {
48 return false;
49 }
50 }
51 // If we are here, all components satisfy less than relation.
52 return true;
53 }
54};
4.1.7. List Templates
VTK‑m internally uses template metaprogramming, which utilizes C++ templates to run source-generating programs, to customize code to various data and compute platforms. One basic structure often uses with template metaprogramming is a list of class names (also sometimes called a tuple or vector, although both of those names have different meanings in VTK‑m).
Many VTK‑m users only need predefined lists, such as the type lists specified in Section 4.1.7.2 (Type Lists). Those users can skip most of the details of this section. However, it is sometimes useful to modify lists, create new lists, or operate on lists, and these usages are documented here.
4.1.7.1. Building Lists
A basic list is defined with the vtkm::List template.
-
template<typename ...Ts>
struct List A template used to hold a list of types.
Listis an emptystructthat is used to hold a list of types as its template arguments. VTK-m provides templated types that allows aListto be manipulated and used in numerous ways.
It is common (but not necessary) to use the using keyword to define an alias for a list with a particular meaning.
1#include <vtkm/List.h>
2
3// Placeholder classes representing things that might be in a template
4// metaprogram list.
5class Foo;
6class Bar;
7class Baz;
8class Qux;
9class Xyzzy;
10
11// The names of the following tags are indicative of the lists they contain.
12
13using FooList = vtkm::List<Foo>;
14
15using FooBarList = vtkm::List<Foo, Bar>;
16
17using BazQuxXyzzyList = vtkm::List<Baz, Qux, Xyzzy>;
18
19using QuxBazBarFooList = vtkm::List<Qux, Baz, Bar, Foo>;
VTK‑m defines some special and convenience versions of vtkm::List.
4.1.7.2. Type Lists
One of the major use cases for template metaprogramming lists in VTK‑m is to identify a set of potential data types for arrays.
The vtkm/TypeList.h header contains predefined lists for known VTK‑m types.
The following lists are provided.
-
using vtkm::TypeListIdComponent = vtkm::List<vtkm::IdComponent>
A list containing the type vtkm::IdComponent.
-
using vtkm::TypeListIndex = vtkm::List<vtkm::Id, vtkm::Id2, vtkm::Id3>
A list containing types used to index arrays.
-
using vtkm::TypeListFieldScalar = vtkm::List<vtkm::Float32, vtkm::Float64>
A list containing types used for scalar fields.
Specifically, contains floating point numbers of different widths (i.e. vtkm::Float32 and vtkm::Float64).
-
using vtkm::TypeListFieldVec2 = vtkm::List<vtkm::Vec2f_32, vtkm::Vec2f_64>
A list containing types for values for fields with two dimensional vectors.
-
using vtkm::TypeListFieldVec3 = vtkm::List<vtkm::Vec3f_32, vtkm::Vec3f_64>
A list containing types for values for fields with three dimensional vectors.
-
using vtkm::TypeListFieldVec4 = vtkm::List<vtkm::Vec4f_32, vtkm::Vec4f_64>
A list containing types for values for fields with four dimensional vectors.
-
using vtkm::TypeListFloatVec = vtkm::List<vtkm::Vec2f_32, vtkm::Vec2f_64, vtkm::Vec3f_32, vtkm::Vec3f_64, vtkm::Vec4f_32, vtkm::Vec4f_64>
A list containing common types for floating-point vectors.
Specifically contains floating point vectors of size 2, 3, and 4 with floating point components. Scalars are not included.
-
using vtkm::TypeListField = vtkm::List<vtkm::Float32, vtkm::Float64, vtkm::Vec2f_32, vtkm::Vec2f_64, vtkm::Vec3f_32, vtkm::Vec3f_64, vtkm::Vec4f_32, vtkm::Vec4f_64>
A list containing common types for values in fields.
Specifically contains floating point scalars and vectors of size 2, 3, and 4 with floating point components.
-
using vtkm::TypeListScalarAll = vtkm::List<vtkm::Int8, vtkm::UInt8, vtkm::Int16, vtkm::UInt16, vtkm::Int32, vtkm::UInt32, vtkm::Int64, vtkm::UInt64, vtkm::Float32, vtkm::Float64>
A list of all scalars defined in vtkm/Types.h.
A scalar is a type that holds a single number. This should containing all true variations of scalars, but there might be some arithmetic C types not included. For example, this list contains
signed char, andunsigned char, but notcharas one of those types will behave the same as it. Two of the three types behave the same, but be aware that template resolution will treat them differently.
-
using vtkm::TypeListBaseC = vtkm::ListAppend<vtkm::TypeListScalarAll, vtkm::List<bool, char, signed long, unsigned long>>
-
using vtkm::TypeListVecCommon = vtkm::List<vtkm::Vec2ui_8, vtkm::Vec2i_32, vtkm::Vec2i_64, vtkm::Vec2f_32, vtkm::Vec2f_64, vtkm::Vec3ui_8, vtkm::Vec3i_32, vtkm::Vec3i_64, vtkm::Vec3f_32, vtkm::Vec3f_64, vtkm::Vec4ui_8, vtkm::Vec4i_32, vtkm::Vec4i_64, vtkm::Vec4f_32, vtkm::Vec4f_64>
A list of the most commonly use Vec classes.
Specifically, these are vectors of size 2, 3, or 4 containing either unsigned bytes, signed integers of 32 or 64 bits, or floating point values of 32 or 64 bits.
-
using vtkm::TypeListVecAll = vtkm::ListAppend<vtkm::TypeListVecCommon, vtkm::internal::TypeListVecUncommon>
A list of all vector classes with standard types as components and lengths between 2 and 4.
-
using vtkm::TypeListAll = vtkm::ListAppend<vtkm::TypeListScalarAll, vtkm::TypeListVecAll>
A list of all basic types listed in vtkm/Types.h.
Does not include all possible VTK-m types like arbitrarily typed and sized Vecs (only up to length 4) or math types like matrices.
-
using vtkm::TypeListCommon = vtkm::List<vtkm::UInt8, vtkm::Int32, vtkm::Int64, vtkm::Float32, vtkm::Float64, vtkm::Vec3f_32, vtkm::Vec3f_64>
A list of the most commonly used types across multiple domains.
Includes integers, floating points, and 3 dimensional vectors of floating points.
If these lists are not sufficient, it is possible to build new type lists using the existing type lists and the list bases from Section 4.1.7.1 (Building Lists) as demonstrated in the following example.
1// A list of 2D vector types.
2using Vec2List = vtkm::List<vtkm::Vec2f_32, vtkm::Vec2f_64>;
3
4// An application that uses 2D geometry might commonly encounter this list of
5// types.
6using MyCommonTypes = vtkm::ListAppend<Vec2List, vtkm::TypeListCommon>;
The vtkm/cont/DefaultTypes.h header defines a macro named VTKM_DEFAULT_TYPE_LIST that defines a default list of types to use when, for example, determining the type of a field array.
This macro can change depending on VTK‑m compile options.
4.1.7.3. Querying Lists
vtkm/List.h contains some templated classes to help get information about a list type.
This are particularly useful for lists that are provided as templated parameters for which you do not know the exact type.
4.1.7.3.1. Is a List
The VTKM_IS_LIST does a compile-time check to make sure a particular type is actually a vtkm::List of types.
If the compile-time check fails, then a build error will occur.
This is a good way to verify that a templated class or method that expects a list actually gets a list.
-
VTKM_IS_LIST(type)
Checks that the argument is a proper list.
This is a handy concept check for functions and classes to make sure that a template argument is actually a device adapter tag. (You can get weird errors elsewhere in the code when a mistake is made.)
1template<typename List>
2class MyImportantClass
3{
4 VTKM_IS_LIST(List);
5 // Implementation...
6};
7
8void DoImportantStuff()
9{
10 MyImportantClass<vtkm::List<vtkm::Id>> important1; // This compiles fine
11 MyImportantClass<vtkm::Id> important2; // COMPILE ERROR: vtkm::Id is not a list
4.1.7.3.2. List Size
The size of a list can be determined by using the vtkm::ListSize template.
The type of the template will resolve to a std::integral_constant<vtkm::IdComponent,N> where N is the number of types in the list.
vtkm::ListSize does not work with vtkm::ListUniversal.
-
template<typename List>
using vtkm::ListSize = typename detail::ListSizeImpl<List>::type Becomes an std::integral_constant containing the number of types in a list.
1 using MyList = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
2
3 constexpr vtkm::IdComponent myListSize = vtkm::ListSize<MyList>::value;
4 // myListSize is 3
4.1.7.3.3. List Contains
The vtkm::ListHas template can be used to determine if a vtkm::List contains a particular type.
vtkm::ListHas takes two template parameters.
The first parameter is a form of vtkm::List.
The second parameter is any type to check to see if it is in the list.
If the type is in the list, then vtkm::ListHas resolves to std::true_type.
Otherwise it resolves to std::false_type.
vtkm::ListHas always returns true for vtkm::ListUniversal.
-
template<typename List, typename T>
using vtkm::ListHas = typename detail::ListHasImpl<List, T>::type Checks to see if the given
Tis in the list pointed to byList.Becomes
std::true_typeif theTis inList.std::false_typeotherwise.
1 using MyList = vtkm::List<vtkm::Int8, vtkm::Int16, vtkm::Int32, vtkm::Int64>;
2
3 constexpr bool hasInt = vtkm::ListHas<MyList, int>::value;
4 // hasInt is true
5
6 constexpr bool hasFloat = vtkm::ListHas<MyList, float>::value;
7 // hasFloat is false
4.1.7.3.4. List Indices
The vtkm::ListIndexOf template can be used to get the index of a particular type in a vtkm::List.
vtkm::ListIndexOf takes two template parameters.
The first parameter is a form of vtkm::List.
The second parameter is any type to check to see if it is in the list.
The type of the template will resolve to a std::integral_constant<vtkm::IdComponent,N> where N is the index of the type.
If the requested type is not in the list, then vtkm::ListIndexOf becomes std::integral_constant<vtkm::IdComponent,-1>.
-
template<typename List, typename T>
using vtkm::ListIndexOf = typename detail::ListIndexOfImpl<List, T>::type Finds the index of a given type.
Becomes a
std::integral_constantfor the index of the given type. If the given type is not in the list, the value is set to -1.
Conversely, the vtkm::ListAt template can be used to get the type for a particular index.
The two template parameters for vtkm::ListAt are the vtkm::List and an index for the list.
-
template<typename List, vtkm::IdComponent Index>
using vtkm::ListAt = typename detail::ListAtImpl<List, Index>::type Finds the type at the given index.
This becomes the type of the list at the given index.
Neither vtkm::ListIndexOf nor vtkm::ListAt works with vtkm::ListUniversal.
1 using MyList = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
2
3 constexpr vtkm::IdComponent indexOfInt8 = vtkm::ListIndexOf<MyList, vtkm::Int8>::value;
4 // indexOfInt8 is 0
5 constexpr vtkm::IdComponent indexOfInt32 =
6 vtkm::ListIndexOf<MyList, vtkm::Int32>::value;
7 // indexOfInt32 is 1
8 constexpr vtkm::IdComponent indexOfInt64 =
9 vtkm::ListIndexOf<MyList, vtkm::Int64>::value;
10 // indexOfInt64 is 2
11 constexpr vtkm::IdComponent indexOfFloat32 =
12 vtkm::ListIndexOf<MyList, vtkm::Float32>::value;
13 // indexOfFloat32 is -1 (not in list)
14
15 using T0 = vtkm::ListAt<MyList, 0>; // T0 is vtkm::Int8
16 using T1 = vtkm::ListAt<MyList, 1>; // T1 is vtkm::Int32
17 using T2 = vtkm::ListAt<MyList, 2>; // T2 is vtkm::Int64
4.1.7.4. Operating on Lists
In addition to providing the base templates for defining and querying lists, vtkm/List.h also contains several features for operating on lists.
4.1.7.4.1. Appending Lists
The vtkm::ListAppend template joins together 2 or more vtkm::List types.
The items are concatenated in the order provided to vtkm::ListAppend.
vtkm::ListAppend does not work with vtkm::ListUniversal.
-
template<typename ...Lists>
using vtkm::ListAppend = typename detail::ListAppendImpl<Lists...>::type Concatinates a set of lists into a single list.
Note that this does not work correctly with
vtkm::ListUniversal.
1using BigTypes = vtkm::List<vtkm::Int64, vtkm::Float64>;
2using MediumTypes = vtkm::List<vtkm::Int32, vtkm::Float32>;
3using SmallTypes = vtkm::List<vtkm::Int8>;
4
5using SmallAndBigTypes = vtkm::ListAppend<SmallTypes, BigTypes>;
6// SmallAndBigTypes is vtkm::List<vtkm::Int8, vtkm::Int64, vtkm::Float64>
7
8using AllMyTypes = vtkm::ListAppend<BigTypes, MediumTypes, SmallTypes>;
9// AllMyTypes is
10// vtkm::List<vtkm::Int64, vtkm::Float64, vtkm::Int32, vtkm::Float32, vtkm::Int8>
4.1.7.4.2. Intersecting Lists
The vtkm::ListIntersect template takes two vtkm::List types and becomes a vtkm::List containing all types in both lists.
If one of the lists is vtkm::ListUniversal, the contents of the other list used.
-
template<typename List1, typename List2>
using vtkm::ListIntersect = typename detail::ListIntersectImpl<List1, List2>::type Constructs a list containing types present in all lists.
1using SignedInts = vtkm::List<vtkm::Int8, vtkm::Int16, vtkm::Int32, vtkm::Int64>;
2using WordTypes = vtkm::List<vtkm::Int32, vtkm::UInt32, vtkm::Int64, vtkm::UInt64>;
3
4using SignedWords = vtkm::ListIntersect<SignedInts, WordTypes>;
5// SignedWords is vtkm::List<vtkm::Int32, vtkm::Int64>
4.1.7.4.3. Resolve a Template with all Types in a List
The vtkm::ListApply template transfers all of the types in a vtkm::List to another template.
The first template argument of vtkm::ListApply is the vtkm::List to apply.
The second template argument is another template to apply to.
vtkm::ListApply becomes an instance of the passed template with all the types in the vtkm::List.
vtkm::ListApply can be used to convert a vtkm::List to some other template.
vtkm::ListApply cannot be used with vtkm::ListUniversal.
-
template<typename List, template<typename...> class Target>
using vtkm::ListApply = typename detail::ListApplyImpl<List, Target>::type Applies the list of types to a template.
Given a ListTag and a templated class, returns the class instantiated with the types represented by the ListTag.
1using MyList = vtkm::List<vtkm::Id, vtkm::Id3, vtkm::Vec3f>;
2
3using MyTuple = vtkm::ListApply<MyList, std::tuple>;
4// MyTuple is std::tuple<vtkm::Id, vtkm::Id3, vtkm::Vec3f>
4.1.7.4.4. Transform Each Type in a List
The vtkm::ListTransform template applies each item in a vtkm::List to another template and constructs a list from all these applications.
The first template argument of vtkm::ListTransform is the vtkm::List to apply.
The second template argument is another template to apply to.
vtkm::ListTransform becomes an instance of a new vtkm::List containing the passed template each type.
vtkm::ListTransform cannot be used with vtkm::ListUniversal.
-
template<typename List, template<typename> class Transform>
using vtkm::ListTransform = typename detail::ListTransformImpl<List, Transform>::type Constructs a list containing all types in a source list applied to a transform template.
1using MyList = vtkm::List<vtkm::Int32, vtkm::Float32>;
2
3template<typename T>
4using MakeVec = vtkm::Vec<T, 3>;
5
6using MyVecList = vtkm::ListTransform<MyList, MakeVec>;
7// MyVecList is vtkm::List<vtkm::Vec<vtkm::Int32, 3>, vtkm::Vec<vtkm::Float32, 3>>
4.1.7.4.5. Conditionally Removing Items from a List
The vtkm::ListRemoveIf template removes items from a vtkm::List given a predicate.
The first template argument of vtkm::ListRemoveIf is the vtkm::List.
The second argument is another template that is used as a predicate to determine if the type should be removed or not.
The predicate should become a type with a value member that is a static true or false value.
Any type in the list that the predicate evaluates to true is removed.
vtkm::ListRemoveIf cannot be used with vtkm::ListUniversal.
-
template<typename List, template<typename> class Predicate>
using vtkm::ListRemoveIf = typename detail::ListRemoveIfImpl<List, Predicate>::type Takes an existing
Listand a predicate template that is applied to each type in theList.Any type in the
Listthat has a value element equal to true (the equivalent ofstd::true_type), that item will be removed from the list. For example the following typevtkm::ListRemoveIf<vtkm::List<int, float, long long, double>, std::is_integral>
resolves to a
Listthat is equivalent tovtkm::List<float, double>becausestd::is_integral<int>andstd::is_integral<long long>resolve tostd::true_typewhereasstd::is_integral<float>andstd::is_integral<double>resolve tostd::false_type.
1using MyList =
2 vtkm::List<vtkm::Int64, vtkm::Float64, vtkm::Int32, vtkm::Float32, vtkm::Int8>;
3
4using FilteredList = vtkm::ListRemoveIf<MyList, std::is_integral>;
5// FilteredList is vtkm::List<vtkm::Float64, vtkm::Float32>
4.1.7.4.6. Combine all Pairs of Two Lists
The vtkm::ListCross takes two lists and performs a cross product of them.
It does this by creating a new vtkm::List that contains nested vtkm::List types, each of length 2 and containing all possible pairs of items in the first list with items in the second list.
vtkm::ListCross is often used in conjunction with another list processing command, such as vtkm::ListTransform to build templated types of many combinations.
vtkm::ListCross cannot be used with vtkm::ListUniversal.
-
template<typename List1, typename List2>
using vtkm::ListCross = typename detail::ListCrossImpl<List1, List2>::type Generates a list that is the cross product of two input lists.
The resulting list has the form of
vtkm::List<vtkm::List<A1,B1>, vtkm::List<A1,B2>,...>
1using BaseTypes = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
2using BoolCases = vtkm::List<std::false_type, std::true_type>;
3
4using CrossTypes = vtkm::ListCross<BaseTypes, BoolCases>;
5// CrossTypes is
6// vtkm::List<vtkm::List<vtkm::Int8, std::false_type>,
7// vtkm::List<vtkm::Int8, std::true_type>,
8// vtkm::List<vtkm::Int32, std::false_type>,
9// vtkm::List<vtkm::Int32, std::true_type>,
10// vtkm::List<vtkm::Int64, std::false_type>,
11// vtkm::List<vtkm::Int64, std::true_type>>
12
13template<typename TypeAndIsVec>
14using ListPairToType =
15 typename std::conditional<vtkm::ListAt<TypeAndIsVec, 1>::value,
16 vtkm::Vec<vtkm::ListAt<TypeAndIsVec, 0>, 3>,
17 vtkm::ListAt<TypeAndIsVec, 0>>::type;
18
19using AllTypes = vtkm::ListTransform<CrossTypes, ListPairToType>;
20// AllTypes is
21// vtkm::List<vtkm::Int8,
22// vtkm::Vec<vtkm::Int8, 3>,
23// vtkm::Int32,
24// vtkm::Vec<vtkm::Int32, 3>,
25// vtkm::Int64,
26// vtkm::Vec<vtkm::Int64, 3>>
4.1.7.4.7. Call a Function For Each Type in a List
The vtkm::ListForEach function takes a functor object and a vtkm::List.
It then calls the functor object with the default object of each type in the list.
This is most typically used with C++ run-time type information to convert a run-time polymorphic object to a statically typed (and possibly inlined) call.
-
template<typename Functor, typename ...Ts, typename ...Args>
void vtkm::ListForEach(Functor &&f, vtkm::List<Ts...>, Args&&... args) For each typename represented by the list, call the functor with a default instance of that type.
The following example shows a rudimentary version of converting a dynamically-typed array to a statically-typed array similar to what is done in VTK‑m classes like vtkm::cont::UnknownArrayHandle, which is documented in Chapter 3.5 (Unknown Array Handles).
1struct MyArrayBase
2{
3 // A virtual destructor makes sure C++ RTTI will be generated. It also helps
4 // ensure subclass destructors are called.
5 virtual ~MyArrayBase() {}
6};
7
8template<typename T>
9struct MyArrayImpl : public MyArrayBase
10{
11 std::vector<T> Array;
12};
13
14template<typename T>
15void PrefixSum(std::vector<T>& array)
16{
17 T sum(typename vtkm::VecTraits<T>::ComponentType(0));
18 for (typename std::vector<T>::iterator iter = array.begin(); iter != array.end();
19 iter++)
20 {
21 sum = sum + *iter;
22 *iter = sum;
23 }
24}
25
26struct PrefixSumFunctor
27{
28 MyArrayBase* ArrayPointer;
29
30 PrefixSumFunctor(MyArrayBase* arrayPointer)
31 : ArrayPointer(arrayPointer)
32 {
33 }
34
35 template<typename T>
36 void operator()(T)
37 {
38 using ConcreteArrayType = MyArrayImpl<T>;
39 ConcreteArrayType* concreteArray =
40 dynamic_cast<ConcreteArrayType*>(this->ArrayPointer);
41 if (concreteArray != NULL)
42 {
43 PrefixSum(concreteArray->Array);
44 }
45 }
46};
47
48void DoPrefixSum(MyArrayBase* array)
49{
50 PrefixSumFunctor functor = PrefixSumFunctor(array);
51 vtkm::ListForEach(functor, vtkm::TypeListCommon());
52}
4.1.8. Pair
VTK‑m defines a vtkm::Pair templated object that behaves just like std::pair from the standard template library.
The difference is that vtkm::Pair will work in both the execution and control environments, whereas the STL std::pair does not always work in the execution environment.
-
template<typename T1, typename T2>
struct Pair A
vtkm::Pairis essentially the same as an STL pair object except that the methods (constructors and operators) are defined to work in both the control and execution environments (whereas std::pair is likely to work only in the control environment).Public Types
-
using first_type = FirstType
The same as FirstType, but follows the naming convention of std::pair.
-
using second_type = SecondType
The same as SecondType, but follows the naming convention of std::pair.
Public Functions
-
Pair() = default
-
inline Pair(const FirstType &firstSrc, const SecondType &secondSrc)
-
inline Pair(FirstType &&firstSrc, SecondType &&secondSrc) noexcept(noexcept(FirstType{std::declval<FirstType&&>()}, SecondType{std::declval<SecondType&&>()}))
-
template<typename U1, typename U2>
inline Pair(vtkm::Pair<U1, U2> &&src) noexcept(noexcept(U1{std::declval<U1&&>()}, U2{std::declval<U2&&>()}))
-
template<typename U1, typename U2>
inline Pair(std::pair<U1, U2> &&src) noexcept(noexcept(U1{std::declval<U1&&>()}, U2{std::declval<U2&&>()}))
-
vtkm::Pair<FirstType, SecondType> &operator=(const vtkm::Pair<FirstType, SecondType> &src) = default
-
vtkm::Pair<FirstType, SecondType> &operator=(vtkm::Pair<FirstType, SecondType> &&src) = default
-
inline bool operator==(const vtkm::Pair<FirstType, SecondType> &other) const
-
inline bool operator!=(const vtkm::Pair<FirstType, SecondType> &other) const
-
inline bool operator<(const vtkm::Pair<FirstType, SecondType> &other) const
Tests ordering on the first object, and then on the second object if the first are equal.
-
inline bool operator>(const vtkm::Pair<FirstType, SecondType> &other) const
Tests ordering on the first object, and then on the second object if the first are equal.
-
inline bool operator<=(const vtkm::Pair<FirstType, SecondType> &other) const
Tests ordering on the first object, and then on the second object if the first are equal.
-
inline bool operator>=(const vtkm::Pair<FirstType, SecondType> &other) const
Tests ordering on the first object, and then on the second object if the first are equal.
Public Members
-
FirstType first
The pair’s first object.
Note that this field breaks VTK-m’s naming conventions to make vtkm::Pair more compatible with std::pair.
-
SecondType second
The pair’s second object.
Note that this field breaks VTK-m’s naming conventions to make vtkm::Pair more compatible with std::pair.
-
using first_type = FirstType
The VTK‑m version of vtkm::Pair supports the same types, fields, and operations as the STL version.
VTK‑m also provides a vtkm::make_Pair() function for convenience.
4.1.9. Tuple
VTK‑m defines a vtkm::Tuple templated object that behaves like std::tuple from the standard template library.
The main difference is that vtkm::Tuple will work in both the execution and control environments, whereas the STL std::tuple does not always work in the execution environment.
-
template<typename ...Ts>
class Tuple VTK-m replacement for std::tuple.
This function serves the same function as
std::tupleand behaves similarly. However, this version ofTupleworks on devices that VTK-m supports. There are also some implementation details that makes compiling faster for VTK-m use. We also provide some methods likeApplyandForEachthat are helpful for several VTK-m operations.
4.1.9.1. Defining and Constructing
vtkm::Tuple takes any number of template parameters that define the objects stored the tuple.
1 vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Int32>> myTuple;
You can construct a vtkm::Tuple with arguments that will be used to initialize the respective objects.
As a convenience, you can use vtkm::MakeTuple() to construct a vtkm::Tuple of types based on the arguments.
-
template<typename ...Ts>
auto vtkm::MakeTuple(Ts&&... args) -> vtkm::Tuple<typename std::decay<Ts>::type...> Creates a new
vtkm::Tuplewith the given types.
-
template<typename ...Ts>
auto vtkm::make_tuple(Ts&&... args) -> decltype(vtkm::MakeTuple(std::forward<Ts>(args)...)) Compatible with
std::make_tupleforvtkm::Tuple.
1 // Initialize a tuple with 0, [0, 1, 2], and an existing ArrayHandle.
2 vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>> myTuple1(
3 0, vtkm::Vec3f(0, 1, 2), array);
4
5 // Another way to create the same tuple.
6 auto myTuple2 = vtkm::MakeTuple(vtkm::Id(0), vtkm::Vec3f(0, 1, 2), array);
4.1.9.2. Querying
The size of a vtkm::Tuple can be determined by using the vtkm::TupleSize template, which resolves to an std::integral_constant.
The types at particular indices can be determined with vtkm::TupleElement.
-
template<typename TupleType>
using vtkm::TupleSize = std::integral_constant<vtkm::IdComponent, TupleType::Size> Get the size of a tuple.
Given a
vtkm::Tupletype, becomes astd::integral_constantof the type.
-
template<vtkm::IdComponent Index, typename TupleType>
using vtkm::TupleElement = typename detail::TupleElementImpl<Index, TupleType>::type Becomes the type of the given index for the given
vtkm::Tuple.
1 using TupleType = vtkm::Tuple<vtkm::Id, vtkm::Float32, vtkm::Float64>;
2
3 // Becomes 3
4 constexpr vtkm::IdComponent size = vtkm::TupleSize<TupleType>::value;
5
6 using FirstType = vtkm::TupleElement<0, TupleType>; // vtkm::Id
7 using SecondType = vtkm::TupleElement<1, TupleType>; // vtkm::Float32
8 using ThirdType = vtkm::TupleElement<2, TupleType>; // vtkm::Float64
The function vtkm::Get() can be used to retrieve an element from the vtkm::Tuple.
vtkm::Get() returns a reference to the element, so you can set a vtkm::Tuple element by setting the return value of vtkm::Get().
-
template<vtkm::IdComponent Index, typename ...Ts>
auto vtkm::Get(const vtkm::Tuple<Ts...> &tuple) Retrieve the object from a
vtkm::Tupleat the given index.
-
template<vtkm::IdComponent Index, typename ...Ts>
auto vtkm::Get(vtkm::Tuple<Ts...> &tuple) Retrieve the object from a
vtkm::Tupleat the given index.
-
template<std::size_t Index, typename ...Ts>
auto vtkm::get(const vtkm::Tuple<Ts...> &tuple) -> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple)) Compatible with
std::getforvtkm::Tuple.
-
template<std::size_t Index, typename ...Ts>
auto vtkm::get(vtkm::Tuple<Ts...> &tuple) -> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple)) Compatible with
std::getforvtkm::Tuple.
1 auto myTuple = vtkm::MakeTuple(vtkm::Id3(0, 1, 2), vtkm::Vec3f(3, 4, 5));
2
3 // Gets the value [0, 1, 2]
4 vtkm::Id3 x = vtkm::Get<0>(myTuple);
5
6 // Changes the second object in myTuple to [6, 7, 8]
7 vtkm::Get<1>(myTuple) = vtkm::Vec3f(6, 7, 8);
4.1.9.3. For Each Tuple Value
The vtkm::ForEach() function takes a tuple and a function or functor and calls the function for each of the items in the tuple.
Nothing is returned from vtkm::ForEach(), and any return value from the function is ignored.
-
template<typename ...Ts, typename Function>
void vtkm::ForEach(const vtkm::Tuple<Ts...> &tuple, Function &&f) Call a function with each value of the given tuple.
The function calls will be done in the order of the values in the
vtkm::Tuple.
-
template<typename ...Ts, typename Function>
void vtkm::ForEach(vtkm::Tuple<Ts...> &tuple, Function &&f) Call a function with each value of the given tuple.
The function calls will be done in the order of the values in the
vtkm::Tuple.
vtkm::ForEach() can be used to check the validity of each item in a vtkm::Tuple.
1void CheckPositive(vtkm::Float64 x)
2{
3 if (x < 0)
4 {
5 throw vtkm::cont::ErrorBadValue("Values need to be positive.");
6 }
7}
8
9// ...
10
11 vtkm::Tuple<vtkm::Float64, vtkm::Float64, vtkm::Float64> tuple(
12 CreateValue(0), CreateValue(1), CreateValue(2));
13
14 // Will throw an error if any of the values are negative.
15 vtkm::ForEach(tuple, CheckPositive);
vtkm::ForEach() can also be used to aggregate values in a vtkm::Tuple.
1struct SumFunctor
2{
3 vtkm::Float64 Sum = 0;
4
5 template<typename T>
6 void operator()(const T& x)
7 {
8 this->Sum = this->Sum + static_cast<vtkm::Float64>(x);
9 }
10};
11
12// ...
13
14 vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
15 CreateValue(0), CreateValue(1), CreateValue(2));
16
17 SumFunctor sum;
18 vtkm::ForEach(tuple, sum);
19 vtkm::Float64 average = sum.Sum / 3;
The previous examples used an explicit struct as the functor for clarity.
However, it is often less verbose to use a C++ lambda function.
1 vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
2 CreateValue(0), CreateValue(1), CreateValue(2));
3
4 vtkm::Float64 sum = 0;
5 auto sumFunctor = [&sum](auto x) { sum += static_cast<vtkm::Float64>(x); };
6
7 vtkm::ForEach(tuple, sumFunctor);
8 vtkm::Float64 average = sum / 3;
4.1.9.4. Transform Each Tuple Value
The vtkm::Transform() function builds a new vtkm::Tuple by calling a function or functor on each of the items in an existing vtkm::Tuple.
The return value is placed in the corresponding part of the resulting vtkm::Tuple, and the type is automatically created from the return type of the function.
-
template<typename TupleType, typename Function>
auto vtkm::Transform(const TupleType &&tuple, Function &&f) -> decltype(Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f))) Construct a new
vtkm::Tupleby applying a function to each value.The
vtkm::Transformfunction builds a newvtkm::Tupleby calling a function or functor on each of the items in the giventuple. The return value is placed in the corresponding part of the resulting Tuple, and the type is automatically created from the return type of the function.
-
template<typename TupleType, typename Function>
auto vtkm::Transform(TupleType &&tuple, Function &&f) -> decltype(Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f))) Get the size of a tuple.
Given a
vtkm::Tupletype, becomes astd::integral_constantof the type.
1struct GetReadPortalFunctor
2{
3 template<typename Array>
4 typename Array::ReadPortalType operator()(const Array& array) const
5 {
6 VTKM_IS_ARRAY_HANDLE(Array);
7 return array.ReadPortal();
8 }
9};
10
11// ...
12
13 auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
14
15 auto portalTuple = vtkm::Transform(arrayTuple, GetReadPortalFunctor{});
4.1.9.5. Apply
The vtkm::Apply() function calls a function or functor using the objects in a vtkm::Tuple as the arguments.
If the function returns a value, that value is returned from vtkm::Apply().
-
template<typename ...Ts, typename Function, typename ...Args>
auto vtkm::Apply(const vtkm::Tuple<Ts...> &tuple, Function &&f, Args&&... args) -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...)) Call a function with the values of a
vtkm::Tupleas arguments.If a
vtkm::Tuple<A, B, C>is given with valuesa,b, andc, thenfwill be called asf(a, b, c).Additional arguments can optionally be given to
vtkm::Apply(). These arguments will be added to the beginning of the arguments to the function.The returned value of the function (if any) will be returned from
vtkm::Apply().
-
template<typename ...Ts, typename Function, typename ...Args>
auto vtkm::Apply(vtkm::Tuple<Ts...> &tuple, Function &&f, Args&&... args) -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...)) Call a function with the values of a
vtkm::Tupleas arguments.If a
vtkm::Tuple<A, B, C>is given with valuesa,b, andc, thenfwill be called asf(a, b, c).Additional arguments can optionally be given to
vtkm::Apply(). These arguments will be added to the beginning of the arguments to the function.The returned value of the function (if any) will be returned from
vtkm::Apply().
1struct AddArraysFunctor
2{
3 template<typename Array1, typename Array2, typename Array3>
4 vtkm::Id operator()(Array1 inArray1, Array2 inArray2, Array3 outArray) const
5 {
6 VTKM_IS_ARRAY_HANDLE(Array1);
7 VTKM_IS_ARRAY_HANDLE(Array2);
8 VTKM_IS_ARRAY_HANDLE(Array3);
9
10 vtkm::Id length = inArray1.GetNumberOfValues();
11 VTKM_ASSERT(inArray2.GetNumberOfValues() == length);
12 outArray.Allocate(length);
13
14 auto inPortal1 = inArray1.ReadPortal();
15 auto inPortal2 = inArray2.ReadPortal();
16 auto outPortal = outArray.WritePortal();
17 for (vtkm::Id index = 0; index < length; ++index)
18 {
19 outPortal.Set(index, inPortal1.Get(index) + inPortal2.Get(index));
20 }
21
22 return length;
23 }
24};
25
26// ...
27
28 auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
29
30 vtkm::Id arrayLength = vtkm::Apply(arrayTuple, AddArraysFunctor{});
If additional arguments are given to vtkm::Apply(), they are also passed to the function (before the objects in the vtkm::Tuple).
This is helpful for passing state to the function.
1struct ScanArrayLengthFunctor
2{
3 template<vtkm::IdComponent N, typename Array, typename... Remaining>
4 vtkm::Vec<vtkm::Id, N + 1 + vtkm::IdComponent(sizeof...(Remaining))> operator()(
5 const vtkm::Vec<vtkm::Id, N>& partialResult,
6 const Array& nextArray,
7 const Remaining&... remainingArrays) const
8 {
9 vtkm::Vec<vtkm::Id, N + 1> nextResult;
10 std::copy(&partialResult[0], &partialResult[0] + N, &nextResult[0]);
11 nextResult[N] = nextResult[N - 1] + nextArray.GetNumberOfValues();
12 return (*this)(nextResult, remainingArrays...);
13 }
14
15 template<vtkm::IdComponent N>
16 vtkm::Vec<vtkm::Id, N> operator()(const vtkm::Vec<vtkm::Id, N>& result) const
17 {
18 return result;
19 }
20};
21
22// ...
23
24 auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
25
26 vtkm::Vec<vtkm::Id, 4> sizeScan =
27 vtkm::Apply(arrayTuple, ScanArrayLengthFunctor{}, vtkm::Vec<vtkm::Id, 1>{ 0 });
4.1.10. Error Codes
For operations that occur in the control environment, VTK‑m uses exceptions to report errors as described in Chapter 2.9 (Error Handling).
However, when operating in the execution environment, it is not feasible to throw exceptions. Thus, for operations designed for the execution environment, the status of an operation that can fail is returned as an vtkm::ErrorCode, which is an enum.
-
enum class vtkm::ErrorCode
Identifies whether an operation was successful or what type of error it had.
Most errors in VTK-m are reported by throwing an exception. However, there are some places, most notably the execution environment, where it is not possible to throw an exception. For those cases, it is typical for a function to return an
ErrorCodeidentifier. The calling code can check to see if the operation was a success or what kind of error was encountered otherwise.Use the
vtkm::ErrorString()function to get a descriptive string of the error type.Values:
-
enumerator Success
A successful operation.
This code is returned when the operation was successful. Calling code should check the error code against this identifier when checking the status.
-
enumerator InvalidShapeId
A unknown shape identifier was encountered.
All cell shapes must be listed in
vtkm::CellShapeIdEnum.
-
enumerator InvalidNumberOfPoints
The wrong number of points was provided for a given cell type.
For example, if a triangle has 4 points associated with it, you are likely to get this error.
-
enumerator InvalidCellMetric
A cell metric was requested for a cell that does not support that metric.
-
enumerator WrongShapeIdForTagType
This is an internal error from the lightweight cell library.
-
enumerator InvalidPointId
A bad point identifier was detected while operating on a cell.
-
enumerator InvalidEdgeId
A bad edge identifier was detected while operating on a cell.
-
enumerator InvalidFaceId
A bad face identifier was detected while operating on a cell.
-
enumerator SolutionDidNotConverge
An iterative operation did not find an appropriate solution.
This error code might be returned with some results of an iterative solution. However, solution did not appear to resolve, so the results might not be accurate.
-
enumerator MatrixFactorizationFailed
A solution was not found for a linear system.
Some VTK-m computations use linear algebra to solve a system of equations. If the equations does not give a valid result, this error can be returned.
-
enumerator DegenerateCellDetected
An operation detected a degenerate cell.
A degenerate cell has two or more vertices combined into one, which changes the structure of the cell. For example, if 2 vertices of a tetrahedron are at the same point, the cell degenerates to a triangle. Degenerate cells have the potential to interfere with some computations on cells.
-
enumerator MalformedCellDetected
An operation detected on a malformed cell.
Most cell shapes have some assumptions about their geometry (e.g. not self intersecting). If an operation detects an expected behavior is violated, this error is returned. (Note that
vtkm::DegenerateCellDetectedhas its own error coe.)
-
enumerator OperationOnEmptyCell
An operation was attempted on a cell with an empty shape.
There is a special “empty” cell shape type (
vtkm::CellShapeTagEmpty) that can be used as a placeholder for a cell with no information. Math operations such as interpolation cannot be performed on empty cells, and attempting to do so will result in this error.
-
enumerator CellNotFound
A cell matching some given criteria could not be found.
This error code is most often used in a cell locator where no cell in the given region could be found.
-
enumerator UnknownError
-
enumerator Success
If a function or method returns an vtkm::ErrorCode, it is a good practice to check to make sure that the returned value is vtkm::ErrorCode::Success.
If it is not, you can use the vtkm::ErrorString() function to convert the vtkm::ErrorCode to a descriptive C string.
The easiest thing to do from within a worklet is to call the worklet’s RaiseError method.
-
inline const char *vtkm::ErrorString(vtkm::ErrorCode code) noexcept
Convert a
vtkm::ErrorCodeinto a human-readable string.This method is useful when reporting the results of a function that failed.
1 vtkm::ErrorCode status = cellLocator.FindCell(point, cellId, parametric);
2 if (status != vtkm::ErrorCode::Success)
3 {
4 this->RaiseError(vtkm::ErrorString(status));
5 }