Add advanced types chapter to user's guide

This commit is contained in:
Kenneth Moreland 2023-11-12 20:52:07 -07:00
parent 94ca69f831
commit f1e3bed044
28 changed files with 2641 additions and 221 deletions

@ -0,0 +1,802 @@
==============================
Advanced Types
==============================
:chapref:`base-types:Base Types` introduced some of the base data types defined for use in |VTKm|.
However, for simplicity Chapter :chapref:`base-types: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.
------------------------------
Single Number Types
------------------------------
As described in Chapter :chapref:`base-types:Base Types`, |VTKm| 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 :type:`vtkm::FloatDefault` for floating-point numbers, :type:`vtkm::Id` for array and similar indices, and :type:`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 | | :type:`vtkm::Int8` | :type:`vtkm::UInt8` |
+-------+-----------------------+---------------------+----------------------+
| 2 | | :type:`vtkm::Int16` | :type:`vtkm::UInt16` |
+-------+-----------------------+---------------------+----------------------+
| 4 | :type:`vtkm::Float32` | :type:`vtkm::Int32` | :type:`vtkm::UInt32` |
+-------+-----------------------+---------------------+----------------------+
| 8 | :type:`vtkm::Float64` | :type:`vtkm::Int64` | :type:`vtkm::UInt64` |
+-------+-----------------------+---------------------+----------------------+
These |VTKm|--defined types should be preferred over basic C types like ``int`` or ``float``.
------------------------------
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, |VTKm| provides the :class:`vtkm::Vec` templated type, which is essentially a fixed length array of a given type.
.. doxygenclass:: vtkm::Vec
:members:
The default constructor of :class:`vtkm::Vec` objects leaves the values uninitialized.
All vectors have a constructor with one argument that is used to initialize all components.
All :class:`vtkm::Vec` objects also have a constructor that allows you to set the individual components (one per argument).
All :class:`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 :func:`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.
.. load-example:: CreatingVectorTypes
:file: GuideExampleCoreDataTypes.cxx
:caption: Creating vector types.
.. doxygenfunction:: vtkm::make_Vec
The types :type:`vtkm::Id2`, :type:`vtkm::Id3`, and :type:`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, :type:`vtkm::IdComponent2`, :type:`vtkm::IdComponent3`, and :type:`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 :class:`vtkm::Vec` with all of its template parameters can be cumbersome, |VTKm| provides easy to use aliases for small vectors of base types.
As introduced in :secref:`base-types:Vector Types`, the following type aliases are available.
+-------+------+------------------------+------------------------+-------------------------+
| bytes | size | floating point | signed integer | unsigned integer |
+=======+======+========================+========================+=========================+
| 1 | 2 | | :type:`vtkm::Vec2i_8` | :type:`vtkm::Vec2ui_8` |
+-------+------+------------------------+------------------------+-------------------------+
| | 3 | | :type:`vtkm::Vec3i_8` | :type:`vtkm::Vec3ui_8` |
+-------+------+------------------------+------------------------+-------------------------+
| | 4 | | :type:`vtkm::Vec4i_8` | :type:`vtkm::Vec4ui_8` |
+-------+------+------------------------+------------------------+-------------------------+
| 2 | 2 | | :type:`vtkm::Vec2i_16` | :type:`vtkm::Vec2ui_16` |
+-------+------+------------------------+------------------------+-------------------------+
| | 3 | | :type:`vtkm::Vec3i_16` | :type:`vtkm::Vec3ui_16` |
+-------+------+------------------------+------------------------+-------------------------+
| | 4 | | :type:`vtkm::Vec4i_16` | :type:`vtkm::Vec4ui_16` |
+-------+------+------------------------+------------------------+-------------------------+
| 4 | 2 | :type:`vtkm::Vec2f_32` | :type:`vtkm::Vec2i_32` | :type:`vtkm::Vec2ui_32` |
+-------+------+------------------------+------------------------+-------------------------+
| | 3 | :type:`vtkm::Vec3f_32` | :type:`vtkm::Vec3i_32` | :type:`vtkm::Vec3ui_32` |
+-------+------+------------------------+------------------------+-------------------------+
| | 4 | :type:`vtkm::Vec4f_32` | :type:`vtkm::Vec4i_32` | :type:`vtkm::Vec4ui_32` |
+-------+------+------------------------+------------------------+-------------------------+
| 8 | 2 | :type:`vtkm::Vec2f_64` | :type:`vtkm::Vec2i_64` | :type:`vtkm::Vec2ui_64` |
+-------+------+------------------------+------------------------+-------------------------+
| | 3 | :type:`vtkm::Vec3f_64` | :type:`vtkm::Vec3i_64` | :type:`vtkm::Vec3ui_64` |
+-------+------+------------------------+------------------------+-------------------------+
| | 4 | :type:`vtkm::Vec4f_64` | :type:`vtkm::Vec4i_64` | :type:`vtkm::Vec4ui_64` |
+-------+------+------------------------+------------------------+-------------------------+
:class:`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 :func:`vtkm::Dot` function is overloaded to provide a dot product for every type of vector.
.. load-example:: VectorOperations
:file: GuideExampleCoreDataTypes.cxx
:caption: Vector operations.
These operators, of course, only work if they are also defined for the component type of the :class:`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, :class:`vtkm::Vec` can be repurposed for creating any sequence of homogeneous objects.
Here is a simple example of using :class:`vtkm::Vec` to hold the state of a polygon.
.. load-example:: EquilateralTriangle
:file: GuideExampleCoreDataTypes.cxx
:caption: Repurposing a :class:`vtkm::Vec`.
Vec-like Types
==============================
.. index:: Vec-like
The :class:`vtkm::Vec` class provides a convenient structure for holding and passing small vectors of data.
However, there are times when using :class:`vtkm::Vec` is inconvenient or inappropriate.
For example, the size of :class:`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 :class:`vtkm::Vec` might come from a source that makes it inconvenient or less efficient to construct a :class:`vtkm::Vec`.
For this reason, |VTKm| also provides several |Veclike| objects that behave much like :class:`vtkm::Vec` but are a different class.
These |Veclike| objects have the same interface as :class:`vtkm::Vec` except that the ``NUM_COMPONENTS`` constant is not available on those that are sized at run time.
|Veclike| objects also come with a ``CopyInto`` method that will take their contents and copy them into a standard :class:`vtkm::Vec` class.
(The standard :class:`vtkm::Vec` class also has a :func:`vtkm::Vec::CopyInto` method for consistency.)
C-Array Vec Wrapper
------------------------------
The first |Veclike| object is :class:`vtkm::VecC`, which exposes a C-type array as a :class:`vtkm::Vec`.
.. doxygenclass:: vtkm::VecC
:members:
The constructor for :class:`vtkm::VecC` takes a C array and a size of that array.
There is also a constant version of :class:`vtkm::VecC` named :class:`vtkm::VecCConst`, which takes a constant array and cannot be mutated.
.. doxygenclass:: vtkm::VecCConst
:members:
The ``vtkm/Types.h`` header defines both :class:`vtkm::VecC` and :class:`vtkm::VecCConst` as well as multiple versions of :func:`vtkm::make_VecC` to easily convert a C array to either a :class:`vtkm::VecC` or :class:`vtkm::VecCConst`.
.. doxygenfunction:: vtkm::make_VecC(T*, vtkm::IdComponent)
.. doxygenfunction:: vtkm::make_VecC(const T *array, vtkm::IdComponent size)
The following example demonstrates converting values from a constant table into a :class:`vtkm::VecCConst` for further consumption.
The table and associated methods define how 8 points come together to form a hexahedron.
.. load-example:: VecCExample
:file: GuideExampleCoreDataTypes.cxx
:caption: Using :class:`vtkm::VecCConst` with a constant array.
.. commonerrors::
The :class:`vtkm::VecC` and :class:`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 :class:`vtkm::VecC` or :class:`vtkm::VecCConst` becomes invalid, then using the object becomes invalid.
Make sure that the scope of the :class:`vtkm::VecC` or :class:`vtkm::VecCConst` does not outlive the scope of the data it points to.
Variable-Sized Vec
------------------------------
The next |Veclike| object is :class:`vtkm::VecVariable`, which provides a |Veclike| object that can be resized at run time to a maximum value.
Unlike :class:`vtkm::VecC`, :class:`vtkm::VecVariable` holds its own memory, which makes it a bit safer to use.
But also unlike :class:`vtkm::VecC`, you must define the maximum size of :class:`vtkm::VecVariable` at compile time.
Thus, :class:`vtkm::VecVariable` is really only appropriate to use when there is a predetermined limit to the vector size that is fairly small.
.. doxygenclass:: vtkm::VecVariable
:members:
The following example uses a :class:`vtkm::VecVariable` to store the trace of edges within a hexahedron.
This example uses the methods defined in :numref:`ex:VecVariableExample`.
.. load-example:: VecVariableExample
:file: GuideExampleCoreDataTypes.cxx
:caption: Using :class:`vtkm::VecVariable`.
Vecs from Portals
------------------------------
|VTKm| provides further examples of |Veclike| objects as well.
For example, the :class:`vtkm::VecFromPortal` and :class:`vtkm::VecFromPortalPermute` objects allow you to treat a subsection of an arbitrarily large array as a :class:`vtkm::Vec`.
These objects work by attaching to array portals, which are described in Section~\ref{sec:ArrayPortals}.
.. todo:: Fix reference to array portals.
.. doxygenclass:: vtkm::VecFromPortal
:members:
.. doxygenclass:: vtkm::VecFromPortalPermute
:members:
Point Coordinate Vec
------------------------------
Another example of a |Veclike| object is :class:`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 :chapref:`dataset:Data Sets`.
------------------------------
Range
------------------------------
|VTKm| provides a convenience structure named :class:`vtkm::Range` to help manage a range of values.
The :class:`vtkm::Range` ``struct`` contains two data members, :member:`vtkm::Range::Min` and :member:`vtkm::Range::Max`, which represent the ends of the range of numbers.
:member:`vtkm::Range::Min` and :member:`vtkm::Range::Max` are both of type :type:`vtkm::Float64`.
:member:`vtkm::Range::Min` and :member:`vtkm::Range::Max` can be directly accessed, but :class:`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.
.. doxygenstruct:: vtkm::Range
:members:
The following example demonstrates the operation of :class:`vtkm::Range`.
.. load-example:: UsingRange
:file: GuideExampleCoreDataTypes.cxx
:caption: Using :class:`vtkm::Range`.
------------------------------
Bounds
------------------------------
|VTKm| provides a convenience structure named :class:`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
:class:`vtkm::Bounds` ``struct`` contains three data members,
:member:`vtkm::Bounds::X`, :member:`vtkm::Bounds::Y`, and :member:`vtkm::Bounds::Z`, which represent the range of
the bounds along each respective axis. All three of these members are of
type :class:`vtkm::Range`, which is discussed previously in :secref:`advanced-types:Range`.
:member:`vtkm::Bounds::X`, :member:`vtkm::Bounds::Y`, and :member:`vtkm::Bounds::Z` can
be directly accessed, but :class:`vtkm::Bounds` also comes with the
following helper functions to make it easier to build and use ranges.
.. doxygenstruct:: vtkm::Bounds
:members:
The following example demonstrates the operation of :class:`vtkm::Bounds`.
.. load-example:: UsingBounds
:file: GuideExampleCoreDataTypes.cxx
:caption: Using `vtkm::Bounds`.
------------------------------
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, |VTKm| provides :class:`RangeId`, which behaves similarly to :class:`Range` except for integer values.
.. doxygenstruct:: vtkm::RangeId
:members:
|VTKm| also often must operate on 2D and 3D arrays (particularly for structured cell sets).
For these use cases, :class:`RangeId2` and :class:`RangeId3` are provided.
.. doxygenstruct:: vtkm::RangeId2
:members:
.. doxygenstruct:: vtkm::RangeId3
:members:
------------------------------
Traits
------------------------------
.. index::
single: traits
single: tag
When using templated types, it is often necessary to get information about the type or specialize code based on general properties of the type.
|VTKm| 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.
Type Traits
==============================
.. index::
double: traits; type
The :class:`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 |VTKm| types described in :chapref:`base-types:Base Types`.
:class:`vtkm::TypeTraits` contains the following elements.
.. doxygenclass:: vtkm::TypeTraits
:members:
The :type:`vtkm::TypeTraits::NumericTag` will be an alias for one of the following tags.
.. index::
triple: tag; type; numeric
.. doxygenstruct:: vtkm::TypeTraitsRealTag
.. doxygenstruct:: vtkm::TypeTraitsIntegerTag
The :type:`vtkm::TypeTraits::DimensionalityTag` will be an alias for one of the following tags.
.. index::
triple: tag; type; dimensionality
.. doxygenstruct:: vtkm::TypeTraitsScalarTag
.. doxygenstruct:: vtkm::TypeTraitsVectorTag
If for some reason one of these tags do not apply, :type:`vtkm::TypeTraitsUnknownTag` will be used.
.. doxygenstruct:: vtkm::TypeTraitsUnknownTag
The definition of :class:`vtkm::TypeTraits` for :type:`vtkm::Float32` could like something like this.
.. load-example:: TypeTraitsImpl
:file: GuideExampleTraits.cxx
:caption: Example definition of ``vtkm::TypeTraits<vtkm::Float32>``.
Here is a simple example of using :class:`vtkm::TypeTraits` to implement a generic function that behaves like the remainder operator (``%``) for all types including floating points and vectors.
.. load-example:: TypeTraits
:file: GuideExampleTraits.cxx
:caption: Using :class:`vtkm::TypeTraits` for a generic remainder.
Vector Traits
==============================
.. index::
double: traits; vector
The templated :class:`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 :class:`vtkm::Vec` objects but have different ways to perform this introspection.
.. index:: Vec-like
For example, |VTKm| contains |Veclike| 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 :class:`vtkm::VecTraits` templated class provides information and accessors to vector types.It contains the following elements.
.. doxygenstruct:: vtkm::VecTraits
:members:
The :type:`vtkm::VecTraits::HasMultipleComponents` could be one of the following tags.
.. index::
triple: tag; vector; multiple components
.. doxygenstruct:: vtkm::VecTraitsTagMultipleComponents
.. doxygenstruct:: vtkm::VecTraitsTagSingleComponent
The :type:`vtkm::VecTraits::IsSizeStatic` could be one of the following tags.
.. index::
triple: tag; vector; static
.. doxygenstruct:: vtkm::VecTraitsTagSizeStatic
.. doxygenstruct:: vtkm::VecTraitsTagSizeVariable
The definition of :class:`vtkm::VecTraits` for :type:`vtkm::Id3` could look something like this.
.. load-example:: VecTraitsImpl
:file: GuideExampleTraits.cxx
:caption: Example definition of ``vtkm::VecTraits<vtkm::Id3>``.
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 :index:`less` functors that define an ordering that can be used for sorting and other operations.
.. load-example:: VecTraits
:file: GuideExampleTraits.cxx
:caption: Using :class:`vtkm::VecTraits` for less functors.
------------------------------
List Templates
------------------------------
.. index::
single: lists
single: template metaprogramming
single: metaprogramming
|VTKm| 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 |VTKm|).
Many |VTKm| users only need predefined lists, such as the type lists specified in :secref:`advanced-types: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.
Building Lists
==============================
A basic list is defined with the :class:`vtkm::List` template.
.. doxygenstruct:: vtkm::List
It is common (but not necessary) to use the ``using`` keyword to define an alias for a list with a particular meaning.
.. load-example:: BaseLists
:file: GuideExampleLists.cxx
:caption: Creating lists of types.
|VTKm| defines some special and convenience versions of :class:`vtkm::List`.
.. doxygentypedef:: vtkm::ListEmpty
.. doxygentypedef:: vtkm::ListUniversal
Type Lists
==============================
.. index::
double: type; lists
One of the major use cases for template metaprogramming lists in |VTKm| is to identify a set of potential data types for arrays.
The :file:`vtkm/TypeList.h` header contains predefined lists for known |VTKm| types.
The following lists are provided.
.. doxygentypedef:: vtkm::TypeListId
.. doxygentypedef:: vtkm::TypeListId2
.. doxygentypedef:: vtkm::TypeListId3
.. doxygentypedef:: vtkm::TypeListId4
.. doxygentypedef:: vtkm::TypeListIdComponent
.. doxygentypedef:: vtkm::TypeListIndex
.. doxygentypedef:: vtkm::TypeListFieldScalar
.. doxygentypedef:: vtkm::TypeListFieldVec2
.. doxygentypedef:: vtkm::TypeListFieldVec3
.. doxygentypedef:: vtkm::TypeListFieldVec4
.. doxygentypedef:: vtkm::TypeListFloatVec
.. doxygentypedef:: vtkm::TypeListField
.. doxygentypedef:: vtkm::TypeListScalarAll
.. doxygentypedef:: vtkm::TypeListBaseC
.. doxygentypedef:: vtkm::TypeListVecCommon
.. doxygentypedef:: vtkm::TypeListVecAll
.. doxygentypedef:: vtkm::TypeListAll
.. doxygentypedef:: vtkm::TypeListCommon
If these lists are not sufficient, it is possible to build new type lists using the existing type lists and the list bases from :secref:`advanced-types:Building Lists` as demonstrated in the following example.
.. load-example:: CustomTypeLists
:file: GuideExampleLists.cxx
:caption: Defining new type lists.
The :file:`vtkm/cont/DefaultTypes.h` header defines a macro named :c:macro:`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 |VTKm| compile options.
Querying Lists
==============================
:file:`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.
Is a List
------------------------------
The :c:macro:`VTKM_IS_LIST` does a compile-time check to make sure a particular type is actually a :class:`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.
.. doxygendefine:: VTKM_IS_LIST
.. load-example:: VTKM_IS_LIST
:file: GuideExampleLists.cxx
:caption: Checking that a template parameter is a valid :class:`vtkm::List`.
List Size
------------------------------
The size of a list can be determined by using the :type:`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.
:type:`vtkm::ListSize` does not work with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListSize
.. load-example:: ListSize
:file: GuideExampleLists.cxx
:caption: Getting the size of a :class:`vtkm::List`.
List Contains
------------------------------
The :type:`vtkm::ListHas` template can be used to determine if a :class:`vtkm::List` contains a particular type.
:type:`vtkm::ListHas` takes two template parameters.
The first parameter is a form of :class:`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 :type:`vtkm::ListHas` resolves to ``std::true_type``.
Otherwise it resolves to ``std::false_type``.
:type:`vtkm::ListHas` always returns true for :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListHas
.. load-example:: ListHas
:file: GuideExampleLists.cxx
:caption: Determining if a :class:`vtkm::List` contains a particular type.
List Indices
------------------------------
The :type:`vtkm::ListIndexOf` template can be used to get the index of a particular type in a :class:`vtkm::List`.
:type:`vtkm::ListIndexOf` takes two template parameters.
The first parameter is a form of :class:`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 :type:`vtkm::ListIndexOf` becomes ``std::integral_constant<vtkm::IdComponent,-1>``.
.. doxygentypedef:: vtkm::ListIndexOf
Conversely, the :type:`vtkm::ListAt` template can be used to get the type for a particular index.
The two template parameters for :type:`vtkm::ListAt` are the :class:`vtkm::List` and an index for the list.
.. doxygentypedef:: vtkm::ListAt
Neither :type:`vtkm::ListIndexOf` nor :type:`vtkm::ListAt` works with :type:`vtkm::ListUniversal`.
.. load-example:: ListIndices
:file: GuideExampleLists.cxx
:caption: Using indices with :class:`vtkm::List`.
Operating on Lists
==============================
In addition to providing the base templates for defining and querying lists, :file:`vtkm/List.h` also contains several features for operating on lists.
Appending Lists
------------------------------
The :type:`vtkm::ListAppend` template joins together 2 or more :class:`vtkm::List` types.
The items are concatenated in the order provided to :type:`vtkm::ListAppend`.
:type:`vtkm::ListAppend` does not work with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListAppend
.. load-example:: ListAppend
:file: GuideExampleLists.cxx
:caption: Appending :class:`vtkm::List` types.
Intersecting Lists
------------------------------
The :type:`vtkm::ListIntersect` template takes two :class:`vtkm::List` types and becomes a :class:`vtkm::List` containing all types in both lists.
If one of the lists is :type:`vtkm::ListUniversal`, the contents of the other list used.
.. doxygentypedef:: vtkm::ListIntersect
.. load-example:: ListIntersect
:file: GuideExampleLists.cxx
:caption: Intersecting :class:`vtkm::List` types.
Resolve a Template with all Types in a List
--------------------------------------------------
The :type:`vtkm::ListApply` template transfers all of the types in a :class:`vtkm::List` to another template.
The first template argument of :type:`vtkm::ListApply` is the :class:`vtkm::List` to apply.
The second template argument is another template to apply to.
:type:`vtkm::ListApply` becomes an instance of the passed template with all the types in the :class:`vtkm::List`.
:type:`vtkm::ListApply` can be used to convert a :class:`vtkm::List` to some other template.
:type:`vtkm::ListApply` cannot be used with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListApply
.. load-example:: ListApply
:file: GuideExampleLists.cxx
:caption: Applying a :class:`vtkm::List` to another template.
Transform Each Type in a List
------------------------------
The :type:`vtkm::ListTransform` template applies each item in a :class:`vtkm::List` to another template and constructs a list from all these applications.
The first template argument of :type:`vtkm::ListTransform` is the :class:`vtkm::List` to apply.
The second template argument is another template to apply to.
:type:`vtkm::ListTransform` becomes an instance of a new :class:`vtkm::List` containing the passed template each type.
:type:`vtkm::ListTransform` cannot be used with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListTransform
.. load-example:: ListTransform
:file: GuideExampleLists.cxx
:caption: Transforming a :class:`vtkm::List` using a custom template.
Conditionally Removing Items from a List
----------------------------------------
The :type:`vtkm::ListRemoveIf` template removes items from a :class:`vtkm::List` given a predicate.
The first template argument of :type:`vtkm::ListRemoveIf` is the :class:`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.
:type:`vtkm::ListRemoveIf` cannot be used with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListRemoveIf
.. load-example:: ListRemoveIf
:file: GuideExampleLists.cxx
:caption: Removing items from a :class:`vtkm::List`.
Combine all Pairs of Two Lists
------------------------------
The :type:`vtkm::ListCross` takes two lists and performs a cross product of them.
It does this by creating a new :class:`vtkm::List` that contains nested :class:`vtkm::List` types, each of length 2 and containing all possible pairs of items in the first list with items in the second list.
:type:`vtkm::ListCross` is often used in conjunction with another list processing command, such as :type:`vtkm::ListTransform` to build templated types of many combinations.
:type:`vtkm::ListCross` cannot be used with :type:`vtkm::ListUniversal`.
.. doxygentypedef:: vtkm::ListCross
.. load-example:: ListCross
:file: GuideExampleLists.cxx
:caption: Creating the cross product of 2 :class:`vtkm::List` types.
Call a Function For Each Type in a List
----------------------------------------
The :type:`vtkm::ListForEach` function takes a functor object and a :class:`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.
.. doxygenfunction:: vtkm::ListForEach(Functor &&f, vtkm::List<Ts...>, Args&&... args)
The following example shows a rudimentary version of converting a dynamically-typed array to a statically-typed array similar to what is done in |VTKm| classes like :class:`vtkm::cont::UnknownArrayHandle` (which is documented in Chapter~\ref{chap:UnknownArrayHandle}).
.. todo:: Fix ``UnknownArrayHandle`` chapter reference above.
.. load-example:: ListForEach
:file: GuideExampleLists.cxx
:caption: Converting dynamic types to static types with :type:`vtkm::ListForEach`.
------------------------------
Pair
------------------------------
|VTKm| defines a :class:`vtkm::Pair` templated object that behaves just like ``std::pair`` from the standard template library.
The difference is that :class:`vtkm::Pair` will work in both the execution and control environments, whereas the STL ``std::pair`` does not always work in the execution environment.
.. doxygenstruct:: vtkm::Pair
:members:
:undoc-members:
The |VTKm| version of :class:`vtkm::Pair` supports the same types, fields, and operations as the STL version.
|VTKm| also provides a :func:`vtkm::make_Pair` function for convenience.
.. doxygenfunction:: vtkm::make_Pair
------------------------------
Tuple
------------------------------
|VTKm| defines a :class:`vtkm::Tuple` templated object that behaves like ``std::tuple`` from the standard template library.
The main difference is that :class:`vtkm::Tuple` will work in both the execution and control environments, whereas the STL ``std::tuple`` does not always work in the execution environment.
.. doxygenclass:: vtkm::Tuple
Defining and Constructing
==============================
:class:`vtkm::Tuple` takes any number of template parameters that define the objects stored the tuple.
.. load-example:: DefineTuple
:file: GuideExampleTuple.cxx
:caption: Defining a :class:`vtkm::Tuple`.
You can construct a :class:`vtkm::Tuple` with arguments that will be used to initialize the respective objects.
As a convenience, you can use :func:`vtkm::MakeTuple` to construct a :class:`vtkm::Tuple` of types based on the arguments.
.. doxygenfunction:: vtkm::MakeTuple
.. doxygenfunction:: vtkm::make_tuple
.. load-example:: InitTuple
:file: GuideExampleTuple.cxx
:caption: Initializing values in a :class:`vtkm::Tuple`.
Querying
==============================
The size of a :class:`vtkm::Tuple` can be determined by using the :type:`vtkm::TupleSize` template, which resolves to an ``std::integral_constant``.
The types at particular indices can be determined with :type:`vtkm::TupleElement`.
.. doxygentypedef:: vtkm::TupleSize
.. doxygentypedef:: vtkm::TupleElement
.. load-example:: TupleQuery
:file: GuideExampleTuple.cxx
:caption: Querying :class:`vtkm::Tuple` types.
The function :func:`vtkm::Get` can be used to retrieve an element from the :class:`vtkm::Tuple`.
:func:`vtkm::Get` returns a reference to the element, so you can set a :class:`vtkm::Tuple` element by setting the return value of :func:`vtkm::Get`.
.. doxygenfunction:: vtkm::Get(const vtkm::Tuple<Ts...> &tuple)
.. doxygenfunction:: vtkm::Get(vtkm::Tuple<Ts...> &tuple)
.. doxygenfunction:: vtkm::get(const vtkm::Tuple<Ts...> &tuple)
.. doxygenfunction:: vtkm::get(vtkm::Tuple<Ts...> &tuple)
.. load-example:: TupleGet
:file: GuideExampleTuple.cxx
:caption: Retrieving values from a :class:`vtkm::Tuple`.
For Each Tuple Value
==============================
The :func:`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 :func:`vtkm::ForEach`, and any return value from the function is ignored.
.. doxygenfunction:: vtkm::ForEach(const vtkm::Tuple<Ts...> &tuple, Function &&f)
.. doxygenfunction:: vtkm::ForEach(vtkm::Tuple<Ts...> &tuple, Function &&f)
:func:`vtkm::ForEach` can be used to check the validity of each item in a :class:`vtkm::Tuple`.
.. load-example:: TupleCheck
:file: GuideExampleTuple.cxx
:caption: Using :func:`vtkm::Tuple::ForEach` to check the contents.
:func:`vtkm::ForEach` can also be used to aggregate values in a :class:`vtkm::Tuple`.
.. load-example:: TupleAggregate
:file: GuideExampleTuple.cxx
:caption: Using :func:`vtkm::Tuple::ForEach` to aggregate.
The previous examples used an explicit ``struct`` as the functor for clarity.
However, it is often less verbose to use a C++ lambda function.
.. load-example:: TupleAggregateLambda
:file: GuideExampleTuple.cxx
:caption: Using :func:`vtkm::Tuple::ForEach` to aggregate.
Transform Each Tuple Value
==============================
The :func:`vtkm::Transform` function builds a new :class:`vtkm::Tuple` by calling a function or functor on each of the items in an existing :class:`vtkm::Tuple`.
The return value is placed in the corresponding part of the resulting :class:`vtkm::Tuple`, and the type is automatically created from the return type of the function.
.. doxygenfunction:: vtkm::Transform(const TupleType &&tuple, Function &&f) -> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
.. doxygenfunction:: vtkm::Transform(TupleType &&tuple, Function &&f) -> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
.. load-example:: TupleTransform
:file: GuideExampleTuple.cxx
:caption: Transforming a :class:`vtkm::Tuple`.
Apply
==============================
The :func:`vtkm::Apply` function calls a function or functor using the objects in a :class:`vtkm::Tuple` as the arguments.
If the function returns a value, that value is returned from :func:`vtkm::Apply`.
.. doxygenfunction:: vtkm::Apply(const vtkm::Tuple<Ts...> &tuple, Function &&f, Args&&... args) -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
.. doxygenfunction:: vtkm::Apply(vtkm::Tuple<Ts...> &tuple, Function &&f, Args&&... args) -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
.. load-example:: TupleApply
:file: GuideExampleTuple.cxx
:caption: Applying a :class:`vtkm::Tuple` as arguments to a function.
If additional arguments are given to :func:`vtkm::Apply`, they are also passed to the function (before the objects in the :class:`vtkm::Tuple`).
This is helpful for passing state to the function.
.. load-example:: TupleApplyExtraArgs
:file: GuideExampleTuple.cxx
:caption: Using extra arguments with :func:`vtkm::Tuple::Apply`.
.. todo:: Document ``Variant``.
------------------------------
Error Codes
------------------------------
.. index:: error codes
For operations that occur in the control environment, |VTKm| uses exceptions to report errors as described in :chapref:`error-handling: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 :enum:`vtkm::ErrorCode`, which is an ``enum``.
.. doxygenenum:: vtkm::ErrorCode
If a function or method returns an :enum:`vtkm::ErrorCode`, it is a good practice to check to make sure that the returned value is :enumerator:`vtkm::ErrorCode::Success`.
If it is not, you can use the :func:`vtkm::ErrorString` function to convert the :enum:`vtkm::ErrorCode` to a descriptive C string.
The easiest thing to do from within a worklet is to call the worklet's ``RaiseError`` method.
.. doxygenfunction:: vtkm::ErrorString
.. load-example:: HandleErrorCode
:file: GuideExampleCellLocator.cxx
:caption: Checking an :enum:`vtkm::ErrorCode` and reporting errors in a worklet.

