vtk-m2/vtkm/cont/ArrayRangeCompute.hxx
Kenneth Moreland 4758d3d978 Gracefully handle array range requests on empty arrays
Previously, The ArrayRangeCompute code would throw an exception if you
tried to compute the array range on an empty array. This change instead
returns empty ranges.
2017-04-18 14:43:05 -06:00

129 lines
3.5 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 2017 Sandia Corporation.
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_ArrayRangeCompute_hxx
#define vtk_m_cont_ArrayRangeCompute_hxx
#include <vtkm/cont/ArrayRangeCompute.h>
#include <vtkm/BinaryOperators.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/TryExecute.h>
namespace vtkm {
namespace cont {
namespace detail {
template<typename ArrayHandleType>
struct ArrayRangeComputeFunctor
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
ArrayHandleType InputArray;
vtkm::cont::ArrayHandle<vtkm::Range> RangeArray;
VTKM_CONT
ArrayRangeComputeFunctor(const ArrayHandleType &input)
: InputArray(input)
{ }
template<typename Device>
VTKM_CONT
bool operator()(Device)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
using ValueType = typename ArrayHandleType::ValueType;
using VecTraits = vtkm::VecTraits<ValueType>;
const vtkm::IdComponent NumberOfComponents = VecTraits::NUM_COMPONENTS;
typedef vtkm::cont::DeviceAdapterAlgorithm<Device> Algorithm;
this->RangeArray.Allocate(NumberOfComponents);
if (this->InputArray.GetNumberOfValues() < 1)
{
for (vtkm::IdComponent i = 0; i < NumberOfComponents; ++i)
{
this->RangeArray.GetPortalControl().Set(i, vtkm::Range());
}
return true;
}
vtkm::Vec<ValueType,2> initial(
this->InputArray.GetPortalConstControl().Get(0));
vtkm::Vec<ValueType, 2> result =
Algorithm::Reduce(this->InputArray,
initial,
vtkm::MinAndMax<ValueType>());
for (vtkm::IdComponent i = 0; i < NumberOfComponents; ++i)
{
this->RangeArray.GetPortalControl().Set(
i, vtkm::Range(VecTraits::GetComponent(result[0], i),
VecTraits::GetComponent(result[1], i)));
}
return true;
}
};
template<typename ArrayHandleType>
inline
vtkm::cont::ArrayHandle<vtkm::Range>
ArrayRangeComputeImpl(const ArrayHandleType &input,
vtkm::cont::RuntimeDeviceTracker tracker)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
detail::ArrayRangeComputeFunctor<ArrayHandleType> functor(input);
if (!vtkm::cont::TryExecute(functor, tracker))
{
throw vtkm::cont::ErrorExecution(
"Failed to run ArrayRangeComputation on any device.");
}
return functor.RangeArray;
}
} // namespace detail
template<typename ArrayHandleType>
inline
vtkm::cont::ArrayHandle<vtkm::Range>
ArrayRangeCompute(const ArrayHandleType &input,
vtkm::cont::RuntimeDeviceTracker tracker)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
return detail::ArrayRangeComputeImpl(input, tracker);
}
}
} // namespace vtkm::cont
#endif //vtk_m_cont_ArrayRangeCompute_hxx