Merge branch 'master' into philox

This commit is contained in:
Li-Ta Lo 2020-03-23 08:28:02 -06:00
commit c795f74b24
131 changed files with 9651 additions and 4335 deletions

@ -104,7 +104,7 @@ function(do_verify root_dir prefix)
#Step 1. Setup the extensions to check, and all file and directory
# extensions
set(files_extensions
*.hpp #needed for diy and taotuple
*.hpp #needed for diy
*.h
*.hxx
)

@ -202,6 +202,7 @@ check_type_size("long long" VTKm_SIZE_LONG_LONG BUILTIN_TYPES_ONLY)
#-----------------------------------------------------------------------------
# Add subdirectories
add_subdirectory(vtkmstd)
add_subdirectory(vtkm)
#-----------------------------------------------------------------------------

@ -64,7 +64,7 @@ void BenchRayTracing(::benchmark::State& state)
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
vtkm::rendering::raytracing::Camera rayCamera;
rayCamera.SetParameters(camera, canvas);
rayCamera.SetParameters(camera, vtkm::Int32(canvas.GetWidth()), vtkm::Int32(canvas.GetHeight()));
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
rayCamera.CreateRays(rays, coords.GetBounds());

@ -158,15 +158,13 @@ the covers for most users.
The `GetPortalConstControl` and `GetPortalControl` methods have been
deprecated. Instead, the methods `ReadPortal` and `WritePortal` should be
used. The calling signature is the same as their predecessors, but the
returned portal contains a `Token` as part of its state and prevents and
changes to the `ArrayHandle` it comes from. The `WritePortal` also prevents
other reads from the array.
returned portal contains a reference back to the original `ArrayHandle`.
The reference keeps track of whether the memory allocation has changed.
The advantage is that the returned portal will always be valid. However, it
is now the case that a control portal can prevent something else from
running. This means that control portals should drop scope as soon as
possible. It is because of this behavior change that new methods were
created instead of altering the old ones.
If the `ArrayHandle` is changed while the `ArrayPortal` still exists,
nothing will happen immediately. However, if the portal is subsequently
accessed (i.e. `Set` or `Get` is called on it), then a fatal error will be
reported to the log.
## Deadlocks
@ -175,46 +173,38 @@ to able to be immediately invalidated), the scopes have the ability to
cause operations to block. This can cause issues if the `ArrayHandle` is
attempted to be used by multiple `Token`s at once.
Care should be taken to ensure that a single thread does not attempt to use
an `ArrayHandle` two ways at the same time.
The following is a contrived example of causing a deadlock.
``` cpp
auto portal = array.WritePortal();
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
{
portal.Set(index, /* An interesting value */);
}
vtkm::cont::Invoker invoke;
invoke(MyWorklet, array); // Oops. Deadlock here.
vtkm::cont::Token token1;
auto portal1 = array.PrepareForInPlace(Device{}, token1);
vtkm::cont::Token token2;
auto portal2 = array.PrepareForInput(Device{}, token2);
```
In this example, the last line deadlocks because `portal` is still holding
onto `array` for writing. When the worklet is invoked, it waits for
everything to stop writing to `array` so that it can be safely be read.
Instead, `portal` should be properly scoped.
The last line will deadlock as `PrepareForInput` waits for `token1` to
detach, which will never happen. To prevent this from happening, if you use
the same `Token` on the array, it will always allow the action. Thus, the
following will work fine.
``` cpp
{
auto portal = array.GetPortalControl();
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
{
portal.Set(index, /* An interesting value */);
}
}
vtkm::cont::Invoker invoke;
invoke(MyWorklet, array); // Runs fine because portal left scope
vtkm::cont::Token token;
auto portal1 = array.PrepareForInPlace(Device{}, token);
auto portal2 = array.PrepareForInput(Device{}, token);
```
Alternately, you can call `Detach` on the portal, which will invalidate the
portal and unlock the `ArrayHandle`.
This prevents deadlock during the invocation of a worklet (so long as no
intermediate object tries to create its own `Token`, which would be bad
practice).
``` cpp
auto portal = array.WritePortal();
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
{
portal.Set(index, /* An interesting value */);
}
portal.Detach();
vtkm::cont::Invoker invoke;
invoke(MyWorklet, array); // Runs fine because portal detached
```
Deadlocks are more likely when actually running multiple threads in the
control environment, but still pretty unlikely. One way it can occur is if
you have one (or more) worklet that has two output fields. You then try to
run the worklet(s) simultaneously on multiple threads. It could be that one
thread locks the first output array and the other thread locks the second
output array.
However, having multiple threads trying to write to the same output arrays
at the same time without its own coordination is probably a bad idea in itself.

@ -0,0 +1,14 @@
# Porting layer for future std features
Currently, VTK-m is using C++11. However, it is often useful to use
features in the `std` namespace that are defined for C++14 or later. We can
provide our own versions (sometimes), but it is preferable to use the
version provided by the compiler if available.
There were already some examples of defining portable versions of C++14 and
C++17 classes in a `vtkmstd` namespace, but these were sprinkled around the
source code.
There is now a top level `vtkmstd` directory and in it are header files
that provide portable versions of these future C++ classes. In each case,
preprocessor macros are used to select which version of the class to use.

220
docs/changelog/tuple.md Normal file

@ -0,0 +1,220 @@
# Add a vtkm::Tuple class
This change added a `vtkm::Tuple` class that is very similar in nature to
`std::tuple`. This should replace our use of tao tuple.
The motivation for this change was some recent attempts at removing objects
like `Invocation` and `FunctionInterface`. I expected these changes to
speed up the build, but in fact they ended up slowing down the build. I
believe the problem was that these required packing variable parameters
into a tuple. I was using the tao `tuple` class, but it seemed to slow down
the compile. (That is, compiling tao's `tuple` seemed much slower than
compiling the equivalent `FunctionInterface` class.)
The implementation of `vtkm::Tuple` is using `pyexpander` to build lots of
simple template cases for the object (with a backup implementation for even
longer argument lists). I believe the compiler is better and parsing
through thousands of lines of simple templates than to employ clever MPL to
build general templates.
## Usage
The `vtkm::Tuple` class is defined in the `vtkm::Tuple.h` header file. A
`Tuple` is designed to behave much like a `std::tuple` with some minor
syntax differences to fit VTK-m coding standards.
A tuple is declared with a list of template argument types.
``` cpp
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>> myTuple;
```
If given no arguments, a `vtkm::Tuple` will default-construct its contained
objects. A `vtkm::Tuple` can also be constructed with the initial values of
all contained objects.
``` cpp
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>>
myTuple(0, vtkm::Vec3f(0, 1, 2), array);
```
For convenience there is a `vtkm::MakeTuple` function that takes arguments
and packs them into a `Tuple` of the appropriate type. (There is also a
`vtkm::make_tuple` alias to the function to match the `std` version.)
``` cpp
auto myTuple = vtkm::MakeTuple(0, vtkm::Vec3f(0, 1, 2), array);
```
Data is retrieved from a `Tuple` by using the `vtkm::Get` method. The `Get`
method is templated on the index to get the value from. The index is of
type `vtkm::IdComponent`. (There is also a `vtkm::get` that uses a
`std::size_t` as the index type as an alias to the function to match the
`std` version.)
``` cpp
vtkm::Id a = vtkm::Get<0>(myTuple);
vtkm::Vec3f b = vtkm::Get<1>(myTuple);
vtkm::cont::ArrayHandle<vtkm::Float32> c = vtkm::Get<2>(myTuple);
```
Likewise `vtkm::TupleSize` and `vtkm::TupleElement` (and their aliases
`vtkm::Tuple_size`, `vtkm::tuple_element`, and `vtkm::tuple_element_t`) are
provided.
## Extended Functionality
The `vtkm::Tuple` class contains some functionality beyond that of
`std::tuple` to cover some common use cases in VTK-m that are tricky to
implement. In particular, these methods allow you to use a `Tuple` as you
would commonly use parameter packs. This allows you to stash parameter
packs in a `Tuple` and then get them back out again.
### For Each
`vtkm::Tuple::ForEach()` is a method that takes a function or functor and
calls it for each of the items in the tuple. Nothing is returned from
`ForEach` and any return value from the function is ignored.
`ForEach` can be used to check the validity of each item.
``` cpp
void CheckPositive(vtkm::Float64 x)
{
if (x < 0)
{
throw vtkm::cont::ErrorBadValue("Values need to be positive.");
}
}
// ...
vtkm::Tuple<vtkm::Float64, vtkm::Float64, vtkm::Float64> tuple(
CreateValue1(), CreateValue2(), CreateValue3());
// Will throw an error if any of the values are negative.
tuple.ForEach(CheckPositive);
```
`ForEach` can also be used to aggregate values.
``` cpp
struct SumFunctor
{
vtkm::Float64 Sum = 0;
template <typename T>
void operator()(const T& x)
{
this->Sum = this->Sum + static_cast<vtkm::Float64>(x);
}
};
// ...
vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
CreateValue1(), CreateValue2(), CreateValue3());
SumFunctor sum;
tuple.ForEach(sum);
vtkm::Float64 average = sum.Sum / 3;
```
### Transform
`vtkm::Tuple::Transform` is a method that builds a new `Tuple` by calling a
function or functor on each of the items. 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.
``` cpp
struct GetReadPortalFunctor
{
template <typename Array>
typename Array::ReadPortal operator()(const Array& array) const
{
VTKM_IS_ARRAY_HANDLE(Array);
return array.ReadPortal();
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
auto portalTuple = arrayTuple.Transform(GetReadPortalFunctor{});
```
### Apply
`vtkm::Tuple::Apply` is a method that calls a function or functor using the
objects in the `Tuple` as the arguments. If the function returns a value,
that value is returned from `Apply`.
``` cpp
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;
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
vtkm::Id arrayLength = arrayTuple.Apply(AddArraysFunctor{});
```
If additional arguments are given to `Apply`, they are also passed to the
function (before the objects in the `Tuple`). This is helpful for passing
state to the function. (This feature is not available in either `ForEach`
or `Transform` for technical implementation reasons.)
``` cpp
struct ScanArrayLengthFunctor
{
template <std::size_t N, typename Array, typename... Remaining>
std::array<vtkm::Id, N + 1 + sizeof...(Remaining)>
operator()(const std::array<vtkm::Id, N>& partialResult,
const Array& nextArray,
const Remaining&... remainingArrays) const
{
std::array<vtkm::Id, N + 1> nextResult;
std::copy(partialResult.begin(), partialResult.end(), nextResult.begin());
nextResult[N] = nextResult[N - 1] + nextArray.GetNumberOfValues();
return (*this)(nextResult, remainingArray);
}
template <std::size_t N>
std::array<vtkm::Id, N> operator()(const std::array<vtkm::Id, N>& result) const
{
return result;
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
std::array<vtkm::Id, 4> =
arrayTuple.Apply(ScanArrayLengthFunctor{}, std::array<vtkm::Id, 1>{ 0 });
```

@ -27,6 +27,7 @@ set(headers
CellShape.h
CellTraits.h
Deprecated.h
ErrorCode.h
Flags.h
Geometry.h
Hash.h
@ -46,6 +47,7 @@ set(headers
Swap.h
TopologyElementTag.h
Transform3D.h
Tuple.h
TypeList.h
TypeListTag.h
Types.h
@ -66,6 +68,7 @@ set(template_sources
)
vtkm_pyexpander_generated_file(Math.h)
vtkm_pyexpander_generated_file(Tuple.h)
vtkm_declare_headers(
${headers}
@ -80,7 +83,6 @@ if(VTKm_ENABLE_LOGGING)
add_subdirectory(thirdparty/loguru)
endif()
add_subdirectory(thirdparty/optionparser)
add_subdirectory(thirdparty/taotuple)
add_subdirectory(thirdparty/lcl)
add_subdirectory(testing)

@ -164,7 +164,7 @@ namespace internal
{
template <typename VtkmCellShapeTag>
VTKM_EXEC_CONT inline typename CellShapeTagVtkmToVtkc<VtkmCellShapeTag>::Type make_VtkcCellShapeTag(
VTKM_EXEC_CONT inline typename CellShapeTagVtkmToVtkc<VtkmCellShapeTag>::Type make_LclCellShapeTag(
const VtkmCellShapeTag&,
vtkm::IdComponent numPoints = 0)
{
@ -174,15 +174,15 @@ VTKM_EXEC_CONT inline typename CellShapeTagVtkmToVtkc<VtkmCellShapeTag>::Type ma
}
VTKM_EXEC_CONT
inline lcl::Polygon make_VtkcCellShapeTag(const vtkm::CellShapeTagPolygon&,
vtkm::IdComponent numPoints = 0)
inline lcl::Polygon make_LclCellShapeTag(const vtkm::CellShapeTagPolygon&,
vtkm::IdComponent numPoints = 0)
{
return lcl::Polygon(numPoints);
}
VTKM_EXEC_CONT
inline lcl::Cell make_VtkcCellShapeTag(const vtkm::CellShapeTagGeneric& tag,
vtkm::IdComponent numPoints = 0)
inline lcl::Cell make_LclCellShapeTag(const vtkm::CellShapeTagGeneric& tag,
vtkm::IdComponent numPoints = 0)
{
return lcl::Cell(static_cast<std::int8_t>(tag.Id), numPoints);
}

118
vtkm/ErrorCode.h Normal file

@ -0,0 +1,118 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_exec_ErrorCode_h
#define vtk_m_exec_ErrorCode_h
#include <lcl/ErrorCode.h>
#include <vtkm/internal/ExportMacros.h>
namespace vtkm
{
enum class ErrorCode
{
Success,
InvalidShapeId,
InvalidNumberOfPoints,
WrongShapeIdForTagType,
InvalidPointId,
InvalidEdgeId,
InvalidFaceId,
SolutionDidNotConverge,
MatrixFactorizationFailed,
DegenerateCellDetected,
MalformedCellDetected,
OperationOnEmptyCell,
CellNotFound,
UnknownError
};
VTKM_EXEC_CONT
inline const char* ErrorString(vtkm::ErrorCode code) noexcept
{
switch (code)
{
case vtkm::ErrorCode::Success:
return "Success";
case vtkm::ErrorCode::InvalidShapeId:
return "Invalid shape id";
case vtkm::ErrorCode::InvalidNumberOfPoints:
return "Invalid number of points";
case vtkm::ErrorCode::WrongShapeIdForTagType:
return "Wrong shape id for tag type";
case vtkm::ErrorCode::InvalidPointId:
return "Invalid point id";
case vtkm::ErrorCode::InvalidEdgeId:
return "Invalid edge id";
case vtkm::ErrorCode::InvalidFaceId:
return "Invalid face id";
case vtkm::ErrorCode::SolutionDidNotConverge:
return "Solution did not converge";
case vtkm::ErrorCode::MatrixFactorizationFailed:
return "Matrix factorization failed";
case vtkm::ErrorCode::DegenerateCellDetected:
return "Degenerate cell detected";
case vtkm::ErrorCode::MalformedCellDetected:
return "Malformed cell detected";
case vtkm::ErrorCode::OperationOnEmptyCell:
return "Operation on empty cell";
case vtkm::ErrorCode::CellNotFound:
return "Cell not found";
case vtkm::ErrorCode::UnknownError:
return "Unknown error";
}
return "Invalid error";
}
namespace internal
{
VTKM_EXEC_CONT inline vtkm::ErrorCode LclErrorToVtkmError(lcl::ErrorCode code) noexcept
{
switch (code)
{
case lcl::ErrorCode::SUCCESS:
return vtkm::ErrorCode::Success;
case lcl::ErrorCode::INVALID_SHAPE_ID:
return vtkm::ErrorCode::InvalidShapeId;
case lcl::ErrorCode::INVALID_NUMBER_OF_POINTS:
return vtkm::ErrorCode::InvalidNumberOfPoints;
case lcl::ErrorCode::WRONG_SHAPE_ID_FOR_TAG_TYPE:
return vtkm::ErrorCode::WrongShapeIdForTagType;
case lcl::ErrorCode::INVALID_POINT_ID:
return vtkm::ErrorCode::InvalidPointId;
case lcl::ErrorCode::SOLUTION_DID_NOT_CONVERGE:
return vtkm::ErrorCode::SolutionDidNotConverge;
case lcl::ErrorCode::MATRIX_LUP_FACTORIZATION_FAILED:
return vtkm::ErrorCode::MatrixFactorizationFailed;
case lcl::ErrorCode::DEGENERATE_CELL_DETECTED:
return vtkm::ErrorCode::DegenerateCellDetected;
}
return vtkm::ErrorCode::UnknownError;
}
} // namespace internal
} // namespace vtkm
#define VTKM_RETURN_ON_ERROR(call) \
do \
{ \
auto status = (call); \
if (status != ::vtkm::ErrorCode::Success) \
{ \
return status; \
} \
} while (false)
#endif //vtk_m_exec_ErrorCode_h

4904
vtkm/Tuple.h Normal file

File diff suppressed because it is too large Load Diff

504
vtkm/Tuple.h.in Normal file

@ -0,0 +1,504 @@
//============================================================================
// 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.
//============================================================================
$# This file uses the pyexpander macro processing utility to build the
$# FunctionInterface facilities that use a variable number of arguments.
$# Information, documentation, and downloads for pyexpander can be found at:
$#
$# http://pyexpander.sourceforge.net/
$#
$# To build the source code, execute the following (after installing
$# pyexpander, of course):
$#
$# expander.py VariantDetail.h.in > VariantDetail.h
$#
$# Ignore the following comment. It is meant for the generated file.
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by Tuple.h.in
#ifndef vtk_m_Tuple_h
#define vtk_m_Tuple_h
#include <vtkm/Types.h>
#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/internal/IndexTag.h>
$py(max_expanded=20)\
$# Python commands used in template expansion.
$py(
def type_list(num_params, name='T'):
if num_params < 1:
return ''
result = '%s0' % name
for param in range(1, num_params):
result += ', %s%d' % (name, param)
return result
def typename_list(num_params, name='T'):
if num_params < 1:
return ''
result = 'typename %s0' % name
for param in range(1, num_params):
result += ', typename %s%d' % (name, param)
return result
def perfect_param_list(num_params, classname='A', argname='a'):
if num_params < 1:
return ''
result = '%s0&& %s0' % (classname, argname)
for param in range(1, num_params):
result += ', %s%d&& %s%d' % (classname, param, argname, param)
return result
)\
$#
$extend(type_list, typename_list, perfect_param_list)\
namespace vtkm
{
///@{
/// \brief VTK-m replacement for std::tuple
///
/// This function serves the same function as `std::tuple` and behaves similarly. However, this
/// version of `Tuple` works on devices that VTK-m supports. There are also some implementation
/// details that makes compiling faster for VTK-m use. We also provide some methods like `Apply`
/// and `ForEach` that are helpful for several VTK-m operations.
///
template <typename... Ts>
class Tuple;
/// \brief Get the size of a tuple.
///
/// Given a `vtkm::Tuple` type, because a `std::integral_constant` of the type.
///
template <typename TupleType>
using TupleSize = std::integral_constant<vtkm::IdComponent, TupleType::Size>;
/// \brief Compatible with `std::tuple_size` for `vtkm::Tuple`.
///
template <typename TupleType>
using tuple_size = std::integral_constant<std::size_t, static_cast<std::size_t>(TupleType::Size)>;
namespace detail
{
template <vtkm::IdComponent Index, typename TupleType>
struct TupleElementImpl
{
using type = decltype(TupleType::ElementTypeI(vtkm::internal::IndexTag<Index>{}));
};
} // namespace detail
/// \brief Becomes the type of the given index for the given `vtkm::Tuple`.
///
template <vtkm::IdComponent Index, typename TupleType>
using TupleElement = typename detail::TupleElementImpl<Index, TupleType>::type;
/// \brief Compatible with `std::tuple_element` for `vtkm::Tuple`.
///
template <std::size_t Index, typename TupleType>
struct tuple_element
{
using type = TupleElement<static_cast<vtkm::IdComponent>(Index), TupleType>;
};
/// \brief Compatible with `std::tuple_element_t` for `vtkm::Tuple`.
///
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.
///
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>())
{
return tuple.template Get<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>())
{
return tuple.template Get<Index>();
}
///@}
///@{
/// \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)
-> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
-> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
///@}
/// \brief Creates a new `vtkm::Tuple` with the given types.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto MakeTuple(Ts&&... args) -> vtkm::Tuple<typename std::decay<Ts>::type...>
{
return vtkm::Tuple<typename std::decay<Ts>::type...>(std::forward<Ts>(args)...);
}
/// \brief Compatible with `std::make_tuple` for `vtkm::Tuple`.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto make_tuple(Ts&&... args) -> decltype(vtkm::MakeTuple(std::forward<Ts>(args)...))
{
return vtkm::MakeTuple(std::forward<Ts>(args)...);
}
namespace detail
{
struct TupleTransformFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Ts>
VTKM_EXEC_CONT auto operator()(Function&& f, Ts&&... args)
-> decltype(vtkm::MakeTuple(f(std::forward<Ts>(args))...))
{
return vtkm::MakeTuple(f(std::forward<Ts>(args))...);
}
};
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
template <typename Function, typename... Ts>
VTKM_EXEC_CONT void operator()(Function&& f, Ts&&... args)
{
(void)std::initializer_list<bool>{ (f(std::forward<Ts>(args)), false)... };
}
};
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
template <>
class Tuple<>
{
public:
static constexpr vtkm::IdComponent Size = 0;
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args)
-> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args) const
-> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&&) const
{
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT vtkm::Tuple<> Transform(Function&&) const
{
return vtkm::Tuple<>{};
}
};
// clang-format off
$for(num_params in range(1, max_expanded + 1))\
template<$typename_list(num_params)>
class Tuple<$type_list(num_params)>
{
$for(index in range(0, num_params))\
T$(index) Value$(index);
static T$(index) ElementTypeI(vtkm::internal::IndexTag<$(index)>);
VTKM_EXEC_CONT vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>)
{
return this->Value$(index);
}
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>) const
{
return this->Value$(index);
}
$endfor\
// Invalid indices
template <vtkm::IdComponent Index>
static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);
template <vtkm::IdComponent, typename>
friend struct detail::TupleElementImpl;
public:
static constexpr vtkm::IdComponent Size = $(num_params);
template <vtkm::IdComponent Index>
using ElementType = vtkm::TupleElement<Index, Tuple<$type_list(num_params)>>;
Tuple() = default;
Tuple(Tuple&&) = default;
Tuple(const Tuple&) = default;
~Tuple() = default;
Tuple& operator=(Tuple&&) = default;
Tuple& operator=(const Tuple&) = default;
VTKM_SUPPRESS_EXEC_WARNINGS
template <$typename_list(num_params, 'A')>
VTKM_EXEC_CONT Tuple($perfect_param_list(num_params, 'A', 'a'))
: Value0(std::forward<A0>(a0))
$for(index in range(1, num_params))\
, Value$(index)(std::forward<A$(index)>(a$(index)))
$endfor\
{
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args)
-> decltype(f(std::forward<Args>(args)..., $type_list(num_params, "Value")))
{
return f(std::forward<Args>(args)..., $type_list(num_params, "Value"));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args) const
-> decltype(f(std::forward<Args>(args)..., $type_list(num_params, "Value")))
{
return f(std::forward<Args>(args)..., $type_list(num_params, "Value"));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*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_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*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)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
};
$endfor\
// Fallback case for tuples with > $(max_expanded) items.
template<$typename_list(max_expanded + 1), typename... Ts>
class Tuple<$type_list(max_expanded + 1), Ts...>
{
$for(index in range(0, max_expanded))\
T$(index) Value$(index);
static T$(index) ElementTypeI(vtkm::internal::IndexTag<$(index)>);
VTKM_EXEC_CONT vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>)
{
return this->Value$(index);
}
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>) const
{
return this->Value$(index);
}
$endfor\
// Implement the "extra" objects in a sub-Tuple
using RemainingValuesType = vtkm::Tuple<T$(max_expanded), Ts...>;
RemainingValuesType RemainingValues;
template <vtkm::IdComponent Index>
static vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>
ElementTypeI(vtkm::internal::IndexTag<Index>);
template <typename vtkm::IdComponent Index>
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>>&
GetImpl(vtkm::internal::IndexTag<Index>) { return vtkm::Get<Index - $(max_expanded)>(this->RemainingValues); }
template <typename vtkm::IdComponent Index>
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>>&
GetImpl(vtkm::internal::IndexTag<Index>) const { return vtkm::Get<Index - $(max_expanded)>(this->RemainingValues); }
template <vtkm::IdComponent, typename>
friend struct detail::TupleElementImpl;
public:
static constexpr vtkm::IdComponent Size =
$(max_expanded + 1) + static_cast<vtkm::IdComponent>(sizeof...(Ts));
template <vtkm::IdComponent Index>
using ElementType = vtkm::TupleElement<Index, Tuple<$type_list(max_expanded + 1), Ts...>>;
Tuple() = default;
Tuple(Tuple&&) = default;
Tuple(const Tuple&) = default;
~Tuple() = default;
Tuple& operator=(Tuple&&) = default;
Tuple& operator=(const Tuple&) = default;
VTKM_SUPPRESS_EXEC_WARNINGS
template <$typename_list(max_expanded, 'A'), typename... As>
VTKM_EXEC_CONT Tuple($perfect_param_list(max_expanded, 'A', 'a'), As&&... remainingArgs)
: Value0(std::forward<A0>(a0))
$for(index in range(1, max_expanded))\
, Value$(index)(std::forward<A$(index)>(a$(index)))
$endfor\
, RemainingValues(std::forward<As>(remainingArgs)...)
{
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args)
-> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1)))
{
return this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args) const
-> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1)))
{
return this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*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_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*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)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
};
///@}
// clang-format on
} // namespace vtkm
#endif //vtk_m_Tuple_h