@ -222,6 +222,4 @@ For example, :type:`vtkm::Vec4ui_8` is a \textidentifier{Vec} of 4 unsigned byte
.. doxygentypedef:: vtkm::Vec4ui_64
These types really just scratch the surface of the ``Vec`` types available in |VTKm| and the things that can be done with them.
See ``:chapref:`advanced-types:Advanced Types` `` for more information on ``Vec`` types and what can be done with them.
.. todo:: Update chapter reference.
See :chapref:`advanced-types:Advanced Types` for more information on ``Vec`` types and what can be done with them.

@ -15,7 +15,7 @@ There are multiple base filter classes that we can choose from.
These different classes are documented later in Chapter \ref{chap:FilterTypeReference}.
For this example we will use the :class:`vtkm::filter::FilterField` base class, which is used to derive one field from another field.
.. todo:: Fix above reference.
.. todo:: Fix above reference to filter types chapter.
The following example shows the declaration of our pressure unit conversion filter.
By convention, this declaration would be placed in a header file with a ``.h`` extension.
@ -69,7 +69,7 @@ One of the challenges with writing filters is determining the actual types the a
The :class:`vtkm::cont::Field` object pulled from the input :class:`vtkm::cont::DataSet` contains a :class:`vtkm::cont::ArrayHandle` (see :chapref:`basic-array-handles:Basic Array Handles`), but you do not know what the template parameters of the :class:`vtkm::cont::ArrayHandle` are.
There are numerous ways to extract an array of an unknown type out of a :class:`vtkm::cont::ArrayHandle` (many of which will be explored later in Chapter \ref{chap:UnknownArrayHandle}), but the :class:`vtkm::filter::FilterField` contains some convenience functions to simplify this.
.. todo:: Fix above reference.
.. todo:: Fix above reference to unknown array handle chapter.
In particular, this filter operates specifically on scalar fields.
For this purpose, :class:`vtkm::filter::FilterField` provides the :func:`vtkm::filter::FilterField::CastAndCallScalarField` helper method.
@ -115,4 +115,4 @@ This chapter has just provided a brief introduction to creating filters.
There are several more filter superclasses to help express algorithms of different types.
After some more worklet concepts to implement more complex algorithms are introduced in :partref:`part-advanced:Advanced Development`, we will see a more complete documentation of the types of filters in Chapter \ref{chap:FilterTypeReference}.
.. todo:: Fix above reference.
.. todo:: Fix above reference to filter type reference.

