vtk-m/vtkm/worklet/Keys.hxx
Vicente Adolfo Bolea Sanchez 9d0da855b3 ConvertNumComponentsToOffsets using ScanExtented vs. ScanExclusive
This commit also:
- Removes a corner case not longer used at ArrayPortalGroupVecVariable::get
- Changes doc regarding the number of offset elements in the input
  array handler of ConvertNumComponentsToOffsets.
- Updates invokation of make_ArrayGroupVectVariable in multiple files
- Adds its corresponding changelog entry
2020-03-05 10:57:34 -05:00

136 lines
4.9 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.
//============================================================================
#ifndef vtk_m_worklet_Keys_hxx
#define vtk_m_worklet_Keys_hxx
#include <vtkm/worklet/Keys.h>
namespace vtkm
{
namespace worklet
{
/// Build the internal arrays without modifying the input. This is more
/// efficient for stable sorted arrays, but requires an extra copy of the
/// keys for unstable sorting.
template <typename T>
template <typename KeyArrayType>
VTKM_CONT void Keys<T>::BuildArrays(const KeyArrayType& keys,
KeysSortType sort,
vtkm::cont::DeviceAdapterId device)
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Keys::BuildArrays");
switch (sort)
{
case KeysSortType::Unstable:
{
KeyArrayHandleType mutableKeys;
vtkm::cont::Algorithm::Copy(device, keys, mutableKeys);
this->BuildArraysInternal(mutableKeys, device);
}
break;
case KeysSortType::Stable:
this->BuildArraysInternalStable(keys, device);
break;
}
}
/// Build the internal arrays and also sort the input keys. This is more
/// efficient for unstable sorting, but requires an extra copy for stable
/// sorting.
template <typename T>
template <typename KeyArrayType>
VTKM_CONT void Keys<T>::BuildArraysInPlace(KeyArrayType& keys,
KeysSortType sort,
vtkm::cont::DeviceAdapterId device)
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Keys::BuildArraysInPlace");
switch (sort)
{
case KeysSortType::Unstable:
this->BuildArraysInternal(keys, device);
break;
case KeysSortType::Stable:
{
this->BuildArraysInternalStable(keys, device);
KeyArrayHandleType tmp;
// Copy into a temporary array so that the permutation array copy
// won't alias input/output memory:
vtkm::cont::Algorithm::Copy(device, keys, tmp);
vtkm::cont::Algorithm::Copy(
device, vtkm::cont::make_ArrayHandlePermutation(this->SortedValuesMap, tmp), keys);
}
break;
}
}
template <typename T>
template <typename KeyArrayType>
VTKM_CONT void Keys<T>::BuildArraysInternal(KeyArrayType& keys, vtkm::cont::DeviceAdapterId device)
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Keys::BuildArraysInternal");
const vtkm::Id numKeys = keys.GetNumberOfValues();
vtkm::cont::Algorithm::Copy(device, vtkm::cont::ArrayHandleIndex(numKeys), this->SortedValuesMap);
// TODO: Do we need the ability to specify a comparison functor for sort?
vtkm::cont::Algorithm::SortByKey(device, keys, this->SortedValuesMap);
// Find the unique keys and the number of values per key.
vtkm::cont::Algorithm::ReduceByKey(device,
keys,
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>(1, numKeys),
this->UniqueKeys,
this->Counts,
vtkm::Sum());
// Get the offsets from the counts with a scan.
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast(this->Counts, vtkm::Id()), this->Offsets);
VTKM_ASSERT(numKeys ==
vtkm::cont::ArrayGetValue(this->Offsets.GetNumberOfValues() - 1, this->Offsets));
}
template <typename T>
template <typename KeyArrayType>
VTKM_CONT void Keys<T>::BuildArraysInternalStable(const KeyArrayType& keys,
vtkm::cont::DeviceAdapterId device)
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Keys::BuildArraysInternalStable");
const vtkm::Id numKeys = keys.GetNumberOfValues();
// Produce a stable sorted map of the keys:
this->SortedValuesMap = StableSortIndices::Sort(device, keys);
auto sortedKeys = vtkm::cont::make_ArrayHandlePermutation(this->SortedValuesMap, keys);
// Find the unique keys and the number of values per key.
vtkm::cont::Algorithm::ReduceByKey(device,
sortedKeys,
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>(1, numKeys),
this->UniqueKeys,
this->Counts,
vtkm::Sum());
// Get the offsets from the counts with a scan.
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast(this->Counts, vtkm::Id()), this->Offsets);
VTKM_ASSERT(numKeys ==
vtkm::cont::ArrayGetValue(this->Offsets.GetNumberOfValues() - 1, this->Offsets));
}
}
}
#endif