@ -35,8 +35,8 @@
#include <vector>
#include <vtkm/cont/internal/ArrayHandleExecutionManager.h>
#include <vtkm/cont/internal/ArrayPortalCheck.h>
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
#include <vtkm/cont/internal/ArrayPortalToken.h>
namespace vtkm
{
@ -262,9 +262,9 @@ public:
using StorageType = vtkm::cont::internal::Storage<T, StorageTag_>;
using ValueType = T;
using StorageTag = StorageTag_;
using WritePortalType = vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalType>;
using WritePortalType = vtkm::cont::internal::ArrayPortalCheck<typename StorageType::PortalType>;
using ReadPortalType =
vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalConstType>;
vtkm::cont::internal::ArrayPortalCheck<typename StorageType::PortalConstType>;
template <typename DeviceAdapterTag>
struct ExecutionTypes
{
@ -454,6 +454,9 @@ public:
this->WaitToWrite(lock, vtkm::cont::Token{});
this->ReleaseResourcesExecutionInternal(lock);
this->Internals->GetControlArray(lock)->Allocate(numberOfValues);
// Set to false and then to true to ensure anything pointing to an array before the allocate
// is invalidated.
this->Internals->SetControlArrayValid(lock, false);
this->Internals->SetControlArrayValid(lock, true);
}
@ -690,7 +693,7 @@ protected:
class VTKM_ALWAYS_EXPORT InternalStruct
{
mutable StorageType ControlArray;
mutable bool ControlArrayValid = false;
mutable std::shared_ptr<bool> ControlArrayValid;
mutable std::unique_ptr<ExecutionManagerType> ExecutionArray;
mutable bool ExecutionArrayValid = false;
@ -711,28 +714,52 @@ protected:
InternalStruct(const StorageType& storage);
InternalStruct(StorageType&& storage);
#ifdef VTKM_ASSERTS_CHECKED
~InternalStruct()
{
// It should not be possible to destroy this array if any tokens are still attached to it.
LockType lock(this->Mutex);
VTKM_ASSERT((*this->GetReadCount(lock) == 0) && (*this->GetWriteCount(lock) == 0));
this->SetControlArrayValid(lock, false);
}
#else
~InternalStruct() = default;
#endif
// To access any feature in InternalStruct, you must have locked the mutex. You have
// to prove it by passing in a reference to a std::unique_lock.
VTKM_CONT bool IsControlArrayValid(const LockType& lock) const
{
this->CheckLock(lock);
return this->ControlArrayValid;
if (!this->ControlArrayValid)
{
return false;
}
else
{
return *this->ControlArrayValid;
}
}
VTKM_CONT void SetControlArrayValid(const LockType& lock, bool value)
{
this->CheckLock(lock);
this->ControlArrayValid = value;
if (IsControlArrayValid(lock) == value)
{
return;
}
if (value) // ControlArrayValid == false or nullptr
{
// If we are changing the valid flag from false to true, then refresh the pointer.
// There may be array portals that already have a reference to the flag. Those portals
// will stay in an invalid state whereas new portals will go to a valid state. To
// handle both conditions, drop the old reference and create a new one.
this->ControlArrayValid.reset(new bool(true));
}
else // value == false and ControlArrayValid == true
{
*this->ControlArrayValid = false;
}
}
VTKM_CONT std::shared_ptr<bool> GetControlArrayValidPointer(const LockType& lock) const
{
this->CheckLock(lock);
return this->ControlArrayValid;
}
VTKM_CONT StorageType* GetControlArray(const LockType& lock) const
{

@ -21,7 +21,7 @@ template <typename T, typename S>
ArrayHandle<T, S>::InternalStruct::InternalStruct(
const typename ArrayHandle<T, S>::StorageType& storage)
: ControlArray(storage)
, ControlArrayValid(true)
, ControlArrayValid(new bool(true))
, ExecutionArrayValid(false)
{
}
@ -29,7 +29,7 @@ ArrayHandle<T, S>::InternalStruct::InternalStruct(
template <typename T, typename S>
ArrayHandle<T, S>::InternalStruct::InternalStruct(typename ArrayHandle<T, S>::StorageType&& storage)
: ControlArray(std::move(storage))
, ControlArrayValid(true)
, ControlArrayValid(new bool(true))
, ExecutionArrayValid(false)
{
}
@ -160,15 +160,15 @@ template <typename T, typename S>
typename ArrayHandle<T, S>::ReadPortalType ArrayHandle<T, S>::ReadPortal() const
{
LockType lock = this->GetLock();
vtkm::cont::Token token;
this->WaitToRead(lock, token);
{
vtkm::cont::Token token;
this->WaitToRead(lock, token);
}
this->SyncControlArray(lock);
if (this->Internals->IsControlArrayValid(lock))
{
token.Attach(
*this, this->Internals->GetReadCount(lock), lock, &this->Internals->ConditionVariable);
return ReadPortalType(std::move(token),
return ReadPortalType(this->Internals->GetControlArrayValidPointer(lock),
this->Internals->GetControlArray(lock)->GetPortalConst());
}
else
@ -182,8 +182,10 @@ template <typename T, typename S>
typename ArrayHandle<T, S>::WritePortalType ArrayHandle<T, S>::WritePortal() const
{
LockType lock = this->GetLock();
vtkm::cont::Token token;
this->WaitToWrite(lock, token);
{
vtkm::cont::Token token;
this->WaitToWrite(lock, token);
}
this->SyncControlArray(lock);
if (this->Internals->IsControlArrayValid(lock))
@ -192,9 +194,8 @@ typename ArrayHandle<T, S>::WritePortalType ArrayHandle<T, S>::WritePortal() con
// array will become invalid. Play it safe and release the execution
// resources. (Use the const version to preserve the execution array.)
this->ReleaseResourcesExecutionInternal(lock);
token.Attach(
*this, this->Internals->GetWriteCount(lock), lock, &this->Internals->ConditionVariable);
return WritePortalType(std::move(token), this->Internals->GetControlArray(lock)->GetPortal());
return WritePortalType(this->Internals->GetControlArrayValidPointer(lock),
this->Internals->GetControlArray(lock)->GetPortal());
}
else
{

@ -14,12 +14,13 @@
#include <vtkm/Deprecated.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Tuple.h>
#include <vtkm/VecTraits.h>
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkm/internal/brigand.hpp>
#include <vtkmstd/integer_sequence.h>
#include <type_traits>
namespace vtkm
@ -61,278 +62,162 @@ struct AllAreArrayHandles
};
// GetValueType: ---------------------------------------------------------------
// Determines the output ValueType of the objects in TupleType, a vtkmstd::tuple
// which can contain ArrayHandles, ArrayPortals...anything with a ValueType
// defined, really. For example, if the input TupleType contains 3 types with
// Float32 ValueTypes, then the ValueType defined here will be Vec<Float32, 3>.
// This also validates that all members have the same ValueType.
template <typename TupleType>
struct GetValueTypeImpl;
// Determines the output `ValueType` of the set of `ArrayHandle` objects. For example, if the input
// set contains 3 types with `vtkm::Float32` ValueTypes, then the ValueType defined here will be
// `vtkm::Vec<Float32, 3>`. This also validates that all members have the same `ValueType`.
template <typename Head, typename... Tail>
struct GetValueTypeImpl<vtkmstd::tuple<Head, Tail...>>
template <typename ExpectedValueType, typename ArrayType>
constexpr bool CheckValueType()
{
using Type = typename Head::ValueType;
private:
using Next = GetValueTypeImpl<vtkmstd::tuple<Tail...>>;
VTKM_STATIC_ASSERT_MSG(VTKM_PASS_COMMAS(std::is_same<Type, typename Next::Type>::value),
VTKM_STATIC_ASSERT_MSG((std::is_same<ExpectedValueType, typename ArrayType::ValueType>::value),
"ArrayHandleCompositeVector must be built from "
"ArrayHandles with the same ValueTypes.");
};
return std::is_same<ExpectedValueType, typename ArrayType::ValueType>::value;
}
template <typename Head>
struct GetValueTypeImpl<vtkmstd::tuple<Head>>
{
using Type = typename Head::ValueType;
};
template <typename TupleType>
template <typename ArrayType0, typename... ArrayTypes>
struct GetValueType
{
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<TupleType>::value >= 1);
static const vtkm::IdComponent COUNT =
static_cast<vtkm::IdComponent>(vtkmstd::tuple_size<TupleType>::value);
using ComponentType = typename GetValueTypeImpl<TupleType>::Type;
static constexpr vtkm::IdComponent COUNT =
static_cast<vtkm::IdComponent>(sizeof...(ArrayTypes)) + 1;
using ComponentType = typename ArrayType0::ValueType;
static constexpr std::array<bool, sizeof...(ArrayTypes) + 1> ValueCheck{
{ true, CheckValueType<ComponentType, ArrayTypes>()... }
};
using ValueType = vtkm::Vec<ComponentType, COUNT>;
};
// TupleTypePrepend: -----------------------------------------------------------
// Prepend a type to a tuple, defining the new tuple in Type.
template <typename PrependType, typename TupleType>
struct TupleTypePrepend;
template <typename PrependType, typename... TupleTypes>
struct TupleTypePrepend<PrependType, vtkmstd::tuple<TupleTypes...>>
// Special case for only one component
template <typename ArrayType>
struct GetValueType<ArrayType>
{
using Type = vtkmstd::tuple<PrependType, TupleTypes...>;
static constexpr vtkm::IdComponent COUNT = 1;
using ComponentType = typename ArrayType::ValueType;
using ValueType = typename ArrayType::ValueType;
};
// ArrayTupleForEach: ----------------------------------------------------------
// Collection of methods that iterate through the arrays in ArrayTuple to
// implement the ArrayHandle API.
template <std::size_t Index, std::size_t Count, typename ArrayTuple>
struct ArrayTupleForEach
// -----------------------------------------------------------------------------
// Functors to access Storage methods. This is used with vtkm::Tuple's
// ForEach and Transform methods.
struct WritePortal
{
using Next = ArrayTupleForEach<Index + 1, Count, ArrayTuple>;
template <typename PortalTuple>
VTKM_CONT static void GetPortalTupleControl(ArrayTuple& arrays, PortalTuple& portals)
template <typename ArrayHandle>
typename ArrayHandle::WritePortalType operator()(const ArrayHandle& array) const
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).WritePortal();
Next::GetPortalTupleControl(arrays, portals);
}
template <typename PortalTuple>
VTKM_CONT static void GetPortalConstTupleControl(const ArrayTuple& arrays, PortalTuple& portals)
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).ReadPortal();
Next::GetPortalConstTupleControl(arrays, portals);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInput(const ArrayTuple& arrays,
PortalTuple& portals,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).PrepareForInput(DeviceTag(), token);
Next::template PrepareForInput<DeviceTag>(arrays, portals, token);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInPlace(ArrayTuple& arrays,
PortalTuple& portals,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) =
vtkmstd::get<Index>(arrays).PrepareForInPlace(DeviceTag(), token);
Next::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForOutput(ArrayTuple& arrays,
PortalTuple& portals,
vtkm::Id numValues,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) =
vtkmstd::get<Index>(arrays).PrepareForOutput(numValues, DeviceTag(), token);
Next::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
}
VTKM_CONT
static void Allocate(ArrayTuple& arrays, vtkm::Id numValues)
{
vtkmstd::get<Index>(arrays).Allocate(numValues);
Next::Allocate(arrays, numValues);
}
VTKM_CONT
static void Shrink(ArrayTuple& arrays, vtkm::Id numValues)
{
vtkmstd::get<Index>(arrays).Shrink(numValues);
Next::Shrink(arrays, numValues);
}
VTKM_CONT
static void ReleaseResources(ArrayTuple& arrays)
{
vtkmstd::get<Index>(arrays).ReleaseResources();
Next::ReleaseResources(arrays);
return array.WritePortal();
}
};
template <std::size_t Index, typename ArrayTuple>
struct ArrayTupleForEach<Index, Index, ArrayTuple>
struct ReadPortal
{
template <typename PortalTuple>
VTKM_CONT static void GetPortalTupleControl(ArrayTuple&, PortalTuple&)
template <typename ArrayHandle>
typename ArrayHandle::ReadPortalType operator()(const ArrayHandle& array) const
{
return array.ReadPortal();
}
template <typename PortalTuple>
VTKM_CONT static void GetPortalConstTupleControl(const ArrayTuple&, PortalTuple&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInput(const ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInPlace(ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForOutput(ArrayTuple&, PortalTuple&, vtkm::Id, vtkm::cont::Token&)
{
}
VTKM_CONT static void Allocate(ArrayTuple&, vtkm::Id) {}
VTKM_CONT static void Shrink(ArrayTuple&, vtkm::Id) {}
VTKM_CONT static void ReleaseResources(ArrayTuple&) {}
};
// PortalTupleTraits: ----------------------------------------------------------
// Determine types of ArrayHandleCompositeVector portals and construct the
// portals from the input arrays.
template <typename ArrayTuple>
struct PortalTupleTypeGeneratorImpl;
template <typename Head, typename... Tail>
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head, Tail...>>
struct Allocate
{
using Next = PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Tail...>>;
using PortalControlTuple = typename TupleTypePrepend<typename Head::WritePortalType,
typename Next::PortalControlTuple>::Type;
using PortalConstControlTuple =
typename TupleTypePrepend<typename Head::ReadPortalType,
typename Next::PortalConstControlTuple>::Type;
template <typename DeviceTag>
struct ExecutionTypes
vtkm::Id NumValues;
VTKM_CONT Allocate(vtkm::Id numValues)
: NumValues(numValues)
{
using PortalTuple = typename TupleTypePrepend<
typename Head::template ExecutionTypes<DeviceTag>::Portal,
typename Next::template ExecutionTypes<DeviceTag>::PortalTuple>::Type;
using PortalConstTuple = typename TupleTypePrepend<
typename Head::template ExecutionTypes<DeviceTag>::PortalConst,
typename Next::template ExecutionTypes<DeviceTag>::PortalConstTuple>::Type;
};
}
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
array.Allocate(this->NumValues);
}
};
template <typename Head>
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head>>
struct Shrink
{
using PortalControlTuple = vtkmstd::tuple<typename Head::WritePortalType>;
using PortalConstControlTuple = vtkmstd::tuple<typename Head::ReadPortalType>;
template <typename DeviceTag>
struct ExecutionTypes
vtkm::Id NumValues;
VTKM_CONT Shrink(vtkm::Id numValues)
: NumValues(numValues)
{
using PortalTuple = vtkmstd::tuple<typename Head::template ExecutionTypes<DeviceTag>::Portal>;
using PortalConstTuple =
vtkmstd::tuple<typename Head::template ExecutionTypes<DeviceTag>::PortalConst>;
};
}
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
array.Shrink(this->NumValues);
}
};
template <typename ArrayTuple>
struct PortalTupleTraits
struct ReleaseResources
{
private:
using TypeGenerator = PortalTupleTypeGeneratorImpl<ArrayTuple>;
using ForEachArray = ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
public:
using PortalTuple = typename TypeGenerator::PortalControlTuple;
using PortalConstTuple = typename TypeGenerator::PortalConstControlTuple;
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalTuple>::value);
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalConstTuple>::value);
template <typename DeviceTag>
struct ExecutionTypes
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
using PortalTuple = typename TypeGenerator::template ExecutionTypes<DeviceTag>::PortalTuple;
using PortalConstTuple =
typename TypeGenerator::template ExecutionTypes<DeviceTag>::PortalConstTuple;
array.ReleaseResources();
}
};
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalTuple>::value);
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalConstTuple>::value);
};
// -----------------------------------------------------------------------------
// Functors to access ArrayTransfer methods. This is used with vtkm::Tuple's
// ForEach and Transform methods.
VTKM_CONT
static const PortalTuple GetPortalTupleControl(ArrayTuple& arrays)
template <typename Device>
struct PrepareForInput
{
vtkm::cont::Token& Token;
VTKM_CONT PrepareForInput(vtkm::cont::Token& token)
: Token(token)
{
PortalTuple portals;
ForEachArray::GetPortalTupleControl(arrays, portals);
return portals;
}
VTKM_CONT
static const PortalConstTuple GetPortalConstTupleControl(const ArrayTuple& arrays)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::PortalConst operator()(
const Array& array)
{
return array.PrepareForInput(Device{}, this->Token);
}
};
template <typename Device>
struct PrepareForInPlace
{
vtkm::cont::Token& Token;
VTKM_CONT PrepareForInPlace(vtkm::cont::Token& token)
: Token(token)
{
PortalConstTuple portals;
ForEachArray::GetPortalConstTupleControl(arrays, portals);
return portals;
}
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalConstTuple PrepareForInput(
const ArrayTuple& arrays,
vtkm::cont::Token& token)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::Portal operator()(Array& array)
{
return array.PrepareForInPlace(Device{}, this->Token);
}
};
template <typename Device>
struct PrepareForOutput
{
vtkm::Id NumValues;
vtkm::cont::Token& Token;
VTKM_CONT PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token)
: NumValues(numValues)
, Token(token)
{
typename ExecutionTypes<DeviceTag>::PortalConstTuple portals;
ForEachArray::template PrepareForInput<DeviceTag>(arrays, portals, token);
return portals;
}
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple PrepareForInPlace(
ArrayTuple& arrays,
vtkm::cont::Token& token)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::Portal operator()(Array& array)
{
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
ForEachArray::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
return portals;
return array.PrepareForOutput(this->NumValues, Device{}, this->Token);
}
};
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple
PrepareForOutput(ArrayTuple& arrays, vtkm::Id numValues, vtkm::cont::Token& token)
struct ReleaseResourcesExecution
{
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
ForEachArray::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
return portals;
array.ReleaseResourcesExecution();
}
};
@ -347,7 +232,7 @@ struct ArraySizeValidatorImpl
VTKM_CONT
static bool Exec(const TupleType& tuple, vtkm::Id numVals)
{
return vtkmstd::get<Index>(tuple).GetNumberOfValues() == numVals && Next::Exec(tuple, numVals);
return vtkm::Get<Index>(tuple).GetNumberOfValues() == numVals && Next::Exec(tuple, numVals);
}
};
@ -364,113 +249,96 @@ struct ArraySizeValidator
VTKM_CONT
static bool Exec(const TupleType& tuple, vtkm::Id numVals)
{
return ArraySizeValidatorImpl<0, vtkmstd::tuple_size<TupleType>::value, TupleType>::Exec(
tuple, numVals);
return ArraySizeValidatorImpl<0, vtkm::TupleSize<TupleType>::value, TupleType>::Exec(tuple,
numVals);
}
};
template <typename PortalList>
template <typename... PortalList>
using AllPortalsAreWritable =
typename brigand::all<PortalList,
typename brigand::all<brigand::list<PortalList...>,
brigand::bind<vtkm::internal::PortalSupportsSets, brigand::_1>>::type;
// GetFromPortals: -------------------------------------------------------------
// Given a set of array portals as arguments, returns a Vec comprising the values
// at the provided index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Portals>
VTKM_EXEC_CONT typename GetValueType<Portals...>::ValueType GetFromPortals(
vtkm::Id index,
const Portals&... portals)
{
return { portals.Get(index)... };
}
// SetToPortals: ---------------------------------------------------------------
// Given a Vec-like object, and index, and a set of array portals, sets each of
// the portals to the respective component of the Vec.
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ValueType, vtkm::IdComponent... I, typename... Portals>
VTKM_EXEC_CONT void SetToPortalsImpl(vtkm::Id index,
const ValueType& value,
vtkmstd::integer_sequence<vtkm::IdComponent, I...>,
const Portals&... portals)
{
using Traits = vtkm::VecTraits<ValueType>;
(void)std::initializer_list<bool>{ (portals.Set(index, Traits::GetComponent(value, I)),
false)... };
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ValueType, typename... Portals>
VTKM_EXEC_CONT void SetToPortals(vtkm::Id index, const ValueType& value, const Portals&... portals)
{
SetToPortalsImpl(
index,
value,
vtkmstd::make_integer_sequence<vtkm::IdComponent, vtkm::IdComponent(sizeof...(Portals))>{},
portals...);
}
} // end namespace compvec
template <typename PortalTuple>
template <typename... PortalTypes>
class VTKM_ALWAYS_EXPORT ArrayPortalCompositeVector
{
using Writable = compvec::AllPortalsAreWritable<PortalTuple>;
using Writable = compvec::AllPortalsAreWritable<PortalTypes...>;
using TupleType = vtkm::Tuple<PortalTypes...>;
TupleType Portals;
public:
using ValueType = typename compvec::GetValueType<PortalTuple>::ValueType;
using ValueType = typename compvec::GetValueType<PortalTypes...>::ValueType;
private:
using Traits = vtkm::VecTraits<ValueType>;
// Get: ----------------------------------------------------------------------
template <vtkm::IdComponent VectorIndex, typename PortalTupleT>
struct GetImpl;
template <vtkm::IdComponent VectorIndex, typename Head, typename... Tail>
struct GetImpl<VectorIndex, vtkmstd::tuple<Head, Tail...>>
{
using Next = GetImpl<VectorIndex + 1, vtkmstd::tuple<Tail...>>;
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, ValueType& vec, vtkm::Id arrayIndex)
{
Traits::SetComponent(vec, VectorIndex, vtkmstd::get<VectorIndex>(portals).Get(arrayIndex));
Next::Exec(portals, vec, arrayIndex);
}
};
template <vtkm::IdComponent VectorIndex, typename Head>
struct GetImpl<VectorIndex, vtkmstd::tuple<Head>>
{
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, ValueType& vec, vtkm::Id arrayIndex)
{
Traits::SetComponent(vec, VectorIndex, vtkmstd::get<VectorIndex>(portals).Get(arrayIndex));
}
};
// Set: ----------------------------------------------------------------------
template <vtkm::IdComponent VectorIndex, typename PortalTupleT>
struct SetImpl;
template <vtkm::IdComponent VectorIndex, typename Head, typename... Tail>
struct SetImpl<VectorIndex, vtkmstd::tuple<Head, Tail...>>
{
using Next = SetImpl<VectorIndex + 1, vtkmstd::tuple<Tail...>>;
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, const ValueType& vec, vtkm::Id arrayIndex)
{
vtkmstd::get<VectorIndex>(portals).Set(arrayIndex, Traits::GetComponent(vec, VectorIndex));
Next::Exec(portals, vec, arrayIndex);
}
};
template <vtkm::IdComponent VectorIndex, typename Head>
struct SetImpl<VectorIndex, vtkmstd::tuple<Head>>
{
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, const ValueType& vec, vtkm::Id arrayIndex)
{
vtkmstd::get<VectorIndex>(portals).Set(arrayIndex, Traits::GetComponent(vec, VectorIndex));
}
};
public:
VTKM_EXEC_CONT
ArrayPortalCompositeVector() {}
VTKM_CONT
ArrayPortalCompositeVector(const PortalTuple& portals)
ArrayPortalCompositeVector(const PortalTypes&... portals)
: Portals(portals...)
{
}
VTKM_CONT
ArrayPortalCompositeVector(const TupleType& portals)
: Portals(portals)
{
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return vtkmstd::get<0>(this->Portals).GetNumberOfValues(); }
vtkm::Id GetNumberOfValues() const { return vtkm::Get<0>(this->Portals).GetNumberOfValues(); }
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const
{
ValueType result;
GetImpl<0, PortalTuple>::Exec(this->Portals, result, index);
return result;
return this->Portals.Apply(compvec::GetFromPortals<PortalTypes...>, index);
}
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
SetImpl<0, PortalTuple>::Exec(this->Portals, value, index);
this->Portals.Apply(compvec::SetToPortals<ValueType, PortalTypes...>, index, value);
}
private:
PortalTuple Portals;
};
} // namespace internal
@ -483,12 +351,6 @@ struct VTKM_ALWAYS_EXPORT StorageTagCompositeVec
namespace internal
{
template <typename ArrayTuple>
struct VTKM_ALWAYS_EXPORT VTKM_DEPRECATED(1.6, "Use StorageTagCompositeVec instead.")
StorageTagCompositeVector
{
};
template <typename... ArrayTs>
struct CompositeVectorTraits
{
@ -499,38 +361,27 @@ struct CompositeVectorTraits
"Template parameters for ArrayHandleCompositeVector "
"must be a list of ArrayHandle types.");
using ValueType = typename compvec::GetValueType<vtkmstd::tuple<ArrayTs...>>::ValueType;
using ValueType = typename compvec::GetValueType<ArrayTs...>::ValueType;
using StorageTag = vtkm::cont::StorageTagCompositeVec<typename ArrayTs::StorageTag...>;
using StorageType = Storage<ValueType, StorageTag>;
using Superclass = ArrayHandle<ValueType, StorageTag>;
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... Arrays>
class Storage<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>>
: CompositeVectorTraits<Arrays...>::StorageType
{
using Superclass = typename CompositeVectorTraits<Arrays...>::StorageType;
using Superclass::Superclass;
};
VTKM_DEPRECATED_SUPPRESS_END
template <typename T, typename... StorageTags>
class Storage<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
vtkm::cont::StorageTagCompositeVec<StorageTags...>>
{
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
using ForEachArray =
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
using PortalTypes = compvec::PortalTupleTraits<ArrayTuple>;
using PortalTupleType = typename PortalTypes::PortalTuple;
using PortalConstTupleType = typename PortalTypes::PortalConstTuple;
using ArrayTuple = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
ArrayTuple Arrays;
bool Valid;
public:
using ValueType = typename compvec::GetValueType<ArrayTuple>::ValueType;
using PortalType = ArrayPortalCompositeVector<PortalTupleType>;
using PortalConstType = ArrayPortalCompositeVector<PortalConstTupleType>;
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
using PortalType = ArrayPortalCompositeVector<
typename vtkm::cont::ArrayHandle<T, StorageTags>::WritePortalType...>;
using PortalConstType =
ArrayPortalCompositeVector<typename vtkm::cont::ArrayHandle<T, StorageTags>::ReadPortalType...>;
VTKM_CONT
Storage()
@ -538,18 +389,6 @@ public:
{
}
VTKM_CONT
Storage(const ArrayTuple& arrays)
: Arrays(arrays)
, Valid(true)
{
using SizeValidator = compvec::ArraySizeValidator<ArrayTuple>;
if (!SizeValidator::Exec(this->Arrays, this->GetNumberOfValues()))
{
throw ErrorBadValue("All arrays must have the same number of values.");
}
}
template <typename... ArrayTypes>
VTKM_CONT Storage(const ArrayTypes&... arrays)
: Arrays(arrays...)
@ -566,42 +405,44 @@ public:
PortalType GetPortal()
{
VTKM_ASSERT(this->Valid);
return PortalType(PortalTypes::GetPortalTupleControl(this->Arrays));
return this->Arrays.Transform(compvec::WritePortal{});
}
void TypeCheck(int) const;
VTKM_CONT
PortalConstType GetPortalConst() const
{
VTKM_ASSERT(this->Valid);
return PortalConstType(PortalTypes::GetPortalConstTupleControl(this->Arrays));
this->Arrays.Transform(compvec::ReadPortal{});
return this->Arrays.Transform(compvec::ReadPortal{});
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(this->Valid);
return vtkmstd::get<0>(this->Arrays).GetNumberOfValues();
return vtkm::Get<0>(this->Arrays).GetNumberOfValues();
}
VTKM_CONT
void Allocate(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
ForEachArray::Allocate(this->Arrays, numValues);
this->Arrays.ForEach(compvec::Allocate{ numValues });
}
VTKM_CONT
void Shrink(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
ForEachArray::Shrink(this->Arrays, numValues);
this->Arrays.ForEach(compvec::Shrink{ numValues });
}
VTKM_CONT
void ReleaseResources()
{
VTKM_ASSERT(this->Valid);
ForEachArray::ReleaseResources(this->Arrays);
this->Arrays.ForEach(compvec::ReleaseResources{});
}
VTKM_CONT
@ -617,28 +458,25 @@ public:
VTKM_ASSERT(this->Valid);
return this->Arrays;
}
private:
ArrayTuple Arrays;
bool Valid;
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... Arrays, typename DeviceTag>
struct ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>,
DeviceTag>
: ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
typename CompositeVectorTraits<Arrays...>::StorageType,
DeviceTag>
// Special case for single component. Just defer to the original storage.
template <typename T, typename StorageTag>
class Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : public Storage<T, StorageTag>
{
using Superclass =
ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
typename CompositeVectorTraits<Arrays...>::StorageType,
DeviceTag>;
using Superclass::Superclass;
using ArrayType = vtkm::cont::ArrayHandle<T, StorageTag>;
using TupleType = vtkm::Tuple<ArrayType>;
public:
Storage() = default;
Storage(const ArrayType& array)
: Storage<T, StorageTag>(array.GetStorage())
{
}
VTKM_CONT
const TupleType GetArrayTuple() const { return TupleType(ArrayType(this->GetStoragea())); }
};
VTKM_DEPRECATED_SUPPRESS_END
template <typename T, typename... StorageTags, typename DeviceTag>
class ArrayTransfer<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
@ -647,26 +485,27 @@ class ArrayTransfer<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(Storag
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceTag);
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
using ArrayTuple = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
public:
using ValueType = typename compvec::GetValueType<ArrayTuple>::ValueType;
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
private:
using ForEachArray =
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
using StorageTag = vtkm::cont::StorageTagCompositeVec<StorageTags...>;
using StorageType = internal::Storage<ValueType, StorageTag>;
using ControlTraits = compvec::PortalTupleTraits<ArrayTuple>;
using ExecutionTraits = typename ControlTraits::template ExecutionTypes<DeviceTag>;
StorageType* Storage;
public:
using PortalControl = ArrayPortalCompositeVector<typename ControlTraits::PortalTuple>;
using PortalConstControl = ArrayPortalCompositeVector<typename ControlTraits::PortalConstTuple>;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
using PortalExecution = ArrayPortalCompositeVector<typename ExecutionTraits::PortalTuple>;
using PortalExecution = ArrayPortalCompositeVector<
typename vtkm::cont::ArrayHandle<T,
StorageTags>::template ExecutionTypes<DeviceTag>::Portal...>;
using PortalConstExecution =
ArrayPortalCompositeVector<typename ExecutionTraits::PortalConstTuple>;
ArrayPortalCompositeVector<typename vtkm::cont::ArrayHandle<T, StorageTags>::
template ExecutionTypes<DeviceTag>::PortalConst...>;
VTKM_CONT
ArrayTransfer(StorageType* storage)
@ -680,22 +519,20 @@ public:
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) const
{
return PortalConstExecution(
ControlTraits::template PrepareForInput<DeviceTag>(this->GetArrayTuple(), token));
return this->GetArrayTuple().Transform(compvec::PrepareForInput<DeviceTag>{ token });
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
{
return PortalExecution(
ControlTraits::template PrepareForInPlace<DeviceTag>(this->GetArrayTuple(), token));
return this->GetArrayTuple().Transform(compvec::PrepareForInPlace<DeviceTag>{ token });
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token)
{
return PortalExecution(
ControlTraits::template PrepareForOutput<DeviceTag>(this->GetArrayTuple(), numValues, token));
return this->GetArrayTuple().Transform(
compvec::PrepareForOutput<DeviceTag>{ numValues, token });
}
VTKM_CONT
@ -707,17 +544,14 @@ public:
}
VTKM_CONT
void Shrink(vtkm::Id numValues) { ForEachArray::Shrink(this->GetArrayTuple(), numValues); }
void Shrink(vtkm::Id numValues) { this->GetArrayTuple().ForEach(compvec::Shrink{ numValues }); }
VTKM_CONT
void ReleaseResources() { ForEachArray::ReleaseResources(this->GetArrayTuple()); }
void ReleaseResources() { this->GetArrayTuple().ForEach(compvec::ReleaseResourcesExecution{}); }
VTKM_CONT
const ArrayTuple& GetArrayTuple() const { return this->Storage->GetArrayTuple(); }
ArrayTuple& GetArrayTuple() { return this->Storage->GetArrayTuple(); }
private:
StorageType* Storage;
};
} // namespace internal
@ -742,7 +576,7 @@ class ArrayHandleCompositeVector
{
private:
using Traits = internal::CompositeVectorTraits<ArrayTs...>;
using TupleType = vtkmstd::tuple<ArrayTs...>;
using TupleType = vtkm::Tuple<ArrayTs...>;
using StorageType = typename Traits::StorageType;
public:
@ -798,59 +632,12 @@ struct SerializableTypeString<
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
{
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... AHs>
struct SerializableTypeString<vtkm::cont::ArrayHandle<
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<vtkmstd::tuple<AHs...>>>>
: SerializableTypeString<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
};
VTKM_DEPRECATED_SUPPRESS_END
}
} // vtkm::cont
namespace mangled_diy_namespace
{
namespace internal
{
template <typename Functor, typename TupleType, typename... Args>
inline void TupleForEachImpl(TupleType&& t,
std::integral_constant<size_t, 0>,
Functor&& f,
Args&&... args)
{
f(vtkmstd::get<0>(t), std::forward<Args>(args)...);
}
template <typename Functor, typename TupleType, size_t Index, typename... Args>
inline void TupleForEachImpl(TupleType&& t,
std::integral_constant<size_t, Index>,
Functor&& f,
Args&&... args)
{
TupleForEachImpl(std::forward<TupleType>(t),
std::integral_constant<size_t, Index - 1>{},
std::forward<Functor>(f),
std::forward<Args>(args)...);
f(vtkmstd::get<Index>(t), std::forward<Args>(args)...);
}
template <typename Functor, typename TupleType, typename... Args>
inline void TupleForEach(TupleType&& t, Functor&& f, Args&&... args)
{
constexpr auto size = vtkmstd::tuple_size<typename std::decay<TupleType>::type>::value;
TupleForEachImpl(std::forward<TupleType>(t),
std::integral_constant<size_t, size - 1>{},
std::forward<Functor>(f),
std::forward<Args>(args)...);
}
} // internal
template <typename... AHs>
struct Serialization<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
@ -860,33 +647,47 @@ private:
struct SaveFunctor
{
template <typename AH>
void operator()(const AH& ah, BinaryBuffer& bb) const
BinaryBuffer& Buffer;
SaveFunctor(BinaryBuffer& bb)
: Buffer(bb)
{
vtkmdiy::save(bb, ah);
}
template <typename AH>
void operator()(const AH& ah) const
{
vtkmdiy::save(this->Buffer, ah);
}
};
struct LoadFunctor
{
template <typename AH>
void operator()(AH& ah, BinaryBuffer& bb) const
BinaryBuffer& Buffer;
LoadFunctor(BinaryBuffer& bb)
: Buffer(bb)
{
vtkmdiy::load(bb, ah);
}
template <typename AH>
void operator()(AH& ah) const
{
vtkmdiy::load(this->Buffer, ah);
}
};
static BaseType Create(const AHs&... arrays) { return Type(arrays...); }
public:
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
{
internal::TupleForEach(obj.GetStorage().GetArrayTuple(), SaveFunctor{}, bb);
obj.GetStorage().GetArrayTuple().ForEach(SaveFunctor{ bb });
}
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
{
vtkmstd::tuple<AHs...> arrayTuple;
internal::TupleForEach(arrayTuple, LoadFunctor{}, bb);
obj = BaseType(typename BaseType::StorageType(arrayTuple));
vtkm::Tuple<AHs...> tuple;
tuple.ForEach(LoadFunctor{ bb });
obj = tuple.Apply(Create);
}
};
@ -897,16 +698,6 @@ struct Serialization<
: Serialization<vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
{
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... AHs>
struct Serialization<vtkm::cont::ArrayHandle<
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<vtkmstd::tuple<AHs...>>>>
: Serialization<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
};
VTKM_DEPRECATED_SUPPRESS_END
} // diy
/// @endcond SERIALIZATION