@ -75,6 +75,7 @@ today_fmt = '%B %d, %Y'
rst_prolog = '''
.. |VTKm| replace:: VTKm
.. |Veclike| replace:: ``Vec``-like
.. |report-year| replace:: 2023
.. |report-number| replace:: ORNL/TM-2023/3182
'''

@ -15,13 +15,17 @@ set(examples
GuideExampleEnvironmentModifierMacros.cxx
GuideExampleInitialization.cxx
GuideExampleIO.cxx
GuideExampleLists.cxx
GuideExampleProvidedFilters.cxx
GuideExampleRendering.cxx
GuideExampleRuntimeDeviceTracker.cxx
GuideExampleTimer.cxx
GuideExampleTraits.cxx
GuideExampleTuple.cxx
)
set(examples_device
GuideExampleCellEdgesFaces.cxx
GuideExampleCellLocator.cxx
GuideExampleDataSetCreation.cxx
GuideExampleErrorHandling.cxx
GuideExampleSimpleAlgorithm.cxx

@ -0,0 +1,175 @@
//=============================================================================
//
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
//=============================================================================
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.h>
#include <vtkm/cont/CellLocatorGeneral.h>
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/VecFromPortalPermute.h>
#include <vtkm/exec/CellInterpolate.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
constexpr vtkm::Id DimensionSize = 50;
const vtkm::Id3 DimensionSizes = vtkm::Id3(DimensionSize);
////
//// BEGIN-EXAMPLE UseCellLocator
////
struct QueryCellsWorklet : public vtkm::worklet::WorkletMapField
{
using ControlSignature =
void(FieldIn, ExecObject, WholeCellSetIn<Cell, Point>, WholeArrayIn, FieldOut);
using ExecutionSignature = void(_1, _2, _3, _4, _5);
template<typename Point,
typename CellLocatorExecObject,
typename CellSet,
typename FieldPortal,
typename OutType>
VTKM_EXEC void operator()(const Point& point,
const CellLocatorExecObject& cellLocator,
const CellSet& cellSet,
const FieldPortal& field,
OutType& out) const
{
// Use the cell locator to find the cell containing the point and the parametric
// coordinates within that cell.
vtkm::Id cellId;
vtkm::Vec3f parametric;
////
//// BEGIN-EXAMPLE HandleErrorCode
////
vtkm::ErrorCode status = cellLocator.FindCell(point, cellId, parametric);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
}
////
//// END-EXAMPLE HandleErrorCode
////
// Use this information to interpolate the point field to the given location.
if (cellId >= 0)
{
// Get shape information about the cell containing the point coordinate
auto cellShape = cellSet.GetCellShape(cellId);
auto indices = cellSet.GetIndices(cellId);
// Make a Vec-like containing the field data at the cell's points
auto fieldValues = vtkm::make_VecFromPortalPermute(&indices, &field);
// Do the interpolation
vtkm::exec::CellInterpolate(fieldValues, parametric, cellShape, out);
}
else
{
this->RaiseError("Given point outside of the cell set.");
}
}
};
//
// Later in the associated Filter class...
//
//// PAUSE-EXAMPLE
struct DemoQueryCells
{
vtkm::cont::Invoker Invoke;
vtkm::cont::ArrayHandle<vtkm::Vec3f> QueryPoints;
template<typename FieldType, typename Storage>
VTKM_CONT vtkm::cont::ArrayHandle<FieldType> Run(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<FieldType, Storage>& inputField)
{
//// RESUME-EXAMPLE
////
//// BEGIN-EXAMPLE ConstructCellLocator
////
vtkm::cont::CellLocatorGeneral cellLocator;
cellLocator.SetCellSet(inDataSet.GetCellSet());
cellLocator.SetCoordinates(inDataSet.GetCoordinateSystem());
cellLocator.Update();
////
//// END-EXAMPLE ConstructCellLocator
////
vtkm::cont::ArrayHandle<FieldType> interpolatedField;
this->Invoke(QueryCellsWorklet{},
this->QueryPoints,
&cellLocator,
inDataSet.GetCellSet(),
inputField,
interpolatedField);
////
//// END-EXAMPLE UseCellLocator
////
return interpolatedField;
}
};
void TestCellLocator()
{
using ValueType = vtkm::Vec3f;
using ArrayType = vtkm::cont::ArrayHandle<ValueType>;
vtkm::cont::DataSet data = vtkm::cont::DataSetBuilderUniform::Create(DimensionSizes);
ArrayType inField;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleUniformPointCoordinates(
DimensionSizes, ValueType(0.0f), ValueType(2.0f)),
inField);
DemoQueryCells demo;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleUniformPointCoordinates(
DimensionSizes - vtkm::Id3(1), ValueType(0.5f)),
demo.QueryPoints);
ArrayType interpolated = demo.Run(data, inField);
vtkm::cont::ArrayHandleUniformPointCoordinates expected(
DimensionSizes - vtkm::Id3(1), ValueType(1.0f), ValueType(2.0f));
std::cout << "Expected: ";
vtkm::cont::printSummary_ArrayHandle(expected, std::cout);
std::cout << "Interpolated: ";
vtkm::cont::printSummary_ArrayHandle(interpolated, std::cout);
VTKM_TEST_ASSERT(test_equal_portals(expected.ReadPortal(), interpolated.ReadPortal()));
}
void Run()
{
TestCellLocator();
}
} // anonymous namespace
int GuideExampleCellLocator(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}

