#include <vtkm/Types.h>

////
//// BEGIN-EXAMPLE ImplicitArrayFunctor.cxx
////
struct DoubleIndexFunctor
{
  VTKM_EXEC_CONT
  vtkm::Id operator()(vtkm::Id index) const { return 2 * index; }
};
////
//// END-EXAMPLE ImplicitArrayFunctor.cxx
////

////
//// BEGIN-EXAMPLE ImplicitArrayHandle.cxx
////
#include <vtkm/cont/ArrayHandleImplicit.h>

class ArrayHandleDoubleIndex
  : public vtkm::cont::ArrayHandleImplicit<DoubleIndexFunctor>
{
public:
  VTKM_ARRAY_HANDLE_SUBCLASS_NT(
    ArrayHandleDoubleIndex,
    (vtkm::cont::ArrayHandleImplicit<DoubleIndexFunctor>));

  VTKM_CONT
  ArrayHandleDoubleIndex(vtkm::Id numberOfValues)
    : Superclass(DoubleIndexFunctor(), numberOfValues)
  {
  }
};
////
//// END-EXAMPLE ImplicitArrayHandle.cxx
////

#include <vtkm/cont/ArrayCopyDevice.h>

#include <vtkm/cont/testing/Testing.h>

namespace
{

void Test()
{
  ////
  //// BEGIN-EXAMPLE DeclareImplicitArray.cxx
  ////
  vtkm::cont::ArrayHandleImplicit<DoubleIndexFunctor> implicitArray(
    DoubleIndexFunctor(), 50);
  ////
  //// END-EXAMPLE DeclareImplicitArray.cxx
  ////

  ArrayHandleDoubleIndex implicitArray2(50);

  auto implicitArray3 =
    ////
    //// BEGIN-EXAMPLE MakeArrayHandleImplicit.cxx
    ////
    vtkm::cont::make_ArrayHandleImplicit(DoubleIndexFunctor(), 50);
  ////
  //// END-EXAMPLE MakeArrayHandleImplicit.cxx
  ////

  vtkm::cont::ArrayHandle<vtkm::Id> explicitArray;
  vtkm::cont::ArrayHandle<vtkm::Id> explicitArray2;
  vtkm::cont::ArrayHandle<vtkm::Id> explicitArray3;

  vtkm::cont::ArrayCopyDevice(implicitArray, explicitArray);
  vtkm::cont::ArrayCopyDevice(implicitArray2, explicitArray2);
  vtkm::cont::ArrayCopyDevice(implicitArray3, explicitArray3);

  VTKM_TEST_ASSERT(explicitArray.GetNumberOfValues() == 50, "Wrong num vals.");
  VTKM_TEST_ASSERT(explicitArray2.GetNumberOfValues() == 50, "Wrong num vals.");
  VTKM_TEST_ASSERT(explicitArray3.GetNumberOfValues() == 50, "Wrong num vals.");
  for (vtkm::Id index = 0; index < explicitArray.GetNumberOfValues(); index++)
  {
    VTKM_TEST_ASSERT(explicitArray.ReadPortal().Get(index) == 2 * index,
                     "Bad array value.");
    VTKM_TEST_ASSERT(explicitArray2.ReadPortal().Get(index) == 2 * index,
                     "Bad array value.");
    VTKM_TEST_ASSERT(explicitArray3.ReadPortal().Get(index) == 2 * index,
                     "Bad array value.");
  }
}

} // anonymous namespace

int ArrayHandleImplicit(int argc, char* argv[])
{
  return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}
