2014-02-11 17:34:56 +00:00
|
|
|
//============================================================================
|
|
|
|
// 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 2014 Sandia Corporation.
|
|
|
|
// Copyright 2014 UT-Battelle, LLC.
|
2015-05-21 12:09:22 +00:00
|
|
|
// Copyright 2014 Los Alamos National Security.
|
2014-02-11 17:34:56 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//============================================================================
|
2014-03-07 15:19:09 +00:00
|
|
|
#ifndef vtk_m_cont_internal_DeviceAdapterAlgorithmSerial_h
|
|
|
|
#define vtk_m_cont_internal_DeviceAdapterAlgorithmSerial_h
|
2014-02-11 17:34:56 +00:00
|
|
|
|
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
2014-09-08 20:59:11 +00:00
|
|
|
#include <vtkm/cont/ArrayPortalToIterators.h>
|
2014-11-25 14:14:04 +00:00
|
|
|
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
2014-02-11 17:34:56 +00:00
|
|
|
#include <vtkm/cont/ErrorExecution.h>
|
|
|
|
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
|
|
|
|
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
|
|
|
|
|
|
|
|
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
|
|
|
|
|
|
|
#include <boost/iterator/counting_iterator.hpp>
|
|
|
|
#include <boost/utility/enable_if.hpp>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <numeric>
|
|
|
|
|
|
|
|
namespace vtkm {
|
|
|
|
namespace cont {
|
|
|
|
|
2015-04-30 13:01:52 +00:00
|
|
|
|
2014-02-11 17:34:56 +00:00
|
|
|
template<>
|
|
|
|
struct DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial> :
|
|
|
|
vtkm::cont::internal::DeviceAdapterAlgorithmGeneral<
|
|
|
|
DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial>,
|
|
|
|
vtkm::cont::DeviceAdapterTagSerial>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
typedef vtkm::cont::DeviceAdapterTagSerial Device;
|
|
|
|
|
|
|
|
public:
|
2015-05-04 19:53:35 +00:00
|
|
|
|
|
|
|
template<typename T, class CIn>
|
|
|
|
VTKM_CONT_EXPORT static T Reduce(
|
|
|
|
const vtkm::cont::ArrayHandle<T,CIn> &input, T initialValue)
|
|
|
|
{
|
|
|
|
return Reduce(input, initialValue, vtkm::internal::Add());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, class CIn, class BinaryOperator>
|
|
|
|
VTKM_CONT_EXPORT static T Reduce(
|
|
|
|
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
|
|
|
T initialValue,
|
|
|
|
BinaryOperator binaryOp)
|
|
|
|
{
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,CIn>
|
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalIn;
|
|
|
|
|
|
|
|
PortalIn inputPortal = input.PrepareForInput(Device());
|
|
|
|
return std::accumulate(vtkm::cont::ArrayPortalToIteratorBegin(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(inputPortal),
|
|
|
|
initialValue,
|
|
|
|
binaryOp);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U, class KIn, class VIn, class KOut, class VOut,
|
|
|
|
class BinaryOperation>
|
|
|
|
VTKM_CONT_EXPORT static void ReduceByKey(
|
|
|
|
const vtkm::cont::ArrayHandle<T,KIn> &keys,
|
|
|
|
const vtkm::cont::ArrayHandle<U,VIn> &values,
|
|
|
|
vtkm::cont::ArrayHandle<T,KOut> &keys_output,
|
|
|
|
vtkm::cont::ArrayHandle<U,VOut> &values_output,
|
|
|
|
BinaryOperation binaryOp)
|
|
|
|
{
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,KIn>
|
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalKIn;
|
2015-06-01 16:19:17 +00:00
|
|
|
typedef typename vtkm::cont::ArrayHandle<U,VIn>
|
2015-05-04 19:53:35 +00:00
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalVIn;
|
|
|
|
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,KOut>
|
|
|
|
::template ExecutionTypes<Device>::Portal PortalKOut;
|
2015-06-01 16:19:17 +00:00
|
|
|
typedef typename vtkm::cont::ArrayHandle<U,VOut>
|
2015-05-04 19:53:35 +00:00
|
|
|
::template ExecutionTypes<Device>::Portal PortalVOut;
|
|
|
|
|
|
|
|
PortalKIn keysPortalIn = keys.PrepareForInput(Device());
|
|
|
|
PortalVIn valuesPortalIn = values.PrepareForInput(Device());
|
|
|
|
|
|
|
|
const vtkm::Id numberOfKeys = keys.GetNumberOfValues();
|
|
|
|
PortalKOut keysPortalOut = keys_output.PrepareForOutput(numberOfKeys, Device());
|
|
|
|
PortalVOut valuesPortalOut = values_output.PrepareForOutput(numberOfKeys, Device());
|
|
|
|
|
|
|
|
vtkm::Id writePos = 0;
|
|
|
|
vtkm::Id readPos = 0;
|
|
|
|
|
|
|
|
T currentKey = keysPortalIn.Get(readPos);
|
|
|
|
U currentValue = valuesPortalIn.Get(readPos);
|
|
|
|
|
|
|
|
for(++readPos; readPos < numberOfKeys; ++readPos)
|
|
|
|
{
|
|
|
|
while(readPos < numberOfKeys &&
|
|
|
|
currentKey == keysPortalIn.Get(readPos) )
|
|
|
|
{
|
|
|
|
currentValue = binaryOp(currentValue, valuesPortalIn.Get(readPos));
|
|
|
|
++readPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(readPos < numberOfKeys)
|
|
|
|
{
|
|
|
|
keysPortalOut.Set(writePos, currentKey);
|
|
|
|
valuesPortalOut.Set(writePos, currentValue);
|
|
|
|
++writePos;
|
|
|
|
|
|
|
|
currentKey = keysPortalIn.Get(readPos);
|
|
|
|
currentValue = valuesPortalIn.Get(readPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//now write out the last set of values
|
|
|
|
keysPortalOut.Set(writePos, currentKey);
|
|
|
|
valuesPortalOut.Set(writePos, currentValue);
|
|
|
|
|
|
|
|
//now we need to shrink to the correct number of keys/values
|
|
|
|
//writePos is zero-based so add 1 to get correct length
|
|
|
|
keys_output.Shrink( writePos + 1 );
|
|
|
|
values_output.Shrink( writePos + 1 );
|
|
|
|
}
|
|
|
|
|
2014-02-11 17:34:56 +00:00
|
|
|
template<typename T, class CIn, class COut>
|
|
|
|
VTKM_CONT_EXPORT static T ScanInclusive(
|
|
|
|
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
|
|
|
vtkm::cont::ArrayHandle<T,COut>& output)
|
|
|
|
{
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,COut>
|
|
|
|
::template ExecutionTypes<Device>::Portal PortalOut;
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,CIn>
|
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalIn;
|
|
|
|
|
|
|
|
vtkm::Id numberOfValues = input.GetNumberOfValues();
|
|
|
|
|
|
|
|
PortalIn inputPortal = input.PrepareForInput(Device());
|
|
|
|
PortalOut outputPortal = output.PrepareForOutput(numberOfValues, Device());
|
|
|
|
|
2015-05-29 14:38:28 +00:00
|
|
|
if (numberOfValues <= 0) { return T(); }
|
2014-02-11 17:34:56 +00:00
|
|
|
|
2014-09-08 20:59:11 +00:00
|
|
|
std::partial_sum(vtkm::cont::ArrayPortalToIteratorBegin(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorBegin(outputPortal));
|
2014-02-11 17:34:56 +00:00
|
|
|
|
|
|
|
// Return the value at the last index in the array, which is the full sum.
|
|
|
|
return outputPortal.Get(numberOfValues - 1);
|
|
|
|
}
|
|
|
|
|
2015-04-29 19:48:25 +00:00
|
|
|
template<typename T, class CIn, class COut, class BinaryOperation>
|
|
|
|
VTKM_CONT_EXPORT static T ScanInclusive(
|
|
|
|
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
|
|
|
vtkm::cont::ArrayHandle<T,COut>& output,
|
|
|
|
BinaryOperation binaryOp)
|
|
|
|
{
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,COut>
|
|
|
|
::template ExecutionTypes<Device>::Portal PortalOut;
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,CIn>
|
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalIn;
|
|
|
|
|
2015-04-30 13:01:52 +00:00
|
|
|
internal::WrappedBinaryOperator<T,BinaryOperation> wrappedBinaryOp(
|
|
|
|
binaryOp);
|
|
|
|
|
2015-04-29 19:48:25 +00:00
|
|
|
vtkm::Id numberOfValues = input.GetNumberOfValues();
|
|
|
|
|
|
|
|
PortalIn inputPortal = input.PrepareForInput(Device());
|
|
|
|
PortalOut outputPortal = output.PrepareForOutput(numberOfValues, Device());
|
|
|
|
|
2015-05-29 14:38:28 +00:00
|
|
|
if (numberOfValues <= 0) { return T(); }
|
2015-04-29 19:48:25 +00:00
|
|
|
|
|
|
|
std::partial_sum(vtkm::cont::ArrayPortalToIteratorBegin(inputPortal),
|
2015-04-30 13:01:52 +00:00
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorBegin(outputPortal),
|
|
|
|
wrappedBinaryOp);
|
2015-04-29 19:48:25 +00:00
|
|
|
|
|
|
|
// Return the value at the last index in the array, which is the full sum.
|
|
|
|
return outputPortal.Get(numberOfValues - 1);
|
|
|
|
}
|
|
|
|
|
2014-02-11 17:34:56 +00:00
|
|
|
template<typename T, class CIn, class COut>
|
|
|
|
VTKM_CONT_EXPORT static T ScanExclusive(
|
|
|
|
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
|
|
|
vtkm::cont::ArrayHandle<T,COut>& output)
|
|
|
|
{
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,COut>
|
|
|
|
::template ExecutionTypes<Device>::Portal PortalOut;
|
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,CIn>
|
|
|
|
::template ExecutionTypes<Device>::PortalConst PortalIn;
|
|
|
|
|
|
|
|
vtkm::Id numberOfValues = input.GetNumberOfValues();
|
|
|
|
|
|
|
|
PortalIn inputPortal = input.PrepareForInput(Device());
|
|
|
|
PortalOut outputPortal = output.PrepareForOutput(numberOfValues, Device());
|
|
|
|
|
2015-05-29 14:38:28 +00:00
|
|
|
if (numberOfValues <= 0) { return T(); }
|
2014-02-11 17:34:56 +00:00
|
|
|
|
2014-09-08 20:59:11 +00:00
|
|
|
std::partial_sum(vtkm::cont::ArrayPortalToIteratorBegin(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(inputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorBegin(outputPortal));
|
2014-02-11 17:34:56 +00:00
|
|
|
|
|
|
|
T fullSum = outputPortal.Get(numberOfValues - 1);
|
|
|
|
|
|
|
|
// Shift right by one
|
2014-09-08 20:59:11 +00:00
|
|
|
std::copy_backward(vtkm::cont::ArrayPortalToIteratorBegin(outputPortal),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(outputPortal)-1,
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(outputPortal));
|
2014-02-11 17:34:56 +00:00
|
|
|
outputPortal.Set(0, 0);
|
|
|
|
return fullSum;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// This runs in the execution environment.
|
|
|
|
template<class FunctorType>
|
|
|
|
class ScheduleKernel
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ScheduleKernel(const FunctorType &functor)
|
|
|
|
: Functor(functor) { }
|
|
|
|
|
|
|
|
//needed for when calling from schedule on a range
|
|
|
|
VTKM_EXEC_EXPORT void operator()(vtkm::Id index) const
|
|
|
|
{
|
|
|
|
this->Functor(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const FunctorType Functor;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
template<class Functor>
|
|
|
|
VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
2014-02-11 21:20:30 +00:00
|
|
|
vtkm::Id numInstances)
|
2014-02-11 17:34:56 +00:00
|
|
|
{
|
|
|
|
const vtkm::Id MESSAGE_SIZE = 1024;
|
|
|
|
char errorString[MESSAGE_SIZE];
|
|
|
|
errorString[0] = '\0';
|
|
|
|
vtkm::exec::internal::ErrorMessageBuffer
|
|
|
|
errorMessage(errorString, MESSAGE_SIZE);
|
|
|
|
|
|
|
|
functor.SetErrorMessageBuffer(errorMessage);
|
|
|
|
|
|
|
|
DeviceAdapterAlgorithm<Device>::ScheduleKernel<Functor> kernel(functor);
|
|
|
|
|
|
|
|
std::for_each(
|
|
|
|
::boost::counting_iterator<vtkm::Id>(0),
|
|
|
|
::boost::counting_iterator<vtkm::Id>(numInstances),
|
|
|
|
kernel);
|
|
|
|
|
|
|
|
if (errorMessage.IsErrorRaised())
|
2014-02-11 21:20:30 +00:00
|
|
|
{
|
2014-02-11 17:34:56 +00:00
|
|
|
throw vtkm::cont::ErrorExecution(errorString);
|
2014-02-11 21:20:30 +00:00
|
|
|
}
|
2014-02-11 17:34:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class FunctorType>
|
|
|
|
VTKM_CONT_EXPORT
|
|
|
|
static void Schedule(FunctorType functor, vtkm::Id3 rangeMax)
|
|
|
|
{
|
|
|
|
DeviceAdapterAlgorithm<Device>::Schedule(functor,
|
|
|
|
rangeMax[0] * rangeMax[1] * rangeMax[2] );
|
|
|
|
}
|
|
|
|
|
2014-06-23 23:33:04 +00:00
|
|
|
template<typename T, class Storage>
|
|
|
|
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Storage>& values)
|
2014-02-11 17:34:56 +00:00
|
|
|
{
|
2014-06-23 23:33:04 +00:00
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,Storage>
|
2014-02-11 17:34:56 +00:00
|
|
|
::template ExecutionTypes<Device>::Portal PortalType;
|
|
|
|
|
|
|
|
PortalType arrayPortal = values.PrepareForInPlace(Device());
|
2014-09-08 20:59:11 +00:00
|
|
|
vtkm::cont::ArrayPortalToIterators<PortalType> iterators(arrayPortal);
|
|
|
|
std::sort(iterators.GetBegin(), iterators.GetEnd());
|
2014-02-11 17:34:56 +00:00
|
|
|
}
|
|
|
|
|
2014-06-23 23:33:04 +00:00
|
|
|
template<typename T, class Storage, class Compare>
|
|
|
|
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Storage>& values,
|
2014-02-11 21:20:30 +00:00
|
|
|
Compare comp)
|
2014-02-11 17:34:56 +00:00
|
|
|
{
|
2014-06-23 23:33:04 +00:00
|
|
|
typedef typename vtkm::cont::ArrayHandle<T,Storage>
|
2014-02-11 17:34:56 +00:00
|
|
|
::template ExecutionTypes<Device>::Portal PortalType;
|
|
|
|
|
|
|
|
PortalType arrayPortal = values.PrepareForInPlace(Device());
|
2014-09-08 20:59:11 +00:00
|
|
|
vtkm::cont::ArrayPortalToIterators<PortalType> iterators(arrayPortal);
|
|
|
|
std::sort(iterators.GetBegin(), iterators.GetEnd(), comp);
|
2014-02-11 17:34:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_CONT_EXPORT static void Synchronize()
|
|
|
|
{
|
|
|
|
// Nothing to do. This device is serial and has no asynchronous operations.
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
} // namespace vtkm::cont
|
|
|
|
|
2014-06-11 16:43:36 +00:00
|
|
|
#endif //vtk_m_cont_internal_DeviceAdapterAlgorithmSerial_h
|