@ -0,0 +1,476 @@
//=============================================================================
//
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
//=============================================================================
#include <vtkm/List.h>
#include <vtkm/TypeList.h>
namespace
{
////
//// BEGIN-EXAMPLE CustomTypeLists
////
// A list of 2D vector types.
using Vec2List = vtkm::List<vtkm::Vec2f_32, vtkm::Vec2f_64>;
// An application that uses 2D geometry might commonly encounter this list of
// types.
using MyCommonTypes = vtkm::ListAppend<Vec2List, vtkm::TypeListCommon>;
////
//// END-EXAMPLE CustomTypeLists
////
VTKM_STATIC_ASSERT((std::is_same<vtkm::ListAt<Vec2List, 0>, vtkm::Vec2f_32>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::ListAt<Vec2List, 1>, vtkm::Vec2f_64>::value));
VTKM_STATIC_ASSERT((std::is_same<MyCommonTypes,
vtkm::List<vtkm::Vec2f_32,
vtkm::Vec2f_64,
vtkm::UInt8,
vtkm::Int32,
vtkm::Int64,
vtkm::Float32,
vtkm::Float64,
vtkm::Vec3f_32,
vtkm::Vec3f_64>>::value));
} // anonymous namespace
#include <vtkm/VecTraits.h>
#include <vtkm/testing/Testing.h>
#include <algorithm>
#include <string>
#include <vector>
////
//// BEGIN-EXAMPLE BaseLists
////
#include <vtkm/List.h>
//// PAUSE-EXAMPLE
namespace
{
//// RESUME-EXAMPLE
// Placeholder classes representing things that might be in a template
// metaprogram list.
class Foo;
class Bar;
class Baz;
class Qux;
class Xyzzy;
// The names of the following tags are indicative of the lists they contain.
using FooList = vtkm::List<Foo>;
using FooBarList = vtkm::List<Foo, Bar>;
using BazQuxXyzzyList = vtkm::List<Baz, Qux, Xyzzy>;
using QuxBazBarFooList = vtkm::List<Qux, Baz, Bar, Foo>;
////
//// END-EXAMPLE BaseLists
////
class Foo
{
};
class Bar
{
};
class Baz
{
};
class Qux
{
};
class Xyzzy
{
};
struct ListFunctor
{
std::string FoundTags;
template<typename T>
void operator()(T)
{
this->FoundTags.append(vtkm::testing::TypeName<T>::Name());
}
void operator()(Foo) { this->FoundTags.append("Foo"); }
void operator()(Bar) { this->FoundTags.append("Bar"); }
void operator()(Baz) { this->FoundTags.append("Baz"); }
void operator()(Qux) { this->FoundTags.append("Qux"); }
void operator()(Xyzzy) { this->FoundTags.append("Xyzzy"); }
};
template<typename List>
void TryList(List, const char* expectedString)
{
ListFunctor checkFunctor;
vtkm::ListForEach(checkFunctor, List());
std::cout << std::endl
<< "Expected " << expectedString << std::endl
<< "Found " << checkFunctor.FoundTags << std::endl;
VTKM_TEST_ASSERT(checkFunctor.FoundTags == expectedString, "List wrong");
}
void TestBaseLists()
{
TryList(FooList(), "Foo");
TryList(FooBarList(), "FooBar");
TryList(BazQuxXyzzyList(), "BazQuxXyzzy");
TryList(QuxBazBarFooList(), "QuxBazBarFoo");
}
////
//// BEGIN-EXAMPLE VTKM_IS_LIST
////
template<typename List>
class MyImportantClass
{
VTKM_IS_LIST(List);
// Implementation...
};
void DoImportantStuff()
{
MyImportantClass<vtkm::List<vtkm::Id>> important1; // This compiles fine
//// PAUSE-EXAMPLE
#if 0
//// RESUME-EXAMPLE
MyImportantClass<vtkm::Id> important2; // COMPILE ERROR: vtkm::Id is not a list
////
//// END-EXAMPLE VTKM_IS_LIST
////
//// PAUSE-EXAMPLE
#endif
(void)important1; // Quiet compiler
//// RESUME-EXAMPLE
}
void TestCheckListType()
{
DoImportantStuff();
}
void TestListSize()
{
////
//// BEGIN-EXAMPLE ListSize
////
using MyList = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
constexpr vtkm::IdComponent myListSize = vtkm::ListSize<MyList>::value;
// myListSize is 3
////
//// END-EXAMPLE ListSize
////
VTKM_STATIC_ASSERT(myListSize == 3);
}
void TestListHas()
{
////
//// BEGIN-EXAMPLE ListHas
////
using MyList = vtkm::List<vtkm::Int8, vtkm::Int16, vtkm::Int32, vtkm::Int64>;
constexpr bool hasInt = vtkm::ListHas<MyList, int>::value;
// hasInt is true
constexpr bool hasFloat = vtkm::ListHas<MyList, float>::value;
// hasFloat is false
////
//// END-EXAMPLE ListHas
////
VTKM_STATIC_ASSERT(hasInt);
VTKM_STATIC_ASSERT(!hasFloat);
}
void TestListIndices()
{
////
//// BEGIN-EXAMPLE ListIndices
////
using MyList = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
constexpr vtkm::IdComponent indexOfInt8 = vtkm::ListIndexOf<MyList, vtkm::Int8>::value;
// indexOfInt8 is 0
constexpr vtkm::IdComponent indexOfInt32 =
vtkm::ListIndexOf<MyList, vtkm::Int32>::value;
// indexOfInt32 is 1
constexpr vtkm::IdComponent indexOfInt64 =
vtkm::ListIndexOf<MyList, vtkm::Int64>::value;
// indexOfInt64 is 2
constexpr vtkm::IdComponent indexOfFloat32 =
vtkm::ListIndexOf<MyList, vtkm::Float32>::value;
// indexOfFloat32 is -1 (not in list)
using T0 = vtkm::ListAt<MyList, 0>; // T0 is vtkm::Int8
using T1 = vtkm::ListAt<MyList, 1>; // T1 is vtkm::Int32
using T2 = vtkm::ListAt<MyList, 2>; // T2 is vtkm::Int64
////
//// END-EXAMPLE ListIndices
////
VTKM_TEST_ASSERT(indexOfInt8 == 0);
VTKM_TEST_ASSERT(indexOfInt32 == 1);
VTKM_TEST_ASSERT(indexOfInt64 == 2);
VTKM_TEST_ASSERT(indexOfFloat32 == -1);
VTKM_STATIC_ASSERT((std::is_same<T0, vtkm::Int8>::value));
VTKM_STATIC_ASSERT((std::is_same<T1, vtkm::Int32>::value));
VTKM_STATIC_ASSERT((std::is_same<T2, vtkm::Int64>::value));
}
namespace TestListAppend
{
////
//// BEGIN-EXAMPLE ListAppend
////
using BigTypes = vtkm::List<vtkm::Int64, vtkm::Float64>;
using MediumTypes = vtkm::List<vtkm::Int32, vtkm::Float32>;
using SmallTypes = vtkm::List<vtkm::Int8>;
using SmallAndBigTypes = vtkm::ListAppend<SmallTypes, BigTypes>;
// SmallAndBigTypes is vtkm::List<vtkm::Int8, vtkm::Int64, vtkm::Float64>
using AllMyTypes = vtkm::ListAppend<BigTypes, MediumTypes, SmallTypes>;
// AllMyTypes is
// vtkm::List<vtkm::Int64, vtkm::Float64, vtkm::Int32, vtkm::Float32, vtkm::Int8>
////
//// END-EXAMPLE ListAppend
////
VTKM_STATIC_ASSERT(
(std::is_same<SmallAndBigTypes,
vtkm::List<vtkm::Int8, vtkm::Int64, vtkm::Float64>>::value));
VTKM_STATIC_ASSERT(
(std::is_same<
AllMyTypes,
vtkm::List<vtkm::Int64, vtkm::Float64, vtkm::Int32, vtkm::Float32, vtkm::Int8>>::
value));
}
namespace TestListIntersect
{
////
//// BEGIN-EXAMPLE ListIntersect
////
using SignedInts = vtkm::List<vtkm::Int8, vtkm::Int16, vtkm::Int32, vtkm::Int64>;
using WordTypes = vtkm::List<vtkm::Int32, vtkm::UInt32, vtkm::Int64, vtkm::UInt64>;
using SignedWords = vtkm::ListIntersect<SignedInts, WordTypes>;
// SignedWords is vtkm::List<vtkm::Int32, vtkm::Int64>
////
//// END-EXAMPLE ListIntersect
////
VTKM_STATIC_ASSERT(
(std::is_same<SignedWords, vtkm::List<vtkm::Int32, vtkm::Int64>>::value));
}
namespace TestListApply
{
////
//// BEGIN-EXAMPLE ListApply
////
using MyList = vtkm::List<vtkm::Id, vtkm::Id3, vtkm::Vec3f>;
using MyTuple = vtkm::ListApply<MyList, std::tuple>;
// MyTuple is std::tuple<vtkm::Id, vtkm::Id3, vtkm::Vec3f>
////
//// END-EXAMPLE ListApply
////
VTKM_STATIC_ASSERT(
(std::is_same<MyTuple, std::tuple<vtkm::Id, vtkm::Id3, vtkm::Vec3f>>::value));
}
namespace TestListTransform
{
////
//// BEGIN-EXAMPLE ListTransform
////
using MyList = vtkm::List<vtkm::Int32, vtkm::Float32>;
template<typename T>
using MakeVec = vtkm::Vec<T, 3>;
using MyVecList = vtkm::ListTransform<MyList, MakeVec>;
// MyVecList is vtkm::List<vtkm::Vec<vtkm::Int32, 3>, vtkm::Vec<vtkm::Float32, 3>>
////
//// END-EXAMPLE ListTransform
////
VTKM_STATIC_ASSERT((std::is_same<MyVecList,
vtkm::List<vtkm::Vec<vtkm::Int32, 3>,
vtkm::Vec<vtkm::Float32, 3>>>::value));
}
namespace TestListRemoveIf
{
////
//// BEGIN-EXAMPLE ListRemoveIf
////
using MyList =
vtkm::List<vtkm::Int64, vtkm::Float64, vtkm::Int32, vtkm::Float32, vtkm::Int8>;
using FilteredList = vtkm::ListRemoveIf<MyList, std::is_integral>;
// FilteredList is vtkm::List<vtkm::Float64, vtkm::Float32>
////
//// END-EXAMPLE ListRemoveIf
////
VTKM_STATIC_ASSERT(
(std::is_same<FilteredList, vtkm::List<vtkm::Float64, vtkm::Float32>>::value));
}
namespace TestListCross
{
////
//// BEGIN-EXAMPLE ListCross
////
using BaseTypes = vtkm::List<vtkm::Int8, vtkm::Int32, vtkm::Int64>;
using BoolCases = vtkm::List<std::false_type, std::true_type>;
using CrossTypes = vtkm::ListCross<BaseTypes, BoolCases>;
// CrossTypes is
// vtkm::List<vtkm::List<vtkm::Int8, std::false_type>,
// vtkm::List<vtkm::Int8, std::true_type>,
// vtkm::List<vtkm::Int32, std::false_type>,
// vtkm::List<vtkm::Int32, std::true_type>,
// vtkm::List<vtkm::Int64, std::false_type>,
// vtkm::List<vtkm::Int64, std::true_type>>
template<typename TypeAndIsVec>
using ListPairToType =
typename std::conditional<vtkm::ListAt<TypeAndIsVec, 1>::value,
vtkm::Vec<vtkm::ListAt<TypeAndIsVec, 0>, 3>,
vtkm::ListAt<TypeAndIsVec, 0>>::type;
using AllTypes = vtkm::ListTransform<CrossTypes, ListPairToType>;
// AllTypes is
// vtkm::List<vtkm::Int8,
// vtkm::Vec<vtkm::Int8, 3>,
// vtkm::Int32,
// vtkm::Vec<vtkm::Int32, 3>,
// vtkm::Int64,
// vtkm::Vec<vtkm::Int64, 3>>
////
//// END-EXAMPLE ListCross
////
VTKM_STATIC_ASSERT(
(std::is_same<CrossTypes,
vtkm::List<vtkm::List<vtkm::Int8, std::false_type>,
vtkm::List<vtkm::Int8, std::true_type>,
vtkm::List<vtkm::Int32, std::false_type>,
vtkm::List<vtkm::Int32, std::true_type>,
vtkm::List<vtkm::Int64, std::false_type>,
vtkm::List<vtkm::Int64, std::true_type>>>::value));
VTKM_STATIC_ASSERT((std::is_same<AllTypes,
vtkm::List<vtkm::Int8,
vtkm::Vec<vtkm::Int8, 3>,
vtkm::Int32,
vtkm::Vec<vtkm::Int32, 3>,
vtkm::Int64,
vtkm::Vec<vtkm::Int64, 3>>>::value));
}
////
//// BEGIN-EXAMPLE ListForEach
////
struct MyArrayBase
{
// A virtual destructor makes sure C++ RTTI will be generated. It also helps
// ensure subclass destructors are called.
virtual ~MyArrayBase() {}
};
template<typename T>
struct MyArrayImpl : public MyArrayBase
{
std::vector<T> Array;
};
template<typename T>
void PrefixSum(std::vector<T>& array)
{
T sum(typename vtkm::VecTraits<T>::ComponentType(0));
for (typename std::vector<T>::iterator iter = array.begin(); iter != array.end();
iter++)
{
sum = sum + *iter;
*iter = sum;
}
}
struct PrefixSumFunctor
{
MyArrayBase* ArrayPointer;
PrefixSumFunctor(MyArrayBase* arrayPointer)
: ArrayPointer(arrayPointer)
{
}
template<typename T>
void operator()(T)
{
using ConcreteArrayType = MyArrayImpl<T>;
ConcreteArrayType* concreteArray =
dynamic_cast<ConcreteArrayType*>(this->ArrayPointer);
if (concreteArray != NULL)
{
PrefixSum(concreteArray->Array);
}
}
};
void DoPrefixSum(MyArrayBase* array)
{
PrefixSumFunctor functor = PrefixSumFunctor(array);
vtkm::ListForEach(functor, vtkm::TypeListCommon());
}
////
//// END-EXAMPLE ListForEach
////
void TestPrefixSum()
{
MyArrayImpl<vtkm::Id> array;
array.Array.resize(10);
std::fill(array.Array.begin(), array.Array.end(), 1);
DoPrefixSum(&array);
for (vtkm::Id index = 0; index < 10; index++)
{
VTKM_TEST_ASSERT(array.Array[(std::size_t)index] == index + 1,
"Got bad prefix sum.");
}
}
void Test()
{
TestBaseLists();
TestCheckListType();
TestListSize();
TestListHas();
TestListIndices();
TestPrefixSum();
}
} // anonymous namespace
int GuideExampleLists(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,359 @@
//=============================================================================
//
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
//=============================================================================
#include <vtkm/TypeTraits.h>
#include <vtkm/VecTraits.h>
#include <vtkm/testing/Testing.h>
////
//// BEGIN-EXAMPLE TypeTraits
////
#include <vtkm/TypeTraits.h>
#include <vtkm/Math.h>
//// PAUSE-EXAMPLE
namespace TraitsExamples
{
//// RESUME-EXAMPLE
template<typename T>
T AnyRemainder(const T& numerator, const T& denominator);
namespace detail
{
template<typename T>
T AnyRemainderImpl(const T& numerator,
const T& denominator,
vtkm::TypeTraitsIntegerTag,
vtkm::TypeTraitsScalarTag)
{
return numerator % denominator;
}
template<typename T>
T AnyRemainderImpl(const T& numerator,
const T& denominator,
vtkm::TypeTraitsRealTag,
vtkm::TypeTraitsScalarTag)
{
// The VTK-m math library contains a Remainder function that operates on
// floating point numbers.
return vtkm::Remainder(numerator, denominator);
}
template<typename T, typename NumericTag>
T AnyRemainderImpl(const T& numerator,
const T& denominator,
NumericTag,
vtkm::TypeTraitsVectorTag)
{
T result;
for (int componentIndex = 0; componentIndex < T::NUM_COMPONENTS; componentIndex++)
{
result[componentIndex] =
AnyRemainder(numerator[componentIndex], denominator[componentIndex]);
}
return result;
}
} // namespace detail
template<typename T>
T AnyRemainder(const T& numerator, const T& denominator)
{
return detail::AnyRemainderImpl(numerator,
denominator,
typename vtkm::TypeTraits<T>::NumericTag(),
typename vtkm::TypeTraits<T>::DimensionalityTag());
}
////
//// END-EXAMPLE TypeTraits
////
void TryRemainder()
{
vtkm::Id m1 = AnyRemainder(7, 3);
VTKM_TEST_ASSERT(m1 == 1, "Got bad remainder");
vtkm::Float32 m2 = AnyRemainder(7.0f, 3.0f);
VTKM_TEST_ASSERT(test_equal(m2, 1), "Got bad remainder");
vtkm::Id3 m3 = AnyRemainder(vtkm::Id3(10, 9, 8), vtkm::Id3(7, 6, 5));
VTKM_TEST_ASSERT(test_equal(m3, vtkm::Id3(3, 3, 3)), "Got bad remainder");
vtkm::Vec3f_32 m4 = AnyRemainder(vtkm::make_Vec(10, 9, 8), vtkm::make_Vec(7, 6, 5));
VTKM_TEST_ASSERT(test_equal(m4, vtkm::make_Vec(3, 3, 3)), "Got bad remainder");
}
template<typename T>
struct TypeTraits;
////
//// BEGIN-EXAMPLE TypeTraitsImpl
////
//// PAUSE-EXAMPLE
#if 0
//// RESUME-EXAMPLE
namespace vtkm {
//// PAUSE-EXAMPLE
#endif
//// RESUME-EXAMPLE
template<>
struct TypeTraits<vtkm::Float32>
{
using NumericTag = vtkm::TypeTraitsRealTag;
using DimensionalityTag = vtkm::TypeTraitsScalarTag;
VTKM_EXEC_CONT
static vtkm::Float32 ZeroInitialization() { return vtkm::Float32(0); }
};
//// PAUSE-EXAMPLE
#if 0
//// RESUME-EXAMPLE
}
//// PAUSE-EXAMPLE
#endif
//// RESUME-EXAMPLE
////
//// END-EXAMPLE TypeTraitsImpl
////
void TryCustomTypeTraits()
{
using CustomTraits = TraitsExamples::TypeTraits<vtkm::Float32>;
using OriginalTraits = vtkm::TypeTraits<vtkm::Float32>;
VTKM_STATIC_ASSERT(
(std::is_same<CustomTraits::NumericTag, OriginalTraits::NumericTag>::value));
VTKM_STATIC_ASSERT((std::is_same<CustomTraits::DimensionalityTag,
OriginalTraits::DimensionalityTag>::value));
VTKM_TEST_ASSERT(CustomTraits::ZeroInitialization() ==
OriginalTraits::ZeroInitialization(),
"Bad zero initialization.");
}
} // namespace TraitsExamples
////
//// BEGIN-EXAMPLE VecTraits
////
#include <vtkm/VecTraits.h>
//// PAUSE-EXAMPLE
namespace TraitsExamples
{
//// RESUME-EXAMPLE
// This functor provides a total ordering of vectors. Every compared vector
// will be either less, greater, or equal (assuming all the vector components
// also have a total ordering).
template<typename T>
struct LessTotalOrder
{
VTKM_EXEC_CONT
bool operator()(const T& left, const T& right)
{
for (int index = 0; index < vtkm::VecTraits<T>::NUM_COMPONENTS; index++)
{
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
const ComponentType& leftValue = vtkm::VecTraits<T>::GetComponent(left, index);
const ComponentType& rightValue = vtkm::VecTraits<T>::GetComponent(right, index);
if (leftValue < rightValue)
{
return true;
}
if (rightValue < leftValue)
{
return false;
}
}
// If we are here, the vectors are equal (or at least equivalent).
return false;
}
};
// This functor provides a partial ordering of vectors. It returns true if and
// only if all components satisfy the less operation. It is possible for
// vectors to be neither less, greater, nor equal, but the transitive closure
// is still valid.
template<typename T>
struct LessPartialOrder
{
VTKM_EXEC_CONT
bool operator()(const T& left, const T& right)
{
for (int index = 0; index < vtkm::VecTraits<T>::NUM_COMPONENTS; index++)
{
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
const ComponentType& leftValue = vtkm::VecTraits<T>::GetComponent(left, index);
const ComponentType& rightValue = vtkm::VecTraits<T>::GetComponent(right, index);
if (!(leftValue < rightValue))
{
return false;
}
}
// If we are here, all components satisfy less than relation.
return true;
}
};
////
//// END-EXAMPLE VecTraits
////
void TryLess()
{
LessTotalOrder<vtkm::Id> totalLess1;
VTKM_TEST_ASSERT(totalLess1(1, 2), "Bad less.");
VTKM_TEST_ASSERT(!totalLess1(2, 1), "Bad less.");
VTKM_TEST_ASSERT(!totalLess1(1, 1), "Bad less.");
LessPartialOrder<vtkm::Id> partialLess1;
VTKM_TEST_ASSERT(partialLess1(1, 2), "Bad less.");
VTKM_TEST_ASSERT(!partialLess1(2, 1), "Bad less.");
VTKM_TEST_ASSERT(!partialLess1(1, 1), "Bad less.");
LessTotalOrder<vtkm::Id3> totalLess3;
VTKM_TEST_ASSERT(totalLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(3, 2, 1)), "Bad less.");
VTKM_TEST_ASSERT(!totalLess3(vtkm::Id3(3, 2, 1), vtkm::Id3(1, 2, 3)), "Bad less.");
VTKM_TEST_ASSERT(!totalLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(1, 2, 3)), "Bad less.");
VTKM_TEST_ASSERT(totalLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(2, 3, 4)), "Bad less.");
LessPartialOrder<vtkm::Id3> partialLess3;
VTKM_TEST_ASSERT(!partialLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(3, 2, 1)), "Bad less.");
VTKM_TEST_ASSERT(!partialLess3(vtkm::Id3(3, 2, 1), vtkm::Id3(1, 2, 3)), "Bad less.");
VTKM_TEST_ASSERT(!partialLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(1, 2, 3)), "Bad less.");
VTKM_TEST_ASSERT(partialLess3(vtkm::Id3(1, 2, 3), vtkm::Id3(2, 3, 4)), "Bad less.");
}
template<typename T>
struct VecTraits;
////
//// BEGIN-EXAMPLE VecTraitsImpl
////
//// PAUSE-EXAMPLE
#if 0
//// RESUME-EXAMPLE
namespace vtkm {
//// PAUSE-EXAMPLE
#endif
//// RESUME-EXAMPLE
template<>
struct VecTraits<vtkm::Id3>
{
using ComponentType = vtkm::Id;
using BaseComponentType = vtkm::Id;
static const int NUM_COMPONENTS = 3;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
VTKM_EXEC_CONT
static vtkm::IdComponent GetNumberOfComponents(const vtkm::Id3&)
{
return NUM_COMPONENTS;
}
VTKM_EXEC_CONT
static const vtkm::Id& GetComponent(const vtkm::Id3& vector, int component)
{
return vector[component];
}
VTKM_EXEC_CONT
static vtkm::Id& GetComponent(vtkm::Id3& vector, int component)
{
return vector[component];
}
VTKM_EXEC_CONT
static void SetComponent(vtkm::Id3& vector, int component, vtkm::Id value)
{
vector[component] = value;
}
template<typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, 3>;
template<typename NewComponentType>
using ReplaceBaseComponentType = vtkm::Vec<NewComponentType, 3>;
template<vtkm::IdComponent DestSize>
VTKM_EXEC_CONT static void CopyInto(const vtkm::Id3& src,
vtkm::Vec<vtkm::Id, DestSize>& dest)
{
for (vtkm::IdComponent index = 0; (index < NUM_COMPONENTS) && (index < DestSize);
index++)
{
dest[index] = src[index];
}
}
};
//// PAUSE-EXAMPLE
#if 0
//// RESUME-EXAMPLE
} // namespace vtkm
//// PAUSE-EXAMPLE
#endif
//// RESUME-EXAMPLE
////
//// END-EXAMPLE VecTraitsImpl
////
void TryCustomVecTriats()
{
using CustomTraits = TraitsExamples::VecTraits<vtkm::Id3>;
using OriginalTraits = vtkm::VecTraits<vtkm::Id3>;
VTKM_STATIC_ASSERT(
(std::is_same<CustomTraits::ComponentType, OriginalTraits::ComponentType>::value));
VTKM_STATIC_ASSERT(CustomTraits::NUM_COMPONENTS == OriginalTraits::NUM_COMPONENTS);
VTKM_STATIC_ASSERT((std::is_same<CustomTraits::HasMultipleComponents,
OriginalTraits::HasMultipleComponents>::value));
VTKM_STATIC_ASSERT(
(std::is_same<CustomTraits::IsSizeStatic, OriginalTraits::IsSizeStatic>::value));
vtkm::Id3 value = TestValue(10, vtkm::Id3());
VTKM_TEST_ASSERT(CustomTraits::GetNumberOfComponents(value) ==
OriginalTraits::GetNumberOfComponents(value),
"Wrong size.");
VTKM_TEST_ASSERT(CustomTraits::GetComponent(value, 1) ==
OriginalTraits::GetComponent(value, 1),
"Wrong component.");
CustomTraits::SetComponent(value, 2, 0);
VTKM_TEST_ASSERT(value[2] == 0, "Did not set component.");
vtkm::Id2 shortValue;
CustomTraits::CopyInto(value, shortValue);
VTKM_TEST_ASSERT(test_equal(shortValue[0], value[0]));
VTKM_TEST_ASSERT(test_equal(shortValue[1], value[1]));
}
void Test()
{
TryRemainder();
TryCustomTypeTraits();
TryLess();
TryCustomVecTriats();
}
} // namespace TraitsExamples
int GuideExampleTraits(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(TraitsExamples::Test, argc, argv);
}

