vtk-m2/vtkm/internal/testing/UnitTestArrayPortalValueReference.cxx
Kenneth Moreland 1ca55ac319 Add specialized operators for ArrayPortalValueReference
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.
2019-02-20 13:33:55 -07:00

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);
}