diff --git a/CMake/VTKmCheckPyexpander.cmake b/CMake/VTKmCheckPyexpander.cmake index 062739c4b..048b11fa0 100644 --- a/CMake/VTKmCheckPyexpander.cmake +++ b/CMake/VTKmCheckPyexpander.cmake @@ -54,20 +54,16 @@ if(${pyexpander_result}) return() endif() -file(WRITE ${GENERATED_FILE} "${pyexpander_output}") +file(WRITE ${GENERATED_FILE}.save "${pyexpander_output}") execute_process( - COMMAND ${CMAKE_COMMAND} -E compare_files ${SOURCE_FILE} ${GENERATED_FILE} + COMMAND ${CMAKE_COMMAND} -E compare_files ${SOURCE_FILE} ${GENERATED_FILE}.save RESULT_VARIABLE diff_result ) if(${diff_result}) # If diff returned non-zero, it failed and the two files are different. get_filename_component(filename ${SOURCE_FILE} NAME) - # Move the generated file so that the build does not confuse it with the - # files in the source directory. - file(REMOVE ${GENERATED_FILE}.save) - file(RENAME ${GENERATED_FILE} ${GENERATED_FILE}.save) message(SEND_ERROR "The source file ${filename} does not match the generated file. If you have modified this file directly, then you have messed up. Modify the ${filename}.in file instead and then copy the pyexpander result to ${filename}. If you modified ${filename}.in, then you might just need to copy the pyresult back to the source directory. If you have not modifed either, then you have likely checked out an inappropriate change. Check the git logs to see what changes were made. If the changes have resulted from modifying ${filename}.in, then you can finish by moving ${GENERATED_FILE}.save over ${SOURCE_FILE}") @@ -75,7 +71,7 @@ else() # Now that we have done the comparison, remove the generated file so there is # no confusion between the generated files and the source files checked into # the repository. - file(REMOVE ${GENERATED_FILE}) + file(REMOVE ${GENERATED_FILE}.save) # Pyexpander successfully checked, so touch a file to tell make when the # check was last successfully performed. execute_process( diff --git a/vtkm/CMakeLists.txt b/vtkm/CMakeLists.txt index 46a555923..79f8e1a91 100644 --- a/vtkm/CMakeLists.txt +++ b/vtkm/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories(${Boost_INCLUDE_DIRS}) set(headers Extent.h ListTag.h + Pair.h TypeListTag.h Types.h TypeTraits.h @@ -40,3 +41,7 @@ add_subdirectory(internal) #add the control and exec folders add_subdirectory(cont) add_subdirectory(exec) + +#----------------------------------------------------------------------------- +#add the worklet folder +add_subdirectory(worklet) diff --git a/vtkm/ListTag.h b/vtkm/ListTag.h index e2dc19530..76912442d 100644 --- a/vtkm/ListTag.h +++ b/vtkm/ListTag.h @@ -24,8 +24,32 @@ #include +#include +#include + namespace vtkm { +namespace internal { + +template +struct ListTagCheck +{ + static const bool Valid = + boost::is_base_of::value; +}; + +} // namespace internal + +/// Checks that the argument is a proper list tag. This is a handy concept +/// check for functions and classes to make sure that a template argument is +/// actually a device adapter tag. (You can get weird errors elsewhere in the +/// code when a mistake is made.) +/// +#define VTKM_IS_LIST_TAG(tag) \ + BOOST_STATIC_ASSERT_MSG( \ + ::vtkm::internal::ListTagCheck::Valid, \ + "Provided type is not a valid VTK-m list tag.") + namespace detail { template @@ -35,14 +59,14 @@ struct ListJoin { }; /// A special tag for an empty list. /// -struct ListTagEmpty { +struct ListTagEmpty : detail::ListRoot { typedef detail::ListBase List; }; /// A tag that is a construction of two other tags joined together. This struct /// can be subclassed and still behave like a list tag. template -struct ListTagJoin { +struct ListTagJoin : detail::ListRoot { typedef detail::ListJoin List; }; @@ -81,6 +105,7 @@ template VTKM_CONT_EXPORT void ListForEach(Functor &f, ListTag) { + VTKM_IS_LIST_TAG(ListTag); detail::ListForEachImpl(f, typename ListTag::List()); } @@ -91,9 +116,33 @@ template VTKM_CONT_EXPORT void ListForEach(const Functor &f, ListTag) { + VTKM_IS_LIST_TAG(ListTag); detail::ListForEachImpl(f, typename ListTag::List()); } +/// Checks to see if the given \c Type is in the list pointed to by \c ListTag. +/// There is a static boolean named \c value that is set to true if the type is +/// contained in the list and false otherwise. +/// +template +struct ListContains +{ + VTKM_IS_LIST_TAG(ListTag); + static const bool value = + detail::ListContainsImpl::value; +}; + +namespace detail { + +template +struct ListContainsImpl, Type> +{ + static const bool value = (vtkm::ListContains::value || + vtkm::ListContains::value); +}; + +} // namespace detail + } // namespace vtkm #endif //vtk_m_ListTag_h diff --git a/vtkm/Pair.h b/vtkm/Pair.h new file mode 100644 index 000000000..efa3e84a6 --- /dev/null +++ b/vtkm/Pair.h @@ -0,0 +1,143 @@ +//============================================================================ +// 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 vtk_m_Pair_h +#define vtk_m_Pair_h + +#include +#include + +#include + +namespace vtkm { + +/// A \c vtkm::Pair is essentially the same as an STL pair object except that +/// the methods (constructors and operators) are defined to work in both the +/// control and execution environments (whereas std::pair is likely to work +/// only in the control environment). +/// +template +struct Pair +{ + /// The type of the first object. + /// + typedef T1 FirstType; + + /// The type of the second object. + /// + typedef T2 SecondType; + + /// The same as FirstType, but follows the naming convention of std::pair. + /// + typedef FirstType first_type; + + /// The same as SecondType, but follows the naming convention of std::pair. + /// + typedef SecondType second_type; + + /// The pair's first object. Note that this field breaks VTK-m's naming + /// conventions to make vtkm::Pair more compatible with std::pair. + /// + FirstType first; + + /// The pair's second object. Note that this field breaks VTK-m's naming + /// conventions to make vtkm::Pair more compatible with std::pair. + /// + SecondType second; + + VTKM_EXEC_CONT_EXPORT + Pair() : first(), second() { } + + VTKM_EXEC_CONT_EXPORT + Pair(const FirstType &firstSrc, const SecondType &secondSrc) + : first(firstSrc), second(secondSrc) { } + + template + VTKM_EXEC_CONT_EXPORT + Pair(const vtkm::Pair &src) + : first(src.first), second(src.second) { } + + template + VTKM_EXEC_CONT_EXPORT + Pair(const std::pair &src) + : first(src.first), second(src.second) { } + + VTKM_EXEC_CONT_EXPORT + vtkm::Pair & + operator=(const vtkm::Pair &src) { + this->first = src.first; + this->second = src.second; + return *this; + } + + VTKM_EXEC_CONT_EXPORT + bool operator==(const vtkm::Pair &other) const { + return ((this->first == other.first) && (this->second == other.second)); + } + + VTKM_EXEC_CONT_EXPORT + bool operator!=(const vtkm::Pair &other) const { + return !(*this == other); + } + + /// Tests ordering on the first object, and then on the second object if the + /// first are equal. + /// + VTKM_EXEC_CONT_EXPORT + bool operator<(const vtkm::Pair &other) const { + return ((this->first < other.first) + || (!(other.first < this->first) && (this->second < other.second))); + } + + /// Tests ordering on the first object, and then on the second object if the + /// first are equal. + /// + VTKM_EXEC_CONT_EXPORT + bool operator>(const vtkm::Pair &other) const { + return (other < *this); + } + + /// Tests ordering on the first object, and then on the second object if the + /// first are equal. + /// + VTKM_EXEC_CONT_EXPORT + bool operator<=(const vtkm::Pair &other) const { + return !(other < *this); + } + + /// Tests ordering on the first object, and then on the second object if the + /// first are equal. + /// + VTKM_EXEC_CONT_EXPORT + bool operator>=(const vtkm::Pair &other) const { + return !(*this < other); + } +}; + +template +VTKM_EXEC_CONT_EXPORT +vtkm::Pair make_Pair(const T1 &firstSrc, const T2 &secondSrc) +{ + return vtkm::Pair(firstSrc, secondSrc); +} + +} // namespace vtkm + +#endif //vtk_m_Pair_h diff --git a/vtkm/TypeListTag.h b/vtkm/TypeListTag.h index 689eadb66..2d7d4e2c0 100644 --- a/vtkm/TypeListTag.h +++ b/vtkm/TypeListTag.h @@ -180,6 +180,16 @@ struct TypeListTagCommon vtkm::Vec > { }; +// Special implementation of ListContains for TypeListTagAll to always be +// true. Although TypeListTagAll is necessarily finite, the point is to +// be all inclusive. Besides, this should speed up the compilation when +// checking a list that should contain everything. +template +struct ListContains +{ + static const bool value = true; +}; + } // namespace vtkm #endif //vtk_m_TypeListTag_h diff --git a/vtkm/cont/ArrayHandle.h b/vtkm/cont/ArrayHandle.h index 45f312a1a..16a5c3270 100644 --- a/vtkm/cont/ArrayHandle.h +++ b/vtkm/cont/ArrayHandle.h @@ -43,6 +43,14 @@ namespace cont { namespace internal { +/// \brief Base class of all ArrayHandle classes. +/// +/// This is an empty class that is used to check if something is an \c +/// ArrayHandle class (or at least something that behaves exactly like one). +/// The \c ArrayHandle template class inherits from this. +/// +class ArrayHandleBase { }; + /// Checks to see if the given type and storage can form a valid array handle /// (some storage objects cannot support all types). This check is compatable /// with the Boost meta-template programming library (MPL). It contains a @@ -59,6 +67,29 @@ struct IsValidArrayHandle { >::type type; }; +/// Checks to see if the given object is an array handle. This check is +/// compatiable with the Boost meta-template programming library (MPL). It +/// contains a typedef named type that is eitehr boost::mpl::true_ or +/// boost::mpl::false_. Both of these have a typedef named value with the +/// respective boolean value. +/// +/// Unlike \c IsValidArrayHandle, if an \c ArrayHandle is used with this +/// class, then it must be created by the compiler and therefore must already +/// be valid. Where \c IsValidArrayHandle is used when you know something is +/// an \c ArrayHandle but you are not sure if the \c StorageTag is valid, this +/// class is used to ensure that a given type is an \c ArrayHandle. It is +/// used internally in the VTKM_IS_ARRAY_HANDLE macro. +/// +template +struct ArrayHandleCheck +{ + typedef typename boost::is_base_of< + ::vtkm::cont::internal::ArrayHandleBase, T>::type type; +}; + +#define VTKM_IS_ARRAY_HANDLE(type) \ + BOOST_MPL_ASSERT(( ::vtkm::cont::internal::ArrayHandleCheck )) + } // namespace internal /// \brief Manages an array-worth of data. @@ -85,7 +116,7 @@ struct IsValidArrayHandle { template< typename T, typename StorageTag_ = VTKM_DEFAULT_STORAGE_TAG> -class ArrayHandle +class ArrayHandle : public internal::ArrayHandleBase { private: typedef vtkm::cont::internal::Storage StorageType; diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index 9065068bf..f42de8ea5 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -35,6 +35,7 @@ set(headers Error.h ErrorControl.h ErrorControlAssert.h + ErrorControlBadType.h ErrorControlBadValue.h ErrorControlInternal.h ErrorControlOutOfMemory.h @@ -51,6 +52,7 @@ set(headers #----------------------------------------------------------------------------- add_subdirectory(internal) +add_subdirectory(arg) vtkm_declare_headers(${impl_headers} ${headers}) diff --git a/vtkm/cont/DynamicArrayHandle.h b/vtkm/cont/DynamicArrayHandle.h index fa9ea90b9..a44dc9f52 100644 --- a/vtkm/cont/DynamicArrayHandle.h +++ b/vtkm/cont/DynamicArrayHandle.h @@ -130,6 +130,7 @@ public: VTKM_CONT_EXPORT internal::DynamicArrayHandleCast ResetTypeList(NewTypeList = NewTypeList()) const { + VTKM_IS_LIST_TAG(NewTypeList); return internal::DynamicArrayHandleCast< NewTypeList,VTKM_DEFAULT_STORAGE_LIST_TAG>(*this); } @@ -145,6 +146,7 @@ public: VTKM_CONT_EXPORT internal::DynamicArrayHandleCast ResetStorageList(NewStorageList = NewStorageList()) const { + VTKM_IS_LIST_TAG(NewStorageList); return internal::DynamicArrayHandleCast< VTKM_DEFAULT_TYPE_LIST_TAG,NewStorageList>(*this); } @@ -258,6 +260,8 @@ void DynamicArrayHandle::CastAndCall(const Functor &f, TypeList, StorageList) const { + VTKM_IS_LIST_TAG(TypeList); + VTKM_IS_LIST_TAG(StorageList); typedef detail::DynamicArrayHandleTryType TryTypeType; TryTypeType tryType = TryTypeType(*this, f); vtkm::ListForEach(tryType, TypeList()); @@ -273,6 +277,9 @@ namespace internal { template class DynamicArrayHandleCast : public vtkm::cont::DynamicArrayHandle { + VTKM_IS_LIST_TAG(TypeList); + VTKM_IS_LIST_TAG(StorageList); + public: VTKM_CONT_EXPORT DynamicArrayHandleCast() : DynamicArrayHandle() { } @@ -291,6 +298,7 @@ public: VTKM_CONT_EXPORT DynamicArrayHandleCast ResetTypeList(NewTypeList = NewTypeList()) const { + VTKM_IS_LIST_TAG(NewTypeList); return DynamicArrayHandleCast(*this); } @@ -298,6 +306,7 @@ public: VTKM_CONT_EXPORT internal::DynamicArrayHandleCast ResetStorageList(NewStorageList = NewStorageList()) const { + VTKM_IS_LIST_TAG(NewStorageList); return internal::DynamicArrayHandleCast(*this); } diff --git a/vtkm/cont/DynamicPointCoordinates.h b/vtkm/cont/DynamicPointCoordinates.h index a1bf51085..a9b32365f 100644 --- a/vtkm/cont/DynamicPointCoordinates.h +++ b/vtkm/cont/DynamicPointCoordinates.h @@ -165,6 +165,7 @@ public: VTKM_DEFAULT_STORAGE_LIST_TAG> ResetPointCoordinatesList( NewPointCoordinatesList = NewPointCoordinatesList()) const { + VTKM_IS_LIST_TAG(NewPointCoordinatesList); return internal::DynamicPointCoordinatesCast< NewPointCoordinatesList, VTKM_DEFAULT_TYPE_LIST_TAG, @@ -185,6 +186,7 @@ public: NewTypeList, VTKM_DEFAULT_STORAGE_LIST_TAG> ResetTypeList(NewTypeList = NewTypeList()) const { + VTKM_IS_LIST_TAG(NewTypeList); return internal::DynamicPointCoordinatesCast< VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG, NewTypeList, @@ -205,6 +207,7 @@ public: VTKM_DEFAULT_TYPE_LIST_TAG, NewStorageList> ResetStorageList(NewStorageList = NewStorageList()) const { + VTKM_IS_LIST_TAG(NewStorageList); return internal::DynamicPointCoordinatesCast< VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG, VTKM_DEFAULT_TYPE_LIST_TAG, @@ -300,6 +303,9 @@ void DynamicPointCoordinates::CastAndCall(const Functor &f, TypeList, StorageList) const { + VTKM_IS_LIST_TAG(PointCoordinatesList); + VTKM_IS_LIST_TAG(TypeList); + VTKM_IS_LIST_TAG(StorageList); typedef detail::DynamicPointCoordinatesTryStorage< Functor, TypeList, StorageList> TryTypeType; TryTypeType tryType = TryTypeType(*this, f); @@ -318,6 +324,10 @@ template class DynamicPointCoordinatesCast : public vtkm::cont::DynamicPointCoordinates { + VTKM_IS_LIST_TAG(PointCoordinatesList); + VTKM_IS_LIST_TAG(TypeList); + VTKM_IS_LIST_TAG(StorageList); + public: VTKM_CONT_EXPORT DynamicPointCoordinatesCast() : DynamicPointCoordinates() { } @@ -340,6 +350,7 @@ public: DynamicPointCoordinatesCast ResetPointCoordinatesList( NewPointCoordinatesList = NewPointCoordinatesList()) const { + VTKM_IS_LIST_TAG(NewPointCoordinatesList); return DynamicPointCoordinatesCast< NewPointCoordinatesList,TypeList,StorageList>(*this); } @@ -348,6 +359,7 @@ public: VTKM_CONT_EXPORT DynamicPointCoordinatesCast ResetTypeList(NewTypeList = NewTypeList()) const { + VTKM_IS_LIST_TAG(NewTypeList); return DynamicPointCoordinatesCast< PointCoordinatesList,NewTypeList,StorageList>(*this); } @@ -356,6 +368,7 @@ public: VTKM_CONT_EXPORT DynamicPointCoordinatesCast ResetStorageList(NewStorageList = NewStorageList()) const { + VTKM_IS_LIST_TAG(NewStorageList); return DynamicPointCoordinatesCast< PointCoordinatesList,TypeList,NewStorageList>(*this); } diff --git a/vtkm/cont/ErrorControlBadType.h b/vtkm/cont/ErrorControlBadType.h new file mode 100644 index 000000000..bd4e6ca46 --- /dev/null +++ b/vtkm/cont/ErrorControlBadType.h @@ -0,0 +1,41 @@ +//============================================================================ +// 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 vtk_m_cont_ErrorControlBadType_h +#define vtk_m_cont_ErrorControlBadType_h + +#include + +namespace vtkm { +namespace cont { + +/// This class is thrown when VTK-m encounters data of a type that is +/// incompatible with the current operation. +/// +class ErrorControlBadType : public ErrorControl +{ +public: + ErrorControlBadType(const std::string &message) + : ErrorControl(message) { } +}; + +} +} // namespace vtkm::cont + +#endif //vtk_m_cont_ErrorControlBadType_h diff --git a/vtkm/cont/arg/CMakeLists.txt b/vtkm/cont/arg/CMakeLists.txt new file mode 100644 index 000000000..1030589e5 --- /dev/null +++ b/vtkm/cont/arg/CMakeLists.txt @@ -0,0 +1,38 @@ +##============================================================================ +## 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_directories(${Boost_INCLUDE_DIRS}) + +set(headers + ControlSignatureTagBase.h + Transport.h + TransportTagArrayIn.h + TransportTagArrayOut.h + TransportTagExecObject.h + TypeCheck.h + TypeCheckTagArray.h + TypeCheckTagExecObject.h + ) + +vtkm_declare_headers(${headers}) + + +#----------------------------------------------------------------------------- +add_subdirectory(testing) diff --git a/vtkm/cont/arg/ControlSignatureTagBase.h b/vtkm/cont/arg/ControlSignatureTagBase.h new file mode 100644 index 000000000..59a4bce91 --- /dev/null +++ b/vtkm/cont/arg/ControlSignatureTagBase.h @@ -0,0 +1,69 @@ +//============================================================================ +// 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 vtk_m_cont_arg_ControlSignatureTagBase_h +#define vtk_m_cont_arg_ControlSignatureTagBase_h + +#include +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief The base class for all tags used in a \c ControlSignature. +/// +/// If a new \c ControlSignature tag is created, it must be derived from this +/// class in some way. This helps identify \c ControlSignature tags in the \c +/// VTKM_IS_CONTROL_SIGNATURE_TAG macro and allows checking the validity of a +/// \c ControlSignature. +/// +/// In addition to inheriting from this base class, a \c ControlSignature tag +/// must define the following three typedefs: \c TypeCheckTag, \c TransportTag +/// and \c FetchTag. +/// +struct ControlSignatureTagBase { }; + +namespace internal { + +template +struct ControlSignatureTagCheck +{ + static const bool Valid = + boost::is_base_of< + vtkm::cont::arg::ControlSignatureTagBase, ControlSignatureTag>::value; +}; + +} // namespace internal + +/// Checks that the argument is a proper tag for an \c ControlSignature. This +/// is a handy concept check when modifying tags or dispatching to make sure +/// that a template argument is actually an \c ControlSignature tag. (You can +/// get weird errors elsewhere in the code when a mistake is made.) +/// +#define VTKM_IS_CONTROL_SIGNATURE_TAG(tag) \ + BOOST_STATIC_ASSERT_MSG( \ + ::vtkm::cont::arg::internal::ControlSignatureTagCheck::Valid, \ + "Provided a type that is not a valid ControlSignature tag.") + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_ControlSignatureTagBase_h diff --git a/vtkm/cont/arg/Transport.h b/vtkm/cont/arg/Transport.h new file mode 100644 index 000000000..f656deacb --- /dev/null +++ b/vtkm/cont/arg/Transport.h @@ -0,0 +1,79 @@ +//============================================================================ +// 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 vtk_m_cont_arg_Transport_h +#define vtk_m_cont_arg_Transport_h + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief Class for transporting from the control to the execution environment. +/// +/// The \c Transport class is used to transport data of a certain type from the +/// control environment to the execution environment. It is used internally in +/// VTK-m's dispatch mechanism. +/// +/// \c Transport is a templated class with three arguments. The first argument +/// is a tag declaring the mechanism of transport. The second argument is the +/// type of data to transport. The third argument is device adapter tag for +/// the device to move the data to. +/// +/// There is no generic implementation of \c Transport. There are partial +/// specializations of \c Transport for each mechanism supported. If you get a +/// compiler error about an incomplete type for \c Transport, it means you used +/// an invalid \c TransportTag or it is an invalid combination of data type or +/// device adapter. +/// +template +struct Transport +#ifdef VTKM_DOXYGEN_ONLY +{ + /// \brief The type used in the execution environment. + /// + /// All \c Transport specializations are expected to declare a type named \c + /// ExecObjectType that is the object type used in the execution environment. + /// For example, for an \c ArrayHandle, the \c ExecObjectType is the portal + /// used in the execution environment. + /// + typedef typename ContObjectType:: + template ExecutionTypes::PortalConst ExecObjectType; + + /// \brief Send data to the execution environment. + /// + /// All \c Transport specializations are expected to have a constant + /// parenthesis operator that takes the data in the control environment and + /// returns an object that is accessible in the execution environment. The + /// operator also has a second argument that is the size of the dispatch that + /// can be used, for example, to allocate data for an output array. + /// + VTKM_CONT_EXPORT + ExecObjectType operator()(const ContObjectType contData, vtkm::Id size) const; +}; +#else // VTKM_DOXYGEN_ONLY + ; +#endif // VTKM_DOXYGEN_ONLY + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_Transport_h diff --git a/vtkm/cont/arg/TransportTagArrayIn.h b/vtkm/cont/arg/TransportTagArrayIn.h new file mode 100644 index 000000000..763fffd68 --- /dev/null +++ b/vtkm/cont/arg/TransportTagArrayIn.h @@ -0,0 +1,61 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TransportTagArrayIn_h +#define vtk_m_cont_arg_TransportTagArrayIn_h + +#include + +#include + +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief \c Transport tag for input arrays. +/// +/// \c TransportTagArrayIn is a tag used with the \c Transport class to +/// transport \c ArrayHandle objects for input data. +/// +struct TransportTagArrayIn { }; + +template +struct Transport +{ + // If you get a compile error here, it means you tried to use an object that + // is not an array handle as an argument that is expected to be one. + VTKM_IS_ARRAY_HANDLE(ContObjectType); + + typedef typename ContObjectType::template ExecutionTypes::PortalConst + ExecObjectType; + + VTKM_CONT_EXPORT + ExecObjectType operator()(const ContObjectType &object, vtkm::Id) const + { + return object.PrepareForInput(Device()); + } +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TransportTagArrayIn_h diff --git a/vtkm/cont/arg/TransportTagArrayOut.h b/vtkm/cont/arg/TransportTagArrayOut.h new file mode 100644 index 000000000..94df18de9 --- /dev/null +++ b/vtkm/cont/arg/TransportTagArrayOut.h @@ -0,0 +1,61 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TransportTagArrayOut_h +#define vtk_m_cont_arg_TransportTagArrayOut_h + +#include + +#include + +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief \c Transport tag for output arrays. +/// +/// \c TransportTagArrayOut is a tag used with the \c Transport class to +/// transport \c ArrayHandle objects for output data. +/// +struct TransportTagArrayOut { }; + +template +struct Transport +{ + // If you get a compile error here, it means you tried to use an object that + // is not an array handle as an argument that is expected to be one. + VTKM_IS_ARRAY_HANDLE(ContObjectType); + + typedef typename ContObjectType::template ExecutionTypes::Portal + ExecObjectType; + + VTKM_CONT_EXPORT + ExecObjectType operator()(ContObjectType object, vtkm::Id size) const + { + return object.PrepareForOutput(size, Device()); + } +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TransportTagArrayOut_h diff --git a/vtkm/cont/arg/TransportTagExecObject.h b/vtkm/cont/arg/TransportTagExecObject.h new file mode 100644 index 000000000..0ace84fb0 --- /dev/null +++ b/vtkm/cont/arg/TransportTagExecObject.h @@ -0,0 +1,65 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TransportTagExecObject_h +#define vtk_m_cont_arg_TransportTagExecObject_h + +#include + +#include + +#include + +#include +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief \c Transport tag for execution objects. +/// +/// \c TransportTagExecObject is a tag used with the \c Transport class to +/// transport objects that work directly in the execution environment. +/// +struct TransportTagExecObject { }; + +template +struct Transport +{ + // If you get a compile error here, it means you tried to use an object that + // is not an execution object as an argument that is expected to be one. All + // execution objects are expected to inherit from + // vtkm::exec::ExecutionObjectBase. + BOOST_MPL_ASSERT(( boost::is_base_of )); + + typedef ContObjectType ExecObjectType; + + VTKM_CONT_EXPORT + ExecObjectType operator()(const ContObjectType &object, vtkm::Id) const + { + return object; + } +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TransportTagExecObject_h diff --git a/vtkm/cont/arg/TypeCheck.h b/vtkm/cont/arg/TypeCheck.h new file mode 100644 index 000000000..f72b1bcf9 --- /dev/null +++ b/vtkm/cont/arg/TypeCheck.h @@ -0,0 +1,53 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TypeCheck_h +#define vtk_m_cont_arg_TypeCheck_h + +namespace vtkm { +namespace cont { +namespace arg { + +/// \brief Class for checking that a type matches the semantics for an argument. +/// +/// The \c TypeCheck class is used in dispatchers to test whether an argument +/// passed to the \c Invoke command matches the corresponding argument in the +/// \c ControlSignature. +/// +/// This check happens after casting dynamic classes to static classes, so the +/// check need not worry about querying dynamic types. +/// +/// The generic implementation of \c TypeCheck always results in failure. When +/// a new type check tag is defined, along with it should be partial +/// specializations that find valid types. +/// +template +struct TypeCheck +{ + /// The static constant boolean \c value is set to \c true if the type is + /// valid for the given check tag and \c false otherwise. + /// + static const bool value = false; +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TypeCheck_h diff --git a/vtkm/cont/arg/TypeCheckTagArray.h b/vtkm/cont/arg/TypeCheckTagArray.h new file mode 100644 index 000000000..9ce2ff72a --- /dev/null +++ b/vtkm/cont/arg/TypeCheckTagArray.h @@ -0,0 +1,76 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TypeCheckTagArray_h +#define vtk_m_cont_arg_TypeCheckTagArray_h + +#include + +#include + +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// The Array type check passes for any object that behaves like an \c +/// ArrayHandle class and can be passed to the ArrayIn and ArrayOut transports. +/// +template +struct TypeCheckTagArray +{ + VTKM_IS_LIST_TAG(TypeList); +}; + +namespace detail { + +template +struct TypeCheckArrayValueType; + +template +struct TypeCheckArrayValueType +{ + static const bool value = + vtkm::ListContains::value; +}; + +template +struct TypeCheckArrayValueType +{ + static const bool value = false; +}; + +} // namespace detail + +template +struct TypeCheck, ArrayType> +{ + static const bool value = + detail::TypeCheckArrayValueType< + TypeList, + ArrayType, + vtkm::cont::internal::ArrayHandleCheck::type::value>::value; +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TypeCheckTagArray_h diff --git a/vtkm/cont/arg/TypeCheckTagExecObject.h b/vtkm/cont/arg/TypeCheckTagExecObject.h new file mode 100644 index 000000000..219958107 --- /dev/null +++ b/vtkm/cont/arg/TypeCheckTagExecObject.h @@ -0,0 +1,50 @@ +//============================================================================ +// 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 vtk_m_cont_arg_TypeCheckTagExecObject_h +#define vtk_m_cont_arg_TypeCheckTagExecObject_h + +#include + +#include + +#include + +namespace vtkm { +namespace cont { +namespace arg { + +/// The ExecObject type check passes for any object that inherits from \c +/// ExecutionObjectBase. This is supposed to signify that the object can be +/// used in the execution environment although there is no way to verify that. +/// +struct TypeCheckTagExecObject { }; + +template +struct TypeCheck +{ + static const bool value = + boost::is_base_of::value; +}; + +} +} +} // namespace vtkm::cont::arg + +#endif //vtk_m_cont_arg_TypeCheckTagExecObject_h diff --git a/vtkm/cont/arg/testing/CMakeLists.txt b/vtkm/cont/arg/testing/CMakeLists.txt new file mode 100644 index 000000000..9fbbd6314 --- /dev/null +++ b/vtkm/cont/arg/testing/CMakeLists.txt @@ -0,0 +1,30 @@ +##============================================================================ +## 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. +##============================================================================ + +set(unit_tests + UnitTestControlSignatureTag.cxx + UnitTestTransportArrayIn.cxx + UnitTestTransportArrayOut.cxx + UnitTestTransportExecObject.cxx + UnitTestTypeCheckArray.cxx + UnitTestTypeCheckExecObject.cxx + ) + +vtkm_unit_tests(SOURCES ${unit_tests}) diff --git a/vtkm/cont/arg/testing/UnitTestControlSignatureTag.cxx b/vtkm/cont/arg/testing/UnitTestControlSignatureTag.cxx new file mode 100644 index 000000000..1520020a6 --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestControlSignatureTag.cxx @@ -0,0 +1,58 @@ +//============================================================================ +// 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 + +#include + +namespace { + +void TestControlSignatures() +{ + VTKM_IS_CONTROL_SIGNATURE_TAG( + vtkm::worklet::WorkletMapField::FieldIn); + + VTKM_TEST_ASSERT( + vtkm::cont::arg::internal::ControlSignatureTagCheck< + vtkm::worklet::WorkletMapField::FieldIn >::Valid, + "Bad check for FieldIn"); + + VTKM_TEST_ASSERT( + vtkm::cont::arg::internal::ControlSignatureTagCheck< + vtkm::worklet::WorkletMapField::FieldOut >::Valid, + "Bad check for FieldOut"); + + VTKM_TEST_ASSERT( + !vtkm::cont::arg::internal::ControlSignatureTagCheck< + vtkm::exec::arg::WorkIndex >::Valid, + "Bad check for WorkIndex"); + + VTKM_TEST_ASSERT( + !vtkm::cont::arg::internal::ControlSignatureTagCheck::Valid, + "Bad check for vtkm::Id"); +} + +} // anonymous namespace + +int UnitTestControlSignatureTag(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestControlSignatures); +} + diff --git a/vtkm/cont/arg/testing/UnitTestTransportArrayIn.cxx b/vtkm/cont/arg/testing/UnitTestTransportArrayIn.cxx new file mode 100644 index 000000000..e1cdd612c --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestTransportArrayIn.cxx @@ -0,0 +1,96 @@ +//============================================================================ +// 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 + +#include + +#include +#include + +#include + +namespace { + +static const vtkm::Id ARRAY_SIZE = 10; + +template +struct TestKernel : public vtkm::exec::FunctorBase +{ + PortalType Portal; + + VTKM_EXEC_EXPORT + void operator()(vtkm::Id index) const + { + typedef typename PortalType::ValueType ValueType; + if (this->Portal.Get(index) != TestValue(index, ValueType())) + { + this->RaiseError("Got bad execution object."); + } + } +}; + +template +struct TryArrayInType +{ + template + void operator()(T) const + { + T array[ARRAY_SIZE]; + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + array[index] = TestValue(index, T()); + } + + typedef vtkm::cont::ArrayHandle ArrayHandleType; + ArrayHandleType handle = vtkm::cont::make_ArrayHandle(array, ARRAY_SIZE); + + typedef typename ArrayHandleType:: + template ExecutionTypes::PortalConst PortalType; + + vtkm::cont::arg::Transport< + vtkm::cont::arg::TransportTagArrayIn, ArrayHandleType, Device> + transport; + + TestKernel kernel; + kernel.Portal = transport(handle, ARRAY_SIZE); + + vtkm::cont::DeviceAdapterAlgorithm::Schedule(kernel, ARRAY_SIZE); + } +}; + +template +void TryArrayInTransport(Device) +{ + vtkm::testing::Testing::TryAllTypes(TryArrayInType()); +} + +void TestArrayInTransport() +{ + std::cout << "Trying ArrayIn transport with serial device." << std::endl; + TryArrayInTransport(vtkm::cont::DeviceAdapterTagSerial()); +} + +} // Anonymous namespace + +int UnitTestTransportArrayIn(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestArrayInTransport); +} diff --git a/vtkm/cont/arg/testing/UnitTestTransportArrayOut.cxx b/vtkm/cont/arg/testing/UnitTestTransportArrayOut.cxx new file mode 100644 index 000000000..4944569fb --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestTransportArrayOut.cxx @@ -0,0 +1,92 @@ +//============================================================================ +// 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 + +#include + +#include +#include + +#include + +namespace { + +static const vtkm::Id ARRAY_SIZE = 10; + +template +struct TestKernel : public vtkm::exec::FunctorBase +{ + PortalType Portal; + + VTKM_EXEC_EXPORT + void operator()(vtkm::Id index) const + { + typedef typename PortalType::ValueType ValueType; + this->Portal.Set(index, TestValue(index, ValueType())); + } +}; + +template +struct TryArrayOutType +{ + template + void operator()(T) const + { + typedef vtkm::cont::ArrayHandle ArrayHandleType; + ArrayHandleType handle; + + typedef typename ArrayHandleType:: + template ExecutionTypes::Portal PortalType; + + vtkm::cont::arg::Transport< + vtkm::cont::arg::TransportTagArrayOut, ArrayHandleType, Device> + transport; + + TestKernel kernel; + kernel.Portal = transport(handle, ARRAY_SIZE); + + VTKM_TEST_ASSERT(handle.GetNumberOfValues() == ARRAY_SIZE, + "ArrayOut transport did not allocate array correctly."); + + vtkm::cont::DeviceAdapterAlgorithm::Schedule(kernel, ARRAY_SIZE); + + CheckPortal(handle.GetPortalConstControl()); + } +}; + +template +void TryArrayOutTransport(Device) +{ + vtkm::testing::Testing::TryAllTypes(TryArrayOutType()); +} + +void TestArrayOutTransport() +{ + std::cout << "Trying ArrayOut transport with serial device." << std::endl; + TryArrayOutTransport(vtkm::cont::DeviceAdapterTagSerial()); +} + +} // Anonymous namespace + +int UnitTestTransportArrayOut(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestArrayOutTransport); +} diff --git a/vtkm/cont/arg/testing/UnitTestTransportExecObject.cxx b/vtkm/cont/arg/testing/UnitTestTransportExecObject.cxx new file mode 100644 index 000000000..cd8c83b21 --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestTransportExecObject.cxx @@ -0,0 +1,80 @@ +//============================================================================ +// 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 + +#include +#include + +#include + +#include + +#define EXPECTED_NUMBER 42 + +namespace { + +struct TestExecutionObject : public vtkm::exec::ExecutionObjectBase +{ + vtkm::Int32 Number; +}; + +struct TestKernel : public vtkm::exec::FunctorBase +{ + TestExecutionObject Object; + + VTKM_EXEC_EXPORT + void operator()(vtkm::Id) const + { + if (this->Object.Number != EXPECTED_NUMBER) + { + this->RaiseError("Got bad execution object."); + } + } +}; + +template +void TryExecObjectTransport(Device) +{ + TestExecutionObject contObject; + contObject.Number = EXPECTED_NUMBER; + + vtkm::cont::arg::Transport< + vtkm::cont::arg::TransportTagExecObject, TestExecutionObject, Device> + transport; + + TestKernel kernel; + kernel.Object = transport(contObject, 1); + + vtkm::cont::DeviceAdapterAlgorithm::Schedule(kernel, 1); +} + +void TestExecObjectTransport() +{ + std::cout << "Trying ExecObject transport with serial device." << std::endl; + TryExecObjectTransport(vtkm::cont::DeviceAdapterTagSerial()); +} + +} // Anonymous namespace + +int UnitTestTransportExecObject(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestExecObjectTransport); +} diff --git a/vtkm/cont/arg/testing/UnitTestTypeCheckArray.cxx b/vtkm/cont/arg/testing/UnitTestTypeCheckArray.cxx new file mode 100644 index 000000000..30fa45877 --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestTypeCheckArray.cxx @@ -0,0 +1,95 @@ +//============================================================================ +// 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 + +#include +#include +#include + +#include + +namespace { + +struct TryArraysOfType +{ + template + void operator()(T) const + { + using vtkm::cont::arg::TypeCheck; + typedef vtkm::cont::arg::TypeCheckTagArray + TypeCheckTagArray; + + typedef vtkm::cont::ArrayHandle StandardArray; + VTKM_TEST_ASSERT((TypeCheck::value), + "Standard array type check failed."); + + typedef vtkm::cont::ArrayHandleCounting CountingArray; + VTKM_TEST_ASSERT((TypeCheck::value), + "Counting array type check failed."); + + typedef typename vtkm::cont::ArrayHandleCompositeVectorType< + StandardArray,CountingArray>::type CompositeArray; + VTKM_TEST_ASSERT((TypeCheck::value), + "Composite array type check failed."); + + // Just some type that is not a valid array. + typedef typename StandardArray::PortalControl NotAnArray; + VTKM_TEST_ASSERT(!(TypeCheck::value), + "Not an array type check failed."); + + // Another type that is not a valid array. + VTKM_TEST_ASSERT(!(TypeCheck::value), + "Not an array type check failed."); + } +}; + +void TestCheckArray() +{ + vtkm::testing::Testing::TryAllTypes(TryArraysOfType()); + + std::cout << "Trying some arrays with types that do not match the list." + << std::endl; + using vtkm::cont::arg::TypeCheck; + using vtkm::cont::arg::TypeCheckTagArray; + + typedef vtkm::cont::ArrayHandle ScalarArray; + VTKM_TEST_ASSERT( + (TypeCheck,ScalarArray>::value), + "Scalar for scalar check failed."); + VTKM_TEST_ASSERT( + !(TypeCheck,ScalarArray>::value), + "Scalar for vector check failed."); + + typedef vtkm::cont::ArrayHandle > VecArray; + VTKM_TEST_ASSERT( + (TypeCheck,VecArray>::value), + "Vector for vector check failed."); + VTKM_TEST_ASSERT( + !(TypeCheck,VecArray>::value), + "Vector for scalar check failed."); +} + +} // anonymous namespace + +int UnitTestTypeCheckArray(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestCheckArray); +} diff --git a/vtkm/cont/arg/testing/UnitTestTypeCheckExecObject.cxx b/vtkm/cont/arg/testing/UnitTestTypeCheckExecObject.cxx new file mode 100644 index 000000000..f4e9f3a61 --- /dev/null +++ b/vtkm/cont/arg/testing/UnitTestTypeCheckExecObject.cxx @@ -0,0 +1,61 @@ +//============================================================================ +// 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 + +#include + +#include + +namespace { + +struct TestExecutionObject : vtkm::exec::ExecutionObjectBase { }; +struct TestNotExecutionObject { }; + +void TestCheckExecObject() +{ + std::cout << "Checking reporting of type checking exec object." << std::endl; + + using vtkm::cont::arg::TypeCheck; + using vtkm::cont::arg::TypeCheckTagExecObject; + + VTKM_TEST_ASSERT( + (TypeCheck::value), + "Type check failed."); + + VTKM_TEST_ASSERT( + !(TypeCheck::value), + "Type check failed."); + + VTKM_TEST_ASSERT( + !(TypeCheck::value), + "Type check failed."); + + VTKM_TEST_ASSERT( + !(TypeCheck >::value), + "Type check failed."); +} + +} // anonymous namespace + +int UnitTestTypeCheckExecObject(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestCheckExecObject); +} diff --git a/vtkm/cont/internal/DeviceAdapterTag.h b/vtkm/cont/internal/DeviceAdapterTag.h index d4766c75a..f96cb8423 100644 --- a/vtkm/cont/internal/DeviceAdapterTag.h +++ b/vtkm/cont/internal/DeviceAdapterTag.h @@ -80,10 +80,11 @@ struct DeviceAdapterTagCheck /// concept check for functions and classes to make sure that a template /// argument is actually a device adapter tag. (You can get weird errors /// elsewhere in the code when a mistake is made.) +/// #define VTKM_IS_DEVICE_ADAPTER_TAG(tag) \ BOOST_STATIC_ASSERT_MSG( \ ::vtkm::cont::internal::DeviceAdapterTagCheck::Valid, \ - "Provided type is not a valid VTKm device adapter tag.") + "Provided type is not a valid VTK-m device adapter tag.") //----------------------------------------------------------------------------- #if VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_SERIAL diff --git a/vtkm/cont/internal/DynamicTransform.h b/vtkm/cont/internal/DynamicTransform.h index 5fcd95e71..d2f695ab8 100644 --- a/vtkm/cont/internal/DynamicTransform.h +++ b/vtkm/cont/internal/DynamicTransform.h @@ -26,26 +26,6 @@ namespace vtkm { namespace cont { namespace internal { -namespace detail { - -template -struct DynamicArrayTransformCastAndCall -{ - const ContinueFunctor &Continue; - - VTKM_CONT_EXPORT - DynamicArrayTransformCastAndCall(const ContinueFunctor &continueFunc) - : Continue(continueFunc) { } - - template - VTKM_CONT_EXPORT - void operator()(const T &x) const { - this->Continue(x); - } -}; - -} // namespace detail - /// Tag used to identify an object that is a dynamic object that contains a /// CastAndCall method that iterates over all possible dynamic choices to run /// templated code. @@ -109,8 +89,7 @@ private: const ContinueFunctor &continueFunc, vtkm::cont::internal::DynamicTransformTagCastAndCall) const { - dynamicInput.CastAndCall( - detail::DynamicArrayTransformCastAndCall(continueFunc)); + dynamicInput.CastAndCall(continueFunc); } }; diff --git a/vtkm/exec/CMakeLists.txt b/vtkm/exec/CMakeLists.txt index 436ca3eb3..b0ad1586e 100644 --- a/vtkm/exec/CMakeLists.txt +++ b/vtkm/exec/CMakeLists.txt @@ -19,11 +19,13 @@ ##============================================================================ set(headers + ExecutionObjectBase.h FunctorBase.h ) #----------------------------------------------------------------------------- add_subdirectory(internal) +add_subdirectory(arg) vtkm_declare_headers(${impl_headers} ${headers}) diff --git a/vtkm/exec/internal/WorkletBase.h b/vtkm/exec/ExecutionObjectBase.h similarity index 67% rename from vtkm/exec/internal/WorkletBase.h rename to vtkm/exec/ExecutionObjectBase.h index 2b519dace..62f57d884 100644 --- a/vtkm/exec/internal/WorkletBase.h +++ b/vtkm/exec/ExecutionObjectBase.h @@ -17,25 +17,23 @@ // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ -#ifndef vtk_m_exec_internal_WorkletBase_h -#define vtk_m_exec_internal_WorkletBase_h - -#include +#ifndef vtk_m_exec_ExecutionObjectBase_h +#define vtk_m_exec_ExecutionObjectBase_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 VTK-m. Different -/// worklets have different calling semantics. +/// Base \c ExecutionObjectBase for execution objects to inherit from so that +/// you can use an arbitrary object as a parameter in an execution environment +/// function. Any method you want to use on the execution side must have the +/// VTKM_EXEC_EXPORT modifier. /// -class WorkletBase : public FunctorBase +class ExecutionObjectBase { + }; } -} -} // namespace vtkm::exec::internal +} // namespace vtkm::exec -#endif //vtk_m_exec_internal_WorkletBase_h +#endif //vtk_m_exec_ExecutionObjectBase_h diff --git a/vtkm/exec/arg/AspectTagDefault.h b/vtkm/exec/arg/AspectTagDefault.h new file mode 100644 index 000000000..dbc19ffc2 --- /dev/null +++ b/vtkm/exec/arg/AspectTagDefault.h @@ -0,0 +1,35 @@ +//============================================================================ +// 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 vtk_m_exec_arg_AspectTagDefault_h +#define vtk_m_exec_arg_AspectTagDefault_h + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief Aspect tag to use for default load/store of data. +/// +struct AspectTagDefault { }; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_AspectTagDefault_h diff --git a/vtkm/exec/arg/BasicArg.h b/vtkm/exec/arg/BasicArg.h new file mode 100644 index 000000000..d2adea78d --- /dev/null +++ b/vtkm/exec/arg/BasicArg.h @@ -0,0 +1,49 @@ +//============================================================================ +// 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 vtk_m_exec_arg_BasicArg_h +#define vtk_m_exec_arg_BasicArg_h + +#include + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief The underlying tag for basic \c ExecutionSignature arguments. +/// +/// The basic \c ExecutionSignature arguments of _1, _2, etc. are all +/// subclasses of \c BasicArg. They all make available the components of +/// this class. +/// +template +struct BasicArg : vtkm::exec::arg::ExecutionSignatureTagBase +{ + static const vtkm::IdComponent INDEX = ControlSignatureIndex; + typedef vtkm::exec::arg::AspectTagDefault AspectTag; +}; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_BasicArg_h diff --git a/vtkm/exec/arg/CMakeLists.txt b/vtkm/exec/arg/CMakeLists.txt new file mode 100644 index 000000000..fb6d3e0a2 --- /dev/null +++ b/vtkm/exec/arg/CMakeLists.txt @@ -0,0 +1,36 @@ +##============================================================================ +## 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. +##============================================================================ + +set(headers + AspectTagDefault.h + BasicArg.h + ExecutionSignatureTagBase.h + Fetch.h + FetchTagArrayDirectIn.h + FetchTagArrayDirectOut.h + FetchTagExecObject.h + WorkIndex.h + ) + +vtkm_declare_headers(${headers}) + + +#----------------------------------------------------------------------------- +add_subdirectory(testing) diff --git a/vtkm/exec/arg/ExecutionSignatureTagBase.h b/vtkm/exec/arg/ExecutionSignatureTagBase.h new file mode 100644 index 000000000..d6418794c --- /dev/null +++ b/vtkm/exec/arg/ExecutionSignatureTagBase.h @@ -0,0 +1,71 @@ +//============================================================================ +// 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 vtk_m_exec_arg_ExecutionSignatureTagBase_h +#define vtk_m_exec_arg_ExecutionSignatureTagBase_h + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief The base class for all tags used in an \c ExecutionSignature. +/// +/// If a new \c ExecutionSignature tag is created, it must be derived from this +/// class in some way. This helps identify \c ExecutionSignature tags in the \c +/// VTKM_IS_EXECUTION_SIGNATURE_TAG macro and allows checking the validity of +/// an \c ExecutionSignature. +/// +/// In addition to inheriting from this base class, an \c ExecutionSignature +/// tag must define a \c static \c const \c vtkm::IdComponent named \c INDEX +/// that points to a parameter in the \c ControlSignature and a \c typedef +/// named \c AspectTag that defines the aspect of the fetch. +/// +struct ExecutionSignatureTagBase { }; + +namespace internal { + +template +struct ExecutionSignatureTagCheck +{ + static const bool Valid = + boost::is_base_of< + vtkm::exec::arg::ExecutionSignatureTagBase, ExecutionSignatureTag>:: + value; +}; + +} // namespace internal + +/// Checks that the argument is a proper tag for an \c ExecutionSignature. This +/// is a handy concept check when modifying tags or dispatching to make sure +/// that a template argument is actually an \c ExecutionSignature tag. (You can +/// get weird errors elsewhere in the code when a mistake is made.) +/// +#define VTKM_IS_EXECUTION_SIGNATURE_TAG(tag) \ + BOOST_STATIC_ASSERT_MSG( \ + ::vtkm::exec::arg::internal::ExecutionSignatureTagCheck::Valid, \ + "Provided a type that is not a valid ExecutionSignature tag.") + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_ExecutionSignatureTagBase_h diff --git a/vtkm/exec/arg/Fetch.h b/vtkm/exec/arg/Fetch.h new file mode 100644 index 000000000..9632b816f --- /dev/null +++ b/vtkm/exec/arg/Fetch.h @@ -0,0 +1,108 @@ +//============================================================================ +// 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 vtk_m_exec_arg_Fetch_h +#define vtk_m_exec_arg_Fetch_h + +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief Class for loading and storing values in thread instance. +/// +/// The \c Fetch class is used within a thread in the execution environment +/// to load a value from an execution object specific for the given thread +/// instance and to store a resulting value back in the object. (Either load +/// or store can be a no-op.) +/// +/// \c Fetch is a templated class with four arguments. The first argument is +/// a tag declaring the type of fetch, which is usually tied to a particular +/// type of execution object. The second argument is an aspect tag that +/// declares what type of data to pull/push. Together, these two tags determine +/// the mechanism for the fetch. The third argument as an Invocation object +/// containing the details of the call. The fourth argument identifies the +/// parameter of the input arguments that is the source of the data. +/// +/// There is no generic implementaiton of \c Fetch. There are partial +/// specializations of \c Fetch for each mechanism (fetch-aspect tag +/// combination) supported. If you get a compiler error about an incomplete +/// type for \c Fetch, it means you used an invalid \c FetchTag - \c AspectTag +/// combination. Most likely this means that a parameter in an +/// ExecutionSignature with a particular aspect is pointing to the wrong +/// argument or an invalid argument in the ControlSignature. +/// +template +struct Fetch +#ifdef VTKM_DOXYGEN_ONLY +{ + /// \brief The type of the execution object to load and store data (optional). + /// + /// This is the type of the parameter of the \c Invocation pointed to by + /// \c ParameterIndex. Declaring this is optional, but often helpful. + /// + typedef typename Invocation::ParameterInterface:: + template ParameterType::type ExecObjectType; + + /// \brief The type of value to load and store. + /// + /// All \c Fetch specializations are expected to declare a type named \c + /// ValueType that is the type of object returned from \c Load and passed to + /// \c Store. + /// + typedef typename ExecObjectType::ValueType ValueType; + + /// \brief Load data for a work instance. + /// + /// All \c Fetch specializations are expected to have a constant method named + /// \c Load that takes a work instance index and an \c Invocation object + /// (preferably as a constant reference) and returns the value appropriate + /// for the work instance. If there is no actual data to load (for example + /// for a write-only fetch), this method can be a no-op and return any value. + /// + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id index, const Invocation &invocation) const; + + /// \brief Store data from a work instance. + /// + /// All \c Fetch specializations are expected to have a constant method named + /// \c Store that takes a work instance index, a an \c Invocation object + /// (preferably as a constant reference), and a value computed by the given + /// work instance and stores that value into the execution object associated + /// with this fetch. If the store is not applicable (for example for a + /// read-only fetch), this method can be a no-op. + /// + VTKM_EXEC_EXPORT + void Store(vtkm::Id index, + const Invocation &invocation, + const ValueType &value) const; +}; +#else // VTKM_DOXYGEN_ONLY + ; +#endif // VTKM_DOXYGEN_ONLY + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_Fetch_h diff --git a/vtkm/exec/arg/FetchTagArrayDirectIn.h b/vtkm/exec/arg/FetchTagArrayDirectIn.h new file mode 100644 index 000000000..e751d7543 --- /dev/null +++ b/vtkm/exec/arg/FetchTagArrayDirectIn.h @@ -0,0 +1,69 @@ +//============================================================================ +// 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 vtk_m_exec_arg_FetchTagArrayDirectIn_h +#define vtk_m_exec_arg_FetchTagArrayDirectIn_h + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief \c Fetch tag for getting array values with direct indexing. +/// +/// \c FetchTagArrayDirectIn is a tag used with the \c Fetch class to retreive +/// values from an array portal. The fetch uses direct indexing, so the thread +/// index given to \c Load is used as the index into the array. +/// +struct FetchTagArrayDirectIn { }; + + +template +struct Fetch< + vtkm::exec::arg::FetchTagArrayDirectIn, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParameterIndex> +{ + typedef typename Invocation::ParameterInterface:: + template ParameterType::type ExecObjectType; + + typedef typename ExecObjectType::ValueType ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id index, const Invocation &invocation) const + { + return invocation.Parameters.template GetParameter(). + Get(index); + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id, const Invocation &, const ValueType &) const + { + // Store is a no-op for this fetch. + } +}; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_FetchTagArrayDirectIn_h diff --git a/vtkm/exec/arg/FetchTagArrayDirectOut.h b/vtkm/exec/arg/FetchTagArrayDirectOut.h new file mode 100644 index 000000000..20581a89c --- /dev/null +++ b/vtkm/exec/arg/FetchTagArrayDirectOut.h @@ -0,0 +1,72 @@ +//============================================================================ +// 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 vtk_m_exec_arg_FetchTagArrayDirectOut_h +#define vtk_m_exec_arg_FetchTagArrayDirectOut_h + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief \c Fetch tag for setting array values with direct indexing. +/// +/// \c FetchTagArrayDirectOut is a tag used with the \c Fetch class to store +/// values in an array portal. The fetch uses direct indexing, so the thread +/// index given to \c Store is used as the index into the array. +/// +struct FetchTagArrayDirectOut { }; + + +template +struct Fetch< + vtkm::exec::arg::FetchTagArrayDirectOut, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParameterIndex> +{ + typedef typename Invocation::ParameterInterface:: + template ParameterType::type ExecObjectType; + + typedef typename ExecObjectType::ValueType ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id, const Invocation &) const + { + // Load is a no-op for this fetch. + return ValueType(); + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id index, + const Invocation &invocation, + const ValueType &value) const + { + invocation.Parameters.template GetParameter(). + Set(index, value); + } +}; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_FetchTagArrayDirectOut_h diff --git a/vtkm/exec/arg/FetchTagExecObject.h b/vtkm/exec/arg/FetchTagExecObject.h new file mode 100644 index 000000000..dcf2aa3cf --- /dev/null +++ b/vtkm/exec/arg/FetchTagExecObject.h @@ -0,0 +1,81 @@ +//============================================================================ +// 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 vtk_m_exec_arg_FetchTagExecObject_h +#define vtk_m_exec_arg_FetchTagExecObject_h + +#include +#include + +#include + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief \c Fetch tag for execution objects. +/// +/// \c FetchTagExecObject is a tag used with the \c Fetch class to retreive +/// execution objects. For safety, execution objects are read-only. \c +/// FetchTagExecObject is almost always used in conjunction with \c +/// TransportTagExecObject and vice versa. +/// +struct FetchTagExecObject { }; + + +template +struct Fetch< + vtkm::exec::arg::FetchTagExecObject, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParameterIndex> +{ + typedef typename Invocation::ParameterInterface:: + template ParameterType::type ExecObjectType; + + // If you get a compile error here, it means you tried to use an object that + // is not an execution object as an argument that is expected to be one. All + // execution objects are expected to inherit from + // vtkm::exec::ExecutionObjectBase. + BOOST_MPL_ASSERT(( boost::is_base_of )); + + typedef ExecObjectType ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id vtkmNotUsed(index), + const Invocation &invocation) const + { + return invocation.Parameters.template GetParameter(); + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id, const Invocation &, const ValueType &) const + { + // Store is a no-op for this fetch. + } +}; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_FetchTagExecObject_h diff --git a/vtkm/exec/arg/WorkIndex.h b/vtkm/exec/arg/WorkIndex.h new file mode 100644 index 000000000..d9680b69e --- /dev/null +++ b/vtkm/exec/arg/WorkIndex.h @@ -0,0 +1,77 @@ +//============================================================================ +// 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 vtk_m_exec_arg_WorkIndex_h +#define vtk_m_exec_arg_WorkIndex_h + +#include +#include + +namespace vtkm { +namespace exec { +namespace arg { + +/// \brief Aspect tag to use for getting the work index. +/// +/// The \c AspectTagWorkIndex aspect tag causes the \c Fetch class to ignore +/// whatever data is in the associated execution object and return the index. +/// +struct AspectTagWorkIndex { }; + +/// \brief The \c ExecutionSignature tag to use to get the work index +/// +/// When a worklet is dispatched, it broken into pieces defined by the input +/// domain and scheduled on independent threads. This tag in the \c +/// ExecutionSignature passes the index for this work. \c WorkletBase contains +/// a typedef that points to this class. +/// +struct WorkIndex : vtkm::exec::arg::ExecutionSignatureTagBase +{ + // The index does not really matter because the fetch is going to ignore it. + // However, it still has to point to a valid parameter in the + // ControlSignature because the templating is going to grab a fetch tag + // whether we use it or not. 1 should be guaranteed to be valid since you + // need at least one argument for the input domain. + static const vtkm::IdComponent INDEX = 1; + typedef vtkm::exec::arg::AspectTagWorkIndex AspectTag; +}; + +template +struct Fetch +{ + typedef vtkm::Id ValueType; + + VTKM_EXEC_EXPORT + vtkm::Id Load(vtkm::Id index, const Invocation &) const + { + return index; + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id, const Invocation &, const ValueType &) const + { + // Store is a no-op. + } +}; + +} +} +} // namespace vtkm::exec::arg + +#endif //vtk_m_exec_arg_WorkIndex_h diff --git a/vtkm/exec/arg/testing/CMakeLists.txt b/vtkm/exec/arg/testing/CMakeLists.txt new file mode 100644 index 000000000..ada3ad5d3 --- /dev/null +++ b/vtkm/exec/arg/testing/CMakeLists.txt @@ -0,0 +1,29 @@ +#============================================================================ +## 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. +##============================================================================ + +set(unit_tests + UnitTestExecutionSignatureTag.cxx + UnitTestFetchArrayDirectIn.cxx + UnitTestFetchArrayDirectOut.cxx + UnitTestFetchExecObject.cxx + UnitTestFetchWorkIndex.cxx + ) + +vtkm_unit_tests(SOURCES ${unit_tests}) diff --git a/vtkm/exec/arg/testing/UnitTestExecutionSignatureTag.cxx b/vtkm/exec/arg/testing/UnitTestExecutionSignatureTag.cxx new file mode 100644 index 000000000..5a08ce99b --- /dev/null +++ b/vtkm/exec/arg/testing/UnitTestExecutionSignatureTag.cxx @@ -0,0 +1,52 @@ +//============================================================================ +// 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 +#include + +#include + +namespace { + +void TestExecutionSignatures() +{ + VTKM_IS_EXECUTION_SIGNATURE_TAG(vtkm::exec::arg::BasicArg<1>); + + VTKM_TEST_ASSERT( + vtkm::exec::arg::internal::ExecutionSignatureTagCheck< + vtkm::exec::arg::BasicArg<2> >::Valid, + "Bad check for BasicArg"); + + VTKM_TEST_ASSERT( + vtkm::exec::arg::internal::ExecutionSignatureTagCheck< + vtkm::exec::arg::WorkIndex >::Valid, + "Bad check for WorkIndex"); + + VTKM_TEST_ASSERT( + !vtkm::exec::arg::internal::ExecutionSignatureTagCheck::Valid, + "Bad check for vtkm::Id"); +} + +} // anonymous namespace + +int UnitTestExecutionSignatureTag(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestExecutionSignatures); +} diff --git a/vtkm/exec/arg/testing/UnitTestFetchArrayDirectIn.cxx b/vtkm/exec/arg/testing/UnitTestFetchArrayDirectIn.cxx new file mode 100644 index 000000000..a3087768e --- /dev/null +++ b/vtkm/exec/arg/testing/UnitTestFetchArrayDirectIn.cxx @@ -0,0 +1,120 @@ +//============================================================================ +// 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 + +#include +#include + +#include + +namespace { + +static const vtkm::Id ARRAY_SIZE = 10; + +template +struct TestPortal +{ + typedef T ValueType; + + VTKM_EXEC_CONT_EXPORT + vtkm::Id GetNumberOfValues() const { return ARRAY_SIZE; } + + VTKM_EXEC_CONT_EXPORT + ValueType Get(vtkm::Id index) const { + VTKM_TEST_ASSERT(index >= 0, "Bad portal index."); + VTKM_TEST_ASSERT(index < this->GetNumberOfValues(), "Bad portal index."); + return TestValue(index, ValueType()); + } +}; + +struct NullParam { }; + +template +struct FetchArrayDirectInTests +{ + + template + void TryInvocation(const Invocation &invocation) const + { + typedef vtkm::exec::arg::Fetch< + vtkm::exec::arg::FetchTagArrayDirectIn, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParamIndex> FetchType; + + FetchType fetch; + + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + T value = fetch.Load(index, invocation); + VTKM_TEST_ASSERT(test_equal(value, TestValue(index, T())), + "Got invalid value from Load."); + + value = T(2)*value; + + // This should be a no-op, but we should be able to call it. + fetch.Store(index, invocation, value); + } + } + + void operator()() const + { + std::cout << "Trying ArrayDirectIn fetch on parameter " << ParamIndex + << " with type " << vtkm::testing::TypeName::Name() + << std::endl; + + typedef vtkm::internal::FunctionInterface< + void(NullParam,NullParam,NullParam,NullParam,NullParam)> + BaseFunctionInterface; + + this->TryInvocation(vtkm::internal::make_Invocation<1>( + BaseFunctionInterface().Replace( + TestPortal()), + NullParam(), + NullParam())); + } + +}; + +struct TryType +{ + template + void operator()(T) const + { + FetchArrayDirectInTests<1,T>()(); + FetchArrayDirectInTests<2,T>()(); + FetchArrayDirectInTests<3,T>()(); + FetchArrayDirectInTests<4,T>()(); + FetchArrayDirectInTests<5,T>()(); + } +}; + +void TestExecObjectFetch() +{ + vtkm::testing::Testing::TryAllTypes(TryType()); +} + +} // anonymous namespace + +int UnitTestFetchArrayDirectIn(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestExecObjectFetch); +} diff --git a/vtkm/exec/arg/testing/UnitTestFetchArrayDirectOut.cxx b/vtkm/exec/arg/testing/UnitTestFetchArrayDirectOut.cxx new file mode 100644 index 000000000..537053e90 --- /dev/null +++ b/vtkm/exec/arg/testing/UnitTestFetchArrayDirectOut.cxx @@ -0,0 +1,129 @@ +//============================================================================ +// 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 + +#include +#include + +#include + +namespace { + +static const vtkm::Id ARRAY_SIZE = 10; + +static vtkm::Id g_NumSets; + +template +struct TestPortal +{ + typedef T ValueType; + + VTKM_EXEC_CONT_EXPORT + vtkm::Id GetNumberOfValues() const { return ARRAY_SIZE; } + + VTKM_EXEC_CONT_EXPORT + void Set(vtkm::Id index, const ValueType &value) const { + VTKM_TEST_ASSERT(index >= 0, "Bad portal index."); + VTKM_TEST_ASSERT(index < this->GetNumberOfValues(), "Bad portal index."); + VTKM_TEST_ASSERT(test_equal(value, TestValue(index, ValueType())), + "Tried to set invalid value."); + g_NumSets++; + } +}; + +struct NullParam { }; + +template +struct FetchArrayDirectOutTests +{ + + template + void TryInvocation(const Invocation &invocation) const + { + typedef vtkm::exec::arg::Fetch< + vtkm::exec::arg::FetchTagArrayDirectOut, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParamIndex> FetchType; + + FetchType fetch; + + g_NumSets = 0; + + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + // This is a no-op, but should be callable. + T value = fetch.Load(index, invocation); + + value = TestValue(index, T()); + + // The portal will check to make sure we are setting a good value. + fetch.Store(index, invocation, value); + } + + VTKM_TEST_ASSERT(g_NumSets == ARRAY_SIZE, + "Array portal's set not called correct number of times." + "Store method must be wrong."); + } + + void operator()() const + { + std::cout << "Trying ArrayDirectOut fetch on parameter " << ParamIndex + << " with type " << vtkm::testing::TypeName::Name() + << std::endl; + + typedef vtkm::internal::FunctionInterface< + void(NullParam,NullParam,NullParam,NullParam,NullParam)> + BaseFunctionInterface; + + this->TryInvocation(vtkm::internal::make_Invocation<1>( + BaseFunctionInterface().Replace( + TestPortal()), + NullParam(), + NullParam())); + } + +}; + +struct TryType +{ + template + void operator()(T) const + { + FetchArrayDirectOutTests<1,T>()(); + FetchArrayDirectOutTests<2,T>()(); + FetchArrayDirectOutTests<3,T>()(); + FetchArrayDirectOutTests<4,T>()(); + FetchArrayDirectOutTests<5,T>()(); + } +}; + +void TestExecObjectFetch() +{ + vtkm::testing::Testing::TryAllTypes(TryType()); +} + +} // anonymous namespace + +int UnitTestFetchArrayDirectOut(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestExecObjectFetch); +} diff --git a/vtkm/exec/arg/testing/UnitTestFetchExecObject.cxx b/vtkm/exec/arg/testing/UnitTestFetchExecObject.cxx new file mode 100644 index 000000000..1a2fb722a --- /dev/null +++ b/vtkm/exec/arg/testing/UnitTestFetchExecObject.cxx @@ -0,0 +1,100 @@ +//============================================================================ +// 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 + +#include +#include + +#include + +#include + +#define EXPECTED_NUMBER 67 + +namespace { + +struct TestExecutionObject : public vtkm::exec::ExecutionObjectBase +{ + TestExecutionObject() : Number(0xDEADDEAD) { } + TestExecutionObject(vtkm::Int32 number) : Number(number) { } + vtkm::Int32 Number; +}; + +struct NullParam { }; + +template +void TryInvocation(const Invocation &invocation) +{ + typedef vtkm::exec::arg::Fetch< + vtkm::exec::arg::FetchTagExecObject, + vtkm::exec::arg::AspectTagDefault, + Invocation, + ParamIndex> FetchType; + + FetchType fetch; + + TestExecutionObject execObject = fetch.Load(0, invocation); + VTKM_TEST_ASSERT(execObject.Number == EXPECTED_NUMBER, + "Did not load object correctly."); + + execObject.Number = -1; + + // This should be a no-op. + fetch.Store(0, invocation, execObject); + + // Data in Invocation should not have changed. + execObject = invocation.Parameters.template GetParameter(); + VTKM_TEST_ASSERT(execObject.Number == EXPECTED_NUMBER, + "Fetch changed read-only execution object."); +} + +template +void TryParamIndex() +{ + std::cout << "Trying ExecObject fetch on parameter " << ParamIndex + << std::endl; + + typedef vtkm::internal::FunctionInterface< + void(NullParam,NullParam,NullParam,NullParam,NullParam)> + BaseFunctionInterface; + + TryInvocation(vtkm::internal::make_Invocation<1>( + BaseFunctionInterface().Replace( + TestExecutionObject(EXPECTED_NUMBER)), + NullParam(), + NullParam())); +} + +void TestExecObjectFetch() +{ + TryParamIndex<1>(); + TryParamIndex<2>(); + TryParamIndex<3>(); + TryParamIndex<4>(); + TryParamIndex<5>(); +} + +} // anonymous namespace + +int UnitTestFetchExecObject(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestExecObjectFetch); +} diff --git a/vtkm/exec/arg/testing/UnitTestFetchWorkIndex.cxx b/vtkm/exec/arg/testing/UnitTestFetchWorkIndex.cxx new file mode 100644 index 000000000..a447c34d9 --- /dev/null +++ b/vtkm/exec/arg/testing/UnitTestFetchWorkIndex.cxx @@ -0,0 +1,76 @@ +//============================================================================ +// 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 + +#include + +#include +#include + +#include + +namespace { + +struct NullParam { }; + +template +void TryInvocation(const Invocation &invocation) +{ + typedef vtkm::exec::arg::Fetch< + vtkm::exec::arg::FetchTagArrayDirectIn, // Not used but probably common. + vtkm::exec::arg::AspectTagWorkIndex, + Invocation, + 1> FetchType; + + FetchType fetch; + + for (vtkm::Id index = 0; index < 10; index++) + { + vtkm::Id value = fetch.Load(index, invocation); + VTKM_TEST_ASSERT(value == index, + "Fetch did not give correct work index."); + + value++; + + // This should be a no-op. + fetch.Store(index, invocation, value); + } +} + +void TestWorkIndexFetch() +{ + std::cout << "Trying WorkIndex fetch." << std::endl; + + typedef vtkm::internal::FunctionInterface< + void(NullParam,NullParam,NullParam,NullParam,NullParam)> + BaseFunctionInterface; + + TryInvocation(vtkm::internal::make_Invocation<1>(BaseFunctionInterface(), + NullParam(), + NullParam())); +} + +} // anonymous namespace + +int UnitTestFetchWorkIndex(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestWorkIndexFetch); +} diff --git a/vtkm/exec/internal/CMakeLists.txt b/vtkm/exec/internal/CMakeLists.txt index 9636472b4..de99254f4 100644 --- a/vtkm/exec/internal/CMakeLists.txt +++ b/vtkm/exec/internal/CMakeLists.txt @@ -20,9 +20,12 @@ set(headers ErrorMessageBuffer.h - WorkletBase.h + WorkletInvokeFunctor.h + WorkletInvokeFunctorDetail.h ) vtkm_declare_headers(${headers}) +vtkm_pyexpander_generated_file(WorkletInvokeFunctorDetail.h) + add_subdirectory(testing) diff --git a/vtkm/exec/internal/WorkletInvokeFunctor.h b/vtkm/exec/internal/WorkletInvokeFunctor.h new file mode 100644 index 000000000..eae790d30 --- /dev/null +++ b/vtkm/exec/internal/WorkletInvokeFunctor.h @@ -0,0 +1,67 @@ +//============================================================================ +// 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 vtk_m_exec_internal_WorkletInvokeFunctor_h +#define vtk_m_exec_internal_WorkletInvokeFunctor_h + +#include + +#include + +#include + +#include + +namespace vtkm { +namespace exec { +namespace internal { + +template +class WorkletInvokeFunctor : public vtkm::exec::FunctorBase +{ +public: + VTKM_CONT_EXPORT + WorkletInvokeFunctor(const WorkletType &worklet, + const InvocationType &invocation) + : Worklet(worklet), Invocation(invocation) { } + + VTKM_CONT_EXPORT + void SetErrorMessageBuffer( + const vtkm::exec::internal::ErrorMessageBuffer &buffer) + { + this->FunctorBase::SetErrorMessageBuffer(buffer); + this->Worklet.SetErrorMessageBuffer(buffer); + } + + VTKM_EXEC_EXPORT + void operator()(vtkm::Id index) const + { + detail::DoWorkletInvokeFunctor(this->Worklet, this->Invocation, index); + } + +private: + WorkletType Worklet; + InvocationType Invocation; +}; + +} +} +} // vtkm::exec::internal + +#endif //vtk_m_exec_internal_WorkletInvokeFunctor_h diff --git a/vtkm/exec/internal/WorkletInvokeFunctorDetail.h b/vtkm/exec/internal/WorkletInvokeFunctorDetail.h new file mode 100644 index 000000000..f04b106cc --- /dev/null +++ b/vtkm/exec/internal/WorkletInvokeFunctorDetail.h @@ -0,0 +1,1266 @@ +//============================================================================ +// 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. +//============================================================================ +// **** DO NOT EDIT THIS FILE!!! **** +// This file is automatically generated by WorkletInvokeFunctorDetail.h.in + +// Technically speaking, we can implement this functionality with some clever +// use of FunctionInterface rather than using pyexpander to make variadic +// code. However, this code is probably more friendly to compilers. I expect +// it to compiler faster and optimize better. + +#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h +#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h + +#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD) +#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h +#endif + +#include +#include + +#include + +#if VTKM_MAX_FUNCTION_PARAMETERS != 10 +#error Mismatch of maximum parameters between FunctionInterfaceDatailPre.h.in and WorkletInvokeFunctorDetail.h.in +#endif + + +namespace vtkm { +namespace exec { +namespace internal { +namespace detail { + +/// A helper class that takes an \c Invocation object and an index to a +/// parameter in the ExecutionSignature and finds the \c Fetch type valid for +/// that parameter. +template +struct InvocationToFetch +{ +private: + typedef typename Invocation::ExecutionInterface:: + template ParameterType::type + ExecutionSignatureTag; + + // Expected fields from ExecutionSignatureTag. If these do not exist in + // ExecutionSignatureTag, then something that is not really an execution + // signature tag was used in an ExecutionSignature. + static const vtkm::IdComponent ControlParameterIndex = + ExecutionSignatureTag::INDEX; + typedef typename ExecutionSignatureTag::AspectTag AspectTag; + + // Find the fetch tag from the control signature tag pointed to by + // ParameterIndex. + typedef typename Invocation::ControlInterface ControlInterface; + typedef typename ControlInterface:: + template ParameterType::type ControlSignatureTag; + typedef typename ControlSignatureTag::FetchTag FetchTag; + +public: + typedef vtkm::exec::arg::Fetch< + FetchTag,AspectTag,Invocation,ControlParameterIndex> type; +}; + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + worklet(p1); + + fetch1.Store(index, invocation, p1); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + worklet(p1,p2); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + worklet(p1,p2,p3); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + worklet(p1,p2,p3,p4); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5,p6)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5,p6); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5,p6,p7)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5,p6,p7); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5,p6,p7,p8)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5,p6,p7,p8); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType9; + FetchType9 fetch9; + typename FetchType9::ValueType p9 = fetch9.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5,p6,p7,p8,p9)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); + fetch9.Store(index, invocation, p9); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType9; + FetchType9 fetch9; + typename FetchType9::ValueType p9 = fetch9.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5,p6,p7,p8,p9); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); + fetch9.Store(index, invocation, p9); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType9; + FetchType9 fetch9; + typename FetchType9::ValueType p9 = fetch9.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType10; + FetchType10 fetch10; + typename FetchType10::ValueType p10 = fetch10.Load(index, invocation); + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType r = ReturnValueType(worklet(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10)); + + returnFetch.Store(index, invocation, r); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); + fetch9.Store(index, invocation, p9); + fetch10.Store(index, invocation, p10); +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface, + InputDomainIndex> Invocation; + + typedef typename InvocationToFetch::type FetchType1; + FetchType1 fetch1; + typename FetchType1::ValueType p1 = fetch1.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType2; + FetchType2 fetch2; + typename FetchType2::ValueType p2 = fetch2.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType3; + FetchType3 fetch3; + typename FetchType3::ValueType p3 = fetch3.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType4; + FetchType4 fetch4; + typename FetchType4::ValueType p4 = fetch4.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType5; + FetchType5 fetch5; + typename FetchType5::ValueType p5 = fetch5.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType6; + FetchType6 fetch6; + typename FetchType6::ValueType p6 = fetch6.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType7; + FetchType7 fetch7; + typename FetchType7::ValueType p7 = fetch7.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType8; + FetchType8 fetch8; + typename FetchType8::ValueType p8 = fetch8.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType9; + FetchType9 fetch9; + typename FetchType9::ValueType p9 = fetch9.Load(index, invocation); + + typedef typename InvocationToFetch::type FetchType10; + FetchType10 fetch10; + typename FetchType10::ValueType p10 = fetch10.Load(index, invocation); + + worklet(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10); + + fetch1.Store(index, invocation, p1); + fetch2.Store(index, invocation, p2); + fetch3.Store(index, invocation, p3); + fetch4.Store(index, invocation, p4); + fetch5.Store(index, invocation, p5); + fetch6.Store(index, invocation, p6); + fetch7.Store(index, invocation, p7); + fetch8.Store(index, invocation, p8); + fetch9.Store(index, invocation, p9); + fetch10.Store(index, invocation, p10); +} + + +} +} +} +} // namespace vtkm::exec::internal::detail + +#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h diff --git a/vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in b/vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in new file mode 100644 index 000000000..f5eec4ec5 --- /dev/null +++ b/vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in @@ -0,0 +1,220 @@ +//============================================================================ +// 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 file uses the pyexpander macro processing utility to build the +$# FunctionInterface facilities that use a variable number of arguments. +$# Information, documentation, and downloads for pyexpander can be found at: +$# +$# http://pyexpander.sourceforge.net/ +$# +$# To build the source code, execute the following (after installing +$# pyexpander, of course): +$# +$# expander.py WorkletInvokeFunctorDetail.h.in > WorkletInvokeFunctorDetail.h +$# +$# Ignore the following comment. It is meant for the generated file. +// **** DO NOT EDIT THIS FILE!!! **** +// This file is automatically generated by WorkletInvokeFunctorDetail.h.in + +// Technically speaking, we can implement this functionality with some clever +// use of FunctionInterface rather than using pyexpander to make variadic +// code. However, this code is probably more friendly to compilers. I expect +// it to compiler faster and optimize better. + +#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h +#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h + +#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD) +#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h +#endif + +#include +#include + +#include + +$# This needs to match the max_parameters in FunctionInterfaceDetailPre.h.in +$py(max_parameters=10)\ +#if VTKM_MAX_FUNCTION_PARAMETERS != $(max_parameters) +#error Mismatch of maximum parameters between FunctionInterfaceDatailPre.h.in and WorkletInvokeFunctorDetail.h.in +#endif + +$# Python commands used in template expansion. +$py( +def comma_if(flag): + if flag: + return ',' + else: + return ''; + +def ptype(num, name=''): + if num == 0: + return '%sR' % name + else: + return '%sP%d' % (name, num) + +def pname(num, name=''): + if num == 0: + return '%sr' % name + else: + return '%sp%d' % (name, num) + +def template_params(num_params, start=0, name=''): + if num_params < start: + return '' + result = 'typename %s' % ptype(start, name) + for param in xrange(start+1, num_params+1): + result += ',\n typename %s' % ptype(param, name) + return result + +def signature(num_params, return_type=ptype(0), name=''): + result = '%s(' % return_type + if num_params > 0: + result += ptype(1, name) + for param in xrange(2, num_params+1): + result += ',%s' % ptype(param, name) + result += ')' + return result + +def arg_list(num_params, name='', start=1): + if num_params < start: + return '' + result = pname(start, name) + for param in xrange(start+1, num_params+1): + result += ',%s' % pname(param, name) + return result +)\ +$# +$extend(comma_if, ptype, pname, template_params, signature, arg_list)\ + +namespace vtkm { +namespace exec { +namespace internal { +namespace detail { + +/// A helper class that takes an \c Invocation object and an index to a +/// parameter in the ExecutionSignature and finds the \c Fetch type valid for +/// that parameter. +template +struct InvocationToFetch +{ +private: + typedef typename Invocation::ExecutionInterface:: + template ParameterType::type + ExecutionSignatureTag; + + // Expected fields from ExecutionSignatureTag. If these do not exist in + // ExecutionSignatureTag, then something that is not really an execution + // signature tag was used in an ExecutionSignature. + static const vtkm::IdComponent ControlParameterIndex = + ExecutionSignatureTag::INDEX; + typedef typename ExecutionSignatureTag::AspectTag AspectTag; + + // Find the fetch tag from the control signature tag pointed to by + // ParameterIndex. + typedef typename Invocation::ControlInterface ControlInterface; + typedef typename ControlInterface:: + template ParameterType::type ControlSignatureTag; + typedef typename ControlSignatureTag::FetchTag FetchTag; + +public: + typedef vtkm::exec::arg::Fetch< + FetchTag,AspectTag,Invocation,ControlParameterIndex> type; +}; + +$for(num_params in range(1, max_parameters+1))\ +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface<$signature(num_params)>, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface<$signature(num_params)>, + InputDomainIndex> Invocation; +$for(param_index in range(1, num_params+1))\ + + typedef typename InvocationToFetch::type FetchType$(param_index); + FetchType$(param_index) fetch$(param_index); + typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation); +$endfor\ + + typedef typename InvocationToFetch::type ReturnFetchType; + typedef typename ReturnFetchType::ValueType ReturnValueType; + ReturnFetchType returnFetch; + ReturnValueType $pname(0) = ReturnValueType(worklet($arg_list(num_params))); + + returnFetch.Store(index, invocation, $pname(0)); + +$for(param_index in range(1, num_params+1))\ + fetch$(param_index).Store(index, invocation, $pname(param_index)); +$endfor\ +} + +template +void DoWorkletInvokeFunctor( + const WorkletType &worklet, + const vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>, + InputDomainIndex> &invocation, + vtkm::Id index) +{ + typedef vtkm::internal::Invocation< + ParameterInterface, + ControlInterface, + vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>, + InputDomainIndex> Invocation; +$for(param_index in range(1, num_params+1))\ + + typedef typename InvocationToFetch::type FetchType$(param_index); + FetchType$(param_index) fetch$(param_index); + typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation); +$endfor\ + + worklet($arg_list(num_params)); + +$for(param_index in range(1, num_params+1))\ + fetch$(param_index).Store(index, invocation, $pname(param_index)); +$endfor\ +} + +$endfor\ + +} +} +} +} // namespace vtkm::exec::internal::detail + +#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h diff --git a/vtkm/exec/internal/testing/CMakeLists.txt b/vtkm/exec/internal/testing/CMakeLists.txt index 90d268e13..3c14d7a18 100644 --- a/vtkm/exec/internal/testing/CMakeLists.txt +++ b/vtkm/exec/internal/testing/CMakeLists.txt @@ -22,5 +22,6 @@ set(unit_tests UnitTestErrorMessageBuffer.cxx + UnitTestWorkletInvokeFunctor.cxx ) vtkm_unit_tests(SOURCES ${unit_tests}) diff --git a/vtkm/exec/internal/testing/UnitTestWorkletInvokeFunctor.cxx b/vtkm/exec/internal/testing/UnitTestWorkletInvokeFunctor.cxx new file mode 100644 index 000000000..fbe2b6eb2 --- /dev/null +++ b/vtkm/exec/internal/testing/UnitTestWorkletInvokeFunctor.cxx @@ -0,0 +1,285 @@ +//============================================================================ +// 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 + +#include + +#include + +#include + +#include +#include + +namespace { + +struct TestExecObject +{ + VTKM_EXEC_CONT_EXPORT + TestExecObject() : Value(NULL) { } + + VTKM_EXEC_CONT_EXPORT + TestExecObject(vtkm::Id *value) : Value(value) { } + + vtkm::Id *Value; +}; + +struct TestFetchTagInput { }; +struct TestFetchTagOutput { }; + +// Missing TransportTag, but we are not testing that so we can leave it out. +struct TestControlSignatureTagInput +{ + typedef TestFetchTagInput FetchTag; +}; +struct TestControlSignatureTagOutput +{ + typedef TestFetchTagOutput FetchTag; +}; + +} // anonymous namespace + +namespace vtkm { +namespace exec { +namespace arg { + +template +struct Fetch +{ + typedef vtkm::Id ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id index, const Invocation &invocation) const { + return *invocation.Parameters. + template GetParameter().Value + 10*index; + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id, const Invocation &, ValueType) const { + // No-op + } +}; + +template +struct Fetch +{ + typedef vtkm::Id ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id, const Invocation &) const { + // No-op + return ValueType(); + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id index, + const Invocation &invocation, + ValueType value) const { + *invocation.Parameters.template GetParameter().Value = + value + 20*index; + } +}; + +} +} +} // vtkm::exec::arg + +namespace { + +typedef void TestControlSignature(TestControlSignatureTagInput, + TestControlSignatureTagOutput); +typedef vtkm::internal::FunctionInterface + TestControlInterface; + +typedef void TestExecutionSignature1(vtkm::exec::arg::BasicArg<1>, + vtkm::exec::arg::BasicArg<2>); +typedef vtkm::internal::FunctionInterface + TestExecutionInterface1; + +typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2( + vtkm::exec::arg::BasicArg<1>); +typedef vtkm::internal::FunctionInterface + TestExecutionInterface2; + +typedef vtkm::internal::FunctionInterface + ExecutionParameterInterface; + +typedef vtkm::internal::Invocation< + ExecutionParameterInterface, + TestControlInterface, + TestExecutionInterface1, + 1> InvocationType1; + +typedef vtkm::internal::Invocation< + ExecutionParameterInterface, + TestControlInterface, + TestExecutionInterface2, + 1> InvocationType2; + +// Not a full worklet, but provides operators that we expect in a worklet. +struct TestWorkletProxy : vtkm::exec::FunctorBase +{ + VTKM_EXEC_EXPORT + void operator()(vtkm::Id input, vtkm::Id &output) const + { + output = input + 100; + } + + VTKM_EXEC_EXPORT + vtkm::Id operator()(vtkm::Id input) const + { + return input + 200; + } +}; + +#define ERROR_MESSAGE "Expected worklet error." + +// Not a full worklet, but provides operators that we expect in a worklet. +struct TestWorkletErrorProxy : vtkm::exec::FunctorBase +{ + VTKM_EXEC_EXPORT + void operator()(vtkm::Id, vtkm::Id) const + { + this->RaiseError(ERROR_MESSAGE); + } +}; + +// Check behavior of InvocationToFetch helper class. + +BOOST_MPL_ASSERT(( boost::is_same< + vtkm::exec::internal::detail::InvocationToFetch::type, + vtkm::exec::arg::Fetch > )); + +BOOST_MPL_ASSERT(( boost::is_same< + vtkm::exec::internal::detail::InvocationToFetch::type, + vtkm::exec::arg::Fetch > )); + +BOOST_MPL_ASSERT(( boost::is_same< + vtkm::exec::internal::detail::InvocationToFetch::type, + vtkm::exec::arg::Fetch > )); + +void TestDoWorkletInvoke() +{ + std::cout << "Testing internal worklet invoke." << std::endl; + + vtkm::Id inputTestValue; + vtkm::Id outputTestValue; + vtkm::internal::FunctionInterface execObjects = + vtkm::internal::make_FunctionInterface(TestExecObject(&inputTestValue), + TestExecObject(&outputTestValue)); + + std::cout << " Try void return." << std::endl; + inputTestValue = 5; + outputTestValue = 0xDEADDEAD; + vtkm::exec::internal::detail::DoWorkletInvokeFunctor( + TestWorkletProxy(), + vtkm::internal::make_Invocation<1>(execObjects, + TestControlInterface(), + TestExecutionInterface1()), + 1); + VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed."); + VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30, + "Output value not set right."); + + std::cout << " Try return value." << std::endl; + inputTestValue = 6; + outputTestValue = 0xDEADDEAD; + vtkm::exec::internal::detail::DoWorkletInvokeFunctor( + TestWorkletProxy(), + vtkm::internal::make_Invocation<1>(execObjects, + TestControlInterface(), + TestExecutionInterface2()), + 2); + VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed."); + VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2, + "Output value not set right."); +} + +void TestNormalFunctorInvoke() +{ + std::cout << "Testing normal worklet invoke." << std::endl; + + vtkm::Id inputTestValue; + vtkm::Id outputTestValue; + vtkm::internal::FunctionInterface execObjects = + vtkm::internal::make_FunctionInterface(TestExecObject(&inputTestValue), + TestExecObject(&outputTestValue)); + + std::cout << " Try void return." << std::endl; + inputTestValue = 5; + outputTestValue = 0xDEADDEAD; + typedef vtkm::exec::internal::WorkletInvokeFunctor WorkletInvokeFunctor1; + WorkletInvokeFunctor1 workletInvokeFunctor1 = + WorkletInvokeFunctor1(TestWorkletProxy(), InvocationType1(execObjects)); + workletInvokeFunctor1(1); + VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed."); + VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30, + "Output value not set right."); + + std::cout << " Try return value." << std::endl; + inputTestValue = 6; + outputTestValue = 0xDEADDEAD; + typedef vtkm::exec::internal::WorkletInvokeFunctor WorkletInvokeFunctor2; + WorkletInvokeFunctor2 workletInvokeFunctor2 = + WorkletInvokeFunctor2(TestWorkletProxy(), InvocationType2(execObjects)); + workletInvokeFunctor2(2); + VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed."); + VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2, + "Output value not set right."); +} + +void TestErrorFunctorInvoke() +{ + std::cout << "Testing invoke with an error raised in the worklet." << std::endl; + + vtkm::Id inputTestValue = 5; + vtkm::Id outputTestValue = 0xDEADDEAD; + vtkm::internal::FunctionInterface execObjects = + vtkm::internal::make_FunctionInterface(TestExecObject(&inputTestValue), + TestExecObject(&outputTestValue)); + + typedef vtkm::exec::internal::WorkletInvokeFunctor WorkletInvokeFunctor1; + WorkletInvokeFunctor1 workletInvokeFunctor1 = + WorkletInvokeFunctor1(TestWorkletErrorProxy(), InvocationType1(execObjects)); + char message[1024]; + message[0] = '\0'; + vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024); + workletInvokeFunctor1.SetErrorMessageBuffer(errorMessage); + workletInvokeFunctor1(1); + + VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly."); + VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE), + "Got wrong error message."); +} + +void TestWorkletInvokeFunctor() +{ + TestDoWorkletInvoke(); + TestNormalFunctorInvoke(); + TestErrorFunctorInvoke(); +} + +} // anonymous namespace + +int UnitTestWorkletInvokeFunctor(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestWorkletInvokeFunctor); +} diff --git a/vtkm/internal/CMakeLists.txt b/vtkm/internal/CMakeLists.txt index 64d1c76d2..dbf855514 100644 --- a/vtkm/internal/CMakeLists.txt +++ b/vtkm/internal/CMakeLists.txt @@ -25,6 +25,7 @@ set(headers FunctionInterface.h FunctionInterfaceDetailPost.h FunctionInterfaceDetailPre.h + Invocation.h ListTagDetail.h ) diff --git a/vtkm/internal/FunctionInterface.h b/vtkm/internal/FunctionInterface.h index 268becab3..41f083906 100644 --- a/vtkm/internal/FunctionInterface.h +++ b/vtkm/internal/FunctionInterface.h @@ -20,8 +20,8 @@ #ifndef vtk_m_internal_FunctionInterface_h #define vtk_m_internal_FunctionInterface_h +#include #include -#include #include #include @@ -498,7 +498,7 @@ public: /// the return type of the transform for a given input type. /// /// The transformation is only applied to the parameters of the function. The - /// return argument is uneffected. + /// return argument is unaffected. /// /// The return type can be determined with the \c StaticTransformType /// template. @@ -567,7 +567,7 @@ public: /// /// Here is a contrived but illustrative example. This transformation will /// pass all arguments except any string that looks like a number will be - /// converted to a vtkm::Scalar. Note that because the types are not + /// converted to a vtkm::FloatDefault. Note that because the types are not /// determined till runtime, this transform cannot be determined at compile /// time with meta-template programming. /// @@ -589,7 +589,7 @@ public: /// if ((input[0] >= '0' && (input[0] <= '9')) /// { /// std::stringstream stream(input); - /// vtkm::Scalar value; + /// vtkm::FloatDefault value; /// stream >> value; /// continueFunc(value); /// } @@ -625,7 +625,7 @@ public: template VTKM_CONT_EXPORT void DynamicTransformCont(const TransformFunctor &transform, - const FinishFunctor &finish) { + const FinishFunctor &finish) const { typedef detail::FunctionInterfaceDynamicTransformContContinue< FunctionSignature, ResultType(), @@ -637,7 +637,7 @@ public: ContinueFunctorType(*this, emptyInterface, transform, finish); continueFunctor.DoNextTransform(emptyInterface); - this->Result = emptyInterface.GetReturnValueSafe(); +// this->Result = emptyInterface.GetReturnValueSafe(); } /// \brief Applies a function to all the parameters. @@ -682,7 +682,7 @@ class FunctionInterfaceDynamicTransformContContinue { public: FunctionInterfaceDynamicTransformContContinue( - vtkm::internal::FunctionInterface &originalInterface, + const vtkm::internal::FunctionInterface &originalInterface, vtkm::internal::FunctionInterface &newInterface, const TransformFunctor &transform, const FinishFunctor &finish) @@ -740,14 +740,33 @@ public: } private: - vtkm::internal::FunctionInterface &OriginalInterface; + const vtkm::internal::FunctionInterface &OriginalInterface; vtkm::internal::FunctionInterface &NewInterface; const TransformFunctor &Transform; const FinishFunctor &Finish; }; +template +struct FunctionInterfaceZipReturn +{ + typedef vtkm::Pair type; +}; + +template<> +struct FunctionInterfaceZipReturn +{ + typedef void type; +}; + } // namespace detail +/// Used to determine the type returned from \c make_FunctionInterfaceZip. +/// Contains a typedef named \c type that is the appropriate \c +/// FunctionInterface type. +/// +template +struct FunctionInterfaceZipType; + } } // namespace vtkm::internal diff --git a/vtkm/internal/FunctionInterfaceDetailPost.h b/vtkm/internal/FunctionInterfaceDetailPost.h index 7adbf6197..9303f44d4 100644 --- a/vtkm/internal/FunctionInterfaceDetailPost.h +++ b/vtkm/internal/FunctionInterfaceDetailPost.h @@ -641,6 +641,753 @@ make_FunctionInterface( } +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + +template +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn::type ( + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair, + vtkm::Pair + )> type; +}; + + +/// Creates a "zipped" version of two \c FunctionInterface objects. Each +/// parameter in the returned object is a \c vtkm::Pair that is a combination +/// of the corresponding pair of the input objects. +/// +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + result.template SetParameter<6>( + vtkm::make_Pair(first.template GetParameter<6>(), + second.template GetParameter<6>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + result.template SetParameter<6>( + vtkm::make_Pair(first.template GetParameter<6>(), + second.template GetParameter<6>())); + result.template SetParameter<7>( + vtkm::make_Pair(first.template GetParameter<7>(), + second.template GetParameter<7>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + result.template SetParameter<6>( + vtkm::make_Pair(first.template GetParameter<6>(), + second.template GetParameter<6>())); + result.template SetParameter<7>( + vtkm::make_Pair(first.template GetParameter<7>(), + second.template GetParameter<7>())); + result.template SetParameter<8>( + vtkm::make_Pair(first.template GetParameter<8>(), + second.template GetParameter<8>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + result.template SetParameter<6>( + vtkm::make_Pair(first.template GetParameter<6>(), + second.template GetParameter<6>())); + result.template SetParameter<7>( + vtkm::make_Pair(first.template GetParameter<7>(), + second.template GetParameter<7>())); + result.template SetParameter<8>( + vtkm::make_Pair(first.template GetParameter<8>(), + second.template GetParameter<8>())); + result.template SetParameter<9>( + vtkm::make_Pair(first.template GetParameter<9>(), + second.template GetParameter<9>())); + + return result; +} + +template +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface &first, + const vtkm::internal::FunctionInterface &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface, + vtkm::internal::FunctionInterface >::type result; + + result.template SetParameter<1>( + vtkm::make_Pair(first.template GetParameter<1>(), + second.template GetParameter<1>())); + result.template SetParameter<2>( + vtkm::make_Pair(first.template GetParameter<2>(), + second.template GetParameter<2>())); + result.template SetParameter<3>( + vtkm::make_Pair(first.template GetParameter<3>(), + second.template GetParameter<3>())); + result.template SetParameter<4>( + vtkm::make_Pair(first.template GetParameter<4>(), + second.template GetParameter<4>())); + result.template SetParameter<5>( + vtkm::make_Pair(first.template GetParameter<5>(), + second.template GetParameter<5>())); + result.template SetParameter<6>( + vtkm::make_Pair(first.template GetParameter<6>(), + second.template GetParameter<6>())); + result.template SetParameter<7>( + vtkm::make_Pair(first.template GetParameter<7>(), + second.template GetParameter<7>())); + result.template SetParameter<8>( + vtkm::make_Pair(first.template GetParameter<8>(), + second.template GetParameter<8>())); + result.template SetParameter<9>( + vtkm::make_Pair(first.template GetParameter<9>(), + second.template GetParameter<9>())); + result.template SetParameter<10>( + vtkm::make_Pair(first.template GetParameter<10>(), + second.template GetParameter<10>())); + + return result; +} + + } } // namespace vtkm::internal diff --git a/vtkm/internal/FunctionInterfaceDetailPost.h.in b/vtkm/internal/FunctionInterfaceDetailPost.h.in index 19a9e06ef..dcfe121da 100644 --- a/vtkm/internal/FunctionInterfaceDetailPost.h.in +++ b/vtkm/internal/FunctionInterfaceDetailPost.h.in @@ -69,8 +69,8 @@ def template_params(num_params, start=0, name=''): result += ',\n typename %s' % ptype(param, name) return result -def signature(num_params, return_type=ptype(0), name=''): - result = '%s(' % return_type +def signature(num_params, name=''): + result = '%s(' % ptype(0, name) if num_params > 0: result += ptype(1, name) for param in xrange(2, num_params+1): @@ -136,6 +136,53 @@ $endfor\ $endfor\ +$for(num_params in xrange(0, max_parameters+1))\ +template<$template_params(num_params, name='T'), + $template_params(num_params, name='U')> +struct FunctionInterfaceZipType< + vtkm::internal::FunctionInterface<$signature(num_params, name='T')>, + vtkm::internal::FunctionInterface<$signature(num_params, name='U')> > +{ + typedef vtkm::internal::FunctionInterface< + typename detail::FunctionInterfaceZipReturn<$ptype(0,name='T'),$ptype(0,name='U')>::type ( +$for(param_index in xrange(1, num_params+1))\ + vtkm::Pair<$ptype(param_index,name='T'), $ptype(param_index,name='U')>$comma_if(num_params-param_index) +$endfor\ + )> type; +}; + +$endfor\ + +/// Creates a "zipped" version of two \c FunctionInterface objects. Each +/// parameter in the returned object is a \c vtkm::Pair that is a combination +/// of the corresponding pair of the input objects. +/// +$for(num_params in xrange(1, max_parameters+1))\ +template<$template_params(num_params, name='T'), + $template_params(num_params, name='U')> +VTKM_EXEC_CONT_EXPORT +typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface<$signature(num_params, name='T')>, + vtkm::internal::FunctionInterface<$signature(num_params, name='U')> >::type +make_FunctionInterfaceZip( + const vtkm::internal::FunctionInterface<$signature(num_params, name='T')> &first, + const vtkm::internal::FunctionInterface<$signature(num_params, name='U')> &second) +{ + typename vtkm::internal::FunctionInterfaceZipType< + vtkm::internal::FunctionInterface<$signature(num_params, name='T')>, + vtkm::internal::FunctionInterface<$signature(num_params, name='U')> >::type result; + +$for(param_index in xrange(1, num_params+1))\ + result.template SetParameter<$(param_index)>( + vtkm::make_Pair(first.template GetParameter<$(param_index)>(), + second.template GetParameter<$(param_index)>())); +$endfor\ + + return result; +} + +$endfor\ + } } // namespace vtkm::internal diff --git a/vtkm/internal/Invocation.h b/vtkm/internal/Invocation.h new file mode 100644 index 000000000..ac200755e --- /dev/null +++ b/vtkm/internal/Invocation.h @@ -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 vtk_m_internal_Invocation_h +#define vtk_m_internal_Invocation_h + +#include + +namespace vtkm { +namespace internal { + +/// \brief Container for types when dispatching worklets. +/// +/// When a dispatcher and associated class invoke a worklet, they need to keep +/// track of the types of all parameters and the associated features of the +/// worklet. \c Invocation is a class that manages all these types. +/// +template +struct Invocation +{ + /// \brief The types of the parameters + /// + /// \c ParameterInterface is (expected to be) a \c FunctionInterface class + /// that lists the types of the parameters for the invocation. + /// + typedef _ParameterInterface ParameterInterface; + + /// \brief The tags of the \c ControlSignature. + /// + /// \c ControlInterface is (expected to be) a \c FunctionInterface class that + /// represents the \c ControlSignature of a worklet (although dispatchers + /// might modify the control signature to provide auxiliary information). + /// + typedef _ControlInterface ControlInterface; + + /// \brief The tags of the \c ExecutionSignature. + /// + /// \c ExecutionInterface is (expected to be) a \c FunctionInterface class that + /// represents the \c ExecutionSignature of a worklet (although dispatchers + /// might modify the execution signature to provide auxiliary information). + /// + typedef _ExecutionInterface ExecutionInterface; + + /// \brief The index of the input domain. + /// + /// When a worklet is invoked, the pool of working threads is based of some + /// constituent element of the input (such as the points or cells). This + /// index points to the parameter that defines this input domain. + /// + static const vtkm::IdComponent InputDomainIndex = _InputDomainIndex; + + VTKM_CONT_EXPORT + Invocation(ParameterInterface parameters) : Parameters(parameters) { } + + /// Defines a new \c Invocation type that is the same as this type except + /// with the \c Parameters replaced. + /// + template + struct ChangeParametersType { + typedef Invocation type; + }; + + /// Returns a new \c Invocation that is the same as this one except that the + /// \c Parameters are replaced with those provided. + /// + template + VTKM_EXEC_CONT_EXPORT + typename ChangeParametersType::type + ChangeParameters(NewParameterInterface newParameters) const { + return typename ChangeParametersType::type( + newParameters); + } + + /// Defines a new \c Invocation type that is the same as this type except + /// with the \c ControlInterface replaced. + /// + template + struct ChangeControlInterfaceType { + typedef Invocation type; + }; + + /// Returns a new \c Invocation that is the same as this one except that the + /// \c ControlInterface type is changed to the type given. + /// + template + typename ChangeControlInterfaceType::type + ChangeControlInterface(NewControlInterface) const { + return typename ChangeControlInterfaceType::type( + this->Parameters); + } + + /// Defines a new \c Invocation type that is the same as this type except + /// with the \c ExecutionInterface replaced. + /// + template + struct ChangeExecutionInterfaceType { + typedef Invocation type; + }; + + /// Returns a new \c Invocation that is the same as this one except that the + /// \c ExecutionInterface type is changed to the type given. + /// + template + typename ChangeExecutionInterfaceType::type + ChangeExecutionInterface(NewExecutionInterface) const { + return typename ChangeExecutionInterfaceType::type( + this->Parameters); + } + + /// Defines a new \c Invocation type that is the same as this type except + /// with the \c InputDomainIndex replaced. + /// + template + struct ChangeInputDomainIndexType { + typedef Invocation type; + }; + + /// Returns a new \c Invocation that is the same as this one except that the + /// \c InputDomainIndex is changed to the static number given. + /// + template + VTKM_EXEC_CONT_EXPORT + typename ChangeInputDomainIndexType::type + ChangeInputDomainIndex() const { + return typename ChangeInputDomainIndexType::type( + this->Parameters); + } + + /// The state of an \c Invocation object holds the parameters of the + /// invocation. + /// + ParameterInterface Parameters; +}; + +/// Convenience function for creating an Invocation object. +/// +template +VTKM_CONT_EXPORT +vtkm::internal::Invocation +make_Invocation(const ParameterInterface ¶ms, + ControlInterface = ControlInterface(), + ExecutionInterface = ExecutionInterface()) +{ + return vtkm::internal::Invocation(params); +} + +} +} // namespace vtkm::internal + +#endif //vtk_m_internal_Invocation_h diff --git a/vtkm/internal/ListTagDetail.h b/vtkm/internal/ListTagDetail.h index 6238ee748..493ff559a 100644 --- a/vtkm/internal/ListTagDetail.h +++ b/vtkm/internal/ListTagDetail.h @@ -29,7 +29,7 @@ #include -#define VTKM_MAX_BASE_LIST 25 +#define VTKM_MAX_BASE_LIST 15 namespace vtkm { @@ -38,6 +38,11 @@ namespace detail { //----------------------------------------------------------------------------- +/// Base class that all ListTag classes inherit from. Helps identify lists +/// in macros like VTKM_IS_LIST_TAG. +/// +struct ListRoot { }; + template struct ListBase { }; @@ -709,891 +714,415 @@ void ListForEachImpl(const Functor &f, ListBase -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) -{ - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); -} -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) -{ - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); -} +//----------------------------------------------------------------------------- -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) -{ - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); -} +template +struct ListContainsImpl; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) +template +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); -} + static const bool value = false; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) +template +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) +template +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); -} + static const bool value = false; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) +template +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T2> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T3> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T3> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T4> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T4> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T5> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T5> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T6> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T6> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T7> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); - f(T24()); -} + static const bool value = true; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T7> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); - f(T24()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; -template -VTKM_CONT_EXPORT -void ListForEachImpl(Functor &f, ListBase) + typename T8> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); - f(T24()); - f(T25()); -} + static const bool value = true; +}; -template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template -VTKM_CONT_EXPORT -void ListForEachImpl(const Functor &f, ListBase) + typename T15> +struct ListContainsImpl, Type> { - f(T1()); - f(T2()); - f(T3()); - f(T4()); - f(T5()); - f(T6()); - f(T7()); - f(T8()); - f(T9()); - f(T10()); - f(T11()); - f(T12()); - f(T13()); - f(T14()); - f(T15()); - f(T16()); - f(T17()); - f(T18()); - f(T19()); - f(T20()); - f(T21()); - f(T22()); - f(T23()); - f(T24()); - f(T25()); -} + static const bool value = + ListContainsImpl, Type>::value; +}; } // namespace detail @@ -1670,37 +1165,27 @@ template -struct ListTagBase + typename T15 = vtkm::detail::ListParamNull> +struct ListTagBase : detail::ListRoot { - typedef detail::ListBase List; + typedef detail::ListBase List; }; template<> -struct ListTagBase<> +struct ListTagBase<> : detail::ListRoot { typedef detail::ListBase List; }; template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1708,7 +1193,7 @@ struct ListTagBase template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1717,7 +1202,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1727,7 +1212,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1738,7 +1223,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1750,7 +1235,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1763,7 +1248,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1777,7 +1262,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1792,7 +1277,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1808,7 +1293,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1825,7 +1310,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1843,7 +1328,7 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; @@ -1862,256 +1347,11 @@ template -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - -template -struct ListTagBase -{ - typedef detail::ListBase List; -}; - } // namespace vtkm diff --git a/vtkm/internal/ListTagDetail.h.in b/vtkm/internal/ListTagDetail.h.in index 5c84396c0..abfadd0c9 100644 --- a/vtkm/internal/ListTagDetail.h.in +++ b/vtkm/internal/ListTagDetail.h.in @@ -41,7 +41,7 @@ $# Ignore the following comment. It is meant for the generated file. #include -$py(max_base_list=25)\ +$py(max_base_list=15)\ #define VTKM_MAX_BASE_LIST $(max_base_list) $# Python commands used in template expansion. @@ -68,11 +68,11 @@ def param_list(num_params, name='T', start=1): result += ',%s%d' % (name, param) return result -def signature(num_params, name='T', return_type='void'): +def signature(num_params, name='T', return_type='void', start=1): result = '%s(' % return_type - if num_params > 0: - result += '%s1' % name - for param in xrange(2, num_params+1): + if num_params >= start: + result += '%s%d' % (name, start) + for param in xrange(start+1, num_params+1): result += ',%s%d' % (name, param) result += ')' return result @@ -86,6 +86,11 @@ namespace detail { //----------------------------------------------------------------------------- +/// Base class that all ListTag classes inherit from. Helps identify lists +/// in macros like VTKM_IS_LIST_TAG. +/// +struct ListRoot { }; + template struct ListBase { }; @@ -120,6 +125,47 @@ $endfor\ $endfor\ +//----------------------------------------------------------------------------- + +template +struct ListContainsImpl; + +template +struct ListContainsImpl, Type> +{ + static const bool value = false; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = false; +}; + +$for(num_params in xrange(2, max_base_list+1))\ +template +struct ListContainsImpl, Type> +{ + static const bool value = true; +}; + +template +struct ListContainsImpl, Type> +{ + static const bool value = + ListContainsImpl, Type>::value; +}; + +$endfor\ + } // namespace detail //----------------------------------------------------------------------------- @@ -127,14 +173,14 @@ $endfor\ /// A basic tag for a list of typenames. This struct can be subclassed /// and still behave like a list tag. template<$template_params(max_base_list, default=' = vtkm::detail::ListParamNull')> -struct ListTagBase +struct ListTagBase : detail::ListRoot { typedef detail::ListBase List; }; $for(num_params in xrange(0, (max_base_list+1)-1))\ template<$template_params(num_params)> -struct ListTagBase<$param_list(num_params)> +struct ListTagBase<$param_list(num_params)> : detail::ListRoot { typedef detail::ListBase List; }; diff --git a/vtkm/internal/testing/UnitTestFunctionInterface.cxx b/vtkm/internal/testing/UnitTestFunctionInterface.cxx index ced4e107f..1cd504800 100644 --- a/vtkm/internal/testing/UnitTestFunctionInterface.cxx +++ b/vtkm/internal/testing/UnitTestFunctionInterface.cxx @@ -248,6 +248,23 @@ struct ForEachFunctor void operator()(std::string &x) const { x.append("*2"); } }; +struct ZipFunctor +{ + void operator()(const vtkm::Pair &a1, + const vtkm::Pair &a2, + const vtkm::Pair &a3) const + { + std::cout << "In functor for zipped functions." << std::endl; + + VTKM_TEST_ASSERT(a1.first == Arg1, "Bad arg."); + VTKM_TEST_ASSERT(a1.second == Arg3, "Bad arg."); + VTKM_TEST_ASSERT(a2.first == Arg2, "Bad arg."); + VTKM_TEST_ASSERT(a2.second == Arg4, "Bad arg."); + VTKM_TEST_ASSERT(a3.first == Arg3, "Bad arg."); + VTKM_TEST_ASSERT(a3.second == Arg5, "Bad arg."); + } +}; + void TryFunctionInterface5( vtkm::internal::FunctionInterface funcInterface) { @@ -447,6 +464,16 @@ void TestForEach() VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 4*Arg5, "Arg 5 incorrect."); } +void TestZip() +{ + std::cout << "Testing zipping function interfaces." << std::endl; + + vtkm::internal::make_FunctionInterfaceZip( + vtkm::internal::make_FunctionInterface(Arg1, Arg2, Arg3), + vtkm::internal::make_FunctionInterface(Arg3, Arg4, Arg5)). + InvokeCont(ZipFunctor()); +} + #if 0 void TestInvokeTime() { @@ -527,6 +554,7 @@ void TestFunctionInterface() TestStaticTransform(); TestDynamicTransform(); TestForEach(); + TestZip(); // Disable this last test. It is unreliable and the most critical invoke // (for the instance of a worklet) does not directly use the Invoke // method. diff --git a/vtkm/testing/CMakeLists.txt b/vtkm/testing/CMakeLists.txt index c83cade41..542d16356 100644 --- a/vtkm/testing/CMakeLists.txt +++ b/vtkm/testing/CMakeLists.txt @@ -29,6 +29,7 @@ VTKM_declare_headers(${headers}) set(unit_tests UnitTestExtent.cxx UnitTestListTag.cxx + UnitTestPair.cxx UnitTestTesting.cxx UnitTestTypeListTag.cxx UnitTestTypes.cxx diff --git a/vtkm/testing/Testing.h b/vtkm/testing/Testing.h index 562dfbe77..ddc8bacd3 100644 --- a/vtkm/testing/Testing.h +++ b/vtkm/testing/Testing.h @@ -326,7 +326,7 @@ template VTKM_EXEC_CONT_EXPORT T TestValue(vtkm::Id index, T, vtkm::TypeTraitsRealTag) { - return T(0.01*index + 0.001); + return T(0.01*index + 1.001); } /// Many tests involve getting and setting values in some index-based structure diff --git a/vtkm/testing/UnitTestListTag.cxx b/vtkm/testing/UnitTestListTag.cxx index 0b26c393f..dd73d8696 100644 --- a/vtkm/testing/UnitTestListTag.cxx +++ b/vtkm/testing/UnitTestListTag.cxx @@ -24,6 +24,7 @@ #include +#include #include namespace { @@ -94,9 +95,21 @@ void CheckSame(const vtkm::Vec &expected, } } +template +void CheckContains(TestClass, ListTag, const std::vector contents) +{ + bool listContains = vtkm::ListContains >::value; + bool shouldContain = + std::find(contents.begin(), contents.end(), N) != contents.end(); + VTKM_TEST_ASSERT(listContains == shouldContain, + "ListContains check failed."); +} + template void TryList(const vtkm::Vec &expected, ListTag) { + VTKM_IS_LIST_TAG(ListTag); + std::cout << " Try mutable for each" << std::endl; MutableFunctor functor; vtkm::ListForEach(functor, ListTag()); @@ -105,10 +118,30 @@ void TryList(const vtkm::Vec &expected, ListTag) std::cout << " Try constant for each" << std::endl; vtkm::ListForEach(ConstantFunctor(), ListTag()); CheckSame(expected, g_FoundType); + + std::cout << " Try checking contents" << std::endl; + CheckContains(TestClass<11>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<21>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<22>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<31>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<32>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<33>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<41>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<42>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<43>(), ListTag(), functor.FoundTypes); + CheckContains(TestClass<44>(), ListTag(), functor.FoundTypes); } void TestLists() { + std::cout << "Valid List Tag Checks" << std::endl; + VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck::Valid, + "Failed list tag check"); + VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck::Valid, + "Failed list tag check"); + VTKM_TEST_ASSERT(!vtkm::internal::ListTagCheck >::Valid, + "Failed list tag check"); + std::cout << "ListTagEmpty" << std::endl; TryList(vtkm::Vec(), vtkm::ListTagEmpty()); diff --git a/vtkm/testing/UnitTestPair.cxx b/vtkm/testing/UnitTestPair.cxx new file mode 100644 index 000000000..3e07ac57d --- /dev/null +++ b/vtkm/testing/UnitTestPair.cxx @@ -0,0 +1,171 @@ +//============================================================================ +// 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 +#include +#include + +#include + +namespace { + +//general pair test +template +void PairTest( ) +{ + //test that all the constructors work properly + { + vtkm::Pair no_params_pair; + no_params_pair.first = TestValue(12, T()); + no_params_pair.second = TestValue(34, U()); + vtkm::Pair copy_constructor_pair(no_params_pair); + vtkm::Pair assignment_pair = no_params_pair; + + VTKM_TEST_ASSERT( (no_params_pair == copy_constructor_pair), + "copy constructor doesn't match default constructor"); + VTKM_TEST_ASSERT( !(no_params_pair != copy_constructor_pair), + "operator != is working properly"); + + + VTKM_TEST_ASSERT( (no_params_pair == assignment_pair), + "assignment constructor doesn't match default constructor"); + VTKM_TEST_ASSERT( !(no_params_pair != assignment_pair), + "operator != is working properly"); + } + + //now lets give each item in the pair some values and do some in depth + //comparisons + T a = TestValue(56, T()); + U b = TestValue(78, U()); + + //test the constructors now with real values + { + vtkm::Pair pair_ab(a,b); + vtkm::Pair copy_constructor_pair(pair_ab); + vtkm::Pair assignment_pair = pair_ab; + vtkm::Pair make_p = vtkm::make_Pair(a,b); + + VTKM_TEST_ASSERT( !(pair_ab != pair_ab), + "operator != isn't working properly for vtkm::Pair" ); + VTKM_TEST_ASSERT( (pair_ab == pair_ab), + "operator == isn't working properly for vtkm::Pair" ); + + VTKM_TEST_ASSERT( (pair_ab == copy_constructor_pair), + "copy constructor doesn't match pair constructor"); + VTKM_TEST_ASSERT( (pair_ab == assignment_pair), + "assignment constructor doesn't match pair constructor"); + + VTKM_TEST_ASSERT(copy_constructor_pair.first == a, + "first field not set right"); + VTKM_TEST_ASSERT(assignment_pair.second == b, + "second field not set right"); + + VTKM_TEST_ASSERT( (pair_ab == make_p), + "make_pair function doesn't match pair constructor"); + } + + + //test the ordering operators <, >, <=, >= + { + //in all cases pair_ab2 is > pair_ab. these verify that if the second + //argument of the pair is different we respond properly + U b2(b); + vtkm::VecTraits::SetComponent(b2,0, + vtkm::VecTraits::GetComponent(b2,0)+1); + + vtkm::Pair pair_ab2(a,b2); + vtkm::Pair pair_ab(a,b); + + VTKM_TEST_ASSERT( (pair_ab2 >= pair_ab), "operator >= failed" ); + VTKM_TEST_ASSERT( (pair_ab2 >= pair_ab2), "operator >= failed" ); + + VTKM_TEST_ASSERT( (pair_ab2 > pair_ab), "operator > failed" ); + VTKM_TEST_ASSERT( !(pair_ab2 > pair_ab2), "operator > failed" ); + + VTKM_TEST_ASSERT( !(pair_ab2 < pair_ab), "operator < failed" ); + VTKM_TEST_ASSERT( !(pair_ab2 < pair_ab2), "operator < failed" ); + + VTKM_TEST_ASSERT( !(pair_ab2 <= pair_ab), "operator <= failed" ); + VTKM_TEST_ASSERT( (pair_ab2 <= pair_ab2), "operator <= failed" ); + + VTKM_TEST_ASSERT( !(pair_ab2 == pair_ab), "operator == failed" ); + VTKM_TEST_ASSERT( (pair_ab2 != pair_ab), "operator != failed" ); + + T a2(a); + vtkm::VecTraits::SetComponent(a2,0, + vtkm::VecTraits::GetComponent(a2,0)+1); + vtkm::Pair pair_a2b(a2,b); + //this way can verify that if the first argument of the pair is different + //we respond properly + VTKM_TEST_ASSERT( (pair_a2b >= pair_ab), "operator >= failed" ); + VTKM_TEST_ASSERT( (pair_a2b >= pair_a2b), "operator >= failed" ); + + VTKM_TEST_ASSERT( (pair_a2b > pair_ab), "operator > failed" ); + VTKM_TEST_ASSERT( !(pair_a2b > pair_a2b), "operator > failed" ); + + VTKM_TEST_ASSERT( !(pair_a2b < pair_ab), "operator < failed" ); + VTKM_TEST_ASSERT( !(pair_a2b < pair_a2b), "operator < failed" ); + + VTKM_TEST_ASSERT( !(pair_a2b <= pair_ab), "operator <= failed" ); + VTKM_TEST_ASSERT( (pair_a2b <= pair_a2b), "operator <= failed" ); + + VTKM_TEST_ASSERT( !(pair_a2b == pair_ab), "operator == failed" ); + VTKM_TEST_ASSERT( (pair_a2b != pair_ab), "operator != failed" ); + } + +} + +template< typename FirstType > +struct DecideSecondType +{ + template void operator()(const SecondType&) const + { + PairTest(); + } +}; + +struct DecideFirstType +{ + template void operator()(const T&) const + { + //T is our first type for vtkm::Pair, now to figure out the second type + vtkm::testing::Testing::TryTypes(DecideSecondType(), + vtkm::TypeListTagField()); + + } +}; + +void TestPair() +{ + //we want to test each combination of standard dax types in a + //vtkm::Pair, so to do that we dispatch twice on TryTypes. We could + //dispatch on all types, but that gets excessively large and takes a + //long time to compile (although it runs fast). Instead, just select + //a subset of non-trivial combinations. + vtkm::testing::Testing::TryTypes(DecideFirstType(), + vtkm::TypeListTagCommon()); +} + +} // anonymous namespace + +int UnitTestPair(int, char *[]) +{ + return vtkm::testing::Testing::Run(TestPair); +} diff --git a/vtkm/worklet/CMakeLists.txt b/vtkm/worklet/CMakeLists.txt new file mode 100644 index 000000000..90c5f6fd5 --- /dev/null +++ b/vtkm/worklet/CMakeLists.txt @@ -0,0 +1,33 @@ +##============================================================================ +## 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. +##============================================================================ + +set(headers + DispatcherMapField.h + WorkletMapField.h + ) + +#----------------------------------------------------------------------------- +add_subdirectory(internal) + +vtkm_declare_headers(${headers}) + + +#----------------------------------------------------------------------------- +add_subdirectory(testing) diff --git a/vtkm/worklet/DispatcherMapField.h b/vtkm/worklet/DispatcherMapField.h new file mode 100644 index 000000000..e5b4e5040 --- /dev/null +++ b/vtkm/worklet/DispatcherMapField.h @@ -0,0 +1,93 @@ +//============================================================================ +// 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 vtk_m_worklet_Dispatcher_MapField_h +#define vtk_m_worklet_Dispatcher_MapField_h + +#include +#include +#include + +namespace vtkm { +namespace worklet { + +/// \brief Dispatcher for worklets that inherit from \c WorkletMapField. +/// +template +class DispatcherMapField : + public vtkm::worklet::internal::DispatcherBase< + DispatcherMapField, + WorkletType, + vtkm::worklet::WorkletMapField, + Device> +{ + typedef vtkm::worklet::internal::DispatcherBase< + DispatcherMapField, + WorkletType, + vtkm::worklet::WorkletMapField, + Device> Superclass; + +public: + VTKM_CONT_EXPORT + DispatcherMapField(const WorkletType &worklet = WorkletType()) + : Superclass(worklet) { } + + template + VTKM_CONT_EXPORT + void DoInvoke(const Invocation &invocation) const + { + // The parameter for the input domain is stored in the Invocation. (It is + // also in the worklet, but it is safer to get it from the Invocation + // in case some other dispatch operation had to modify it.) + static const vtkm::IdComponent InputDomainIndex = + Invocation::InputDomainIndex; + + // ParameterInterface (from Invocation) is a FunctionInterface type + // containing types for all objects passed to the Invoke method (with + // some dynamic casting performed so objects like DynamicArrayHandle get + // cast to ArrayHandle). + typedef typename Invocation::ParameterInterface ParameterInterface; + + // This is the type for the input domain (derived from the last two things + // we got from the Invocation). + typedef typename ParameterInterface:: + template ParameterType::type InputDomainType; + + // We can pull the input domain parameter (the data specifying the input + // domain) from the invocation object. + InputDomainType inputDomain = + invocation.Parameters.template GetParameter(); + + // For a DispatcherMapField, the inputDomain must be an ArrayHandle (or + // a DynamicArrayHandle that gets cast to one). The size of the domain + // (number of threads/worklet instances) is equal to the size of the + // array. + vtkm::Id numInstances = inputDomain.GetNumberOfValues(); + + // A MapField is a pretty straightforward dispatch. Once we know the number + // of invocations, the superclass can take care of the rest. + this->BasicInvoke(invocation, numInstances); + } +}; + +} +} // namespace vtkm::worklet + +#endif //vtk_m_worklet_Dispatcher_MapField_h diff --git a/vtkm/worklet/WorkletMapField.h b/vtkm/worklet/WorkletMapField.h new file mode 100644 index 000000000..b05344b8b --- /dev/null +++ b/vtkm/worklet/WorkletMapField.h @@ -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 vtk_m_worklet_WorkletMapField_h +#define vtk_m_worklet_WorkletMapField_h + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +namespace vtkm { +namespace worklet { + +/// Base class for worklets that do a simple mapping of field arrays. All +/// inputs and outputs are on the same domain. That is, all the arrays are the +/// same size. +/// +class WorkletMapField : public vtkm::worklet::internal::WorkletBase +{ +public: + /// \brief A control signature tag for input fields. + /// + /// This tag takes a template argument that is a type list tag that limits + /// the possible value types in the array. + /// + template + struct FieldIn : vtkm::cont::arg::ControlSignatureTagBase { + typedef vtkm::cont::arg::TypeCheckTagArray TypeCheckTag; + typedef vtkm::cont::arg::TransportTagArrayIn TransportTag; + typedef vtkm::exec::arg::FetchTagArrayDirectIn FetchTag; + }; + + /// \brief A control signature tag for output fields. + /// + /// This tag takes a template argument that is a type list tag that limits + /// the possible value types in the array. + /// + template + struct FieldOut : vtkm::cont::arg::ControlSignatureTagBase { + typedef vtkm::cont::arg::TypeCheckTagArray TypeCheckTag; + typedef vtkm::cont::arg::TransportTagArrayOut TransportTag; + typedef vtkm::exec::arg::FetchTagArrayDirectOut FetchTag; + }; +}; + +} +} // namespace vtkm::worklet + +#endif //vtk_m_worklet_WorkletMapField_h diff --git a/vtkm/worklet/internal/CMakeLists.txt b/vtkm/worklet/internal/CMakeLists.txt new file mode 100644 index 000000000..076bafa55 --- /dev/null +++ b/vtkm/worklet/internal/CMakeLists.txt @@ -0,0 +1,30 @@ +##============================================================================ +## 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. +##============================================================================ + +set(headers + DispatcherBase.h + WorkletBase.h + ) + +vtkm_declare_headers(${headers}) + +vtkm_pyexpander_generated_file(DispatcherBaseDetailInvoke.h) + +add_subdirectory(testing) diff --git a/vtkm/worklet/internal/DispatcherBase.h b/vtkm/worklet/internal/DispatcherBase.h new file mode 100644 index 000000000..db2716ac3 --- /dev/null +++ b/vtkm/worklet/internal/DispatcherBase.h @@ -0,0 +1,371 @@ +//============================================================================ +// 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 vtk_m_worklet_internal_DispatcherBase_h +#define vtk_m_worklet_internal_DispatcherBase_h + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +namespace vtkm { +namespace worklet { +namespace internal { + +namespace detail { + +// Checks that an argument in a ControlSignature is a valid control signature +// tag. Causes a compile error otherwise. +struct DispatcherBaseControlSignatureTagCheck +{ + template + struct ReturnType { + // If you get a compile error here, it means there is something that is + // not a valid control signature tag in a worklet's ControlSignature. + VTKM_IS_CONTROL_SIGNATURE_TAG(ControlSignatureTag); + typedef ControlSignatureTag type; + }; +}; + +// Checks that an argument in a ExecutionSignature is a valid execution +// signature tag. Causes a compile error otherwise. +struct DispatcherBaseExecutionSignatureTagCheck +{ + template + struct ReturnType { + // If you get a compile error here, it means there is something that is not + // a valid execution signature tag in a worklet's ExecutionSignature. + VTKM_IS_EXECUTION_SIGNATURE_TAG(ExecutionSignatureTag); + typedef ExecutionSignatureTag type; + }; +}; + +// Used in the dynamic cast to check to make sure that the type passed into +// the Invoke method matches the type accepted by the ControlSignature. +template +struct DispatcherBaseTypeCheckFunctor +{ + const ContinueFunctor &Continue; + vtkm::IdComponent ParameterIndex; + + VTKM_CONT_EXPORT + DispatcherBaseTypeCheckFunctor(const ContinueFunctor &continueFunc, + vtkm::IdComponent parameterIndex) + : Continue(continueFunc), ParameterIndex(parameterIndex) { } + + template + VTKM_CONT_EXPORT + typename boost::enable_if_c::value>::type + operator()(const T &x) const + { + this->Continue(x); + } + + // This code is actually taking an error found at compile-time and not + // reporting it until run-time. This seems strange at first, but this + // behavior is actually important. With dynamic arrays and similar dynamic + // classes, there may be types that are technically possible (such as using a + // vector where a scalar is expected) but in reality never happen. Thus, for + // these unsported combinations we just silently halt the compiler from + // attempting to create code for these errant conditions and throw a run-time + // error if one every tries to create one. + template + VTKM_CONT_EXPORT + typename boost::disable_if_c::value>::type + operator()(const T &) const + { + std::stringstream message; + message << "Encountered bad type for parameter " + << this->ParameterIndex + << " when calling Invoke on a dispatcher."; + throw vtkm::cont::ErrorControlBadType(message.str()); + } +}; + +// Uses vtkm::cont::internal::DynamicTransform and the DynamicTransformCont +// method of FunctionInterface to convert all DynamicArrayHandles and any +// other arguments declaring themselves as dynamic to static versions. +struct DispatcherBaseDynamicTransform +{ + vtkm::cont::internal::DynamicTransform BasicDynamicTransform; + vtkm::IdComponent *ParameterCounter; + + VTKM_CONT_EXPORT + DispatcherBaseDynamicTransform(vtkm::IdComponent *parameterCounter) + : ParameterCounter(parameterCounter) + { + *this->ParameterCounter = 0; + } + + template + VTKM_CONT_EXPORT + void operator()(const vtkm::Pair &input, + const ContinueFunctor &continueFunc) const + { + (*this->ParameterCounter)++; + + typedef DispatcherBaseTypeCheckFunctor< + ContinueFunctor, typename ControlSignatureTag::TypeCheckTag> + TypeCheckFunctor; + this->BasicDynamicTransform(input.second, + TypeCheckFunctor(continueFunc, + *this->ParameterCounter)); + } +}; + +// A functor called at the end of the dynamic transform to call the next +// step in the dynamic transform. +template +struct DispatcherBaseDynamicTransformHelper +{ + const DispatcherBaseType *Dispatcher; + + VTKM_CONT_EXPORT + DispatcherBaseDynamicTransformHelper(const DispatcherBaseType *dispatcher) + : Dispatcher(dispatcher) { } + + template + VTKM_CONT_EXPORT + void operator()(const FunctionInterface ¶meters) const { + this->Dispatcher->DynamicTransformInvoke(parameters); + } +}; + +// A functor used in a StaticCast of a FunctionInterface to transport arguments +// from the control environment to the execution environment. +template +struct DispatcherBaseTransportFunctor +{ + vtkm::Id NumInstances; + + DispatcherBaseTransportFunctor(vtkm::Id numInstances) + : NumInstances(numInstances) { } + + template + struct InvokeTypes { + typedef typename T::FirstType::TransportTag TransportTag; + typedef typename T::SecondType ControlParameter; + typedef vtkm::cont::arg::Transport + TransportType; + }; + + template + struct ReturnType { + typedef typename InvokeTypes::TransportType::ExecObjectType type; + }; + + template + VTKM_CONT_EXPORT + typename ReturnType::type + operator()(const T &invokeData) const { + typename InvokeTypes::TransportType transport; + return transport(invokeData.second, this->NumInstances); + } +}; + +} // namespace detail + +/// Base class for all dispatcher classes. Every worklet type should have its +/// own dispatcher. +/// +template +class DispatcherBase +{ +private: + typedef DispatcherBase MyType; + + friend struct detail::DispatcherBaseDynamicTransformHelper; + +protected: + typedef vtkm::internal::FunctionInterface< + typename WorkletType::ControlSignature> ControlInterface; + typedef vtkm::internal::FunctionInterface< + typename WorkletType::ExecutionSignature> ExecutionInterface; + + static const vtkm::IdComponent NUM_INVOKE_PARAMS = ControlInterface::ARITY; + +private: + // We don't really need these types, but declaring them checks the arguments + // of the control and execution signatures. + typedef typename ControlInterface:: + template StaticTransformType< + detail::DispatcherBaseControlSignatureTagCheck>::type + ControlSignatureCheck; + typedef typename ExecutionInterface:: + template StaticTransformType< + detail::DispatcherBaseExecutionSignatureTagCheck>::type + ExecutionSignatureCheck; + + template + VTKM_CONT_EXPORT + void StartInvoke( + const vtkm::internal::FunctionInterface ¶meters) const + { + typedef vtkm::internal::FunctionInterface ParameterInterface; + BOOST_STATIC_ASSERT_MSG(ParameterInterface::ARITY == NUM_INVOKE_PARAMS, + "Dispatcher Invoke called with wrong number of arguments."); + + BOOST_MPL_ASSERT(( boost::is_base_of )); + + // As we do the dynamic transform, we are also going to check the static + // type against the TypeCheckTag in the ControlSignature tags. To do this, + // the check needs access to both the parameter (in the parameters + // argument) and the ControlSignature tags (in the ControlInterface type). + // To make this possible, we use the zip mechanism of FunctionInterface to + // combine these two separate function interfaces into a single + // FunctionInterface with each parameter being a Pair containing both + // the ControlSignature tag and the control object itself. + typedef typename vtkm::internal::FunctionInterfaceZipType< + ControlInterface, ParameterInterface>::type ZippedInterface; + ZippedInterface zippedInterface = + vtkm::internal::make_FunctionInterfaceZip(ControlInterface(), + parameters); + + vtkm::IdComponent parameterIndexCounter; + + zippedInterface.DynamicTransformCont( + detail::DispatcherBaseDynamicTransform(¶meterIndexCounter), + detail::DispatcherBaseDynamicTransformHelper(this)); + } + + template + VTKM_CONT_EXPORT + void DynamicTransformInvoke( + const vtkm::internal::FunctionInterface ¶meters) const + { + // TODO: Check parameters + static const vtkm::IdComponent INPUT_DOMAIN_INDEX = + WorkletType::InputDomain::INDEX; + reinterpret_cast(this)->DoInvoke( + vtkm::internal::make_Invocation( + parameters, ControlInterface(), ExecutionInterface())); + } + +public: + // Implementation of the Invoke method is in this generated file. +#include + +protected: + VTKM_CONT_EXPORT + DispatcherBase(const WorkletType &worklet) : Worklet(worklet) { } + + template + VTKM_CONT_EXPORT + void BasicInvoke(const Invocation &invocation, vtkm::Id numInstances) const + { + this->InvokeTransportParameters(invocation, numInstances); + } + + WorkletType Worklet; + +private: + // These are not implemented. Dispatchers cannot be copied. + DispatcherBase(const MyType &); + void operator=(const MyType &); + + template + VTKM_CONT_EXPORT + void InvokeTransportParameters(const Invocation &invocation, + vtkm::Id numInstances) const + { + // The first step in invoking a worklet is transport the arguments to the + // execution environment. The invocation object passed to this function + // contains the parameters passed to Invoke in the control environment. We + // will use the template magic in the FunctionInterface class to invoke the + // appropriate Transport class on each parameter to get a list of execution + // objects (corresponding to the arguments of the Invoke in the control + // environment) in a FunctionInterface. + + // The Transport relies on both the ControlSignature tag and the control + // object itself. To make it easier to work with each parameter, use the + // zip mechanism of FunctionInterface to combine the separate function + // interfaces of the ControlSignature and the parameters into one. This + // will make a FunctionInterface with each parameter being a Pair + // containing both the ControlSignature tag and the control object itself. + typedef typename vtkm::internal::FunctionInterfaceZipType< + typename Invocation::ControlInterface, + typename Invocation::ParameterInterface>::type ZippedInterface; + ZippedInterface zippedInterface = + vtkm::internal::make_FunctionInterfaceZip( + typename Invocation::ControlInterface(), invocation.Parameters); + + // Use the StaticTransform mechanism to run the + // DispatcherBaseTransportFunctor on each parameter of the zipped + // interface. This functor will in turn run the appropriate Transform on + // the parameter and return the associated execution object. The end result + // of the transform is a FunctionInterface containing execution objects + // corresponding to each Invoke argument. + typedef detail::DispatcherBaseTransportFunctor TransportFunctor; + typedef typename ZippedInterface::template StaticTransformType< + TransportFunctor>::type ExecObjectParameters; + ExecObjectParameters execObjectParameters = + zippedInterface.StaticTransformCont(TransportFunctor(numInstances)); + + // Replace the parameters in the invocation with the execution object and + // pass to next step of Invoke. + this->InvokeSchedule(invocation.ChangeParameters(execObjectParameters), + numInstances); + } + + template + VTKM_CONT_EXPORT + void InvokeSchedule(const Invocation &invocation, vtkm::Id numInstances) const + { + // The WorkletInvokeFunctor class handles the magic of fetching values + // for each instance and calling the worklet's function. So just create + // a WorkletInvokeFunctor and schedule it with the device adapter. + typedef vtkm::exec::internal::WorkletInvokeFunctor + WorkletInvokeFunctorType; + WorkletInvokeFunctorType workletFunctor = + WorkletInvokeFunctorType(this->Worklet, invocation); + + typedef vtkm::cont::DeviceAdapterAlgorithm Algorithm; + Algorithm::Schedule(workletFunctor, numInstances); + } +}; + +} +} +} // namespace vtkm::worklet::internal + +#endif //vtk_m_worklet_internal_DispatcherBase_h diff --git a/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h b/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h new file mode 100644 index 000000000..422ed3fd5 --- /dev/null +++ b/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h @@ -0,0 +1,143 @@ +//============================================================================ +// 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. +//============================================================================ +// **** DO NOT EDIT THIS FILE!!! **** +// This file is automatically generated by FunctionInterfaceDetailPre.h.in + +#if !defined(vtk_m_worklet_internal_DispatcherBase_h) +#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h +#endif + +// Note that this file is included from the middle of the DispatcherBase.h +// class to provide the implementation of the Invoke method, which requires +// variable length template args. If we choose to support C++11 variable +// template arguments, then this could all be replaced efficiently with a +// single method with a variadic template function that calls +// make_FunctionInterface. + + + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4,a5)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4,a5,a6)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4,a5,a6,a7)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4,a5,a6,a7,a8)); +} + +template +VTKM_CONT_EXPORT +void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface(a1,a2,a3,a4,a5,a6,a7,a8,a9)); +} + diff --git a/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h.in b/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h.in new file mode 100644 index 000000000..89972d436 --- /dev/null +++ b/vtkm/worklet/internal/DispatcherBaseDetailInvoke.h.in @@ -0,0 +1,86 @@ +//============================================================================ +// 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 file uses the pyexpander macro processing utility to build the +$# FunctionInterface facilities that use a variable number of arguments. +$# Information, documentation, and downloads for pyexpander can be found at: +$# +$# http://pyexpander.sourceforge.net/ +$# +$# To build the source code, execute the following (after installing +$# pyexpander, of course): +$# +$# expander.py DispatcherBaseDetailInvoke.h.in > DispatcherBaseDetailInvoke.h +$# +$# Ignore the following comment. It is meant for the generated file. +// **** DO NOT EDIT THIS FILE!!! **** +// This file is automatically generated by FunctionInterfaceDetailPre.h.in + +#if !defined(vtk_m_worklet_internal_DispatcherBase_h) +#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h +#endif + +// Note that this file is included from the middle of the DispatcherBase.h +// class to provide the implementation of the Invoke method, which requires +// variable length template args. If we choose to support C++11 variable +// template arguments, then this could all be replaced efficiently with a +// single method with a variadic template function that calls +// make_FunctionInterface. + +$py(max_parameters=9)\ + +$# Python commands used in template expansion. +$py( +def template_params(num_params, name='T', start=1, default=''): + if num_params < start: + return '' + result = 'typename %s%d%s' % (name, start, default) + for param in xrange(start+1, num_params+1): + result += ',\n typename %s%d%s' % (name, param, default) + return result + +def function_params(num_params, typename='T', argname='a', start=1): + if num_params < start: + return '' + result = '%s%d %s%d' % (typename, start, argname, start) + for param in xrange(start+1, num_params+1): + result += ', %s%d %s%d' % (typename, param, argname, param) + return result + +def arg_list(num_params, argname='a', start=1): + if num_params < start: + return '' + result = '%s%d' % (argname, start) + for param in xrange(start+1, num_params+1): + result += ',%s%d' % (argname, param) + return result +)\ +$# +$extend(template_params, function_params, arg_list)\ + +$for(num_params in xrange(1, max_parameters+1))\ +template<$template_params(num_params)> +VTKM_CONT_EXPORT +void Invoke($function_params(num_params)) const +{ + this->StartInvoke( + vtkm::internal::make_FunctionInterface($arg_list(num_params))); +} + +$endfor\ diff --git a/vtkm/worklet/internal/WorkletBase.h b/vtkm/worklet/internal/WorkletBase.h new file mode 100644 index 000000000..02170da1a --- /dev/null +++ b/vtkm/worklet/internal/WorkletBase.h @@ -0,0 +1,161 @@ +//============================================================================ +// 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 vtk_m_worklet_internal_WorkletBase_h +#define vtk_m_worklet_internal_WorkletBase_h + +#include + +#include +#include +#include +#include + +#include +#include + +namespace vtkm { +namespace worklet { +namespace internal { + +/// Base class for all worklet classes. Worklet classes are subclasses and a +/// operator() const is added to implement an algorithm in VTK-m. Different +/// worklets have different calling semantics. +/// +class WorkletBase : public vtkm::exec::FunctorBase +{ +public: + template + struct Arg : vtkm::exec::arg::BasicArg { }; + + /// Basic execution argument tags + struct _1 : Arg<1> { }; + struct _2 : Arg<2> { }; + struct _3 : Arg<3> { }; + struct _4 : Arg<4> { }; + struct _5 : Arg<5> { }; + struct _6 : Arg<6> { }; + struct _7 : Arg<7> { }; + struct _8 : Arg<8> { }; + struct _9 : Arg<9> { }; + + /// \c ExecutionSignature tag for getting the work index. + typedef vtkm::exec::arg::WorkIndex WorkIndex; + + /// \c ControlSignature tag for execution object inputs. + struct ExecObject { + typedef vtkm::cont::arg::TypeCheckTagExecObject TypeCheckTag; + typedef vtkm::cont::arg::TransportTagExecObject TransportTag; + typedef vtkm::exec::arg::FetchTagExecObject FetchTag; + }; + + /// Default input domain is the first argument. Worklet subclasses can + /// override this by redefining this type. + typedef _1 InputDomain; + + /// \brief A type list containing the type vtkm::Id. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagId IdType; + + /// \brief A type list containing the type vtkm::Id2. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagId2 Id2Type; + + /// \brief A type list containing the type vtkm::Id3. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagId3 Id3Type; + + /// \brief A list of types commonly used for indexing. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagIndex Index; + + /// \brief A list of types commonly used for scalar fields. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagFieldScalar Scalar; + + /// \brief A list of all basic types used for scalar fields. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagScalarAll ScalarAll; + + /// \brief A list of types commonly used for vector fields of 2 components. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagFieldVec2 Vec2; + + /// \brief A list of types commonly used for vector fields of 3 components. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagFieldVec3 Vec3; + + /// \brief A list of types commonly used for vector fields of 4 components. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagFieldVec4 Vec4; + + /// \brief A list of all basic types used for vector fields. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagVecAll VecAll; + + /// \brief A list of types (scalar and vector) commonly used in fields. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagField FieldCommon; + + /// \brief A list of vector types commonly used in fields. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagVecCommon VecCommon; + + /// \brief A list of generally common types. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagCommon CommonTypes; + + /// \brief A list of all basic types. + /// + /// This is a convenience type to use as template arguments to \c + /// ControlSignature tags to specify the types of worklet arguments. + typedef vtkm::TypeListTagAll AllTypes; +}; + +} +} +} // namespace vtkm::worklet::internal + +#endif //vtk_m_worklet_internal_WorkletBase_h diff --git a/vtkm/worklet/internal/testing/CMakeLists.txt b/vtkm/worklet/internal/testing/CMakeLists.txt new file mode 100644 index 000000000..72fd6c0bb --- /dev/null +++ b/vtkm/worklet/internal/testing/CMakeLists.txt @@ -0,0 +1,25 @@ +##============================================================================ +## 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. +##============================================================================ + +set(unit_tests + UnitTestDispatcherBase.cxx + ) + +vtkm_unit_tests(SOURCES ${unit_tests}) diff --git a/vtkm/worklet/internal/testing/UnitTestDispatcherBase.cxx b/vtkm/worklet/internal/testing/UnitTestDispatcherBase.cxx new file mode 100644 index 000000000..924878ccf --- /dev/null +++ b/vtkm/worklet/internal/testing/UnitTestDispatcherBase.cxx @@ -0,0 +1,310 @@ +//============================================================================ +// 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 + +#include + +#include + +#include + +#include + +namespace { + +typedef vtkm::cont::DeviceAdapterTagSerial Device; + +static const vtkm::Id ARRAY_SIZE = 10; + +struct TestExecObject +{ + VTKM_EXEC_CONT_EXPORT + TestExecObject() : Array(NULL) { } + + VTKM_EXEC_CONT_EXPORT + TestExecObject(vtkm::Id *array) : Array(array) { } + + vtkm::Id *Array; +}; + +struct TestTypeCheckTag { }; +struct TestTransportTag { }; +struct TestFetchTagInput { }; +struct TestFetchTagOutput { }; + +} // anonymous namespace + +namespace vtkm { +namespace cont { +namespace arg { + +template<> +struct TypeCheck +{ + static const bool value = true; +}; + +template<> +struct Transport +{ + typedef TestExecObject ExecObjectType; + + VTKM_CONT_EXPORT + ExecObjectType operator()(vtkm::Id *contData, vtkm::Id size) const + { + VTKM_TEST_ASSERT(size == ARRAY_SIZE, + "Got unexpected size in test transport."); + return ExecObjectType(contData); + } +}; + +} +} +} // namespace vtkm::cont::arg + +namespace vtkm { +namespace exec { +namespace arg { + +template +struct Fetch +{ + typedef vtkm::Id ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id index, const Invocation &invocation) const { + return invocation.Parameters. + template GetParameter().Array[index]; + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id, const Invocation &, ValueType) const { + // No-op + } +}; + +template +struct Fetch +{ + typedef vtkm::Id ValueType; + + VTKM_EXEC_EXPORT + ValueType Load(vtkm::Id, const Invocation &) const { + // No-op + return ValueType(); + } + + VTKM_EXEC_EXPORT + void Store(vtkm::Id index, + const Invocation &invocation, + ValueType value) const { + invocation.Parameters.template GetParameter().Array[index] = + value; + } +}; + +} +} +} // vtkm::exec::arg + +namespace { + +class TestWorkletBase : public vtkm::worklet::internal::WorkletBase +{ +public: + struct TestIn : vtkm::cont::arg::ControlSignatureTagBase { + typedef TestTypeCheckTag TypeCheckTag; + typedef TestTransportTag TransportTag; + typedef TestFetchTagInput FetchTag; + }; + struct TestOut : vtkm::cont::arg::ControlSignatureTagBase { + typedef TestTypeCheckTag TypeCheckTag; + typedef TestTransportTag TransportTag; + typedef TestFetchTagOutput FetchTag; + }; +}; + +class TestWorklet : public TestWorkletBase +{ +public: + typedef void ControlSignature(TestIn, TestOut); + typedef _2 ExecutionSignature(_1, WorkIndex); + + VTKM_EXEC_EXPORT + vtkm::Id operator()(vtkm::Id value, vtkm::Id index) const + { + VTKM_TEST_ASSERT(value == TestValue(index, vtkm::Id()), + "Got bad value in worklet."); + return TestValue(index, vtkm::Id()) + 1000; + } +}; + +#define ERROR_MESSAGE "Expected worklet error." + +class TestErrorWorklet : public TestWorkletBase +{ +public: + typedef void ControlSignature(TestIn, TestOut); + typedef void ExecutionSignature(_1, _2); + + VTKM_EXEC_EXPORT + void operator()(vtkm::Id, vtkm::Id) const + { + this->RaiseError(ERROR_MESSAGE); + } +}; + +template +class TestDispatcher : + public vtkm::worklet::internal::DispatcherBase< + TestDispatcher, + WorkletType, + TestWorkletBase, + Device> +{ + typedef vtkm::worklet::internal::DispatcherBase< + TestDispatcher, + WorkletType, + TestWorkletBase, + Device> Superclass; + typedef vtkm::internal::FunctionInterface + ParameterInterface; + typedef vtkm::internal::Invocation< + ParameterInterface, + typename Superclass::ControlInterface, + typename Superclass::ExecutionInterface, + 1> Invocation; +public: + VTKM_CONT_EXPORT + TestDispatcher(const WorkletType &worklet = WorkletType()) + : Superclass(worklet) { } + + VTKM_CONT_EXPORT + void DoInvoke(const Invocation &invocation) const + { + std::cout << "In TestDispatcher::DoInvoke()" << std::endl; + this->BasicInvoke(invocation, ARRAY_SIZE); + } + +private: + WorkletType Worklet; +}; + +void TestBasicInvoke() +{ + std::cout << "Test basic invoke" << std::endl; + std::cout << " Set up data." << std::endl; + vtkm::Id inputArray[ARRAY_SIZE]; + vtkm::Id outputArray[ARRAY_SIZE]; + + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + inputArray[index] = TestValue(index, vtkm::Id()); + outputArray[index] = 0xDEADDEAD; + } + + std::cout << " Create and run dispatcher." << std::endl; + TestDispatcher dispatcher; + dispatcher.Invoke(inputArray, outputArray); + + std::cout << " Check output of invoke." << std::endl; + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + VTKM_TEST_ASSERT(outputArray[index] == TestValue(index, vtkm::Id()) + 1000, + "Got bad value from testing."); + } +} + +void TestInvokeWithError() +{ + std::cout << "Test invoke with error raised" << std::endl; + std::cout << " Set up data." << std::endl; + vtkm::Id inputArray[ARRAY_SIZE]; + vtkm::Id outputArray[ARRAY_SIZE]; + + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + inputArray[index] = TestValue(index, vtkm::Id()); + outputArray[index] = 0xDEADDEAD; + } + + try + { + std::cout << " Create and run dispatcher that raises error." << std::endl; + TestDispatcher dispatcher; + dispatcher.Invoke(inputArray, outputArray); + VTKM_TEST_FAIL("Exception not thrown."); + } + catch (vtkm::cont::ErrorExecution error) + { + std::cout << " Got expected exception." << std::endl; + VTKM_TEST_ASSERT(error.GetMessage() == ERROR_MESSAGE, + "Got unexpected error message."); + } +} + +void TestInvokeWithBadType() +{ + std::cout << "Test invoke with bad type" << std::endl; + + vtkm::Id array[ARRAY_SIZE]; + TestDispatcher dispatcher; + + try + { + std::cout << " First argument bad." << std::endl; + dispatcher.Invoke(NULL, array); + } + catch (vtkm::cont::ErrorControlBadType error) + { + std::cout << " Got expected exception." << std::endl; + std::cout << " " << error.GetMessage() << std::endl; + VTKM_TEST_ASSERT(error.GetMessage().find(" 1 ") != std::string::npos, + "Parameter index not named in error message."); + } + + try + { + std::cout << " Second argument bad." << std::endl; + dispatcher.Invoke(array, NULL); + } + catch (vtkm::cont::ErrorControlBadType error) + { + std::cout << " Got expected exception." << std::endl; + std::cout << " " << error.GetMessage() << std::endl; + VTKM_TEST_ASSERT(error.GetMessage().find(" 2 ") != std::string::npos, + "Parameter index not named in error message."); + } +} + +void TestDispatcherBase() +{ + TestBasicInvoke(); + TestInvokeWithError(); + TestInvokeWithBadType(); +} + +} // anonymous namespace + +int UnitTestDispatcherBase(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestDispatcherBase); +} diff --git a/vtkm/worklet/testing/CMakeLists.txt b/vtkm/worklet/testing/CMakeLists.txt new file mode 100644 index 000000000..f688f1945 --- /dev/null +++ b/vtkm/worklet/testing/CMakeLists.txt @@ -0,0 +1,25 @@ +##============================================================================ +## 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. +##============================================================================ + +set(unit_tests + UnitTestWorkletMapField.cxx + ) + +vtkm_unit_tests(SOURCES ${unit_tests}) diff --git a/vtkm/worklet/testing/UnitTestWorkletMapField.cxx b/vtkm/worklet/testing/UnitTestWorkletMapField.cxx new file mode 100644 index 000000000..9bad18605 --- /dev/null +++ b/vtkm/worklet/testing/UnitTestWorkletMapField.cxx @@ -0,0 +1,136 @@ +//============================================================================ +// 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 +#include + +#include +#include + +#include + +namespace { + +static const vtkm::Id ARRAY_SIZE = 10; + +class TestWorklet : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn<>, FieldOut<>); + typedef void ExecutionSignature(_1, _2, WorkIndex); + + template + void operator()(const T &in, T &out, vtkm::Id workIndex) const + { + if (in != TestValue(workIndex, T()) + T(100)) + { + this->RaiseError("Got wrong input value."); + } + out = in - T(100); + } + + template + void operator()(const T1 &, const T2 &, vtkm::Id) const + { + this->RaiseError("Cannot call this worklet with different types."); + } +}; + +class TestWorkletLimitedTypes : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn, FieldOut); + typedef _2 ExecutionSignature(_1, WorkIndex); + + template + T operator()(const T &in, vtkm::Id workIndex) const + { + if (in != TestValue(workIndex, T()) + T(100)) + { + this->RaiseError("Got wrong input value."); + } + return in - T(100); + } +}; + +template +struct DoTestWorklet +{ + template + VTKM_CONT_EXPORT + void operator()(T) const + { + std::cout << "Set up data." << std::endl; + T inputArray[ARRAY_SIZE]; + + for (vtkm::Id index = 0; index < ARRAY_SIZE; index++) + { + inputArray[index] = TestValue(index, T()) + T(100); + } + + vtkm::cont::ArrayHandle inputHandle = + vtkm::cont::make_ArrayHandle(inputArray, ARRAY_SIZE); + vtkm::cont::ArrayHandle outputHandle; + + std::cout << "Create and run dispatcher." << std::endl; + vtkm::worklet::DispatcherMapField dispatcher; + dispatcher.Invoke(inputHandle, outputHandle); + + std::cout << "Check result." << std::endl; + CheckPortal(outputHandle.GetPortalConstControl()); + + std::cout << "Repeat with dynamic arrays." << std::endl; + // Clear out output array. + outputHandle = vtkm::cont::ArrayHandle(); + vtkm::cont::DynamicArrayHandle inputDynamic(inputHandle); + vtkm::cont::DynamicArrayHandle outputDynamic(outputHandle); + dispatcher.Invoke(inputDynamic, outputDynamic); + CheckPortal(outputHandle.GetPortalConstControl()); + } +}; + +void TestWorkletMapField() +{ + std::cout << "--- Worklet accepting all types." << std::endl; + vtkm::testing::Testing::TryTypes(DoTestWorklet(), + vtkm::TypeListTagCommon()); + + std::cout << "--- Worklet accepting some types." << std::endl; + vtkm::testing::Testing::TryTypes(DoTestWorklet(), + vtkm::TypeListTagFieldScalar()); + + std::cout << "--- Sending bad type to worklet." << std::endl; + try + { + DoTestWorklet()(vtkm::Vec()); + VTKM_TEST_FAIL("Did not throw expected error."); + } + catch (vtkm::cont::ErrorControlBadType &error) + { + std::cout << "Got expected error: " << error.GetMessage() << std::endl; + } +} + +} // anonymous namespace + +int UnitTestWorkletMapField(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestWorkletMapField); +}