@ -0,0 +1,364 @@
//=============================================================================
//
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
//=============================================================================
#include <vtkm/Tuple.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
constexpr vtkm::Id ARRAY_SIZE = 10;
void Define()
{
////
//// BEGIN-EXAMPLE DefineTuple
////
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Int32>> myTuple;
////
//// END-EXAMPLE DefineTuple
////
(void)myTuple;
}
void Init()
{
vtkm::cont::ArrayHandle<vtkm::Float32> array;
////
//// BEGIN-EXAMPLE InitTuple
////
// Initialize a tuple with 0, [0, 1, 2], and an existing ArrayHandle.
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>> myTuple1(
0, vtkm::Vec3f(0, 1, 2), array);
// Another way to create the same tuple.
auto myTuple2 = vtkm::MakeTuple(vtkm::Id(0), vtkm::Vec3f(0, 1, 2), array);
////
//// END-EXAMPLE InitTuple
////
VTKM_TEST_ASSERT(std::is_same<decltype(myTuple1), decltype(myTuple2)>::value);
VTKM_TEST_ASSERT(vtkm::Get<0>(myTuple1) == 0);
VTKM_TEST_ASSERT(vtkm::Get<0>(myTuple2) == 0);
VTKM_TEST_ASSERT(test_equal(vtkm::Get<1>(myTuple1), vtkm::Vec3f(0, 1, 2)));
VTKM_TEST_ASSERT(test_equal(vtkm::Get<1>(myTuple2), vtkm::Vec3f(0, 1, 2)));
}
void Query()
{
////
//// BEGIN-EXAMPLE TupleQuery
////
using TupleType = vtkm::Tuple<vtkm::Id, vtkm::Float32, vtkm::Float64>;
// Becomes 3
constexpr vtkm::IdComponent size = vtkm::TupleSize<TupleType>::value;
using FirstType = vtkm::TupleElement<0, TupleType>; // vtkm::Id
using SecondType = vtkm::TupleElement<1, TupleType>; // vtkm::Float32
using ThirdType = vtkm::TupleElement<2, TupleType>; // vtkm::Float64
////
//// END-EXAMPLE TupleQuery
////
VTKM_TEST_ASSERT(size == 3);
VTKM_TEST_ASSERT(std::is_same<FirstType, vtkm::Id>::value);
VTKM_TEST_ASSERT(std::is_same<SecondType, vtkm::Float32>::value);
VTKM_TEST_ASSERT(std::is_same<ThirdType, vtkm::Float64>::value);
}
void Get()
{
////
//// BEGIN-EXAMPLE TupleGet
////
auto myTuple = vtkm::MakeTuple(vtkm::Id3(0, 1, 2), vtkm::Vec3f(3, 4, 5));
// Gets the value [0, 1, 2]
vtkm::Id3 x = vtkm::Get<0>(myTuple);
// Changes the second object in myTuple to [6, 7, 8]
vtkm::Get<1>(myTuple) = vtkm::Vec3f(6, 7, 8);
////
//// END-EXAMPLE TupleGet
////
VTKM_TEST_ASSERT(x == vtkm::Id3(0, 1, 2));
VTKM_TEST_ASSERT(test_equal(vtkm::Get<1>(myTuple), vtkm::Vec3f(6, 7, 8)));
}
vtkm::Int16 CreateValue(vtkm::Id index)
{
return TestValue(index, vtkm::Int16{});
}
////
//// BEGIN-EXAMPLE TupleCheck
////
void CheckPositive(vtkm::Float64 x)
{
if (x < 0)
{
throw vtkm::cont::ErrorBadValue("Values need to be positive.");
}
}
// ...
//// PAUSE-EXAMPLE
void ForEachCheck()
{
//// RESUME-EXAMPLE
vtkm::Tuple<vtkm::Float64, vtkm::Float64, vtkm::Float64> tuple(
CreateValue(0), CreateValue(1), CreateValue(2));
// Will throw an error if any of the values are negative.
vtkm::ForEach(tuple, CheckPositive);
////
//// END-EXAMPLE TupleCheck
////
}
////
//// BEGIN-EXAMPLE TupleAggregate
////
struct SumFunctor
{
vtkm::Float64 Sum = 0;
template<typename T>
void operator()(const T& x)
{
this->Sum = this->Sum + static_cast<vtkm::Float64>(x);
}
};
// ...
//// PAUSE-EXAMPLE
void ForEachAggregate()
{
//// RESUME-EXAMPLE
vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
CreateValue(0), CreateValue(1), CreateValue(2));
SumFunctor sum;
vtkm::ForEach(tuple, sum);
vtkm::Float64 average = sum.Sum / 3;
////
//// END-EXAMPLE TupleAggregate
////
VTKM_TEST_ASSERT(test_equal(average, 101));
}
void ForEachAggregateLambda()
{
////
//// BEGIN-EXAMPLE TupleAggregateLambda
////
vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
CreateValue(0), CreateValue(1), CreateValue(2));
vtkm::Float64 sum = 0;
auto sumFunctor = [&sum](auto x) { sum += static_cast<vtkm::Float64>(x); };
vtkm::ForEach(tuple, sumFunctor);
vtkm::Float64 average = sum / 3;
////
//// END-EXAMPLE TupleAggregateLambda
////
VTKM_TEST_ASSERT(test_equal(average, 101));
}
////
//// BEGIN-EXAMPLE TupleTransform
////
struct GetReadPortalFunctor
{
template<typename Array>
typename Array::ReadPortalType operator()(const Array& array) const
{
VTKM_IS_ARRAY_HANDLE(Array);
return array.ReadPortal();
}
};
// ...
//// PAUSE-EXAMPLE
void Transform()
{
vtkm::cont::ArrayHandle<vtkm::Id> array1;
array1.Allocate(ARRAY_SIZE);
SetPortal(array1.WritePortal());
vtkm::cont::ArrayHandle<vtkm::Float32> array2;
array2.Allocate(ARRAY_SIZE);
SetPortal(array2.WritePortal());
vtkm::cont::ArrayHandle<vtkm::Vec3f> array3;
array3.Allocate(ARRAY_SIZE);
SetPortal(array3.WritePortal());
//// RESUME-EXAMPLE
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
auto portalTuple = vtkm::Transform(arrayTuple, GetReadPortalFunctor{});
////
//// END-EXAMPLE TupleTransform
////
CheckPortal(vtkm::Get<0>(portalTuple));
CheckPortal(vtkm::Get<1>(portalTuple));
CheckPortal(vtkm::Get<2>(portalTuple));
}
////
//// BEGIN-EXAMPLE TupleApply
////
struct AddArraysFunctor
{
template<typename Array1, typename Array2, typename Array3>
vtkm::Id operator()(Array1 inArray1, Array2 inArray2, Array3 outArray) const
{
VTKM_IS_ARRAY_HANDLE(Array1);
VTKM_IS_ARRAY_HANDLE(Array2);
VTKM_IS_ARRAY_HANDLE(Array3);
vtkm::Id length = inArray1.GetNumberOfValues();
VTKM_ASSERT(inArray2.GetNumberOfValues() == length);
outArray.Allocate(length);
auto inPortal1 = inArray1.ReadPortal();
auto inPortal2 = inArray2.ReadPortal();
auto outPortal = outArray.WritePortal();
for (vtkm::Id index = 0; index < length; ++index)
{
outPortal.Set(index, inPortal1.Get(index) + inPortal2.Get(index));
}
return length;
}
};
// ...
//// PAUSE-EXAMPLE
void Apply()
{
vtkm::cont::ArrayHandle<vtkm::Float32> array1;
array1.Allocate(ARRAY_SIZE);
SetPortal(array1.WritePortal());
vtkm::cont::ArrayHandle<vtkm::Float32> array2;
vtkm::cont::ArrayCopy(array1, array2);
vtkm::cont::ArrayHandle<vtkm::Float32> array3;
//// RESUME-EXAMPLE
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
vtkm::Id arrayLength = vtkm::Apply(arrayTuple, AddArraysFunctor{});
////
//// END-EXAMPLE TupleApply
////
VTKM_TEST_ASSERT(arrayLength == ARRAY_SIZE);
auto portal = array3.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(i), 2 * TestValue(i, vtkm::Float32{})));
}
}
////
//// BEGIN-EXAMPLE TupleApplyExtraArgs
////
struct ScanArrayLengthFunctor
{
template<vtkm::IdComponent N, typename Array, typename... Remaining>
vtkm::Vec<vtkm::Id, N + 1 + vtkm::IdComponent(sizeof...(Remaining))> operator()(
const vtkm::Vec<vtkm::Id, N>& partialResult,
const Array& nextArray,
const Remaining&... remainingArrays) const
{
vtkm::Vec<vtkm::Id, N + 1> nextResult;
std::copy(&partialResult[0], &partialResult[0] + N, &nextResult[0]);
nextResult[N] = nextResult[N - 1] + nextArray.GetNumberOfValues();
return (*this)(nextResult, remainingArrays...);
}
template<vtkm::IdComponent N>
vtkm::Vec<vtkm::Id, N> operator()(const vtkm::Vec<vtkm::Id, N>& result) const
{
return result;
}
};
// ...
//// PAUSE-EXAMPLE
void ApplyExtraArgs()
{
vtkm::cont::ArrayHandle<vtkm::Id> array1;
array1.Allocate(ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id3> array2;
array2.Allocate(ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Vec3f> array3;
array3.Allocate(ARRAY_SIZE);
//// RESUME-EXAMPLE
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
vtkm::Vec<vtkm::Id, 4> sizeScan =
vtkm::Apply(arrayTuple, ScanArrayLengthFunctor{}, vtkm::Vec<vtkm::Id, 1>{ 0 });
////
//// END-EXAMPLE TupleApplyExtraArgs
////
VTKM_TEST_ASSERT(sizeScan[0] == 0 * ARRAY_SIZE);
VTKM_TEST_ASSERT(sizeScan[1] == 1 * ARRAY_SIZE);
VTKM_TEST_ASSERT(sizeScan[2] == 2 * ARRAY_SIZE);
VTKM_TEST_ASSERT(sizeScan[3] == 3 * ARRAY_SIZE);
}
void Run()
{
Define();
Init();
Query();
Get();
ForEachCheck();
ForEachAggregate();
ForEachAggregateLambda();
Transform();
Apply();
ApplyExtraArgs();
}
} // anonymous namespace
int GuideExampleTuple(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}

@ -18,7 +18,7 @@ All the file I/O classes are declared under the ``vtkm::io`` namespace.
increasing power and complexity.
In particular, :secref:`dataset:Building Data Sets` describes how to build |VTKm| data set objects and Section \ref{sec:ArrayHandle:Adapting} documents how to adapt data structures defined in other libraries to be used directly in |VTKm|.
.. todo:: Add ArrayHandle section reference above.
.. todo:: Add custom ArrayHandle section reference above.
------------------------------
Readers

@ -1,3 +1,8 @@
==============================
Advanced Development
==============================
.. toctree::
:maxdepth: 2
advanced-types.rst

@ -412,8 +412,6 @@ The input and output of this filter are a structured data sets.
.. doxygenclass:: vtkm::filter::entity_extraction::ExtractStructured
:members:
.. todo:: Document vtkm::RangeId and vtkm::RangeId3 (in advanced types chapter).
Ghost Cell Removal
------------------------------

@ -511,7 +511,7 @@ First call :func:`vtkm::rendering::View::Paint` on the :class:`vtkm::rendering::
Second, get the image color data out of the :class:`vtkm::rendering::View`'s :class:`vtkm::rendering::Canvas` object.
This is done by calling :func:`vtkm::rendering::Canvas::GetColorBuffer`.
This will return a :class:`vtkm::cont::ArrayHandle` object containing the image's pixel color data.
(:class:`vtkm::cont::ArrayHandle` is discussed in detail in Chapter \ref{chap:BasicArrayHandles} and subsequent chapters.)
(:class:`vtkm::cont::ArrayHandle` is discussed in detail in :chapref:`basic-array-handles:Basic Array Handles` and subsequent chapters.)
A raw pointer can be pulled out of this :class:`vtkm::cont::ArrayHandle` by casting it to the :class:`vtkm::cont::ArrayHandleBase` subclass and calling the :func:`vtkm::cont::ArrayHandleBase::GetReadPointer` method on that.
Third, the pixel color data are pasted into the OpenGL render context.
There are multiple ways to do so, but the most straightforward way is to use the ``glDrawPixels`` function provided by OpenGL.
@ -519,8 +519,6 @@ Fourth, swap the OpenGL buffers.
The method to swap OpenGL buffers varies by OS platform.
The aforementioned graphics libraries GLUT and GLFW each provide a function for doing so.
.. todo:: Fix chapter reference above.
.. load-example:: RenderToOpenGL
:file: GuideExampleRenderingInteractive.cxx
:caption: Rendering a :class:`vtkm::rendering::View` and pasting the result to an active OpenGL context.

@ -63,7 +63,7 @@ The parameters of the function prototype are *tags* that identify the type of da
``ControlSignature`` tags are defined by the worklet type and the various tags are documented more fully in Chapter \ref{chap:WorkletTypeReference}.
In the case of :numref:`ex:ControlSignature`, the two tags ``FieldIn`` and ``FieldOut`` represent input and output data, respectively.
.. todo:: Fix reference above.
.. todo:: Fix worklet type reference above.
.. index::
single: control signature

@ -28,15 +28,24 @@ namespace vtkm
///
struct Bounds
{
/// The range of values in the X direction. The `vtkm::Range` struct provides
/// the minimum and maximum along that axis.
vtkm::Range X;
/// The range of values in the Y direction. The `vtkm::Range` struct provides
/// the minimum and maximum along that axis.
vtkm::Range Y;
/// The range of values in the Z direction. The `vtkm::Range` struct provides
/// the minimum and maximum along that axis.
vtkm::Range Z;
/// Construct an empty bounds. The bounds will represent no space until
/// otherwise modified.
VTKM_EXEC_CONT
Bounds() {}
Bounds(const Bounds&) = default;
/// Construct a bounds with a given range in the x, y, and z dimensions.
VTKM_EXEC_CONT
Bounds(const vtkm::Range& xRange, const vtkm::Range& yRange, const vtkm::Range& zRange)
: X(xRange)
@ -45,6 +54,8 @@ struct Bounds
{
}
/// Construct a bounds with the minimum and maximum coordinates in the x, y, and z
/// directions.
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
VTKM_EXEC_CONT Bounds(const T1& minX,
const T2& maxX,

@ -16,8 +16,18 @@
namespace vtkm
{
/// @brief 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 `ErrorCode` identifier. 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.
enum class ErrorCode
{
// Documentation is below (for better layout in generated documents).
Success,
InvalidShapeId,
InvalidNumberOfPoints,
@ -36,6 +46,87 @@ enum class ErrorCode
UnknownError
};
/// @var ErrorCode Success
/// @brief 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.
/// @var ErrorCode InvalidShapeId
/// @brief A unknown shape identifier was encountered.
///
/// All cell shapes must be listed in `vtkm::CellShapeIdEnum`.
/// @var ErrorCode InvalidNumberOfPoints
/// @brief 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.
/// @var ErrorCode InvalidCellMetric
/// @brief A cell metric was requested for a cell that does not support that metric.
/// @var ErrorCode WrongShapeIdForTagType
/// This is an internal error from the lightweight cell library.
/// @var ErrorCode InvalidPointId
/// @brief A bad point identifier was detected while operating on a cell.
/// @var ErrorCode InvalidEdgeId
/// @brief A bad edge identifier was detected while operating on a cell.
/// @var ErrorCode InvalidFaceId
/// @brief A bad face identifier was detected while operating on a cell.
/// @var ErrorCode SolutionDidNotConverge
/// @brief 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.
/// @var ErrorCode MatrixFactorizationFailed
/// @brief 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.
/// @var ErrorCode DegenerateCellDetected
/// @brief 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.
/// @var ErrorCode MalformedCellDetected
/// @brief 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::DegenerateCellDetected`
/// has its own error coe.)
/// @var ErrorCode OperationOnEmptyCell
/// @brief 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.
/// @var ErrorCode CellNotFound
/// @brief 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.
/// @brief Convert a `vtkm::ErrorCode` into a human-readable string.
///
/// This method is useful when reporting the results of a function that
/// failed.
VTKM_EXEC_CONT
inline const char* ErrorString(vtkm::ErrorCode code) noexcept
{

@ -30,6 +30,11 @@ namespace vtkm
" Compilers often have a recursive template instantiation limit of around 1024," \
" so operations on lists this large can lead to confusing and misleading errors.")
/// @brief A template used to hold a list of types.
///
/// `List` is an empty `struct` that is used to hold a list of types as its template
/// arguments. VTK-m provides templated types that allows a `List` to be
/// manipulated and used in numerous ways.
template <typename... Ts>
struct List
{
@ -78,13 +83,14 @@ struct UniversalTypeTag
} // namespace detail
/// A special tag for an empty list.
/// @brief A convenience type for an empty list.
///
using ListEmpty = vtkm::List<>;
/// A special tag for a list that represents holding all potential values
/// @brief A special type for a list that represents holding all potential values
///
/// Note: Can not be used with ForEach and some list transforms for obvious reasons.
/// Note: This list cannot be used with `ForEach` and some list transforms
/// for obvious reasons.
using ListUniversal = vtkm::List<detail::UniversalTypeTag>;
namespace detail
@ -711,7 +717,6 @@ struct ListIntersectImpl<vtkm::ListUniversal, vtkm::ListUniversal>
template <typename List1, typename List2>
using ListIntersect = typename detail::ListIntersectImpl<List1, List2>::type;
///@{
/// For each typename represented by the list, call the functor with a
/// default instance of that type.
///
@ -729,7 +734,6 @@ VTKM_EXEC_CONT void ListForEach(Functor&&, vtkm::ListEmpty, Args&&...)
{
// No types to run functor on.
}
///@}
namespace detail
{

@ -30,9 +30,13 @@ namespace vtkm
///
struct Range
{
/// The minumum value of the range (inclusive).
vtkm::Float64 Min;
/// Tha maximum value of the range (inclusive).
vtkm::Float64 Max;
/// Construct a range with a given minimum and maximum. If no minimum or maximum is
/// given, the range will be empty.
VTKM_EXEC_CONT
Range()
: Min(vtkm::Infinity64())

@ -27,9 +27,12 @@ namespace vtkm
///
struct RangeId
{
/// The minimum index of the range (inclusive).
vtkm::Id Min;
/// The maximum index of the range (exclusive).
vtkm::Id Max;
/// Construct a range with no indices.
VTKM_EXEC_CONT
RangeId()
: Min(0)
@ -37,6 +40,8 @@ struct RangeId
{
}
/// Construct a range with the given minimum (inclusive) and maximum (exclusive)
/// indices.
VTKM_EXEC_CONT
RangeId(vtkm::Id min, vtkm::Id max)
: Min(min)

@ -15,22 +15,28 @@
namespace vtkm
{
/// \brief Represent 2D integer range.
/// @brief Represent 2D integer range.
///
/// \c vtkm::RangeId2 is a helper class for representing a 2D range of integer
/// `vtkm::RangeId2` is 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, y, and z directions.
/// in the x and y directions.
///
/// \c RangeId2 also contains several helper functions for computing and
/// `RangeId2` also contains several helper functions for computing and
/// maintaining the range.
///
struct RangeId2
{
/// The range of values in the X direction. The `vtkm::RangeId` struct provides
/// the minimum and maximum along that axis.
vtkm::RangeId X;
/// The range of values in the Y direction. The `vtkm::RangeId` struct provides
/// the minimum and maximum along that axis.
vtkm::RangeId Y;
/// Construct an empty 2D range.
RangeId2() = default;
/// Construct a range with the given x and y directions.
VTKM_EXEC_CONT
RangeId2(const vtkm::RangeId& xrange, const vtkm::RangeId& yrange)
: X(xrange)
@ -38,6 +44,7 @@ struct RangeId2
{
}
/// Construct a range with the given minimum (inclusive) and maximum (exclusive) points.
VTKM_EXEC_CONT
RangeId2(vtkm::Id minX, vtkm::Id maxX, vtkm::Id minY, vtkm::Id maxY)
: X(vtkm::RangeId(minX, maxX))
@ -45,8 +52,8 @@ struct RangeId2
{
}
/// Initialize range with an array of 6 values in the order xmin, xmax,
/// ymin, ymax, zmin, zmax.
/// Initialize range with an array of 4 values in the order xmin, xmax,
/// ymin, ymax.
///
VTKM_EXEC_CONT
explicit RangeId2(const vtkm::Id range[4])

@ -26,12 +26,20 @@ namespace vtkm
///
struct RangeId3
{
/// The range of values in the X direction. The `vtkm::RangeId` struct provides
/// the minimum and maximum along that axis.
vtkm::RangeId X;
/// The range of values in the Y direction. The `vtkm::RangeId` struct provides
/// the minimum and maximum along that axis.
vtkm::RangeId Y;
/// The range of values in the Z direction. The `vtkm::RangeId` struct provides
/// the minimum and maximum along that axis.
vtkm::RangeId Z;
/// Construct an empty 3D range.
RangeId3() = default;
/// Construct a range with the given x, y, and z directions.
VTKM_EXEC_CONT
RangeId3(const vtkm::RangeId& xrange, const vtkm::RangeId& yrange, const vtkm::RangeId& zrange)
: X(xrange)
@ -40,6 +48,7 @@ struct RangeId3
{
}
/// Construct a range with the given minimum (inclusive) and maximum (exclusive) points.
VTKM_EXEC_CONT
RangeId3(vtkm::Id minX, vtkm::Id maxX, vtkm::Id minY, vtkm::Id maxY, vtkm::Id minZ, vtkm::Id maxZ)
: X(vtkm::RangeId(minX, maxX))

@ -75,27 +75,31 @@ struct tuple_element
template <std::size_t Index, typename TupleType>
using tuple_element_t = typename tuple_element<Index, TupleType>::type;
///@{
/// \brief Retrieve the object from a `vtkm::Tuple` at the given index.
///
/// @brief Retrieve the object from a `vtkm::Tuple` at the given index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple)
#ifndef VTKM_DOXYGEN_ONLY
// Breathe (for Sphinx) has problems parsing this declarator id.
-> decltype(tuple.template Get<Index>())
#endif
{
return tuple.template Get<Index>();
}
/// @brief Retrieve the object from a `vtkm::Tuple` at the given index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple)
#ifndef VTKM_DOXYGEN_ONLY
// Breathe (for Sphinx) has problems parsing this declarator id.
-> decltype(tuple.template Get<Index>())
#endif
{
return tuple.template Get<Index>();
}
///@}
///@{
/// \brief Compatible with `std::get` for `vtkm::Tuple`.
///
/// @brief Compatible with `std::get` for `vtkm::Tuple`.
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
@ -104,6 +108,7 @@ VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
/// @brief Compatible with `std::get` for `vtkm::Tuple`.
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
@ -111,7 +116,6 @@ VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
///@}
/// \brief Creates a new `vtkm::Tuple` with the given types.
///
@ -145,14 +149,6 @@ struct TupleTransformFunctor
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleTransform(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f));
}
struct TupleForEachFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
@ -163,17 +159,69 @@ struct TupleForEachFunctor
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleForEach(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f));
}
} // namespace detail
/// @endcond
/// @brief Call a function with the values of a `vtkm::Tuple` as arguments.
///
/// If a `vtkm::Tuple<A, B, C>` is given with values `a`, `b`, and `c`, then
/// `f` will be called as `f(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>
VTKM_EXEC_CONT auto Apply(const vtkm::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
-> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}
/// @copydoc Apply
template <typename... Ts, typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(vtkm::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
-> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}
/// @brief 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>
VTKM_EXEC_CONT void ForEach(const vtkm::Tuple<Ts...>& tuple, Function&& f)
{
return vtkm::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}
/// @copydoc ForEach
template <typename... Ts, typename Function>
VTKM_EXEC_CONT void ForEach(vtkm::Tuple<Ts...>& tuple, Function&& f)
{
return vtkm::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}
/// @brief Construct a new `vtkm::Tuple` by applying a function to each value.
///
/// The `vtkm::Transform` function builds a new `vtkm::Tuple` by calling a function
/// or functor on each of the items in the given `tuple`. 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>
VTKM_EXEC_CONT auto Transform(const TupleType&& tuple, Function&& f)
-> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
{
return Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f));
}
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto Transform(TupleType&& tuple, Function&& f)
-> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
{
return Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f));
}
template <>
class Tuple<>
{
@ -285,28 +333,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -396,28 +444,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -519,28 +567,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -654,28 +702,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -801,28 +849,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -960,28 +1008,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -1131,28 +1179,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -1314,28 +1362,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -1509,28 +1557,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -1716,28 +1764,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -1935,28 +1983,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -2166,28 +2214,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -2409,28 +2457,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -2664,28 +2712,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -2931,28 +2979,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -3210,28 +3258,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -3501,28 +3549,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -3804,28 +3852,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -4119,28 +4167,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -4446,28 +4494,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -4872,28 +4920,28 @@ public:
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};