@ -79,8 +79,9 @@ public:
VTKM_CONT
ArrayHandleConstant(T value, vtkm::Id numberOfValues = 0)
: Superclass(
typename Superclass::ReadPortalType(internal::ConstantFunctor<T>(value), numberOfValues))
: Superclass(typename internal::Storage<T, StorageTag>::PortalConstType(
internal::ConstantFunctor<T>(value),
numberOfValues))
{
}
};

@ -126,7 +126,7 @@ public:
VTKM_CONT
ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::Id length)
: Superclass(typename Superclass::ReadPortalType(start, step, length))
: Superclass(internal::ArrayPortalCounting<CountingValueType>(start, step, length))
{
}
};

@ -15,29 +15,18 @@
#include <vtkm/cont/Storage.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Tuple.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkm/internal/brigand.hpp>
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <vtkmstd/integer_sequence.h>
#include <type_traits>
#include <utility>
// Some compilers like brigand's integer sequences.
// Some compilers prefer tao's.
// Brigand seems to have more support, so we'll use that as default and fallback
// to tao when brigand fails. With C++14, we'll be able to just use the STL.
#if !defined(VTKM_CUDA_DEVICE_PASS) && \
(defined(VTKM_GCC) || \
(defined(__apple_build_version__) && (__apple_build_version__ >= 10000000)) || \
(defined(VTKM_CLANG) && (__clang_major__ >= 5)))
#define VTKM_USE_TAO_SEQ
#endif
namespace vtkm
{
namespace cont
@ -407,14 +396,10 @@ struct DecoratorStorageTraits
"ArrayHandleDecorator must be a list of ArrayHandle "
"types.");
using ArrayTupleType = vtkmstd::tuple<ArrayTs...>;
using ArrayTupleType = vtkm::Tuple<ArrayTs...>;
// size_t integral constants that index ArrayTs:
#ifndef VTKM_USE_TAO_SEQ
using IndexList = brigand::make_sequence<brigand::size_t<0>, sizeof...(ArrayTs)>;
#else // VTKM_USE_TAO_SEQ
using IndexList = tao::seq::make_index_sequence<sizeof...(ArrayTs)>;
#endif // VTKM_USE_TAO_SEQ
// size_t integral constants that index ArrayTs:
using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>;
// true_type/false_type depending on whether the decorator supports Allocate/Shrink:
using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
@ -532,186 +517,83 @@ struct DecoratorStorageTraits
}
#ifndef VTKM_USE_TAO_SEQ
// Portal construction methods. These actually create portals.
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues,
impl,
// More MSVC ICE avoidance while expanding the Indices parameter pack,
// which is a list of std::integral_constant<size_t, ...>:
//
// Indices::value : Works everywhere but MSVC2017, which crashes on it.
// Indices{} : Works on MSVC2017, but won't compile on MSVC2015.
// Indices{}.value : Works on both MSVC2015 and MSVC2017.
//
// Don't touch the following line unless you really, really have to.
WritePortal(vtkmstd::get<Indices{}.value>(arrays))...);
numValues, impl, WritePortal(vtkm::Get<Indices>(arrays))...);
}
template <template <typename...> class List, typename... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
template <std::size_t... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(
const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
ReadPortal(vtkmstd::get<Indices{}.value>(arrays))...);
numValues, impl, ReadPortal(vtkm::Get<Indices>(arrays))...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev,
vtkm::cont::Token& token)
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(
const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalInput(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev,
vtkm::cont::Token& token)
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(
const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInPlace(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalInPlace(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalOutput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalOutput(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
CallAllocate(IsAllocatable{}, impl, numValues, vtkm::Get<Indices>(arrays)...);
}
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
CallShrink(IsShrinkable{}, impl, numValues, vtkm::Get<Indices>(arrays)...);
}
#else // VTKM_USE_TAO_SEQ
// Portal construction methods. These actually create portals.
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues, impl, WritePortal(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues, impl, ReadPortal(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues, impl, GetPortalInput(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalInPlace(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalOutput(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
}
#endif // VTKM_USE_TAO_SEQ
};
} // end namespace decor
@ -1030,7 +912,7 @@ public:
ArrayHandleDecorator(vtkm::Id numValues,
const typename std::decay<DecoratorImplT>::type& impl,
const typename std::decay<ArrayTs>::type&... arrays)
: Superclass{ StorageType{ impl, vtkmstd::make_tuple(arrays...), numValues } }
: Superclass{ StorageType{ impl, vtkm::MakeTuple(arrays...), numValues } }
{
}
};

@ -17,7 +17,7 @@
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <vtkmstd/integer_sequence.h>
#include <array>
#include <limits>
@ -70,7 +70,7 @@ public:
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex) const
{
return this->Get(valueIndex, tao::seq::make_index_sequence<NUM_COMPONENTS>());
return this->Get(valueIndex, vtkmstd::make_index_sequence<NUM_COMPONENTS>());
}
template <typename SPT = SourcePortalType,
@ -78,7 +78,7 @@ public:
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex, const ValueType& value) const
{
this->Set(valueIndex, value, tao::seq::make_index_sequence<NUM_COMPONENTS>());
this->Set(valueIndex, value, vtkmstd::make_index_sequence<NUM_COMPONENTS>());
}
private:
@ -89,7 +89,7 @@ private:
}
template <std::size_t... I>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, tao::seq::index_sequence<I...>) const
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, vtkmstd::index_sequence<I...>) const
{
return ValueType{ this->GetComponent<I>(valueIndex)... };
}
@ -105,7 +105,7 @@ private:
template <std::size_t... I>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex,
const ValueType& value,
tao::seq::index_sequence<I...>) const
vtkmstd::index_sequence<I...>) const
{
// Is there a better way to unpack an expression and execute them with no other side effects?
(void)std::initializer_list<bool>{ this->SetComponent<I>(valueIndex, value)... };

@ -15,30 +15,7 @@
#include <vtkm/internal/ArrayPortalHelpers.h>
namespace vtkmstd
{
/// Implementation of std::void_t (C++17):
/// Allows for specialization of class templates based on members of template
/// parameters.
#if defined(VTKM_GCC) && (__GNUC__ < 5)
// Due to a defect in the wording (CWG 1558) unused parameters in alias templates
// were not guaranteed to ensure SFINAE, and therefore would consider everything
// to match the 'true' side. For VTK-m the only known compiler that implemented
// this defect is GCC < 5.
template <class... T>
struct void_pack
{
using type = void;
};
template <class... T>
using void_t = typename void_pack<T...>::type;
#else
template <typename...>
using void_t = void;
#endif
} // end namespace vtkmstd
#include <vtkmstd/void_t.h>
namespace vtkm
{

@ -501,12 +501,10 @@ public:
using ArrayHandleType = ArrayHandle<WordTypeDefault, StorageTagBasic>;
/// The BitPortal used in the control environment.
using WritePortalType = vtkm::cont::internal::ArrayPortalToken<
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>>;
using WritePortalType = detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
/// A read-only BitPortal used in the control environment.
using ReadPortalType = vtkm::cont::internal::ArrayPortalToken<
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>>;
using ReadPortalType = detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
using PortalControl VTKM_DEPRECATED(1.6, "Use BitField::WritePortalType instead.") =
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
@ -638,7 +636,7 @@ public:
VTKM_CONT WritePortalType WritePortal() const
{
auto dataPortal = this->Internals->Data.WritePortal();
return WritePortalType{ dataPortal.GetToken(), dataPortal, this->Internals->NumberOfBits };
return WritePortalType{ dataPortal, this->Internals->NumberOfBits };
}
/// \brief Get a read-only portal to the data that is usable from the control environment.
@ -647,7 +645,7 @@ public:
VTKM_CONT ReadPortalType ReadPortal() const
{
auto dataPortal = this->Internals->Data.ReadPortal();
return ReadPortalType{ dataPortal.GetToken(), dataPortal, this->Internals->NumberOfBits };
return ReadPortalType{ dataPortal, this->Internals->NumberOfBits };
}
VTKM_CONT

@ -218,7 +218,7 @@ endif()
target_link_libraries(vtkm_cont PUBLIC vtkm_compiler_flags ${backends})
target_link_libraries(vtkm_cont PUBLIC Threads::Threads)
target_link_libraries(vtkm_cont PUBLIC vtkm_taotuple vtkm_optionparser vtkm_diy vtkm_lcl)
target_link_libraries(vtkm_cont PUBLIC vtkm_optionparser vtkm_diy vtkm_lcl)
if(TARGET vtkm_loguru)
target_link_libraries(vtkm_cont PRIVATE vtkm_loguru)
endif()

@ -108,22 +108,26 @@ private:
// tests are done on the projection of the point on the cell. Extra checks
// should be added to test if the point actually falls on the cell.
template <typename CellShapeTag, typename CoordsType>
VTKM_EXEC static bool PointInsideCell(FloatVec3 point,
CellShapeTag cellShape,
CoordsType cellPoints,
const vtkm::exec::FunctorBase& worklet,
FloatVec3& parametricCoordinates)
VTKM_EXEC static vtkm::ErrorCode PointInsideCell(FloatVec3 point,
CellShapeTag cellShape,
CoordsType cellPoints,
FloatVec3& parametricCoordinates,
bool& inside)
{
auto bounds = vtkm::internal::cl_uniform_bins::ComputeCellBounds(cellPoints);
if (point[0] >= bounds.Min[0] && point[0] <= bounds.Max[0] && point[1] >= bounds.Min[1] &&
point[1] <= bounds.Max[1] && point[2] >= bounds.Min[2] && point[2] <= bounds.Max[2])
{
bool success = false;
parametricCoordinates = vtkm::exec::WorldCoordinatesToParametricCoordinates(
cellPoints, point, cellShape, success, worklet);
return success && vtkm::exec::CellInside(parametricCoordinates, cellShape);
VTKM_RETURN_ON_ERROR(vtkm::exec::WorldCoordinatesToParametricCoordinates(
cellPoints, point, cellShape, parametricCoordinates));
inside = vtkm::exec::CellInside(parametricCoordinates, cellShape);
}
return false;
else
{
inside = false;
}
// Return success error code even point is not inside this cell
return vtkm::ErrorCode::Success;
}
public:
@ -157,10 +161,9 @@ public:
}
VTKM_EXEC
void FindCell(const FloatVec3& point,
vtkm::Id& cellId,
FloatVec3& parametric,
const vtkm::exec::FunctorBase& worklet) const override
vtkm::ErrorCode FindCell(const FloatVec3& point,
vtkm::Id& cellId,
FloatVec3& parametric) const override
{
using namespace vtkm::internal::cl_uniform_bins;
@ -176,7 +179,7 @@ public:
auto ldim = this->LeafDimensions.Get(binId);
if (!ldim[0] || !ldim[1] || !ldim[2])
{
return;
return vtkm::ErrorCode::CellNotFound;
}
auto leafGrid = ComputeLeafGrid(binId3, ldim, this->TopLevel);
@ -196,14 +199,19 @@ public:
auto indices = this->CellSet.GetIndices(cid);
auto pts = vtkm::make_VecFromPortalPermute(&indices, this->Coords);
FloatVec3 pc;
if (PointInsideCell(point, this->CellSet.GetCellShape(cid), pts, worklet, pc))
bool inside;
VTKM_RETURN_ON_ERROR(
PointInsideCell(point, this->CellSet.GetCellShape(cid), pts, pc, inside));
if (inside)
{
cellId = cid;
parametric = pc;
break;
return vtkm::ErrorCode::Success;
}
}
}
return vtkm::ErrorCode::CellNotFound;
}
private:

@ -69,7 +69,7 @@ struct Invoker
typename std::enable_if<detail::scatter_or_mask<T>::value, int>::type* = nullptr>
inline void operator()(Worklet&& worklet, T&& scatterOrMask, Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet, scatterOrMask);
@ -94,7 +94,7 @@ struct Invoker
U&& scatterOrMaskB,
Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet, scatterOrMaskA, scatterOrMaskB);
@ -112,7 +112,7 @@ struct Invoker
typename std::enable_if<!detail::scatter_or_mask<T>::value, int>::type* = nullptr>
inline void operator()(Worklet&& worklet, T&& t, Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet);

@ -33,7 +33,6 @@ class VTKM_ALWAYS_EXPORT ArrayPortalRef : public vtkm::ArrayPortalRef<T>
public:
ArrayPortalRef() = default;
~ArrayPortalRef() = default;
ArrayPortalRef(std::shared_ptr<vtkm::ArrayPortalVirtual<T>> portal, vtkm::Id numValues) noexcept
: vtkm::ArrayPortalRef<T>(portal.get(), numValues),

@ -53,6 +53,8 @@ ArrayHandleImpl::InternalStruct::~InternalStruct()
this->ExecutionInterface->Free(execArray);
}
this->SetControlArrayValid(lock, false);
delete this->ControlArray;
delete this->ExecutionInterface;
}
@ -98,6 +100,9 @@ void ArrayHandleImpl::Allocate(LockType& lock, vtkm::Id numberOfValues, vtkm::UI
this->WaitToWrite(lock, vtkm::cont::Token{});
this->ReleaseResourcesExecutionInternal(lock);
this->Internals->GetControlArray(lock)->AllocateValues(numberOfValues, sizeOfT);
// Set to false and then to true to ensure anything pointing to an array before the allocate
// is invalidated.
this->Internals->SetControlArrayValid(lock, false);
this->Internals->SetControlArrayValid(lock, true);
}

@ -203,7 +203,7 @@ struct VTKM_CONT_EXPORT ArrayHandleImpl
class VTKM_CONT_EXPORT InternalStruct
{
mutable bool ControlArrayValid;
mutable std::shared_ptr<bool> ControlArrayValid;
StorageBasicBase* ControlArray;
mutable ExecutionArrayInterfaceBasicBase* ExecutionInterface = nullptr;
@ -226,7 +226,7 @@ struct VTKM_CONT_EXPORT ArrayHandleImpl
template <typename T>
VTKM_CONT explicit InternalStruct(T)
: ControlArrayValid(false)
: ControlArrayValid(new bool(false))
, ControlArray(new vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>())
{
}
@ -234,7 +234,7 @@ struct VTKM_CONT_EXPORT ArrayHandleImpl
template <typename T>
VTKM_CONT explicit InternalStruct(
const vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>& storage)
: ControlArrayValid(true)
: ControlArrayValid(new bool(true))
, ControlArray(new vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>(storage))
{
}
@ -242,7 +242,7 @@ struct VTKM_CONT_EXPORT ArrayHandleImpl
VTKM_CONT
template <typename T>
explicit InternalStruct(vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>&& storage)
: ControlArrayValid(true)
: ControlArrayValid(new bool(true))
, ControlArray(
new vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>(std::move(storage)))
{
@ -255,12 +255,25 @@ struct VTKM_CONT_EXPORT ArrayHandleImpl
VTKM_CONT bool IsControlArrayValid(const LockType& lock) const
{
this->CheckLock(lock);
return this->ControlArrayValid;
return *this->ControlArrayValid;
}
VTKM_CONT void SetControlArrayValid(const LockType& lock, bool value)
{
this->CheckLock(lock);
this->ControlArrayValid = value;
if (!IsControlArrayValid(lock) && value)
{
// If we are changing the valid flag from false to true, then refresh the pointer.
// There may be array portals that already have a reference to the flag. Those portals
// will stay in an invalid state whereas new portals will go to a valid state. To
// handle both conditions, drop the old reference and create a new one.
this->ControlArrayValid.reset(new bool);
}
*this->ControlArrayValid = value;
}
VTKM_CONT std::shared_ptr<bool> GetControlArrayValidPointer(const LockType& lock) const
{
this->CheckLock(lock);
return this->ControlArrayValid;
}
VTKM_CONT StorageBasicBase* GetControlArray(const LockType& lock) const
{
@ -347,9 +360,9 @@ public:
using StorageTag = ::vtkm::cont::StorageTagBasic;
using StorageType = vtkm::cont::internal::Storage<T, StorageTag>;
using ValueType = T;
using WritePortalType = vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalType>;
using WritePortalType = vtkm::cont::internal::ArrayPortalCheck<typename StorageType::PortalType>;
using ReadPortalType =
vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalConstType>;
vtkm::cont::internal::ArrayPortalCheck<typename StorageType::PortalConstType>;
using PortalControl VTKM_DEPRECATED(1.6, "Use ArrayHandle::WritePortalType instead.") =
typename StorageType::PortalType;

@ -157,8 +157,10 @@ typename ArrayHandle<T, StorageTagBasic>::ReadPortalType
ArrayHandle<T, StorageTagBasic>::ReadPortal() const
{
LockType lock = this->GetLock();
vtkm::cont::Token token;
this->Internals->WaitToRead(lock, token);
{
vtkm::cont::Token token;
this->Internals->WaitToRead(lock, token);
}
this->SyncControlArray(lock);
this->Internals->CheckControlArrayValid(lock);
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
@ -166,12 +168,8 @@ ArrayHandle<T, StorageTagBasic>::ReadPortal() const
StorageType* privStorage =
static_cast<StorageType*>(this->Internals->Internals->GetControlArray(lock));
token.Attach(this->Internals,
this->Internals->Internals->GetReadCount(lock),
lock,
&this->Internals->Internals->ConditionVariable);
return ArrayHandle<T, StorageTagBasic>::ReadPortalType(std::move(token),
privStorage->GetPortalConst());
return ArrayHandle<T, StorageTagBasic>::ReadPortalType(
this->Internals->Internals->GetControlArrayValidPointer(lock), privStorage->GetPortalConst());
}
template <typename T>
@ -179,8 +177,10 @@ typename ArrayHandle<T, StorageTagBasic>::WritePortalType
ArrayHandle<T, StorageTagBasic>::WritePortal() const
{
LockType lock = this->GetLock();
vtkm::cont::Token token;
this->Internals->WaitToWrite(lock, token);
{
vtkm::cont::Token token;
this->Internals->WaitToWrite(lock, token);
}
this->SyncControlArray(lock);
this->Internals->CheckControlArrayValid(lock);
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
@ -192,12 +192,8 @@ ArrayHandle<T, StorageTagBasic>::WritePortal() const
this->ReleaseResourcesExecutionInternal(lock);
StorageType* privStorage =
static_cast<StorageType*>(this->Internals->Internals->GetControlArray(lock));
token.Attach(this->Internals,
this->Internals->Internals->GetWriteCount(lock),
lock,
&this->Internals->Internals->ConditionVariable);
return ArrayHandle<T, StorageTagBasic>::WritePortalType(std::move(token),
privStorage->GetPortal());
return ArrayHandle<T, StorageTagBasic>::WritePortalType(
this->Internals->Internals->GetControlArrayValidPointer(lock), privStorage->GetPortal());
}
template <typename T>

@ -0,0 +1,167 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_internal_ArrayPortalCheck_h
#define vtk_m_cont_internal_ArrayPortalCheck_h
#include <vtkm/cont/ArrayPortal.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
/// \brief A wrapper around an `ArrayPortal` that checks to status from the originating array.
///
/// After you get an `ArrayPortal` from an `ArrayHandle`, there is a possibility that the
/// `ArrayHandle` could change in a way that would invalidate the `ArrayPortal` (for example
/// freeing the memory). You could lock the `ArrayHandle`, but that encourages deadlocks.
/// Instead, this `ArrayPortal` keeps a reference to a flag from the `ArrayHandle` that tells
/// whether the memory referenced by the `ArrayPortal is still valid.
///
template <typename PortalType_>
class VTKM_ALWAYS_EXPORT ArrayPortalCheck : public PortalType_
{
std::shared_ptr<bool> Valid;
using Superclass = PortalType_;
public:
template <typename... PortalArgs>
VTKM_CONT ArrayPortalCheck(const std::shared_ptr<bool>& valid, PortalArgs&&... args)
: Superclass(std::forward<PortalArgs>(args)...)
, Valid(valid)
{
}
VTKM_CONT ArrayPortalCheck()
: Valid(new bool)
{
*this->Valid = false;
}
// Even though these do not do anything the default implementation does not, they are defined so
// that the CUDA compiler does not try to compile it for devices and then fail because the
// std::shared_ptr does not work on CUDA devices.
VTKM_CONT ArrayPortalCheck(const ArrayPortalCheck& src)
: Superclass(src)
, Valid(src.Valid)
{
}
VTKM_CONT ArrayPortalCheck(ArrayPortalCheck&& rhs)
: Superclass(std::move(static_cast<Superclass&&>(rhs)))
, Valid(std::move(rhs.Valid))
{
}
VTKM_CONT ArrayPortalCheck& operator=(const ArrayPortalCheck& src)
{
this->Superclass::operator=(src);
this->Valid = src.Valid;
return *this;
}
VTKM_CONT ArrayPortalCheck& operator=(ArrayPortalCheck&& rhs)
{
this->Superclass::operator=(std::move(static_cast<Superclass&&>(rhs)));
this->Valid = std::move(rhs.Valid);
return *this;
}
VTKM_CONT ~ArrayPortalCheck() {}
// The Get and Set methods are marked for execution environment even though they won't
// work there. This is so that this class can be used in classes that work in both
// control and execution environments without having to suppress warnings in them all.
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PT = Superclass,
typename std::enable_if<vtkm::internal::PortalSupportsGets<PT>::value, int>::type = 0>
VTKM_EXEC_CONT typename Superclass::ValueType Get(vtkm::Id index) const
{
if (!(*this->Valid))
{
VTKM_LOG_F(vtkm::cont::LogLevel::Fatal,
"Attempted to read from an ArrayPortal whose data has been deleted.");
return typename Superclass::ValueType{};
}
// Technically, this is not perfectly thread safe. It is possible that the check above
// passed and then another thread has deleted the underlying array before we got here.
// However, any case in which this portal is used where such a condition can possible
// happen is a grevious error. In which case a different run is likely to give the
// correct error and the problem can be fixed.
return this->Superclass::Get(index);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PT = Superclass,
typename std::enable_if<vtkm::internal::PortalSupportsGets3D<PT>::value, int>::type = 0>
VTKM_EXEC_CONT typename Superclass::ValueType Get(vtkm::Id3 index) const
{
if (!(*this->Valid))
{
VTKM_LOG_F(vtkm::cont::LogLevel::Fatal,
"Attempted to read from an ArrayPortal whose data has been deleted.");
return typename Superclass::ValueType{};
}
// Technically, this is not perfectly thread safe. It is possible that the check above
// passed and then another thread has deleted the underlying array before we got here.
// However, any case in which this portal is used where such a condition can possible
// happen is a grevious error. In which case a different run is likely to give the
// correct error and the problem can be fixed.
return this->Superclass::Get(index);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PT = Superclass,
typename std::enable_if<vtkm::internal::PortalSupportsSets<PT>::value, int>::type = 0>
VTKM_EXEC_CONT void Set(vtkm::Id index, typename Superclass::ValueType value) const
{
if (!(*this->Valid))
{
VTKM_LOG_F(vtkm::cont::LogLevel::Fatal,
"Attempted to write to an ArrayPortal whose data has been deleted.");
return;
}
// Technically, this is not perfectly thread safe. It is possible that the check above
// passed and then another thread has deleted the underlying array before we got here.
// However, any case in which this portal is used where such a condition can possible
// happen is a grevious error. In which case a different run is likely to give the
// correct error and the problem can be fixed.
this->Superclass::Set(index, value);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PT = Superclass,
typename std::enable_if<vtkm::internal::PortalSupportsSets3D<PT>::value, int>::type = 0>
VTKM_EXEC_CONT void Set(vtkm::Id3 index, typename Superclass::ValueType value) const
{
if (!(*this->Valid))
{
VTKM_LOG_F(vtkm::cont::LogLevel::Fatal,
"Attempted to write to an ArrayPortal whose data has been deleted.");
return;
}
// Technically, this is not perfectly thread safe. It is possible that the check above
// passed and then another thread has deleted the underlying array before we got here.
// However, any case in which this portal is used where such a condition can possible
// happen is a grevious error. In which case a different run is likely to give the
// correct error and the problem can be fixed.
this->Superclass::Set(index, value);
}
VTKM_CONT std::shared_ptr<bool> GetValidPointer() const { return this->Valid; }
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_internal_ArrayPortalCheck_h

@ -1,114 +0,0 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_internal_ArrayPortalToken_h
#define vtk_m_cont_internal_ArrayPortalToken_h
#include <vtkm/cont/ArrayPortal.h>
#include <vtkm/cont/Token.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
/// \brief A wrapper around an `ArrayPortal` that also holds its state with a token.
///
/// Usually when you get an `ArrayPortal`, you have to associate it with a `Token`
/// object to define its scope. This class wraps around an `ArrayPortal` and also
/// holds its own `Token` that should be attached appropriately to the source
/// `ArrayHandle`. When this class goes out of scope, so will its `Token`.
///
/// Because `Token`s only work in the control environment, so it is for this class.
///
template <typename PortalType_>
class VTKM_ALWAYS_EXPORT ArrayPortalToken : public PortalType_
{
std::shared_ptr<vtkm::cont::Token> Token;
using Superclass = PortalType_;
public:
template <typename... PortalArgs>
VTKM_CONT ArrayPortalToken(vtkm::cont::Token&& token, PortalArgs&&... args)
: Superclass(std::forward<PortalArgs>(args)...)
, Token(new vtkm::cont::Token(std::move(token)))
{
}
template <typename... PortalArgs>
VTKM_CONT ArrayPortalToken(std::shared_ptr<vtkm::cont::Token> token, PortalArgs&&... args)
: Superclass(std::forward<PortalArgs>(args)...)
, Token(token)
{
}
template <typename... PortalArgs>
VTKM_CONT ArrayPortalToken(PortalArgs&&... args)
: Superclass(std::forward<PortalArgs>(args)...)
, Token(new vtkm::cont::Token)
{
}
// Even though these do not do anything the default implementation does not, they are defined so
// that the CUDA compiler does not try to compile it for devices and then fail because the
// std::shared_ptr does not work on CUDA devices.
VTKM_CONT ArrayPortalToken(const ArrayPortalToken& src)
: Superclass(src)
, Token(src.Token)
{
}
VTKM_CONT ArrayPortalToken(ArrayPortalToken&& rhs)
: Superclass(std::move(static_cast<Superclass&&>(rhs)))
, Token(std::move(rhs.Token))
{
}
VTKM_CONT ArrayPortalToken& operator=(const ArrayPortalToken& src)
{
this->Superclass::operator=(src);
this->Token = src.Token;
return *this;
}
VTKM_CONT ArrayPortalToken& operator=(ArrayPortalToken&& rhs)
{
this->Superclass::operator=(std::move(static_cast<Superclass&&>(rhs)));
this->Token = std::move(rhs.Token);
return *this;
}
VTKM_CONT ~ArrayPortalToken() {}
/// \brief Detach this portal from the `ArrayHandle`.
///
/// This will open up the `ArrayHandle` for reading and/or writing.
///
VTKM_CONT void Detach()
{
this->Token->DetachFromAll();
// Reset this portal in case the superclass is holding other array portals with their own
// tokens. Detach is supposed to invalidate the array portal, so it is OK to do this.
*this = ArrayPortalToken<PortalType_>();
}
/// \brief Get the `Token` of the `ArrayPortal`.
///
/// You can keep a copy of this shared pointer to keep the scope around longer than this
/// object exists (unless, of course, the `Token` is explicitly detached).
///
VTKM_CONT std::shared_ptr<vtkm::cont::Token> GetToken() const { return this->Token; }
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_internal_ArrayPortalToken_h

@ -15,8 +15,8 @@ set(headers
ArrayHandleExecutionManager.h
ArrayManagerExecution.h
ArrayManagerExecutionShareWithControl.h
ArrayPortalCheck.h
ArrayPortalFromIterators.h
ArrayPortalToken.h
ArrayTransfer.h
AtomicInterfaceControl.h
AtomicInterfaceExecution.h

@ -104,7 +104,13 @@ public:
bool& match) const
{
vtkm::Id calculated = CalculateCellId(pointIn);
locator->FindCell(pointIn, cellId, parametric, (*this));
vtkm::ErrorCode status = locator->FindCell(pointIn, cellId, parametric);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
match = false;
return;
}
match = (calculated == cellId);
}

@ -60,7 +60,11 @@ public:
const PointType& pc,
PointType& wc) const
{
wc = vtkm::exec::ParametricCoordinatesToWorldCoordinates(points, pc, cellShape, *this);
auto status = vtkm::exec::ParametricCoordinatesToWorldCoordinates(points, pc, cellShape, wc);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
}
}
};
@ -166,7 +170,11 @@ public:
vtkm::Id& cellId,
vtkm::Vec3f& pcoords) const
{
locator->FindCell(point, cellId, pcoords, *this);
vtkm::ErrorCode status = locator->FindCell(point, cellId, pcoords);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
}
}
};

@ -69,7 +69,13 @@ public:
bool& match) const
{
vtkm::Id calculated = CalculateCellId(pointIn);
locator->FindCell(pointIn, cellId, parametric, (*this));
vtkm::ErrorCode status = locator->FindCell(pointIn, cellId, parametric);
if ((status != vtkm::ErrorCode::Success) && (status != vtkm::ErrorCode::CellNotFound))
{
this->RaiseError(vtkm::ErrorString(status));
match = false;
return;
}
match = (calculated == cellId);
}

@ -2704,7 +2704,6 @@ private:
portal.SetWord(2, 0x00100000ul);
portal.SetWord(8, 0x00100010ul);
portal.SetWord(11, 0x10000000ul);
portal.Detach();
testIndexArray(bits);
}
}
@ -2795,7 +2794,6 @@ private:
portal.SetWord(2, 0x00100000ul);
portal.SetWord(8, 0x00100010ul);
portal.SetWord(11, 0x10000000ul);
portal.Detach();
verifyPopCount(bits);
}
}

