Merge topic 'iterator_maintainence'
813f5a422 Fixup custom portal iterator logic. 4e13f7706 Fix markup on ArrayPortalStreaming. 4805f08e1 Add host/device markup to IteratorFromArrayPortal. Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Kenneth Moreland <kmorel@sandia.gov> Merge-request: !1929
This commit is contained in:
commit
4bf1eefd83
28
docs/changelog/custom_portal_iterators.md
Normal file
28
docs/changelog/custom_portal_iterators.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Portals may advertise custom iterators
|
||||
|
||||
The `ArrayPortalToIterator` utilities are used to produce STL-style iterators
|
||||
from vtk-m's `ArrayHandle` portals. By default, a facade class is constructed
|
||||
around the portal API, adapting it to an iterator interface.
|
||||
|
||||
However, some portals use iterators internally, or may be able to construct a
|
||||
lightweight iterator easily. For these, it is preferable to directly use the
|
||||
specialized iterators instead of going through the generic facade. A portal may
|
||||
now declare the following optional API to advertise that it has custom
|
||||
iterators:
|
||||
|
||||
```
|
||||
struct MyPortal
|
||||
{
|
||||
using IteratorType = ...; // alias to the portal's specialized iterator type
|
||||
IteratorType GetIteratorBegin(); // Return the begin iterator
|
||||
IteratorType GetIteratorEnd(); // Return the end iterator
|
||||
|
||||
// ...rest of ArrayPortal API...
|
||||
};
|
||||
```
|
||||
|
||||
If these members are present, `ArrayPortalToIterators` will forward the portal's
|
||||
specialized iterators instead of constructing a facade. This works when using
|
||||
the `ArrayPortalToIterators` class directly, and also with the
|
||||
`ArrayPortalToIteratorBegin` and `ArrayPortalToIteratorEnd` convenience
|
||||
functions.
|
@ -74,12 +74,6 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const { return this->Functor(index); }
|
||||
|
||||
using IteratorType =
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<ArrayPortalImplicit<FunctorType>>;
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetIteratorBegin() const { return IteratorType(*this); }
|
||||
|
||||
private:
|
||||
FunctorType Functor;
|
||||
vtkm::Id NumberOfValues;
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
using PortalType = P;
|
||||
using ValueType = typename PortalType::ValueType;
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming()
|
||||
: InputPortal()
|
||||
, BlockIndex(0)
|
||||
@ -38,7 +38,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming(const PortalType& inputPortal,
|
||||
vtkm::Id blockIndex,
|
||||
vtkm::Id blockSize,
|
||||
@ -51,7 +51,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename OtherP>
|
||||
VTKM_CONT ArrayPortalStreaming(const ArrayPortalStreaming<OtherP>& src)
|
||||
VTKM_EXEC_CONT ArrayPortalStreaming(const ArrayPortalStreaming<OtherP>& src)
|
||||
: InputPortal(src.GetPortal())
|
||||
, BlockIndex(src.GetBlockIndex())
|
||||
, BlockSize(src.GetBlockSize())
|
||||
@ -59,10 +59,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->CurBlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const
|
||||
{
|
||||
return this->InputPortal.Get(this->BlockIndex * this->BlockSize + index);
|
||||
@ -70,30 +70,30 @@ public:
|
||||
|
||||
template <typename Writable_ = Writable,
|
||||
typename = typename std::enable_if<Writable_::value>::type>
|
||||
VTKM_CONT void Set(vtkm::Id index, const ValueType& value) const
|
||||
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
|
||||
{
|
||||
this->InputPortal.Set(this->BlockIndex * this->BlockSize + index, value);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
const PortalType& GetPortal() const { return this->InputPortal; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetBlockSize(vtkm::Id blockSize) { this->BlockSize = blockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetBlockIndex(vtkm::Id blockIndex) { this->BlockIndex = blockIndex; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetCurBlockSize(vtkm::Id curBlockSize) { this->CurBlockSize = curBlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetBlockSize() { return this->BlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetBlockIndex() { return this->BlockIndex; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetCurBlockSize() { return this->CurBlockSize; }
|
||||
|
||||
private:
|
||||
|
@ -39,7 +39,6 @@ public:
|
||||
using T = typename ValueType::FirstType;
|
||||
using U = typename ValueType::SecondType;
|
||||
|
||||
using IteratorType = ValueType_;
|
||||
using PortalTypeFirst = PortalTypeFirst_;
|
||||
using PortalTypeSecond = PortalTypeSecond_;
|
||||
|
||||
|
@ -51,6 +51,13 @@ namespace cont
|
||||
/// (e.g., ArrayHandleCast may be casting a read-only OR read-write array), the
|
||||
/// Set method may be conditionally removed using SFINAE.
|
||||
///
|
||||
/// The ArrayPortalToIterators utilities wrap ArrayPortals in STL-style
|
||||
/// iterators. If an ArrayPortal implementation wishes to provide a custom
|
||||
/// iterator type, it may define an IteratorType type alias along with the
|
||||
/// methods `IteratorType GetIteratorBegin()` and
|
||||
/// `IteratorType GetIteratorEnd()`. These are not required members, but if
|
||||
/// present, will allow additional optimizations for certain portals.
|
||||
///
|
||||
template <typename T>
|
||||
class ArrayPortal
|
||||
{
|
||||
|
@ -13,6 +13,17 @@
|
||||
#include <vtkm/cont/ArrayPortal.h>
|
||||
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
|
||||
|
||||
namespace vtkmstd
|
||||
{
|
||||
|
||||
/// Implementation of std::void_t (C++17):
|
||||
/// Allows for specialization of class templates based on members of template
|
||||
/// parameters.
|
||||
template <typename...>
|
||||
using void_t = void;
|
||||
|
||||
} // end namespace vtkmstd
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
@ -31,7 +42,7 @@ namespace cont
|
||||
/// ArrayPortalFromIterator has a specialization to return the original
|
||||
/// iterators.
|
||||
///
|
||||
template <typename PortalType>
|
||||
template <typename PortalType, typename CustomIterSFINAE = void>
|
||||
class ArrayPortalToIterators
|
||||
{
|
||||
public:
|
||||
@ -40,7 +51,7 @@ public:
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
explicit ArrayPortalToIterators(const PortalType& portal)
|
||||
: Portal(portal)
|
||||
{
|
||||
}
|
||||
@ -65,6 +76,34 @@ private:
|
||||
PortalType Portal;
|
||||
};
|
||||
|
||||
// Specialize for custom iterator types:
|
||||
template <typename PortalType>
|
||||
class ArrayPortalToIterators<PortalType, vtkmstd::void_t<typename PortalType::IteratorType>>
|
||||
{
|
||||
public:
|
||||
using IteratorType = typename PortalType::IteratorType;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
explicit ArrayPortalToIterators(const PortalType& portal)
|
||||
: Begin(portal.GetIteratorBegin())
|
||||
, End(portal.GetIteratorEnd())
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetBegin() const { return this->Begin; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetEnd() const { return this->End; }
|
||||
|
||||
private:
|
||||
IteratorType Begin;
|
||||
IteratorType End;
|
||||
};
|
||||
|
||||
/// Convenience function for converting an ArrayPortal to a begin iterator.
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
|
@ -24,6 +24,7 @@ set(unit_tests
|
||||
UnitTestCudaDeviceAdapter.cu
|
||||
UnitTestCudaGeometry.cu
|
||||
UnitTestCudaImplicitFunction.cu
|
||||
UnitTestCudaIterators.cu
|
||||
UnitTestCudaMath.cu
|
||||
UnitTestCudaShareUserProvidedManagedMemory.cu
|
||||
UnitTestCudaPointLocatorUniformGrid.cu
|
||||
|
50
vtkm/cont/cuda/testing/UnitTestCudaIterators.cu
Normal file
50
vtkm/cont/cuda/testing/UnitTestCudaIterators.cu
Normal file
@ -0,0 +1,50 @@
|
||||
//============================================================================
|
||||
// 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/cont/ArrayHandle.h>
|
||||
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// cuda portals created from basic array handles should produce raw device
|
||||
// pointers with ArrayPortalToIterator (see ArrayPortalFromThrust).
|
||||
void TestIteratorSpecialization()
|
||||
{
|
||||
vtkm::cont::ArrayHandle<int> handle;
|
||||
|
||||
auto outputPortal = handle.PrepareForOutput(1, vtkm::cont::DeviceAdapterTagCuda{});
|
||||
auto inputPortal = handle.PrepareForInput(vtkm::cont::DeviceAdapterTagCuda{});
|
||||
auto inPlacePortal = handle.PrepareForInPlace(vtkm::cont::DeviceAdapterTagCuda{});
|
||||
|
||||
auto outputIter = vtkm::cont::ArrayPortalToIteratorBegin(outputPortal);
|
||||
auto inputIter = vtkm::cont::ArrayPortalToIteratorBegin(inputPortal);
|
||||
auto inPlaceIter = vtkm::cont::ArrayPortalToIteratorBegin(inPlacePortal);
|
||||
|
||||
(void)outputIter;
|
||||
(void)inputIter;
|
||||
(void)inPlaceIter;
|
||||
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(outputIter), int*>::value);
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(inputIter), int const*>::value);
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(inPlaceIter), int*>::value);
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
int UnitTestCudaIterators(int argc, char* argv[])
|
||||
{
|
||||
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
|
||||
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
|
||||
return vtkm::cont::testing::Testing::Run(TestIteratorSpecialization, argc, argv);
|
||||
}
|
@ -91,6 +91,16 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
IteratorT GetIteratorBegin() const { return this->BeginIterator; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorT GetIteratorEnd() const
|
||||
{
|
||||
IteratorType iterator = this->BeginIterator;
|
||||
using difference_type = typename std::iterator_traits<IteratorType>::difference_type;
|
||||
iterator += static_cast<difference_type>(this->NumberOfValues);
|
||||
return iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
IteratorT BeginIterator;
|
||||
vtkm::Id NumberOfValues;
|
||||
@ -175,6 +185,16 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
IteratorT GetIteratorBegin() const { return this->BeginIterator; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorT GetIteratorEnd() const
|
||||
{
|
||||
using difference_type = typename std::iterator_traits<IteratorType>::difference_type;
|
||||
IteratorType iterator = this->BeginIterator;
|
||||
iterator += static_cast<difference_type>(this->NumberOfValues);
|
||||
return iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
IteratorT BeginIterator;
|
||||
vtkm::Id NumberOfValues;
|
||||
@ -193,79 +213,4 @@ private:
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
/// Partial specialization of \c ArrayPortalToIterators for \c
|
||||
/// ArrayPortalFromIterators. Returns the original array rather than
|
||||
/// the portal wrapped in an \c IteratorFromArrayPortal.
|
||||
///
|
||||
template <typename IterType>
|
||||
class ArrayPortalToIterators<vtkm::cont::internal::ArrayPortalFromIterators<IterType>>
|
||||
{
|
||||
using PortalType = vtkm::cont::internal::ArrayPortalFromIterators<IterType>;
|
||||
|
||||
public:
|
||||
#if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0)
|
||||
using IteratorType = IterType;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
: Iterator(portal.GetIteratorBegin())
|
||||
, NumberOfValues(portal.GetNumberOfValues())
|
||||
{
|
||||
}
|
||||
|
||||
#else // VTKM_MSVC
|
||||
// The MSVC compiler issues warnings when using raw pointer math when in
|
||||
// debug mode. To keep the compiler happy (and add some safety checks),
|
||||
// wrap the iterator in checked_array_iterator.
|
||||
using IteratorType = stdext::checked_array_iterator<IterType>;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
: Iterator(portal.GetIteratorBegin(), static_cast<size_t>(portal.GetNumberOfValues()))
|
||||
, NumberOfValues(portal.GetNumberOfValues())
|
||||
{
|
||||
}
|
||||
|
||||
#endif // VTKM_MSVC
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetBegin() const { return this->Iterator; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetEnd() const
|
||||
{
|
||||
IteratorType iterator = this->Iterator;
|
||||
using difference_type = typename std::iterator_traits<IteratorType>::difference_type;
|
||||
|
||||
#if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0)
|
||||
std::advance(iterator, static_cast<difference_type>(this->NumberOfValues));
|
||||
#else
|
||||
//Visual Studio checked iterators throw exceptions when you try to advance
|
||||
//nullptr iterators even if the advancement length is zero. So instead
|
||||
//don't do the advancement at all
|
||||
if (this->NumberOfValues > 0)
|
||||
{
|
||||
std::advance(iterator, static_cast<difference_type>(this->NumberOfValues));
|
||||
}
|
||||
#endif
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
IteratorType Iterator;
|
||||
vtkm::Id NumberOfValues;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif //vtk_m_cont_internal_ArrayPortalFromIterators_h
|
||||
|
@ -35,12 +35,14 @@ public:
|
||||
|
||||
using iter = IteratorFromArrayPortal<ArrayPortalType>;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
IteratorFromArrayPortal()
|
||||
: Portal()
|
||||
, Index(0)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
explicit IteratorFromArrayPortal(const ArrayPortalType& portal, vtkm::Id index = 0)
|
||||
: Portal(portal)
|
||||
, Index(index)
|
||||
@ -49,15 +51,19 @@ public:
|
||||
VTKM_ASSERT(index <= portal.GetNumberOfValues());
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
reference operator*() const { return reference(this->Portal, this->Index); }
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
reference operator->() const { return reference(this->Portal, this->Index); }
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
reference operator[](difference_type idx) const
|
||||
{
|
||||
return reference(this->Portal, this->Index + static_cast<vtkm::Id>(idx));
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter& operator++()
|
||||
{
|
||||
this->Index++;
|
||||
@ -65,8 +71,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter operator++(int) { return iter(this->Portal, this->Index++); }
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter& operator--()
|
||||
{
|
||||
this->Index--;
|
||||
@ -74,8 +82,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter operator--(int) { return iter(this->Portal, this->Index--); }
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter& operator+=(difference_type n)
|
||||
{
|
||||
this->Index += static_cast<vtkm::Id>(n);
|
||||
@ -83,6 +93,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter& operator-=(difference_type n)
|
||||
{
|
||||
this->Index += static_cast<vtkm::Id>(n);
|
||||
@ -90,6 +101,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
iter operator-(difference_type n) const
|
||||
{
|
||||
return iter(this->Portal, this->Index - static_cast<vtkm::Id>(n));
|
||||
@ -100,68 +112,71 @@ public:
|
||||
};
|
||||
|
||||
template <class ArrayPortalType>
|
||||
IteratorFromArrayPortal<ArrayPortalType> make_IteratorBegin(const ArrayPortalType& portal)
|
||||
VTKM_EXEC_CONT IteratorFromArrayPortal<ArrayPortalType> make_IteratorBegin(
|
||||
const ArrayPortalType& portal)
|
||||
{
|
||||
return IteratorFromArrayPortal<ArrayPortalType>(portal, 0);
|
||||
}
|
||||
|
||||
template <class ArrayPortalType>
|
||||
IteratorFromArrayPortal<ArrayPortalType> make_IteratorEnd(const ArrayPortalType& portal)
|
||||
VTKM_EXEC_CONT IteratorFromArrayPortal<ArrayPortalType> make_IteratorEnd(
|
||||
const ArrayPortalType& portal)
|
||||
{
|
||||
return IteratorFromArrayPortal<ArrayPortalType>(portal, portal.GetNumberOfValues());
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator==(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator==(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index == rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator!=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator!=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index != rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator<(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator<(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index < rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator<=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator<=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index <= rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator>(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator>(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index > rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
bool operator>=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT bool operator>=(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index >= rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
std::ptrdiff_t operator-(vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
VTKM_EXEC_CONT std::ptrdiff_t operator-(
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& lhs,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& rhs)
|
||||
{
|
||||
return lhs.Index - rhs.Index;
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> operator+(
|
||||
VTKM_EXEC_CONT vtkm::cont::internal::IteratorFromArrayPortal<PortalType> operator+(
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& iter,
|
||||
std::ptrdiff_t n)
|
||||
{
|
||||
@ -170,7 +185,7 @@ vtkm::cont::internal::IteratorFromArrayPortal<PortalType> operator+(
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> operator+(
|
||||
VTKM_EXEC_CONT vtkm::cont::internal::IteratorFromArrayPortal<PortalType> operator+(
|
||||
std::ptrdiff_t n,
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<PortalType> const& iter)
|
||||
{
|
||||
|
@ -74,10 +74,9 @@ struct TemplatedTests
|
||||
array, array + ARRAY_SIZE);
|
||||
|
||||
std::cout << " Check that ArrayPortalToIterators is not doing indirection." << std::endl;
|
||||
// If you get a compile error here about mismatched types, it might be
|
||||
// that ArrayPortalToIterators is not properly overloaded to return the
|
||||
// original iterator.
|
||||
#if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0)
|
||||
// If you get a compile error here about mismatched types, it might be
|
||||
// that ArrayPortalToIterators is not properly overloaded to return the
|
||||
// original iterator.
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorBegin(portal) == array,
|
||||
"Begin iterator wrong.");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorEnd(portal) == array + ARRAY_SIZE,
|
||||
@ -86,24 +85,6 @@ struct TemplatedTests
|
||||
"Begin const iterator wrong.");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorEnd(const_portal) == array + ARRAY_SIZE,
|
||||
"End const iterator wrong.");
|
||||
#else //VTKM_MSVC
|
||||
// The MSVC compiler issues warnings when using raw pointer math when in
|
||||
// debug mode. To keep the compiler happy (and add some safety checks),
|
||||
// wrap the iterator in checked_array_iterator.
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorBegin(portal) ==
|
||||
stdext::checked_array_iterator<ValueType*>(array, ARRAY_SIZE),
|
||||
"Begin iterator wrong.");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorEnd(portal) ==
|
||||
stdext::checked_array_iterator<ValueType*>(array, ARRAY_SIZE) + ARRAY_SIZE,
|
||||
"End iterator wrong.");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorBegin(const_portal) ==
|
||||
stdext::checked_array_iterator<const ValueType*>(array, ARRAY_SIZE),
|
||||
"Begin const iterator wrong.");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorEnd(const_portal) ==
|
||||
stdext::checked_array_iterator<const ValueType*>(array, ARRAY_SIZE) +
|
||||
ARRAY_SIZE,
|
||||
"End const iterator wrong.");
|
||||
#endif // VTKM_MSVC
|
||||
|
||||
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == ARRAY_SIZE, "Portal array size wrong.");
|
||||
VTKM_TEST_ASSERT(const_portal.GetNumberOfValues() == ARRAY_SIZE,
|
||||
|
@ -163,9 +163,68 @@ struct TestFunctor
|
||||
}
|
||||
};
|
||||
|
||||
// Defines minimal API needed for ArrayPortalToIterators to detect and
|
||||
// use custom iterators:
|
||||
struct SpecializedIteratorAPITestPortal
|
||||
{
|
||||
using IteratorType = int;
|
||||
IteratorType GetIteratorBegin() const { return 32; }
|
||||
IteratorType GetIteratorEnd() const { return 13; }
|
||||
};
|
||||
|
||||
void TestCustomIterator()
|
||||
{
|
||||
std::cout << " Testing custom iterator detection." << std::endl;
|
||||
|
||||
// Dummy portal type for this test:
|
||||
using PortalType = SpecializedIteratorAPITestPortal;
|
||||
using ItersType = vtkm::cont::ArrayPortalToIterators<PortalType>;
|
||||
|
||||
PortalType portal;
|
||||
ItersType iters{ portal };
|
||||
|
||||
VTKM_TEST_ASSERT(
|
||||
std::is_same<typename ItersType::IteratorType, typename PortalType::IteratorType>::value);
|
||||
VTKM_TEST_ASSERT(
|
||||
std::is_same<decltype(iters.GetBegin()), typename PortalType::IteratorType>::value);
|
||||
VTKM_TEST_ASSERT(
|
||||
std::is_same<decltype(iters.GetEnd()), typename PortalType::IteratorType>::value);
|
||||
VTKM_TEST_ASSERT(iters.GetBegin() == 32);
|
||||
VTKM_TEST_ASSERT(iters.GetEnd() == 13);
|
||||
|
||||
// Convenience API, too:
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(vtkm::cont::ArrayPortalToIteratorBegin(portal)),
|
||||
typename PortalType::IteratorType>::value);
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(vtkm::cont::ArrayPortalToIteratorEnd(portal)),
|
||||
typename PortalType::IteratorType>::value);
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorBegin(portal) == 32);
|
||||
VTKM_TEST_ASSERT(vtkm::cont::ArrayPortalToIteratorEnd(portal) == 13);
|
||||
}
|
||||
|
||||
void TestBasicStorageSpecialization()
|
||||
{
|
||||
// Control iterators from basic storage arrays should just be pointers:
|
||||
vtkm::cont::ArrayHandle<int> handle;
|
||||
handle.Allocate(1);
|
||||
|
||||
auto portal = handle.GetPortalControl();
|
||||
auto portalConst = handle.GetPortalConstControl();
|
||||
|
||||
auto iter = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto iterConst = vtkm::cont::ArrayPortalToIteratorBegin(portalConst);
|
||||
|
||||
(void)iter;
|
||||
(void)iterConst;
|
||||
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(iter), int*>::value);
|
||||
VTKM_TEST_ASSERT(std::is_same<decltype(iterConst), int const*>::value);
|
||||
}
|
||||
|
||||
void TestArrayPortalToIterators()
|
||||
{
|
||||
vtkm::testing::Testing::TryTypes(TestFunctor());
|
||||
TestCustomIterator();
|
||||
TestBasicStorageSpecialization();
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
@ -356,73 +356,4 @@ private:
|
||||
}
|
||||
} // namespace vtkm::exec::cuda::internal
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
/// Partial specialization of \c ArrayPortalToIterators for \c
|
||||
/// ArrayPortalFromThrust. Returns the original array rather than
|
||||
/// the portal wrapped in an \c IteratorFromArrayPortal.
|
||||
///
|
||||
template <typename T>
|
||||
class ArrayPortalToIterators<vtkm::exec::cuda::internal::ArrayPortalFromThrust<T>>
|
||||
{
|
||||
using PortalType = vtkm::exec::cuda::internal::ArrayPortalFromThrust<T>;
|
||||
|
||||
public:
|
||||
using IteratorType = typename PortalType::IteratorType;
|
||||
|
||||
VTKM_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
: BIterator(portal.GetIteratorBegin())
|
||||
, EIterator(portal.GetIteratorEnd())
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetBegin() const { return this->BIterator; }
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetEnd() const { return this->EIterator; }
|
||||
|
||||
private:
|
||||
IteratorType BIterator;
|
||||
IteratorType EIterator;
|
||||
vtkm::Id NumberOfValues;
|
||||
};
|
||||
|
||||
/// Partial specialization of \c ArrayPortalToIterators for \c
|
||||
/// ConstArrayPortalFromThrust. Returns the original array rather than
|
||||
/// the portal wrapped in an \c IteratorFromArrayPortal.
|
||||
///
|
||||
template <typename T>
|
||||
class ArrayPortalToIterators<vtkm::exec::cuda::internal::ConstArrayPortalFromThrust<T>>
|
||||
{
|
||||
using PortalType = vtkm::exec::cuda::internal::ConstArrayPortalFromThrust<T>;
|
||||
|
||||
public:
|
||||
using IteratorType = typename PortalType::IteratorType;
|
||||
|
||||
VTKM_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
: BIterator(portal.GetIteratorBegin())
|
||||
, EIterator(portal.GetIteratorEnd())
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetBegin() const { return this->BIterator; }
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetEnd() const { return this->EIterator; }
|
||||
|
||||
private:
|
||||
IteratorType BIterator;
|
||||
IteratorType EIterator;
|
||||
vtkm::Id NumberOfValues;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif //vtk_m_exec_cuda_internal_ArrayPortalFromThrust_h
|
||||
|
Loading…
Reference in New Issue
Block a user