//============================================================================ // 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 #include #include #include namespace { static constexpr vtkm::Id ARRAY_SIZE = 10; template void SetReference(vtkm::Id index, vtkm::internal::ArrayPortalValueReference ref) { using ValueType = typename ArrayPortalType::ValueType; ref = TestValue(index, ValueType()); } template void CheckReference(vtkm::Id index, vtkm::internal::ArrayPortalValueReference ref) { using ValueType = typename ArrayPortalType::ValueType; VTKM_TEST_ASSERT(test_equal(ref, TestValue(index, ValueType())), "Got bad value from reference."); } template void TryOperatorsNoVec(vtkm::Id index, vtkm::internal::ArrayPortalValueReference 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 void TryOperatorsNoVec(vtkm::Id, vtkm::internal::ArrayPortalValueReference, vtkm::TypeTraitsVectorTag) { } template void TryOperatorsInt(vtkm::Id index, vtkm::internal::ArrayPortalValueReference ref, vtkm::internal::ArrayPortalValueReference scratch, vtkm::TypeTraitsScalarTag, vtkm::TypeTraitsIntegerTag) { 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) == (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); scratch = ValueType(7); const ValueType operand = ValueType(7); #define RESET \ ref = TestValue(index, ValueType()); \ expected = TestValue(index, ValueType()); RESET; ref &= scratch; expected &= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref &= operand; expected &= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref |= scratch; expected |= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref |= operand; expected |= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref >>= scratch; expected >>= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref >>= operand; expected >>= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref <<= scratch; expected <<= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref <<= operand; expected <<= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref ^= scratch; expected ^= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref ^= operand; expected ^= operand; VTKM_TEST_ASSERT(ref == expected); #undef RESET } template void TryOperatorsInt(vtkm::Id, vtkm::internal::ArrayPortalValueReference, vtkm::internal::ArrayPortalValueReference, DimTag, NumericTag) { } template void TryOperators(vtkm::Id index, vtkm::internal::ArrayPortalValueReference ref, vtkm::internal::ArrayPortalValueReference scratch) { using ValueType = typename ArrayPortalType::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::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)); scratch = ValueType(7); const ValueType operand = ValueType(7); #define RESET \ ref = TestValue(index, ValueType()); \ expected = TestValue(index, ValueType()); RESET; ref += scratch; expected += operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref += operand; expected += operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref -= scratch; expected -= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref -= operand; expected -= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref *= scratch; expected *= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref *= operand; expected *= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref /= scratch; expected /= operand; VTKM_TEST_ASSERT(ref == expected); RESET; ref /= operand; expected /= operand; VTKM_TEST_ASSERT(ref == expected); RESET; TryOperatorsInt(index, ref, scratch, typename vtkm::TypeTraits::DimensionalityTag(), typename vtkm::TypeTraits::NumericTag()); #undef RESET } struct DoTestForType { template VTKM_CONT void operator()(const ValueType&) const { vtkm::cont::ArrayHandle array; array.Allocate(ARRAY_SIZE); std::cout << "Set array using reference" << std::endl; using PortalType = typename vtkm::cont::ArrayHandle::WritePortalType; PortalType portal = array.WritePortal(); for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index) { SetReference(index, vtkm::internal::ArrayPortalValueReference(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(portal, index)); } std::cout << "Make a scratch buffer for ref-ref operations." << std::endl; vtkm::cont::ArrayHandle scratchArray; scratchArray.Allocate(1); PortalType scratchPortal = scratchArray.WritePortal(); 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(portal, index), vtkm::internal::ArrayPortalValueReference(scratchPortal, 0)); } } }; void DoTest() { // We are not testing on the default (exemplar) types because we want to test operators, and // many basic C types could fail on basic operations. Small integer types (such as unsigned // bytes) get automatically promoted to larger types, so doing somthing like a += operation // causes annoying compiler warnings. Float types are also problematic because comparison // operations like == can fail even when you expect the values to be the same. vtkm::testing::Testing::TryTypes(DoTestForType(), vtkm::List()); } } // anonymous namespace int UnitTestArrayPortalValueReference(int argc, char* argv[]) { return vtkm::testing::Testing::Run(DoTest, argc, argv); }