mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Merge branch 'add_serial_deviceAdapter'
This commit is contained in:
commit
5b8bec5ecd
144
vtkm/cont/ArrayHandleCounting.h
Normal file
144
vtkm/cont/ArrayHandleCounting.h
Normal file
@ -0,0 +1,144 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_ArrayHandleCounting_h
|
||||
#define vtkm_cont_ArrayHandleCounting_h
|
||||
|
||||
#include <vtkm/cont/ArrayContainerControlImplicit.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/// \brief An implicit array portal that returns an counting value.
|
||||
template <class CountingValueType>
|
||||
class ArrayPortalCounting
|
||||
{
|
||||
public:
|
||||
typedef CountingValueType ValueType;
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ArrayPortalCounting() :
|
||||
StartingValue(),
|
||||
NumberOfValues(0)
|
||||
{ }
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ArrayPortalCounting(ValueType startingValue, vtkm::Id numValues) :
|
||||
StartingValue(startingValue),
|
||||
NumberOfValues(numValues)
|
||||
{ }
|
||||
|
||||
template<typename OtherValueType>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ArrayPortalCounting(const ArrayPortalCounting<OtherValueType> &src)
|
||||
: StartingValue(src.StartingValue),
|
||||
NumberOfValues(src.NumberOfValues)
|
||||
{ }
|
||||
|
||||
template<typename OtherValueType>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ArrayPortalCounting<ValueType> &operator=(
|
||||
const ArrayPortalCounting<OtherValueType> &src)
|
||||
{
|
||||
this->StartingValue = src.StartingValue;
|
||||
this->NumberOfValues = src.NumberOfValues;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ValueType Get(vtkm::Id index) const { return StartingValue+index; }
|
||||
|
||||
typedef vtkm::cont::internal::IteratorFromArrayPortal<
|
||||
ArrayPortalCounting < CountingValueType> > IteratorType;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
IteratorType GetIteratorBegin() const
|
||||
{
|
||||
return IteratorType(*this);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
IteratorType GetIteratorEnd() const
|
||||
{
|
||||
return IteratorType(*this, this->NumberOfValues);
|
||||
}
|
||||
|
||||
private:
|
||||
CountingValueType StartingValue;
|
||||
vtkm::Id NumberOfValues;
|
||||
};
|
||||
|
||||
/// A convenience class that provides a typedef to the appropriate tag for
|
||||
/// a counting array container.
|
||||
template<typename ConstantValueType>
|
||||
struct ArrayHandleCountingTraits
|
||||
{
|
||||
typedef vtkm::cont::ArrayContainerControlTagImplicit<
|
||||
vtkm::cont::internal::ArrayPortalCounting<ConstantValueType> > Tag;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// ArrayHandleCountings is a specialization of ArrayHandle. By default it
|
||||
/// contains a increment value, that is increment for each step between zero
|
||||
/// and the passed in length
|
||||
template <typename CountingValueType>
|
||||
class ArrayHandleCounting
|
||||
: public vtkm::cont::ArrayHandle <
|
||||
CountingValueType,
|
||||
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
|
||||
>
|
||||
{
|
||||
typedef vtkm::cont::ArrayHandle <
|
||||
CountingValueType,
|
||||
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
|
||||
> Superclass;
|
||||
public:
|
||||
|
||||
ArrayHandleCounting(CountingValueType startingValue, vtkm::Id length)
|
||||
:Superclass(typename Superclass::PortalConstControl(startingValue, length))
|
||||
{
|
||||
}
|
||||
|
||||
ArrayHandleCounting():Superclass() {}
|
||||
};
|
||||
|
||||
/// A convenience function for creating an ArrayHandleCounting. It takes the
|
||||
/// value to start counting from and and the number of times to increment.
|
||||
template<typename CountingValueType>
|
||||
VTKM_CONT_EXPORT
|
||||
vtkm::cont::ArrayHandleCounting<CountingValueType>
|
||||
make_ArrayHandleCounting(CountingValueType startingValue,
|
||||
vtkm::Id length)
|
||||
{
|
||||
return vtkm::cont::ArrayHandleCounting<CountingValueType>(startingValue,
|
||||
length);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif //vtkm_cont_ArrayHandleCounting_h
|
@ -27,6 +27,8 @@ set(headers
|
||||
ArrayHandle.h
|
||||
ArrayPortal.h
|
||||
Assert.h
|
||||
DeviceAdapter.h
|
||||
DeviceAdapterSerial.h
|
||||
Error.h
|
||||
ErrorControl.h
|
||||
ErrorControlAssert.h
|
||||
|
73
vtkm/cont/DeviceAdapter.h
Normal file
73
vtkm/cont/DeviceAdapter.h
Normal file
@ -0,0 +1,73 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_DeviceAdapter_h
|
||||
#define vtkm_cont_DeviceAdapter_h
|
||||
|
||||
// These are listed in non-alphabetical order because this is the conceptual
|
||||
// order in which the sub-files are loaded. (But the compile should still
|
||||
// succeed of the order is changed.)
|
||||
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/internal/ArrayManagerExecution.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterAlgorithm.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
|
||||
#ifdef VTKM_DOXYGEN_ONLY
|
||||
/// \brief A tag specifying the interface between the control and execution environments.
|
||||
///
|
||||
/// A DeviceAdapter tag specifies a set of functions and classes that provide
|
||||
/// mechanisms to run algorithms on a type of parallel device. The tag
|
||||
/// DeviceAdapterTag___ does not actually exist. Rather, this documentation is
|
||||
/// provided to describe the interface for a DeviceAdapter. Loading the
|
||||
/// dax/cont/DeviceAdapter.h header file will set a default device adapter
|
||||
/// appropriate for the current compile environment. You can specify the
|
||||
/// default device adapter by first setting the \c VTKM_DEVICE_ADAPTER macro.
|
||||
/// Valid values for \c VTKM_DEVICE_ADAPTER are the following:
|
||||
///
|
||||
/// \li \c VTKM_DEVICE_ADAPTER_SERIAL Runs all algorithms in serial. Can be
|
||||
/// helpful for debugging.
|
||||
/// \li \c VTKM_DEVICE_ADAPTER_CUDA Dispatches and runs algorithms on a GPU
|
||||
/// using CUDA. Must be compiling with a CUDA compiler (nvcc).
|
||||
/// \li \c VTKM_DEVICE_ADAPTER_OPENMP Dispatches an algorithm over multiple
|
||||
/// CPU cores using OpenMP compiler directives. Must be compiling with an
|
||||
/// OpenMP-compliant compiler with OpenMP pragmas enabled.
|
||||
/// \li \c VTKM_DEVICE_ADAPTER_TBB Dispatches and runs algorithms on multiple
|
||||
/// threads using the Intel Threading Building Blocks (TBB) libraries. Must
|
||||
/// have the TBB headers available and the resulting code must be linked with
|
||||
/// the TBB libraries.
|
||||
///
|
||||
/// See the ArrayManagerExecution.h and DeviceAdapterAlgorithm.h files for
|
||||
/// documentation on all the functions and classes that must be
|
||||
/// overloaded/specialized to create a new device adapter.
|
||||
///
|
||||
struct DeviceAdapterTag___ { };
|
||||
#endif //VTKM_DOXYGEN_ONLY
|
||||
|
||||
namespace internal {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
||||
#endif //vtkm_cont_DeviceAdapter_h
|
27
vtkm/cont/DeviceAdapterSerial.h
Normal file
27
vtkm/cont/DeviceAdapterSerial.h
Normal file
@ -0,0 +1,27 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_DeviceAdapterSerial_h
|
||||
#define vtkm_cont_DeviceAdapterSerial_h
|
||||
|
||||
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
|
||||
#include <vtkm/cont/internal/ArrayManagerExecutionSerial.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h>
|
||||
|
||||
#endif //vtkm_cont_DeviceAdapterSerial_h
|
@ -26,6 +26,13 @@ set(headers
|
||||
ArrayPortalFromIterators.h
|
||||
ArrayPortalShrink.h
|
||||
ArrayTransfer.h
|
||||
DeviceAdapterAlgorithm.h
|
||||
DeviceAdapterAlgorithmGeneral.h
|
||||
DeviceAdapterAlgorithmSerial.h
|
||||
DeviceAdapterError.h
|
||||
DeviceAdapterTag.h
|
||||
DeviceAdapterTagSerial.h
|
||||
IteratorFromArrayPortal.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
404
vtkm/cont/internal/DeviceAdapterAlgorithm.h
Normal file
404
vtkm/cont/internal/DeviceAdapterAlgorithm.h
Normal file
@ -0,0 +1,404 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithm_h
|
||||
#define vtkm_cont_internal_DeviceAdapterAlgorithm_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <vtkm/cont/internal/ArrayManagerExecution.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
|
||||
/// \brief Struct containing device adapter algorithms.
|
||||
///
|
||||
/// This struct, templated on the device adapter tag, comprises static methods
|
||||
/// that implement the algorithms provided by the device adapter. The default
|
||||
/// struct is not implemented. Device adapter implementations must specialize
|
||||
/// the template.
|
||||
///
|
||||
template<class DeviceAdapterTag>
|
||||
struct DeviceAdapterAlgorithm
|
||||
#ifdef VTKM_DOXYGEN_ONLY
|
||||
{
|
||||
/// \brief Copy the contents of one ArrayHandle to another
|
||||
///
|
||||
/// Copies the contents of \c input to \c output. The array \c to will be
|
||||
/// allocated to the appropriate size.
|
||||
///
|
||||
template<typename T, class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void Copy(
|
||||
const vtkm::cont::ArrayHandle<T, CIn, DeviceAdapterTag> &input,
|
||||
vtkm::cont::ArrayHandle<T, COut, DeviceAdapterTag> &output);
|
||||
|
||||
/// \brief Output is the first index in input for each item in values that wouldn't alter the ordering of input
|
||||
///
|
||||
/// LowerBounds is a vectorized search. From each value in \c values it finds
|
||||
/// the first place the item can be inserted in the ordered \c input array and
|
||||
/// stores the index in \c output.
|
||||
///
|
||||
/// \par Requirements:
|
||||
/// \arg \c input must already be sorted
|
||||
///
|
||||
template<typename T, class CIn, class CVal, class COut>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output);
|
||||
|
||||
/// \brief Output is the first index in input for each item in values that wouldn't alter the ordering of input
|
||||
///
|
||||
/// LowerBounds is a vectorized search. From each value in \c values it finds
|
||||
/// the first place the item can be inserted in the ordered \c input array and
|
||||
/// stores the index in \c output. Uses the custom comparison functor to
|
||||
/// determine the correct location for each item.
|
||||
///
|
||||
/// \par Requirements:
|
||||
/// \arg \c input must already be sorted
|
||||
///
|
||||
template<typename T, class CIn, class CVal, class COut, class Compare>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output,
|
||||
Compare comp);
|
||||
|
||||
/// \brief A special version of LowerBounds that does an in place operation.
|
||||
///
|
||||
/// This version of lower bounds performs an in place operation where each
|
||||
/// value in the \c values_output array is replaced by the index in \c input
|
||||
/// where it occurs. Because this is an in place operation, the type of the
|
||||
/// arrays is limited to vtkm::Id.
|
||||
///
|
||||
template<class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id,CIn,DeviceAdapterTag>& input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& values_output);
|
||||
|
||||
/// \brief Compute an inclusive prefix sum operation on the input ArrayHandle.
|
||||
///
|
||||
/// Computes an inclusive prefix sum operation on the \c input ArrayHandle,
|
||||
/// storing the results in the \c output ArrayHandle. InclusiveScan is
|
||||
/// similiar to the stl partial sum function, exception that InclusiveScan
|
||||
/// doesn't do a serial sumnation. This means that if you have defined a
|
||||
/// custom plus operator for T it must be associative, or you will get
|
||||
/// inconsistent results. When the input and output ArrayHandles are the same
|
||||
/// ArrayHandle the operation will be done inplace.
|
||||
///
|
||||
/// \return The total sum.
|
||||
///
|
||||
template<typename T, class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static T ScanInclusive(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
|
||||
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag>& output);
|
||||
|
||||
/// \brief Compute an exclusive prefix sum operation on the input ArrayHandle.
|
||||
///
|
||||
/// Computes an exclusive prefix sum operation on the \c input ArrayHandle,
|
||||
/// storing the results in the \c output ArrayHandle. ExclusiveScan is
|
||||
/// similiar to the stl partial sum function, exception that ExclusiveScan
|
||||
/// doesn't do a serial sumnation. This means that if you have defined a
|
||||
/// custom plus operator for T it must be associative, or you will get
|
||||
/// inconsistent results. When the input and output ArrayHandles are the same
|
||||
/// ArrayHandle the operation will be done inplace.
|
||||
///
|
||||
/// \return The total sum.
|
||||
///
|
||||
template<typename T, class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static T ScanExclusive(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
|
||||
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag>& output);
|
||||
|
||||
/// \brief Schedule many instances of a function to run on concurrent threads.
|
||||
///
|
||||
/// Calls the \c functor on several threads. This is the function used in the
|
||||
/// control environment to spawn activity in the execution environment. \c
|
||||
/// functor is a function-like object that can be invoked with the calling
|
||||
/// specification <tt>functor(vtkm::Id index)</tt>. It also has a method called
|
||||
/// from the control environment to establish the error reporting buffer with
|
||||
/// the calling specification <tt>functor.SetErrorMessageBuffer(const
|
||||
/// vtkm::exec::internal::ErrorMessageBuffer &errorMessage)</tt>. This object
|
||||
/// can be stored in the functor's state such that if RaiseError is called on
|
||||
/// it in the execution environment, an ErrorExecution will be thrown from
|
||||
/// Schedule.
|
||||
///
|
||||
/// The argument of the invoked functor uniquely identifies the thread or
|
||||
/// instance of the invocation. There should be one invocation for each index
|
||||
/// in the range [0, \c numInstances].
|
||||
///
|
||||
template<class Functor>
|
||||
VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
vtkm::Id numInstances);
|
||||
|
||||
/// \brief Schedule many instances of a function to run on concurrent threads.
|
||||
///
|
||||
/// Calls the \c functor on several threads. This is the function used in the
|
||||
/// control environment to spawn activity in the execution environment. \c
|
||||
/// functor is a function-like object that can be invoked with the calling
|
||||
/// specification <tt>functor(vtkm::Id3 index)</tt> or <tt>functor(vtkm::Id
|
||||
/// index)</tt>. It also has a method called from the control environment to
|
||||
/// establish the error reporting buffer with the calling specification
|
||||
/// <tt>functor.SetErrorMessageBuffer(const
|
||||
/// vtkm::exec::internal::ErrorMessageBuffer &errorMessage)</tt>. This object
|
||||
/// can be stored in the functor's state such that if RaiseError is called on
|
||||
/// it in the execution environment, an ErrorExecution will be thrown from
|
||||
/// Schedule.
|
||||
///
|
||||
/// The argument of the invoked functor uniquely identifies the thread or
|
||||
/// instance of the invocation. It is at the device adapter's discretion
|
||||
/// whether to schedule on 1D or 3D indices, so the functor should have an
|
||||
/// operator() overload for each index type. If 3D indices are used, there is
|
||||
/// one invocation for every i, j, k value between [0, 0, 0] and \c rangeMax.
|
||||
/// If 1D indices are used, this Schedule behaves as if <tt>Schedule(functor,
|
||||
/// rangeMax[0]*rangeMax[1]*rangeMax[2])</tt> were called.
|
||||
///
|
||||
template<class Functor, class IndiceType>
|
||||
VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
vtkm::Id3 rangeMax);
|
||||
|
||||
/// \brief Unstable ascending sort of input array.
|
||||
///
|
||||
/// Sorts the contents of \c values so that they in ascending value. Doesn't
|
||||
/// guarantee stability
|
||||
///
|
||||
template<typename T, class Container>
|
||||
VTKM_CONT_EXPORT static void Sort(
|
||||
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag> &values);
|
||||
|
||||
/// \brief Unstable ascending sort of input array.
|
||||
///
|
||||
/// Sorts the contents of \c values so that they in ascending value based
|
||||
/// on the custom compare functor.
|
||||
///
|
||||
template<typename T, class Container, class Compare>
|
||||
VTKM_CONT_EXPORT static void Sort(
|
||||
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag> &values,
|
||||
Compare comp);
|
||||
|
||||
/// \brief Performs stream compaction to remove unwanted elements in the input array. Output becomes the index values of input that are valid.
|
||||
///
|
||||
/// Calls the parallel primitive function of stream compaction on the \c
|
||||
/// input to remove unwanted elements. The result of the stream compaction is
|
||||
/// placed in \c output. The \c input values are used as the stream
|
||||
/// compaction stencil while \c input indices are used as the values to place
|
||||
/// into \c ouput. The size of \c output will be modified after this call as
|
||||
/// we can't know the number of elements that will be removed by the stream
|
||||
/// compaction algorithm.
|
||||
///
|
||||
template<typename T, class CStencil, class COut>
|
||||
VTKM_CONT_EXPORT static void StreamCompact(
|
||||
const vtkm::cont::ArrayHandle<T,CStencil,DeviceAdapterTag> &stencil,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag> &output);
|
||||
|
||||
/// \brief Performs stream compaction to remove unwanted elements in the input array.
|
||||
///
|
||||
/// Calls the parallel primitive function of stream compaction on the \c
|
||||
/// input to remove unwanted elements. The result of the stream compaction is
|
||||
/// placed in \c output. The values in \c stencil are used as the stream
|
||||
/// compaction stencil while \c input values are placed into \c ouput. The
|
||||
/// size of \c output will be modified after this call as we can't know the
|
||||
/// number of elements that will be removed by the stream compaction
|
||||
/// algorithm.
|
||||
///
|
||||
template<typename T, typename U, class CIn, class CStencil, class COut>
|
||||
VTKM_CONT_EXPORT static void StreamCompact(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
|
||||
const vtkm::cont::ArrayHandle<U,CStencil,DeviceAdapterTag> &stencil,
|
||||
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag> &output);
|
||||
|
||||
/// \brief Completes any asynchronous operations running on the device.
|
||||
///
|
||||
/// Waits for any asynchronous operations running on the device to complete.
|
||||
///
|
||||
VTKM_CONT_EXPORT static void Synchronize();
|
||||
|
||||
/// \brief Reduce an array to only the unique values it contains
|
||||
///
|
||||
/// Removes all duplicate values in \c values that are adjacent to each
|
||||
/// other. Which means you should sort the input array unless you want
|
||||
/// duplicate values that aren't adjacent. Note the values array size might
|
||||
/// be modified by this operation.
|
||||
///
|
||||
template<typename T, class Container>
|
||||
VTKM_CONT_EXPORT static void Unique(
|
||||
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag>& values);
|
||||
|
||||
/// \brief Reduce an array to only the unique values it contains
|
||||
///
|
||||
/// Removes all duplicate values in \c values that are adjacent to each
|
||||
/// other. Which means you should sort the input array unless you want
|
||||
/// duplicate values that aren't adjacent. Note the values array size might
|
||||
/// be modified by this operation.
|
||||
///
|
||||
/// Uses the custom binary predicate Comparison to determine if something
|
||||
/// is unique. The predicate must return true if the two items are the same.
|
||||
///
|
||||
template<typename T, class Container, class Compare>
|
||||
VTKM_CONT_EXPORT static void Unique(
|
||||
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag>& values,
|
||||
Compare comp);
|
||||
|
||||
/// \brief Output is the last index in input for each item in values that wouldn't alter the ordering of input
|
||||
///
|
||||
/// UpperBounds is a vectorized search. From each value in \c values it finds
|
||||
/// the last place the item can be inserted in the ordered \c input array and
|
||||
/// stores the index in \c output.
|
||||
///
|
||||
/// \par Requirements:
|
||||
/// \arg \c input must already be sorted
|
||||
///
|
||||
template<typename T, class CIn, class CVal, class COut>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag___>& input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag___>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag___>& output);
|
||||
|
||||
/// \brief Output is the last index in input for each item in values that wouldn't alter the ordering of input
|
||||
///
|
||||
/// LowerBounds is a vectorized search. From each value in \c values it finds
|
||||
/// the last place the item can be inserted in the ordered \c input array and
|
||||
/// stores the index in \c output. Uses the custom comparison functor to
|
||||
/// determine the correct location for each item.
|
||||
///
|
||||
/// \par Requirements:
|
||||
/// \arg \c input must already be sorted
|
||||
///
|
||||
template<typename T, class CIn, class CVal, class COut, class Compare>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output,
|
||||
Compare comp);
|
||||
|
||||
/// \brief A special version of UpperBounds that does an in place operation.
|
||||
///
|
||||
/// This version of lower bounds performs an in place operation where each
|
||||
/// value in the \c values_output array is replaced by the last index in
|
||||
/// \c input where it occurs. Because this is an in place operation, the type
|
||||
/// of the arrays is limited to vtkm::Id.
|
||||
///
|
||||
template<class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id,CIn,DeviceAdapterTag___>& input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag___>& values_output);
|
||||
};
|
||||
#else // VTKM_DOXYGEN_ONLY
|
||||
;
|
||||
#endif //VTKM_DOXYGEN_ONLY
|
||||
|
||||
/// \brief Class providing a device-specific timer.
|
||||
///
|
||||
/// The class provide the actual implementation used by vtkm::cont::Timer.
|
||||
/// A default implementation is provided but device adapters should provide
|
||||
/// one (in conjunction with DeviceAdapterAlgorithm) where appropriate. The
|
||||
/// interface for this class is exactly the same as vtkm::cont::Timer.
|
||||
///
|
||||
template<class DeviceAdapterTag>
|
||||
class DeviceAdapterTimerImplementation
|
||||
{
|
||||
public:
|
||||
/// When a timer is constructed, all threads are synchronized and the
|
||||
/// current time is marked so that GetElapsedTime returns the number of
|
||||
/// seconds elapsed since the construction.
|
||||
VTKM_CONT_EXPORT DeviceAdapterTimerImplementation()
|
||||
{
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
/// Resets the timer. All further calls to GetElapsedTime will report the
|
||||
/// number of seconds elapsed since the call to this. This method
|
||||
/// synchronizes all asynchronous operations.
|
||||
///
|
||||
VTKM_CONT_EXPORT void Reset()
|
||||
{
|
||||
this->StartTime = this->GetCurrentTime();
|
||||
}
|
||||
|
||||
/// Returns the elapsed time in seconds between the construction of this
|
||||
/// class or the last call to Reset and the time this function is called. The
|
||||
/// time returned is measured in wall time. GetElapsedTime may be called any
|
||||
/// number of times to get the progressive time. This method synchronizes all
|
||||
/// asynchronous operations.
|
||||
///
|
||||
VTKM_CONT_EXPORT vtkm::Scalar GetElapsedTime()
|
||||
{
|
||||
TimeStamp currentTime = this->GetCurrentTime();
|
||||
|
||||
vtkm::Scalar elapsedTime;
|
||||
elapsedTime = currentTime.Seconds - this->StartTime.Seconds;
|
||||
elapsedTime += ((currentTime.Microseconds - this->StartTime.Microseconds)
|
||||
/vtkm::Scalar(1000000));
|
||||
|
||||
return elapsedTime;
|
||||
}
|
||||
struct TimeStamp {
|
||||
vtkm::internal::Int64Type Seconds;
|
||||
vtkm::internal::Int64Type Microseconds;
|
||||
};
|
||||
TimeStamp StartTime;
|
||||
|
||||
VTKM_CONT_EXPORT TimeStamp GetCurrentTime()
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>
|
||||
::Synchronize();
|
||||
|
||||
TimeStamp retval;
|
||||
#ifdef _WIN32
|
||||
timeb currentTime;
|
||||
::ftime(¤tTime);
|
||||
retval.Seconds = currentTime.time;
|
||||
retval.Microseconds = 1000*currentTime.millitm;
|
||||
#else
|
||||
timeval currentTime;
|
||||
gettimeofday(¤tTime, NULL);
|
||||
retval.Seconds = currentTime.tv_sec;
|
||||
retval.Microseconds = currentTime.tv_usec;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// These includes are intentionally placed here after the declaration of the
|
||||
// DeviceAdapterAlgorithm template prototype, which all the implementations
|
||||
// need.
|
||||
|
||||
#if VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_SERIAL
|
||||
#include <vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h>
|
||||
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_CUDA
|
||||
// #include <vtkm/cuda/cont/internal/DeviceAdapterAlgorithmCuda.h>
|
||||
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_OPENMP
|
||||
// #include <vtkm/openmp/cont/internal/DeviceAdapterAlgorithmOpenMP.h>
|
||||
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_TBB
|
||||
// #include <vtkm/tbb/cont/internal/DeviceAdapterAlgorithmTBB.h>
|
||||
#endif
|
||||
|
||||
#endif //vtkm_cont_DeviceAdapterAlgorithm_h
|
993
vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h
Normal file
993
vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h
Normal file
@ -0,0 +1,993 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h
|
||||
#define vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayContainerControlBasic.h>
|
||||
|
||||
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
||||
#include <vtkm/exec/internal/WorkletBase.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Predicate that takes a single argument \c x, and returns
|
||||
/// True if it isn't the identity of the Type \p T.
|
||||
template<typename T>
|
||||
struct not_default_constructor
|
||||
{
|
||||
VTKM_EXEC_CONT_EXPORT bool operator()(const T &x)
|
||||
{
|
||||
return (x != T());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
namespace internal {
|
||||
|
||||
/// \brief
|
||||
///
|
||||
/// This struct provides algorithms that implement "general" device adapter
|
||||
/// algorithms. If a device adapter provides implementations for Schedule,
|
||||
/// and Synchronize, the rest of the algorithms can be implemented by calling
|
||||
/// these functions.
|
||||
///
|
||||
/// It should be noted that we recommend that you also implement Sort,
|
||||
/// ScanInclusive, and ScanExclusive for improved performance.
|
||||
///
|
||||
/// An easy way to implement the DeviceAdapterAlgorithm specialization is to
|
||||
/// subclass this and override the implementation of methods as necessary.
|
||||
/// As an example, the code would look something like this.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// template<>
|
||||
/// struct DeviceAdapterAlgorithm<DeviceAdapterTagFoo>
|
||||
/// : DeviceAdapterAlgorithmGeneral<DeviceAdapterAlgorithm<DeviceAdapterTagFoo>,
|
||||
/// DeviceAdapterTagFoo>
|
||||
/// {
|
||||
/// template<class Functor>
|
||||
/// VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
/// vtkm::Id numInstances)
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// template<class Functor>
|
||||
/// VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
/// vtkm::Id3 maxRange)
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// VTKM_CONT_EXPORT static void Synchronize()
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// You might note that DeviceAdapterAlgorithmGeneral has two template
|
||||
/// parameters that are redundant. Although the first parameter, the class for
|
||||
/// the actual DeviceAdapterAlgorithm class containing Schedule, and
|
||||
/// Synchronize is the same as DeviceAdapterAlgorithm<DeviceAdapterTag>, it is
|
||||
/// made a separate template parameter to avoid a recursive dependence between
|
||||
/// DeviceAdapterAlgorithmGeneral.h and DeviceAdapterAlgorithm.h
|
||||
///
|
||||
template<class DerivedAlgorithm, class DeviceAdapterTag>
|
||||
struct DeviceAdapterAlgorithmGeneral
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
// Get Execution Value
|
||||
// This method is used internally to get a single element from the execution
|
||||
// array. Might want to expose this and/or allow actual device adapter
|
||||
// implementations to provide one.
|
||||
private:
|
||||
template<typename T, class CIn>
|
||||
VTKM_CONT_EXPORT
|
||||
static T GetExecutionValue(const vtkm::cont::ArrayHandle<T, CIn> &input,
|
||||
vtkm::Id index)
|
||||
{
|
||||
typedef vtkm::cont::ArrayHandle<T,CIn> InputArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<T,vtkm::cont::ArrayContainerControlTagBasic>
|
||||
OutputArrayType;
|
||||
|
||||
OutputArrayType output;
|
||||
|
||||
CopyKernel<
|
||||
typename InputArrayType::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename OutputArrayType::template ExecutionTypes<DeviceAdapterTag>::Portal>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(1, DeviceAdapterTag()),
|
||||
index);
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, 1);
|
||||
|
||||
return output.GetPortalConstControl().Get(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Copy
|
||||
private:
|
||||
template<class InputPortalType, class OutputPortalType>
|
||||
struct CopyKernel {
|
||||
InputPortalType InputPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
vtkm::Id InputOffset;
|
||||
vtkm::Id OutputOffset;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
CopyKernel(InputPortalType inputPortal,
|
||||
OutputPortalType outputPortal,
|
||||
vtkm::Id inputOffset = 0,
|
||||
vtkm::Id outputOffset = 0)
|
||||
: InputPortal(inputPortal),
|
||||
OutputPortal(outputPortal),
|
||||
InputOffset(inputOffset),
|
||||
OutputOffset(outputOffset)
|
||||
{ }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
this->OutputPortal.Set(
|
||||
index + this->OutputOffset,
|
||||
this->InputPortal.Get(index + this->InputOffset));
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename T, class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void Copy(const vtkm::cont::ArrayHandle<T, CIn> &input,
|
||||
vtkm::cont::ArrayHandle<T, COut> &output)
|
||||
{
|
||||
vtkm::Id arraySize = input.GetNumberOfValues();
|
||||
|
||||
CopyKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, arraySize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Lower Bounds
|
||||
private:
|
||||
template<class InputPortalType,class ValuesPortalType,class OutputPortalType>
|
||||
struct LowerBoundsKernel {
|
||||
InputPortalType InputPortal;
|
||||
ValuesPortalType ValuesPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
LowerBoundsKernel(InputPortalType inputPortal,
|
||||
ValuesPortalType valuesPortal,
|
||||
OutputPortalType outputPortal)
|
||||
: InputPortal(inputPortal),
|
||||
ValuesPortal(valuesPortal),
|
||||
OutputPortal(outputPortal) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
// This method assumes that (1) InputPortalType can return working
|
||||
// iterators in the execution environment and that (2) methods not
|
||||
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
|
||||
// called from the execution environment. Neither one of these is
|
||||
// necessarily true, but it is true for the current uses of this general
|
||||
// function and I don't want to compete with STL if I don't have to.
|
||||
|
||||
typename InputPortalType::IteratorType resultPos =
|
||||
std::lower_bound(this->InputPortal.GetIteratorBegin(),
|
||||
this->InputPortal.GetIteratorEnd(),
|
||||
this->ValuesPortal.Get(index));
|
||||
|
||||
vtkm::Id resultIndex =
|
||||
static_cast<vtkm::Id>(
|
||||
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
|
||||
this->OutputPortal.Set(index, resultIndex);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
template<class InputPortalType,class ValuesPortalType,class OutputPortalType,class Compare>
|
||||
struct LowerBoundsComparisonKernel {
|
||||
InputPortalType InputPortal;
|
||||
ValuesPortalType ValuesPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
Compare CompareFunctor;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
LowerBoundsComparisonKernel(InputPortalType inputPortal,
|
||||
ValuesPortalType valuesPortal,
|
||||
OutputPortalType outputPortal,
|
||||
Compare comp)
|
||||
: InputPortal(inputPortal),
|
||||
ValuesPortal(valuesPortal),
|
||||
OutputPortal(outputPortal),
|
||||
CompareFunctor(comp) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
// This method assumes that (1) InputPortalType can return working
|
||||
// iterators in the execution environment and that (2) methods not
|
||||
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
|
||||
// called from the execution environment. Neither one of these is
|
||||
// necessarily true, but it is true for the current uses of this general
|
||||
// function and I don't want to compete with STL if I don't have to.
|
||||
|
||||
typename InputPortalType::IteratorType resultPos =
|
||||
std::lower_bound(this->InputPortal.GetIteratorBegin(),
|
||||
this->InputPortal.GetIteratorEnd(),
|
||||
this->ValuesPortal.Get(index),
|
||||
this->CompareFunctor);
|
||||
|
||||
vtkm::Id resultIndex =
|
||||
static_cast<vtkm::Id>(
|
||||
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
|
||||
this->OutputPortal.Set(index, resultIndex);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
template<typename T, class CIn, class CVal, class COut>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal> &values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
|
||||
{
|
||||
vtkm::Id arraySize = values.GetNumberOfValues();
|
||||
|
||||
LowerBoundsKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<vtkm::Id,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
values.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, arraySize);
|
||||
}
|
||||
|
||||
template<typename T, class CIn, class CVal, class COut, class Compare>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal> &values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output,
|
||||
Compare comp)
|
||||
{
|
||||
vtkm::Id arraySize = values.GetNumberOfValues();
|
||||
|
||||
LowerBoundsComparisonKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<vtkm::Id,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal,
|
||||
Compare>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
values.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(arraySize, DeviceAdapterTag()),
|
||||
comp);
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, arraySize);
|
||||
}
|
||||
|
||||
template<class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void LowerBounds(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id,CIn> &input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &values_output)
|
||||
{
|
||||
DeviceAdapterAlgorithmGeneral<
|
||||
DerivedAlgorithm,DeviceAdapterTag>::LowerBounds(input,
|
||||
values_output,
|
||||
values_output);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Scan Exclusive
|
||||
private:
|
||||
template<typename PortalType>
|
||||
struct SetConstantKernel
|
||||
{
|
||||
typedef typename PortalType::ValueType ValueType;
|
||||
PortalType Portal;
|
||||
ValueType Value;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
SetConstantKernel(const PortalType &portal, ValueType value)
|
||||
: Portal(portal), Value(value) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const
|
||||
{
|
||||
this->Portal.Set(index, this->Value);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
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 vtkm::cont::ArrayHandle<T,vtkm::cont::ArrayContainerControlTagBasic>
|
||||
TempArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<T,COut> OutputArrayType;
|
||||
|
||||
TempArrayType inclusiveScan;
|
||||
T result = DerivedAlgorithm::ScanInclusive(input, inclusiveScan);
|
||||
|
||||
vtkm::Id numValues = inclusiveScan.GetNumberOfValues();
|
||||
if (numValues < 1)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef typename TempArrayType::template ExecutionTypes<DeviceAdapterTag>
|
||||
::PortalConst SrcPortalType;
|
||||
SrcPortalType srcPortal = inclusiveScan.PrepareForInput(DeviceAdapterTag());
|
||||
|
||||
typedef typename OutputArrayType::template ExecutionTypes<DeviceAdapterTag>
|
||||
::Portal DestPortalType;
|
||||
DestPortalType destPortal = output.PrepareForOutput(numValues,
|
||||
DeviceAdapterTag());
|
||||
|
||||
// Set first value in output (always 0).
|
||||
DerivedAlgorithm::Schedule(
|
||||
SetConstantKernel<DestPortalType>(destPortal,0), 1);
|
||||
// Shift remaining values over by one.
|
||||
DerivedAlgorithm::Schedule(
|
||||
CopyKernel<SrcPortalType,DestPortalType>(srcPortal,
|
||||
destPortal,
|
||||
0,
|
||||
1),
|
||||
numValues - 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Scan Inclusive
|
||||
private:
|
||||
template<typename PortalType>
|
||||
struct ScanKernel : vtkm::exec::internal::WorkletBase
|
||||
{
|
||||
PortalType Portal;
|
||||
vtkm::Id Stride;
|
||||
vtkm::Id Offset;
|
||||
vtkm::Id Distance;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
ScanKernel(const PortalType &portal, vtkm::Id stride, vtkm::Id offset)
|
||||
: Portal(portal),
|
||||
Stride(stride),
|
||||
Offset(offset),
|
||||
Distance(stride/2)
|
||||
{ }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const
|
||||
{
|
||||
typedef typename PortalType::ValueType ValueType;
|
||||
|
||||
vtkm::Id leftIndex = this->Offset + index*this->Stride;
|
||||
vtkm::Id rightIndex = leftIndex + this->Distance;
|
||||
|
||||
if (rightIndex < this->Portal.GetNumberOfValues())
|
||||
{
|
||||
ValueType leftValue = this->Portal.Get(leftIndex);
|
||||
ValueType rightValue = this->Portal.Get(rightIndex);
|
||||
this->Portal.Set(rightIndex, leftValue+rightValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
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<DeviceAdapterTag>::Portal PortalType;
|
||||
|
||||
DerivedAlgorithm::Copy(input, output);
|
||||
|
||||
vtkm::Id numValues = output.GetNumberOfValues();
|
||||
if (numValues < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PortalType portal = output.PrepareForInPlace(DeviceAdapterTag());
|
||||
|
||||
vtkm::Id stride;
|
||||
for (stride = 2; stride-1 < numValues; stride *= 2)
|
||||
{
|
||||
ScanKernel<PortalType> kernel(portal, stride, stride/2 - 1);
|
||||
DerivedAlgorithm::Schedule(kernel, numValues/stride);
|
||||
}
|
||||
|
||||
// Do reverse operation on odd indices. Start at stride we were just at.
|
||||
for (stride /= 2; stride > 1; stride /= 2)
|
||||
{
|
||||
ScanKernel<PortalType> kernel(portal, stride, stride - 1);
|
||||
DerivedAlgorithm::Schedule(kernel, numValues/stride);
|
||||
}
|
||||
|
||||
return GetExecutionValue(output, numValues-1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Sort
|
||||
private:
|
||||
template<typename PortalType, typename CompareType>
|
||||
struct BitonicSortMergeKernel : vtkm::exec::internal::WorkletBase
|
||||
{
|
||||
PortalType Portal;
|
||||
CompareType Compare;
|
||||
vtkm::Id GroupSize;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
BitonicSortMergeKernel(const PortalType &portal,
|
||||
const CompareType &compare,
|
||||
vtkm::Id groupSize)
|
||||
: Portal(portal), Compare(compare), GroupSize(groupSize) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
typedef typename PortalType::ValueType ValueType;
|
||||
|
||||
vtkm::Id groupIndex = index%this->GroupSize;
|
||||
vtkm::Id blockSize = 2*this->GroupSize;
|
||||
vtkm::Id blockIndex = index/this->GroupSize;
|
||||
|
||||
vtkm::Id lowIndex = blockIndex * blockSize + groupIndex;
|
||||
vtkm::Id highIndex = lowIndex + this->GroupSize;
|
||||
|
||||
if (highIndex < this->Portal.GetNumberOfValues())
|
||||
{
|
||||
ValueType lowValue = this->Portal.Get(lowIndex);
|
||||
ValueType highValue = this->Portal.Get(highIndex);
|
||||
if (this->Compare(highValue, lowValue))
|
||||
{
|
||||
this->Portal.Set(highIndex, lowValue);
|
||||
this->Portal.Set(lowIndex, highValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PortalType, typename CompareType>
|
||||
struct BitonicSortCrossoverKernel : vtkm::exec::internal::WorkletBase
|
||||
{
|
||||
PortalType Portal;
|
||||
CompareType Compare;
|
||||
vtkm::Id GroupSize;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
BitonicSortCrossoverKernel(const PortalType &portal,
|
||||
const CompareType &compare,
|
||||
vtkm::Id groupSize)
|
||||
: Portal(portal), Compare(compare), GroupSize(groupSize) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
typedef typename PortalType::ValueType ValueType;
|
||||
|
||||
vtkm::Id groupIndex = index%this->GroupSize;
|
||||
vtkm::Id blockSize = 2*this->GroupSize;
|
||||
vtkm::Id blockIndex = index/this->GroupSize;
|
||||
|
||||
vtkm::Id lowIndex = blockIndex*blockSize + groupIndex;
|
||||
vtkm::Id highIndex = blockIndex*blockSize + (blockSize - groupIndex - 1);
|
||||
|
||||
if (highIndex < this->Portal.GetNumberOfValues())
|
||||
{
|
||||
ValueType lowValue = this->Portal.Get(lowIndex);
|
||||
ValueType highValue = this->Portal.Get(highIndex);
|
||||
if (this->Compare(highValue, lowValue))
|
||||
{
|
||||
this->Portal.Set(highIndex, lowValue);
|
||||
this->Portal.Set(lowIndex, highValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct DefaultCompareFunctor
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
VTKM_EXEC_EXPORT
|
||||
bool operator()(const T& first, const T& second) const
|
||||
{
|
||||
return first < second;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename T, class Container, class CompareType>
|
||||
VTKM_CONT_EXPORT static void Sort(
|
||||
vtkm::cont::ArrayHandle<T,Container> &values,
|
||||
CompareType compare)
|
||||
{
|
||||
typedef typename vtkm::cont::ArrayHandle<T,Container> ArrayType;
|
||||
typedef typename ArrayType::template ExecutionTypes<DeviceAdapterTag>
|
||||
::Portal PortalType;
|
||||
|
||||
vtkm::Id numValues = values.GetNumberOfValues();
|
||||
if (numValues < 2) { return; }
|
||||
|
||||
PortalType portal = values.PrepareForInPlace(DeviceAdapterTag());
|
||||
|
||||
vtkm::Id numThreads = 1;
|
||||
while (numThreads < numValues) { numThreads *= 2; }
|
||||
numThreads /= 2;
|
||||
|
||||
typedef BitonicSortMergeKernel<PortalType,CompareType> MergeKernel;
|
||||
typedef BitonicSortCrossoverKernel<PortalType,CompareType> CrossoverKernel;
|
||||
|
||||
for (vtkm::Id crossoverSize = 1;
|
||||
crossoverSize < numValues;
|
||||
crossoverSize *= 2)
|
||||
{
|
||||
DerivedAlgorithm::Schedule(CrossoverKernel(portal,compare,crossoverSize),
|
||||
numThreads);
|
||||
for (vtkm::Id mergeSize = crossoverSize/2; mergeSize > 0; mergeSize /= 2)
|
||||
{
|
||||
DerivedAlgorithm::Schedule(MergeKernel(portal,compare,mergeSize),
|
||||
numThreads);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, class Container>
|
||||
VTKM_CONT_EXPORT static void Sort(
|
||||
vtkm::cont::ArrayHandle<T,Container> &values)
|
||||
{
|
||||
DerivedAlgorithm::Sort(values, DefaultCompareFunctor());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Stream Compact
|
||||
private:
|
||||
template<class StencilPortalType, class OutputPortalType>
|
||||
struct StencilToIndexFlagKernel
|
||||
{
|
||||
typedef typename StencilPortalType::ValueType StencilValueType;
|
||||
StencilPortalType StencilPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
StencilToIndexFlagKernel(StencilPortalType stencilPortal,
|
||||
OutputPortalType outputPortal)
|
||||
: StencilPortal(stencilPortal), OutputPortal(outputPortal) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const
|
||||
{
|
||||
StencilValueType value = this->StencilPortal.Get(index);
|
||||
bool flag = not_default_constructor<StencilValueType>()(value);
|
||||
this->OutputPortal.Set(index, flag ? 1 : 0);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
template<class InputPortalType,
|
||||
class StencilPortalType,
|
||||
class IndexPortalType,
|
||||
class OutputPortalType>
|
||||
struct CopyIfKernel
|
||||
{
|
||||
InputPortalType InputPortal;
|
||||
StencilPortalType StencilPortal;
|
||||
IndexPortalType IndexPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
CopyIfKernel(InputPortalType inputPortal,
|
||||
StencilPortalType stencilPortal,
|
||||
IndexPortalType indexPortal,
|
||||
OutputPortalType outputPortal)
|
||||
: InputPortal(inputPortal),
|
||||
StencilPortal(stencilPortal),
|
||||
IndexPortal(indexPortal),
|
||||
OutputPortal(outputPortal) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const
|
||||
{
|
||||
typedef typename StencilPortalType::ValueType StencilValueType;
|
||||
StencilValueType stencilValue = this->StencilPortal.Get(index);
|
||||
if (not_default_constructor<StencilValueType>()(stencilValue))
|
||||
{
|
||||
vtkm::Id outputIndex = this->IndexPortal.Get(index);
|
||||
|
||||
typedef typename OutputPortalType::ValueType OutputValueType;
|
||||
OutputValueType value = this->InputPortal.Get(index);
|
||||
|
||||
this->OutputPortal.Set(outputIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<typename T, typename U, class CIn, class CStencil, class COut>
|
||||
VTKM_CONT_EXPORT static void StreamCompact(
|
||||
const vtkm::cont::ArrayHandle<T,CIn>& input,
|
||||
const vtkm::cont::ArrayHandle<U,CStencil>& stencil,
|
||||
vtkm::cont::ArrayHandle<T,COut>& output)
|
||||
{
|
||||
VTKM_ASSERT_CONT(input.GetNumberOfValues() == stencil.GetNumberOfValues());
|
||||
vtkm::Id arrayLength = stencil.GetNumberOfValues();
|
||||
|
||||
typedef vtkm::cont::ArrayHandle<
|
||||
vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic> IndexArrayType;
|
||||
IndexArrayType indices;
|
||||
|
||||
typedef typename vtkm::cont::ArrayHandle<U,CStencil>
|
||||
::template ExecutionTypes<DeviceAdapterTag>::PortalConst
|
||||
StencilPortalType;
|
||||
StencilPortalType stencilPortal =
|
||||
stencil.PrepareForInput(DeviceAdapterTag());
|
||||
|
||||
typedef typename IndexArrayType
|
||||
::template ExecutionTypes<DeviceAdapterTag>::Portal IndexPortalType;
|
||||
IndexPortalType indexPortal =
|
||||
indices.PrepareForOutput(arrayLength, DeviceAdapterTag());
|
||||
|
||||
StencilToIndexFlagKernel<
|
||||
StencilPortalType, IndexPortalType> indexKernel(stencilPortal,
|
||||
indexPortal);
|
||||
|
||||
DerivedAlgorithm::Schedule(indexKernel, arrayLength);
|
||||
|
||||
vtkm::Id outArrayLength = DerivedAlgorithm::ScanExclusive(indices, indices);
|
||||
|
||||
typedef typename vtkm::cont::ArrayHandle<T,CIn>
|
||||
::template ExecutionTypes<DeviceAdapterTag>::PortalConst
|
||||
InputPortalType;
|
||||
InputPortalType inputPortal = input.PrepareForInput(DeviceAdapterTag());
|
||||
|
||||
typedef typename vtkm::cont::ArrayHandle<T,COut>
|
||||
::template ExecutionTypes<DeviceAdapterTag>::Portal OutputPortalType;
|
||||
OutputPortalType outputPortal =
|
||||
output.PrepareForOutput(outArrayLength, DeviceAdapterTag());
|
||||
|
||||
CopyIfKernel<
|
||||
InputPortalType,
|
||||
StencilPortalType,
|
||||
IndexPortalType,
|
||||
OutputPortalType>copyKernel(inputPortal,
|
||||
stencilPortal,
|
||||
indexPortal,
|
||||
outputPortal);
|
||||
DerivedAlgorithm::Schedule(copyKernel, arrayLength);
|
||||
}
|
||||
|
||||
template<typename T, class CStencil, class COut>
|
||||
VTKM_CONT_EXPORT static void StreamCompact(
|
||||
const vtkm::cont::ArrayHandle<T,CStencil> &stencil,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
|
||||
{
|
||||
typedef vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandleType;
|
||||
|
||||
CountingHandleType input =
|
||||
vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0),
|
||||
stencil.GetNumberOfValues());
|
||||
DerivedAlgorithm::StreamCompact(input, stencil, output);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Unique
|
||||
private:
|
||||
template<class InputPortalType, class StencilPortalType>
|
||||
struct ClassifyUniqueKernel {
|
||||
InputPortalType InputPortal;
|
||||
StencilPortalType StencilPortal;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
ClassifyUniqueKernel(InputPortalType inputPortal,
|
||||
StencilPortalType stencilPortal)
|
||||
: InputPortal(inputPortal), StencilPortal(stencilPortal) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
typedef typename StencilPortalType::ValueType ValueType;
|
||||
if (index == 0)
|
||||
{
|
||||
// Always copy first value.
|
||||
this->StencilPortal.Set(index, ValueType(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
ValueType flag = ValueType(this->InputPortal.Get(index-1)
|
||||
!= this->InputPortal.Get(index));
|
||||
this->StencilPortal.Set(index, flag);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
template<class InputPortalType, class StencilPortalType, class Compare>
|
||||
struct ClassifyUniqueComparisonKernel {
|
||||
InputPortalType InputPortal;
|
||||
StencilPortalType StencilPortal;
|
||||
Compare CompareFunctor;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
ClassifyUniqueComparisonKernel(InputPortalType inputPortal,
|
||||
StencilPortalType stencilPortal,
|
||||
Compare comp):
|
||||
InputPortal(inputPortal),
|
||||
StencilPortal(stencilPortal),
|
||||
CompareFunctor(comp) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
typedef typename StencilPortalType::ValueType ValueType;
|
||||
if (index == 0)
|
||||
{
|
||||
// Always copy first value.
|
||||
this->StencilPortal.Set(index, ValueType(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//comparison predicate returns true when they match
|
||||
const bool same = !(this->CompareFunctor(this->InputPortal.Get(index-1),
|
||||
this->InputPortal.Get(index)));
|
||||
ValueType flag = ValueType(same);
|
||||
this->StencilPortal.Set(index, flag);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename T, class Container>
|
||||
VTKM_CONT_EXPORT static void Unique(
|
||||
vtkm::cont::ArrayHandle<T,Container> &values)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic>
|
||||
stencilArray;
|
||||
vtkm::Id inputSize = values.GetNumberOfValues();
|
||||
|
||||
ClassifyUniqueKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,Container>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<vtkm::Id,vtkm::cont::ArrayContainerControlTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal>
|
||||
classifyKernel(values.PrepareForInput(DeviceAdapterTag()),
|
||||
stencilArray.PrepareForOutput(inputSize, DeviceAdapterTag()));
|
||||
DerivedAlgorithm::Schedule(classifyKernel, inputSize);
|
||||
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::ArrayContainerControlTagBasic>
|
||||
outputArray;
|
||||
|
||||
DerivedAlgorithm::StreamCompact(values, stencilArray, outputArray);
|
||||
|
||||
DerivedAlgorithm::Copy(outputArray, values);
|
||||
}
|
||||
|
||||
template<typename T, class Container, class Compare>
|
||||
VTKM_CONT_EXPORT static void Unique(
|
||||
vtkm::cont::ArrayHandle<T,Container> &values,
|
||||
Compare comp)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic>
|
||||
stencilArray;
|
||||
vtkm::Id inputSize = values.GetNumberOfValues();
|
||||
|
||||
ClassifyUniqueComparisonKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,Container>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<vtkm::Id,vtkm::cont::ArrayContainerControlTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal,
|
||||
Compare>
|
||||
classifyKernel(values.PrepareForInput(DeviceAdapterTag()),
|
||||
stencilArray.PrepareForOutput(inputSize, DeviceAdapterTag()),
|
||||
comp);
|
||||
DerivedAlgorithm::Schedule(classifyKernel, inputSize);
|
||||
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::ArrayContainerControlTagBasic>
|
||||
outputArray;
|
||||
|
||||
DerivedAlgorithm::StreamCompact(values, stencilArray, outputArray);
|
||||
|
||||
DerivedAlgorithm::Copy(outputArray, values);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Upper bounds
|
||||
private:
|
||||
template<class InputPortalType,class ValuesPortalType,class OutputPortalType>
|
||||
struct UpperBoundsKernel {
|
||||
InputPortalType InputPortal;
|
||||
ValuesPortalType ValuesPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
UpperBoundsKernel(InputPortalType inputPortal,
|
||||
ValuesPortalType valuesPortal,
|
||||
OutputPortalType outputPortal)
|
||||
: InputPortal(inputPortal),
|
||||
ValuesPortal(valuesPortal),
|
||||
OutputPortal(outputPortal) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
// This method assumes that (1) InputPortalType can return working
|
||||
// iterators in the execution environment and that (2) methods not
|
||||
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
|
||||
// called from the execution environment. Neither one of these is
|
||||
// necessarily true, but it is true for the current uses of this general
|
||||
// function and I don't want to compete with STL if I don't have to.
|
||||
|
||||
typename InputPortalType::IteratorType resultPos =
|
||||
std::upper_bound(this->InputPortal.GetIteratorBegin(),
|
||||
this->InputPortal.GetIteratorEnd(),
|
||||
this->ValuesPortal.Get(index));
|
||||
|
||||
vtkm::Id resultIndex =
|
||||
static_cast<vtkm::Id>(
|
||||
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
|
||||
this->OutputPortal.Set(index, resultIndex);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
template<class InputPortalType,class ValuesPortalType,class OutputPortalType,class Compare>
|
||||
struct UpperBoundsKernelComparisonKernel {
|
||||
InputPortalType InputPortal;
|
||||
ValuesPortalType ValuesPortal;
|
||||
OutputPortalType OutputPortal;
|
||||
Compare CompareFunctor;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
UpperBoundsKernelComparisonKernel(InputPortalType inputPortal,
|
||||
ValuesPortalType valuesPortal,
|
||||
OutputPortalType outputPortal,
|
||||
Compare comp)
|
||||
: InputPortal(inputPortal),
|
||||
ValuesPortal(valuesPortal),
|
||||
OutputPortal(outputPortal),
|
||||
CompareFunctor(comp) { }
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const {
|
||||
// This method assumes that (1) InputPortalType can return working
|
||||
// iterators in the execution environment and that (2) methods not
|
||||
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
|
||||
// called from the execution environment. Neither one of these is
|
||||
// necessarily true, but it is true for the current uses of this general
|
||||
// function and I don't want to compete with STL if I don't have to.
|
||||
|
||||
typename InputPortalType::IteratorType resultPos =
|
||||
std::upper_bound(this->InputPortal.GetIteratorBegin(),
|
||||
this->InputPortal.GetIteratorEnd(),
|
||||
this->ValuesPortal.Get(index),
|
||||
this->CompareFunctor);
|
||||
|
||||
vtkm::Id resultIndex =
|
||||
static_cast<vtkm::Id>(
|
||||
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
|
||||
this->OutputPortal.Set(index, resultIndex);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename T, class CIn, class CVal, class COut>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal> &values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
|
||||
{
|
||||
vtkm::Id arraySize = values.GetNumberOfValues();
|
||||
|
||||
UpperBoundsKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
values.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, arraySize);
|
||||
}
|
||||
|
||||
template<typename T, class CIn, class CVal, class COut, class Compare>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<T,CIn> &input,
|
||||
const vtkm::cont::ArrayHandle<T,CVal> &values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output,
|
||||
Compare comp)
|
||||
{
|
||||
vtkm::Id arraySize = values.GetNumberOfValues();
|
||||
|
||||
UpperBoundsKernelComparisonKernel<
|
||||
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
|
||||
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal,
|
||||
Compare>
|
||||
kernel(input.PrepareForInput(DeviceAdapterTag()),
|
||||
values.PrepareForInput(DeviceAdapterTag()),
|
||||
output.PrepareForOutput(arraySize, DeviceAdapterTag()),
|
||||
comp);
|
||||
|
||||
DerivedAlgorithm::Schedule(kernel, arraySize);
|
||||
}
|
||||
|
||||
template<class CIn, class COut>
|
||||
VTKM_CONT_EXPORT static void UpperBounds(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id,CIn> &input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id,COut> &values_output)
|
||||
{
|
||||
DeviceAdapterAlgorithmGeneral<DerivedAlgorithm,
|
||||
DeviceAdapterTag>::UpperBounds(input, values_output, values_output);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
||||
#endif //vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h
|
190
vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h
Normal file
190
vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h
Normal file
@ -0,0 +1,190 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h
|
||||
#define vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ErrorExecution.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterAlgorithm.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 {
|
||||
|
||||
template<>
|
||||
struct DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial> :
|
||||
vtkm::cont::internal::DeviceAdapterAlgorithmGeneral<
|
||||
DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial>,
|
||||
vtkm::cont::DeviceAdapterTagSerial>
|
||||
{
|
||||
private:
|
||||
typedef vtkm::cont::DeviceAdapterTagSerial Device;
|
||||
|
||||
public:
|
||||
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());
|
||||
|
||||
if (numberOfValues <= 0) { return 0; }
|
||||
|
||||
std::partial_sum(inputPortal.GetIteratorBegin(),
|
||||
inputPortal.GetIteratorEnd(),
|
||||
outputPortal.GetIteratorBegin());
|
||||
|
||||
// Return the value at the last index in the array, which is the full sum.
|
||||
return outputPortal.Get(numberOfValues - 1);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
if (numberOfValues <= 0) { return 0; }
|
||||
|
||||
std::partial_sum(inputPortal.GetIteratorBegin(),
|
||||
inputPortal.GetIteratorEnd(),
|
||||
outputPortal.GetIteratorBegin());
|
||||
|
||||
T fullSum = outputPortal.Get(numberOfValues - 1);
|
||||
|
||||
// Shift right by one
|
||||
std::copy_backward(outputPortal.GetIteratorBegin(),
|
||||
outputPortal.GetIteratorEnd()-1,
|
||||
outputPortal.GetIteratorEnd());
|
||||
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,
|
||||
vtkm::Id numInstances)
|
||||
{
|
||||
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())
|
||||
{
|
||||
throw vtkm::cont::ErrorExecution(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
template<class FunctorType>
|
||||
VTKM_CONT_EXPORT
|
||||
static void Schedule(FunctorType functor, vtkm::Id3 rangeMax)
|
||||
{
|
||||
DeviceAdapterAlgorithm<Device>::Schedule(functor,
|
||||
rangeMax[0] * rangeMax[1] * rangeMax[2] );
|
||||
}
|
||||
|
||||
template<typename T, class Container>
|
||||
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Container>& values)
|
||||
{
|
||||
typedef typename vtkm::cont::ArrayHandle<T,Container>
|
||||
::template ExecutionTypes<Device>::Portal PortalType;
|
||||
|
||||
PortalType arrayPortal = values.PrepareForInPlace(Device());
|
||||
std::sort(arrayPortal.GetIteratorBegin(), arrayPortal.GetIteratorEnd());
|
||||
}
|
||||
|
||||
template<typename T, class Container, class Compare>
|
||||
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Container>& values,
|
||||
Compare comp)
|
||||
{
|
||||
typedef typename vtkm::cont::ArrayHandle<T,Container>
|
||||
::template ExecutionTypes<Device>::Portal PortalType;
|
||||
|
||||
PortalType arrayPortal = values.PrepareForInPlace(Device());
|
||||
std::sort(arrayPortal.GetIteratorBegin(), arrayPortal.GetIteratorEnd(),comp);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT static void Synchronize()
|
||||
{
|
||||
// Nothing to do. This device is serial and has no asynchronous operations.
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif //vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h
|
32
vtkm/cont/internal/DeviceAdapterError.h
Normal file
32
vtkm/cont/internal/DeviceAdapterError.h
Normal file
@ -0,0 +1,32 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterError_h
|
||||
#define vtkm_cont_internal_DeviceAdapterError_h
|
||||
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
|
||||
/// This is an invalid DeviceAdapter. The point of this class is to include the
|
||||
/// header file to make this invalid class the default DeviceAdapter. From that
|
||||
/// point, you have to specify an appropriate DeviceAdapter or else get a
|
||||
/// compile error.
|
||||
///
|
||||
VTKM_CREATE_DEVICE_ADAPTER(Error);
|
||||
|
||||
#endif //vtkm_cont_internal_DeviceAdapterError_h
|
@ -91,6 +91,11 @@ struct DeviceAdapterTagCheck
|
||||
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
|
||||
#define VTKM_DEFAULT_DEVICE_ADAPTER_TAG ::vtkm::cont::DeviceAdapterTagSerial
|
||||
|
||||
#elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_ERROR
|
||||
|
||||
#include <vtkm/cont/internal/DeviceAdapterError.h>
|
||||
#define VTKM_DEFAULT_DEVICE_ADAPTER_TAG ::vtkm::cont::DeviceAdapterTagError
|
||||
|
||||
#elif (VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_UNDEFINED) || !defined(VTKM_DEVICE_ADAPTER)
|
||||
|
||||
#ifndef VTKM_DEFAULT_DEVICE_ADAPTER_TAG
|
||||
|
@ -22,6 +22,6 @@
|
||||
set(unit_tests
|
||||
UnitTestArrayManagerExecutionShareWithControl.cxx
|
||||
UnitTestArrayPortalFromIterators.cxx
|
||||
# UnitTestIteratorFromArrayPortal.cxx
|
||||
UnitTestIteratorFromArrayPortal.cxx
|
||||
)
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
set(headers
|
||||
Testing.h
|
||||
TestingDeviceAdapter.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
@ -28,7 +29,11 @@ set(unit_tests
|
||||
UnitTestArrayContainerControlBasic.cxx
|
||||
UnitTestArrayContainerControlImplicit.cxx
|
||||
UnitTestArrayHandle.cxx
|
||||
UnitTestArrayHandleCounting.cxx
|
||||
UnitTestContTesting.cxx
|
||||
UnitTestDeviceAdapterAlgorithmDependency.cxx
|
||||
UnitTestDeviceAdapterAlgorithmGeneral.cxx
|
||||
UnitTestDeviceAdapterSerial.cxx
|
||||
)
|
||||
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
||||
|
1330
vtkm/cont/testing/TestingDeviceAdapter.h
Normal file
1330
vtkm/cont/testing/TestingDeviceAdapter.h
Normal file
File diff suppressed because it is too large
Load Diff
125
vtkm/cont/testing/UnitTestArrayHandleCounting.cxx
Normal file
125
vtkm/cont/testing/UnitTestArrayHandleCounting.cxx
Normal file
@ -0,0 +1,125 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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.
|
||||
//============================================================================
|
||||
|
||||
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
|
||||
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace {
|
||||
|
||||
const vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
//increments by two instead of one wrapper
|
||||
template<typename T>
|
||||
struct CountByTwo
|
||||
{
|
||||
CountByTwo(): Value() {}
|
||||
explicit CountByTwo(T t): Value(t) {}
|
||||
|
||||
bool operator==(const T& other) const
|
||||
{ return Value == other; }
|
||||
|
||||
bool operator==(const CountByTwo<T>& other) const
|
||||
{ return Value == other.Value; }
|
||||
|
||||
CountByTwo<T> operator+(vtkm::Id count) const
|
||||
{ return CountByTwo<T>(Value+(count*2)); }
|
||||
|
||||
CountByTwo<T>& operator++()
|
||||
{ ++Value; ++Value; return *this; }
|
||||
|
||||
friend std::ostream& operator<< (std::ostream& os, const CountByTwo<T>& obj)
|
||||
{ os << obj.Value; return os; }
|
||||
T Value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template< typename ValueType>
|
||||
struct TemplatedTests
|
||||
{
|
||||
typedef vtkm::cont::ArrayHandleCounting<ValueType> ArrayHandleType;
|
||||
|
||||
typedef vtkm::cont::ArrayHandle<ValueType,
|
||||
typename vtkm::cont::internal::ArrayHandleCountingTraits<ValueType>::Tag>
|
||||
ArrayHandleType2;
|
||||
|
||||
typedef typename ArrayHandleType::PortalConstControl PortalType;
|
||||
|
||||
void operator()( const ValueType startingValue )
|
||||
{
|
||||
ArrayHandleType arrayConst(startingValue, ARRAY_SIZE);
|
||||
|
||||
ArrayHandleType arrayMake = vtkm::cont::make_ArrayHandleCounting(startingValue,ARRAY_SIZE);
|
||||
|
||||
ArrayHandleType2 arrayHandle =
|
||||
ArrayHandleType2(PortalType(startingValue, ARRAY_SIZE));
|
||||
|
||||
VTKM_TEST_ASSERT(arrayConst.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Counting array using constructor has wrong size.");
|
||||
|
||||
VTKM_TEST_ASSERT(arrayMake.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Counting array using make has wrong size.");
|
||||
|
||||
VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Counting array using raw array handle + tag has wrong size.");
|
||||
|
||||
ValueType properValue = startingValue;
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
VTKM_TEST_ASSERT(arrayConst.GetPortalConstControl().Get(index) == properValue,
|
||||
"Counting array using constructor has unexpected value.");
|
||||
VTKM_TEST_ASSERT(arrayMake.GetPortalConstControl().Get(index) == properValue,
|
||||
"Counting array using make has unexpected value.");
|
||||
|
||||
VTKM_TEST_ASSERT(arrayHandle.GetPortalConstControl().Get(index) == properValue,
|
||||
"Counting array using raw array handle + tag has unexpected value.");
|
||||
++properValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TestFunctor
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(const T t)
|
||||
{
|
||||
TemplatedTests<T> tests;
|
||||
tests(t);
|
||||
}
|
||||
};
|
||||
|
||||
void TestArrayHandleCounting()
|
||||
{
|
||||
TestFunctor()(vtkm::Id(0));
|
||||
TestFunctor()(vtkm::Scalar(0));
|
||||
TestFunctor()( CountByTwo<vtkm::Id>(12) );
|
||||
TestFunctor()( CountByTwo<vtkm::Scalar>(1.2f) );
|
||||
}
|
||||
|
||||
|
||||
} // annonymous namespace
|
||||
|
||||
int UnitTestArrayHandleCounting(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestArrayHandleCounting);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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.
|
||||
//============================================================================
|
||||
|
||||
// This tests a previous problem where code templated on the device adapter and
|
||||
// used one of the device adapter algorithms (for example, the dispatcher) had
|
||||
// to be declared after any device adapter it was ever used with.
|
||||
|
||||
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
|
||||
// Important for this test!
|
||||
//This file must be included after ArrayHandle.h
|
||||
#include <vtkm/cont/DeviceAdapterSerial.h>
|
||||
|
||||
namespace {
|
||||
|
||||
struct ExampleWorklet
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T vtkmNotUsed(v)) const { }
|
||||
};
|
||||
|
||||
void CheckPostDefinedDeviceAdapter()
|
||||
{
|
||||
// Nothing to really check. If this compiles, then the test is probably
|
||||
// successful.
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> test;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestDeviceAdapterAlgorithmDependency(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(CheckPostDefinedDeviceAdapter);
|
||||
}
|
106
vtkm/cont/testing/UnitTestDeviceAdapterAlgorithmGeneral.cxx
Normal file
106
vtkm/cont/testing/UnitTestDeviceAdapterAlgorithmGeneral.cxx
Normal file
@ -0,0 +1,106 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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.
|
||||
//============================================================================
|
||||
|
||||
// This test makes sure that the algorithms specified in
|
||||
// DeviceAdapterAlgorithmGeneral.h are working correctly. It does this by
|
||||
// creating a test device adapter that uses the serial device adapter for the
|
||||
// base schedule/scan/sort algorithms and using the general algorithms for
|
||||
// everything else. Because this test is based of the serial device adapter,
|
||||
// make sure that UnitTestDeviceAdapterSerial is working before trying to debug
|
||||
// this one.
|
||||
|
||||
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterSerial.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
|
||||
|
||||
#include <vtkm/cont/testing/TestingDeviceAdapter.h>
|
||||
|
||||
VTKM_CREATE_DEVICE_ADAPTER(TestAlgorithmGeneral);
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
|
||||
template<>
|
||||
struct DeviceAdapterAlgorithm<
|
||||
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral> :
|
||||
vtkm::cont::internal::DeviceAdapterAlgorithmGeneral<
|
||||
DeviceAdapterAlgorithm<
|
||||
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>,
|
||||
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
|
||||
{
|
||||
private:
|
||||
typedef vtkm::cont::DeviceAdapterAlgorithm<
|
||||
vtkm::cont::DeviceAdapterTagSerial> Algorithm;
|
||||
|
||||
typedef vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral
|
||||
DeviceAdapterTagTestAlgorithmGeneral;
|
||||
|
||||
public:
|
||||
|
||||
template<class Functor>
|
||||
VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
vtkm::Id numInstances)
|
||||
{
|
||||
Algorithm::Schedule(functor, numInstances);
|
||||
}
|
||||
|
||||
template<class Functor>
|
||||
VTKM_CONT_EXPORT static void Schedule(Functor functor,
|
||||
vtkm::Id3 rangeMax)
|
||||
{
|
||||
Algorithm::Schedule(functor, rangeMax);
|
||||
}
|
||||
|
||||
VTKM_CONT_EXPORT static void Synchronize()
|
||||
{
|
||||
Algorithm::Synchronize();
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename T, class ArrayContainerControlTag>
|
||||
class ArrayManagerExecution
|
||||
<T,
|
||||
ArrayContainerControlTag,
|
||||
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
|
||||
: public vtkm::cont::internal::ArrayManagerExecution
|
||||
<T, ArrayContainerControlTag, vtkm::cont::DeviceAdapterTagSerial>
|
||||
{
|
||||
public:
|
||||
typedef vtkm::cont::internal::ArrayManagerExecution
|
||||
<T, ArrayContainerControlTag, vtkm::cont::DeviceAdapterTagSerial>
|
||||
Superclass;
|
||||
typedef typename Superclass::ValueType ValueType;
|
||||
typedef typename Superclass::PortalType PortalType;
|
||||
typedef typename Superclass::PortalConstType PortalConstType;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::testing
|
||||
|
||||
int UnitTestDeviceAdapterAlgorithmGeneral(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::TestingDeviceAdapter
|
||||
<vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>::Run();
|
||||
}
|
31
vtkm/cont/testing/UnitTestDeviceAdapterSerial.cxx
Normal file
31
vtkm/cont/testing/UnitTestDeviceAdapterSerial.cxx
Normal file
@ -0,0 +1,31 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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.
|
||||
//============================================================================
|
||||
|
||||
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterSerial.h>
|
||||
|
||||
#include <vtkm/cont/testing/TestingDeviceAdapter.h>
|
||||
|
||||
int UnitTestDeviceAdapterSerial(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::TestingDeviceAdapter
|
||||
<vtkm::cont::DeviceAdapterTagSerial>::Run();
|
||||
}
|
94
vtkm/exec/internal/ErrorMessageBuffer.h
Normal file
94
vtkm/exec/internal/ErrorMessageBuffer.h
Normal file
@ -0,0 +1,94 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_exec_internal_ErrorMessageBuffer_h
|
||||
#define vtkm_exec_internal_ErrorMessageBuffer_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace internal {
|
||||
|
||||
/// Used to hold an error in the execution environment until the parallel
|
||||
/// execution can complete. This is to be used in conjunction with a
|
||||
/// DeviceAdapter's Schedule function to implement errors in execution
|
||||
/// environments that cannot throw errors. This string should be global to all
|
||||
/// threads. If the first entry in the string is '\0' (the C string
|
||||
/// terminator), then we consider it as no error. Otherwise, the array contains
|
||||
/// the string describing the error.
|
||||
///
|
||||
/// Before scheduling worklets, the global array should be cleared to have no
|
||||
/// error. This can only be reliably done by the device adapter.
|
||||
///
|
||||
class ErrorMessageBuffer
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT_EXPORT ErrorMessageBuffer()
|
||||
: MessageBuffer(), MessageBufferSize(0) { }
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
ErrorMessageBuffer(char *messageBuffer, vtkm::Id bufferSize)
|
||||
: MessageBuffer(messageBuffer), MessageBufferSize(bufferSize) { }
|
||||
|
||||
VTKM_EXEC_EXPORT void RaiseError(const char *message) const
|
||||
{
|
||||
// Only raise the error if one has not been raised yet. This check is not
|
||||
// guaranteed to work across threads. However, chances are that if two or
|
||||
// more threads simultaneously pass this test, they will be writing the
|
||||
// same error, which is fine. Even in the much less likely case that two
|
||||
// threads simultaneously write different error messages, the worst case is
|
||||
// that you get a mangled message. That's not good (and it's what we are
|
||||
// trying to avoid), but it's not critical.
|
||||
if (this->IsErrorRaised()) { return; }
|
||||
|
||||
// Safely copy message into array.
|
||||
for (vtkm::Id index = 0; index < this->MessageBufferSize; index++)
|
||||
{
|
||||
this->MessageBuffer[index] = message[index];
|
||||
if (message[index] == '\0') { break; }
|
||||
}
|
||||
|
||||
// Make sure message is null terminated.
|
||||
this->MessageBuffer[this->MessageBufferSize-1] = '\0';
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT bool IsErrorRaised() const
|
||||
{
|
||||
if (this->MessageBufferSize > 0)
|
||||
{
|
||||
return (this->MessageBuffer[0] != '\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no buffer set, then always report an error.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
char *MessageBuffer;
|
||||
vtkm::Id MessageBufferSize;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::exec::internal
|
||||
|
||||
#endif // vtkm_exec_internal_ErrorMessageBuffer_h
|
64
vtkm/exec/internal/WorkletBase.h
Normal file
64
vtkm/exec/internal/WorkletBase.h
Normal file
@ -0,0 +1,64 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_exec_WorkletBase_h
|
||||
#define vtkm_exec_WorkletBase_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace internal {
|
||||
|
||||
/// Base class for all worklet classes. Worklet classes are subclasses and a
|
||||
/// operator() const is added to implement an algorithm in Dax. Different
|
||||
/// worklets have different calling semantics.
|
||||
///
|
||||
class WorkletBase
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT_EXPORT WorkletBase() { }
|
||||
|
||||
VTKM_EXEC_EXPORT void RaiseError(const char *message) const
|
||||
{
|
||||
this->ErrorMessage.RaiseError(message);
|
||||
}
|
||||
|
||||
/// Set the error message buffer so that running algorithms can report
|
||||
/// errors. This is supposed to be set by the dispatcher. This method may be
|
||||
/// replaced as the execution semantics change.
|
||||
///
|
||||
VTKM_CONT_EXPORT void SetErrorMessageBuffer(
|
||||
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
|
||||
{
|
||||
this->ErrorMessage = buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::exec::internal
|
||||
|
||||
#endif //vtkm_exec_WorkletBase_h
|
@ -29,6 +29,7 @@ set(unit_tests
|
||||
UnitTestTesting.cxx
|
||||
UnitTestTypes.cxx
|
||||
UnitTestTypeTraits.cxx
|
||||
UnitTestVectorTraits.cxx
|
||||
)
|
||||
|
||||
VTKM_unit_tests(SOURCES ${unit_tests})
|
||||
|
63
vtkm/testing/UnitTestVectorTraits.cxx
Normal file
63
vtkm/testing/UnitTestVectorTraits.cxx
Normal file
@ -0,0 +1,63 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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.
|
||||
//============================================================================
|
||||
#include <vtkm/testing/VectorTraitsTests.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
namespace {
|
||||
|
||||
static const vtkm::Id MAX_VECTOR_SIZE = 5;
|
||||
static const vtkm::Id VectorInit[MAX_VECTOR_SIZE] = { 42, 54, 67, 12, 78 };
|
||||
|
||||
struct TestVectorTypeFunctor
|
||||
{
|
||||
template <typename T> void operator()(const T&) const {
|
||||
typedef vtkm::VectorTraits<T> Traits;
|
||||
VTKM_TEST_ASSERT(Traits::NUM_COMPONENTS <= MAX_VECTOR_SIZE,
|
||||
"Need to update test for larger vectors.");
|
||||
T vector;
|
||||
for (int index = 0; index < Traits::NUM_COMPONENTS; index++)
|
||||
{
|
||||
Traits::SetComponent(vector, index, VectorInit[index]);
|
||||
}
|
||||
vtkm::testing::TestVectorType(vector);
|
||||
}
|
||||
};
|
||||
|
||||
void TestVectorTraits()
|
||||
{
|
||||
TestVectorTypeFunctor test;
|
||||
vtkm::testing::Testing::TryAllTypes(test);
|
||||
std::cout << "vtkm::Tuple<vtkm::Scalar, 5>" << std::endl;
|
||||
test(vtkm::Tuple<vtkm::Scalar,5>());
|
||||
|
||||
vtkm::testing::TestVectorComponentsTag<vtkm::Id3>();
|
||||
vtkm::testing::TestVectorComponentsTag<vtkm::Vector3>();
|
||||
vtkm::testing::TestVectorComponentsTag<vtkm::Vector4>();
|
||||
vtkm::testing::TestScalarComponentsTag<vtkm::Id>();
|
||||
vtkm::testing::TestScalarComponentsTag<vtkm::Scalar>();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestVectorTraits(int, char *[])
|
||||
{
|
||||
return vtkm::testing::Testing::Run(TestVectorTraits);
|
||||
}
|
157
vtkm/testing/VectorTraitsTests.h
Normal file
157
vtkm/testing/VectorTraitsTests.h
Normal file
@ -0,0 +1,157 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
// Copyright 2014. 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 vtkm_testing_VectorTraitsTest_h
|
||||
#define vtkm_testing_VectorTraitsTest_h
|
||||
|
||||
#include <vtkm/VectorTraits.h>
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
namespace vtkm {
|
||||
namespace testing {
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline void CompareDimensionalityTags(vtkm::TypeTraitsScalarTag,
|
||||
vtkm::VectorTraitsTagSingleComponent)
|
||||
{
|
||||
// If we are here, everything is fine.
|
||||
}
|
||||
inline void CompareDimensionalityTags(vtkm::TypeTraitsVectorTag,
|
||||
vtkm::VectorTraitsTagMultipleComponents)
|
||||
{
|
||||
// If we are here, everything is fine.
|
||||
}
|
||||
|
||||
/// Compares some manual arithmetic through type traits to arithmetic with
|
||||
/// the Tuple class.
|
||||
template <class T>
|
||||
static void TestVectorTypeImpl(
|
||||
const typename boost::remove_const<T>::type &vector)
|
||||
{
|
||||
typedef typename vtkm::VectorTraits<T> Traits;
|
||||
typedef typename Traits::ComponentType ComponentType;
|
||||
static const int NUM_COMPONENTS = Traits::NUM_COMPONENTS;
|
||||
typedef typename boost::remove_const<T>::type NonConstT;
|
||||
|
||||
{
|
||||
NonConstT result;
|
||||
const ComponentType multiplier = 4;
|
||||
for (int i = 0; i < NUM_COMPONENTS; i++)
|
||||
{
|
||||
Traits::SetComponent(result, i, multiplier*Traits::GetComponent(vector, i));
|
||||
}
|
||||
VTKM_TEST_ASSERT(test_equal(Traits::ToTuple(result),
|
||||
multiplier*Traits::ToTuple(vector)),
|
||||
"Got bad result for scalar multiple");
|
||||
}
|
||||
|
||||
{
|
||||
NonConstT result;
|
||||
const ComponentType multiplier = 7;
|
||||
for (int i = 0; i < NUM_COMPONENTS; i++)
|
||||
{
|
||||
Traits::GetComponent(result, i)
|
||||
= multiplier * Traits::GetComponent(vector, i);
|
||||
}
|
||||
VTKM_TEST_ASSERT(test_equal(Traits::ToTuple(result),
|
||||
multiplier*Traits::ToTuple(vector)),
|
||||
"Got bad result for scalar multiple");
|
||||
}
|
||||
|
||||
{
|
||||
ComponentType result = 0;
|
||||
for (int i = 0; i < NUM_COMPONENTS; i++)
|
||||
{
|
||||
ComponentType component
|
||||
= Traits::GetComponent(vector, i);
|
||||
result += component * component;
|
||||
}
|
||||
VTKM_TEST_ASSERT(
|
||||
test_equal(result,
|
||||
vtkm::dot(Traits::ToTuple(vector), Traits::ToTuple(vector))),
|
||||
"Got bad result for dot product");
|
||||
}
|
||||
|
||||
// This will fail to compile if the tags are wrong.
|
||||
detail::CompareDimensionalityTags(
|
||||
typename vtkm::TypeTraits<T>::DimensionalityTag(),
|
||||
typename vtkm::VectorTraits<T>::HasMultipleComponents());
|
||||
}
|
||||
|
||||
inline void CheckVectorComponentsTag(vtkm::VectorTraitsTagMultipleComponents)
|
||||
{
|
||||
// If we are running here, everything is fine.
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Checks to make sure that the HasMultipleComponents tag is actually for
|
||||
/// multiple components. Should only be called for vector classes that actually
|
||||
/// have multiple components.
|
||||
///
|
||||
template<class T>
|
||||
inline void TestVectorComponentsTag()
|
||||
{
|
||||
// This will fail to compile if the tag is wrong
|
||||
// (i.e. not vtkm::VectorTraitsTagMultipleComponents)
|
||||
detail::CheckVectorComponentsTag(
|
||||
typename vtkm::VectorTraits<T>::HasMultipleComponents());
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline void CheckScalarComponentsTag(vtkm::VectorTraitsTagSingleComponent)
|
||||
{
|
||||
// If we are running here, everything is fine.
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Compares some manual arithmetic through type traits to arithmetic with
|
||||
/// the Tuple class.
|
||||
template <class T>
|
||||
static void TestVectorType(const T &vector)
|
||||
{
|
||||
detail::TestVectorTypeImpl<T>(vector);
|
||||
detail::TestVectorTypeImpl<const T>(vector);
|
||||
}
|
||||
|
||||
/// Checks to make sure that the HasMultipleComponents tag is actually for a
|
||||
/// single component. Should only be called for "vector" classes that actually
|
||||
/// have only a single component (that is, are really scalars).
|
||||
///
|
||||
template<class T>
|
||||
inline void TestScalarComponentsTag()
|
||||
{
|
||||
// This will fail to compile if the tag is wrong
|
||||
// (i.e. not vtkm::VectorTraitsTagSingleComponent)
|
||||
detail::CheckScalarComponentsTag(
|
||||
typename vtkm::VectorTraits<T>::HasMultipleComponents());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::testing
|
||||
|
||||
#endif //vtkm_testing_VectorTraitsTest_h
|
Loading…
Reference in New Issue
Block a user