@ -116,27 +116,31 @@ struct tuple_element
template <std::size_t Index, typename TupleType>
using tuple_element_t = typename tuple_element<Index, TupleType>::type;
///@{
/// \brief Retrieve the object from a `vtkm::Tuple` at the given index.
///
/// @brief Retrieve the object from a `vtkm::Tuple` at the given index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple)
#ifndef VTKM_DOXYGEN_ONLY
// Breathe (for Sphinx) has problems parsing this declarator id.
-> decltype(tuple.template Get<Index>())
#endif
{
return tuple.template Get<Index>();
}
/// @brief Retrieve the object from a `vtkm::Tuple` at the given index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple)
#ifndef VTKM_DOXYGEN_ONLY
// Breathe (for Sphinx) has problems parsing this declarator id.
-> decltype(tuple.template Get<Index>())
#endif
{
return tuple.template Get<Index>();
}
///@}
///@{
/// \brief Compatible with `std::get` for `vtkm::Tuple`.
///
/// @brief Compatible with `std::get` for `vtkm::Tuple`.
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
@ -145,6 +149,7 @@ VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
/// @brief Compatible with `std::get` for `vtkm::Tuple`.
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
@ -152,7 +157,6 @@ VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
///@}
/// \brief Creates a new `vtkm::Tuple` with the given types.
///
@ -186,14 +190,6 @@ struct TupleTransformFunctor
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleTransform(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f));
}
struct TupleForEachFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
@ -204,17 +200,69 @@ struct TupleForEachFunctor
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleForEach(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f));
}
} // namespace detail
/// @endcond
/// @brief Call a function with the values of a `vtkm::Tuple` as arguments.
///
/// If a `vtkm::Tuple<A, B, C>` is given with values `a`, `b`, and `c`, then
/// `f` will be called as `f(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>
VTKM_EXEC_CONT auto Apply(const vtkm::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
-> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}
/// @copydoc Apply
template <typename... Ts, typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(vtkm::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
-> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}
/// @brief 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>
VTKM_EXEC_CONT void ForEach(const vtkm::Tuple<Ts...>& tuple, Function&& f)
{
return vtkm::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}
/// @copydoc ForEach
template <typename... Ts, typename Function>
VTKM_EXEC_CONT void ForEach(vtkm::Tuple<Ts...>& tuple, Function&& f)
{
return vtkm::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}
/// @brief Construct a new `vtkm::Tuple` by applying a function to each value.
///
/// The `vtkm::Transform` function builds a new `vtkm::Tuple` by calling a function
/// or functor on each of the items in the given `tuple`. 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>
VTKM_EXEC_CONT auto Transform(const TupleType&& tuple, Function&& f)
-> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
{
return Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f));
}
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto Transform(TupleType&& tuple, Function&& f)
-> decltype(Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f)))
{
return Apply(tuple, detail::TupleTransformFunctor{}, std::forward<Function>(f));
}
template <>
class Tuple<>
{
@ -332,28 +380,28 @@ $endfor\
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};
@ -472,28 +520,28 @@ $endfor\
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
vtkm::ForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
-> decltype(vtkm::Transform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
return vtkm::Transform(*this, std::forward<Function>(f));
}
};

