2.1. Base Types

It is common for a framework to define its own types. Even the C++ standard template library defines its own base types like std::size_t and std::pair. VTK‑m is no exception.

In fact VTK‑m provides a great many base types. It is the general coding standard of VTK‑m to not directly use the base C types like int and float and instead to use types declared in VTK‑m. The rational is to precisely declare the representation of each variable to prevent future trouble.

Consider that you are programming something and you need to declare an integer variable. You would declare this variable as int, right? Well, maybe. In C++, the declaration int does not simply mean “an integer.” int means something much more specific than that. If you were to look up the C++11 standard, you would find that int is an integer represented in 32 bits with a two’s complement signed representation. In fact, a C++ compiler has no less than 8 standard integer types.

So, int is nowhere near as general as the code might make it seem, and treating it as such could lead to trouble. For example, consider the MPI standard, which, back in the 1990’s, implicitly selected int for its indexing needs. Fast forward to today where there is a need to reference buffers with more than 2 billion elements, but the standard is stuck with a data type that cannot represent sizes that big. (To be fair, it is possible to represent buffers this large in MPI, but it is extraordinarily awkward to do so.

Consequently, we feel that with VTK‑m it is best to declare the intention of a variable with its declaration, which should help both prevent errors and future proof code. All the types presented in this chapter are declared in vtkm/Types.h, which is typically included either directly or indirectly by all source using VTK‑m.

2.1.1. Floating Point Types

VTK‑m declares 2 types to hold floating point numbers: vtkm::Float32 and vtkm::Float64. These, of course, represent floating point numbers with 32-bits and 64-bits of precision, respectively. These should be used when the precision of a floating point number is predetermined.

using vtkm::Float32 = float

Base type to use for 32-bit floating-point numbers.

using vtkm::Float64 = double

Base type to use for 64-bit floating-point numbers.

When the precision of a floating point number is not predetermined, operations usually have to be overloaded or templated to work with multiple precisions. In cases where a precision must be set, but no particular precision is specified, vtkm::FloatDefault should be used.

using vtkm::FloatDefault = vtkm::Float32

The floating point type to use when no other precision is specified.

vtkm::FloatDefault will be set to either vtkm::Float32 or vtkm::Float64 depending on whether the CMake option VTKm_USE_DOUBLE_PRECISION was set when VTK‑m was compiled, as discussed in Section 1.2.2 (Configuring VTK‑m). Using vtkm::FloatDefault makes it easier for users to trade off precision and speed.

2.1.2. Integer Types

The most common use of an integer in VTK‑m is to index arrays. For this purpose, the vtkm::Id type should be used. (The width of vtkm::Id is determined by the VTKm_USE_64BIT_IDS CMake option.)

using vtkm::Id = vtkm::Int64

Base type to use to index arrays.

This type represents an ID (index into arrays). It should be used whenever indexing data that could grow arbitrarily large.

VTK‑m also has a secondary index type named vtkm::IdComponent, which is smaller and typically used for indexing groups of components within a thread. For example, if you had an array of 3D points, you would use vtkm::Id to reference each point, and you would use vtkm::IdComponent to reference the respective \(x\), \(y\), and \(z\) components.

using vtkm::IdComponent = vtkm::Int32

Base type to use to index small lists.

This type represents a component ID (index of component in a vector). The number of components, being a value fixed at compile time, is generally assumed to be quite small. However, we are currently using a 32-bit width integer because modern processors tend to access them more efficiently than smaller widths.

Did You Know?

The VTK‑m index types, vtkm::Id and vtkm::IdComponent use signed integers. This breaks with the convention of other common index types like the C++ standard template library std::size_t, which use unsigned integers. Unsigned integers make sense for indices as a valid index is always 0 or greater. However, doing things like iterating in a for loop backward, representing relative indices, and representing invalid values is much easier with signed integers. Thus, VTK‑m chooses to use a signed integer for indexing.

VTK‑m also has types to declare an integer of a specific width and sign. The types vtkm::Int8, vtkm::Int16, vtkm::Int32, and vtkm::Int64 specify signed integers of 1, 2, 4, and 8 bytes, respectively. Likewise, the types vtkm::UInt8, vtkm::UInt16, vtkm::UInt32, and vtkm::UInt64 specify unsigned integers of 1, 2, 4, and 8 bytes, respectively.

using vtkm::Int8 = int8_t

Base type to use for 8-bit signed integer numbers.

using vtkm::UInt8 = uint8_t

Base type to use for 8-bit unsigned integer numbers.

using vtkm::Int16 = int16_t

Base type to use for 16-bit signed integer numbers.

using vtkm::UInt16 = uint16_t

Base type to use for 16-bit unsigned integer numbers.

using vtkm::Int32 = int32_t

Base type to use for 32-bit signed integer numbers.

using vtkm::UInt32 = uint32_t

Base type to use for 32-bit unsigned integer numbers.

using vtkm::Int64 = signed long long

Base type to use for 64-bit signed integer numbers.

using vtkm::UInt64 = unsigned long long

Base type to use for 64-bit signed integer numbers.

2.1.3. 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 a collection of base types to represent these short vectors, which are collectively referred to as Vec types.

vtkm::Vec2f, vtkm::Vec3f, and vtkm::Vec4f specify floating point vectors of 2, 3, and 4 components, respectively. The precision of the floating point numbers follows that of vtkm::FloatDefault (which, as documented in Section 2.1.1 (Floating Point Types), is specified by the VTKm_USE_DOUBLE_PRECISION compile option). Components of these and other Vec types can be references through the [ ] operator, much like a C array. A Vec also supports basic arithmetic operators so that it can be used much like its scalar-value counterparts.

using vtkm::Vec2f = vtkm::Vec<vtkm::FloatDefault, 2>

Vec2f corresponds to a 2-dimensional vector of floating point values.

Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is typedef for vtkm::Vec<vtkm::FloatDefault, 2>.

using vtkm::Vec3f = vtkm::Vec<vtkm::FloatDefault, 3>

Vec3f corresponds to a 3-dimensional vector of floating point values.

Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is typedef for vtkm::Vec<vtkm::FloatDefault, 3>.

using vtkm::Vec4f = vtkm::Vec<vtkm::FloatDefault, 4>

Vec4f corresponds to a 4-dimensional vector of floating point values.

Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is typedef for vtkm::Vec<vtkm::FloatDefault, 4>.

Example 2.1 Simple use of Vec objects.
1  vtkm::Vec2f A(1);         // A is (1, 1)
2  A[1] = 3;                 // A is (1, 3) now
3  vtkm::Vec2f B = { 4, 5 }; // B is (4, 5)
4  vtkm::Vec2f C = A + B;    // C is (5, 8)
5  vtkm::FloatDefault manhattanDistance = C[0] + C[1];

You can also specify the precision for each of these vector types by appending the bit size of each component. For example, vtkm::Vec3f_32 and vtkm::Vec3f_64 represent 3-component floating point vectors with each component being 32 bits and 64 bits respectively. Note that the precision number refers to the precision of each component, not the vector as a whole. So vtkm::Vec3f_32 contains 3 32-bit (4-byte) floating point components, which means the entire vtkm::Vec3f_32 requires 96 bits (12 bytes).

using vtkm::Vec2f_32 = vtkm::Vec<vtkm::Float32, 2>

Vec2f_32 corresponds to a 2-dimensional vector of 32-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float32, 2>.

using vtkm::Vec2f_64 = vtkm::Vec<vtkm::Float64, 2>

Vec2f_64 corresponds to a 2-dimensional vector of 64-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float64, 2>.

using vtkm::Vec3f_32 = vtkm::Vec<vtkm::Float32, 3>

Vec3f_32 corresponds to a 3-dimensional vector of 32-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float32, 3>.

using vtkm::Vec3f_64 = vtkm::Vec<vtkm::Float64, 3>

Vec3f_64 corresponds to a 3-dimensional vector of 64-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float64, 3>.

using vtkm::Vec4f_32 = vtkm::Vec<vtkm::Float32, 4>

Vec4f_32 corresponds to a 4-dimensional vector of 32-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float32, 4>.

using vtkm::Vec4f_64 = vtkm::Vec<vtkm::Float64, 4>

Vec4f_64 corresponds to a 4-dimensional vector of 64-bit floating point values.

It is typedef for vtkm::Vec<vtkm::Float64, 4>.

To help with indexing 2-, 3-, and 4- dimensional arrays, VTK‑m provides the types vtkm::Id2, vtkm::Id3, and vtkm::Id4, which are textidentifier{Vec}s of type vtkm::Id. Likewise, VTK‑m provides vtkm::IdComponent2, vtkm::IdComponent3, and vtkm::IdComponent4.

using vtkm::Id2 = vtkm::Vec<vtkm::Id, 2>

Id2 corresponds to a 2-dimensional index.

using vtkm::Id3 = vtkm::Vec<vtkm::Id, 3>

Id3 corresponds to a 3-dimensional index for 3d arrays.

Note that the precision of each index may be less than vtkm::Id.

using vtkm::Id4 = vtkm::Vec<vtkm::Id, 4>

Id4 corresponds to a 4-dimensional index.

using vtkm::IdComponent2 = vtkm::Vec<vtkm::IdComponent, 2>

IdComponent2 corresponds to an index to a local (small) 2-d array or equivalent.

using vtkm::IdComponent3 = vtkm::Vec<vtkm::IdComponent, 3>

IdComponent2 corresponds to an index to a local (small) 3-d array or equivalent.

using vtkm::IdComponent4 = vtkm::Vec<vtkm::IdComponent, 4>

IdComponent4 corresponds to an index to a local (small) 4-d array or equivalent.

VTK‑m also provides types for textidentifier{Vec}s of integers of all varieties described in Section ref{sec:IntegerTypes}. vtkm::Vec2i, vtkm::Vec3i, and vtkm::Vec4i are vectors of signed integers whereas vtkm::Vec2ui, vtkm::Vec3ui, and vtkm::Vec4ui are vectors of unsigned integers. All of these sport components of a width equal to vtkm::Id.

using vtkm::Vec2i = vtkm::Vec<vtkm::Id, 2>

Vec2i corresponds to a 2-dimensional vector of integer values.

Each integer value is of the default precision (i.e. vtkm::Id).

using vtkm::Vec3i = vtkm::Vec<vtkm::Id, 3>

Vec3i corresponds to a 3-dimensional vector of integer values.

Each integer value is of the default precision (i.e. vtkm::Id).

using vtkm::Vec4i = vtkm::Vec<vtkm::Id, 4>

Vec4i corresponds to a 4-dimensional vector of integer values.

Each integer value is of the default precision (i.e. vtkm::Id).

using vtkm::Vec2ui = vtkm::Vec<vtkm::UInt64, 2>

Vec2ui corresponds to a 2-dimensional vector of unsigned integer values.

Each integer value is of the default precision (following vtkm::Id).

using vtkm::Vec3ui = vtkm::Vec<vtkm::UInt64, 3>

Vec3ui corresponds to a 3-dimensional vector of unsigned integer values.

Each integer value is of the default precision (following vtkm::Id).

using vtkm::Vec4ui = vtkm::Vec<vtkm::UInt64, 4>

Vec4ui corresponds to a 4-dimensional vector of unsigned integer values.

Each integer value is of the default precision (following vtkm::Id).

The width can be specified by appending the desired number of bits in the same way as the floating point textidentifier{Vec}s. For example, vtkm::Vec4ui_8 is a textidentifier{Vec} of 4 unsigned bytes.

using vtkm::Vec2i_8 = vtkm::Vec<vtkm::Int8, 2>

Vec2i_8 corresponds to a 2-dimensional vector of 8-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 2>.

using vtkm::Vec2ui_8 = vtkm::Vec<vtkm::UInt8, 2>

Vec2ui_8 corresponds to a 2-dimensional vector of 8-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 2>.

using vtkm::Vec2i_16 = vtkm::Vec<vtkm::Int16, 2>

Vec2i_16 corresponds to a 2-dimensional vector of 16-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 2>.

using vtkm::Vec2ui_16 = vtkm::Vec<vtkm::UInt16, 2>

Vec2ui_16 corresponds to a 2-dimensional vector of 16-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 2>.

using vtkm::Vec2i_32 = vtkm::Vec<vtkm::Int32, 2>

Vec2i_32 corresponds to a 2-dimensional vector of 32-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 2>.

using vtkm::Vec2ui_32 = vtkm::Vec<vtkm::UInt32, 2>

Vec2ui_32 corresponds to a 2-dimensional vector of 32-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 2>.

using vtkm::Vec2i_64 = vtkm::Vec<vtkm::Int64, 2>

Vec2i_64 corresponds to a 2-dimensional vector of 64-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int64, 2>.

using vtkm::Vec2ui_64 = vtkm::Vec<vtkm::UInt64, 2>

Vec2ui_64 corresponds to a 2-dimensional vector of 64-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt64, 2>.

using vtkm::Vec3i_8 = vtkm::Vec<vtkm::Int8, 3>

Vec3i_8 corresponds to a 3-dimensional vector of 8-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 3>.

using vtkm::Vec3ui_8 = vtkm::Vec<vtkm::UInt8, 3>

Vec3ui_8 corresponds to a 3-dimensional vector of 8-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 3>.

using vtkm::Vec3i_16 = vtkm::Vec<vtkm::Int16, 3>

Vec3i_16 corresponds to a 3-dimensional vector of 16-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 3>.

using vtkm::Vec3ui_16 = vtkm::Vec<vtkm::UInt16, 3>

Vec3ui_16 corresponds to a 3-dimensional vector of 16-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 3>.

using vtkm::Vec3i_32 = vtkm::Vec<vtkm::Int32, 3>

Vec3i_32 corresponds to a 3-dimensional vector of 32-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 3>.

using vtkm::Vec3ui_32 = vtkm::Vec<vtkm::UInt32, 3>

Vec3ui_32 corresponds to a 3-dimensional vector of 32-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 3>.

using vtkm::Vec3i_64 = vtkm::Vec<vtkm::Int64, 3>

Vec3i_64 corresponds to a 3-dimensional vector of 64-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int64, 3>.

using vtkm::Vec3ui_64 = vtkm::Vec<vtkm::UInt64, 3>

Vec3ui_64 corresponds to a 3-dimensional vector of 64-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt64, 3>.

using vtkm::Vec4i_8 = vtkm::Vec<vtkm::Int8, 4>

Vec4i_8 corresponds to a 4-dimensional vector of 8-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 4>.

using vtkm::Vec4ui_8 = vtkm::Vec<vtkm::UInt8, 4>

Vec4ui_8 corresponds to a 4-dimensional vector of 8-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 4>.

using vtkm::Vec4i_16 = vtkm::Vec<vtkm::Int16, 4>

Vec4i_16 corresponds to a 4-dimensional vector of 16-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 4>.

using vtkm::Vec4ui_16 = vtkm::Vec<vtkm::UInt16, 4>

Vec4ui_16 corresponds to a 4-dimensional vector of 16-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 4>.

using vtkm::Vec4i_32 = vtkm::Vec<vtkm::Int32, 4>

Vec4i_32 corresponds to a 4-dimensional vector of 32-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int32, 4>.

using vtkm::Vec4ui_32 = vtkm::Vec<vtkm::UInt32, 4>

Vec4ui_32 corresponds to a 4-dimensional vector of 32-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt32, 4>.

using vtkm::Vec4i_64 = vtkm::Vec<vtkm::Int64, 4>

Vec4i_64 corresponds to a 4-dimensional vector of 64-bit integer values.

It is typedef for vtkm::Vec<vtkm::Int64, 4>.

using vtkm::Vec4ui_64 = vtkm::Vec<vtkm::UInt64, 4>

Vec4ui_64 corresponds to a 4-dimensional vector of 64-bit unsigned integer values.

It is typedef for vtkm::Vec<vtkm::UInt64, 4>.

These types really just scratch the surface of the Vec types available in VTK‑m and the things that can be done with them. See Chapter 4.1 (Advanced Types) for more information on Vec types and what can be done with them.