@ -79,7 +79,9 @@ struct TemplatedTests
using ArrayHandleType2 = vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagCounting>;
using PortalType = typename ArrayHandleType::ReadPortalType;
using PortalType =
typename vtkm::cont::internal::Storage<ValueType,
typename ArrayHandleType::StorageTag>::PortalConstType;
void operator()(const ValueType& startingValue, const ValueType& step)
{

@ -180,12 +180,46 @@ void ThreadsDecrementArray(vtkm::cont::ArrayHandle<ValueType, Storage> array)
CheckPortal(array.ReadPortal());
}
template <typename Storage>
void InvalidateControlPortal(vtkm::cont::ArrayHandle<ValueType, Storage> array)
{
std::cout << " Starting invalidate control portal" << std::endl;
auto writePortal = array.WritePortal();
{
// PrepareForInPlace should invalidate the local control portal. It should work, but
// further use of writePortal will be invalid.
vtkm::cont::Token token;
array.PrepareForInPlace(vtkm::cont::DeviceAdapterTagSerial{}, token);
#if 0
std::cout << " This should result in an error in the log and possibly a crash." << std::endl;
// Unfortunately, there is no way to check this other than visual inspection or outright crash
writePortal.Get(0);
#endif
}
auto readPortal = array.ReadPortal();
{
vtkm::cont::Token token;
array.PrepareForInPlace(vtkm::cont::DeviceAdapterTagSerial{}, token);
#if 0
std::cout << " This should result in an error in the log and possibly a crash." << std::endl;
// Unfortunately, there is no way to check this other than visual inspection or outright crash
readPortal.Get(0);
#endif
}
}
template <typename Storage>
void DoThreadSafetyTest(vtkm::cont::ArrayHandle<ValueType, Storage> array)
{
ThreadsIncrementToArray(array);
ThreadsCheckArray(array);
ThreadsDecrementArray(array);
InvalidateControlPortal(array);
}
void DoTest()

@ -32,7 +32,7 @@ void TestArrayHandleUniformPointCoordinates()
"Array computed wrong number of points.");
std::cout << "Getting array portal." << std::endl;
vtkm::internal::ArrayPortalUniformPointCoordinates portal = arrayHandle.ReadPortal();
auto portal = arrayHandle.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == NUM_POINTS, "Portal has wrong number of points.");
VTKM_TEST_ASSERT(portal.GetRange3() == DIMENSIONS, "Portal range is wrong.");

@ -217,15 +217,6 @@ struct Test
// the concreteArray getting locked up.
CheckPortal(virtualArray.ReadPortal());
SetPortal(concreteArray.WritePortal());
// Make sure Detach also correctly unlocks the concrete array.
auto readPortal = virtualArray.ReadPortal();
readPortal.Detach();
concreteArray.WritePortal();
auto writePortal = virtualArray.WritePortal();
writePortal.Detach();
concreteArray.WritePortal();
}
void operator()()

@ -105,7 +105,11 @@ public:
const PointType& pc,
PointType& wc) const
{
wc = vtkm::exec::CellInterpolate(points, pc, cellShape, *this);
auto status = vtkm::exec::CellInterpolate(points, pc, cellShape, wc);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
}
}
};
@ -155,7 +159,11 @@ public:
vtkm::Id& cellId,
vtkm::Vec3f& pcoords) const
{
locator->FindCell(point, cellId, pcoords, *this);
vtkm::ErrorCode status = locator->FindCell(point, cellId, pcoords);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
}
}
};

@ -12,6 +12,8 @@
#include <vtkm/Assert.h>
#include <vtkm/CellShape.h>
#include <vtkm/Deprecated.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/VecAxisAlignedPointCoordinates.h>
#include <vtkm/VecTraits.h>
@ -25,71 +27,39 @@ namespace vtkm
namespace exec
{
//-----------------------------------------------------------------------------
/// \brief Take the derivative (get the gradient) of a point field in a cell.
///
/// Given the point field values for each node and the parametric coordinates
/// of a point within the cell, finds the derivative with respect to each
/// coordinate (i.e. the gradient) at that point. The derivative is not always
/// constant in some "linear" cells.
///
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& pointFieldValues,
const WorldCoordType& worldCoordinateValues,
const vtkm::Vec<ParametricCoordType, 3>& parametricCoords,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::Vec<typename FieldVecType::ComponentType, 3> result;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
result = CellDerivative(
pointFieldValues, worldCoordinateValues, parametricCoords, CellShapeTag(), worklet));
default:
worklet.RaiseError("Unknown cell shape sent to derivative.");
return vtkm::Vec<typename FieldVecType::ComponentType, 3>();
}
return result;
}
//-----------------------------------------------------------------------------
namespace internal
{
template <typename VtkcCellShapeTag,
template <typename LclCellShapeTag,
typename FieldVecType,
typename WorldCoordType,
typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivativeImpl(
VtkcCellShapeTag tag,
VTKM_EXEC vtkm::ErrorCode CellDerivativeImpl(
LclCellShapeTag tag,
const FieldVecType& field,
const WorldCoordType& wCoords,
const ParametricCoordType& pcoords,
const vtkm::exec::FunctorBase& worklet)
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
VTKM_ASSERT(field.GetNumberOfComponents() == tag.numberOfPoints());
VTKM_ASSERT(wCoords.GetNumberOfComponents() == tag.numberOfPoints());
result = { 0 };
if ((field.GetNumberOfComponents() != tag.numberOfPoints()) ||
(wCoords.GetNumberOfComponents() != tag.numberOfPoints()))
{
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
using FieldType = typename FieldVecType::ComponentType;
auto fieldNumComponents = vtkm::VecTraits<FieldType>::GetNumberOfComponents(field[0]);
vtkm::Vec<FieldType, 3> derivs;
auto status = lcl::derivative(tag,
lcl::makeFieldAccessorNestedSOA(wCoords, 3),
lcl::makeFieldAccessorNestedSOA(field, fieldNumComponents),
pcoords,
derivs[0],
derivs[1],
derivs[2]);
if (status != lcl::ErrorCode::SUCCESS)
{
worklet.RaiseError(lcl::errorString(status));
derivs = vtkm::TypeTraits<vtkm::Vec<FieldType, 3>>::ZeroInitialization();
}
return derivs;
result[0],
result[1],
result[2]);
return vtkm::internal::LclErrorToVtkmError(status);
}
} // namespace internal
@ -98,47 +68,47 @@ template <typename FieldVecType,
typename WorldCoordType,
typename ParametricCoordType,
typename CellShapeTag>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag shape,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
return internal::CellDerivativeImpl(
vtkm::internal::make_VtkcCellShapeTag(shape), field, wCoords, pcoords, worklet);
vtkm::internal::make_LclCellShapeTag(shape), field, wCoords, pcoords, result);
}
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType&,
const WorldCoordType&,
const vtkm::Vec<ParametricCoordType, 3>&,
vtkm::CellShapeTagEmpty,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType&,
const WorldCoordType&,
const vtkm::Vec<ParametricCoordType, 3>&,
vtkm::CellShapeTagEmpty,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
worklet.RaiseError("Attempted to take derivative in empty cell.");
return vtkm::Vec<typename FieldVecType::ComponentType, 3>();
result = { 0 };
return vtkm::ErrorCode::OperationOnEmptyCell;
}
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
vtkm::IdComponent numPoints = field.GetNumberOfComponents();
VTKM_ASSERT(numPoints >= 1);
VTKM_ASSERT(numPoints == wCoords.GetNumberOfComponents());
if (numPoints != wCoords.GetNumberOfComponents())
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
switch (numPoints)
{
case 1:
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagVertex(), worklet);
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagVertex(), result);
case 2:
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagLine(), worklet);
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagLine(), result);
}
auto dt = static_cast<ParametricCoordType>(1) / static_cast<ParametricCoordType>(numPoints - 1);
@ -155,56 +125,105 @@ VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
auto lineField = vtkm::make_Vec(field[idx - 1], field[idx]);
auto lineWCoords = vtkm::make_Vec(wCoords[idx - 1], wCoords[idx]);
auto pc = (pcoords[0] - static_cast<ParametricCoordType>(idx) * dt) / dt;
return internal::CellDerivativeImpl(lcl::Line{}, lineField, lineWCoords, &pc, worklet);
return internal::CellDerivativeImpl(lcl::Line{}, lineField, lineWCoords, &pc, result);
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
VTKM_ASSERT(field.GetNumberOfComponents() == wCoords.GetNumberOfComponents());
const vtkm::IdComponent numPoints = field.GetNumberOfComponents();
VTKM_ASSERT(numPoints > 0);
if ((numPoints <= 0) || (numPoints != wCoords.GetNumberOfComponents()))
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
switch (field.GetNumberOfComponents())
{
case 1:
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagVertex(), worklet);
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagVertex(), result);
case 2:
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagLine(), worklet);
return CellDerivative(field, wCoords, pcoords, vtkm::CellShapeTagLine(), result);
default:
return internal::CellDerivativeImpl(
lcl::Polygon(numPoints), field, wCoords, pcoords, worklet);
return internal::CellDerivativeImpl(lcl::Polygon(numPoints), field, wCoords, pcoords, result);
}
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& field,
const vtkm::VecAxisAlignedPointCoordinates<2>& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
const vtkm::VecAxisAlignedPointCoordinates<2>& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
return internal::CellDerivativeImpl(lcl::Pixel{}, field, wCoords, pcoords, worklet);
return internal::CellDerivativeImpl(lcl::Pixel{}, field, wCoords, pcoords, result);
}
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
const vtkm::VecAxisAlignedPointCoordinates<3>& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
return internal::CellDerivativeImpl(lcl::Voxel{}, field, wCoords, pcoords, result);
}
//-----------------------------------------------------------------------------
/// \brief Take the derivative (get the gradient) of a point field in a cell.
///
/// Given the point field values for each node and the parametric coordinates
/// of a point within the cell, finds the derivative with respect to each
/// coordinate (i.e. the gradient) at that point. The derivative is not always
/// constant in some "linear" cells.
///
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& pointFieldValues,
const WorldCoordType& worldCoordinateValues,
const vtkm::Vec<ParametricCoordType, 3>& parametricCoords,
vtkm::CellShapeTagGeneric shape,
vtkm::Vec<typename FieldVecType::ComponentType, 3>& result)
{
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
status = CellDerivative(
pointFieldValues, worldCoordinateValues, parametricCoords, CellShapeTag(), result));
default:
result = { 0 };
status = vtkm::ErrorCode::InvalidShapeId;
}
return status;
}
template <typename FieldVecType,
typename WorldCoordType,
typename ParametricCoordType,
typename CellShapeTag>
VTKM_DEPRECATED(
1.6,
"Call signature has changed to CellDerivative(field, wCoords, pcoords, shape, result).")
VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
const FieldVecType& field,
const vtkm::VecAxisAlignedPointCoordinates<3>& wCoords,
const WorldCoordType& wCoords,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
return internal::CellDerivativeImpl(lcl::Voxel{}, field, wCoords, pcoords, worklet);
vtkm::Vec<typename FieldVecType::ComponentType, 3> result;
vtkm::ErrorCode status = CellDerivative(field, wCoords, pcoords, shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
}
} // namespace vtkm::exec

@ -13,6 +13,8 @@
#include <vtkm/Assert.h>
#include <vtkm/CellShape.h>
#include <vtkm/CellTraits.h>
#include <vtkm/Deprecated.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/Types.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/internal/Assume.h>
@ -116,123 +118,199 @@ public:
} // namespace detail
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::IdComponent CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
CellShapeTag,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
CellShapeTag,
vtkm::IdComponent& numEdges)
{
(void)numPoints; // Silence compiler warnings.
VTKM_ASSERT(numPoints == vtkm::CellTraits<CellShapeTag>::NUM_POINTS);
return detail::CellEdgeTables{}.NumEdges(CellShapeTag::Id);
if (numPoints != vtkm::CellTraits<CellShapeTag>::NUM_POINTS)
{
numEdges = -1;
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
numEdges = detail::CellEdgeTables{}.NumEdges(CellShapeTag::Id);
return vtkm::ErrorCode::Success;
}
static inline VTKM_EXEC vtkm::IdComponent CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolygon,
vtkm::IdComponent& numEdges)
{
VTKM_ASSUME(numPoints > 0);
return numPoints;
if (numPoints <= 0)
{
numEdges = -1;
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
numEdges = numPoints;
return vtkm::ErrorCode::Success;
}
static inline VTKM_EXEC vtkm::IdComponent CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolyLine,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolyLine,
vtkm::IdComponent& numEdges)
{
(void)numPoints; // Silence compiler warnings.
VTKM_ASSUME(numPoints > 0);
return detail::CellEdgeTables{}.NumEdges(vtkm::CELL_SHAPE_POLY_LINE);
if (numPoints <= 0)
{
numEdges = -1;
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
numEdges = detail::CellEdgeTables{}.NumEdges(vtkm::CELL_SHAPE_POLY_LINE);
return vtkm::ErrorCode::Success;
}
static inline VTKM_EXEC vtkm::IdComponent CellEdgeNumberOfEdges(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagGeneric shape,
vtkm::IdComponent& numEdges)
{
if (shape.Id == vtkm::CELL_SHAPE_POLYGON)
{
return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolygon(), worklet);
return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolygon(), numEdges);
}
else if (shape.Id == vtkm::CELL_SHAPE_POLY_LINE)
{
return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolyLine(), worklet);
return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolyLine(), numEdges);
}
else
{
return detail::CellEdgeTables{}.NumEdges(shape.Id);
numEdges = detail::CellEdgeTables{}.NumEdges(shape.Id);
return vtkm::ErrorCode::Success;
}
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
VTKM_DEPRECATED(1.6, "Signature changed to CellEdgeNumberOfEdges(numPoints, shape, result).")
static inline VTKM_EXEC vtkm::IdComponent
CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES);
if (edgeIndex >= vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, worklet))
vtkm::IdComponent numEdges;
vtkm::ErrorCode status = CellEdgeNumberOfEdges(numPoints, shape, numEdges);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError("Invalid edge number.");
return 0;
worklet.RaiseError(vtkm::ErrorString(status));
}
return numEdges;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
CellShapeTag shape,
vtkm::IdComponent& result)
{
if ((pointIndex < 0) || (pointIndex > 1))
{
result = -1;
return vtkm::ErrorCode::InvalidPointId;
}
if ((edgeIndex < 0) || (edgeIndex >= detail::CellEdgeTables::MAX_NUM_EDGES))
{
result = -1;
return vtkm::ErrorCode::InvalidEdgeId;
}
vtkm::IdComponent numEdges;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges));
if (edgeIndex >= numEdges)
{
result = -1;
return vtkm::ErrorCode::InvalidEdgeId;
}
detail::CellEdgeTables table;
return table.PointsInEdge(CellShapeTag::Id, edgeIndex, pointIndex);
result = table.PointsInEdge(CellShapeTag::Id, edgeIndex, pointIndex);
return vtkm::ErrorCode::Success;
}
static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagPolygon,
vtkm::IdComponent& result)
{
VTKM_ASSUME(numPoints >= 3);
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < numPoints);
if (numPoints < 3)
{
result = -1;
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
if ((pointIndex < 0) || (pointIndex > 1))
{
result = -1;
return vtkm::ErrorCode::InvalidPointId;
}
if ((edgeIndex < 0) || (edgeIndex >= numPoints))
{
result = -1;
return vtkm::ErrorCode::InvalidEdgeId;
}
if (edgeIndex + pointIndex < numPoints)
{
return edgeIndex + pointIndex;
result = edgeIndex + pointIndex;
}
else
{
return 0;
result = 0;
}
return vtkm::ErrorCode::Success;
}
static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagGeneric shape,
vtkm::IdComponent& result)
{
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES);
if ((pointIndex < 0) || (pointIndex > 1))
{
result = -1;
return vtkm::ErrorCode::InvalidPointId;
}
if ((edgeIndex < 0) || (edgeIndex >= detail::CellEdgeTables::MAX_NUM_EDGES))
{
result = -1;
return vtkm::ErrorCode::InvalidEdgeId;
}
if (shape.Id == vtkm::CELL_SHAPE_POLYGON)
{
return CellEdgeLocalIndex(
numPoints, pointIndex, edgeIndex, vtkm::CellShapeTagPolygon(), worklet);
numPoints, pointIndex, edgeIndex, vtkm::CellShapeTagPolygon(), result);
}
else
{
detail::CellEdgeTables table;
if (edgeIndex >= table.NumEdges(shape.Id))
{
worklet.RaiseError("Invalid edge number.");
return 0;
result = -1;
return vtkm::ErrorCode::InvalidEdgeId;
}
return table.PointsInEdge(shape.Id, edgeIndex, pointIndex);
result = table.PointsInEdge(shape.Id, edgeIndex, pointIndex);
return vtkm::ErrorCode::Success;
}
}
template <typename CellShapeTag>
VTKM_DEPRECATED(
1.6,
"Signature changed to CellEdgeLocalIndex(numPoints, pointIndex, edgeIndex, shape, result).")
static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::IdComponent result;
vtkm::ErrorCode status = CellEdgeLocalIndex(numPoints, pointIndex, edgeIndex, shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
/// \brief Returns a canonical identifier for a cell edge
///
/// Given information about a cell edge and the global point indices for that cell, returns a
@ -240,25 +318,54 @@ static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent n
/// the same if and only if the edges contain the same points.
///
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline VTKM_EXEC vtkm::Id2 CellEdgeCanonicalId(
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeCanonicalId(
vtkm::IdComponent numPoints,
vtkm::IdComponent edgeIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet)
vtkm::Id2& result)
{
vtkm::Id pointIndex0 =
globalPointIndicesVec[vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, worklet)];
vtkm::Id pointIndex1 =
globalPointIndicesVec[vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, worklet)];
result = { -1, -1 };
vtkm::IdComponent localIndex0;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, localIndex0));
vtkm::Id pointIndex0 = globalPointIndicesVec[localIndex0];
vtkm::IdComponent localIndex1;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, localIndex1));
vtkm::Id pointIndex1 = globalPointIndicesVec[localIndex1];
if (pointIndex0 < pointIndex1)
{
return vtkm::Id2(pointIndex0, pointIndex1);
result = vtkm::Id2(pointIndex0, pointIndex1);
}
else
{
return vtkm::Id2(pointIndex1, pointIndex0);
result = vtkm::Id2(pointIndex1, pointIndex0);
}
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
VTKM_DEPRECATED(
1.6,
"Signature changed to CellEdgeCononicalId(numPoints, edgeIndex, shape, globalIds, result).")
static inline VTKM_EXEC vtkm::Id2
CellEdgeCanonicalId(vtkm::IdComponent numPoints,
vtkm::IdComponent edgeIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::Id2 result;
vtkm::ErrorCode status =
CellEdgeCanonicalId(numPoints, edgeIndex, shape, globalPointIndicesVec, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
}
} // namespace vtkm::exec

@ -12,6 +12,8 @@
#include <vtkm/Assert.h>
#include <vtkm/CellShape.h>
#include <vtkm/Deprecated.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/Types.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/internal/Assume.h>
@ -140,65 +142,148 @@ public:
} // namespace detail
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::IdComponent CellFaceNumberOfFaces(CellShapeTag shape,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfFaces(CellShapeTag shape,
vtkm::IdComponent& result)
{
(void)shape; //C4100 false positive workaround
detail::CellFaceTables table;
return table.NumFaces(shape.Id);
result = table.NumFaces(shape.Id);
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::IdComponent CellFaceNumberOfPoints(
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
VTKM_DEPRECATED(1.6, "Signature changed to CellFaceNumberOfFaces(shape, result).")
static inline VTKM_EXEC vtkm::IdComponent
CellFaceNumberOfFaces(CellShapeTag shape, const vtkm::exec::FunctorBase& worklet)
{
VTKM_ASSUME(faceIndex >= 0);
VTKM_ASSUME(faceIndex < detail::CellFaceTables::MAX_NUM_FACES);
if (faceIndex >= vtkm::exec::CellFaceNumberOfFaces(shape, worklet))
vtkm::IdComponent result;
vtkm::ErrorCode status = CellFaceNumberOfFaces(shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError("Invalid face number.");
return 0;
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfPoints(vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::IdComponent& result)
{
if ((faceIndex < 0) || (faceIndex >= detail::CellFaceTables::MAX_NUM_FACES))
{
result = -1;
return vtkm::ErrorCode::InvalidFaceId;
}
vtkm::IdComponent numFaces;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfFaces(shape, numFaces));
if (faceIndex >= numFaces)
{
result = -1;
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
return table.NumPointsInFace(shape.Id, faceIndex);
result = table.NumPointsInFace(shape.Id, faceIndex);
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
VTKM_DEPRECATED(1.6, "Signature changed to CellFaceNumberOfPoints(faceIndex, shape, result).")
static inline VTKM_EXEC vtkm::IdComponent
CellFaceNumberOfPoints(vtkm::IdComponent faceIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::IdComponent result;
vtkm::ErrorCode status = CellFaceNumberOfPoints(faceIndex, shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceShape(vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::UInt8& result)
{
if ((faceIndex < 0) || (faceIndex >= detail::CellFaceTables::MAX_NUM_FACES))
{
result = vtkm::CELL_SHAPE_EMPTY;
return vtkm::ErrorCode::InvalidFaceId;
}
vtkm::IdComponent numFacePoints;
VTKM_RETURN_ON_ERROR(CellFaceNumberOfPoints(faceIndex, shape, numFacePoints));
switch (numFacePoints)
{
case 3:
result = vtkm::CELL_SHAPE_TRIANGLE;
break;
case 4:
result = vtkm::CELL_SHAPE_QUAD;
break;
default:
result = vtkm::CELL_SHAPE_POLYGON;
break;
}
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
VTKM_DEPRECATED(1.6, "Signature changed to CellFaceShape(faceIndex, shape, result).")
static inline VTKM_EXEC vtkm::UInt8 CellFaceShape(vtkm::IdComponent faceIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
VTKM_ASSUME(faceIndex >= 0);
VTKM_ASSUME(faceIndex < detail::CellFaceTables::MAX_NUM_FACES);
switch (CellFaceNumberOfPoints(faceIndex, shape, worklet))
vtkm::UInt8 result;
vtkm::ErrorCode status = CellFaceShape(faceIndex, shape, result);
if (status != vtkm::ErrorCode::Success)
{
case 3:
return vtkm::CELL_SHAPE_TRIANGLE;
case 4:
return vtkm::CELL_SHAPE_QUAD;
default:
return vtkm::CELL_SHAPE_POLYGON;
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceLocalIndex(vtkm::IdComponent pointIndex,
vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::IdComponent& result)
{
vtkm::IdComponent numPointsInFace;
result = -1;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, numPointsInFace));
if (numPointsInFace < 1)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
result = table.PointsInFace(shape.Id, faceIndex, pointIndex);
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
VTKM_DEPRECATED(1.6,
"Signature changed to CellFaceLocalIndex(pointIndex, faceIndex, shape, result).")
static inline VTKM_EXEC vtkm::IdComponent CellFaceLocalIndex(vtkm::IdComponent pointIndex,
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::IdComponent numPointsInFace = vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, worklet);
if (numPointsInFace < 1)
vtkm::IdComponent result;
vtkm::ErrorCode status = CellFaceLocalIndex(pointIndex, faceIndex, shape, result);
if (status != vtkm::ErrorCode::Success)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return -1;
worklet.RaiseError(vtkm::ErrorString(status));
}
detail::CellFaceTables table;
return table.PointsInFace(shape.Id, faceIndex, pointIndex);
return result;
}
/// \brief Returns a canonical identifier for a cell face
@ -212,68 +297,69 @@ static inline VTKM_EXEC vtkm::IdComponent CellFaceLocalIndex(vtkm::IdComponent p
/// than a single point or single edge.
///
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline VTKM_EXEC vtkm::Id3 CellFaceCanonicalId(
static inline VTKM_EXEC vtkm::ErrorCode CellFaceCanonicalId(
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet)
vtkm::Id3& result)
{
const vtkm::IdComponent numPointsInFace =
vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, worklet);
vtkm::IdComponent numPointsInFace;
result = { -1 };
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, numPointsInFace));
if (numPointsInFace == 0)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return vtkm::Id3(0);
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
//Sort the first 3 face points/nodes in ascending order
vtkm::Id3 sorted(globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 0)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 1)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 2)]);
result = vtkm::Id3(globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 0)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 1)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 2)]);
vtkm::Id temp;
if (sorted[0] > sorted[2])
if (result[0] > result[2])
{
temp = sorted[0];
sorted[0] = sorted[2];
sorted[2] = temp;
temp = result[0];
result[0] = result[2];
result[2] = temp;
}
if (sorted[0] > sorted[1])
if (result[0] > result[1])
{
temp = sorted[0];
sorted[0] = sorted[1];
sorted[1] = temp;
temp = result[0];
result[0] = result[1];
result[1] = temp;
}
if (sorted[1] > sorted[2])
if (result[1] > result[2])
{
temp = sorted[1];
sorted[1] = sorted[2];
sorted[2] = temp;
temp = result[1];
result[1] = result[2];
result[2] = temp;
}
// Check the rest of the points to see if they are in the lowest 3
for (vtkm::IdComponent pointIndex = 3; pointIndex < numPointsInFace; pointIndex++)
{
vtkm::Id nextPoint = globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, pointIndex)];
if (nextPoint < sorted[2])
if (nextPoint < result[2])
{
if (nextPoint < sorted[1])
if (nextPoint < result[1])
{
sorted[2] = sorted[1];
if (nextPoint < sorted[0])
result[2] = result[1];
if (nextPoint < result[0])
{
sorted[1] = sorted[0];
sorted[0] = nextPoint;
result[1] = result[0];
result[0] = nextPoint;
}
else // nextPoint > P0, nextPoint < P1
{
sorted[1] = nextPoint;
result[1] = nextPoint;
}
}
else // nextPoint > P1, nextPoint < P2
{
sorted[2] = nextPoint;
result[2] = nextPoint;
}
}
else // nextPoint > P2
@ -282,7 +368,25 @@ static inline VTKM_EXEC vtkm::Id3 CellFaceCanonicalId(
}
}
return sorted;
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
VTKM_DEPRECATED(1.6,
"Signature changed to CellFaceCononicalId(faceIndex, shape, globalIds, result).")
static inline VTKM_EXEC vtkm::Id3
CellFaceCanonicalId(vtkm::IdComponent faceIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::Id3 result;
vtkm::ErrorCode status = CellFaceCanonicalId(faceIndex, shape, globalPointIndicesVec, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
}
} // namespace vtkm::exec

@ -12,6 +12,8 @@
#include <vtkm/Assert.h>
#include <vtkm/CellShape.h>
#include <vtkm/Deprecated.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/VecAxisAlignedPointCoordinates.h>
#include <vtkm/exec/FunctorBase.h>
@ -31,92 +33,65 @@ namespace internal
{
template <typename VtkcCellShapeTag, typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolateImpl(
VtkcCellShapeTag tag,
const FieldVecType& field,
const ParametricCoordType& pcoords,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolateImpl(VtkcCellShapeTag tag,
const FieldVecType& field,
const ParametricCoordType& pcoords,
typename FieldVecType::ComponentType& result)
{
VTKM_ASSERT(tag.numberOfPoints() == field.GetNumberOfComponents());
if (tag.numberOfPoints() != field.GetNumberOfComponents())
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
using FieldValueType = typename FieldVecType::ComponentType;
IdComponent numComponents = vtkm::VecTraits<FieldValueType>::GetNumberOfComponents(field[0]);
FieldValueType result(0);
auto status =
lcl::interpolate(tag, lcl::makeFieldAccessorNestedSOA(field, numComponents), pcoords, result);
if (status != lcl::ErrorCode::SUCCESS)
{
worklet.RaiseError(lcl::errorString(status));
}
return result;
return vtkm::internal::LclErrorToVtkmError(status);
}
} // namespace internal
//-----------------------------------------------------------------------------
/// \brief Interpolate a point field in a cell.
///
/// Given the point field values for each node and the parametric coordinates
/// of a point within the cell, interpolates the field to that point.
///
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& parametricCoords,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
{
typename FieldVecType::ComponentType result;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
result = CellInterpolate(pointFieldValues, parametricCoords, CellShapeTag(), worklet));
default:
worklet.RaiseError("Unknown cell shape sent to interpolate.");
return typename FieldVecType::ComponentType();
}
return result;
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType, typename CellShapeTag>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag tag,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag tag,
typename FieldVecType::ComponentType& result)
{
auto lclTag =
vtkm::internal::make_VtkcCellShapeTag(tag, pointFieldValues.GetNumberOfComponents());
return internal::CellInterpolateImpl(lclTag, pointFieldValues, pcoords, worklet);
auto lclTag = vtkm::internal::make_LclCellShapeTag(tag, pointFieldValues.GetNumberOfComponents());
return internal::CellInterpolateImpl(lclTag, pointFieldValues, pcoords, result);
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
const FieldVecType&,
const vtkm::Vec<ParametricCoordType, 3>&,
vtkm::CellShapeTagEmpty,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType&,
const vtkm::Vec<ParametricCoordType, 3>&,
vtkm::CellShapeTagEmpty,
typename FieldVecType::ComponentType& result)
{
worklet.RaiseError("Attempted to interpolate an empty cell.");
return typename FieldVecType::ComponentType();
result = { 0 };
return vtkm::ErrorCode::OperationOnEmptyCell;
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
const FieldVecType& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
typename FieldVecType::ComponentType& result)
{
const vtkm::IdComponent numPoints = field.GetNumberOfComponents();
VTKM_ASSERT(numPoints >= 1);
if (numPoints < 1)
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
if (numPoints == 1)
{
return CellInterpolate(field, pcoords, vtkm::CellShapeTagVertex(), worklet);
return CellInterpolate(field, pcoords, vtkm::CellShapeTagVertex(), result);
}
using T = ParametricCoordType;
@ -125,53 +100,101 @@ VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
vtkm::IdComponent idx = static_cast<vtkm::IdComponent>(pcoords[0] / dt);
if (idx == numPoints - 1)
{
return field[numPoints - 1];
result = field[numPoints - 1];
return vtkm::ErrorCode::Success;
}
T pc = (pcoords[0] - static_cast<T>(idx) * dt) / dt;
return internal::CellInterpolateImpl(
lcl::Line{}, vtkm::make_Vec(field[idx], field[idx + 1]), &pc, worklet);
lcl::Line{}, vtkm::make_Vec(field[idx], field[idx + 1]), &pc, result);
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC typename FieldVecType::ComponentType CellInterpolate(
const FieldVecType& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
typename FieldVecType::ComponentType& result)
{
const vtkm::IdComponent numPoints = field.GetNumberOfComponents();
VTKM_ASSERT(numPoints > 0);
if (numPoints < 1)
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
switch (numPoints)
{
case 1:
return CellInterpolate(field, pcoords, vtkm::CellShapeTagVertex(), worklet);
return CellInterpolate(field, pcoords, vtkm::CellShapeTagVertex(), result);
case 2:
return CellInterpolate(field, pcoords, vtkm::CellShapeTagLine(), worklet);
return CellInterpolate(field, pcoords, vtkm::CellShapeTagLine(), result);
default:
return internal::CellInterpolateImpl(lcl::Polygon(numPoints), field, pcoords, worklet);
return internal::CellInterpolateImpl(lcl::Polygon(numPoints), field, pcoords, result);
}
}
//-----------------------------------------------------------------------------
template <typename ParametricCoordType>
VTKM_EXEC vtkm::Vec3f CellInterpolate(const vtkm::VecAxisAlignedPointCoordinates<2>& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const vtkm::VecAxisAlignedPointCoordinates<2>& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
vtkm::Vec3f& result)
{
return internal::CellInterpolateImpl(lcl::Pixel{}, field, pcoords, worklet);
return internal::CellInterpolateImpl(lcl::Pixel{}, field, pcoords, result);
}
//-----------------------------------------------------------------------------
template <typename ParametricCoordType>
VTKM_EXEC vtkm::Vec3f CellInterpolate(const vtkm::VecAxisAlignedPointCoordinates<3>& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const vtkm::VecAxisAlignedPointCoordinates<3>& field,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
vtkm::Vec3f& result)
{
return internal::CellInterpolateImpl(lcl::Voxel{}, field, pcoords, worklet);
return internal::CellInterpolateImpl(lcl::Voxel{}, field, pcoords, result);
}
//-----------------------------------------------------------------------------
/// \brief Interpolate a point field in a cell.
///
/// Given the point field values for each node and the parametric coordinates
/// of a point within the cell, interpolates the field to that point.
///
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& parametricCoords,
vtkm::CellShapeTagGeneric shape,
typename FieldVecType::ComponentType& result)
{
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
status = CellInterpolate(pointFieldValues, parametricCoords, CellShapeTag(), result));
default:
result = { 0 };
status = vtkm::ErrorCode::InvalidShapeId;
}
return status;
}
//-----------------------------------------------------------------------------
template <typename FieldVecType, typename ParametricCoordType, typename CellShapeTag>
VTKM_DEPRECATED(1.6,
"Signature changed to CellInterpolate(pointFieldValues, pcoords, shape, result).")
VTKM_EXEC typename FieldVecType::ComponentType
CellInterpolate(const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
typename FieldVecType::ComponentType result;
vtkm::ErrorCode status = CellInterpolate(pointFieldValues, pcoords, shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
}
} // namespace vtkm::exec

