mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-20 11:05:44 +00:00
c2f2c166c0
Fancy array handles being Counting, Implicit, Permutation, Transform, and Zip.
541 lines
19 KiB
C++
541 lines
19 KiB
C++
//=============================================================================
|
|
//
|
|
// 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.
|
|
//
|
|
//=============================================================================
|
|
#ifndef vtk_m_cont_testing_TestingFancyArrayHandles_h
|
|
#define vtk_m_cont_testing_TestingFancyArrayHandles_h
|
|
|
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
|
#include <vtkm/cont/ArrayHandleImplicit.h>
|
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
|
#include <vtkm/cont/ArrayHandleTransform.h>
|
|
#include <vtkm/cont/ArrayHandleZip.h>
|
|
#include <vtkm/VecTraits.h>
|
|
|
|
#include <vtkm/worklet/DispatcherMapField.h>
|
|
#include <vtkm/worklet/WorkletMapField.h>
|
|
|
|
#include <vtkm/cont/testing/Testing.h>
|
|
|
|
namespace fancy_array_detail
|
|
{
|
|
|
|
template<typename T>
|
|
class IncrementBy2
|
|
{
|
|
public:
|
|
VTKM_EXEC_CONT_EXPORT
|
|
IncrementBy2(): Value(0)
|
|
{
|
|
|
|
}
|
|
|
|
VTKM_EXEC_CONT_EXPORT
|
|
explicit IncrementBy2(vtkm::Id index):
|
|
Value(0) //required before we increment
|
|
{
|
|
VTKM_ASSERT_CONT(index >= 0);
|
|
for (vtkm::Id i = 0; i < index; i++)
|
|
{ this->Value++; this->Value++; }
|
|
}
|
|
|
|
VTKM_EXEC_CONT_EXPORT
|
|
IncrementBy2 operator+(const IncrementBy2 &rhs) const
|
|
{
|
|
//don't want to trigger the vtkm::Id constructor
|
|
//when making a copy and cause this to be IncrementBy4
|
|
IncrementBy2 newValue;
|
|
newValue.Value = this->Value + rhs.Value;
|
|
return newValue;
|
|
}
|
|
|
|
VTKM_EXEC_CONT_EXPORT
|
|
bool operator==(const IncrementBy2 &other) const
|
|
{
|
|
return this->Value == other.Value;
|
|
}
|
|
|
|
VTKM_EXEC_CONT_EXPORT
|
|
IncrementBy2 &operator++()
|
|
{
|
|
this->Value++;
|
|
this->Value++;
|
|
return *this;
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
friend std::ostream& operator<<(std::ostream &os, const IncrementBy2 &v)
|
|
{ os << v.Value; return os; }
|
|
|
|
|
|
T Value;
|
|
};
|
|
|
|
template<typename ValueType>
|
|
struct IndexSquared
|
|
{
|
|
VTKM_EXEC_CONT_EXPORT
|
|
ValueType operator()(vtkm::Id i) const
|
|
{ return ValueType( vtkm::dot(i,i) ); }
|
|
};
|
|
|
|
template<typename ValueType>
|
|
struct ValueSquared
|
|
{
|
|
template<typename U>
|
|
VTKM_EXEC_CONT_EXPORT
|
|
ValueType operator()(U u) const
|
|
{ return vtkm::dot(u, u); }
|
|
|
|
template<typename U>
|
|
VTKM_EXEC_CONT_EXPORT
|
|
ValueType operator()( ::fancy_array_detail::IncrementBy2<U> u) const
|
|
{ return ValueType( vtkm::dot(u.Value, u.Value) ); }
|
|
};
|
|
|
|
}
|
|
|
|
namespace vtkm {
|
|
// Allows us to use vec traits with IncrementBy2, will make look like
|
|
// a vector of a single component
|
|
template< typename T >
|
|
struct VecTraits< ::fancy_array_detail::IncrementBy2<T> > :
|
|
public vtkm::internal::VecTraitsBasic< ::fancy_array_detail::IncrementBy2<T> >
|
|
{ };
|
|
}
|
|
|
|
namespace vtkm { namespace testing {
|
|
template<typename T>
|
|
struct TypeName< ::fancy_array_detail::IncrementBy2<T> >
|
|
{
|
|
static std::string Name()
|
|
{
|
|
std::stringstream stream;
|
|
stream << "fancy_array_detail::IncrementBy2< " << TypeName<T>::Name() << " >";
|
|
return stream.str();
|
|
}
|
|
};
|
|
|
|
} }
|
|
|
|
namespace vtkm {
|
|
namespace cont {
|
|
namespace testing {
|
|
|
|
/// This class has a single static member, Run, that tests that all Fancy Array
|
|
/// Handles work with the given DeviceAdapter
|
|
///
|
|
template<class DeviceAdapterTag>
|
|
struct TestingFancyArrayHandles
|
|
{
|
|
|
|
private:
|
|
static const int ARRAY_SIZE = 10;
|
|
|
|
public:
|
|
struct PassThrough : public vtkm::worklet::WorkletMapField
|
|
{
|
|
typedef void ControlSignature(FieldIn<>, FieldOut<>);
|
|
typedef _2 ExecutionSignature(_1);
|
|
|
|
template<class ValueType>
|
|
VTKM_EXEC_EXPORT
|
|
ValueType operator()(const ValueType &inValue) const
|
|
{ return inValue; }
|
|
|
|
};
|
|
|
|
|
|
private:
|
|
struct TestZipAsInput
|
|
{
|
|
template< typename KeyType, typename ValueType >
|
|
VTKM_CONT_EXPORT
|
|
void operator()(vtkm::Pair<KeyType,ValueType> vtkmNotUsed(pair)) const
|
|
{
|
|
typedef vtkm::Pair< KeyType, ValueType > PairType;
|
|
|
|
|
|
KeyType testKeys[ARRAY_SIZE];
|
|
ValueType testValues[ARRAY_SIZE];
|
|
|
|
for(vtkm::Id i=0; i < ARRAY_SIZE; ++i)
|
|
{
|
|
testKeys[i] = KeyType(ARRAY_SIZE - i);
|
|
testValues[i] = ValueType(i);
|
|
}
|
|
vtkm::cont::ArrayHandle< KeyType > keys =
|
|
vtkm::cont::make_ArrayHandle(testKeys, ARRAY_SIZE);
|
|
vtkm::cont::ArrayHandle< ValueType > values =
|
|
vtkm::cont::make_ArrayHandle(testValues, ARRAY_SIZE);
|
|
|
|
vtkm::cont::ArrayHandleZip<
|
|
vtkm::cont::ArrayHandle< KeyType >,
|
|
vtkm::cont::ArrayHandle< ValueType > > zip =
|
|
vtkm::cont::make_ArrayHandleZip(keys, values);
|
|
|
|
vtkm::cont::ArrayHandle< PairType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(zip, result);
|
|
|
|
//verify that the control portal works
|
|
for(int i=0; i < ARRAY_SIZE; ++i)
|
|
{
|
|
const PairType result_v = result.GetPortalConstControl().Get(i);
|
|
const PairType correct_value( KeyType(ARRAY_SIZE - i), ValueType(i) );
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "ArrayHandleZip Failed as input");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
struct TestZipAsOutput
|
|
{
|
|
template< typename KeyType, typename ValueType >
|
|
VTKM_CONT_EXPORT
|
|
void operator()(vtkm::Pair<KeyType,ValueType> vtkmNotUsed(pair)) const
|
|
{
|
|
typedef vtkm::Pair< KeyType, ValueType > PairType;
|
|
|
|
PairType testKeysAndValues[ARRAY_SIZE];
|
|
for(vtkm::Id i=0; i < ARRAY_SIZE; ++i)
|
|
{
|
|
testKeysAndValues[i] = PairType(KeyType(ARRAY_SIZE - i), ValueType(i) );
|
|
}
|
|
vtkm::cont::ArrayHandle< PairType > input =
|
|
vtkm::cont::make_ArrayHandle(testKeysAndValues, ARRAY_SIZE);
|
|
|
|
vtkm::cont::ArrayHandle< KeyType > result_keys;
|
|
vtkm::cont::ArrayHandle< ValueType > result_values;
|
|
vtkm::cont::ArrayHandleZip<
|
|
vtkm::cont::ArrayHandle< KeyType >,
|
|
vtkm::cont::ArrayHandle< ValueType > > result_zip =
|
|
vtkm::cont::make_ArrayHandleZip(result_keys, result_values);
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(input, result_zip);
|
|
|
|
//now the two arrays we have zipped should have data inside them
|
|
for(int i=0; i < ARRAY_SIZE; ++i)
|
|
{
|
|
const KeyType result_key = result_keys.GetPortalConstControl().Get(i);
|
|
const ValueType result_value = result_values.GetPortalConstControl().Get(i);
|
|
|
|
VTKM_TEST_ASSERT(result_key == KeyType(ARRAY_SIZE - i), "ArrayHandleZip Failed as input");
|
|
VTKM_TEST_ASSERT(result_value == ValueType(i), "ArrayHandleZip Failed as input");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TestCountingAsInput
|
|
{
|
|
template< typename ValueType >
|
|
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
|
|
{
|
|
const vtkm::Id length = ARRAY_SIZE;
|
|
|
|
//need to initialize the start value or else vectors will have
|
|
//random values to start
|
|
vtkm::Id initial_value(0);
|
|
const ValueType start = ValueType(initial_value);
|
|
|
|
vtkm::cont::ArrayHandleCounting< ValueType > counting =
|
|
vtkm::cont::make_ArrayHandleCounting(start, length);
|
|
vtkm::cont::ArrayHandle< ValueType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(counting, result);
|
|
|
|
//verify that the control portal works
|
|
for(vtkm::Id i=0; i < length; ++i)
|
|
{
|
|
const ValueType result_v = result.GetPortalConstControl().Get(i);
|
|
const ValueType correct_value = ValueType(initial_value + i);
|
|
const ValueType control_value = counting.GetPortalConstControl().Get(i);
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "Counting Handle Failed");
|
|
VTKM_TEST_ASSERT(result_v == control_value, "Counting Handle Failed");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TestImplicitAsInput
|
|
{
|
|
template< typename ValueType>
|
|
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
|
|
{
|
|
const vtkm::Id length = ARRAY_SIZE;
|
|
typedef ::fancy_array_detail::IndexSquared<ValueType> FunctorType;
|
|
FunctorType functor;
|
|
|
|
vtkm::cont::ArrayHandleImplicit< ValueType, FunctorType > implicit =
|
|
vtkm::cont::make_ArrayHandleImplicit<ValueType>(functor, length);
|
|
|
|
vtkm::cont::ArrayHandle< ValueType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(implicit, result);
|
|
|
|
//verify that the control portal works
|
|
for(vtkm::Id i=0; i < length; ++i)
|
|
{
|
|
const ValueType result_v = result.GetPortalConstControl().Get(i);
|
|
const ValueType correct_value = functor( i );
|
|
const ValueType control_value = implicit.GetPortalConstControl().Get(i);
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "Implicit Handle Failed");
|
|
VTKM_TEST_ASSERT(result_v == control_value, "Implicit Handle Failed");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TestPermutationAsInput
|
|
{
|
|
template< typename ValueType>
|
|
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
|
|
{
|
|
const vtkm::Id length = ARRAY_SIZE;
|
|
|
|
typedef ::fancy_array_detail::IndexSquared<ValueType> FunctorType;
|
|
|
|
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > KeyHandleType;
|
|
typedef vtkm::cont::ArrayHandleImplicit< ValueType,
|
|
FunctorType > ValueHandleType;
|
|
typedef vtkm::cont::ArrayHandlePermutation< KeyHandleType,
|
|
ValueHandleType
|
|
> PermutationHandleType;
|
|
|
|
FunctorType functor;
|
|
for( vtkm::Id start_pos = 0; start_pos < (length-10); start_pos+=10)
|
|
{
|
|
const vtkm::Id counting_length = length - start_pos;
|
|
|
|
KeyHandleType counting =
|
|
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start_pos,
|
|
counting_length);
|
|
|
|
ValueHandleType implicit =
|
|
vtkm::cont::make_ArrayHandleImplicit<ValueType>(functor,
|
|
length);
|
|
|
|
PermutationHandleType permutation =
|
|
vtkm::cont::make_ArrayHandlePermutation(counting,
|
|
implicit);
|
|
|
|
vtkm::cont::ArrayHandle< ValueType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(permutation, result);
|
|
|
|
//verify that the control portal works
|
|
for(vtkm::Id i=0; i <counting_length; ++i)
|
|
{
|
|
const vtkm::Id value_index = i;
|
|
const vtkm::Id key_index = start_pos + i;
|
|
|
|
const ValueType result_v = result.GetPortalConstControl().Get( value_index );
|
|
const ValueType correct_value = implicit.GetPortalConstControl().Get( key_index );
|
|
const ValueType control_value = permutation.GetPortalConstControl().Get( value_index );
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "Implicit Handle Failed");
|
|
VTKM_TEST_ASSERT(result_v == control_value, "Implicit Handle Failed");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TestTransformAsInput
|
|
{
|
|
template< typename ValueType>
|
|
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
|
|
{
|
|
typedef typename vtkm::VecTraits<ValueType>::ComponentType OutputValueType;
|
|
typedef fancy_array_detail::ValueSquared<OutputValueType> FunctorType;
|
|
|
|
const vtkm::Id length = ARRAY_SIZE;
|
|
FunctorType functor;
|
|
|
|
vtkm::cont::ArrayHandle<ValueType> input;
|
|
vtkm::cont::ArrayHandleTransform<
|
|
OutputValueType,
|
|
vtkm::cont::ArrayHandle<ValueType>,
|
|
FunctorType> transformed =
|
|
vtkm::cont::make_ArrayHandleTransform<OutputValueType>(input,
|
|
functor);
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<ValueType>::PortalControl Portal;
|
|
input.Allocate(length);
|
|
Portal portal = input.GetPortalControl();
|
|
vtkm::Id initial_value(length);
|
|
for(vtkm::Id i=0; i < length; ++i)
|
|
{
|
|
portal.Set(i, ValueType(initial_value - i) );
|
|
}
|
|
|
|
vtkm::cont::ArrayHandle< OutputValueType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(transformed, result);
|
|
|
|
//verify that the control portal works
|
|
for(vtkm::Id i=0; i < length; ++i)
|
|
{
|
|
const OutputValueType result_v = result.GetPortalConstControl().Get(i);
|
|
const OutputValueType correct_value = transformed.GetPortalConstControl().Get(i);
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "Transform Handle Failed");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TestCountingTransformAsInput
|
|
{
|
|
template< typename ValueType>
|
|
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
|
|
{
|
|
typedef typename vtkm::VecTraits<ValueType>::ComponentType OutputValueType;
|
|
typedef fancy_array_detail::ValueSquared<OutputValueType> FunctorType;
|
|
|
|
vtkm::Id length = ARRAY_SIZE;
|
|
FunctorType functor;
|
|
|
|
//need to initialize the start value or else vectors will have
|
|
//random values to start
|
|
vtkm::Id initial_value(0);
|
|
const ValueType start = ValueType(initial_value);
|
|
|
|
vtkm::cont::ArrayHandleCounting< ValueType > counting =
|
|
vtkm::cont::make_ArrayHandleCounting(start,
|
|
length);
|
|
|
|
vtkm::cont::ArrayHandleTransform<
|
|
OutputValueType,
|
|
vtkm::cont::ArrayHandleCounting<ValueType>,
|
|
FunctorType>
|
|
countingTransformed =
|
|
vtkm::cont::make_ArrayHandleTransform<OutputValueType>(counting,
|
|
functor);
|
|
|
|
vtkm::cont::ArrayHandle< OutputValueType > result;
|
|
|
|
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
|
|
dispatcher.Invoke(countingTransformed, result);
|
|
|
|
//verify that the control portal works
|
|
for(vtkm::Id i=0; i < length; ++i)
|
|
{
|
|
const OutputValueType result_v = result.GetPortalConstControl().Get(i);
|
|
const OutputValueType correct_value = countingTransformed.GetPortalConstControl().Get(i);
|
|
VTKM_TEST_ASSERT(result_v == correct_value, "Transform Counting Handle Failed");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct ZipTypesToTest
|
|
: vtkm::ListTagBase< vtkm::Pair< vtkm::UInt8, vtkm::Id >,
|
|
vtkm::Pair< vtkm::Int32, vtkm::Vec< vtkm::Float32, 3> >,
|
|
vtkm::Pair< vtkm::Float64, vtkm::Vec< vtkm::UInt8, 4> >,
|
|
vtkm::Pair< vtkm::Vec<vtkm::Float32,3>, vtkm::Vec<vtkm::Int8, 4> >,
|
|
vtkm::Pair< vtkm::Vec<vtkm::Float64,2>, vtkm::Int32 >
|
|
>
|
|
{ };
|
|
|
|
struct HandleTypesToTest
|
|
: vtkm::ListTagBase< vtkm::Int8,
|
|
vtkm::UInt8,
|
|
vtkm::Int32,
|
|
vtkm::Int64,
|
|
vtkm::Vec<vtkm::Int32,2>,
|
|
vtkm::Vec<vtkm::UInt8,4>,
|
|
vtkm::Float32,
|
|
vtkm::Float64,
|
|
vtkm::Vec<vtkm::Float64,3>,
|
|
vtkm::Vec<vtkm::Float32,4>,
|
|
::fancy_array_detail::IncrementBy2 < vtkm::Int32 >,
|
|
::fancy_array_detail::IncrementBy2 < vtkm::Float32 >
|
|
>
|
|
{ };
|
|
|
|
|
|
struct TestAll
|
|
{
|
|
VTKM_CONT_EXPORT void operator()() const
|
|
{
|
|
std::cout << "Doing FancyArrayHandle tests" << std::endl;
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleZip as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestZipAsInput(),
|
|
ZipTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleZip as Output" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestZipAsOutput(),
|
|
ZipTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleCounting as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestCountingAsInput(),
|
|
HandleTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleImplicit as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestImplicitAsInput(),
|
|
HandleTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandlePermutation as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestPermutationAsInput(),
|
|
HandleTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleTransform as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestTransformAsInput(),
|
|
HandleTypesToTest());
|
|
|
|
std::cout << "-------------------------------------------" << std::endl;
|
|
std::cout << "Testing ArrayHandleTransform with Counting as Input" << std::endl;
|
|
vtkm::testing::Testing::TryTypes(
|
|
TestingFancyArrayHandles<DeviceAdapterTag>::TestCountingTransformAsInput(),
|
|
HandleTypesToTest());
|
|
|
|
}
|
|
};
|
|
public:
|
|
|
|
/// Run a suite of tests to check to see if a DeviceAdapter properly supports
|
|
/// all the fancy array handles that vtkm supports. Returns an
|
|
/// error code that can be returned from the main function of a test.
|
|
///
|
|
static VTKM_CONT_EXPORT int Run()
|
|
{
|
|
return vtkm::cont::testing::Testing::Run(TestAll());
|
|
}
|
|
};
|
|
|
|
}
|
|
}
|
|
} // namespace vtkm::cont::testing
|
|
|
|
#endif //vtk_m_cont_testing_TestingFancyArrayHandles_h
|