1ca55ac319
The ArrayPortalValueReference is supposed to behave just like the value it encapsulates and does so by automatically converting to the base type when necessary. However, when it is possible to convert that to something else, it is possible to get errors about ambiguous overloads. To avoid these, add specialized versions of the operators to specify which ones should be used. Also consolidated the CUDA version of an ArrayPortalValueReference to the standard one. The two implementations were equivalent and we would like changes to apply to both.
292 lines
9.4 KiB
C++
292 lines
9.4 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 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
|
// Copyright 2016 UT-Battelle, LLC.
|
|
// Copyright 2016 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.
|
|
//============================================================================
|
|
|
|
#include <vtkm/internal/ArrayPortalValueReference.h>
|
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
|
|
|
#include <vtkm/TypeTraits.h>
|
|
|
|
#include <vtkm/cont/testing/Testing.h>
|
|
|
|
namespace
|
|
{
|
|
|
|
static constexpr vtkm::Id ARRAY_SIZE = 10;
|
|
|
|
template <typename ArrayPortalType>
|
|
void SetReference(vtkm::Id index, vtkm::internal::ArrayPortalValueReference<ArrayPortalType> ref)
|
|
{
|
|
using ValueType = typename ArrayPortalType::ValueType;
|
|
ref = TestValue(index, ValueType());
|
|
}
|
|
|
|
template <typename ArrayPortalType>
|
|
void CheckReference(vtkm::Id index, vtkm::internal::ArrayPortalValueReference<ArrayPortalType> ref)
|
|
{
|
|
using ValueType = typename ArrayPortalType::ValueType;
|
|
VTKM_TEST_ASSERT(test_equal(ref, TestValue(index, ValueType())), "Got bad value from reference.");
|
|
}
|
|
|
|
template <typename ArrayPortalType>
|
|
void TryOperatorsNoVec(vtkm::Id index,
|
|
vtkm::internal::ArrayPortalValueReference<ArrayPortalType> ref,
|
|
vtkm::TypeTraitsScalarTag)
|
|
{
|
|
using ValueType = typename ArrayPortalType::ValueType;
|
|
|
|
ValueType expected = TestValue(index, ValueType());
|
|
VTKM_TEST_ASSERT(ref.Get() == expected, "Reference did not start out as expected.");
|
|
|
|
VTKM_TEST_ASSERT(!(ref < ref));
|
|
VTKM_TEST_ASSERT(ref < ValueType(expected + ValueType(1)));
|
|
VTKM_TEST_ASSERT(ValueType(expected - ValueType(1)) < ref);
|
|
|
|
VTKM_TEST_ASSERT(!(ref > ref));
|
|
VTKM_TEST_ASSERT(ref > ValueType(expected - ValueType(1)));
|
|
VTKM_TEST_ASSERT(ValueType(expected + ValueType(1)) > ref);
|
|
|
|
VTKM_TEST_ASSERT(ref <= ref);
|
|
VTKM_TEST_ASSERT(ref <= ValueType(expected + ValueType(1)));
|
|
VTKM_TEST_ASSERT(ValueType(expected - ValueType(1)) <= ref);
|
|
|
|
VTKM_TEST_ASSERT(ref >= ref);
|
|
VTKM_TEST_ASSERT(ref >= ValueType(expected - ValueType(1)));
|
|
VTKM_TEST_ASSERT(ValueType(expected + ValueType(1)) >= ref);
|
|
}
|
|
|
|
template <typename ArrayPortalType>
|
|
void TryOperatorsNoVec(vtkm::Id,
|
|
vtkm::internal::ArrayPortalValueReference<ArrayPortalType>,
|
|
vtkm::TypeTraitsVectorTag)
|
|
{
|
|
}
|
|
|
|
template <typename ArrayPortalType>
|
|
void TryOperatorsInt(vtkm::Id index,
|
|
vtkm::internal::ArrayPortalValueReference<ArrayPortalType> ref,
|
|
vtkm::TypeTraitsScalarTag,
|
|
vtkm::TypeTraitsIntegerTag)
|
|
{
|
|
using ValueType = typename ArrayPortalType::ValueType;
|
|
|
|
const ValueType operand = TestValue(ARRAY_SIZE, ValueType());
|
|
ValueType expected = TestValue(index, ValueType());
|
|
VTKM_TEST_ASSERT(ref.Get() == expected, "Reference did not start out as expected.");
|
|
|
|
VTKM_TEST_ASSERT((ref % ref) == (expected % expected));
|
|
VTKM_TEST_ASSERT((ref % expected) == (expected % expected));
|
|
VTKM_TEST_ASSERT((expected % ref) == (expected % expected));
|
|
|
|
VTKM_TEST_ASSERT((ref ^ ref) == (expected ^ expected));
|
|
VTKM_TEST_ASSERT((ref ^ expected) == (expected ^ expected));
|
|
VTKM_TEST_ASSERT((expected ^ ref) == (expected ^ expected));
|
|
|
|
VTKM_TEST_ASSERT((ref | ref) == (expected | expected));
|
|
VTKM_TEST_ASSERT((ref | expected) == (expected | expected));
|
|
VTKM_TEST_ASSERT((expected | ref) == (expected | expected));
|
|
|
|
VTKM_TEST_ASSERT((ref & ref) == (expected & expected));
|
|
VTKM_TEST_ASSERT((ref & expected) == (expected & expected));
|
|
VTKM_TEST_ASSERT((expected & ref) == (expected & expected));
|
|
|
|
VTKM_TEST_ASSERT((ref << ref) == (expected << expected));
|
|
VTKM_TEST_ASSERT((ref << expected) == (expected << expected));
|
|
VTKM_TEST_ASSERT((expected << ref) == (expected << expected));
|
|
|
|
VTKM_TEST_ASSERT((ref << ref) == (expected << expected));
|
|
VTKM_TEST_ASSERT((ref << expected) == (expected << expected));
|
|
VTKM_TEST_ASSERT((expected << ref) == (expected << expected));
|
|
|
|
VTKM_TEST_ASSERT(~ref == ~expected);
|
|
|
|
VTKM_TEST_ASSERT(!(!ref));
|
|
|
|
VTKM_TEST_ASSERT(ref && ref);
|
|
VTKM_TEST_ASSERT(ref && expected);
|
|
VTKM_TEST_ASSERT(expected && ref);
|
|
|
|
VTKM_TEST_ASSERT(ref || ref);
|
|
VTKM_TEST_ASSERT(ref || expected);
|
|
VTKM_TEST_ASSERT(expected || ref);
|
|
|
|
ref &= ref;
|
|
expected &= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref &= operand;
|
|
expected &= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref |= ref;
|
|
expected |= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref |= operand;
|
|
expected |= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref >>= ref;
|
|
expected >>= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref >>= operand;
|
|
expected >>= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref <<= ref;
|
|
expected <<= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref <<= operand;
|
|
expected <<= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref ^= ref;
|
|
expected ^= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref ^= operand;
|
|
expected ^= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
}
|
|
|
|
template <typename ArrayPortalType, typename DimTag, typename NumericTag>
|
|
void TryOperatorsInt(vtkm::Id,
|
|
vtkm::internal::ArrayPortalValueReference<ArrayPortalType>,
|
|
DimTag,
|
|
NumericTag)
|
|
{
|
|
}
|
|
|
|
template <typename ArrayPortalType>
|
|
void TryOperators(vtkm::Id index, vtkm::internal::ArrayPortalValueReference<ArrayPortalType> ref)
|
|
{
|
|
using ValueType = typename ArrayPortalType::ValueType;
|
|
|
|
const ValueType operand = TestValue(ARRAY_SIZE, ValueType());
|
|
ValueType expected = TestValue(index, ValueType());
|
|
VTKM_TEST_ASSERT(ref.Get() == expected, "Reference did not start out as expected.");
|
|
|
|
// Test comparison operators.
|
|
VTKM_TEST_ASSERT(ref == ref);
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
VTKM_TEST_ASSERT(expected == ref);
|
|
|
|
VTKM_TEST_ASSERT(!(ref != ref));
|
|
VTKM_TEST_ASSERT(!(ref != expected));
|
|
VTKM_TEST_ASSERT(!(expected != ref));
|
|
|
|
TryOperatorsNoVec(index, ref, typename vtkm::TypeTraits<ValueType>::DimensionalityTag());
|
|
|
|
VTKM_TEST_ASSERT((ref + ref) == (expected + expected));
|
|
VTKM_TEST_ASSERT((ref + expected) == (expected + expected));
|
|
VTKM_TEST_ASSERT((expected + ref) == (expected + expected));
|
|
|
|
VTKM_TEST_ASSERT((ref - ref) == (expected - expected));
|
|
VTKM_TEST_ASSERT((ref - expected) == (expected - expected));
|
|
VTKM_TEST_ASSERT((expected - ref) == (expected - expected));
|
|
|
|
VTKM_TEST_ASSERT((ref * ref) == (expected * expected));
|
|
VTKM_TEST_ASSERT((ref * expected) == (expected * expected));
|
|
VTKM_TEST_ASSERT((expected * ref) == (expected * expected));
|
|
|
|
VTKM_TEST_ASSERT((ref / ref) == (expected / expected));
|
|
VTKM_TEST_ASSERT((ref / expected) == (expected / expected));
|
|
VTKM_TEST_ASSERT((expected / ref) == (expected / expected));
|
|
|
|
ref += ref;
|
|
expected += expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref += operand;
|
|
expected += operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref -= ref;
|
|
expected -= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref -= operand;
|
|
expected -= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref *= ref;
|
|
expected *= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref *= operand;
|
|
expected *= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
ref /= ref;
|
|
expected /= expected;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
ref /= operand;
|
|
expected /= operand;
|
|
VTKM_TEST_ASSERT(ref == expected);
|
|
|
|
// Reset ref
|
|
ref = TestValue(index, ValueType());
|
|
|
|
TryOperatorsInt(index,
|
|
ref,
|
|
typename vtkm::TypeTraits<ValueType>::DimensionalityTag(),
|
|
typename vtkm::TypeTraits<ValueType>::NumericTag());
|
|
}
|
|
|
|
struct DoTestForType
|
|
{
|
|
template <typename ValueType>
|
|
VTKM_CONT void operator()(const ValueType&) const
|
|
{
|
|
vtkm::cont::ArrayHandle<ValueType> array;
|
|
array.Allocate(ARRAY_SIZE);
|
|
|
|
std::cout << "Set array using reference" << std::endl;
|
|
using PortalType = typename vtkm::cont::ArrayHandle<ValueType>::PortalControl;
|
|
PortalType portal = array.GetPortalControl();
|
|
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
|
|
{
|
|
SetReference(index, vtkm::internal::ArrayPortalValueReference<PortalType>(portal, index));
|
|
}
|
|
|
|
std::cout << "Check values" << std::endl;
|
|
CheckPortal(portal);
|
|
|
|
std::cout << "Check references in set array." << std::endl;
|
|
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
|
|
{
|
|
CheckReference(index, vtkm::internal::ArrayPortalValueReference<PortalType>(portal, index));
|
|
}
|
|
|
|
std::cout << "Check that operators work." << std::endl;
|
|
// Start at 1 to avoid issues with 0.
|
|
for (vtkm::Id index = 1; index < ARRAY_SIZE; ++index)
|
|
{
|
|
TryOperators(index, vtkm::internal::ArrayPortalValueReference<PortalType>(portal, index));
|
|
}
|
|
}
|
|
};
|
|
|
|
void DoTest()
|
|
{
|
|
vtkm::testing::Testing::TryTypes(DoTestForType());
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
int UnitTestArrayPortalValueReference(int argc, char* argv[])
|
|
{
|
|
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
|
|
}
|