@ -10,6 +10,8 @@
#ifndef vtk_m_exec_CellLocator_h
#define vtk_m_exec_CellLocator_h
#include <vtkm/Deprecated.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/Types.h>
#include <vtkm/VirtualObjectBase.h>
#include <vtkm/exec/FunctorBase.h>
@ -29,10 +31,23 @@ public:
}
VTKM_EXEC
virtual void FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const = 0;
virtual vtkm::ErrorCode FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric) const = 0;
VTKM_EXEC
VTKM_DEPRECATED(1.6, "FindCell no longer takes worklet argument.")
void FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const
{
vtkm::ErrorCode status = this->FindCell(point, cellId, parametric);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
}
};
} // namespace exec

@ -95,10 +95,9 @@ public:
}
VTKM_EXEC
void FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const override
vtkm::ErrorCode FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric) const override
{
cellId = -1;
vtkm::Id nodeIndex = 0;
@ -109,7 +108,7 @@ public:
switch (state)
{
case FindCellState::EnterNode:
this->EnterNode(state, point, cellId, nodeIndex, parametric, worklet);
VTKM_RETURN_ON_ERROR(this->EnterNode(state, point, cellId, nodeIndex, parametric));
break;
case FindCellState::AscendFromNode:
this->AscendFromNode(state, nodeIndex);
@ -122,6 +121,15 @@ public:
break;
}
}
if (cellId >= 0)
{
return vtkm::ErrorCode::Success;
}
else
{
return vtkm::ErrorCode::CellNotFound;
}
}
private:
@ -134,12 +142,11 @@ private:
};
VTKM_EXEC
void EnterNode(FindCellState& state,
const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Id nodeIndex,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const
vtkm::ErrorCode EnterNode(FindCellState& state,
const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Id nodeIndex,
vtkm::Vec3f& parametric) const
{
VTKM_ASSERT(state == FindCellState::EnterNode);
@ -148,13 +155,14 @@ private:
if (node.ChildIndex < 0)
{
// In a leaf node. Look for a containing cell.
cellId = this->FindInLeaf(point, parametric, node, worklet);
VTKM_RETURN_ON_ERROR(this->FindInLeaf(point, parametric, node, cellId));
state = FindCellState::AscendFromNode;
}
else
{
state = FindCellState::DescendLeftChild;
}
return vtkm::ErrorCode::Success;
}
VTKM_EXEC
@ -221,10 +229,11 @@ private:
}
}
VTKM_EXEC vtkm::Id FindInLeaf(const vtkm::Vec3f& point,
vtkm::Vec3f& parametric,
const vtkm::exec::CellLocatorBoundingIntervalHierarchyNode& node,
const vtkm::exec::FunctorBase& worklet) const
VTKM_EXEC vtkm::ErrorCode FindInLeaf(
const vtkm::Vec3f& point,
vtkm::Vec3f& parametric,
const vtkm::exec::CellLocatorBoundingIntervalHierarchyNode& node,
vtkm::Id& containingCellId) const
{
using IndicesType = typename CellSetPortal::IndicesType;
for (vtkm::Id i = node.Leaf.Start; i < node.Leaf.Start + node.Leaf.Size; ++i)
@ -233,25 +242,31 @@ private:
IndicesType cellPointIndices = this->CellSet.GetIndices(cellId);
vtkm::VecFromPortalPermute<IndicesType, CoordsPortal> cellPoints(&cellPointIndices,
this->Coords);
if (IsPointInCell(point, parametric, this->CellSet.GetCellShape(cellId), cellPoints, worklet))
bool found;
VTKM_RETURN_ON_ERROR(this->IsPointInCell(
point, parametric, this->CellSet.GetCellShape(cellId), cellPoints, found));
if (found)
{
return cellId;
containingCellId = cellId;
return vtkm::ErrorCode::Success;
}
}
return -1;
containingCellId = -1;
return vtkm::ErrorCode::Success;
}
template <typename CoordsType, typename CellShapeTag>
VTKM_EXEC static bool IsPointInCell(const vtkm::Vec3f& point,
vtkm::Vec3f& parametric,
CellShapeTag cellShape,
const CoordsType& cellPoints,
const vtkm::exec::FunctorBase& worklet)
VTKM_EXEC static vtkm::ErrorCode IsPointInCell(const vtkm::Vec3f& point,
vtkm::Vec3f& parametric,
CellShapeTag cellShape,
const CoordsType& cellPoints,
bool& isInside)
{
bool success = false;
parametric = vtkm::exec::WorldCoordinatesToParametricCoordinates(
cellPoints, point, cellShape, success, worklet);
return success && vtkm::exec::CellInside(parametric, cellShape);
isInside = false;
VTKM_RETURN_ON_ERROR(vtkm::exec::WorldCoordinatesToParametricCoordinates(
cellPoints, point, cellShape, parametric));
isInside = vtkm::exec::CellInside(parametric, cellShape);
return vtkm::ErrorCode::Success;
}
using VisitType = vtkm::TopologyElementTagCell;

@ -95,16 +95,14 @@ public:
}
VTKM_EXEC
void FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const override
vtkm::ErrorCode FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric) const override
{
(void)worklet; //suppress unused warning
if (!this->IsInside(point))
{
cellId = -1;
return;
return vtkm::ErrorCode::CellNotFound;
}
// Get the Cell Id from the point.
@ -148,6 +146,8 @@ public:
}
// Get the actual cellId, from the logical cell index of the cell
cellId = logicalCell[2] * this->PlaneSize + logicalCell[1] * this->RowSize + logicalCell[0];
return vtkm::ErrorCode::Success;
}
private:

@ -75,16 +75,14 @@ public:
}
VTKM_EXEC
void FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric,
const vtkm::exec::FunctorBase& worklet) const override
vtkm::ErrorCode FindCell(const vtkm::Vec3f& point,
vtkm::Id& cellId,
vtkm::Vec3f& parametric) const override
{
(void)worklet; //suppress unused warning
if (!this->IsInside(point))
{
cellId = -1;
return;
return vtkm::ErrorCode::CellNotFound;
}
// Get the Cell Id from the point.
vtkm::Id3 logicalCell(0, 0, 0);
@ -112,6 +110,8 @@ public:
cellId =
(logicalCell[2] * this->CellDims[1] + logicalCell[1]) * this->CellDims[0] + logicalCell[0];
parametric = temp - logicalCell;
return vtkm::ErrorCode::Success;
}
private:

@ -27,81 +27,90 @@ namespace exec
//-----------------------------------------------------------------------------
template <typename ParametricCoordType, typename CellShapeTag>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
CellShapeTag,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
auto lclTag = typename vtkm::internal::CellShapeTagVtkmToVtkc<CellShapeTag>::Type{};
(void)numPoints; // Silence compiler warnings.
VTKM_ASSERT(numPoints == lclTag.numberOfPoints());
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
lcl::parametricCenter(lclTag, pcoords);
if (numPoints != lclTag.numberOfPoints())
{
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
return vtkm::internal::LclErrorToVtkmError(lcl::parametricCenter(lclTag, pcoords));
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagEmpty,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagEmpty,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
(void)numPoints; // Silence compiler warnings.
VTKM_ASSERT(numPoints == 0);
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
if (numPoints != 0)
{
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
return vtkm::ErrorCode::Success;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagVertex,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagVertex,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
(void)numPoints; // Silence compiler warnings.
VTKM_ASSERT(numPoints == 1);
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
if (numPoints != 1)
{
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
return vtkm::ErrorCode::Success;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolyLine,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
switch (numPoints)
{
case 1:
ParametricCoordinatesCenter(numPoints, pcoords, vtkm::CellShapeTagVertex(), worklet);
return;
return ParametricCoordinatesCenter(numPoints, vtkm::CellShapeTagVertex(), pcoords);
case 2:
ParametricCoordinatesCenter(numPoints, pcoords, vtkm::CellShapeTagLine(), worklet);
return;
return ParametricCoordinatesCenter(numPoints, vtkm::CellShapeTagLine(), pcoords);
}
pcoords[0] = 0.5;
pcoords[1] = 0;
pcoords[2] = 0;
return vtkm::ErrorCode::Success;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagPolygon,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
VTKM_ASSERT(numPoints > 0);
if (numPoints < 1)
{
pcoords = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
switch (numPoints)
{
case 1:
ParametricCoordinatesCenter(numPoints, pcoords, vtkm::CellShapeTagVertex(), worklet);
break;
return ParametricCoordinatesCenter(numPoints, vtkm::CellShapeTagVertex(), pcoords);
case 2:
ParametricCoordinatesCenter(numPoints, pcoords, vtkm::CellShapeTagLine(), worklet);
break;
return ParametricCoordinatesCenter(numPoints, vtkm::CellShapeTagLine(), pcoords);
default:
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
lcl::parametricCenter(lcl::Polygon(numPoints), pcoords);
break;
return vtkm::internal::LclErrorToVtkmError(
lcl::parametricCenter(lcl::Polygon(numPoints), pcoords));
}
}
@ -110,19 +119,34 @@ static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPo
/// of points.
///
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
vtkm::CellShapeTagGeneric shape,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
ParametricCoordinatesCenter(numPoints, pcoords, CellShapeTag(), worklet));
vtkmGenericCellShapeMacro(status =
ParametricCoordinatesCenter(numPoints, CellShapeTag(), pcoords));
default:
worklet.RaiseError("Bad shape given to ParametricCoordinatesCenter.");
pcoords[0] = pcoords[1] = pcoords[2] = 0;
break;
pcoords = { 0 };
status = vtkm::ErrorCode::InvalidShapeId;
}
return status;
}
template <typename ParametricCoordType, typename CellShapeTag>
VTKM_DEPRECATED(1.6, "Signature changed to ParametricCoordinatesCenter(numPoints, shape, result).")
static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::ErrorCode status = ParametricCoordinatesCenter(numPoints, shape, pcoords);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
}
@ -130,105 +154,119 @@ static inline VTKM_EXEC void ParametricCoordinatesCenter(vtkm::IdComponent numPo
/// of points.
///
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::Vec3f ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
VTKM_DEPRECATED(1.6, "Signature changed to ParametricCoordinatesCenter(numPoints, shape, result).")
static inline VTKM_EXEC vtkm::Vec3f
ParametricCoordinatesCenter(vtkm::IdComponent numPoints,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::Vec3f pcoords(0.0f);
ParametricCoordinatesCenter(numPoints, pcoords, shape, worklet);
vtkm::ErrorCode status = ParametricCoordinatesCenter(numPoints, shape, pcoords);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return pcoords;
}
//-----------------------------------------------------------------------------
template <typename ParametricCoordType, typename CellShapeTag>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
CellShapeTag,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
auto lclTag = typename vtkm::internal::CellShapeTagVtkmToVtkc<CellShapeTag>::Type{};
(void)numPoints; // Silence compiler warnings.
VTKM_ASSUME(numPoints == lclTag.numberOfPoints());
VTKM_ASSUME((pointIndex >= 0) && (pointIndex < numPoints));
if (numPoints != lclTag.numberOfPoints())
{
pcoords = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
if ((pointIndex < 0) || (pointIndex >= numPoints))
{
pcoords = { 0 };
return vtkm::ErrorCode::InvalidPointId;
}
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
lcl::parametricPoint(lclTag, pointIndex, pcoords);
return vtkm::internal::LclErrorToVtkmError(lcl::parametricPoint(lclTag, pointIndex, pcoords));
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent,
vtkm::IdComponent,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagEmpty,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent,
vtkm::IdComponent,
vtkm::CellShapeTagEmpty,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
worklet.RaiseError("Empty cell has no points.");
pcoords[0] = pcoords[1] = pcoords[2] = 0;
return vtkm::ErrorCode::OperationOnEmptyCell;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagVertex,
const vtkm::exec::FunctorBase&)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::CellShapeTagVertex,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
(void)numPoints; // Silence compiler warnings.
(void)pointIndex; // Silence compiler warnings.
VTKM_ASSUME(numPoints == 1);
VTKM_ASSUME(pointIndex == 0);
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
if (numPoints != 1)
{
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
if (pointIndex != 0)
{
return vtkm::ErrorCode::InvalidPointId;
}
return vtkm::ErrorCode::Success;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine,
const vtkm::exec::FunctorBase& functor)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::CellShapeTagPolyLine,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
if (numPoints < 1)
{
pcoords = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
switch (numPoints)
{
case 1:
ParametricCoordinatesPoint(
numPoints, pointIndex, pcoords, vtkm::CellShapeTagVertex(), functor);
return;
return ParametricCoordinatesPoint(numPoints, pointIndex, vtkm::CellShapeTagVertex(), pcoords);
case 2:
ParametricCoordinatesPoint(numPoints, pointIndex, pcoords, vtkm::CellShapeTagLine(), functor);
return;
return ParametricCoordinatesPoint(numPoints, pointIndex, vtkm::CellShapeTagLine(), pcoords);
}
pcoords[0] =
static_cast<ParametricCoordType>(pointIndex) / static_cast<ParametricCoordType>(numPoints - 1);
pcoords[1] = 0;
pcoords[2] = 0;
return vtkm::ErrorCode::Success;
}
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::CellShapeTagPolygon,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
VTKM_ASSUME((numPoints > 0));
VTKM_ASSUME((pointIndex >= 0) && (pointIndex < numPoints));
switch (numPoints)
{
case 1:
ParametricCoordinatesPoint(
numPoints, pointIndex, pcoords, vtkm::CellShapeTagVertex(), worklet);
return;
return ParametricCoordinatesPoint(numPoints, pointIndex, vtkm::CellShapeTagVertex(), pcoords);
case 2:
ParametricCoordinatesPoint(numPoints, pointIndex, pcoords, vtkm::CellShapeTagLine(), worklet);
return;
return ParametricCoordinatesPoint(numPoints, pointIndex, vtkm::CellShapeTagLine(), pcoords);
default:
pcoords = vtkm::TypeTraits<vtkm::Vec<ParametricCoordType, 3>>::ZeroInitialization();
lcl::parametricPoint(lcl::Polygon(numPoints), pointIndex, pcoords);
return;
return vtkm::internal::LclErrorToVtkmError(
lcl::parametricPoint(lcl::Polygon(numPoints), pointIndex, pcoords));
}
}
@ -237,20 +275,38 @@ static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoi
/// the given number of points.
///
template <typename ParametricCoordType>
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::CellShapeTagGeneric shape,
vtkm::Vec<ParametricCoordType, 3>& pcoords)
{
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
ParametricCoordinatesPoint(numPoints, pointIndex, pcoords, CellShapeTag(), worklet));
status = ParametricCoordinatesPoint(numPoints, pointIndex, CellShapeTag(), pcoords));
default:
worklet.RaiseError("Bad shape given to ParametricCoordinatesPoint.");
pcoords[0] = pcoords[1] = pcoords[2] = 0;
break;
status = vtkm::ErrorCode::InvalidShapeId;
}
return status;
}
template <typename ParametricCoordType, typename CellShapeTag>
VTKM_DEPRECATED(
1.6,
"Signature changed to ParametricCoordinatesPoint(numPoints, pointIndex, shape, result).")
static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::Vec<ParametricCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::ErrorCode status = ParametricCoordinatesPoint(numPoints, pointIndex, shape, pcoords);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
}
@ -258,14 +314,21 @@ static inline VTKM_EXEC void ParametricCoordinatesPoint(vtkm::IdComponent numPoi
/// the given number of points.
///
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::Vec3f ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
VTKM_DEPRECATED(
1.6,
"Signature changed to ParametricCoordinatesPoint(numPoints, pointIndex, shape, result).")
static inline VTKM_EXEC vtkm::Vec3f
ParametricCoordinatesPoint(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::Vec3f pcoords(0.0f);
ParametricCoordinatesPoint(numPoints, pointIndex, pcoords, shape, worklet);
vtkm::Vec3f pcoords;
vtkm::ErrorCode status = ParametricCoordinatesPoint(numPoints, pointIndex, shape, pcoords);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return pcoords;
}
@ -273,211 +336,218 @@ static inline VTKM_EXEC vtkm::Vec3f ParametricCoordinatesPoint(
namespace internal
{
template <typename VtkcCellShapeTag, typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinatesImpl(VtkcCellShapeTag tag,
const WorldCoordVector& pointWCoords,
const PCoordType& pcoords,
const vtkm::exec::FunctorBase& worklet)
template <typename LclCellShapeTag, typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinatesImpl(
LclCellShapeTag tag,
const WorldCoordVector& pointWCoords,
const PCoordType& pcoords,
typename WorldCoordVector::ComponentType& wcoords)
{
typename WorldCoordVector::ComponentType wcoords(0);
auto status =
lcl::parametricToWorld(tag, lcl::makeFieldAccessorNestedSOA(pointWCoords, 3), pcoords, wcoords);
if (status != lcl::ErrorCode::SUCCESS)
{
worklet.RaiseError(lcl::errorString(status));
}
return wcoords;
return vtkm::internal::LclErrorToVtkmError(lcl::parametricToWorld(
tag, lcl::makeFieldAccessorNestedSOA(pointWCoords, 3), pcoords, wcoords));
}
} // namespace internal
template <typename WorldCoordVector, typename PCoordType, typename CellShapeTag>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
CellShapeTag shape,
typename WorldCoordVector::ComponentType& result)
{
auto numPoints = pointWCoords.GetNumberOfComponents();
return internal::ParametricCoordinatesToWorldCoordinatesImpl(
vtkm::internal::make_VtkcCellShapeTag(shape, numPoints), pointWCoords, pcoords, worklet);
vtkm::internal::make_LclCellShapeTag(shape, numPoints), pointWCoords, pcoords, result);
}
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagEmpty empty,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagEmpty empty,
typename WorldCoordVector::ComponentType& result)
{
return vtkm::exec::CellInterpolate(pointWCoords, pcoords, empty, worklet);
return vtkm::exec::CellInterpolate(pointWCoords, pcoords, empty, result);
}
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine polyLine,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagPolyLine polyLine,
typename WorldCoordVector::ComponentType& result)
{
return vtkm::exec::CellInterpolate(pointWCoords, pcoords, polyLine, worklet);
return vtkm::exec::CellInterpolate(pointWCoords, pcoords, polyLine, result);
}
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagPolygon,
typename WorldCoordVector::ComponentType& result)
{
auto numPoints = pointWCoords.GetNumberOfComponents();
switch (numPoints)
{
case 1:
return ParametricCoordinatesToWorldCoordinates(
pointWCoords, pcoords, vtkm::CellShapeTagVertex{}, worklet);
pointWCoords, pcoords, vtkm::CellShapeTagVertex{}, result);
case 2:
return ParametricCoordinatesToWorldCoordinates(
pointWCoords, pcoords, vtkm::CellShapeTagLine{}, worklet);
pointWCoords, pcoords, vtkm::CellShapeTagLine{}, result);
default:
return internal::ParametricCoordinatesToWorldCoordinatesImpl(
lcl::Polygon(numPoints), pointWCoords, pcoords, worklet);
lcl::Polygon(numPoints), pointWCoords, pcoords, result);
}
}
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const vtkm::VecAxisAlignedPointCoordinates<2>& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const vtkm::VecAxisAlignedPointCoordinates<2>& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagQuad,
typename WorldCoordVector::ComponentType& result)
{
return internal::ParametricCoordinatesToWorldCoordinatesImpl(
lcl::Pixel{}, pointWCoords, pcoords, worklet);
lcl::Pixel{}, pointWCoords, pcoords, result);
}
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const vtkm::VecAxisAlignedPointCoordinates<3>& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const vtkm::VecAxisAlignedPointCoordinates<3>& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagHexahedron,
typename WorldCoordVector::ComponentType& result)
{
return internal::ParametricCoordinatesToWorldCoordinatesImpl(
lcl::Voxel{}, pointWCoords, pcoords, worklet);
lcl::Voxel{}, pointWCoords, pcoords, result);
}
//-----------------------------------------------------------------------------
/// Returns the world coordinate corresponding to the given parametric coordinate of a cell.
///
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
vtkm::CellShapeTagGeneric shape,
typename WorldCoordVector::ComponentType& result)
{
typename WorldCoordVector::ComponentType wcoords(0);
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(wcoords = ParametricCoordinatesToWorldCoordinates(
pointWCoords, pcoords, CellShapeTag(), worklet));
vtkmGenericCellShapeMacro(status = ParametricCoordinatesToWorldCoordinates(
pointWCoords, pcoords, CellShapeTag(), result));
default:
worklet.RaiseError("Bad shape given to ParametricCoordinatesPoint.");
break;
result = { 0 };
status = vtkm::ErrorCode::InvalidShapeId;
}
return wcoords;
return status;
}
template <typename WorldCoordVector, typename PCoordType, typename CellShapeTag>
VTKM_DEPRECATED(1.6,
"Signature changed to "
"ParametricCoordinatesToWorldCoordinates(pointWCoords, pcoords, shape, result).")
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
ParametricCoordinatesToWorldCoordinates(const WorldCoordVector& pointWCoords,
const vtkm::Vec<PCoordType, 3>& pcoords,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
typename WorldCoordVector::ComponentType result;
vtkm::ErrorCode status =
ParametricCoordinatesToWorldCoordinates(pointWCoords, pcoords, shape, result);
if (status != vtkm::ErrorCode::Success)
{
worklet.RaiseError(vtkm::ErrorString(status));
}
return result;
}
//-----------------------------------------------------------------------------
namespace internal
{
template <typename VtkcCellShapeTag, typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinatesImpl(VtkcCellShapeTag tag,
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
bool& success,
const vtkm::exec::FunctorBase& worklet)
template <typename LclCellShapeTag, typename WorldCoordVector>
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinatesImpl(
LclCellShapeTag tag,
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
typename WorldCoordVector::ComponentType& result)
{
VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == tag.numberOfPoints());
auto pcoords = vtkm::TypeTraits<typename WorldCoordVector::ComponentType>::ZeroInitialization();
auto status =
lcl::worldToParametric(tag, lcl::makeFieldAccessorNestedSOA(pointWCoords, 3), wcoords, pcoords);
success = true;
if (status != lcl::ErrorCode::SUCCESS)
if (pointWCoords.GetNumberOfComponents() != tag.numberOfPoints())
{
worklet.RaiseError(lcl::errorString(status));
success = false;
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
return pcoords;
result = vtkm::TypeTraits<typename WorldCoordVector::ComponentType>::ZeroInitialization();
return vtkm::internal::LclErrorToVtkmError(
lcl::worldToParametric(tag, lcl::makeFieldAccessorNestedSOA(pointWCoords, 3), wcoords, result));
}
} // namespace internal
template <typename WorldCoordVector, typename CellShapeTag>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
CellShapeTag shape,
bool& success,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
CellShapeTag shape,
typename WorldCoordVector::ComponentType& result)
{
auto numPoints = pointWCoords.GetNumberOfComponents();
return internal::WorldCoordinatesToParametricCoordinatesImpl(
vtkm::internal::make_VtkcCellShapeTag(shape, numPoints),
pointWCoords,
wcoords,
success,
worklet);
vtkm::internal::make_LclCellShapeTag(shape, numPoints), pointWCoords, wcoords, result);
}
template <typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector&,
const typename WorldCoordVector::ComponentType&,
vtkm::CellShapeTagEmpty,
bool& success,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector&,
const typename WorldCoordVector::ComponentType&,
vtkm::CellShapeTagEmpty,
typename WorldCoordVector::ComponentType& result)
{
worklet.RaiseError("Attempted to find point coordinates in empty cell.");
success = false;
return typename WorldCoordVector::ComponentType();
result = { 0 };
return vtkm::ErrorCode::OperationOnEmptyCell;
}
template <typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType&,
vtkm::CellShapeTagVertex,
bool& success,
const vtkm::exec::FunctorBase& vtkmNotUsed(worklet))
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType&,
vtkm::CellShapeTagVertex,
typename WorldCoordVector::ComponentType& result)
{
(void)pointWCoords; // Silence compiler warnings.
VTKM_ASSERT(pointWCoords.GetNumberOfComponents() == 1);
success = true;
return typename WorldCoordVector::ComponentType(0, 0, 0);
if (pointWCoords.GetNumberOfComponents() != 1)
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
result = typename WorldCoordVector::ComponentType(0, 0, 0);
return vtkm::ErrorCode::Success;
}
template <typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagPolyLine,
bool& success,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagPolyLine,
typename WorldCoordVector::ComponentType& result)
{
vtkm::IdComponent numPoints = pointWCoords.GetNumberOfComponents();
VTKM_ASSERT(pointWCoords.GetNumberOfComponents() >= 1);
if (numPoints < 1)
{
result = { 0 };
return vtkm::ErrorCode::InvalidNumberOfPoints;
}
if (numPoints == 1)
{
return WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, vtkm::CellShapeTagVertex(), success, worklet);
pointWCoords, wcoords, vtkm::CellShapeTagVertex(), result);
}
using Vector3 = typename WorldCoordVector::ComponentType;
@ -507,84 +577,106 @@ WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
}
vtkm::Vec<Vector3, 2> line(pointWCoords[idx - 1], pointWCoords[idx]);
auto lpc = WorldCoordinatesToParametricCoordinates(
line, wcoords, vtkm::CellShapeTagLine{}, success, worklet);
Vector3 lpc;
VTKM_RETURN_ON_ERROR(
WorldCoordinatesToParametricCoordinates(line, wcoords, vtkm::CellShapeTagLine{}, lpc));
//Segment param is [0,1] on that segment.
//Map that onto the param for the entire segment.
T dParam = static_cast<T>(1) / static_cast<T>(numPoints - 1);
T polyLineParam = static_cast<T>(idx - 1) * dParam + lpc[0] * dParam;
return Vector3(polyLineParam, 0, 0);
result = Vector3(polyLineParam, 0, 0);
return vtkm::ErrorCode::Success;
}
template <typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagPolygon,
bool& success,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagPolygon,
typename WorldCoordVector::ComponentType& result)
{
auto numPoints = pointWCoords.GetNumberOfComponents();
switch (numPoints)
{
case 1:
return WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, vtkm::CellShapeTagVertex{}, success, worklet);
pointWCoords, wcoords, vtkm::CellShapeTagVertex{}, result);
case 2:
return WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, vtkm::CellShapeTagLine{}, success, worklet);
pointWCoords, wcoords, vtkm::CellShapeTagLine{}, result);
default:
return internal::WorldCoordinatesToParametricCoordinatesImpl(
lcl::Polygon(numPoints), pointWCoords, wcoords, success, worklet);
lcl::Polygon(numPoints), pointWCoords, wcoords, result);
}
}
static inline VTKM_EXEC vtkm::Vec3f WorldCoordinatesToParametricCoordinates(
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const vtkm::VecAxisAlignedPointCoordinates<2>& pointWCoords,
const vtkm::Vec3f& wcoords,
vtkm::CellShapeTagQuad,
bool& success,
const FunctorBase& worklet)
vtkm::Vec3f& result)
{
return internal::WorldCoordinatesToParametricCoordinatesImpl(
lcl::Pixel{}, pointWCoords, wcoords, success, worklet);
lcl::Pixel{}, pointWCoords, wcoords, result);
}
static inline VTKM_EXEC vtkm::Vec3f WorldCoordinatesToParametricCoordinates(
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const vtkm::VecAxisAlignedPointCoordinates<3>& pointWCoords,
const vtkm::Vec3f& wcoords,
vtkm::CellShapeTagHexahedron,
bool& success,
const FunctorBase& worklet)
vtkm::Vec3f& result)
{
return internal::WorldCoordinatesToParametricCoordinatesImpl(
lcl::Voxel{}, pointWCoords, wcoords, success, worklet);
lcl::Voxel{}, pointWCoords, wcoords, result);
}
//-----------------------------------------------------------------------------
/// Returns the world paramteric corresponding to the given world coordinate for a cell.
///
template <typename WorldCoordVector>
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagGeneric shape,
bool& success,
const vtkm::exec::FunctorBase& worklet)
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
vtkm::CellShapeTagGeneric shape,
typename WorldCoordVector::ComponentType& result)
{
typename WorldCoordVector::ComponentType result;
vtkm::ErrorCode status;
switch (shape.Id)
{
vtkmGenericCellShapeMacro(result = WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, CellShapeTag(), success, worklet));
vtkmGenericCellShapeMacro(status = WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, CellShapeTag(), result));
default:
success = false;
worklet.RaiseError("Unknown cell shape sent to world 2 parametric.");
return typename WorldCoordVector::ComponentType();
result = { 0 };
status = vtkm::ErrorCode::InvalidShapeId;
}
return status;
}
template <typename WorldCoordVector, typename CellShapeTag>
VTKM_DEPRECATED(1.6,
"Signature changed to "
"WorldCoordinatesToParametricCoordinates(pointWCoords, wcoords, shape, result).")
static inline VTKM_EXEC typename WorldCoordVector::ComponentType
WorldCoordinatesToParametricCoordinates(const WorldCoordVector& pointWCoords,
const typename WorldCoordVector::ComponentType& wcoords,
CellShapeTag shape,
bool& success,
const vtkm::exec::FunctorBase& worklet)
{
typename WorldCoordVector::ComponentType result;
vtkm::ErrorCode status =
WorldCoordinatesToParametricCoordinates(pointWCoords, wcoords, shape, result);
if (status != vtkm::ErrorCode::Success)
{
success = false;
worklet.RaiseError(vtkm::ErrorString(status));
}
else
{
success = true;
}
return result;
}
}

