mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-21 03:25:48 +00:00
Merge topic '43-ArrayHandleSwizzle'
030ef573 Add ArrayHandleSwizzle for reordering/removing components from a vec array. Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !857
This commit is contained in:
commit
e1b78a21ea
525
vtkm/cont/ArrayHandleSwizzle.h
Normal file
525
vtkm/cont/ArrayHandleSwizzle.h
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// 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 Sandia Corporation.
|
||||||
|
// Copyright 2017 UT-Battelle, LLC.
|
||||||
|
// Copyright 2017 Los Alamos National Security.
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||||
|
// 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 vtk_m_cont_ArrayHandleSwizzle_h
|
||||||
|
#define vtk_m_cont_ArrayHandleSwizzle_h
|
||||||
|
|
||||||
|
#include <vtkm/VecTraits.h>
|
||||||
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
// If TestValue appears more than once in ComponentMap, IsUnique will be false,
|
||||||
|
// but true if TestValue is unique.
|
||||||
|
template <vtkm::IdComponent TestValue, vtkm::IdComponent... ComponentMap>
|
||||||
|
struct ComponentIsUnique;
|
||||||
|
|
||||||
|
// Terminal case:
|
||||||
|
template <vtkm::IdComponent TestValue, vtkm::IdComponent Head>
|
||||||
|
struct ComponentIsUnique<TestValue, Head>
|
||||||
|
{
|
||||||
|
const static bool IsUnique = TestValue != Head;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Recursive case:
|
||||||
|
template <vtkm::IdComponent TestValue, vtkm::IdComponent Head, vtkm::IdComponent... Tail>
|
||||||
|
struct ComponentIsUnique<TestValue, Head, Tail...>
|
||||||
|
{
|
||||||
|
using Next = ComponentIsUnique<TestValue, Tail...>;
|
||||||
|
const static bool IsUnique = TestValue != Head && Next::IsUnique;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Validate the component map.
|
||||||
|
// All elements must be (1) unique, (2) >= 0, and (3) < InputSize
|
||||||
|
template <vtkm::IdComponent InputSize, vtkm::IdComponent... ComponentMap>
|
||||||
|
struct ValidateComponentMap;
|
||||||
|
|
||||||
|
// Terminal impl:
|
||||||
|
template <vtkm::IdComponent InputSize, vtkm::IdComponent Head>
|
||||||
|
struct ValidateComponentMap<InputSize, Head>
|
||||||
|
{
|
||||||
|
static const bool Valid = Head >= 0 && Head < InputSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Recursive impl:
|
||||||
|
template <vtkm::IdComponent InputSize, vtkm::IdComponent Head, vtkm::IdComponent... Tail>
|
||||||
|
struct ValidateComponentMap<InputSize, Head, Tail...>
|
||||||
|
{
|
||||||
|
using Next = ValidateComponentMap<InputSize, Tail...>;
|
||||||
|
static const bool IsUnique = ComponentIsUnique<Head, Tail...>::IsUnique;
|
||||||
|
static const bool Valid = Head >= 0 && Head < InputSize && IsUnique && Next::Valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
|
||||||
|
/// This class collects metadata for an ArrayHandleSwizzle.
|
||||||
|
template <typename InputValueType, vtkm::IdComponent... ComponentMap>
|
||||||
|
struct ArrayHandleSwizzleTraits
|
||||||
|
{
|
||||||
|
/// The number of elements in the ComponentMap.
|
||||||
|
static const vtkm::IdComponent COUNT = static_cast<vtkm::IdComponent>(sizeof...(ComponentMap));
|
||||||
|
VTKM_STATIC_ASSERT_MSG(COUNT > 0, "Invalid ComponentMap: Cannot swizzle zero components.");
|
||||||
|
|
||||||
|
/// A std::array containing the ComponentMap for runtime querying.
|
||||||
|
using RuntimeComponentMapType = std::array<vtkm::IdComponent, COUNT>;
|
||||||
|
static VTKM_CONSTEXPR RuntimeComponentMapType GenerateRuntimeComponentMap()
|
||||||
|
{
|
||||||
|
return RuntimeComponentMapType{ { ComponentMap... } };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The ValueType of the ArrayHandleSwizzle's internal ArrayHandle.
|
||||||
|
using InputType = InputValueType;
|
||||||
|
|
||||||
|
/// The VecTraits for InputType.
|
||||||
|
using InputTraits = VecTraits<InputType>;
|
||||||
|
|
||||||
|
using Validator = internal::ValidateComponentMap<InputTraits::NUM_COMPONENTS, ComponentMap...>;
|
||||||
|
VTKM_STATIC_ASSERT_MSG(Validator::Valid,
|
||||||
|
"Invalid ComponentMap: Ids in ComponentMap must be unique, positive, and "
|
||||||
|
"less than the number of input components.");
|
||||||
|
|
||||||
|
/// The ComponentType of the ArrayHandleSwizzle.
|
||||||
|
using ComponentType = typename InputTraits::ComponentType;
|
||||||
|
|
||||||
|
/// The ValueType of the ArrayHandleSwizzle.
|
||||||
|
using OutputType = vtkm::Vec<ComponentType, COUNT>;
|
||||||
|
|
||||||
|
// The VecTraits for OutputType.
|
||||||
|
using OutputTraits = VecTraits<OutputType>;
|
||||||
|
|
||||||
|
/// If true, we use all components in the input vector. If false, we'll need
|
||||||
|
/// to make sure to preserve existing values on write.
|
||||||
|
static const bool ALL_COMPS_USED = InputTraits::NUM_COMPONENTS == COUNT;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent... Map>
|
||||||
|
struct GetImpl;
|
||||||
|
|
||||||
|
// Terminal case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head>
|
||||||
|
struct GetImpl<OutputIndex, Head>
|
||||||
|
{
|
||||||
|
VTKM_CONSTEXPR vtkm::IdComponent operator()() const { return OutputIndex == 0 ? Head : -1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Recursive case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head, vtkm::IdComponent... Tail>
|
||||||
|
struct GetImpl<OutputIndex, Head, Tail...>
|
||||||
|
{
|
||||||
|
using Next = GetImpl<OutputIndex - 1, Tail...>;
|
||||||
|
|
||||||
|
VTKM_CONSTEXPR vtkm::IdComponent operator()() const
|
||||||
|
{
|
||||||
|
return OutputIndex == 0 ? Head : Next()();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Get the component from ComponentMap at the specified index as a
|
||||||
|
/// compile-time constant:
|
||||||
|
template <vtkm::IdComponent OutputIndex>
|
||||||
|
static VTKM_CONSTEXPR vtkm::IdComponent Get()
|
||||||
|
{
|
||||||
|
return GetImpl<OutputIndex, ComponentMap...>()();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent... Map>
|
||||||
|
struct SwizzleImpl;
|
||||||
|
|
||||||
|
// Terminal case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head>
|
||||||
|
struct SwizzleImpl<OutputIndex, Head>
|
||||||
|
{
|
||||||
|
static const vtkm::IdComponent InputIndex = Head;
|
||||||
|
|
||||||
|
void operator()(const InputType& in, OutputType& out) const
|
||||||
|
{
|
||||||
|
OutputTraits::SetComponent(out, OutputIndex, InputTraits::GetComponent(in, InputIndex));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Recursive case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head, vtkm::IdComponent... Tail>
|
||||||
|
struct SwizzleImpl<OutputIndex, Head, Tail...>
|
||||||
|
{
|
||||||
|
using Next = SwizzleImpl<OutputIndex + 1, Tail...>;
|
||||||
|
static const vtkm::IdComponent InputIndex = Head;
|
||||||
|
|
||||||
|
void operator()(const InputType& in, OutputType& out) const
|
||||||
|
{
|
||||||
|
OutputTraits::SetComponent(out, OutputIndex, InputTraits::GetComponent(in, InputIndex));
|
||||||
|
Next()(in, out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Swizzle the input type into the output type.
|
||||||
|
static void Swizzle(const InputType& in, OutputType& out)
|
||||||
|
{
|
||||||
|
SwizzleImpl<0, ComponentMap...>()(in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnSwizzle output type --> input type
|
||||||
|
private:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent... Map>
|
||||||
|
struct UnSwizzleImpl;
|
||||||
|
|
||||||
|
// Terminal case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head>
|
||||||
|
struct UnSwizzleImpl<OutputIndex, Head>
|
||||||
|
{
|
||||||
|
static const vtkm::IdComponent InputIndex = Head;
|
||||||
|
|
||||||
|
void operator()(const OutputType& out, InputType& in) const
|
||||||
|
{
|
||||||
|
InputTraits::SetComponent(in, InputIndex, OutputTraits::GetComponent(out, OutputIndex));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Recursive case:
|
||||||
|
template <vtkm::IdComponent OutputIndex, vtkm::IdComponent Head, vtkm::IdComponent... Tail>
|
||||||
|
struct UnSwizzleImpl<OutputIndex, Head, Tail...>
|
||||||
|
{
|
||||||
|
using Next = UnSwizzleImpl<OutputIndex + 1, Tail...>;
|
||||||
|
static const vtkm::IdComponent InputIndex = Head;
|
||||||
|
|
||||||
|
void operator()(const OutputType& out, InputType& in) const
|
||||||
|
{
|
||||||
|
InputTraits::SetComponent(in, InputIndex, OutputTraits::GetComponent(out, OutputIndex));
|
||||||
|
Next()(out, in);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Entry point:
|
||||||
|
public:
|
||||||
|
/// Unswizzle the output type back into the input type.
|
||||||
|
/// @warning If the entire vector is not used, there may be uninitialized
|
||||||
|
/// data in the resulting InputType vector. See ALL_COMPS_USED flag.
|
||||||
|
static void UnSwizzle(const OutputType& out, InputType& in)
|
||||||
|
{
|
||||||
|
UnSwizzleImpl<0, ComponentMap...>()(out, in);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename PortalType, vtkm::IdComponent... ComponentMap>
|
||||||
|
class VTKM_ALWAYS_EXPORT ArrayPortalSwizzle
|
||||||
|
{
|
||||||
|
using Traits = ArrayHandleSwizzleTraits<typename PortalType::ValueType, ComponentMap...>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using ValueType = typename Traits::OutputType;
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
ArrayPortalSwizzle()
|
||||||
|
: Portal()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
ArrayPortalSwizzle(const PortalType& portal)
|
||||||
|
: Portal(portal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
VTKM_EXEC_CONT ArrayPortalSwizzle(const ArrayPortalSwizzle<PortalType, ComponentMap...>& src)
|
||||||
|
: Portal(src.GetPortal())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
vtkm::Id GetNumberOfValues() const { return this->Portal.GetNumberOfValues(); }
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
ValueType Get(vtkm::Id index) const
|
||||||
|
{
|
||||||
|
typename Traits::OutputType result;
|
||||||
|
Traits::Swizzle(this->Portal.Get(index), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
void Set(vtkm::Id index, const ValueType& value) const
|
||||||
|
{
|
||||||
|
SetImpl<!Traits::ALL_COMPS_USED>(this->Portal)(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// If NeedsRead is true, we need to initialize the InputType vector we write
|
||||||
|
// with the current values at @a index to avoid overwriting unused components.
|
||||||
|
template <bool NeedsRead>
|
||||||
|
struct SetImpl
|
||||||
|
{
|
||||||
|
const PortalType& Portal;
|
||||||
|
|
||||||
|
SetImpl(const PortalType& portal)
|
||||||
|
: Portal(portal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const vtkm::Id& index, const ValueType& value)
|
||||||
|
{
|
||||||
|
typename Traits::InputType in;
|
||||||
|
if (NeedsRead)
|
||||||
|
{
|
||||||
|
in = this->Portal.Get(index);
|
||||||
|
}
|
||||||
|
Traits::UnSwizzle(value, in);
|
||||||
|
this->Portal.Set(index, in);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
const PortalType& GetPortal() const { return this->Portal; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PortalType Portal;
|
||||||
|
}; // class ArrayPortalSwizzle
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
template <typename ArrayHandleType, vtkm::IdComponent... ComponentMap>
|
||||||
|
class StorageTagSwizzle
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename ArrayHandleType, vtkm::IdComponent... ComponentMap>
|
||||||
|
class Storage<typename ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType,
|
||||||
|
ComponentMap...>::OutputType,
|
||||||
|
StorageTagSwizzle<ArrayHandleType, ComponentMap...>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PortalType = ArrayPortalSwizzle<typename ArrayHandleType::PortalControl, ComponentMap...>;
|
||||||
|
using PortalConstType =
|
||||||
|
ArrayPortalSwizzle<typename ArrayHandleType::PortalConstControl, ComponentMap...>;
|
||||||
|
using ValueType = typename PortalType::ValueType;
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
Storage()
|
||||||
|
: Valid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
Storage(const ArrayHandleType& array)
|
||||||
|
: Array(array)
|
||||||
|
, Valid(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
PortalConstType GetPortalConst() const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
return PortalConstType(this->Array.GetPortalConstControl());
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
PortalType GetPortal()
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
return PortalType(this->Array.GetPortalControl());
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::Id GetNumberOfValues() const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
return this->Array.GetNumberOfValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void Allocate(vtkm::Id numberOfValues)
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
this->Array.Allocate(numberOfValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void Shrink(vtkm::Id numberOfValues)
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
this->Array.Shrink(numberOfValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void ReleaseResources()
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
this->Array.ReleaseResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
const ArrayHandleType& GetArray() const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(this->Valid);
|
||||||
|
return this->Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArrayHandleType Array;
|
||||||
|
bool Valid;
|
||||||
|
}; // class Storage
|
||||||
|
|
||||||
|
template <typename ArrayHandleType, vtkm::IdComponent... ComponentMap, typename Device>
|
||||||
|
class ArrayTransfer<typename ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType,
|
||||||
|
ComponentMap...>::OutputType,
|
||||||
|
StorageTagSwizzle<ArrayHandleType, ComponentMap...>,
|
||||||
|
Device>
|
||||||
|
{
|
||||||
|
using ArrayExecutionTypes = typename ArrayHandleType::template ExecutionTypes<Device>;
|
||||||
|
using StorageTag = StorageTagSwizzle<ArrayHandleType, ComponentMap...>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using SwizzleTraits =
|
||||||
|
ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType, ComponentMap...>;
|
||||||
|
using ValueType = typename SwizzleTraits::OutputType;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using PortalControl = typename StorageType::PortalType;
|
||||||
|
using PortalConstControl = typename StorageType::PortalConstType;
|
||||||
|
|
||||||
|
using PortalExecution = ArrayPortalSwizzle<typename ArrayExecutionTypes::Portal, ComponentMap...>;
|
||||||
|
using PortalConstExecution =
|
||||||
|
ArrayPortalSwizzle<typename ArrayExecutionTypes::PortalConst, ComponentMap...>;
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
ArrayTransfer(StorageType* storage)
|
||||||
|
: Array(storage->GetArray())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||||
|
{
|
||||||
|
return PortalConstExecution(this->Array.PrepareForInput(Device()));
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||||
|
{
|
||||||
|
return PortalExecution(this->Array.PrepareForInPlace(Device()));
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||||
|
{
|
||||||
|
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device()));
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
|
||||||
|
{
|
||||||
|
// Implementation of this method should be unnecessary. The internal
|
||||||
|
// array handle should automatically retrieve the output data as
|
||||||
|
// necessary.
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void Shrink(vtkm::Id numberOfValues) { this->Array.Shrink(numberOfValues); }
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void ReleaseResources() { this->Array.ReleaseResourcesExecution(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArrayHandleType Array;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont::internal
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
|
||||||
|
/// \brief A fancy ArrayHandle that rearranges and/or removes components of an
|
||||||
|
/// ArrayHandle with a vtkm::Vec ValueType.
|
||||||
|
///
|
||||||
|
/// ArrayHandleSwizzle is a specialization of ArrayHandle. It takes an
|
||||||
|
/// input ArrayHandle with a vtkm::Vec ValueType and a compile-time component
|
||||||
|
/// map and uses this information to create a new array consisting of the
|
||||||
|
/// specified components of the input ArrayHandle in the specified order. So for
|
||||||
|
/// a given index i, ArrayHandleSwizzle looks up the i-th vtkm::Vec in
|
||||||
|
/// the index array and reads or writes to the specified components, leaving all
|
||||||
|
/// other components unmodified. This is done on the fly rather than creating a
|
||||||
|
/// copy of the array.
|
||||||
|
template <typename ArrayHandleType, vtkm::IdComponent... ComponentMap>
|
||||||
|
class ArrayHandleSwizzle : public vtkm::cont::ArrayHandle<
|
||||||
|
typename ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType,
|
||||||
|
ComponentMap...>::OutputType,
|
||||||
|
StorageTagSwizzle<ArrayHandleType, ComponentMap...>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||||
|
ArrayHandleSwizzle,
|
||||||
|
(ArrayHandleSwizzle<ArrayHandleType, ComponentMap...>),
|
||||||
|
(vtkm::cont::ArrayHandle<typename ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType,
|
||||||
|
ComponentMap...>::OutputType,
|
||||||
|
StorageTagSwizzle<ArrayHandleType, ComponentMap...>>));
|
||||||
|
|
||||||
|
using SwizzleTraits =
|
||||||
|
ArrayHandleSwizzleTraits<typename ArrayHandleType::ValueType, ComponentMap...>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VTKM_CONT
|
||||||
|
ArrayHandleSwizzle(const ArrayHandleType& array)
|
||||||
|
: Superclass(StorageType(array))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// make_ArrayHandleSwizzle is convenience function to generate an
|
||||||
|
/// ArrayHandleSwizzle.
|
||||||
|
template <vtkm::IdComponent... ComponentMap, typename ArrayHandleType>
|
||||||
|
VTKM_CONT ArrayHandleSwizzle<ArrayHandleType, ComponentMap...> make_ArrayHandleSwizzle(
|
||||||
|
const ArrayHandleType& array)
|
||||||
|
{
|
||||||
|
return ArrayHandleSwizzle<ArrayHandleType, ComponentMap...>(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont
|
||||||
|
|
||||||
|
#endif // vtk_m_cont_ArrayHandleSwizzle_h
|
@ -33,6 +33,7 @@ set(headers
|
|||||||
ArrayHandlePermutation.h
|
ArrayHandlePermutation.h
|
||||||
ArrayHandleReverse.h
|
ArrayHandleReverse.h
|
||||||
ArrayHandleStreaming.h
|
ArrayHandleStreaming.h
|
||||||
|
ArrayHandleSwizzle.h
|
||||||
ArrayHandleTransform.h
|
ArrayHandleTransform.h
|
||||||
ArrayHandleUniformPointCoordinates.h
|
ArrayHandleUniformPointCoordinates.h
|
||||||
ArrayHandleZip.h
|
ArrayHandleZip.h
|
||||||
|
@ -43,6 +43,7 @@ set(unit_tests
|
|||||||
UnitTestArrayHandleIndex.cxx
|
UnitTestArrayHandleIndex.cxx
|
||||||
UnitTestArrayHandleReverse.cxx
|
UnitTestArrayHandleReverse.cxx
|
||||||
UnitTestArrayHandlePermutation.cxx
|
UnitTestArrayHandlePermutation.cxx
|
||||||
|
UnitTestArrayHandleSwizzle.cxx
|
||||||
UnitTestArrayHandleTransform.cxx
|
UnitTestArrayHandleTransform.cxx
|
||||||
UnitTestArrayHandleUniformPointCoordinates.cxx
|
UnitTestArrayHandleUniformPointCoordinates.cxx
|
||||||
UnitTestArrayHandleConcatenate.cxx
|
UnitTestArrayHandleConcatenate.cxx
|
||||||
|
400
vtkm/cont/testing/UnitTestArrayHandleSwizzle.cxx
Normal file
400
vtkm/cont/testing/UnitTestArrayHandleSwizzle.cxx
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// 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 2015 Sandia Corporation.
|
||||||
|
// Copyright 2015 UT-Battelle, LLC.
|
||||||
|
// Copyright 2015 Los Alamos National Security.
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleSwizzle.h>
|
||||||
|
#include <vtkm/cont/DeviceAdapter.h>
|
||||||
|
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename ValueType>
|
||||||
|
struct SwizzleTests
|
||||||
|
{
|
||||||
|
using SwizzleInputArrayType = vtkm::cont::ArrayHandle<vtkm::Vec<ValueType, 4>>;
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
using SwizzleArrayType = vtkm::cont::ArrayHandleSwizzle<SwizzleInputArrayType, ComponentMap...>;
|
||||||
|
|
||||||
|
using ReferenceComponentArrayType = vtkm::cont::ArrayHandleCounting<ValueType>;
|
||||||
|
using ReferenceArrayType =
|
||||||
|
typename vtkm::cont::ArrayHandleCompositeVectorType<ReferenceComponentArrayType,
|
||||||
|
ReferenceComponentArrayType,
|
||||||
|
ReferenceComponentArrayType,
|
||||||
|
ReferenceComponentArrayType>::type;
|
||||||
|
|
||||||
|
using DeviceTag = VTKM_DEFAULT_DEVICE_ADAPTER_TAG;
|
||||||
|
using Algo = vtkm::cont::DeviceAdapterAlgorithm<DeviceTag>;
|
||||||
|
|
||||||
|
// This is used to build a ArrayHandleSwizzle's internal array.
|
||||||
|
ReferenceArrayType RefArray;
|
||||||
|
|
||||||
|
void ConstructReferenceArray()
|
||||||
|
{
|
||||||
|
// Build the Ref array
|
||||||
|
const vtkm::Id numValues = 32;
|
||||||
|
ReferenceComponentArrayType c1 =
|
||||||
|
vtkm::cont::make_ArrayHandleCounting<ValueType>(3, 2, numValues);
|
||||||
|
ReferenceComponentArrayType c2 =
|
||||||
|
vtkm::cont::make_ArrayHandleCounting<ValueType>(2, 3, numValues);
|
||||||
|
ReferenceComponentArrayType c3 =
|
||||||
|
vtkm::cont::make_ArrayHandleCounting<ValueType>(4, 4, numValues);
|
||||||
|
ReferenceComponentArrayType c4 =
|
||||||
|
vtkm::cont::make_ArrayHandleCounting<ValueType>(1, 3, numValues);
|
||||||
|
|
||||||
|
this->RefArray = vtkm::cont::make_ArrayHandleCompositeVector(c1, 0, c2, 0, c3, 0, c4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwizzleInputArrayType BuildSwizzleInputArray() const
|
||||||
|
{
|
||||||
|
SwizzleInputArrayType result;
|
||||||
|
Algo::Copy(this->RefArray, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
void SanityCheck() const
|
||||||
|
{
|
||||||
|
using Swizzle = SwizzleArrayType<ComponentMap...>;
|
||||||
|
using Traits = typename Swizzle::SwizzleTraits;
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(Traits::COUNT == vtkm::VecTraits<typename Swizzle::ValueType>::NUM_COMPONENTS,
|
||||||
|
"Traits::COUNT invalid.");
|
||||||
|
VTKM_TEST_ASSERT(
|
||||||
|
VTKM_PASS_COMMAS(std::is_same<typename Traits::ComponentType, ValueType>::value),
|
||||||
|
"Traits::ComponentType invalid.");
|
||||||
|
VTKM_TEST_ASSERT(
|
||||||
|
VTKM_PASS_COMMAS(
|
||||||
|
std::is_same<
|
||||||
|
typename Traits::OutputType,
|
||||||
|
vtkm::Vec<ValueType, static_cast<vtkm::IdComponent>(sizeof...(ComponentMap))>>::value),
|
||||||
|
"Traits::OutputType invalid.");
|
||||||
|
|
||||||
|
SwizzleInputArrayType input = this->BuildSwizzleInputArray();
|
||||||
|
SwizzleArrayType<ComponentMap...> swizzle =
|
||||||
|
vtkm::cont::make_ArrayHandleSwizzle<ComponentMap...>(input);
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(input.GetNumberOfValues() == swizzle.GetNumberOfValues(),
|
||||||
|
"Number of values in copied Swizzle array does not match input.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
void ReadTest() const
|
||||||
|
{
|
||||||
|
using Traits = typename SwizzleArrayType<ComponentMap...>::SwizzleTraits;
|
||||||
|
|
||||||
|
// Test that the expected values are read from an Swizzle array.
|
||||||
|
SwizzleInputArrayType input = this->BuildSwizzleInputArray();
|
||||||
|
SwizzleArrayType<ComponentMap...> swizzle =
|
||||||
|
vtkm::cont::make_ArrayHandleSwizzle<ComponentMap...>(input);
|
||||||
|
|
||||||
|
// Test reading the data back in the control env:
|
||||||
|
this->ValidateReadTest<ComponentMap...>(swizzle);
|
||||||
|
|
||||||
|
// Copy the extract array in the execution environment to test reading:
|
||||||
|
vtkm::cont::ArrayHandle<typename Traits::OutputType> execCopy;
|
||||||
|
Algo::Copy(swizzle, execCopy);
|
||||||
|
this->ValidateReadTest<ComponentMap...>(execCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap, typename ArrayHandleType>
|
||||||
|
void ValidateReadTest(ArrayHandleType testArray) const
|
||||||
|
{
|
||||||
|
using Traits = typename SwizzleArrayType<ComponentMap...>::SwizzleTraits;
|
||||||
|
using MapType = typename Traits::RuntimeComponentMapType;
|
||||||
|
const MapType map = Traits::GenerateRuntimeComponentMap();
|
||||||
|
|
||||||
|
using ReferenceVectorType = typename ReferenceArrayType::ValueType;
|
||||||
|
using SwizzleVectorType = typename Traits::OutputType;
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(map.size() == vtkm::VecTraits<SwizzleVectorType>::NUM_COMPONENTS,
|
||||||
|
"Unexpected runtime component map size.");
|
||||||
|
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == this->RefArray.GetNumberOfValues(),
|
||||||
|
"Number of values incorrect in Read test.");
|
||||||
|
|
||||||
|
auto refPortal = this->RefArray.GetPortalConstControl();
|
||||||
|
auto testPortal = testArray.GetPortalConstControl();
|
||||||
|
|
||||||
|
for (vtkm::Id i = 0; i < testArray.GetNumberOfValues(); ++i)
|
||||||
|
{
|
||||||
|
// Manually swizzle the reference vector using the runtime map information:
|
||||||
|
ReferenceVectorType refVec = refPortal.Get(i);
|
||||||
|
SwizzleVectorType refVecSwizzle;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < map.size(); ++j)
|
||||||
|
{
|
||||||
|
refVecSwizzle[static_cast<vtkm::IdComponent>(j)] = refVec[map[j]];
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(test_equal(refVecSwizzle, testPortal.Get(i), 0.),
|
||||||
|
"Invalid value encountered in Read test.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doubles everything in the input portal.
|
||||||
|
template <typename PortalType>
|
||||||
|
struct WriteTestFunctor : vtkm::exec::FunctorBase
|
||||||
|
{
|
||||||
|
PortalType Portal;
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
WriteTestFunctor(const PortalType& portal)
|
||||||
|
: Portal(portal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
void operator()(vtkm::Id index) const { this->Portal.Set(index, this->Portal.Get(index) * 2.); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
void WriteTest() const
|
||||||
|
{
|
||||||
|
// Control test:
|
||||||
|
{
|
||||||
|
SwizzleInputArrayType input = this->BuildSwizzleInputArray();
|
||||||
|
SwizzleArrayType<ComponentMap...> swizzle =
|
||||||
|
vtkm::cont::make_ArrayHandleSwizzle<ComponentMap...>(input);
|
||||||
|
|
||||||
|
WriteTestFunctor<typename SwizzleArrayType<ComponentMap...>::PortalControl> functor(
|
||||||
|
swizzle.GetPortalControl());
|
||||||
|
|
||||||
|
for (vtkm::Id i = 0; i < swizzle.GetNumberOfValues(); ++i)
|
||||||
|
{
|
||||||
|
functor(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ValidateWriteTestArray<ComponentMap...>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exec test:
|
||||||
|
{
|
||||||
|
SwizzleInputArrayType input = this->BuildSwizzleInputArray();
|
||||||
|
SwizzleArrayType<ComponentMap...> swizzle =
|
||||||
|
vtkm::cont::make_ArrayHandleSwizzle<ComponentMap...>(input);
|
||||||
|
|
||||||
|
using Portal =
|
||||||
|
typename SwizzleArrayType<ComponentMap...>::template ExecutionTypes<DeviceTag>::Portal;
|
||||||
|
|
||||||
|
WriteTestFunctor<Portal> functor(swizzle.PrepareForInPlace(DeviceTag()));
|
||||||
|
|
||||||
|
Algo::Schedule(functor, swizzle.GetNumberOfValues());
|
||||||
|
this->ValidateWriteTestArray<ComponentMap...>(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the swizzled components are twice the reference value.
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
void ValidateWriteTestArray(SwizzleInputArrayType testArray) const
|
||||||
|
{
|
||||||
|
using Traits = typename SwizzleArrayType<ComponentMap...>::SwizzleTraits;
|
||||||
|
using MapType = typename Traits::RuntimeComponentMapType;
|
||||||
|
const MapType map = Traits::GenerateRuntimeComponentMap();
|
||||||
|
|
||||||
|
auto refPortal = this->RefArray.GetPortalConstControl();
|
||||||
|
auto portal = testArray.GetPortalConstControl();
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == refPortal.GetNumberOfValues(),
|
||||||
|
"Number of values in write test output do not match input.");
|
||||||
|
|
||||||
|
for (vtkm::Id i = 0; i < portal.GetNumberOfValues(); ++i)
|
||||||
|
{
|
||||||
|
auto value = portal.Get(i);
|
||||||
|
auto refValue = refPortal.Get(i);
|
||||||
|
|
||||||
|
// Double all of the components that appear in the map to replicate the
|
||||||
|
// test result:
|
||||||
|
for (size_t j = 0; j < map.size(); ++j)
|
||||||
|
{
|
||||||
|
refValue[map[j]] *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(test_equal(refValue, value, 0.), "Value mismatch in Write test.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent... ComponentMap>
|
||||||
|
void TestSwizzle() const
|
||||||
|
{
|
||||||
|
this->SanityCheck<ComponentMap...>();
|
||||||
|
this->ReadTest<ComponentMap...>();
|
||||||
|
this->WriteTest<ComponentMap...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
this->ConstructReferenceArray();
|
||||||
|
|
||||||
|
// Enable for full test. We normally test a reduced set of component maps
|
||||||
|
// to keep compile times/sizes down:
|
||||||
|
#if 0
|
||||||
|
this->TestSwizzle<0, 1>();
|
||||||
|
this->TestSwizzle<0, 2>();
|
||||||
|
this->TestSwizzle<0, 3>();
|
||||||
|
this->TestSwizzle<1, 0>();
|
||||||
|
this->TestSwizzle<1, 2>();
|
||||||
|
this->TestSwizzle<1, 3>();
|
||||||
|
this->TestSwizzle<2, 0>();
|
||||||
|
this->TestSwizzle<2, 1>();
|
||||||
|
this->TestSwizzle<2, 3>();
|
||||||
|
this->TestSwizzle<3, 0>();
|
||||||
|
this->TestSwizzle<3, 1>();
|
||||||
|
this->TestSwizzle<3, 2>();
|
||||||
|
this->TestSwizzle<0, 1, 2>();
|
||||||
|
this->TestSwizzle<0, 1, 3>();
|
||||||
|
this->TestSwizzle<0, 2, 1>();
|
||||||
|
this->TestSwizzle<0, 2, 3>();
|
||||||
|
this->TestSwizzle<0, 3, 1>();
|
||||||
|
this->TestSwizzle<0, 3, 2>();
|
||||||
|
this->TestSwizzle<1, 0, 2>();
|
||||||
|
this->TestSwizzle<1, 0, 3>();
|
||||||
|
this->TestSwizzle<1, 2, 0>();
|
||||||
|
this->TestSwizzle<1, 2, 3>();
|
||||||
|
this->TestSwizzle<1, 3, 0>();
|
||||||
|
this->TestSwizzle<1, 3, 2>();
|
||||||
|
this->TestSwizzle<2, 0, 1>();
|
||||||
|
this->TestSwizzle<2, 0, 3>();
|
||||||
|
this->TestSwizzle<2, 1, 0>();
|
||||||
|
this->TestSwizzle<2, 1, 3>();
|
||||||
|
this->TestSwizzle<2, 3, 0>();
|
||||||
|
this->TestSwizzle<2, 3, 1>();
|
||||||
|
this->TestSwizzle<3, 0, 1>();
|
||||||
|
this->TestSwizzle<3, 0, 2>();
|
||||||
|
this->TestSwizzle<3, 1, 0>();
|
||||||
|
this->TestSwizzle<3, 1, 2>();
|
||||||
|
this->TestSwizzle<3, 2, 0>();
|
||||||
|
this->TestSwizzle<3, 2, 1>();
|
||||||
|
this->TestSwizzle<0, 1, 2, 3>();
|
||||||
|
this->TestSwizzle<0, 1, 3, 2>();
|
||||||
|
this->TestSwizzle<0, 2, 1, 3>();
|
||||||
|
this->TestSwizzle<0, 2, 3, 1>();
|
||||||
|
this->TestSwizzle<0, 3, 1, 2>();
|
||||||
|
this->TestSwizzle<0, 3, 2, 1>();
|
||||||
|
this->TestSwizzle<1, 0, 2, 3>();
|
||||||
|
this->TestSwizzle<1, 0, 3, 2>();
|
||||||
|
this->TestSwizzle<1, 2, 0, 3>();
|
||||||
|
this->TestSwizzle<1, 2, 3, 0>();
|
||||||
|
this->TestSwizzle<1, 3, 0, 2>();
|
||||||
|
this->TestSwizzle<1, 3, 2, 0>();
|
||||||
|
this->TestSwizzle<2, 0, 1, 3>();
|
||||||
|
this->TestSwizzle<2, 0, 3, 1>();
|
||||||
|
this->TestSwizzle<2, 1, 0, 3>();
|
||||||
|
this->TestSwizzle<2, 1, 3, 0>();
|
||||||
|
this->TestSwizzle<2, 3, 0, 1>();
|
||||||
|
this->TestSwizzle<2, 3, 1, 0>();
|
||||||
|
this->TestSwizzle<3, 0, 1, 2>();
|
||||||
|
this->TestSwizzle<3, 0, 2, 1>();
|
||||||
|
this->TestSwizzle<3, 1, 0, 2>();
|
||||||
|
this->TestSwizzle<3, 1, 2, 0>();
|
||||||
|
this->TestSwizzle<3, 2, 0, 1>();
|
||||||
|
this->TestSwizzle<3, 2, 1, 0>();
|
||||||
|
#else
|
||||||
|
this->TestSwizzle<0, 1>();
|
||||||
|
this->TestSwizzle<1, 0>();
|
||||||
|
this->TestSwizzle<2, 3>();
|
||||||
|
this->TestSwizzle<3, 2>();
|
||||||
|
this->TestSwizzle<0, 1, 2>();
|
||||||
|
this->TestSwizzle<0, 3, 1>();
|
||||||
|
this->TestSwizzle<2, 0, 3>();
|
||||||
|
this->TestSwizzle<3, 2, 1>();
|
||||||
|
this->TestSwizzle<0, 1, 2, 3>();
|
||||||
|
this->TestSwizzle<1, 3, 2, 0>();
|
||||||
|
this->TestSwizzle<2, 0, 1, 3>();
|
||||||
|
this->TestSwizzle<3, 1, 0, 2>();
|
||||||
|
this->TestSwizzle<3, 2, 1, 0>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArgToTemplateType
|
||||||
|
{
|
||||||
|
template <typename ValueType>
|
||||||
|
void operator()(ValueType) const
|
||||||
|
{
|
||||||
|
SwizzleTests<ValueType>()();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestArrayHandleSwizzle()
|
||||||
|
{
|
||||||
|
using TestTypes = vtkm::ListTagBase<vtkm::Int32, vtkm::Int64, vtkm::Float32, vtkm::Float64>;
|
||||||
|
vtkm::testing::Testing::TryTypes(ArgToTemplateType(), TestTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent InputSize, vtkm::IdComponent... ComponentMap>
|
||||||
|
using Validator = vtkm::cont::internal::ValidateComponentMap<InputSize, ComponentMap...>;
|
||||||
|
|
||||||
|
void TestComponentMapValidator()
|
||||||
|
{
|
||||||
|
using RepeatComps = Validator<5, 0, 3, 2, 3, 1, 4>;
|
||||||
|
VTKM_TEST_ASSERT(!RepeatComps::Valid, "Repeat components allowed.");
|
||||||
|
|
||||||
|
using NegativeComps = Validator<5, 0, 4, -3, 1, 2>;
|
||||||
|
VTKM_TEST_ASSERT(!NegativeComps::Valid, "Negative components allowed.");
|
||||||
|
|
||||||
|
using OutOfBoundsComps = Validator<5, 0, 2, 3, 5>;
|
||||||
|
VTKM_TEST_ASSERT(!OutOfBoundsComps::Valid, "Out-of-bounds components allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRuntimeComponentMapGenerator()
|
||||||
|
{
|
||||||
|
// Dummy input vector type. Only concerned with the component map:
|
||||||
|
using Dummy = vtkm::Vec<char, 7>;
|
||||||
|
|
||||||
|
using Traits = vtkm::cont::ArrayHandleSwizzleTraits<Dummy, 3, 2, 4, 1, 6, 0>;
|
||||||
|
using MapType = Traits::RuntimeComponentMapType;
|
||||||
|
|
||||||
|
const MapType map = Traits::GenerateRuntimeComponentMap();
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(map.size() == 6, "Invalid map size.");
|
||||||
|
VTKM_TEST_ASSERT(map[0] == 3, "Invalid map entry.");
|
||||||
|
VTKM_TEST_ASSERT(map[1] == 2, "Invalid map entry.");
|
||||||
|
VTKM_TEST_ASSERT(map[2] == 4, "Invalid map entry.");
|
||||||
|
VTKM_TEST_ASSERT(map[3] == 1, "Invalid map entry.");
|
||||||
|
VTKM_TEST_ASSERT(map[4] == 6, "Invalid map entry.");
|
||||||
|
VTKM_TEST_ASSERT(map[5] == 0, "Invalid map entry.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end anon namespace
|
||||||
|
|
||||||
|
int UnitTestArrayHandleSwizzle(int, char* [])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TestComponentMapValidator();
|
||||||
|
TestRuntimeComponentMapGenerator();
|
||||||
|
}
|
||||||
|
catch (vtkm::cont::Error& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: " << e.what() << "\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vtkm::cont::testing::Testing::Run(TestArrayHandleSwizzle);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user