@ -72,6 +72,8 @@ public:
/// also be treated as vectors with VecTraits.
using DimensionalityTag = vtkm::TypeTraitsUnknownTag;
/// @brief A static function that returns 0 (or the closest equivalent to it)
/// for the given type.
VTKM_EXEC_CONT static T ZeroInitialization() { return T(); }
};

@ -79,18 +79,28 @@ struct VTKM_NEVER_EXPORT VecTraits
/// \brief Number of components in the vector.
///
/// This is only defined for vectors of a static size.
/// This is only defined for vectors of a static size. That is, `NUM_COMPONENTS`
/// is not available when `IsSizeStatic` is set to `vtkm::VecTraitsTagSizeVariable`.
///
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
/// Number of components in the given vector.
/// @brief Returns the number of components in the given vector.
///
/// The result of `GetNumberOfComponents()` is the same value of `NUM_COMPONENTS`
/// for vector types that have a static size (that is, `IsSizeStatic` is
/// `vtkm::VecTraitsTagSizeStatic`). But unlike `NUM_COMPONENTS`, `GetNumberOfComponents()`
/// works for vectors of any type.
///
static constexpr vtkm::IdComponent GetNumberOfComponents(const T&) { return NUM_COMPONENTS; }
/// \brief A tag specifying whether this vector has multiple components (i.e. is a "real" vector).
///
/// This tag can be useful for creating specialized functions when a vector
/// is really just a scalar.
/// This type is set to either `vtkm::VecTraitsTagSingleComponent` if the vector length
/// is size 1 or `vtkm::VecTraitsTagMultipleComponents` otherwise.
/// 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, `IsSizeStatic` is
/// `vtkm::VecTraitsTagSizeVariable`), then `HasMultipleComponents` might be
/// `vtkm::VecTraitsTagMultipleComponents` even when at run time there is only one component.
///
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
@ -109,6 +119,7 @@ struct VTKM_NEVER_EXPORT VecTraits
{
return vector;
}
/// @copydoc GetComponent
VTKM_EXEC_CONT static ComponentType& GetComponent(T& vector,
vtkm::IdComponent vtkmNotUsed(component))
{

@ -61,7 +61,7 @@ struct AreaWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
vtkmGenericCellShapeMacro(metricValue =
this->ComputeMetric<OutType>(numPoints, pts, CellShapeTag()));
default:
this->RaiseError(vtkm::ErrorString(vtkm::ErrorCode::CellNotFound));
this->RaiseError(vtkm::ErrorString(vtkm::ErrorCode::InvalidShapeId));
metricValue = OutType(0.0);
}
}

@ -50,7 +50,7 @@ struct VolumeWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
vtkmGenericCellShapeMacro(metricValue =
this->ComputeMetric<OutType>(numPoints, pts, CellShapeTag()));
default:
this->RaiseError(vtkm::ErrorString(vtkm::ErrorCode::CellNotFound));
this->RaiseError(vtkm::ErrorString(vtkm::ErrorCode::InvalidShapeId));
metricValue = OutType(0.0);
}
}

@ -69,7 +69,7 @@ struct MeshQualityWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
vtkmGenericCellShapeMacro(metricValue = self->template ComputeMetric<OutType>(
numPoints, pts, CellShapeTag{}, errorCode));
default:
errorCode = vtkm::ErrorCode::CellNotFound;
errorCode = vtkm::ErrorCode::InvalidShapeId;
metricValue = OutType(0.0);
}