@ -53,6 +53,7 @@ public:
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex3D,
@ -60,9 +61,7 @@ public:
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
// We currently only support multidimensional indices on one-to-one input-
// to-output mappings. (We don't have a use case otherwise.)
// That is why we treat teh threadIndex as also the inputIndex and outputIndex
// This constructor handles multidimensional indices on one-to-one input-to-output
auto logicalIndex = detail::Deflate(threadIndex3D, LogicalIndexType());
this->ThreadIndex = threadIndex1D;
@ -75,6 +74,29 @@ public:
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex3D,
vtkm::Id threadIndex1D,
vtkm::Id inputIndex,
vtkm::IdComponent visitIndex,
vtkm::Id outputIndex,
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
// This constructor handles multidimensional indices on many-to-many input-to-output
auto logicalIndex = detail::Deflate(threadIndex3D, LogicalIndexType());
this->ThreadIndex = threadIndex1D;
this->InputIndex = inputIndex;
this->OutputIndex = outputIndex;
this->VisitIndex = visitIndex;
this->LogicalIndex = logicalIndex;
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
/// \brief The logical index into the input domain.
///
/// This is similar to \c GetIndex3D except the Vec size matches the actual
@ -159,7 +181,6 @@ private:
vtkm::Id OutputIndex;
LogicalIndexType LogicalIndex;
IndicesIncidentType IndicesIncident;
//CellShapeTag CellShape;
vtkm::Id GlobalThreadIndexOffset;
};
@ -192,7 +213,6 @@ public:
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
@ -210,9 +230,29 @@ public:
this->VisitIndex = 0;
this->LogicalIndex = logicalIndex;
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
//this->CellShape = connectivity.GetCellShape(index);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex3D,
vtkm::Id threadIndex1D,
vtkm::Id inputIndex,
vtkm::IdComponent visitIndex,
vtkm::Id outputIndex,
const ConnectivityType& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
{
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex3D, LogicalIndexType());
this->ThreadIndex = threadIndex1D;
this->InputIndex = inputIndex;
this->OutputIndex = outputIndex;
this->VisitIndex = visitIndex;
this->LogicalIndex = logicalIndex;
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
/// \brief The logical index into the input domain.
///
/// This is similar to \c GetIndex3D except the Vec size matches the actual
@ -297,7 +337,6 @@ private:
vtkm::Id OutputIndex;
LogicalIndexType LogicalIndex;
IndicesIncidentType IndicesIncident;
//CellShapeTag CellShape;
vtkm::Id GlobalThreadIndexOffset;
};

@ -72,6 +72,26 @@ public:
{
}
template <vtkm::IdComponent Dimension>
VTKM_EXEC ThreadIndicesPointNeighborhood(
const vtkm::Id3& threadIndex3D,
vtkm::Id threadIndex1D,
vtkm::Id inputIndex,
vtkm::IdComponent visitIndex,
vtkm::Id outputIndex,
const vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell,
Dimension>& connectivity,
vtkm::Id globalThreadIndexOffset = 0)
: State(threadIndex3D, detail::To3D(connectivity.GetPointDimensions()))
, ThreadIndex(threadIndex1D)
, InputIndex(inputIndex)
, OutputIndex(outputIndex)
, VisitIndex(visitIndex)
, GlobalThreadIndexOffset(globalThreadIndexOffset)
{
}
template <vtkm::IdComponent Dimension>
VTKM_EXEC ThreadIndicesPointNeighborhood(
vtkm::Id threadIndex,

@ -179,9 +179,7 @@ public:
const ConnectivityType& connectivity,
const vtkm::Id globalThreadIndexOffset = 0)
{
// We currently only support multidimensional indices on one-to-one input-
// to-output mappings. (We don't have a use case otherwise.)
// That is why we treat teh threadIndex as also the inputIndex and outputIndex
// This constructor handles multidimensional indices on one-to-one input-to-output
auto logicalIndex = detail::Deflate(threadIndex3D, LogicalIndexType());
this->ThreadIndex = threadIndex1D;
this->InputIndex = threadIndex1D;
@ -193,6 +191,26 @@ public:
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
VTKM_EXEC ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex3D,
vtkm::Id threadIndex1D,
vtkm::Id inIndex,
vtkm::IdComponent visitIndex,
vtkm::Id outIndex,
const ConnectivityType& connectivity,
const vtkm::Id globalThreadIndexOffset = 0)
{
// This constructor handles multidimensional indices on many-to-many input-to-output
auto logicalIndex = detail::Deflate(threadIndex3D, LogicalIndexType());
this->ThreadIndex = threadIndex1D;
this->InputIndex = inIndex;
this->VisitIndex = visitIndex;
this->OutputIndex = outIndex;
this->LogicalIndex = logicalIndex;
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
this->CellShape = connectivity.GetCellShape(threadIndex1D);
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
}
/// \brief The index of the thread or work invocation.
///
/// This index refers to which instance of the worklet is being invoked. Every invocation of the

@ -22,6 +22,9 @@
#include <ctime>
#include <random>
#define CHECK_CALL(call) \
VTKM_TEST_ASSERT((call) == vtkm::ErrorCode::Success, "Call resulted in error.")
namespace
{
@ -91,13 +94,6 @@ struct TestDerivativeFunctor
LinearField<FieldType> field,
vtkm::Vec<FieldType, 3> expectedGradient) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
vtkm::IdComponent numPoints = worldCoordinates.GetNumberOfComponents();
vtkm::VecVariable<FieldType, MAX_POINTS> fieldValues;
@ -119,9 +115,9 @@ struct TestDerivativeFunctor
vtkm::FloatDefault totalWeight = 0;
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
vtkm::Vec3f pointPcoords =
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec3f pointPcoords;
CHECK_CALL(
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, pointPcoords));
vtkm::FloatDefault weight = randomDist(g_RandomGenerator);
pcoords = pcoords + weight * pointPcoords;
totalWeight += weight;
@ -130,9 +126,9 @@ struct TestDerivativeFunctor
std::cout << " Test derivative at " << pcoords << std::endl;
vtkm::Vec<FieldType, 3> computedGradient =
vtkm::exec::CellDerivative(fieldValues, worldCoordinates, pcoords, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec<FieldType, 3> computedGradient;
CHECK_CALL(vtkm::exec::CellDerivative(
fieldValues, worldCoordinates, pcoords, shape, computedGradient));
std::cout << " Computed: " << computedGradient << std::endl;
// Note that some gradients (particularly those near the center of
@ -149,19 +145,11 @@ struct TestDerivativeFunctor
LinearField<FieldType> field,
vtkm::Vec<FieldType, 3> expectedGradient) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
vtkm::VecVariable<vtkm::Vec3f, MAX_POINTS> worldCoordinates;
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
vtkm::Vec3f pcoords =
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec3f pcoords;
CHECK_CALL(vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, pcoords));
vtkm::Vec3f wcoords = ParametricToWorld(pcoords);
VTKM_TEST_ASSERT(test_equal(pcoords, WorldToParametric(wcoords)),
"Test world/parametric conversion broken.");

@ -21,6 +21,9 @@
#include <set>
#include <vector>
#define CHECK_CALL(call) \
VTKM_TEST_ASSERT((call) == vtkm::ErrorCode::Success, "Call resulted in error.")
namespace
{
@ -41,13 +44,6 @@ struct TestCellFacesFunctor
CellShapeTag shape,
vtkm::CellTopologicalDimensionsTag<3>) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
std::vector<vtkm::Id> pointIndexProxyBuffer(static_cast<std::size_t>(numPoints));
for (std::size_t index = 0; index < pointIndexProxyBuffer.size(); ++index)
{
@ -55,14 +51,16 @@ struct TestCellFacesFunctor
}
vtkm::VecCConst<vtkm::Id> pointIndexProxy(&pointIndexProxyBuffer.at(0), numPoints);
vtkm::IdComponent numEdges = vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, workletProxy);
vtkm::IdComponent numEdges;
CHECK_CALL(vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges));
VTKM_TEST_ASSERT(numEdges > 0, "No edges?");
std::set<EdgeType> edgeSet;
for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++)
{
EdgeType edge(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, workletProxy),
vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, workletProxy));
EdgeType edge;
CHECK_CALL(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, edge[0]));
CHECK_CALL(vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, edge[1]));
VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge.");
@ -73,49 +71,50 @@ struct TestCellFacesFunctor
VTKM_TEST_ASSERT(edgeSet.find(edge) == edgeSet.end(), "Found duplicate edge");
edgeSet.insert(edge);
vtkm::Id2 canonicalEdgeId =
vtkm::exec::CellEdgeCanonicalId(numPoints, edgeIndex, shape, pointIndexProxy, workletProxy);
vtkm::Id2 canonicalEdgeId;
CHECK_CALL(vtkm::exec::CellEdgeCanonicalId(
numPoints, edgeIndex, shape, pointIndexProxy, canonicalEdgeId));
VTKM_TEST_ASSERT(canonicalEdgeId[0] > 0, "Not using global ids?");
VTKM_TEST_ASSERT(canonicalEdgeId[0] < canonicalEdgeId[1], "Bad order.");
}
vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, workletProxy);
vtkm::IdComponent numFaces;
CHECK_CALL(vtkm::exec::CellFaceNumberOfFaces(shape, numFaces));
VTKM_TEST_ASSERT(numFaces > 0, "No faces?");
std::set<EdgeType> edgesFoundInFaces;
for (vtkm::IdComponent faceIndex = 0; faceIndex < numFaces; faceIndex++)
{
const vtkm::IdComponent numPointsInFace =
vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, workletProxy);
vtkm::IdComponent numPointsInFace;
CHECK_CALL(vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, numPointsInFace));
VTKM_TEST_ASSERT(numPointsInFace >= 3, "Face has fewer points than a triangle.");
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPointsInFace; pointIndex++)
{
vtkm::IdComponent localFaceIndex =
vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy);
vtkm::IdComponent localFaceIndex;
CHECK_CALL(vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, localFaceIndex));
VTKM_TEST_ASSERT(localFaceIndex >= 0, "Invalid point index for face.");
VTKM_TEST_ASSERT(localFaceIndex < numPoints, "Invalid point index for face.");
EdgeType edge;
if (pointIndex < numPointsInFace - 1)
{
edge = EdgeType(
vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy),
vtkm::exec::CellFaceLocalIndex(pointIndex + 1, faceIndex, shape, workletProxy));
CHECK_CALL(vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, edge[0]));
CHECK_CALL(vtkm::exec::CellFaceLocalIndex(pointIndex + 1, faceIndex, shape, edge[1]));
}
else
{
edge =
EdgeType(vtkm::exec::CellFaceLocalIndex(0, faceIndex, shape, workletProxy),
vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy));
CHECK_CALL(vtkm::exec::CellFaceLocalIndex(0, faceIndex, shape, edge[0]));
CHECK_CALL(vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, edge[1]));
}
MakeEdgeCanonical(edge);
VTKM_TEST_ASSERT(edgeSet.find(edge) != edgeSet.end(), "Edge in face not in cell's edges");
edgesFoundInFaces.insert(edge);
}
vtkm::Id3 canonicalFaceId =
vtkm::exec::CellFaceCanonicalId(faceIndex, shape, pointIndexProxy, workletProxy);
vtkm::Id3 canonicalFaceId;
CHECK_CALL(
vtkm::exec::CellFaceCanonicalId(faceIndex, shape, pointIndexProxy, canonicalFaceId));
VTKM_TEST_ASSERT(canonicalFaceId[0] > 0, "Not using global ids?");
VTKM_TEST_ASSERT(canonicalFaceId[0] < canonicalFaceId[1], "Bad order.");
VTKM_TEST_ASSERT(canonicalFaceId[1] < canonicalFaceId[2], "Bad order.");
@ -130,13 +129,6 @@ struct TestCellFacesFunctor
CellShapeTag shape,
vtkm::CellTopologicalDimensionsTag<2>) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
std::vector<vtkm::Id> pointIndexProxyBuffer(static_cast<std::size_t>(numPoints));
for (std::size_t index = 0; index < pointIndexProxyBuffer.size(); ++index)
{
@ -144,14 +136,16 @@ struct TestCellFacesFunctor
}
vtkm::VecCConst<vtkm::Id> pointIndexProxy(&pointIndexProxyBuffer.at(0), numPoints);
vtkm::IdComponent numEdges = vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, workletProxy);
vtkm::IdComponent numEdges;
CHECK_CALL(vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges));
VTKM_TEST_ASSERT(numEdges == numPoints, "Polygons should have same number of points and edges");
std::set<EdgeType> edgeSet;
for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++)
{
EdgeType edge(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, workletProxy),
vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, workletProxy));
EdgeType edge;
CHECK_CALL(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, edge[0]));
CHECK_CALL(vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, edge[1]));
VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge.");
@ -162,13 +156,15 @@ struct TestCellFacesFunctor
VTKM_TEST_ASSERT(edgeSet.find(edge) == edgeSet.end(), "Found duplicate edge");
edgeSet.insert(edge);
vtkm::Id2 canonicalEdgeId =
vtkm::exec::CellEdgeCanonicalId(numPoints, edgeIndex, shape, pointIndexProxy, workletProxy);
vtkm::Id2 canonicalEdgeId;
CHECK_CALL(vtkm::exec::CellEdgeCanonicalId(
numPoints, edgeIndex, shape, pointIndexProxy, canonicalEdgeId));
VTKM_TEST_ASSERT(canonicalEdgeId[0] > 0, "Not using global ids?");
VTKM_TEST_ASSERT(canonicalEdgeId[0] < canonicalEdgeId[1], "Bad order.");
}
vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, workletProxy);
vtkm::IdComponent numFaces;
CHECK_CALL(vtkm::exec::CellFaceNumberOfFaces(shape, numFaces));
VTKM_TEST_ASSERT(numFaces == 0, "Non 3D shape should have no faces");
}
@ -179,17 +175,12 @@ struct TestCellFacesFunctor
CellShapeTag shape,
vtkm::CellTopologicalDimensionsTag<NumDimensions>) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
vtkm::IdComponent numEdges = vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, workletProxy);
vtkm::IdComponent numEdges;
CHECK_CALL(vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges));
VTKM_TEST_ASSERT(numEdges == 0, "0D or 1D shape should have no edges");
vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, workletProxy);
vtkm::IdComponent numFaces;
CHECK_CALL(vtkm::exec::CellFaceNumberOfFaces(shape, numFaces));
VTKM_TEST_ASSERT(numFaces == 0, "Non 3D shape should have no faces");
}

@ -20,6 +20,9 @@
#include <vtkm/testing/Testing.h>
#define CHECK_CALL(call) \
VTKM_TEST_ASSERT((call) == vtkm::ErrorCode::Success, "Call resulted in error.")
namespace
{
@ -63,22 +66,13 @@ struct TestInterpolateFunctor
}
averageValue = static_cast<ComponentType>(1.0 / numPoints) * averageValue;
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
std::cout << " Test interpolated value at each cell node." << std::endl;
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
vtkm::Vec3f pcoord =
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
FieldType interpolatedValue =
vtkm::exec::CellInterpolate(fieldValues, pcoord, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec3f pcoord;
CHECK_CALL(vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, pcoord));
FieldType interpolatedValue;
CHECK_CALL(vtkm::exec::CellInterpolate(fieldValues, pcoord, shape, interpolatedValue));
VTKM_TEST_ASSERT(test_equal(fieldValues[pointIndex], interpolatedValue),
"Interpolation at point not point value.");
@ -87,11 +81,10 @@ struct TestInterpolateFunctor
if (numPoints > 0)
{
std::cout << " Test interpolated value at cell center." << std::endl;
vtkm::Vec3f pcoord = vtkm::exec::ParametricCoordinatesCenter(numPoints, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
FieldType interpolatedValue =
vtkm::exec::CellInterpolate(fieldValues, pcoord, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec3f pcoord;
CHECK_CALL(vtkm::exec::ParametricCoordinatesCenter(numPoints, shape, pcoord));
FieldType interpolatedValue;
CHECK_CALL(vtkm::exec::CellInterpolate(fieldValues, pcoord, shape, interpolatedValue));
std::cout << "AVG= " << averageValue << " interp= " << interpolatedValue << std::endl;
VTKM_TEST_ASSERT(test_equal(averageValue, interpolatedValue),

@ -20,6 +20,9 @@
#include <ctime>
#include <random>
#define CHECK_CALL(call) \
VTKM_TEST_ASSERT((call) == vtkm::ErrorCode::Success, "Call resulted in error.")
namespace
{
@ -57,23 +60,15 @@ static void CompareCoordinates(const PointWCoordsType& pointWCoords,
{
using Vector3 = vtkm::Vec<T, 3>;
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
Vector3 computedWCoords = vtkm::exec::ParametricCoordinatesToWorldCoordinates(
pointWCoords, truePCoords, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
Vector3 computedWCoords;
CHECK_CALL(vtkm::exec::ParametricCoordinatesToWorldCoordinates(
pointWCoords, truePCoords, shape, computedWCoords));
VTKM_TEST_ASSERT(test_equal(computedWCoords, trueWCoords, 0.01),
"Computed wrong world coords from parametric coords.");
bool success = false;
Vector3 computedPCoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
pointWCoords, trueWCoords, shape, success, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
Vector3 computedPCoords;
CHECK_CALL(vtkm::exec::WorldCoordinatesToParametricCoordinates(
pointWCoords, trueWCoords, shape, computedPCoords));
VTKM_TEST_ASSERT(test_equal(computedPCoords, truePCoords, 0.01),
"Computed wrong parametric coords from world coords.");
}
@ -84,21 +79,13 @@ void TestPCoordsSpecial(const PointWCoordsType& pointWCoords, CellShapeTag shape
using Vector3 = typename PointWCoordsType::ComponentType;
using T = typename Vector3::ComponentType;
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
const vtkm::IdComponent numPoints = pointWCoords.GetNumberOfComponents();
std::cout << " Test parametric coordinates at cell nodes." << std::endl;
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
Vector3 pcoords;
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, pcoords, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
CHECK_CALL(vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, pcoords));
Vector3 wcoords = pointWCoords[pointIndex];
CompareCoordinates(pointWCoords, pcoords, wcoords, shape);
}
@ -113,7 +100,7 @@ void TestPCoordsSpecial(const PointWCoordsType& pointWCoords, CellShapeTag shape
wcoords = wcoords / Vector3(T(numPoints));
Vector3 pcoords;
vtkm::exec::ParametricCoordinatesCenter(numPoints, pcoords, shape, workletProxy);
CHECK_CALL(vtkm::exec::ParametricCoordinatesCenter(numPoints, shape, pcoords));
CompareCoordinates(pointWCoords, pcoords, wcoords, shape);
}
}
@ -123,13 +110,6 @@ void TestPCoordsSample(const PointWCoordsType& pointWCoords, CellShapeTag shape)
{
using Vector3 = typename PointWCoordsType::ComponentType;
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
const vtkm::IdComponent numPoints = pointWCoords.GetNumberOfComponents();
std::uniform_real_distribution<vtkm::FloatDefault> randomDist;
@ -141,9 +121,9 @@ void TestPCoordsSample(const PointWCoordsType& pointWCoords, CellShapeTag shape)
vtkm::FloatDefault totalWeight = 0;
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
vtkm::Vec3f pointPcoords =
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
vtkm::Vec3f pointPcoords;
CHECK_CALL(
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, shape, pointPcoords));
vtkm::FloatDefault weight = randomDist(g_RandomGenerator);
pcoords = pcoords + weight * pointPcoords;
totalWeight += weight;
@ -154,13 +134,12 @@ void TestPCoordsSample(const PointWCoordsType& pointWCoords, CellShapeTag shape)
// If you convert to world coordinates and back, you should get the
// same value.
Vector3 wcoords = vtkm::exec::ParametricCoordinatesToWorldCoordinates(
pointWCoords, pcoords, shape, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
bool success = false;
Vector3 computedPCoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, shape, success, workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
Vector3 wcoords;
CHECK_CALL(
vtkm::exec::ParametricCoordinatesToWorldCoordinates(pointWCoords, pcoords, shape, wcoords));
Vector3 computedPCoords;
CHECK_CALL(vtkm::exec::WorldCoordinatesToParametricCoordinates(
pointWCoords, wcoords, shape, computedPCoords));
VTKM_TEST_ASSERT(test_equal(pcoords, computedPCoords, 0.05),
"pcoord/wcoord transform not symmetrical");
@ -183,13 +162,6 @@ struct TestPCoordsFunctor
template <typename CellShapeTag>
PointWCoordType MakePointWCoords(CellShapeTag, vtkm::IdComponent numPoints) const
{
// Stuff to fake running in the execution environment.
char messageBuffer[256];
messageBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(messageBuffer, 256);
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
std::uniform_real_distribution<T> randomDist(-1, 1);
Vector3 sheerVec(randomDist(g_RandomGenerator), randomDist(g_RandomGenerator), 0);
@ -198,9 +170,8 @@ struct TestPCoordsFunctor
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
{
Vector3 pcoords;
vtkm::exec::ParametricCoordinatesPoint(
numPoints, pointIndex, pcoords, CellShapeTag(), workletProxy);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), messageBuffer);
CHECK_CALL(
vtkm::exec::ParametricCoordinatesPoint(numPoints, pointIndex, CellShapeTag(), pcoords));
Vector3 wCoords = Vector3(pcoords[0], pcoords[1], pcoords[2] + vtkm::Dot(pcoords, sheerVec));
pointWCoords.Append(wCoords);

@ -131,8 +131,32 @@ public:
}
}
VTKM_CONT
~FieldSelection() {}
// Normally the default compiler construction of each of these would be fine,
// but we don't want any of them compiled for devices (like CUDA), so we have
// to explicitly mark them as VTKM_CONT.
VTKM_CONT FieldSelection(const FieldSelection& src)
: Mode(src.Mode)
, Fields(src.Fields)
{
}
VTKM_CONT FieldSelection(FieldSelection&& rhs)
: Mode(rhs.Mode)
, Fields(std::move(rhs.Fields))
{
}
VTKM_CONT FieldSelection& operator=(const FieldSelection& src)
{
this->Mode = src.Mode;
this->Fields = src.Fields;
return *this;
}
VTKM_CONT FieldSelection& operator=(FieldSelection&& rhs)
{
this->Mode = rhs.Mode;
this->Fields = std::move(rhs.Fields);
return *this;
}
VTKM_CONT ~FieldSelection() {}
/// Returns true if the input field should be mapped to the output
/// dataset.

@ -59,7 +59,6 @@ vtkm::cont::DataSet MakeTestUniformDataSet()
}
}
}
velocityPortal.Detach();
dsf.AddPointField(dataset, "velocity", velocityField);
return dataset;
}

@ -32,6 +32,16 @@ struct PortalSupportsGetsImpl
using type = decltype(has<PortalType>(0));
};
template <typename PortalType>
struct PortalSupportsGets3DImpl
{
template <typename U, typename S = decltype(std::declval<U>().Get(vtkm::Id3{}))>
static std::true_type has(int);
template <typename U>
static std::false_type has(...);
using type = decltype(has<PortalType>(0));
};
template <typename PortalType>
struct PortalSupportsSetsImpl
{
@ -44,6 +54,18 @@ struct PortalSupportsSetsImpl
using type = decltype(has<PortalType>(0));
};
template <typename PortalType>
struct PortalSupportsSets3DImpl
{
template <typename U,
typename S = decltype(std::declval<U>().Set(vtkm::Id3{},
std::declval<typename U::ValueType>()))>
static std::true_type has(int);
template <typename U>
static std::false_type has(...);
using type = decltype(has<PortalType>(0));
};
template <typename PortalType>
struct PortalSupportsIteratorsImpl
{
@ -60,10 +82,18 @@ template <typename PortalType>
using PortalSupportsGets =
typename detail::PortalSupportsGetsImpl<typename std::decay<PortalType>::type>::type;
template <typename PortalType>
using PortalSupportsGets3D =
typename detail::PortalSupportsGets3DImpl<typename std::decay<PortalType>::type>::type;
template <typename PortalType>
using PortalSupportsSets =
typename detail::PortalSupportsSetsImpl<typename std::decay<PortalType>::type>::type;
template <typename PortalType>
using PortalSupportsSets3D =
typename detail::PortalSupportsSets3DImpl<typename std::decay<PortalType>::type>::type;
template <typename PortalType>
using PortalSupportsIterators =
typename detail::PortalSupportsIteratorsImpl<typename std::decay<PortalType>::type>::type;

@ -56,6 +56,7 @@ set(headers
ConfigureFor32.h
ConfigureFor64.h
ConnectivityStructuredInternals.h
DecayHelpers.h
ExportMacros.h
FunctionInterface.h
FunctionInterfaceDetailPost.h

@ -14,8 +14,6 @@
namespace vtkm
{
namespace worklet
{
namespace internal
{
@ -25,6 +23,5 @@ using remove_pointer_and_decay = typename std::remove_pointer<typename std::deca
template <typename T>
using remove_cvref = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
}
}
}
} // namespace vtkm::internal
#endif

@ -15,67 +15,8 @@
#include <vtkm/Deprecated.h>
#include <vtkm/List.h>
#if defined(VTKM_USING_GLIBCXX_4)
// It would make sense to put this in its own header file, but it is hard to imagine needing
// aligned_union anywhere else.
#include <algorithm>
namespace vtkmstd
{
template <std::size_t... Xs>
struct max_size;
template <std::size_t X>
struct max_size<X>
{
static constexpr std::size_t value = X;
};
template <std::size_t X0, std::size_t... Xs>
struct max_size<X0, Xs...>
{
static constexpr std::size_t other_value = max_size<Xs...>::value;
static constexpr std::size_t value = (other_value > X0) ? other_value : X0;
};
// This is to get around an apparent bug in GCC 4.8 where alianas(x) does not
// seem to work when x is a constexpr. See
// https://stackoverflow.com/questions/29879609/g-complains-constexpr-function-is-not-a-constant-expression
template <std::size_t Alignment, std::size_t Size>
struct aligned_data_block
{
alignas(Alignment) char _s[Size];
};
template <std::size_t Len, class... Types>
struct aligned_union
{
static constexpr std::size_t alignment_value = vtkmstd::max_size<alignof(Types)...>::value;
using type =
vtkmstd::aligned_data_block<alignment_value, vtkmstd::max_size<Len, sizeof(Types)...>::value>;
};
// GCC 4.8 and 4.9 standard library does not support std::is_trivially_copyable.
// There is no relyable way to get this information (since it has to come special from
// the compiler). For our purposes, we will report as nothing being trivially copyable,
// which causes us to call the constructors with everything. This should be fine unless
// some other part of the compiler is trying to check for trivial copies (perhaps nvcc
// on top of GCC 4.8).
template <typename>
struct is_trivially_copyable : std::false_type
{
};
} // namespace vtkmstd
#else // NOT VTKM_USING_GLIBCXX_4
namespace vtkmstd
{
using std::aligned_union;
using std::is_trivially_copyable;
} // namespace vtkmstd
#endif
#include <vtkmstd/aligned_union.h>
#include <vtkmstd/is_trivially_copyable.h>
namespace vtkm
{

@ -63,6 +63,7 @@ set(headers
MapperConnectivity.h
MapperWireframer.h
Quadralizer.h
ScalarRenderer.h
TextAnnotation.h
TextAnnotationBillboard.h
TextAnnotationScreen.h
@ -109,6 +110,7 @@ set(device_sources
MapperRayTracer.cxx
MapperVolume.cxx
MapperWireframer.cxx
ScalarRenderer.cxx
Scene.cxx
TextAnnotation.cxx
TextAnnotationBillboard.cxx
@ -133,6 +135,7 @@ set(device_sources
raytracing/QuadIntersector.cxx
raytracing/RayTracer.cxx
raytracing/RayOperations.cxx
raytracing/ScalarRenderer.cxx
raytracing/ShapeIntersector.cxx
raytracing/SphereExtractor.cxx
raytracing/SphereIntersector.cxx

@ -215,7 +215,8 @@ public:
throw vtkm::cont::ErrorBadValue("Conn Proxy: null canvas");
}
vtkm::rendering::raytracing::Camera rayCamera;
rayCamera.SetParameters(camera, *canvas);
rayCamera.SetParameters(
camera, (vtkm::Int32)canvas->GetWidth(), (vtkm::Int32)canvas->GetHeight());
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
rayCamera.CreateRays(rays, this->Coords.GetBounds());
rays.Buffers.at(0).InitConst(0.f);

@ -182,19 +182,18 @@ void MapperCylinder::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
vtkm::Int32 width = (vtkm::Int32) this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32) this->Internals->Canvas->GetHeight();
this->Internals->RayCamera.SetParameters(camera, width, height);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.GetCamera() = this->Internals->RayCamera;
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);

@ -181,19 +181,18 @@ void MapperPoint::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
vtkm::Int32 width = (vtkm::Int32) this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32) this->Internals->Canvas->GetHeight();
this->Internals->RayCamera.SetParameters(camera, width, height);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.GetCamera() = this->Internals->RayCamera;
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);

@ -103,19 +103,18 @@ void MapperQuad::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
vtkm::Int32 width = (vtkm::Int32) this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32) this->Internals->Canvas->GetHeight();
this->Internals->RayCamera.SetParameters(camera, width, height);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.GetCamera() = this->Internals->RayCamera;
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);

@ -107,11 +107,13 @@ void MapperRayTracer::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
vtkm::Int32 width = (vtkm::Int32) this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32) this->Internals->Canvas->GetHeight();
this->Internals->RayCamera.SetParameters(camera, width, height);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Tracer.GetCamera() = this->Internals->RayCamera;
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);

@ -47,8 +47,6 @@ public:
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
struct RenderFunctor;
};
}
} //namespace vtkm::rendering

@ -14,7 +14,6 @@
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
@ -103,7 +102,10 @@ void MapperVolume::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
vtkm::rendering::raytracing::Camera rayCamera;
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
rayCamera.SetParameters(camera, *this->Internals->Canvas);
vtkm::Int32 width = (vtkm::Int32) this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32) this->Internals->Canvas->GetHeight();
rayCamera.SetParameters(camera, width, height);
rayCamera.CreateRays(rays, coords.GetBounds());
rays.Buffers.at(0).InitConst(0.f);

@ -115,7 +115,9 @@ struct EdgesCounter : public vtkm::worklet::WorkletVisitCellsWithPoints
}
else
{
return vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, *this);
vtkm::IdComponent numEdges;
vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges);
return numEdges;
}
}
}; // struct EdgesCounter
@ -149,10 +151,13 @@ struct EdgesExtracter : public vtkm::worklet::WorkletVisitCellsWithPoints
}
else
{
p1 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
pointIndices.GetNumberOfComponents(), 0, visitIndex, shape, *this)];
p2 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
pointIndices.GetNumberOfComponents(), 1, visitIndex, shape, *this)];
vtkm::IdComponent localEdgeIndex;
vtkm::exec::CellEdgeLocalIndex(
pointIndices.GetNumberOfComponents(), 0, visitIndex, shape, localEdgeIndex);
p1 = pointIndices[localEdgeIndex];
vtkm::exec::CellEdgeLocalIndex(
pointIndices.GetNumberOfComponents(), 1, visitIndex, shape, localEdgeIndex);
p2 = pointIndices[localEdgeIndex];
}
// These indices need to be arranged in a definite order, as they will later be sorted to
// detect duplicates

@ -0,0 +1,217 @@
//============================================================================
// 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/rendering/ScalarRenderer.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/ScalarRenderer.h>
#include <vtkm/rendering/raytracing/SphereExtractor.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
namespace vtkm
{
namespace rendering
{
struct ScalarRenderer::InternalsType
{
bool ValidDataSet;
vtkm::Int32 Width;
vtkm::Int32 Height;
vtkm::Float32 DefaultValue;
vtkm::cont::DataSet DataSet;
vtkm::rendering::raytracing::ScalarRenderer Tracer;
vtkm::Bounds ShapeBounds;
VTKM_CONT
InternalsType()
: ValidDataSet(false)
, Width(1024)
, Height(1024)
, DefaultValue(vtkm::Nan32())
{
}
};
ScalarRenderer::ScalarRenderer()
: Internals(new InternalsType)
{
}
ScalarRenderer::~ScalarRenderer()
{
}
void ScalarRenderer::SetWidth(const vtkm::Int32 width)
{
if (width < 1)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: width must be greater than 0");
}
Internals->Width = width;
}
void ScalarRenderer::SetDefaultValue(const vtkm::Float32 value)
{
Internals->DefaultValue = value;
}
void ScalarRenderer::SetHeight(const vtkm::Int32 height)
{
if (height < 1)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: height must be greater than 0");
}
Internals->Height = height;
}
void ScalarRenderer::SetInput(vtkm::cont::DataSet& dataSet)
{
this->Internals->DataSet = dataSet;
this->Internals->ValidDataSet = true;
raytracing::TriangleExtractor triExtractor;
vtkm::cont::DynamicCellSet cellSet = this->Internals->DataSet.GetCellSet();
vtkm::cont::CoordinateSystem coords = this->Internals->DataSet.GetCoordinateSystem();
triExtractor.ExtractCells(cellSet);
if (triExtractor.GetNumberOfTriangles() > 0)
{
auto triIntersector = std::make_shared<raytracing::TriangleIntersector>();
triIntersector->SetData(coords, triExtractor.GetTriangles());
this->Internals->Tracer.SetShapeIntersector(triIntersector);
this->Internals->ShapeBounds = triIntersector->GetShapeBounds();
}
}
ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& camera)
{
if (!Internals->ValidDataSet)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: input never set");
}
raytracing::Logger* logger = raytracing::Logger::GetInstance();
logger->OpenLogEntry("scalar_render");
vtkm::cont::Timer tot_timer;
tot_timer.Start();
vtkm::cont::Timer timer;
timer.Start();
//
// Create rays
//
vtkm::rendering::raytracing::Camera cam;
cam.SetParameters(camera, this->Internals->Width, this->Internals->Height);
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
cam.CreateRays(rays, this->Internals->ShapeBounds);
rays.Buffers.at(0).InitConst(0.f);
// add fields
const vtkm::Id numFields = this->Internals->DataSet.GetNumberOfFields();
std::map<std::string, vtkm::Range> rangeMap;
for (vtkm::Id i = 0; i < numFields; ++i)
{
vtkm::cont::Field field = this->Internals->DataSet.GetField(i);
vtkm::cont::ArrayHandle<vtkm::Range> ranges;
ranges = field.GetRange();
vtkm::Id comps = ranges.GetNumberOfValues();
if (comps == 1)
{
rangeMap[field.GetName()] = ranges.ReadPortal().Get(0);
this->Internals->Tracer.AddField(field);
}
}
this->Internals->Tracer.Render(rays, Internals->DefaultValue);
using ArrayF32 = vtkm::cont::ArrayHandle<vtkm::Float32>;
std::vector<ArrayF32> res;
std::vector<std::string> names;
const size_t numBuffers = rays.Buffers.size();
vtkm::Id expandSize = Internals->Width * Internals->Height;
for (size_t i = 0; i < numBuffers; ++i)
{
const std::string name = rays.Buffers[i].GetName();
if (name == "default")
continue;
raytracing::ChannelBuffer<vtkm::Float32> buffer = rays.Buffers[i];
raytracing::ChannelBuffer<vtkm::Float32> expanded =
buffer.ExpandBuffer(rays.PixelIdx, expandSize, Internals->DefaultValue);
res.push_back(expanded.Buffer);
names.push_back(name);
}
raytracing::ChannelBuffer<vtkm::Float32> depthChannel(1, rays.NumRays);
depthChannel.Buffer = rays.Distance;
raytracing::ChannelBuffer<vtkm::Float32> depthExpanded =
depthChannel.ExpandBuffer(rays.PixelIdx, expandSize, Internals->DefaultValue);
Result result;
result.Width = Internals->Width;
result.Height = Internals->Height;
result.Scalars = res;
result.ScalarNames = names;
result.Ranges = rangeMap;
result.Depths = depthExpanded.Buffer;
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("write_to_canvas", time);
time = tot_timer.GetElapsedTime();
logger->CloseLogEntry(time);
return result;
}
vtkm::cont::DataSet ScalarRenderer::Result::ToDataSet()
{
if (Scalars.size() == 0)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: result empty");
}
VTKM_ASSERT(Width > 0);
VTKM_ASSERT(Height > 0);
vtkm::cont::DataSet result;
vtkm::Vec<vtkm::Float32, 3> origin(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::Float32, 3> spacing(1.f, 1.f, 1.f);
vtkm::Id3 dims(Width + 1, Height + 1, 1);
result.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", dims, origin, spacing));
vtkm::Id2 dims2(dims[0], dims[1]);
vtkm::cont::CellSetStructured<2> resCellSet;
resCellSet.SetPointDimensions(dims2);
result.SetCellSet(resCellSet);
const size_t fieldSize = Scalars.size();
for (size_t i = 0; i < fieldSize; ++i)
{
result.AddField(
vtkm::cont::Field(ScalarNames[i], vtkm::cont::Field::Association::CELL_SET, Scalars[i]));
}
result.AddField(vtkm::cont::Field("depth", vtkm::cont::Field::Association::CELL_SET, Depths));
return result;
}
}
} // vtkm::rendering

@ -0,0 +1,58 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_rendering_ScalarRenderer_h
#define vtk_m_rendering_ScalarRenderer_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/Camera.h>
#include <memory>
namespace vtkm
{
namespace rendering
{
class VTKM_RENDERING_EXPORT ScalarRenderer
{
public:
ScalarRenderer();
~ScalarRenderer();
void SetInput(vtkm::cont::DataSet& dataSet);
void SetWidth(const vtkm::Int32 width);
void SetHeight(const vtkm::Int32 height);
void SetDefaultValue(vtkm::Float32 value);
struct VTKM_RENDERING_EXPORT Result
{
vtkm::Int32 Width;
vtkm::Int32 Height;
vtkm::cont::ArrayHandle<vtkm::Float32> Depths;
std::vector<vtkm::cont::ArrayHandle<vtkm::Float32>> Scalars;
std::vector<std::string> ScalarNames;
std::map<std::string, vtkm::Range> Ranges;
vtkm::cont::DataSet ToDataSet();
};
ScalarRenderer::Result Render(const vtkm::rendering::Camera& camera);
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
};
}
} //namespace vtkm::rendering
#endif //vtk_m_rendering_ScalarRenderer_h

@ -33,6 +33,7 @@ set(headers
RayTracer.h
RayTracingTypeDefs.h
Sampler.h
ScalarRenderer.h
ShapeIntersector.h
SphereExtractor.h
SphereIntersector.h

@ -494,17 +494,31 @@ Camera::~Camera()
VTKM_CONT
void Camera::SetParameters(const vtkm::rendering::Camera& camera,
vtkm::rendering::CanvasRayTracer& canvas)
const vtkm::Int32 width,
const vtkm::Int32 height)
{
this->SetUp(camera.GetViewUp());
this->SetLookAt(camera.GetLookAt());
this->SetPosition(camera.GetPosition());
this->SetZoom(camera.GetZoom());
this->SetFieldOfView(camera.GetFieldOfView());
this->SetHeight(static_cast<vtkm::Int32>(canvas.GetHeight()));
this->SetWidth(static_cast<vtkm::Int32>(canvas.GetWidth()));
this->SetHeight(height);
this->SetWidth(width);
this->CameraView = camera;
}
VTKM_DEPRECATED(1.6, "Use the canvas width and height rather than the canvas itself.")
VTKM_CONT void Camera::SetParameters(const vtkm::rendering::Camera& camera,
vtkm::rendering::CanvasRayTracer& canvas)
{
this->SetUp(camera.GetViewUp());
this->SetLookAt(camera.GetLookAt());
this->SetPosition(camera.GetPosition());
this->SetZoom(camera.GetZoom());
this->SetFieldOfView(camera.GetFieldOfView());
this->SetHeight(vtkm::Int32(canvas.GetHeight()));
this->SetWidth(vtkm::Int32(canvas.GetWidth()));
this->CameraView = camera;
Canvas = canvas;
}

@ -27,7 +27,6 @@ class VTKM_RENDERING_EXPORT Camera
private:
struct PixelDataFunctor;
vtkm::rendering::CanvasRayTracer Canvas;
vtkm::Int32 Height;
vtkm::Int32 Width;
vtkm::Int32 SubsetWidth;
@ -61,8 +60,12 @@ public:
VTKM_CONT
void SetParameters(const vtkm::rendering::Camera& camera,
vtkm::rendering::CanvasRayTracer& canvas);
const vtkm::Int32 width,
const vtkm::Int32 height);
VTKM_CONT
void SetParameters(const vtkm::rendering::Camera& camera,
vtkm::rendering::CanvasRayTracer& canvas);
VTKM_CONT
void SetHeight(const vtkm::Int32& height);

@ -62,12 +62,11 @@ VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints<vtkm::CellShapeTagPyramid>(
return 5;
}
template <typename P, typename S, typename WorkletType, typename CellShapeTagType>
template <typename P, typename S, typename CellShapeTagType>
VTKM_EXEC_CONT inline bool Sample(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const CellShapeTagType& shapeTag)
{
@ -79,9 +78,8 @@ VTKM_EXEC_CONT inline bool Sample(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
pointsVec.Append(points[i]);
scalarVec.Append(scalars[i]);
}
bool success = false; // ignored
vtkm::Vec<P, 3> pcoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
pointsVec, sampleLocation, shapeTag, success, callingWorklet);
vtkm::Vec<P, 3> pcoords;
vtkm::exec::WorldCoordinatesToParametricCoordinates(pointsVec, sampleLocation, shapeTag, pcoords);
P pmin, pmax;
pmin = vtkm::Min(vtkm::Min(pcoords[0], pcoords[1]), pcoords[2]);
pmax = vtkm::Max(vtkm::Max(pcoords[0], pcoords[1]), pcoords[2]);
@ -89,23 +87,22 @@ VTKM_EXEC_CONT inline bool Sample(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
{
validSample = false;
}
lerpedScalar = vtkm::exec::CellInterpolate(scalarVec, pcoords, shapeTag, callingWorklet);
vtkm::exec::CellInterpolate(scalarVec, pcoords, shapeTag, lerpedScalar);
return validSample;
}
template <typename S, typename P, typename WorkletType, typename CellShapeTagType>
template <typename S, typename P, typename CellShapeTagType>
VTKM_EXEC_CONT inline bool Sample(const vtkm::VecAxisAlignedPointCoordinates<3>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const CellShapeTagType& vtkmNotUsed(shapeTag))
{
bool validSample = true;
bool success;
vtkm::Vec<P, 3> pcoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
points, sampleLocation, vtkm::CellShapeTagHexahedron(), success, callingWorklet);
vtkm::Vec<P, 3> pcoords;
vtkm::exec::WorldCoordinatesToParametricCoordinates(
points, sampleLocation, vtkm::CellShapeTagHexahedron(), pcoords);
P pmin, pmax;
pmin = vtkm::Min(vtkm::Min(pcoords[0], pcoords[1]), pcoords[2]);
pmax = vtkm::Max(vtkm::Max(pcoords[0], pcoords[1]), pcoords[2]);
@ -113,8 +110,7 @@ VTKM_EXEC_CONT inline bool Sample(const vtkm::VecAxisAlignedPointCoordinates<3>&
{
validSample = false;
}
lerpedScalar =
vtkm::exec::CellInterpolate(scalars, pcoords, vtkm::CellShapeTagHexahedron(), callingWorklet);
vtkm::exec::CellInterpolate(scalars, pcoords, vtkm::CellShapeTagHexahedron(), lerpedScalar);
return validSample;
}
} // namespace detail
@ -126,12 +122,11 @@ template <int CellType>
class CellSampler
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& vtkmNotUsed(points),
const vtkm::Vec<S, 8>& vtkmNotUsed(scalars),
const vtkm::Vec<P, 3>& vtkmNotUsed(sampleLocation),
S& vtkmNotUsed(lerpedScalar),
const WorkletType& vtkmNotUsed(callingWorklet),
const vtkm::Int32& vtkmNotUsed(cellShape = CellType)) const
{
static_assert(CellType != CELL_SHAPE_ZOO && CellType != CELL_SHAPE_STRUCTURED &&
@ -149,40 +144,35 @@ template <>
class CellSampler<255>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& cellShape) const
{
bool valid = false;
if (cellShape == CELL_SHAPE_HEXAHEDRON)
{
valid = detail::Sample(points,
scalars,
sampleLocation,
lerpedScalar,
callingWorklet,
vtkm::CellShapeTagHexahedron());
valid = detail::Sample(
points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagHexahedron());
}
if (cellShape == CELL_SHAPE_TETRA)
{
valid = detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagTetra());
valid =
detail::Sample(points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagTetra());
}
if (cellShape == CELL_SHAPE_WEDGE)
{
valid = detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagWedge());
valid =
detail::Sample(points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagWedge());
}
if (cellShape == CELL_SHAPE_PYRAMID)
{
valid = detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagPyramid());
valid =
detail::Sample(points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagPyramid());
}
return valid;
}
@ -195,21 +185,16 @@ template <>
class CellSampler<CELL_SHAPE_HEXAHEDRON>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_HEXAHEDRON)) const
{
return detail::Sample(points,
scalars,
sampleLocation,
lerpedScalar,
callingWorklet,
vtkm::CellShapeTagHexahedron());
return detail::Sample(
points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagHexahedron());
}
};
@ -221,22 +206,17 @@ template <>
class CellSampler<CELL_SHAPE_STRUCTURED>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_HEXAHEDRON)) const
{
vtkm::VecAxisAlignedPointCoordinates<3> rPoints(points[0], points[6] - points[0]);
return detail::Sample(rPoints,
scalars,
sampleLocation,
lerpedScalar,
callingWorklet,
vtkm::CellShapeTagHexahedron());
return detail::Sample(
rPoints, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagHexahedron());
}
};
@ -247,17 +227,16 @@ template <>
class CellSampler<CELL_SHAPE_PYRAMID>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_PYRAMID)) const
{
return detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagPyramid());
points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagPyramid());
}
};
@ -269,17 +248,15 @@ template <>
class CellSampler<CELL_SHAPE_TETRA>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_TETRA)) const
{
return detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagTetra());
return detail::Sample(points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagTetra());
}
};
@ -290,17 +267,15 @@ template <>
class CellSampler<CELL_SHAPE_WEDGE>
{
public:
template <typename P, typename S, typename WorkletType>
template <typename P, typename S>
VTKM_EXEC_CONT inline bool SampleCell(
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
const vtkm::Vec<S, 8>& scalars,
const vtkm::Vec<P, 3>& sampleLocation,
S& lerpedScalar,
const WorkletType& callingWorklet,
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_WEDGE)) const
{
return detail::Sample(
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagWedge());
return detail::Sample(points, scalars, sampleLocation, lerpedScalar, vtkm::CellShapeTagWedge());
}
};
}

@ -528,7 +528,7 @@ public:
query_distance += bumpDistance;
vtkm::Vec<FloatType, 3> location = origin + rdir * (query_distance);
vtkm::Vec<vtkm::FloatDefault, 3> pcoords;
locator->FindCell(location, cellId, pcoords, *this);
locator->FindCell(location, cellId, pcoords);
}
currentCell = cellId;
@ -586,7 +586,7 @@ public:
}
}
if (minDistance < maxDistance)
if (minDistance < maxDistance && minDistance > exitDistance)
{
enterDistance = minDistance;
exitDistance = maxDistance;
@ -1091,8 +1091,7 @@ public:
{
vtkm::Vec<FloatType, 3> sampleLoc = origin + currentDistance * dir;
vtkm::Float32 lerpedScalar;
bool validSample =
Sampler.SampleCell(points, scalars, sampleLoc, lerpedScalar, *this, cellShape);
bool validSample = Sampler.SampleCell(points, scalars, sampleLoc, lerpedScalar, cellShape);
if (!validSample)
{
//

@ -30,7 +30,6 @@ protected:
std::vector<std::shared_ptr<ShapeIntersector>> Intersectors;
Camera camera;
vtkm::cont::Field ScalarField;
vtkm::cont::ArrayHandle<vtkm::Float32> Scalars;
vtkm::Id NumberOfShapes;
vtkm::cont::ArrayHandle<vtkm::Vec4f_32> ColorMap;
vtkm::Range ScalarRange;

@ -0,0 +1,218 @@
//============================================================================
// 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/rendering/raytracing/ScalarRenderer.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
template <typename Precision>
class FilterDepth : public vtkm::worklet::WorkletMapField
{
private:
Precision MissScalar;
public:
VTKM_CONT
FilterDepth(const Precision missScalar)
: MissScalar(missScalar)
{
}
typedef void ControlSignature(FieldIn, FieldInOut);
typedef void ExecutionSignature(_1, _2);
VTKM_EXEC void operator()(const vtkm::Id& hitIndex, Precision& scalar) const
{
Precision value = scalar;
if (hitIndex < 0)
{
value = MissScalar;
}
scalar = value;
}
}; //class WriteBuffer
template <typename Precision>
class WriteBuffer : public vtkm::worklet::WorkletMapField
{
private:
Precision MissScalar;
public:
VTKM_CONT
WriteBuffer(const Precision missScalar)
: MissScalar(missScalar)
{
}
typedef void ControlSignature(FieldIn, FieldIn, FieldOut);
typedef void ExecutionSignature(_1, _2, _3);
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
const Precision& scalar,
Precision& output) const
{
Precision value = scalar;
if (hitIndex < 0)
{
value = MissScalar;
}
output = value;
}
}; //class WriteBuffer
template <typename Precision>
class WriteDepthBuffer : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
WriteDepthBuffer() {}
typedef void ControlSignature(FieldIn, FieldOut);
typedef void ExecutionSignature(_1, _2);
VTKM_EXEC void operator()(const Precision& depth, Precision& output) const { output = depth; }
}; //class WriteDepthBuffer
} // namespace detail
ScalarRenderer::ScalarRenderer()
: IntersectorValid(false)
{
}
ScalarRenderer::~ScalarRenderer()
{
}
void ScalarRenderer::SetShapeIntersector(std::shared_ptr<ShapeIntersector> intersector)
{
Intersector = intersector;
IntersectorValid = true;
}
void ScalarRenderer::AddField(const vtkm::cont::Field& scalarField)
{
vtkm::cont::ArrayHandle<vtkm::Range> ranges = scalarField.GetRange();
if (ranges.GetNumberOfValues() != 1)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer(AddField): field must be a scalar");
}
Ranges.push_back(ranges.GetPortalControl().Get(0));
Fields.push_back(scalarField);
}
void ScalarRenderer::Render(Ray<vtkm::Float32>& rays, vtkm::Float32 missScalar)
{
RenderOnDevice(rays, missScalar);
}
void ScalarRenderer::Render(Ray<vtkm::Float64>& rays, vtkm::Float64 missScalar)
{
RenderOnDevice(rays, missScalar);
}
template <typename Precision>
void ScalarRenderer::RenderOnDevice(Ray<Precision>& rays, Precision missScalar)
{
using Timer = vtkm::cont::Timer;
Logger* logger = Logger::GetInstance();
Timer renderTimer;
renderTimer.Start();
vtkm::Float64 time = 0.;
logger->OpenLogEntry("scalar_renderer");
logger->AddLogData("device", GetDeviceString());
logger->AddLogData("num_rays", rays.NumRays);
const size_t numFields = Fields.size();
if (numFields == 0)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: no fields added");
}
if (!IntersectorValid)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: intersector never set");
}
Timer timer;
timer.Start();
Intersector->IntersectRays(rays);
time = timer.GetElapsedTime();
logger->AddLogData("intersect", time);
for (size_t f = 0; f < numFields; ++f)
{
timer.Start();
Intersector->IntersectionData(rays, Fields[f], Ranges[f]);
time = timer.GetElapsedTime();
logger->AddLogData("intersection_data", time);
AddBuffer(rays, missScalar, Fields[f].GetName());
}
vtkm::worklet::DispatcherMapField<detail::FilterDepth<Precision>>(
detail::FilterDepth<Precision>(missScalar))
.Invoke(rays.HitIdx, rays.Distance);
time = renderTimer.GetElapsedTime();
logger->CloseLogEntry(time);
} // RenderOnDevice
template <typename Precision>
void ScalarRenderer::AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string name)
{
const vtkm::Int32 numChannels = 1;
ChannelBuffer<Precision> buffer(numChannels, rays.NumRays);
vtkm::worklet::DispatcherMapField<detail::WriteBuffer<Precision>>(
detail::WriteBuffer<Precision>(missScalar))
.Invoke(rays.HitIdx, rays.Scalar, buffer.Buffer);
buffer.SetName(name);
rays.Buffers.push_back(buffer);
}
template <typename Precision>
void ScalarRenderer::AddDepthBuffer(Ray<Precision>& rays)
{
const vtkm::Int32 numChannels = 1;
ChannelBuffer<Precision> buffer(numChannels, rays.NumRays);
vtkm::worklet::DispatcherMapField<detail::WriteDepthBuffer<Precision>>(
detail::WriteDepthBuffer<Precision>())
.Invoke(rays.Depth, buffer.Buffer);
buffer.SetName("depth");
rays.Buffers.push_back(buffer);
}
}
}
} // namespace vtkm::rendering::raytracing

@ -0,0 +1,66 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_ScalarRenderer_h
#define vtk_m_rendering_raytracing_ScalarRenderer_h
#include <memory>
#include <vector>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT ScalarRenderer
{
protected:
std::shared_ptr<ShapeIntersector> Intersector;
std::vector<vtkm::cont::Field> Fields;
std::vector<vtkm::Range> Ranges;
bool IntersectorValid;
template <typename Precision>
void RenderOnDevice(Ray<Precision>& rays, Precision missScalar);
template <typename Precision>
void AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string name);
template <typename Precision>
void AddDepthBuffer(Ray<Precision>& rays);
public:
VTKM_CONT
ScalarRenderer();
VTKM_CONT
~ScalarRenderer();
VTKM_CONT
void SetShapeIntersector(std::shared_ptr<ShapeIntersector> intersector);
VTKM_CONT
void AddField(const vtkm::cont::Field& scalarField);
VTKM_CONT
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays, vtkm::Float32 missScalar);
VTKM_CONT
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays, vtkm::Float64 missScalar);
}; //class RayTracer
}
}
} // namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_RayTracer_h

@ -24,6 +24,7 @@ set(unit_tests
UnitTestMapperRayTracer.cxx
UnitTestMapperWireframer.cxx
UnitTestMapperVolume.cxx
UnitTestScalarRenderer.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} ALL_BACKENDS LIBRARIES vtkm_rendering)

@ -0,0 +1,43 @@
//============================================================================
// 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/io/writer/VTKDataSetWriter.h>
#include <vtkm/rendering/ScalarRenderer.h>
#include <vtkm/rendering/testing/RenderTest.h>
namespace
{
void RenderTests()
{
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::DataSet dataset = maker.Make3DRegularDataSet0();
vtkm::Bounds bounds = dataset.GetCoordinateSystem().GetBounds();
vtkm::rendering::Camera camera;
camera.ResetToBounds(bounds);
camera.Azimuth(-40.f);
camera.Elevation(15.f);
vtkm::rendering::ScalarRenderer renderer;
renderer.SetInput(dataset);
vtkm::rendering::ScalarRenderer::Result res = renderer.Render(camera);
vtkm::cont::DataSet result = res.ToDataSet();
vtkm::io::writer::VTKDataSetWriter writer("scalar.vtk");
writer.WriteDataSet(result);
}
} //namespace
int UnitTestScalarRenderer(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(RenderTests, argc, argv);
}

@ -37,6 +37,7 @@ set(unit_tests
UnitTestRange.cxx
UnitTestTesting.cxx
UnitTestTransform3D.cxx
UnitTestTuple.cxx
UnitTestTypeList.cxx
UnitTestTypeListTag.cxx
UnitTestTypes.cxx

@ -0,0 +1,383 @@
//============================================================================
// 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 <vtkmstd/integer_sequence.h>
#include <vtkm/testing/Testing.h>
namespace
{
// Do some compile-time testing of vtkmstd::integer_sequence. This is only tangentially
// related to Tuple, but the two are often used together.
template <vtkm::IdComponent... Ns>
using SequenceId = vtkmstd::integer_sequence<vtkm::IdComponent, Ns...>;
template <vtkm::IdComponent N>
using MakeSequenceId = vtkmstd::make_integer_sequence<vtkm::IdComponent, N>;
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<0>, SequenceId<>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<1>, SequenceId<0>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<2>, SequenceId<0, 1>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<3>, SequenceId<0, 1, 2>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<5>, SequenceId<0, 1, 2, 3, 4>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<8>, SequenceId<0, 1, 2, 3, 4, 5, 6, 7>>::value));
VTKM_STATIC_ASSERT(
(std::is_same<MakeSequenceId<13>, SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>>::value));
VTKM_STATIC_ASSERT(
(std::is_same<
MakeSequenceId<21>,
SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<34>,
SequenceId<0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<89>,
SequenceId<0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88>>::value));
template <vtkm::IdComponent Index>
struct TypePlaceholder
{
vtkm::Id X;
TypePlaceholder(vtkm::Id x)
: X(x)
{
}
};
void Check2(TypePlaceholder<0> a0, TypePlaceholder<1> a1)
{
VTKM_TEST_ASSERT(a0.X == TestValue(0, vtkm::Id{}));
VTKM_TEST_ASSERT(a1.X == TestValue(1, vtkm::Id{}));
}
void Check22(TypePlaceholder<0> a0,
TypePlaceholder<1> a1,
TypePlaceholder<2> a2,
TypePlaceholder<3> a3,
TypePlaceholder<4> a4,
TypePlaceholder<5> a5,
TypePlaceholder<6> a6,
TypePlaceholder<7> a7,
TypePlaceholder<8> a8,
TypePlaceholder<9> a9,
TypePlaceholder<10> a10,
TypePlaceholder<11> a11,
TypePlaceholder<12> a12,
TypePlaceholder<13> a13,
TypePlaceholder<14> a14,
TypePlaceholder<15> a15,
TypePlaceholder<16> a16,
TypePlaceholder<17> a17,
TypePlaceholder<18> a18,
TypePlaceholder<19> a19,
TypePlaceholder<20> a20,
TypePlaceholder<21> a21)
{
VTKM_TEST_ASSERT(a0.X == TestValue(0, vtkm::Id{}));
VTKM_TEST_ASSERT(a1.X == TestValue(1, vtkm::Id{}));
VTKM_TEST_ASSERT(a2.X == TestValue(2, vtkm::Id{}));
VTKM_TEST_ASSERT(a3.X == TestValue(3, vtkm::Id{}));
VTKM_TEST_ASSERT(a4.X == TestValue(4, vtkm::Id{}));
VTKM_TEST_ASSERT(a5.X == TestValue(5, vtkm::Id{}));
VTKM_TEST_ASSERT(a6.X == TestValue(6, vtkm::Id{}));
VTKM_TEST_ASSERT(a7.X == TestValue(7, vtkm::Id{}));
VTKM_TEST_ASSERT(a8.X == TestValue(8, vtkm::Id{}));
VTKM_TEST_ASSERT(a9.X == TestValue(9, vtkm::Id{}));
VTKM_TEST_ASSERT(a10.X == TestValue(10, vtkm::Id{}));
VTKM_TEST_ASSERT(a11.X == TestValue(11, vtkm::Id{}));
VTKM_TEST_ASSERT(a12.X == TestValue(12, vtkm::Id{}));
VTKM_TEST_ASSERT(a13.X == TestValue(13, vtkm::Id{}));
VTKM_TEST_ASSERT(a14.X == TestValue(14, vtkm::Id{}));
VTKM_TEST_ASSERT(a15.X == TestValue(15, vtkm::Id{}));
VTKM_TEST_ASSERT(a16.X == TestValue(16, vtkm::Id{}));
VTKM_TEST_ASSERT(a17.X == TestValue(17, vtkm::Id{}));
VTKM_TEST_ASSERT(a18.X == TestValue(18, vtkm::Id{}));
VTKM_TEST_ASSERT(a19.X == TestValue(19, vtkm::Id{}));
VTKM_TEST_ASSERT(a20.X == TestValue(20, vtkm::Id{}));
VTKM_TEST_ASSERT(a21.X == TestValue(21, vtkm::Id{}));
}
struct CheckReturn
{
template <typename Function, typename... Ts>
vtkm::Id operator()(Function f, Ts... args)
{
f(args...);
return vtkm::Id(sizeof...(Ts));
}
};
struct CheckValues
{
vtkm::IdComponent NumChecked = 0;
template <vtkm::IdComponent Index>
void operator()(TypePlaceholder<Index> x)
{
VTKM_TEST_ASSERT(x.X == TestValue(Index, vtkm::Id{}));
this->NumChecked++;
}
};
struct TransformValues
{
vtkm::Id AddValue;
TransformValues(vtkm::Id addValue)
: AddValue(addValue)
{
}
template <vtkm::IdComponent Index>
vtkm::Id operator()(TypePlaceholder<Index> x) const
{
return x.X + this->AddValue;
}
};
void TestTuple2()
{
using TupleType = vtkm::Tuple<TypePlaceholder<0>, TypePlaceholder<1>>;
VTKM_STATIC_ASSERT(vtkm::TupleSize<TupleType>::value == 2);
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<0>, vtkm::TupleElement<0, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<1>, vtkm::TupleElement<1, TupleType>>::value));
TupleType tuple(TestValue(0, vtkm::Id()), TestValue(1, vtkm::Id()));
tuple.Apply(Check2);
vtkm::Id result = tuple.Apply(CheckReturn{}, Check2);
VTKM_TEST_ASSERT(result == 2);
CheckValues checkFunctor;
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 0);
tuple.ForEach(checkFunctor);
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 2);
auto transformedTuple = tuple.Transform(TransformValues{ 10 });
using TransformedTupleType = decltype(transformedTuple);
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<0, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<1, TransformedTupleType>, vtkm::Id>::value));
VTKM_TEST_ASSERT(vtkm::Get<0>(transformedTuple) == TestValue(0, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<1>(transformedTuple) == TestValue(1, vtkm::Id{}) + 10);
}
void TestTuple22()
{
using TupleType = vtkm::Tuple<TypePlaceholder<0>,
TypePlaceholder<1>,
TypePlaceholder<2>,
TypePlaceholder<3>,
TypePlaceholder<4>,
TypePlaceholder<5>,
TypePlaceholder<6>,
TypePlaceholder<7>,
TypePlaceholder<8>,
TypePlaceholder<9>,
TypePlaceholder<10>,
TypePlaceholder<11>,
TypePlaceholder<12>,
TypePlaceholder<13>,
TypePlaceholder<14>,
TypePlaceholder<15>,
TypePlaceholder<16>,
TypePlaceholder<17>,
TypePlaceholder<18>,
TypePlaceholder<19>,
TypePlaceholder<20>,
TypePlaceholder<21>>;
VTKM_STATIC_ASSERT(vtkm::TupleSize<TupleType>::value == 22);
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<0>, vtkm::TupleElement<0, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<1>, vtkm::TupleElement<1, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<20>, vtkm::TupleElement<20, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<21>, vtkm::TupleElement<21, TupleType>>::value));
TupleType tuple(TestValue(0, vtkm::Id()),
TestValue(1, vtkm::Id()),
TestValue(2, vtkm::Id()),
TestValue(3, vtkm::Id()),
TestValue(4, vtkm::Id()),
TestValue(5, vtkm::Id()),
TestValue(6, vtkm::Id()),
TestValue(7, vtkm::Id()),
TestValue(8, vtkm::Id()),
TestValue(9, vtkm::Id()),
TestValue(10, vtkm::Id()),
TestValue(11, vtkm::Id()),
TestValue(12, vtkm::Id()),
TestValue(13, vtkm::Id()),
TestValue(14, vtkm::Id()),
TestValue(15, vtkm::Id()),
TestValue(16, vtkm::Id()),
TestValue(17, vtkm::Id()),
TestValue(18, vtkm::Id()),
TestValue(19, vtkm::Id()),
TestValue(20, vtkm::Id()),
TestValue(21, vtkm::Id()));
tuple.Apply(Check22);
vtkm::Id result = tuple.Apply(CheckReturn{}, Check22);
VTKM_TEST_ASSERT(result == 22);
CheckValues checkFunctor;
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 0);
tuple.ForEach(checkFunctor);
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 22);
auto transformedTuple = tuple.Transform(TransformValues{ 10 });
using TransformedTupleType = decltype(transformedTuple);
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<0, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<1, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<20, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<21, TransformedTupleType>, vtkm::Id>::value));
VTKM_TEST_ASSERT(vtkm::Get<0>(transformedTuple) == TestValue(0, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<1>(transformedTuple) == TestValue(1, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<20>(transformedTuple) == TestValue(20, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<21>(transformedTuple) == TestValue(21, vtkm::Id{}) + 10);
}
void TestTuple()
{
TestTuple2();
TestTuple22();
}
} // anonymous namespace
int UnitTestTuple(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(TestTuple, argc, argv);
}

@ -1,28 +0,0 @@
##============================================================================
## 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.
##============================================================================
add_library(vtkm_taotuple INTERFACE)
vtkm_get_kit_name(kit_name kit_dir)
# taotuple needs C++11
target_compile_features(vtkm_taotuple INTERFACE cxx_std_11)
target_include_directories(vtkm_taotuple INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${VTKm_INSTALL_INCLUDE_DIR}/vtkm/thirdparty/taotuple>)
install(TARGETS vtkm_taotuple
EXPORT ${VTKm_EXPORT_NAME})
## Install headers
if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
install(DIRECTORY vtkmtaotuple
DESTINATION ${VTKm_INSTALL_INCLUDE_DIR}/${kit_dir}/)
endif()

@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -e
set -x
shopt -s dotglob
readonly name="taotuple"
readonly ownership="TaoCpp Tuple Upstream <kwrobot@kitware.com>"
readonly subtree="vtkm/thirdparty/$name/vtkm$name"
readonly repo="https://gitlab.kitware.com/third-party/$name.git"
readonly tag="for/vtk-m"
readonly paths="
include
LICENSE
README.md
"
extract_source () {
git_archive
}
. "${BASH_SOURCE%/*}/../update-common.sh"

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015-2018 Daniel Frey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,43 +0,0 @@
# The Art of C++ / Tuple
[![Release](https://img.shields.io/github/release/taocpp/tuple.svg)](https://github.com/taocpp/tuple/releases/latest)
[![TravisCI](https://travis-ci.org/taocpp/tuple.svg)](https://travis-ci.org/taocpp/tuple)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/9opt30ae579kw19b/branch/master?svg=true)](https://ci.appveyor.com/project/taocpp/tuple)
[The Art of C++](https://taocpp.github.io/) / Tuple is a C++11 header-only reference implementation of
[`std::tuple`](http://en.cppreference.com/w/cpp/utility/tuple).
## Rationale
Why another implementation of `std::tuple`? To provide a proof-of-concept that,
when avoiding recursion, code can benefit in significant ways. I prepared a talk
about it, including some benchmarks.
[Download presentation](https://github.com/taocpp/tuple/blob/master/Variadic%20Templates.pdf)
TL;DR: GCC 5 on Linux with libstdc++'s `std::tuple` requires 19.6s and an instantiation
depth of at least 3.719 to compile an
[example](https://github.com/taocpp/tuple/blob/master/src/test/tuple/tuple_benchmark.cpp)
generating a tuple with 265 elements via `std::tuple_cat`.
`tao::tuple` requires 1.2s and an instantiation depth of 26 on the same system.
Apple LLVM 7.0 (~Clang 3.7) with libc++'s `std::tuple` requires 70s and an instantiation
depth of 514 to compile the example. `tao::tuple` requires 1.7s and an instantiation depth
of 15 on the same system.
## Compatibility
* Requires C++11 or newer.
* Tested with GCC 4.8+ and Clang 3.4+.
## License
The Art of C++ is certified [Open Source](http://www.opensource.org/docs/definition.html) software. It may be used for any purpose, including commercial purposes, at absolutely no cost. It is distributed under the terms of the [MIT license](http://www.opensource.org/licenses/mit-license.html) reproduced here.
> Copyright (c) 2015-2018 Daniel Frey
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -1,498 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef SimpleTuple_h
#define SimpleTuple_h
// A simple tuple implementation for simple compilers.
//
// Most platforms use the taocpp/tuple implementation in thirdparty/taotuple,
// but not all are capable of handling the metaprogramming techniques used.
// This simple recursion-based tuple implementation is used where tao fails.
#include <type_traits>
#include <utility>
#ifndef TAOCPP_ANNOTATION
#ifdef __CUDACC__
#define TAOCPP_ANNOTATION __host__ __device__
#else
#define TAOCPP_ANNOTATION
#endif // __CUDACC__
#endif // TAOCPP_ANNOTATION
// Ignore "calling a __host__ function from a __host__ _device__ function is not allowed" warnings
#ifndef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#ifdef __CUDACC__
#if __CUDAVER__ >= 75000
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma nv_exec_check_disable
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma hd_warning_disable
#endif
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#endif
#endif
namespace simple_tuple
{
namespace detail
{
template <std::size_t Index, typename Head>
class tuple_leaf
{
protected:
Head Value;
public:
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf()
: Value()
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(const Head& value)
: Value(value)
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(const tuple_leaf& o)
: Value(o.Value)
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(tuple_leaf&& o)
: Value(std::move(o.Value))
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template <typename Other>
TAOCPP_ANNOTATION constexpr tuple_leaf(Other&& o)
: Value(std::forward<Other>(o))
{
}
static TAOCPP_ANNOTATION constexpr Head& Get(tuple_leaf& o) noexcept { return o.Value; }
static TAOCPP_ANNOTATION constexpr const Head& Get(const tuple_leaf& o) noexcept
{
return o.Value;
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION
tuple_leaf& operator=(tuple_leaf& o)
{
this->Value = o.Value;
return *this;
}
};
template <std::size_t Index, typename... Ts>
class tuple_impl;
template <std::size_t Idx, typename HeadT, typename... TailTs>
class tuple_impl<Idx, HeadT, TailTs...> : public tuple_impl<Idx + 1, TailTs...>,
private tuple_leaf<Idx, HeadT>
{
public:
using Tail = tuple_impl<Idx + 1, TailTs...>;
using Leaf = tuple_leaf<Idx, HeadT>;
using Head = HeadT;
static const std::size_t Index = Idx;
TAOCPP_ANNOTATION constexpr tuple_impl()
: Tail()
, Leaf()
{
}
explicit TAOCPP_ANNOTATION constexpr tuple_impl(const HeadT& h, const TailTs&... ts)
: Tail(ts...)
, Leaf(h)
{
}
// The enable_if is needed to ensure that tail lengths match (otherwise empty
// constructors would be called).
template <typename OHeadT,
typename... OTailTs,
typename = typename std::enable_if<sizeof...(TailTs) == sizeof...(OTailTs)>::type>
explicit TAOCPP_ANNOTATION constexpr tuple_impl(OHeadT&& h, OTailTs&&... ts)
: Tail(std::forward<OTailTs>(ts)...)
, Leaf(std::forward<OHeadT>(h))
{
}
constexpr tuple_impl(const tuple_impl&) = default;
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl&& o)
: Tail(std::move(GetTail(o)))
, Leaf(std::forward<Head>(GetHead(o)))
{
}
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl<Idx, Ts...>& o)
: Tail(tuple_impl<Idx, Ts...>::GetTail(o))
, Leaf(tuple_impl<Idx, Ts...>::GetHead(o))
{
}
template <typename OHead, typename... OTailTs>
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl<Idx, OHead, OTailTs...>&& o)
: Tail(std::move(tuple_impl<Idx, OHead, OTailTs...>::GetTail(o)))
, Leaf(std::forward<OHead>(tuple_impl<Idx, OHead, OTailTs...>::GetHead(o)))
{
}
TAOCPP_ANNOTATION
tuple_impl& operator=(const tuple_impl& o)
{
GetHead(*this) = GetHead(o);
GetTail(*this) = GetTail(o);
return *this;
}
TAOCPP_ANNOTATION
tuple_impl& operator=(tuple_impl&& o)
{
GetHead(*this) = std::forward<Head>(GetHead(o));
GetTail(*this) = std::move(GetTail(o));
return *this;
}
template <typename... Ts>
TAOCPP_ANNOTATION tuple_impl& operator=(const tuple_impl<Idx, Ts...>& o)
{
GetHead(*this) = tuple_impl<Idx, Ts...>::GetHead(o);
GetTail(*this) = tuple_impl<Idx, Ts...>::GetTail(o);
return *this;
}
template <typename OHead, typename... OTailTs>
TAOCPP_ANNOTATION tuple_impl& operator=(tuple_impl<Idx, OHead, OTailTs...>&& o)
{
using OtherImpl = tuple_impl<Idx, OHead, OTailTs...>;
GetHead(*this) = std::forward<OHead>(OtherImpl::GetHead(o));
GetTail(*this) = std::move(OtherImpl::GetTail(o));
return *this;
}
static TAOCPP_ANNOTATION constexpr Head& GetHead(tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr const Head& GetHead(const tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<const Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr Tail& GetTail(tuple_impl& o) noexcept
{
return static_cast<Tail&>(o);
}
static TAOCPP_ANNOTATION constexpr const Tail& GetTail(const tuple_impl& o) noexcept
{
return static_cast<const Tail&>(o);
}
};
template <std::size_t Idx, typename HeadT>
class tuple_impl<Idx, HeadT> : private tuple_leaf<Idx, HeadT>
{
public:
using Leaf = tuple_leaf<Idx, HeadT>;
using Head = HeadT;
static const std::size_t Index = Idx;
TAOCPP_ANNOTATION constexpr tuple_impl()
: Leaf()
{
}
explicit TAOCPP_ANNOTATION constexpr tuple_impl(const HeadT& h)
: Leaf(h)
{
}
template <typename OHeadT>
explicit TAOCPP_ANNOTATION constexpr tuple_impl(OHeadT&& h)
: Leaf(std::forward<OHeadT>(h))
{
}
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl& o)
: Leaf(GetHead(o))
{
}
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl&& o)
: Leaf(std::forward<Head>(GetHead(o)))
{
}
template <typename OHeadT>
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl<Idx, OHeadT>& o)
: Leaf(tuple_impl<Idx, OHeadT>::GetHead(o))
{
}
template <typename OHeadT>
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl<Idx, OHeadT>&& o)
: Leaf(std::forward<OHeadT>(tuple_impl<Idx, OHeadT>::GetHead(o)))
{
}
TAOCPP_ANNOTATION
tuple_impl& operator=(const tuple_impl& o)
{
GetHead(*this) = GetHead(o);
return *this;
}
TAOCPP_ANNOTATION
tuple_impl& operator=(tuple_impl&& o)
{
GetHead(*this) = std::forward<Head>(GetHead(o));
return *this;
}
template <typename OHeadT>
TAOCPP_ANNOTATION tuple_impl& operator=(const tuple_impl<Idx, OHeadT>& o)
{
GetHead(*this) = tuple_impl<Idx, OHeadT>::GetHead(o);
return *this;
}
template <typename OHeadT>
TAOCPP_ANNOTATION tuple_impl& operator=(tuple_impl<Idx, OHeadT>&& o)
{
using OtherImpl = tuple_impl<Idx, OHeadT>;
GetHead(*this) = std::forward<OHeadT>(OtherImpl::GetHead(o));
return *this;
}
static TAOCPP_ANNOTATION constexpr Head& GetHead(tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr const Head& GetHead(const tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<const Leaf&>(o));
}
};
template <std::size_t Idx, typename Head, typename... Tail>
TAOCPP_ANNOTATION constexpr Head& get_helper(tuple_impl<Idx, Head, Tail...>& t) noexcept
{
return tuple_impl<Idx, Head, Tail...>::GetHead(t);
}
template <std::size_t Idx, typename Head, typename... Tail>
TAOCPP_ANNOTATION constexpr const Head& get_helper(const tuple_impl<Idx, Head, Tail...>& t) noexcept
{
return tuple_impl<Idx, Head, Tail...>::GetHead(t);
}
// Unassignable stateless type:
struct ignore_impl
{
template <class T>
TAOCPP_ANNOTATION constexpr const ignore_impl& operator=(const T&) const
{
return *this;
}
};
} // end namespace detail
/// Reimplementation of std::tuple with markup for device support.
template <typename... Ts>
class tuple;
template <typename... Ts>
class tuple : public detail::tuple_impl<0, Ts...>
{
using Impl = detail::tuple_impl<0, Ts...>;
public:
TAOCPP_ANNOTATION constexpr tuple()
: Impl()
{
}
TAOCPP_ANNOTATION constexpr explicit tuple(const Ts&... ts)
: Impl(ts...)
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr explicit tuple(const OTs&... ts)
: Impl(ts...)
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr explicit tuple(OTs&&... ts)
: Impl(std::forward<OTs>(ts)...)
{
}
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&& o) = default;
template <typename... OTs>
TAOCPP_ANNOTATION constexpr tuple(const tuple<OTs...>& o)
: Impl(static_cast<detail::tuple_impl<0, OTs...>&>(o))
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr tuple(tuple<OTs...>&& o)
: Impl(static_cast<detail::tuple_impl<0, OTs...>&&>(o))
{
}
TAOCPP_ANNOTATION
tuple& operator=(const tuple& o)
{
this->Impl::operator=(o);
return *this;
}
TAOCPP_ANNOTATION
tuple& operator=(tuple&& o)
{
this->Impl::operator=(std::move(o));
return *this;
}
template <typename... OTs>
TAOCPP_ANNOTATION typename std::enable_if<sizeof...(Ts) == sizeof...(OTs), tuple&>::type
operator=(const tuple<OTs...>& o)
{
this->Impl::operator=(o);
return *this;
}
template <typename... OTs>
TAOCPP_ANNOTATION typename std::enable_if<sizeof...(Ts) == sizeof...(OTs), tuple&>::type
operator=(tuple<OTs...>&& o)
{
this->Impl::operator=(std::move(o));
return *this;
}
};
// Specialize for empty tuple:
template <>
class tuple<>
{
public:
tuple() = default;
};
/// Reimplementation of std::tuple_size with markup for device support.
template <typename TupleType>
struct tuple_size;
template <typename... Ts>
struct tuple_size<tuple<Ts...>>
: public std::integral_constant<std::size_t, static_cast<std::size_t>(sizeof...(Ts))>
{
static const std::size_t value = static_cast<std::size_t>(sizeof...(Ts));
};
/// Reimplementation of std::tuple_element with markup for device support.
template <std::size_t Idx, typename TupleType>
struct tuple_element;
template <std::size_t Idx, typename Head, typename... Tail>
struct tuple_element<Idx, tuple<Head, Tail...>> : public tuple_element<Idx - 1, tuple<Tail...>>
{
};
template <typename Head, typename... Tail>
struct tuple_element<0, tuple<Head, Tail...>>
{
using type = Head;
};
template <std::size_t Idx>
struct tuple_element<Idx, tuple<>>
{
static_assert(Idx < tuple_size<tuple<>>::value, "Tuple index valid.");
};
/// Reimplementation of std::get with markup for device support.
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr const typename tuple_element<Idx, tuple<Ts...>>::type& get(
const tuple<Ts...>& t) noexcept
{
return detail::get_helper<Idx>(t);
}
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr typename tuple_element<Idx, tuple<Ts...>>::type& get(
tuple<Ts...>& t) noexcept
{
return detail::get_helper<Idx>(t);
}
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr typename tuple_element<Idx, tuple<Ts...>>::type&& get(
tuple<Ts...>&& t) noexcept
{
using ResultType = typename tuple_element<Idx, tuple<Ts...>>::type;
return std::forward<ResultType&&>(get<Idx>(t));
}
/// Reimplementation of std::make_tuple with markup for device support.
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple<typename std::decay<Ts>::type...> make_tuple(Ts... ts)
{
using ResultType = tuple<typename std::decay<Ts>::type...>;
return ResultType(std::forward<Ts>(ts)...);
}
/// Reimplementation of std::tie with markup for device support.
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple<Ts&...> tie(Ts&... ts) noexcept
{
return tuple<Ts&...>(ts...);
}
/// Reimplementation of std::ignore with markup for device support.
static const detail::ignore_impl ignore{};
} // end namespace simple_tuple
#endif // SimpleTuple_h

@ -1,58 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef Tuple_h
#define Tuple_h
// tao::tuple is a much more efficient tuple implementation, but it doesn't
// work on MSVC2015. For this compiler, fallback to a simpler implementation.
#if defined(_MSC_VER) && _MSC_VER == 1900
#define TAOCPP_USE_SIMPLE_TUPLE
// There is a bug in apple clang 9.0 that prevents tao-tuple from compiling:
#elif defined(__apple_build_version__) && defined(__clang__) && __clang_major__ == 9 && \
clang_minor == 0
#define TAOCPP_USE_SIMPLE_TUPLE
#endif
#ifdef TAOCPP_USE_SIMPLE_TUPLE
#include "SimpleTuple.h"
#else
#include "tao/tuple/tuple.hpp"
#endif
namespace vtkmstd
{
#ifdef TAOCPP_USE_SIMPLE_TUPLE
using simple_tuple::get;
using simple_tuple::make_tuple;
using simple_tuple::tuple;
using simple_tuple::tuple_element;
using simple_tuple::tuple_size;
#else
using tao::get;
using tao::make_tuple;
using tao::tuple;
using tao::tuple_element;
using tao::tuple_size;
#endif
} // end namespace vtkmstd
#endif // Tuple_h

@ -1,64 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_AT_INDEX_HPP
#define TAO_SEQ_AT_INDEX_HPP
#include <cstddef>
#include "make_integer_sequence.hpp"
namespace tao
{
namespace seq
{
// based on http://talesofcpp.fusionfenix.com/post-22/true-story-efficient-packing
namespace impl
{
template< std::size_t, typename T >
struct indexed
{
using type = T;
};
template< typename, typename... Ts >
struct indexer;
template< std::size_t... Is, typename... Ts >
struct indexer< index_sequence< Is... >, Ts... >
: indexed< Is, Ts >...
{
};
template< std::size_t I, typename T >
indexed< I, T > select( const indexed< I, T >& );
} // namespace impl
template< std::size_t I, typename... Ts >
using at_index = decltype( impl::select< I >( impl::indexer< index_sequence_for< Ts... >, Ts... >() ) );
#ifndef _MSC_VER
template< std::size_t I, typename... Ts >
using at_index_t = typename at_index< I, Ts... >::type;
#else
namespace impl
{
template< typename T >
struct get_type
{
using type = typename T::type;
};
} // namespace impl
template< std::size_t I, typename... Ts >
using at_index_t = typename impl::get_type< at_index< I, Ts... > >::type;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,33 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_CONFIG_HPP
#define TAO_SEQ_CONFIG_HPP
#include <utility>
#ifndef TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#if defined( __cpp_lib_integer_sequence )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#elif defined( _MSC_VER )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#endif
#endif
#ifndef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#if defined( _GLIBCXX_RELEASE ) && ( _GLIBCXX_RELEASE >= 8 ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#elif defined( _MSC_VER ) && ( _MSC_FULL_VER >= 190023918 )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#endif
#endif
#if defined( __cpp_fold_expressions ) && ( !defined( __GNUC__ ) || ( __GNUC__ >= 8 ) )
#define TAO_SEQ_FOLD_EXPRESSIONS
#endif
#endif

@ -1,48 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_EXCLUSIVE_SCAN_HPP
#define TAO_SEQ_EXCLUSIVE_SCAN_HPP
#include <utility>
#include "make_integer_sequence.hpp"
#include "partial_sum.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
template< typename S, typename = make_index_sequence< S::size() > >
struct exclusive_scan;
template< typename S, std::size_t... Is >
struct exclusive_scan< S, index_sequence< Is... > >
{
using type = integer_sequence< typename S::value_type, partial_sum< Is, S >::value... >;
};
} // namespace impl
template< typename T, T... Ns >
struct exclusive_scan
: impl::exclusive_scan< integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
struct exclusive_scan< integer_sequence< T, Ns... > >
: impl::exclusive_scan< integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
using exclusive_scan_t = typename exclusive_scan< T, Ns... >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,36 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_INCLUSIVE_SCAN_HPP
#define TAO_SEQ_INCLUSIVE_SCAN_HPP
#include <utility>
#include "exclusive_scan.hpp"
#include "integer_sequence.hpp"
#include "plus.hpp"
namespace tao
{
namespace seq
{
template< typename T, T... Ns >
struct inclusive_scan
: plus< exclusive_scan_t< T, Ns... >, integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
struct inclusive_scan< integer_sequence< T, Ns... > >
: plus< exclusive_scan_t< integer_sequence< T, Ns... > >, integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
using inclusive_scan_t = typename inclusive_scan< T, Ns... >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,44 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_INTEGER_SEQUENCE_HPP
#define TAO_SEQ_INTEGER_SEQUENCE_HPP
#include <cstddef>
#include <utility>
#include "config.hpp"
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_USE_STD_INTEGER_SEQUENCE
using std::index_sequence;
using std::integer_sequence;
#else
template< typename T, T... Ns >
struct integer_sequence
{
using value_type = T;
static constexpr std::size_t size() noexcept
{
return sizeof...( Ns );
}
};
template< std::size_t... Ns >
using index_sequence = integer_sequence< std::size_t, Ns... >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,36 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_IS_ALL_HPP
#define TAO_SEQ_IS_ALL_HPP
#include "config.hpp"
#ifndef TAO_SEQ_FOLD_EXPRESSIONS
#include "integer_sequence.hpp"
#endif
#include <type_traits>
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
template< bool... Bs >
using is_all = std::integral_constant< bool, ( Bs && ... ) >;
#else
template< bool... Bs >
using is_all = std::integral_constant< bool, std::is_same< integer_sequence< bool, true, Bs... >, integer_sequence< bool, Bs..., true > >::value >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,90 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP
#define TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP
#include <cstddef>
#include <type_traits>
#include <utility>
#include "config.hpp"
#include "integer_sequence.hpp"
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
using std::index_sequence_for;
using std::make_index_sequence;
using std::make_integer_sequence;
#else
namespace impl
{
// we have four instantiations of generate_sequence<>, independent of T or N.
// V is the current bit, E is the end marker - if true, this is the last step.
template< bool V, bool E >
struct generate_sequence;
// last step: generate final integer sequence
template<>
struct generate_sequence< false, true >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = integer_sequence< T, Ns... >;
};
template<>
struct generate_sequence< true, true >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = integer_sequence< T, Ns..., S >;
};
// intermediate step: double existing values, append one more if V is set.
template<>
struct generate_sequence< false, false >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S, Ns..., ( Ns + S )... >;
};
template<>
struct generate_sequence< true, false >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S + 1, Ns..., ( Ns + S )..., 2 * S >;
};
// the final sequence per T/N should be memoized, it will probably be used multiple times.
// also checks the limit and starts the above generator properly.
template< typename T, T N >
struct memoize_sequence
{
static_assert( N < T( 1 << 20 ), "N too large" );
using type = typename generate_sequence< false, false >::template f< T, ( N < T( 1 << 1 ) ) ? T( 1 << 1 ) : ( N < T( 1 << 2 ) ) ? T( 1 << 2 ) : ( N < T( 1 << 3 ) ) ? T( 1 << 3 ) : ( N < T( 1 << 4 ) ) ? T( 1 << 4 ) : ( N < T( 1 << 5 ) ) ? T( 1 << 5 ) : ( N < T( 1 << 6 ) ) ? T( 1 << 6 ) : ( N < T( 1 << 7 ) ) ? T( 1 << 7 ) : ( N < T( 1 << 8 ) ) ? T( 1 << 8 ) : ( N < T( 1 << 9 ) ) ? T( 1 << 9 ) : ( N < T( 1 << 10 ) ) ? T( 1 << 10 ) : T( 1 << 20 ), N, 0 >;
};
} // namespace impl
template< typename T, T N >
using make_integer_sequence = typename impl::memoize_sequence< T, N >::type;
template< std::size_t N >
using make_index_sequence = make_integer_sequence< std::size_t, N >;
template< typename... Ts >
using index_sequence_for = make_index_sequence< sizeof...( Ts ) >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,33 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MAP_HPP
#define TAO_SEQ_MAP_HPP
#include <cstddef>
#include <utility>
#include "integer_sequence.hpp"
#include "select.hpp"
namespace tao
{
namespace seq
{
template< typename, typename >
struct map;
template< std::size_t... Ns, typename M >
struct map< index_sequence< Ns... >, M >
{
using type = integer_sequence< typename M::value_type, select< Ns, M >::value... >;
};
template< typename S, typename M >
using map_t = typename map< S, M >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,35 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MINUS_HPP
#define TAO_SEQ_MINUS_HPP
#include <type_traits>
#include "zip.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
struct minus
{
template< typename T, T A, T B >
using apply = std::integral_constant< T, A - B >;
};
} // namespace impl
template< typename A, typename B >
using minus = zip< impl::minus, A, B >;
template< typename A, typename B >
using minus_t = typename minus< A, B >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,47 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_PARTIAL_SUM_HPP
#define TAO_SEQ_PARTIAL_SUM_HPP
#include <cstddef>
#include <utility>
#include "make_integer_sequence.hpp"
#include "sum.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
template< std::size_t, typename S, typename = make_index_sequence< S::size() > >
struct partial_sum;
template< std::size_t I, typename T, T... Ns, std::size_t... Is >
struct partial_sum< I, integer_sequence< T, Ns... >, index_sequence< Is... > >
: seq::sum< T, ( ( Is < I ) ? Ns : 0 )... >
{
static_assert( I <= sizeof...( Is ), "tao::seq::partial_sum<I, S>: I is out of range" );
};
} // namespace impl
template< std::size_t I, typename T, T... Ns >
struct partial_sum
: impl::partial_sum< I, integer_sequence< T, Ns... > >
{
};
template< std::size_t I, typename T, T... Ns >
struct partial_sum< I, integer_sequence< T, Ns... > >
: impl::partial_sum< I, integer_sequence< T, Ns... > >
{
};
} // namespace seq
} // namespace tao
#endif

Some files were not shown because too many files have changed in this diff Show More