Update Kokkos library in LAMMPS to v3.6.0
This commit is contained in:
@ -10,6 +10,7 @@ KOKKOS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
FILE(GLOB ALGO_HEADERS *.hpp)
|
||||
FILE(GLOB ALGO_SOURCES *.cpp)
|
||||
LIST(APPEND ALGO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h)
|
||||
APPEND_GLOB(ALGO_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/std_algorithms/*.hpp)
|
||||
|
||||
INSTALL (
|
||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
|
||||
|
||||
@ -466,6 +466,25 @@ struct rand<Generator, Kokkos::Experimental::half_t> {
|
||||
};
|
||||
#endif // defined(KOKKOS_HALF_T_IS_FLOAT) && !KOKKOS_HALF_T_IS_FLOAT
|
||||
|
||||
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||
template <class Generator>
|
||||
struct rand<Generator, Kokkos::Experimental::bhalf_t> {
|
||||
using bhalf = Kokkos::Experimental::bhalf_t;
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static bhalf max() { return bhalf(1.0); }
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static bhalf draw(Generator& gen) { return bhalf(gen.frand()); }
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static bhalf draw(Generator& gen, const bhalf& range) {
|
||||
return bhalf(gen.frand(float(range)));
|
||||
}
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static bhalf draw(Generator& gen, const bhalf& start, const bhalf& end) {
|
||||
return bhalf(gen.frand(float(start), float(end)));
|
||||
}
|
||||
};
|
||||
#endif // defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||
|
||||
template <class Generator>
|
||||
struct rand<Generator, float> {
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
@ -499,7 +518,7 @@ struct rand<Generator, double> {
|
||||
};
|
||||
|
||||
template <class Generator>
|
||||
struct rand<Generator, Kokkos::complex<float> > {
|
||||
struct rand<Generator, Kokkos::complex<float>> {
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static Kokkos::complex<float> max() {
|
||||
return Kokkos::complex<float>(1.0, 1.0);
|
||||
@ -528,7 +547,7 @@ struct rand<Generator, Kokkos::complex<float> > {
|
||||
};
|
||||
|
||||
template <class Generator>
|
||||
struct rand<Generator, Kokkos::complex<double> > {
|
||||
struct rand<Generator, Kokkos::complex<double>> {
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
static Kokkos::complex<double> max() {
|
||||
return Kokkos::complex<double>(1.0, 1.0);
|
||||
@ -617,24 +636,23 @@ struct Random_XorShift1024_UseCArrayState<Kokkos::Experimental::OpenMPTarget>
|
||||
: std::false_type {};
|
||||
#endif
|
||||
|
||||
template <class ExecutionSpace>
|
||||
template <class DeviceType>
|
||||
struct Random_UniqueIndex {
|
||||
using locks_view_type = View<int**, ExecutionSpace>;
|
||||
using locks_view_type = View<int**, DeviceType>;
|
||||
KOKKOS_FUNCTION
|
||||
static int get_state_idx(const locks_view_type) {
|
||||
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
|
||||
const int i = ExecutionSpace::impl_hardware_thread_id();
|
||||
return i;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
KOKKOS_IF_ON_HOST(
|
||||
(return DeviceType::execution_space::impl_hardware_thread_id();))
|
||||
|
||||
KOKKOS_IF_ON_DEVICE((return 0;))
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef KOKKOS_ENABLE_CUDA
|
||||
template <>
|
||||
struct Random_UniqueIndex<Kokkos::Cuda> {
|
||||
using locks_view_type = View<int**, Kokkos::Cuda>;
|
||||
template <class MemorySpace>
|
||||
struct Random_UniqueIndex<Kokkos::Device<Kokkos::Cuda, MemorySpace>> {
|
||||
using locks_view_type =
|
||||
View<int**, Kokkos::Device<Kokkos::Cuda, MemorySpace>>;
|
||||
KOKKOS_FUNCTION
|
||||
static int get_state_idx(const locks_view_type& locks_) {
|
||||
#ifdef __CUDA_ARCH__
|
||||
@ -660,9 +678,11 @@ struct Random_UniqueIndex<Kokkos::Cuda> {
|
||||
#endif
|
||||
|
||||
#ifdef KOKKOS_ENABLE_HIP
|
||||
template <>
|
||||
struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
|
||||
using locks_view_type = View<int**, Kokkos::Experimental::HIP>;
|
||||
template <class MemorySpace>
|
||||
struct Random_UniqueIndex<
|
||||
Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>> {
|
||||
using locks_view_type =
|
||||
View<int**, Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>>;
|
||||
KOKKOS_FUNCTION
|
||||
static int get_state_idx(const locks_view_type& locks_) {
|
||||
#ifdef __HIP_DEVICE_COMPILE__
|
||||
@ -688,18 +708,37 @@ struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
|
||||
#endif
|
||||
|
||||
#ifdef KOKKOS_ENABLE_SYCL
|
||||
template <>
|
||||
struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
|
||||
using locks_view_type = View<int**, Kokkos::Experimental::SYCL>;
|
||||
template <class MemorySpace>
|
||||
struct Random_UniqueIndex<
|
||||
Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>> {
|
||||
using locks_view_type =
|
||||
View<int**, Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>>;
|
||||
KOKKOS_FUNCTION
|
||||
static int get_state_idx(const locks_view_type& locks_) {
|
||||
#ifdef KOKKOS_ARCH_INTEL_GPU
|
||||
int i = Kokkos::Impl::clock_tic() % locks_.extent(0);
|
||||
#else
|
||||
int i = 0;
|
||||
#endif
|
||||
auto item = sycl::ext::oneapi::experimental::this_nd_item<3>();
|
||||
std::size_t threadIdx[3] = {item.get_local_id(2), item.get_local_id(1),
|
||||
item.get_local_id(0)};
|
||||
std::size_t blockIdx[3] = {item.get_group(2), item.get_group(1),
|
||||
item.get_group(0)};
|
||||
std::size_t blockDim[3] = {item.get_local_range(2), item.get_local_range(1),
|
||||
item.get_local_range(0)};
|
||||
std::size_t gridDim[3] = {
|
||||
item.get_global_range(2) / item.get_local_range(2),
|
||||
item.get_global_range(1) / item.get_local_range(1),
|
||||
item.get_global_range(0) / item.get_local_range(0)};
|
||||
const int i_offset =
|
||||
(threadIdx[0] * blockDim[1] + threadIdx[1]) * blockDim[2] +
|
||||
threadIdx[2];
|
||||
int i =
|
||||
(((blockIdx[0] * gridDim[1] + blockIdx[1]) * gridDim[2] + blockIdx[2]) *
|
||||
blockDim[0] * blockDim[1] * blockDim[2] +
|
||||
i_offset) %
|
||||
locks_.extent(0);
|
||||
while (Kokkos::atomic_compare_exchange(&locks_(i, 0), 0, 1)) {
|
||||
i = (i + 1) % static_cast<int>(locks_.extent(0));
|
||||
i += blockDim[0] * blockDim[1] * blockDim[2];
|
||||
if (i >= static_cast<int>(locks_.extent(0))) {
|
||||
i = i_offset;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@ -707,9 +746,12 @@ struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
|
||||
#endif
|
||||
|
||||
#ifdef KOKKOS_ENABLE_OPENMPTARGET
|
||||
template <>
|
||||
struct Random_UniqueIndex<Kokkos::Experimental::OpenMPTarget> {
|
||||
using locks_view_type = View<int**, Kokkos::Experimental::OpenMPTarget>;
|
||||
template <class MemorySpace>
|
||||
struct Random_UniqueIndex<
|
||||
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>> {
|
||||
using locks_view_type =
|
||||
View<int**,
|
||||
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>>;
|
||||
KOKKOS_FUNCTION
|
||||
static int get_state_idx(const locks_view_type& locks) {
|
||||
const int team_size = omp_get_num_threads();
|
||||
@ -873,10 +915,13 @@ class Random_XorShift64 {
|
||||
|
||||
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
||||
class Random_XorShift64_Pool {
|
||||
public:
|
||||
using device_type = typename DeviceType::device_type;
|
||||
|
||||
private:
|
||||
using execution_space = typename DeviceType::execution_space;
|
||||
using locks_type = View<int**, execution_space>;
|
||||
using state_data_type = View<uint64_t**, DeviceType>;
|
||||
using execution_space = typename device_type::execution_space;
|
||||
using locks_type = View<int**, device_type>;
|
||||
using state_data_type = View<uint64_t**, device_type>;
|
||||
locks_type locks_;
|
||||
state_data_type state_;
|
||||
int num_states_;
|
||||
@ -884,7 +929,6 @@ class Random_XorShift64_Pool {
|
||||
|
||||
public:
|
||||
using generator_type = Random_XorShift64<DeviceType>;
|
||||
using device_type = DeviceType;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
Random_XorShift64_Pool() {
|
||||
@ -923,8 +967,10 @@ class Random_XorShift64_Pool {
|
||||
state_ = state_data_type("Kokkos::Random_XorShift64::state", num_states_,
|
||||
padding_);
|
||||
|
||||
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
|
||||
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
|
||||
typename state_data_type::HostMirror h_state =
|
||||
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, state_);
|
||||
typename locks_type::HostMirror h_lock =
|
||||
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, locks_);
|
||||
|
||||
// Execute on the HostMirror's default execution space.
|
||||
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
||||
@ -947,8 +993,7 @@ class Random_XorShift64_Pool {
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
Random_XorShift64<DeviceType> get_state() const {
|
||||
const int i =
|
||||
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
|
||||
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
|
||||
return Random_XorShift64<DeviceType>(state_(i, 0), i);
|
||||
}
|
||||
|
||||
@ -1119,11 +1164,14 @@ class Random_XorShift1024 {
|
||||
|
||||
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
||||
class Random_XorShift1024_Pool {
|
||||
public:
|
||||
using device_type = typename DeviceType::device_type;
|
||||
|
||||
private:
|
||||
using execution_space = typename DeviceType::execution_space;
|
||||
using locks_type = View<int**, execution_space>;
|
||||
using int_view_type = View<int**, DeviceType>;
|
||||
using state_data_type = View<uint64_t * [16], DeviceType>;
|
||||
using execution_space = typename device_type::execution_space;
|
||||
using locks_type = View<int**, device_type>;
|
||||
using int_view_type = View<int**, device_type>;
|
||||
using state_data_type = View<uint64_t * [16], device_type>;
|
||||
|
||||
locks_type locks_;
|
||||
state_data_type state_;
|
||||
@ -1135,8 +1183,6 @@ class Random_XorShift1024_Pool {
|
||||
public:
|
||||
using generator_type = Random_XorShift1024<DeviceType>;
|
||||
|
||||
using device_type = DeviceType;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
Random_XorShift1024_Pool() { num_states_ = 0; }
|
||||
|
||||
@ -1175,9 +1221,12 @@ class Random_XorShift1024_Pool {
|
||||
state_ = state_data_type("Kokkos::Random_XorShift1024::state", num_states_);
|
||||
p_ = int_view_type("Kokkos::Random_XorShift1024::p", num_states_, padding_);
|
||||
|
||||
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
|
||||
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
|
||||
typename int_view_type::HostMirror h_p = create_mirror_view(p_);
|
||||
typename state_data_type::HostMirror h_state =
|
||||
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, state_);
|
||||
typename locks_type::HostMirror h_lock =
|
||||
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, locks_);
|
||||
typename int_view_type::HostMirror h_p =
|
||||
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, p_);
|
||||
|
||||
// Execute on the HostMirror's default execution space.
|
||||
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
||||
@ -1203,8 +1252,7 @@ class Random_XorShift1024_Pool {
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
Random_XorShift1024<DeviceType> get_state() const {
|
||||
const int i =
|
||||
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
|
||||
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
|
||||
return Random_XorShift1024<DeviceType>(state_, p_(i, 0), i);
|
||||
};
|
||||
|
||||
@ -1224,265 +1272,34 @@ class Random_XorShift1024_Pool {
|
||||
|
||||
namespace Impl {
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, int rank,
|
||||
class IndexType>
|
||||
struct fill_random_functor_range;
|
||||
template <class ViewType, class RandomPool, int loops, int rank,
|
||||
class IndexType>
|
||||
struct fill_random_functor_begin_end;
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 1, IndexType> {
|
||||
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 0,
|
||||
IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
typename ViewType::const_value_type begin, end;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type begin_,
|
||||
typename ViewType::const_value_type end_)
|
||||
: a(a_), rand_pool(rand_pool_), begin(begin_), end(end_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(const IndexType& i) const {
|
||||
void operator()(IndexType) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0)))
|
||||
a(idx) = Rand::draw(gen, range);
|
||||
}
|
||||
a() = Rand::draw(gen, begin, end);
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 2, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
a(idx, k) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 3, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
a(idx, k, l) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 4, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
||||
a(idx, k, l, m) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 5, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
||||
n++)
|
||||
a(idx, k, l, m, n) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 6, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
||||
n++)
|
||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
||||
o++)
|
||||
a(idx, k, l, m, n, o) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 7, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
||||
n++)
|
||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
||||
o++)
|
||||
for (IndexType p = 0; p < static_cast<IndexType>(a.extent(6));
|
||||
p++)
|
||||
a(idx, k, l, m, n, o, p) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 8, IndexType> {
|
||||
using execution_space = typename ViewType::execution_space;
|
||||
ViewType a;
|
||||
RandomPool rand_pool;
|
||||
typename ViewType::const_value_type range;
|
||||
|
||||
using Rand = rand<typename RandomPool::generator_type,
|
||||
typename ViewType::non_const_value_type>;
|
||||
|
||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
||||
typename ViewType::const_value_type range_)
|
||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(IndexType i) const {
|
||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||
for (IndexType j = 0; j < loops; j++) {
|
||||
const IndexType idx = i * loops + j;
|
||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
||||
n++)
|
||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
||||
o++)
|
||||
for (IndexType p = 0; p < static_cast<IndexType>(a.extent(6));
|
||||
p++)
|
||||
for (IndexType q = 0;
|
||||
q < static_cast<IndexType>(a.extent(7)); q++)
|
||||
a(idx, k, l, m, n, o, p, q) = Rand::draw(gen, range);
|
||||
}
|
||||
}
|
||||
rand_pool.free_state(gen);
|
||||
}
|
||||
};
|
||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 1,
|
||||
IndexType> {
|
||||
@ -1752,19 +1569,6 @@ struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 8,
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
|
||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||
void fill_random(ViewType a, RandomPool g,
|
||||
typename ViewType::const_value_type range) {
|
||||
int64_t LDA = a.extent(0);
|
||||
if (LDA > 0)
|
||||
parallel_for("Kokkos::fill_random", (LDA + 127) / 128,
|
||||
Impl::fill_random_functor_range<ViewType, RandomPool, 128,
|
||||
ViewType::Rank, IndexType>(
|
||||
a, g, range));
|
||||
}
|
||||
|
||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||
void fill_random(ViewType a, RandomPool g,
|
||||
typename ViewType::const_value_type begin,
|
||||
@ -1776,6 +1580,23 @@ void fill_random(ViewType a, RandomPool g,
|
||||
ViewType::Rank, IndexType>(
|
||||
a, g, begin, end));
|
||||
}
|
||||
|
||||
} // namespace Impl
|
||||
|
||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||
void fill_random(ViewType a, RandomPool g,
|
||||
typename ViewType::const_value_type begin,
|
||||
typename ViewType::const_value_type end) {
|
||||
Impl::apply_to_view_of_static_rank(
|
||||
[&](auto dst) { Kokkos::Impl::fill_random(dst, g, begin, end); }, a);
|
||||
}
|
||||
|
||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||
void fill_random(ViewType a, RandomPool g,
|
||||
typename ViewType::const_value_type range) {
|
||||
fill_random(a, g, 0, range);
|
||||
}
|
||||
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
|
||||
@ -437,16 +437,41 @@ struct BinOp1D {
|
||||
BinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
|
||||
typename KeyViewType::const_value_type max)
|
||||
: max_bins_(max_bins__ + 1),
|
||||
mul_(1.0 * max_bins__ / (max - min)),
|
||||
// Cast to int64_t to avoid possible overflow when using integer
|
||||
mul_(std::is_integral<typename KeyViewType::const_value_type>::value
|
||||
? 1.0 * max_bins__ / (int64_t(max) - int64_t(min))
|
||||
: 1.0 * max_bins__ / (max - min)),
|
||||
range_(max - min),
|
||||
min_(min) {}
|
||||
min_(min) {
|
||||
// For integral types the number of bins may be larger than the range
|
||||
// in which case we can exactly have one unique value per bin
|
||||
// and then don't need to sort bins.
|
||||
if (std::is_integral<typename KeyViewType::const_value_type>::value &&
|
||||
static_cast<uint64_t>(range_) <= static_cast<uint64_t>(max_bins__)) {
|
||||
mul_ = 1.;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine bin index from key value
|
||||
template <class ViewType>
|
||||
template <
|
||||
class ViewType,
|
||||
std::enable_if_t<!std::is_integral<typename ViewType::value_type>::value,
|
||||
bool> = true>
|
||||
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
|
||||
return int(mul_ * (keys(i) - min_));
|
||||
}
|
||||
|
||||
// Determine bin index from key value
|
||||
template <
|
||||
class ViewType,
|
||||
std::enable_if_t<std::is_integral<typename ViewType::value_type>::value,
|
||||
bool> = true>
|
||||
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
|
||||
// The cast to int64_t is necessary because otherwise HIP returns the wrong
|
||||
// result.
|
||||
return int(mul_ * (int64_t(keys(i)) - int64_t(min_)));
|
||||
}
|
||||
|
||||
// Return maximum bin index + 1
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
int max_bins() const { return max_bins_; }
|
||||
@ -564,8 +589,26 @@ std::enable_if_t<Kokkos::is_execution_space<ExecutionSpace>::value> sort(
|
||||
exec, 0, view.extent(0)),
|
||||
Impl::min_max_functor<ViewType>(view), reducer);
|
||||
if (result.min_val == result.max_val) return;
|
||||
// For integral types the number of bins may be larger than the range
|
||||
// in which case we can exactly have one unique value per bin
|
||||
// and then don't need to sort bins.
|
||||
bool sort_in_bins = true;
|
||||
// TODO: figure out better max_bins then this ...
|
||||
int64_t max_bins = view.extent(0) / 2;
|
||||
if (std::is_integral<typename ViewType::non_const_value_type>::value) {
|
||||
// Cast to int64_t to avoid possible overflow when using integer
|
||||
int64_t const max_val = result.max_val;
|
||||
int64_t const min_val = result.min_val;
|
||||
// using 10M as the cutoff for special behavior (roughly 40MB for the count
|
||||
// array)
|
||||
if ((max_val - min_val) < 10000000) {
|
||||
max_bins = max_val - min_val + 1;
|
||||
sort_in_bins = false;
|
||||
}
|
||||
}
|
||||
|
||||
BinSort<ViewType, CompType> bin_sort(
|
||||
view, CompType(view.extent(0) / 2, result.min_val, result.max_val), true);
|
||||
view, CompType(max_bins, result.min_val, result.max_val), sort_in_bins);
|
||||
bin_sort.create_permute_vector(exec);
|
||||
bin_sort.sort(exec, view);
|
||||
}
|
||||
|
||||
102
lib/kokkos/algorithms/src/Kokkos_StdAlgorithms.hpp
Normal file
102
lib/kokkos/algorithms/src/Kokkos_StdAlgorithms.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_ALGORITHMS_HPP
|
||||
#define KOKKOS_STD_ALGORITHMS_HPP
|
||||
|
||||
/// \file Kokkos_StdAlgorithms.hpp
|
||||
/// \brief Kokkos counterparts for Standard C++ Library algorithms
|
||||
|
||||
#include <std_algorithms/Kokkos_Constraints.hpp>
|
||||
#include <std_algorithms/Kokkos_RandomAccessIterator.hpp>
|
||||
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||
|
||||
// distance
|
||||
#include <std_algorithms/Kokkos_Distance.hpp>
|
||||
|
||||
// move, swap, iter_swap
|
||||
#include "std_algorithms/Kokkos_ModifyingOperations.hpp"
|
||||
|
||||
// find, find_if, find_if_not
|
||||
// for_each, for_each_n
|
||||
// mismatch
|
||||
// equal
|
||||
// count_if, count
|
||||
// all_of, any_of, none_of
|
||||
// adjacent_find
|
||||
// lexicographical_compare
|
||||
// search, search_n
|
||||
// find_first_of, find_end
|
||||
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||
|
||||
// replace, replace_copy_if, replace_copy, replace_if
|
||||
// copy, copy_n, copy_backward, copy_if
|
||||
// fill, fill_n
|
||||
// transform
|
||||
// generate, generate_n
|
||||
// reverse, reverse_copy
|
||||
// move, move_backward
|
||||
// swap_ranges
|
||||
// unique, unique_copy
|
||||
// rotate, rotate_copy
|
||||
// remove, remove_if, remove_copy, remove_copy_if
|
||||
// shift_left, shift_right
|
||||
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||
|
||||
// is_sorted_until, is_sorted
|
||||
#include <std_algorithms/Kokkos_SortingOperations.hpp>
|
||||
|
||||
// min_element, max_element, minmax_element
|
||||
#include <std_algorithms/Kokkos_MinMaxElementOperations.hpp>
|
||||
|
||||
// is_partitioned, partition_copy, partition_point
|
||||
#include <std_algorithms/Kokkos_PartitioningOperations.hpp>
|
||||
|
||||
// adjacent_difference
|
||||
// reduce, transform_reduce
|
||||
// exclusive_scan, transform_exclusive_scan
|
||||
// inclusive_scan, transform_inclusive_scan
|
||||
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||
|
||||
#endif
|
||||
105
lib/kokkos/algorithms/src/std_algorithms/Kokkos_BeginEnd.hpp
Normal file
105
lib/kokkos/algorithms/src/std_algorithms/Kokkos_BeginEnd.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_BEGIN_END_HPP
|
||||
#define KOKKOS_BEGIN_END_HPP
|
||||
|
||||
#include <Kokkos_View.hpp>
|
||||
#include "Kokkos_RandomAccessIterator.hpp"
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
|
||||
/// \file Kokkos_BeginEnd.hpp
|
||||
/// \brief Kokkos begin, end, cbegin, cend
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
|
||||
template <class DataType, class... Properties>
|
||||
KOKKOS_INLINE_FUNCTION auto begin(
|
||||
const Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
using it_t =
|
||||
Impl::RandomAccessIterator<Kokkos::View<DataType, Properties...>>;
|
||||
return it_t(v);
|
||||
}
|
||||
|
||||
template <class DataType, class... Properties>
|
||||
KOKKOS_INLINE_FUNCTION auto end(
|
||||
const Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
using it_t =
|
||||
Impl::RandomAccessIterator<Kokkos::View<DataType, Properties...>>;
|
||||
return it_t(v, v.extent(0));
|
||||
}
|
||||
|
||||
template <class DataType, class... Properties>
|
||||
KOKKOS_INLINE_FUNCTION auto cbegin(
|
||||
const Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
using ViewConstType =
|
||||
typename Kokkos::View<DataType, Properties...>::const_type;
|
||||
const ViewConstType cv = v;
|
||||
using it_t = Impl::RandomAccessIterator<ViewConstType>;
|
||||
return it_t(cv);
|
||||
}
|
||||
|
||||
template <class DataType, class... Properties>
|
||||
KOKKOS_INLINE_FUNCTION auto cend(
|
||||
const Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
using ViewConstType =
|
||||
typename Kokkos::View<DataType, Properties...>::const_type;
|
||||
const ViewConstType cv = v;
|
||||
using it_t = Impl::RandomAccessIterator<ViewConstType>;
|
||||
return it_t(cv, cv.extent(0));
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
237
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Constraints.hpp
Normal file
237
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Constraints.hpp
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_ALGORITHMS_CONSTRAINTS_HPP_
|
||||
#define KOKKOS_STD_ALGORITHMS_CONSTRAINTS_HPP_
|
||||
|
||||
#include <Kokkos_DetectionIdiom.hpp>
|
||||
#include <Kokkos_View.hpp>
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <typename T, typename enable = void>
|
||||
struct is_admissible_to_kokkos_std_algorithms : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_admissible_to_kokkos_std_algorithms<
|
||||
T, std::enable_if_t< ::Kokkos::is_view<T>::value && T::rank == 1 &&
|
||||
(std::is_same<typename T::traits::array_layout,
|
||||
Kokkos::LayoutLeft>::value ||
|
||||
std::is_same<typename T::traits::array_layout,
|
||||
Kokkos::LayoutRight>::value ||
|
||||
std::is_same<typename T::traits::array_layout,
|
||||
Kokkos::LayoutStride>::value)> >
|
||||
: std::true_type {};
|
||||
|
||||
template <class ViewType>
|
||||
KOKKOS_INLINE_FUNCTION constexpr void
|
||||
static_assert_is_admissible_to_kokkos_std_algorithms(
|
||||
const ViewType& /* view */) {
|
||||
static_assert(is_admissible_to_kokkos_std_algorithms<ViewType>::value,
|
||||
"Currently, Kokkos standard algorithms only accept 1D Views.");
|
||||
}
|
||||
|
||||
//
|
||||
// is_iterator
|
||||
//
|
||||
template <class T>
|
||||
using iterator_category_t = typename T::iterator_category;
|
||||
|
||||
template <class T>
|
||||
using is_iterator = Kokkos::is_detected<iterator_category_t, T>;
|
||||
|
||||
//
|
||||
// are_iterators
|
||||
//
|
||||
template <class... Args>
|
||||
struct are_iterators;
|
||||
|
||||
template <class T>
|
||||
struct are_iterators<T> {
|
||||
static constexpr bool value = is_iterator<T>::value;
|
||||
};
|
||||
|
||||
template <class Head, class... Tail>
|
||||
struct are_iterators<Head, Tail...> {
|
||||
static constexpr bool value =
|
||||
are_iterators<Head>::value && are_iterators<Tail...>::value;
|
||||
};
|
||||
|
||||
//
|
||||
// are_random_access_iterators
|
||||
//
|
||||
template <class... Args>
|
||||
struct are_random_access_iterators;
|
||||
|
||||
template <class T>
|
||||
struct are_random_access_iterators<T> {
|
||||
static constexpr bool value =
|
||||
is_iterator<T>::value &&
|
||||
std::is_base_of<std::random_access_iterator_tag,
|
||||
typename T::iterator_category>::value;
|
||||
};
|
||||
|
||||
template <class Head, class... Tail>
|
||||
struct are_random_access_iterators<Head, Tail...> {
|
||||
static constexpr bool value = are_random_access_iterators<Head>::value &&
|
||||
are_random_access_iterators<Tail...>::value;
|
||||
};
|
||||
|
||||
//
|
||||
// iterators_are_accessible_from
|
||||
//
|
||||
template <class... Args>
|
||||
struct iterators_are_accessible_from;
|
||||
|
||||
template <class ExeSpace, class IteratorType>
|
||||
struct iterators_are_accessible_from<ExeSpace, IteratorType> {
|
||||
using view_type = typename IteratorType::view_type;
|
||||
static constexpr bool value =
|
||||
SpaceAccessibility<ExeSpace,
|
||||
typename view_type::memory_space>::accessible;
|
||||
};
|
||||
|
||||
template <class ExeSpace, class Head, class... Tail>
|
||||
struct iterators_are_accessible_from<ExeSpace, Head, Tail...> {
|
||||
static constexpr bool value =
|
||||
iterators_are_accessible_from<ExeSpace, Head>::value &&
|
||||
iterators_are_accessible_from<ExeSpace, Tail...>::value;
|
||||
};
|
||||
|
||||
template <class ExecutionSpace, class... IteratorTypes>
|
||||
KOKKOS_INLINE_FUNCTION constexpr void
|
||||
static_assert_random_access_and_accessible(const ExecutionSpace& /* ex */,
|
||||
IteratorTypes... /* iterators */) {
|
||||
static_assert(
|
||||
are_random_access_iterators<IteratorTypes...>::value,
|
||||
"Currently, Kokkos standard algorithms require random access iterators.");
|
||||
static_assert(
|
||||
iterators_are_accessible_from<ExecutionSpace, IteratorTypes...>::value,
|
||||
"Incompatible view/iterator and execution space");
|
||||
}
|
||||
|
||||
//
|
||||
// have matching difference_type
|
||||
//
|
||||
template <class... Args>
|
||||
struct iterators_have_matching_difference_type;
|
||||
|
||||
template <class T>
|
||||
struct iterators_have_matching_difference_type<T> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct iterators_have_matching_difference_type<T1, T2> {
|
||||
static constexpr bool value =
|
||||
std::is_same<typename T1::difference_type,
|
||||
typename T2::difference_type>::value;
|
||||
};
|
||||
|
||||
template <class T1, class T2, class... Tail>
|
||||
struct iterators_have_matching_difference_type<T1, T2, Tail...> {
|
||||
static constexpr bool value =
|
||||
iterators_have_matching_difference_type<T1, T2>::value &&
|
||||
iterators_have_matching_difference_type<T2, Tail...>::value;
|
||||
};
|
||||
|
||||
template <class IteratorType1, class IteratorType2>
|
||||
KOKKOS_INLINE_FUNCTION constexpr void
|
||||
static_assert_iterators_have_matching_difference_type(IteratorType1 /* it1 */,
|
||||
IteratorType2 /* it2 */) {
|
||||
static_assert(iterators_have_matching_difference_type<IteratorType1,
|
||||
IteratorType2>::value,
|
||||
"Iterators do not have matching difference_type");
|
||||
}
|
||||
|
||||
template <class IteratorType1, class IteratorType2, class IteratorType3>
|
||||
KOKKOS_INLINE_FUNCTION constexpr void
|
||||
static_assert_iterators_have_matching_difference_type(IteratorType1 it1,
|
||||
IteratorType2 it2,
|
||||
IteratorType3 it3) {
|
||||
static_assert_iterators_have_matching_difference_type(it1, it2);
|
||||
static_assert_iterators_have_matching_difference_type(it2, it3);
|
||||
}
|
||||
|
||||
//
|
||||
// not_openmptarget
|
||||
//
|
||||
template <class ExeSpace>
|
||||
struct not_openmptarget {
|
||||
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||
static constexpr bool value = true;
|
||||
#else
|
||||
static constexpr bool value =
|
||||
!std::is_same<std::decay_t<ExeSpace>,
|
||||
::Kokkos::Experimental::OpenMPTarget>::value;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class ExecutionSpace>
|
||||
KOKKOS_INLINE_FUNCTION constexpr void static_assert_is_not_openmptarget(
|
||||
const ExecutionSpace&) {
|
||||
static_assert(not_openmptarget<ExecutionSpace>::value,
|
||||
"Currently, Kokkos standard algorithms do not support custom "
|
||||
"comparators in OpenMPTarget");
|
||||
}
|
||||
|
||||
//
|
||||
// valid range
|
||||
//
|
||||
template <class IteratorType>
|
||||
void expect_valid_range(IteratorType first, IteratorType last) {
|
||||
// this is a no-op for release
|
||||
KOKKOS_EXPECTS(last >= first);
|
||||
// avoid compiler complaining when KOKKOS_EXPECTS is no-op
|
||||
(void)first;
|
||||
(void)last;
|
||||
}
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
69
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Distance.hpp
Normal file
69
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Distance.hpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_ALGORITHMS_DISTANCE_HPP
|
||||
#define KOKKOS_STD_ALGORITHMS_DISTANCE_HPP
|
||||
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
#include "Kokkos_RandomAccessIterator.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
|
||||
template <class IteratorType>
|
||||
KOKKOS_INLINE_FUNCTION constexpr typename IteratorType::difference_type
|
||||
distance(IteratorType first, IteratorType last) {
|
||||
static_assert(
|
||||
::Kokkos::Experimental::Impl::are_random_access_iterators<
|
||||
IteratorType>::value,
|
||||
"Kokkos::Experimental::distance: only implemented for random access "
|
||||
"iterators.");
|
||||
|
||||
return last - first;
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,120 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_HELPER_PREDICATES_HPP
|
||||
#define KOKKOS_STD_HELPER_PREDICATES_HPP
|
||||
|
||||
#include <Kokkos_Macros.hpp>
|
||||
|
||||
// naming convetion:
|
||||
// StdAlgoSomeExpressiveNameUnaryPredicate
|
||||
// StdAlgoSomeExpressiveNameBinaryPredicate
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
// ------------------
|
||||
// UNARY PREDICATES
|
||||
// ------------------
|
||||
template <class T>
|
||||
struct StdAlgoEqualsValUnaryPredicate {
|
||||
T m_value;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr bool operator()(const T& val) const { return val == m_value; }
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr explicit StdAlgoEqualsValUnaryPredicate(const T& _value)
|
||||
: m_value(_value) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct StdAlgoNotEqualsValUnaryPredicate {
|
||||
T m_value;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr bool operator()(const T& val) const { return !(val == m_value); }
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr explicit StdAlgoNotEqualsValUnaryPredicate(const T& _value)
|
||||
: m_value(_value) {}
|
||||
};
|
||||
|
||||
template <class ValueType, class PredicateType>
|
||||
struct StdAlgoNegateUnaryPredicateWrapper {
|
||||
PredicateType m_pred;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr bool operator()(const ValueType& val) const { return !m_pred(val); }
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr explicit StdAlgoNegateUnaryPredicateWrapper(
|
||||
const PredicateType& pred)
|
||||
: m_pred(pred) {}
|
||||
};
|
||||
|
||||
// ------------------
|
||||
// BINARY PREDICATES
|
||||
// ------------------
|
||||
template <class ValueType1, class ValueType2 = ValueType1>
|
||||
struct StdAlgoEqualBinaryPredicate {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType1, class ValueType2 = ValueType1>
|
||||
struct StdAlgoLessThanBinaryPredicate {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
#endif
|
||||
@ -0,0 +1,409 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_MIN_MAX_ELEMENT_OPERATIONS_HPP
|
||||
#define KOKKOS_STD_MIN_MAX_ELEMENT_OPERATIONS_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "Kokkos_BeginEnd.hpp"
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
#include "Kokkos_Distance.hpp"
|
||||
#include "Kokkos_ModifyingOperations.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class IteratorType, class ReducerType>
|
||||
struct StdMinOrMaxElemFunctor {
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
|
||||
IteratorType m_first;
|
||||
ReducerType m_reducer;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& red_value) const {
|
||||
m_reducer.join(red_value, red_value_type{m_first[i], i});
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdMinOrMaxElemFunctor(IteratorType first, ReducerType reducer)
|
||||
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||
};
|
||||
|
||||
template <class IteratorType, class ReducerType>
|
||||
struct StdMinMaxElemFunctor {
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
IteratorType m_first;
|
||||
ReducerType m_reducer;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& red_value) const {
|
||||
const auto& my_value = m_first[i];
|
||||
m_reducer.join(red_value, red_value_type{my_value, my_value, i, i});
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdMinMaxElemFunctor(IteratorType first, ReducerType reducer)
|
||||
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||
};
|
||||
|
||||
// ------------------------------------------
|
||||
// min_or_max_element_impl
|
||||
// ------------------------------------------
|
||||
template <template <class... Args> class ReducerType, class ExecutionSpace,
|
||||
class IteratorType, class... Args>
|
||||
IteratorType min_or_max_element_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
Args&&... args) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
if (first == last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using value_type = typename IteratorType::value_type;
|
||||
using reducer_type = ReducerType<value_type, index_type, Args...>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
using func_t = StdMinOrMaxElemFunctor<IteratorType, reducer_type>;
|
||||
|
||||
// run
|
||||
reduction_value_type red_result;
|
||||
reducer_type reducer(red_result, std::forward<Args>(args)...);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_t(first, reducer), reducer);
|
||||
|
||||
// fence not needed because reducing into scalar
|
||||
|
||||
// return
|
||||
return first + red_result.loc;
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// minmax_element_impl
|
||||
// ------------------------------------------
|
||||
template <template <class... Args> class ReducerType, class ExecutionSpace,
|
||||
class IteratorType, class... Args>
|
||||
::Kokkos::pair<IteratorType, IteratorType> minmax_element_impl(
|
||||
const std::string& label, const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, Args&&... args) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
if (first == last) {
|
||||
return {first, first};
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using value_type = typename IteratorType::value_type;
|
||||
using reducer_type = ReducerType<value_type, index_type, Args...>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
using func_t = StdMinMaxElemFunctor<IteratorType, reducer_type>;
|
||||
|
||||
// run
|
||||
reduction_value_type red_result;
|
||||
reducer_type reducer(red_result, std::forward<Args>(args)...);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_t(first, reducer), reducer);
|
||||
|
||||
// fence not needed because reducing into scalar
|
||||
|
||||
// return
|
||||
return {first + red_result.min_loc, first + red_result.max_loc};
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
// ----------------------
|
||||
// min_element public API
|
||||
// ----------------------
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto min_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::min_or_max_element_impl<MinFirstLoc>(
|
||||
"Kokkos::min_element_iterator_api_default", ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
return Impl::min_or_max_element_impl<MinFirstLoc>(label, ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto min_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||
"Kokkos::min_element_iterator_api_default", ex, first, last,
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||
label, ex, first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto min_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLoc>(
|
||||
"Kokkos::min_element_view_api_default", ex, begin(v), end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto min_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||
"Kokkos::min_element_view_api_default", ex, begin(v), end(v),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLoc>(label, ex, begin(v),
|
||||
end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||
label, ex, begin(v), end(v), std::move(comp));
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// max_element public API
|
||||
// ----------------------
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto max_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::min_or_max_element_impl<MaxFirstLoc>(
|
||||
"Kokkos::max_element_iterator_api_default", ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
return Impl::min_or_max_element_impl<MaxFirstLoc>(label, ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto max_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||
"Kokkos::max_element_iterator_api_default", ex, first, last,
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||
label, ex, first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto max_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLoc>(
|
||||
"Kokkos::max_element_view_api_default", ex, begin(v), end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLoc>(label, ex, begin(v),
|
||||
end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto max_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||
"Kokkos::max_element_view_api_default", ex, begin(v), end(v),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||
label, ex, begin(v), end(v), std::move(comp));
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// minmax_element public API
|
||||
// -------------------------
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto minmax_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(
|
||||
"Kokkos::minmax_element_iterator_api_default", ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(label, ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto minmax_element(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||
"Kokkos::minmax_element_iterator_api_default", ex, first, last,
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||
label, ex, first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto minmax_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(
|
||||
"Kokkos::minmax_element_view_api_default", ex, begin(v), end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(label, ex, begin(v),
|
||||
end(v));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto minmax_element(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||
"Kokkos::minmax_element_view_api_default", ex, begin(v), end(v),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||
class... Properties>
|
||||
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||
label, ex, begin(v), end(v), std::move(comp));
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_MODIFYING_OPERATIONS_HPP
|
||||
#define KOKKOS_MODIFYING_OPERATIONS_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "Kokkos_BeginEnd.hpp"
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
|
||||
// move
|
||||
template <typename T>
|
||||
KOKKOS_INLINE_FUNCTION std::remove_reference_t<T>&& move(T&& t) {
|
||||
return static_cast<std::remove_reference_t<T>&&>(t);
|
||||
}
|
||||
|
||||
// swap
|
||||
template <class T>
|
||||
KOKKOS_INLINE_FUNCTION void swap(T& a, T& b) noexcept {
|
||||
static_assert(
|
||||
std::is_move_assignable<T>::value && std::is_move_constructible<T>::value,
|
||||
"Kokkos::Experimental::swap arguments must be move assignable "
|
||||
"and move constructible");
|
||||
|
||||
T tmp = std::move(a);
|
||||
a = std::move(b);
|
||||
b = std::move(tmp);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// this is here because we use the swap function above
|
||||
namespace Impl {
|
||||
template <class IteratorType1, class IteratorType2>
|
||||
struct StdIterSwapFunctor {
|
||||
IteratorType1 m_a;
|
||||
IteratorType2 m_b;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(int i) const {
|
||||
(void)i;
|
||||
::Kokkos::Experimental::swap(*m_a, *m_b);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdIterSwapFunctor(IteratorType1 _a, IteratorType2 _b)
|
||||
: m_a(std::move(_a)), m_b(std::move(_b)) {}
|
||||
};
|
||||
|
||||
template <class IteratorType1, class IteratorType2>
|
||||
void iter_swap_impl(IteratorType1 a, IteratorType2 b) {
|
||||
// is there a better way to do this maybe?
|
||||
::Kokkos::parallel_for(
|
||||
1, StdIterSwapFunctor<IteratorType1, IteratorType2>(a, b));
|
||||
Kokkos::DefaultExecutionSpace().fence(
|
||||
"Kokkos::iter_swap: fence after operation");
|
||||
}
|
||||
} // namespace Impl
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// iter_swap
|
||||
template <class IteratorType1, class IteratorType2>
|
||||
void iter_swap(IteratorType1 a, IteratorType2 b) {
|
||||
Impl::iter_swap_impl(a, b);
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_MOD_SEQ_OPS_INC_ALL_HPP
|
||||
#define KOKKOS_STD_MOD_SEQ_OPS_INC_ALL_HPP
|
||||
|
||||
#include "./modifying_sequence_ops/Kokkos_ModifyingSequenceOperationsSet1.hpp"
|
||||
#include "./modifying_sequence_ops/Kokkos_ModifyingSequenceOperationsSet2.hpp"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
59
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Numeric.hpp
Normal file
59
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Numeric.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERIC_ALL_HPP
|
||||
#define KOKKOS_STD_NUMERIC_ALL_HPP
|
||||
|
||||
#include "./numeric/Kokkos_AdjacentDifference.hpp"
|
||||
|
||||
// contains exclusive_scan, transform_exclusive_scan
|
||||
#include "./numeric/Kokkos_ExclusiveScan.hpp"
|
||||
|
||||
// contains inclusive_scan, transform_inclusive_scan
|
||||
#include "./numeric/Kokkos_InclusiveScan.hpp"
|
||||
|
||||
#include "./numeric/Kokkos_Reduce.hpp"
|
||||
#include "./numeric/Kokkos_TransformReduce.hpp"
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,491 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_PARTITIONING_OPERATIONS_HPP
|
||||
#define KOKKOS_STD_PARTITIONING_OPERATIONS_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "Kokkos_BeginEnd.hpp"
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
#include "Kokkos_ModifyingOperations.hpp"
|
||||
#include "Kokkos_NonModifyingSequenceOperations.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
// -------------------------
|
||||
//
|
||||
// functors
|
||||
//
|
||||
// -------------------------
|
||||
|
||||
template <class IteratorType, class ReducerType, class PredicateType>
|
||||
struct StdIsPartitionedFunctor {
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
|
||||
IteratorType m_first;
|
||||
ReducerType m_reducer;
|
||||
PredicateType m_p;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& redValue) const {
|
||||
const auto predicate_value = m_p(m_first[i]);
|
||||
constexpr index_type m_red_id_min =
|
||||
::Kokkos::reduction_identity<index_type>::min();
|
||||
constexpr index_type m_red_id_max =
|
||||
::Kokkos::reduction_identity<index_type>::max();
|
||||
auto rv = predicate_value ? red_value_type{i, m_red_id_min}
|
||||
: red_value_type{m_red_id_max, i};
|
||||
|
||||
m_reducer.join(redValue, rv);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdIsPartitionedFunctor(IteratorType first, ReducerType reducer,
|
||||
PredicateType p)
|
||||
: m_first(std::move(first)),
|
||||
m_reducer(std::move(reducer)),
|
||||
m_p(std::move(p)) {}
|
||||
};
|
||||
|
||||
template <class IteratorType, class ReducerType, class PredicateType>
|
||||
struct StdPartitionPointFunctor {
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
|
||||
IteratorType m_first;
|
||||
ReducerType m_reducer;
|
||||
PredicateType m_p;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& redValue) const {
|
||||
const auto predicate_value = m_p(m_first[i]);
|
||||
auto rv =
|
||||
predicate_value
|
||||
? red_value_type{::Kokkos::reduction_identity<index_type>::min()}
|
||||
: red_value_type{i};
|
||||
m_reducer.join(redValue, rv);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdPartitionPointFunctor(IteratorType first, ReducerType reducer,
|
||||
PredicateType p)
|
||||
: m_first(std::move(first)),
|
||||
m_reducer(std::move(reducer)),
|
||||
m_p(std::move(p)) {}
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct StdPartitionCopyScalar {
|
||||
ValueType true_count_;
|
||||
ValueType false_count_;
|
||||
|
||||
// Here we implement the copy assignment operators explicitly for consistency
|
||||
// with how the Scalar structs are implemented inside
|
||||
// Kokkos_Parallel_Reduce.hpp.
|
||||
KOKKOS_FUNCTION
|
||||
void operator=(const StdPartitionCopyScalar& other) {
|
||||
true_count_ = other.true_count_;
|
||||
false_count_ = other.false_count_;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator=(const volatile StdPartitionCopyScalar& other) volatile {
|
||||
true_count_ = other.true_count_;
|
||||
false_count_ = other.false_count_;
|
||||
}
|
||||
|
||||
// this is needed for
|
||||
// OpenMPTarget/Kokkos_OpenMPTarget_Parallel.hpp:699:21: error: no viable
|
||||
// overloaded '=' m_returnvalue = 0;
|
||||
//
|
||||
KOKKOS_FUNCTION
|
||||
void operator=(const ValueType value) {
|
||||
true_count_ = value;
|
||||
false_count_ = value;
|
||||
}
|
||||
};
|
||||
|
||||
template <class IndexType, class FirstFrom, class FirstDestTrue,
|
||||
class FirstDestFalse, class PredType>
|
||||
struct StdPartitionCopyFunctor {
|
||||
using value_type = StdPartitionCopyScalar<IndexType>;
|
||||
|
||||
FirstFrom m_first_from;
|
||||
FirstDestTrue m_first_dest_true;
|
||||
FirstDestFalse m_first_dest_false;
|
||||
PredType m_pred;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdPartitionCopyFunctor(FirstFrom first_from, FirstDestTrue first_dest_true,
|
||||
FirstDestFalse first_dest_false, PredType pred)
|
||||
: m_first_from(std::move(first_from)),
|
||||
m_first_dest_true(std::move(first_dest_true)),
|
||||
m_first_dest_false(std::move(first_dest_false)),
|
||||
m_pred(std::move(pred)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
const auto& myval = m_first_from[i];
|
||||
if (final_pass) {
|
||||
if (m_pred(myval)) {
|
||||
m_first_dest_true[update.true_count_] = myval;
|
||||
} else {
|
||||
m_first_dest_false[update.false_count_] = myval;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pred(myval)) {
|
||||
update.true_count_ += 1;
|
||||
} else {
|
||||
update.false_count_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.true_count_ = 0;
|
||||
update.false_count_ = 0;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
update.true_count_ += input.true_count_;
|
||||
update.false_count_ += input.false_count_;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------
|
||||
// is_partitioned_impl
|
||||
// ------------------------------------------
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||
bool is_partitioned_impl(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
PredicateType pred) {
|
||||
// true if all elements in the range [first, last) that satisfy
|
||||
// the predicate "pred" appear before all elements that don't.
|
||||
// Also returns true if [first, last) is empty.
|
||||
// also true if all elements satisfy the predicate.
|
||||
|
||||
// we implement it by finding:
|
||||
// - the max location where predicate is true (max_loc_true)
|
||||
// - the min location where predicate is false (min_loc_false)
|
||||
// so the range is partitioned if max_loc_true < (min_loc_false)
|
||||
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
// trivial case
|
||||
if (first == last) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using reducer_type = StdIsPartitioned<index_type>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
using func_t =
|
||||
StdIsPartitionedFunctor<IteratorType, reducer_type, PredicateType>;
|
||||
|
||||
// run
|
||||
reduction_value_type red_result;
|
||||
reducer_type reducer(red_result);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_t(first, reducer, pred), reducer);
|
||||
|
||||
// fence not needed because reducing into scalar
|
||||
|
||||
// decide and return
|
||||
constexpr index_type red_id_min =
|
||||
::Kokkos::reduction_identity<index_type>::min();
|
||||
constexpr index_type red_id_max =
|
||||
::Kokkos::reduction_identity<index_type>::max();
|
||||
|
||||
if (red_result.max_loc_true != red_id_max &&
|
||||
red_result.min_loc_false != red_id_min) {
|
||||
return red_result.max_loc_true < red_result.min_loc_false;
|
||||
} else if (first + red_result.max_loc_true == --last) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// partition_point_impl
|
||||
// ------------------------------------------
|
||||
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||
IteratorType partition_point_impl(const std::string& label,
|
||||
const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, PredicateType pred) {
|
||||
// locates the end of the first partition, that is, the first
|
||||
// element that does not satisfy p or last if all elements satisfy p.
|
||||
// Implementation below finds the first location where p is false.
|
||||
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
if (first == last) {
|
||||
return first;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
using reducer_type = StdPartitionPoint<index_type>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
using func_t =
|
||||
StdPartitionPointFunctor<IteratorType, reducer_type, PredicateType>;
|
||||
|
||||
// run
|
||||
reduction_value_type red_result;
|
||||
reducer_type reducer(red_result);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_t(first, reducer, pred), reducer);
|
||||
|
||||
// fence not needed because reducing into scalar
|
||||
|
||||
// decide and return
|
||||
if (red_result.min_loc_false ==
|
||||
::Kokkos::reduction_identity<index_type>::min()) {
|
||||
// if all elements are true, return last
|
||||
return last;
|
||||
} else {
|
||||
return first + red_result.min_loc_false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// partition_copy_impl
|
||||
// ------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||
class PredicateType>
|
||||
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType>
|
||||
partition_copy_impl(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType from_first, InputIteratorType from_last,
|
||||
OutputIteratorTrueType to_first_true,
|
||||
OutputIteratorFalseType to_first_false,
|
||||
PredicateType pred) {
|
||||
// impl uses a scan, this is similar how we implemented copy_if
|
||||
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(
|
||||
ex, from_first, to_first_true, to_first_false);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(
|
||||
from_first, to_first_true, to_first_false);
|
||||
Impl::expect_valid_range(from_first, from_last);
|
||||
|
||||
if (from_first == from_last) {
|
||||
return {to_first_true, to_first_false};
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using func_type =
|
||||
StdPartitionCopyFunctor<index_type, InputIteratorType,
|
||||
OutputIteratorTrueType, OutputIteratorFalseType,
|
||||
PredicateType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(from_first, from_last);
|
||||
typename func_type::value_type counts{0, 0};
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(from_first, to_first_true, to_first_false, pred), counts);
|
||||
|
||||
// fence not needed here because of the scan into counts
|
||||
|
||||
return {to_first_true + counts.true_count_,
|
||||
to_first_false + counts.false_count_};
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
// ----------------------
|
||||
// is_partitioned public API
|
||||
// ----------------------
|
||||
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||
bool is_partitioned(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, PredicateType p) {
|
||||
return Impl::is_partitioned_impl(
|
||||
"Kokkos::is_partitioned_iterator_api_default", ex, first, last,
|
||||
std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||
bool is_partitioned(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last, PredicateType p) {
|
||||
return Impl::is_partitioned_impl(label, ex, first, last, std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class PredicateType, class DataType,
|
||||
class... Properties>
|
||||
bool is_partitioned(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
PredicateType p) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::is_partitioned_impl("Kokkos::is_partitioned_view_api_default",
|
||||
ex, cbegin(v), cend(v), std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class PredicateType, class DataType,
|
||||
class... Properties>
|
||||
bool is_partitioned(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
PredicateType p) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
|
||||
return Impl::is_partitioned_impl(label, ex, cbegin(v), cend(v), std::move(p));
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// partition_copy
|
||||
// ----------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||
class PredicateType>
|
||||
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType> partition_copy(
|
||||
const ExecutionSpace& ex, InputIteratorType from_first,
|
||||
InputIteratorType from_last, OutputIteratorTrueType to_first_true,
|
||||
OutputIteratorFalseType to_first_false, PredicateType p) {
|
||||
return Impl::partition_copy_impl(
|
||||
"Kokkos::partition_copy_iterator_api_default", ex, from_first, from_last,
|
||||
to_first_true, to_first_false, std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||
class PredicateType>
|
||||
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType> partition_copy(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType from_first, InputIteratorType from_last,
|
||||
OutputIteratorTrueType to_first_true,
|
||||
OutputIteratorFalseType to_first_false, PredicateType p) {
|
||||
return Impl::partition_copy_impl(label, ex, from_first, from_last,
|
||||
to_first_true, to_first_false, std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class DataType3,
|
||||
class... Properties3, class PredicateType>
|
||||
auto partition_copy(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest_true,
|
||||
const ::Kokkos::View<DataType3, Properties3...>& view_dest_false,
|
||||
PredicateType p) {
|
||||
return Impl::partition_copy_impl("Kokkos::partition_copy_view_api_default",
|
||||
ex, cbegin(view_from), cend(view_from),
|
||||
begin(view_dest_true),
|
||||
begin(view_dest_false), std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class DataType3,
|
||||
class... Properties3, class PredicateType>
|
||||
auto partition_copy(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest_true,
|
||||
const ::Kokkos::View<DataType3, Properties3...>& view_dest_false,
|
||||
PredicateType p) {
|
||||
return Impl::partition_copy_impl(label, ex, cbegin(view_from),
|
||||
cend(view_from), begin(view_dest_true),
|
||||
begin(view_dest_false), std::move(p));
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// partition_point
|
||||
// ----------------------
|
||||
template <class ExecutionSpace, class IteratorType, class UnaryPredicate>
|
||||
IteratorType partition_point(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, UnaryPredicate p) {
|
||||
return Impl::partition_point_impl(
|
||||
"Kokkos::partitioned_point_iterator_api_default", ex, first, last,
|
||||
std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class UnaryPredicate>
|
||||
IteratorType partition_point(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
UnaryPredicate p) {
|
||||
return Impl::partition_point_impl(label, ex, first, last, std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class UnaryPredicate, class DataType,
|
||||
class... Properties>
|
||||
auto partition_point(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
UnaryPredicate p) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
return Impl::partition_point_impl(label, ex, begin(v), end(v), std::move(p));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class UnaryPredicate, class DataType,
|
||||
class... Properties>
|
||||
auto partition_point(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& v,
|
||||
UnaryPredicate p) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||
return Impl::partition_point_impl("Kokkos::partition_point_view_api_default",
|
||||
ex, begin(v), end(v), std::move(p));
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,194 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_RANDOM_ACCESS_ITERATOR_HPP
|
||||
#define KOKKOS_RANDOM_ACCESS_ITERATOR_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <Kokkos_Macros.hpp>
|
||||
#include <Kokkos_View.hpp>
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class T>
|
||||
class RandomAccessIterator;
|
||||
|
||||
template <class DataType, class... Args>
|
||||
class RandomAccessIterator< ::Kokkos::View<DataType, Args...> >
|
||||
: public std::iterator<
|
||||
std::random_access_iterator_tag,
|
||||
typename ::Kokkos::View<DataType, Args...>::value_type, ptrdiff_t,
|
||||
typename ::Kokkos::View<DataType, Args...>::pointer_type,
|
||||
typename ::Kokkos::View<DataType, Args...>::reference_type> {
|
||||
public:
|
||||
using view_type = ::Kokkos::View<DataType, Args...>;
|
||||
using iterator_type = RandomAccessIterator<view_type>;
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = typename view_type::value_type;
|
||||
using reference = typename view_type::reference_type;
|
||||
|
||||
static_assert(view_type::rank == 1 &&
|
||||
(std::is_same<typename view_type::traits::array_layout,
|
||||
Kokkos::LayoutLeft>::value ||
|
||||
std::is_same<typename view_type::traits::array_layout,
|
||||
Kokkos::LayoutRight>::value ||
|
||||
std::is_same<typename view_type::traits::array_layout,
|
||||
Kokkos::LayoutStride>::value),
|
||||
"RandomAccessIterator only supports 1D Views with LayoutLeft, "
|
||||
"LayoutRight, LayoutStride.");
|
||||
|
||||
KOKKOS_DEFAULTED_FUNCTION RandomAccessIterator() = default;
|
||||
|
||||
explicit KOKKOS_FUNCTION RandomAccessIterator(const view_type view)
|
||||
: m_view(view) {}
|
||||
explicit KOKKOS_FUNCTION RandomAccessIterator(const view_type view,
|
||||
ptrdiff_t current_index)
|
||||
: m_view(view), m_current_index(current_index) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type& operator++() {
|
||||
++m_current_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type operator++(int) {
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type& operator--() {
|
||||
--m_current_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type operator--(int) {
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
reference operator[](difference_type n) const {
|
||||
return m_view(m_current_index + n);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type& operator+=(difference_type n) {
|
||||
m_current_index += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type& operator-=(difference_type n) {
|
||||
m_current_index -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type operator+(difference_type n) const {
|
||||
return iterator_type(m_view, m_current_index + n);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
iterator_type operator-(difference_type n) const {
|
||||
return iterator_type(m_view, m_current_index - n);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
difference_type operator-(iterator_type it) const {
|
||||
return m_current_index - it.m_current_index;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator==(iterator_type other) const {
|
||||
return m_current_index == other.m_current_index &&
|
||||
m_view.data() == other.m_view.data();
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator!=(iterator_type other) const {
|
||||
return m_current_index != other.m_current_index ||
|
||||
m_view.data() != other.m_view.data();
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator<(iterator_type other) const {
|
||||
return m_current_index < other.m_current_index;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator<=(iterator_type other) const {
|
||||
return m_current_index <= other.m_current_index;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator>(iterator_type other) const {
|
||||
return m_current_index > other.m_current_index;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool operator>=(iterator_type other) const {
|
||||
return m_current_index >= other.m_current_index;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
reference operator*() const { return m_view(m_current_index); }
|
||||
|
||||
private:
|
||||
view_type m_view;
|
||||
ptrdiff_t m_current_index = 0;
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,118 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_ReducerWithArbitraryJoinerNoNeutralElement_hpp_
|
||||
#define KOKKOS_STD_ReducerWithArbitraryJoinerNoNeutralElement_hpp_
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
// This reducer is here and not where all other reducers are
|
||||
// because it is inside Impl and also because it would not work
|
||||
// for OpenMPTarget backend. We can move this later.
|
||||
|
||||
template <class Scalar, class JoinerType, class Space = HostSpace>
|
||||
struct ReducerWithArbitraryJoinerNoNeutralElement {
|
||||
using scalar_type = typename std::remove_cv<Scalar>::type;
|
||||
|
||||
public:
|
||||
// Required
|
||||
using reducer =
|
||||
ReducerWithArbitraryJoinerNoNeutralElement<Scalar, JoinerType, Space>;
|
||||
using value_type = ValueWrapperForNoNeutralElement<scalar_type>;
|
||||
|
||||
using result_view_type = Kokkos::View<value_type, Space>;
|
||||
|
||||
private:
|
||||
JoinerType m_joiner;
|
||||
result_view_type m_value;
|
||||
bool m_references_scalar_v;
|
||||
|
||||
public:
|
||||
KOKKOS_FUNCTION
|
||||
ReducerWithArbitraryJoinerNoNeutralElement(value_type& value_,
|
||||
JoinerType joiner_)
|
||||
: m_joiner(joiner_), m_value(&value_), m_references_scalar_v(true) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
ReducerWithArbitraryJoinerNoNeutralElement(const result_view_type& value_,
|
||||
JoinerType joiner_)
|
||||
: m_joiner(joiner_), m_value(value_), m_references_scalar_v(false) {}
|
||||
|
||||
// Required
|
||||
KOKKOS_FUNCTION
|
||||
void join(value_type& dest, const value_type& src) const {
|
||||
dest.val = m_joiner(dest.val, src.val);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& dest, const volatile value_type& src) const {
|
||||
dest.val = m_joiner(dest.val, src.val);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& val) const {
|
||||
// I cannot call reduction_identity, so need to default this
|
||||
val = {};
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
value_type& reference() const { return *m_value.data(); }
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
result_view_type view() const { return m_value; }
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
bool references_scalar() const { return m_references_scalar_v; }
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,378 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_SORTING_OPERATIONS_HPP
|
||||
#define KOKKOS_STD_SORTING_OPERATIONS_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "Kokkos_BeginEnd.hpp"
|
||||
#include "Kokkos_Constraints.hpp"
|
||||
#include "Kokkos_NonModifyingSequenceOperations.hpp"
|
||||
#include "Kokkos_HelperPredicates.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
// ------------------
|
||||
//
|
||||
// functors
|
||||
//
|
||||
// ------------------
|
||||
|
||||
template <class IteratorType, class IndicatorViewType, class ComparatorType>
|
||||
struct StdIsSortedUntilFunctor {
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
IteratorType m_first;
|
||||
IndicatorViewType m_indicator;
|
||||
ComparatorType m_comparator;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, int& update, const bool final) const {
|
||||
const auto& val_i = m_first[i];
|
||||
const auto& val_ip1 = m_first[i + 1];
|
||||
|
||||
if (m_comparator(val_ip1, val_i)) {
|
||||
++update;
|
||||
}
|
||||
|
||||
if (final) {
|
||||
m_indicator(i) = update;
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdIsSortedUntilFunctor(IteratorType _first1, IndicatorViewType indicator,
|
||||
ComparatorType comparator)
|
||||
: m_first(std::move(_first1)),
|
||||
m_indicator(std::move(indicator)),
|
||||
m_comparator(std::move(comparator)) {}
|
||||
};
|
||||
|
||||
template <class IteratorType, class ComparatorType>
|
||||
struct StdIsSortedFunctor {
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
IteratorType m_first;
|
||||
ComparatorType m_comparator;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, std::size_t& update) const {
|
||||
const auto& val_i = m_first[i];
|
||||
const auto& val_ip1 = m_first[i + 1];
|
||||
|
||||
if (m_comparator(val_ip1, val_i)) {
|
||||
++update;
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdIsSortedFunctor(IteratorType _first1, ComparatorType comparator)
|
||||
: m_first(std::move(_first1)), m_comparator(std::move(comparator)) {}
|
||||
};
|
||||
|
||||
// ------------------------------------------
|
||||
// is_sorted_until_impl
|
||||
// ------------------------------------------
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
IteratorType is_sorted_until_impl(const std::string& label,
|
||||
const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ComparatorType comp) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
|
||||
// trivial case
|
||||
if (num_elements <= 1) {
|
||||
return last;
|
||||
}
|
||||
|
||||
/*
|
||||
use scan and a helper "indicator" view
|
||||
such that we scan the data and fill the indicator with
|
||||
partial sum that is always 0 unless we find a pair that
|
||||
breaks the sorting, so in that case the indicator will
|
||||
have a 1 starting at the location where the sorting breaks.
|
||||
So finding that 1 means finding the location we want.
|
||||
*/
|
||||
|
||||
// aliases
|
||||
using indicator_value_type = std::size_t;
|
||||
using indicator_view_type =
|
||||
::Kokkos::View<indicator_value_type*, ExecutionSpace>;
|
||||
using functor_type =
|
||||
StdIsSortedUntilFunctor<IteratorType, indicator_view_type,
|
||||
ComparatorType>;
|
||||
|
||||
// do scan
|
||||
// use num_elements-1 because each index handles i and i+1
|
||||
const auto num_elements_minus_one = num_elements - 1;
|
||||
indicator_view_type indicator("is_sorted_until_indicator_helper",
|
||||
num_elements_minus_one);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements_minus_one),
|
||||
functor_type(first, indicator, std::move(comp)));
|
||||
|
||||
// try to find the first sentinel value, which indicates
|
||||
// where the sorting condition breaks
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
constexpr indicator_value_type sentinel_value = 1;
|
||||
auto r =
|
||||
KE::find(ex, KE::cbegin(indicator), KE::cend(indicator), sentinel_value);
|
||||
const auto shift = r - ::Kokkos::Experimental::cbegin(indicator);
|
||||
|
||||
return first + (shift + 1);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
IteratorType is_sorted_until_impl(const std::string& label,
|
||||
const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
using value_type = typename IteratorType::value_type;
|
||||
using pred_t = Impl::StdAlgoLessThanBinaryPredicate<value_type>;
|
||||
return is_sorted_until_impl(label, ex, first, last, pred_t());
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// is_sorted_impl
|
||||
// ------------------------------------------
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
bool is_sorted_impl(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ComparatorType comp) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
if (num_elements <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// use num_elements-1 because each index handles i and i+1
|
||||
const auto num_elements_minus_one = num_elements - 1;
|
||||
using functor_type = StdIsSortedFunctor<IteratorType, ComparatorType>;
|
||||
|
||||
// result is incremented by one if sorting breaks at index i
|
||||
std::size_t result = 0;
|
||||
::Kokkos::parallel_reduce(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements_minus_one),
|
||||
functor_type(first, std::move(comp)), result);
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
bool is_sorted_impl(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
using value_type = typename IteratorType::value_type;
|
||||
using pred_t = Impl::StdAlgoLessThanBinaryPredicate<value_type>;
|
||||
return is_sorted_impl(label, ex, first, last, pred_t());
|
||||
}
|
||||
|
||||
} // namespace Impl
|
||||
|
||||
// ----------------------------------
|
||||
// is_sorted_until public API
|
||||
// ----------------------------------
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
IteratorType is_sorted_until(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::is_sorted_until_impl(
|
||||
"Kokkos::is_sorted_until_iterator_api_default", ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
IteratorType is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
return Impl::is_sorted_until_impl(label, ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto is_sorted_until(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_until_impl("Kokkos::is_sorted_until_view_api_default",
|
||||
ex, KE::begin(view), KE::end(view));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_until_impl(label, ex, KE::begin(view), KE::end(view));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
IteratorType is_sorted_until(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
return Impl::is_sorted_until_impl(
|
||||
"Kokkos::is_sorted_until_iterator_api_default", ex, first, last,
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
IteratorType is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::is_sorted_until_impl(label, ex, first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ComparatorType>
|
||||
auto is_sorted_until(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_until_impl("Kokkos::is_sorted_until_view_api_default",
|
||||
ex, KE::begin(view), KE::end(view),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ComparatorType>
|
||||
auto is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_until_impl(label, ex, KE::begin(view), KE::end(view),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
// is_sorted public API
|
||||
// ----------------------------------
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
bool is_sorted(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::is_sorted_impl("Kokkos::is_sorted_iterator_api_default", ex,
|
||||
first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last) {
|
||||
return Impl::is_sorted_impl(label, ex, first, last);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
bool is_sorted(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_impl("Kokkos::is_sorted_view_api_default", ex,
|
||||
KE::cbegin(view), KE::cend(view));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_impl(label, ex, KE::cbegin(view), KE::cend(view));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
bool is_sorted(const ExecutionSpace& ex, IteratorType first, IteratorType last,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
return Impl::is_sorted_impl("Kokkos::is_sorted_iterator_api_default", ex,
|
||||
first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
return Impl::is_sorted_impl(label, ex, first, last, std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ComparatorType>
|
||||
bool is_sorted(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_impl("Kokkos::is_sorted_view_api_default", ex,
|
||||
KE::cbegin(view), KE::cend(view),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ComparatorType>
|
||||
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ComparatorType comp) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::is_sorted_impl(label, ex, KE::cbegin(view), KE::cend(view),
|
||||
std::move(comp));
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_VALUE_WRAPPER_FOR_NO_NEUTRAL_ELEMENT_HPP
|
||||
#define KOKKOS_STD_VALUE_WRAPPER_FOR_NO_NEUTRAL_ELEMENT_HPP
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
//
|
||||
// scalar wrapper used for reductions and scans
|
||||
// when we don't have neutral element
|
||||
//
|
||||
template <class Scalar>
|
||||
struct ValueWrapperForNoNeutralElement {
|
||||
Scalar val;
|
||||
bool is_initial = true;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator=(const ValueWrapperForNoNeutralElement& rhs) {
|
||||
val = rhs.val;
|
||||
is_initial = rhs.is_initial;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator=(const volatile ValueWrapperForNoNeutralElement& rhs) volatile {
|
||||
val = rhs.val;
|
||||
is_initial = rhs.is_initial;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,279 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERICS_ADJACENT_DIFFERENCE_HPP
|
||||
#define KOKKOS_STD_NUMERICS_ADJACENT_DIFFERENCE_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "../Kokkos_BeginEnd.hpp"
|
||||
#include "../Kokkos_Constraints.hpp"
|
||||
#include "../Kokkos_Distance.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// functors
|
||||
//
|
||||
// ------------------------
|
||||
template <class ValueType1, class ValueType2, class RetType = ValueType2>
|
||||
struct StdAdjacentDifferenceDefaultBinaryOpFunctor {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr RetType operator()(const ValueType1& a, const ValueType2& b) const {
|
||||
return a - b;
|
||||
}
|
||||
};
|
||||
|
||||
template <class InputIteratorType, class OutputIteratorType,
|
||||
class BinaryOperator>
|
||||
struct StdAdjacentDiffFunctor {
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
|
||||
const InputIteratorType m_first_from;
|
||||
const OutputIteratorType m_first_dest;
|
||||
BinaryOperator m_op;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i) const {
|
||||
const auto& my_value = m_first_from[i];
|
||||
if (i == 0) {
|
||||
m_first_dest[i] = my_value;
|
||||
} else {
|
||||
const auto& left_value = m_first_from[i - 1];
|
||||
m_first_dest[i] = m_op(my_value, left_value);
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdAdjacentDiffFunctor(InputIteratorType first_from,
|
||||
OutputIteratorType first_dest, BinaryOperator op)
|
||||
: m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)),
|
||||
m_op(std::move(op)) {}
|
||||
};
|
||||
|
||||
// ------------------------------------------
|
||||
// adjacent_difference_impl
|
||||
// ------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp>
|
||||
OutputIteratorType adjacent_difference_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
InputIteratorType first_from,
|
||||
InputIteratorType last_from,
|
||||
OutputIteratorType first_dest,
|
||||
BinaryOp bin_op) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
if (first_from == last_from) {
|
||||
return first_dest;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using value_type = typename OutputIteratorType::value_type;
|
||||
using aux_view_type = ::Kokkos::View<value_type*, ExecutionSpace>;
|
||||
using functor_t =
|
||||
StdAdjacentDiffFunctor<InputIteratorType, OutputIteratorType, BinaryOp>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
aux_view_type aux_view("aux_view", num_elements);
|
||||
::Kokkos::parallel_for(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
functor_t(first_from, first_dest, bin_op));
|
||||
ex.fence("Kokkos::adjacent_difference: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// public API
|
||||
//
|
||||
// ------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType>
|
||||
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
adjacent_difference(const ExecutionSpace& ex, InputIteratorType first_from,
|
||||
InputIteratorType last_from,
|
||||
OutputIteratorType first_dest) {
|
||||
using value_type1 = typename InputIteratorType::value_type;
|
||||
using value_type2 = typename OutputIteratorType::value_type;
|
||||
using binary_op =
|
||||
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||
value_type2>;
|
||||
return Impl::adjacent_difference_impl(
|
||||
"Kokkos::adjacent_difference_iterator_api", ex, first_from, last_from,
|
||||
first_dest, binary_op());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp>
|
||||
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
adjacent_difference(const ExecutionSpace& ex, InputIteratorType first_from,
|
||||
InputIteratorType last_from, OutputIteratorType first_dest,
|
||||
BinaryOp bin_op) {
|
||||
return Impl::adjacent_difference_impl(
|
||||
"Kokkos::adjacent_difference_iterator_api", ex, first_from, last_from,
|
||||
first_dest, bin_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType>
|
||||
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
adjacent_difference(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest) {
|
||||
using value_type1 = typename InputIteratorType::value_type;
|
||||
using value_type2 = typename OutputIteratorType::value_type;
|
||||
using binary_op =
|
||||
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||
value_type2>;
|
||||
return Impl::adjacent_difference_impl(label, ex, first_from, last_from,
|
||||
first_dest, binary_op());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp>
|
||||
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
adjacent_difference(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, BinaryOp bin_op) {
|
||||
return Impl::adjacent_difference_impl(label, ex, first_from, last_from,
|
||||
first_dest, bin_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2>
|
||||
auto adjacent_difference(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
|
||||
using view_type1 = ::Kokkos::View<DataType1, Properties1...>;
|
||||
using view_type2 = ::Kokkos::View<DataType2, Properties2...>;
|
||||
using value_type1 = typename view_type1::value_type;
|
||||
using value_type2 = typename view_type2::value_type;
|
||||
using binary_op =
|
||||
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||
value_type2>;
|
||||
return Impl::adjacent_difference_impl(
|
||||
"Kokkos::adjacent_difference_view_api", ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from), KE::begin(view_dest), binary_op());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp>
|
||||
auto adjacent_difference(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp bin_op) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
return Impl::adjacent_difference_impl(
|
||||
"Kokkos::adjacent_difference_view_api", ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from), KE::begin(view_dest), bin_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2>
|
||||
auto adjacent_difference(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
|
||||
using view_type1 = ::Kokkos::View<DataType1, Properties1...>;
|
||||
using view_type2 = ::Kokkos::View<DataType2, Properties2...>;
|
||||
using value_type1 = typename view_type1::value_type;
|
||||
using value_type2 = typename view_type2::value_type;
|
||||
using binary_op =
|
||||
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||
value_type2>;
|
||||
|
||||
return Impl::adjacent_difference_impl(label, ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from),
|
||||
KE::begin(view_dest), binary_op());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp>
|
||||
auto adjacent_difference(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp bin_op) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
return Impl::adjacent_difference_impl(label, ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from),
|
||||
KE::begin(view_dest), bin_op);
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,517 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERICS_EXCLUSIVE_SCAN_HPP
|
||||
#define KOKKOS_STD_NUMERICS_EXCLUSIVE_SCAN_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "../Kokkos_BeginEnd.hpp"
|
||||
#include "../Kokkos_Constraints.hpp"
|
||||
#include "../Kokkos_Distance.hpp"
|
||||
#include "../Kokkos_ModifyingOperations.hpp"
|
||||
#include "../Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||
#include "Kokkos_IdentityReferenceUnaryFunctor.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||
class FirstDest>
|
||||
struct ExclusiveScanDefaultFunctor {
|
||||
using execution_space = ExeSpace;
|
||||
using value_type =
|
||||
::Kokkos::Experimental::Impl::ValueWrapperForNoNeutralElement<ValueType>;
|
||||
|
||||
ValueType m_init_value;
|
||||
FirstFrom m_first_from;
|
||||
FirstDest m_first_dest;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
ExclusiveScanDefaultFunctor(ValueType init, FirstFrom first_from,
|
||||
FirstDest first_dest)
|
||||
: m_init_value(std::move(init)),
|
||||
m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
if (final_pass) {
|
||||
if (i == 0) {
|
||||
m_first_dest[i] = m_init_value;
|
||||
} else {
|
||||
m_first_dest[i] = update.val + m_init_value;
|
||||
}
|
||||
}
|
||||
|
||||
const auto tmp = value_type{m_first_from[i], false};
|
||||
this->join(update, tmp);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.val = {};
|
||||
update.is_initial = true;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
if (update.is_initial) {
|
||||
update.val = input.val;
|
||||
update.is_initial = false;
|
||||
} else {
|
||||
update.val = update.val + input.val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||
struct TransformExclusiveScanFunctor {
|
||||
using execution_space = ExeSpace;
|
||||
using value_type =
|
||||
::Kokkos::Experimental::Impl::ValueWrapperForNoNeutralElement<ValueType>;
|
||||
|
||||
ValueType m_init_value;
|
||||
FirstFrom m_first_from;
|
||||
FirstDest m_first_dest;
|
||||
BinaryOpType m_binary_op;
|
||||
UnaryOpType m_unary_op;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
TransformExclusiveScanFunctor(ValueType init, FirstFrom first_from,
|
||||
FirstDest first_dest, BinaryOpType bop,
|
||||
UnaryOpType uop)
|
||||
: m_init_value(std::move(init)),
|
||||
m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)),
|
||||
m_binary_op(std::move(bop)),
|
||||
m_unary_op(std::move(uop)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
if (final_pass) {
|
||||
if (i == 0) {
|
||||
// for both ExclusiveScan and TransformExclusiveScan,
|
||||
// init is unmodified
|
||||
m_first_dest[i] = m_init_value;
|
||||
} else {
|
||||
m_first_dest[i] = m_binary_op(update.val, m_init_value);
|
||||
}
|
||||
}
|
||||
|
||||
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||
this->join(update, tmp);
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.val = {};
|
||||
update.is_initial = true;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
if (update.is_initial) {
|
||||
update.val = input.val;
|
||||
} else {
|
||||
update.val = m_binary_op(update.val, input.val);
|
||||
}
|
||||
update.is_initial = false;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------
|
||||
// exclusive_scan_custom_op_impl
|
||||
// --------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||
OutputIteratorType exclusive_scan_custom_op_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, ValueType init_value, BinaryOpType bop) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<ValueType>;
|
||||
using func_type =
|
||||
TransformExclusiveScanFunctor<ExecutionSpace, index_type, ValueType,
|
||||
InputIteratorType, OutputIteratorType,
|
||||
BinaryOpType, unary_op_type>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(init_value, first_from, first_dest, bop, unary_op_type()));
|
||||
ex.fence("Kokkos::exclusive_scan_custom_op: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// transform_exclusive_scan_impl
|
||||
// --------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||
class UnaryOpType>
|
||||
OutputIteratorType transform_exclusive_scan_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, ValueType init_value, BinaryOpType bop,
|
||||
UnaryOpType uop) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using func_type =
|
||||
TransformExclusiveScanFunctor<ExecutionSpace, index_type, ValueType,
|
||||
InputIteratorType, OutputIteratorType,
|
||||
BinaryOpType, UnaryOpType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(init_value, first_from, first_dest, bop, uop));
|
||||
ex.fence("Kokkos::transform_exclusive_scan: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// exclusive_scan_default_op_impl
|
||||
// --------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType>
|
||||
OutputIteratorType exclusive_scan_default_op_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
InputIteratorType first_from,
|
||||
InputIteratorType last_from,
|
||||
OutputIteratorType first_dest,
|
||||
ValueType init_value) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// does it make sense to do this static_assert too?
|
||||
// using input_iterator_value_type = typename InputIteratorType::value_type;
|
||||
// static_assert
|
||||
// (std::is_convertible<std::remove_cv_t<input_iterator_value_type>,
|
||||
// ValueType>::value,
|
||||
// "exclusive_scan: InputIteratorType::value_type not convertible to
|
||||
// ValueType");
|
||||
|
||||
// we are unnecessarily duplicating code, but this is on purpose
|
||||
// so that we can use the default_op for OpenMPTarget.
|
||||
// Originally, I had this implemented as:
|
||||
// '''
|
||||
// using bop_type = StdExclusiveScanDefaultJoinFunctor<ValueType>;
|
||||
// call exclusive_scan_custom_op_impl(..., bop_type());
|
||||
// '''
|
||||
// which avoids duplicating the functors, but for OpenMPTarget
|
||||
// I cannot use a custom binary op.
|
||||
// This is the same problem that occurs for reductions.
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using func_type =
|
||||
ExclusiveScanDefaultFunctor<ExecutionSpace, index_type, ValueType,
|
||||
InputIteratorType, OutputIteratorType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(init_value, first_from, first_dest));
|
||||
ex.fence("Kokkos::exclusive_scan_default_op: fence after operation");
|
||||
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
///////////////////////////////
|
||||
//
|
||||
// exclusive scan API
|
||||
//
|
||||
///////////////////////////////
|
||||
|
||||
// overload set 1
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
ValueType init_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::exclusive_scan_default_op_impl(
|
||||
"Kokkos::exclusive_scan_default_functors_iterator_api", ex, first, last,
|
||||
first_dest, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, ValueType init_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::exclusive_scan_default_op_impl(label, ex, first, last,
|
||||
first_dest, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType>
|
||||
auto exclusive_scan(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::exclusive_scan_default_op_impl(
|
||||
"Kokkos::exclusive_scan_default_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType>
|
||||
auto exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::exclusive_scan_default_op_impl(label, ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from),
|
||||
KE::begin(view_dest), init_value);
|
||||
}
|
||||
|
||||
// overload set 2
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
ValueType init_value, BinaryOpType bop) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::exclusive_scan_custom_op_impl(
|
||||
"Kokkos::exclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||
first_dest, init_value, bop);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, ValueType init_value,
|
||||
BinaryOpType bop) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::exclusive_scan_custom_op_impl(label, ex, first, last, first_dest,
|
||||
init_value, bop);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryOpType>
|
||||
auto exclusive_scan(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value, BinaryOpType bop) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::exclusive_scan_custom_op_impl(
|
||||
"Kokkos::exclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
init_value, bop);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryOpType>
|
||||
auto exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value, BinaryOpType bop) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::exclusive_scan_custom_op_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), init_value, bop);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// transform_exclusive_scan public API
|
||||
//
|
||||
//////////////////////////////////////
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||
class UnaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
ValueType init_value, BinaryOpType binary_op,
|
||||
UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::transform_exclusive_scan_impl(
|
||||
"Kokkos::transform_exclusive_scan_custom_functors_iterator_api", ex,
|
||||
first, last, first_dest, init_value, binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||
class UnaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, ValueType init_value,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
return Impl::transform_exclusive_scan_impl(label, ex, first, last, first_dest,
|
||||
init_value, binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryOpType, class UnaryOpType>
|
||||
auto transform_exclusive_scan(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value, BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_exclusive_scan_impl(
|
||||
"Kokkos::transform_exclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
init_value, binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryOpType, class UnaryOpType>
|
||||
auto transform_exclusive_scan(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
ValueType init_value, BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_exclusive_scan_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), init_value, binary_op, unary_op);
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERIC_IDENTITY_REFERENCE_UNARY_FUNCTOR_HPP
|
||||
#define KOKKOS_STD_NUMERIC_IDENTITY_REFERENCE_UNARY_FUNCTOR_HPP
|
||||
|
||||
#include <Kokkos_Macros.hpp>
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class ValueType>
|
||||
struct StdNumericScanIdentityReferenceUnaryFunctor {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr const ValueType& operator()(const ValueType& a) const { return a; }
|
||||
};
|
||||
|
||||
} // namespace Impl
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,699 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERICS_INCLUSIVE_SCAN_HPP
|
||||
#define KOKKOS_STD_NUMERICS_INCLUSIVE_SCAN_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "../Kokkos_BeginEnd.hpp"
|
||||
#include "../Kokkos_Constraints.hpp"
|
||||
#include "../Kokkos_Distance.hpp"
|
||||
#include "../Kokkos_ModifyingOperations.hpp"
|
||||
#include "../Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||
#include "Kokkos_IdentityReferenceUnaryFunctor.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||
class FirstDest>
|
||||
struct InclusiveScanDefaultFunctor {
|
||||
using execution_space = ExeSpace;
|
||||
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||
|
||||
FirstFrom m_first_from;
|
||||
FirstDest m_first_dest;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
InclusiveScanDefaultFunctor(FirstFrom first_from, FirstDest first_dest)
|
||||
: m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
const auto tmp = value_type{m_first_from[i], false};
|
||||
this->join(update, tmp);
|
||||
|
||||
if (final_pass) {
|
||||
m_first_dest[i] = update.val;
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.val = {};
|
||||
update.is_initial = true;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
if (update.is_initial) {
|
||||
update.val = input.val;
|
||||
} else {
|
||||
update.val = update.val + input.val;
|
||||
}
|
||||
update.is_initial = false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||
struct TransformInclusiveScanNoInitValueFunctor {
|
||||
using execution_space = ExeSpace;
|
||||
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||
|
||||
FirstFrom m_first_from;
|
||||
FirstDest m_first_dest;
|
||||
BinaryOpType m_binary_op;
|
||||
UnaryOpType m_unary_op;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
TransformInclusiveScanNoInitValueFunctor(FirstFrom first_from,
|
||||
FirstDest first_dest,
|
||||
BinaryOpType bop, UnaryOpType uop)
|
||||
: m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)),
|
||||
m_binary_op(std::move(bop)),
|
||||
m_unary_op(std::move(uop)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||
this->join(update, tmp);
|
||||
if (final_pass) {
|
||||
m_first_dest[i] = update.val;
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.val = {};
|
||||
update.is_initial = true;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
if (update.is_initial) {
|
||||
update.val = input.val;
|
||||
} else {
|
||||
update.val = m_binary_op(update.val, input.val);
|
||||
}
|
||||
update.is_initial = false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||
struct TransformInclusiveScanWithInitValueFunctor {
|
||||
using execution_space = ExeSpace;
|
||||
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||
|
||||
FirstFrom m_first_from;
|
||||
FirstDest m_first_dest;
|
||||
BinaryOpType m_binary_op;
|
||||
UnaryOpType m_unary_op;
|
||||
ValueType m_init;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
TransformInclusiveScanWithInitValueFunctor(FirstFrom first_from,
|
||||
FirstDest first_dest,
|
||||
BinaryOpType bop, UnaryOpType uop,
|
||||
ValueType init)
|
||||
: m_first_from(std::move(first_from)),
|
||||
m_first_dest(std::move(first_dest)),
|
||||
m_binary_op(std::move(bop)),
|
||||
m_unary_op(std::move(uop)),
|
||||
m_init(std::move(init)) {}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, value_type& update,
|
||||
const bool final_pass) const {
|
||||
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||
this->join(update, tmp);
|
||||
|
||||
if (final_pass) {
|
||||
m_first_dest[i] = m_binary_op(update.val, m_init);
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void init(value_type& update) const {
|
||||
update.val = {};
|
||||
update.is_initial = true;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void join(volatile value_type& update,
|
||||
volatile const value_type& input) const {
|
||||
if (update.is_initial) {
|
||||
update.val = input.val;
|
||||
} else {
|
||||
update.val = m_binary_op(update.val, input.val);
|
||||
}
|
||||
update.is_initial = false;
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// inclusive_scan_default_op_impl
|
||||
// -------------------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType>
|
||||
OutputIteratorType inclusive_scan_default_op_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using value_type =
|
||||
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||
using func_type =
|
||||
InclusiveScanDefaultFunctor<ExecutionSpace, index_type, value_type,
|
||||
InputIteratorType, OutputIteratorType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(first_from, first_dest));
|
||||
ex.fence("Kokkos::inclusive_scan_default_op: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// inclusive_scan_custom_binary_op_impl
|
||||
// -------------------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType>
|
||||
OutputIteratorType inclusive_scan_custom_binary_op_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, BinaryOpType binary_op) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using value_type =
|
||||
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<value_type>;
|
||||
using func_type = TransformInclusiveScanNoInitValueFunctor<
|
||||
ExecutionSpace, index_type, value_type, InputIteratorType,
|
||||
OutputIteratorType, BinaryOpType, unary_op_type>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(first_from, first_dest, binary_op, unary_op_type()));
|
||||
ex.fence("Kokkos::inclusive_scan_custom_binary_op: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// inclusive_scan_custom_binary_op_impl with init_value
|
||||
// -------------------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class ValueType>
|
||||
OutputIteratorType inclusive_scan_custom_binary_op_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||
ValueType init_value) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<ValueType>;
|
||||
using func_type = TransformInclusiveScanWithInitValueFunctor<
|
||||
ExecutionSpace, index_type, ValueType, InputIteratorType,
|
||||
OutputIteratorType, BinaryOpType, unary_op_type>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(first_from, first_dest, binary_op,
|
||||
unary_op_type(), init_value));
|
||||
ex.fence("Kokkos::inclusive_scan_custom_binary_op: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// transform_inclusive_scan_impl without init_value
|
||||
// -------------------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||
OutputIteratorType transform_inclusive_scan_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
InputIteratorType first_from,
|
||||
InputIteratorType last_from,
|
||||
OutputIteratorType first_dest,
|
||||
BinaryOpType binary_op,
|
||||
UnaryOpType unary_op) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using value_type =
|
||||
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||
using func_type = TransformInclusiveScanNoInitValueFunctor<
|
||||
ExecutionSpace, index_type, value_type, InputIteratorType,
|
||||
OutputIteratorType, BinaryOpType, UnaryOpType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(first_from, first_dest, binary_op, unary_op));
|
||||
ex.fence("Kokkos::transform_inclusive_scan: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// transform_inclusive_scan_impl with init_value
|
||||
// -------------------------------------------------------------
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||
class ValueType>
|
||||
OutputIteratorType transform_inclusive_scan_impl(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first_from, InputIteratorType last_from,
|
||||
OutputIteratorType first_dest, BinaryOpType binary_op, UnaryOpType unary_op,
|
||||
ValueType init_value) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||
first_dest);
|
||||
Impl::expect_valid_range(first_from, last_from);
|
||||
|
||||
// aliases
|
||||
using index_type = typename InputIteratorType::difference_type;
|
||||
using func_type = TransformInclusiveScanWithInitValueFunctor<
|
||||
ExecutionSpace, index_type, ValueType, InputIteratorType,
|
||||
OutputIteratorType, BinaryOpType, UnaryOpType>;
|
||||
|
||||
// run
|
||||
const auto num_elements =
|
||||
Kokkos::Experimental::distance(first_from, last_from);
|
||||
::Kokkos::parallel_scan(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
func_type(first_from, first_dest, binary_op, unary_op, init_value));
|
||||
ex.fence("Kokkos::transform_inclusive_scan: fence after operation");
|
||||
|
||||
// return
|
||||
return first_dest + num_elements;
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
///////////////////////////////
|
||||
//
|
||||
// inclusive scan API
|
||||
//
|
||||
///////////////////////////////
|
||||
|
||||
// overload set 1
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest) {
|
||||
return Impl::inclusive_scan_default_op_impl(
|
||||
"Kokkos::inclusive_scan_default_functors_iterator_api", ex, first, last,
|
||||
first_dest);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest) {
|
||||
return Impl::inclusive_scan_default_op_impl(label, ex, first, last,
|
||||
first_dest);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2>
|
||||
auto inclusive_scan(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_default_op_impl(
|
||||
"Kokkos::inclusive_scan_default_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2>
|
||||
auto inclusive_scan(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_default_op_impl(label, ex, KE::cbegin(view_from),
|
||||
KE::cend(view_from),
|
||||
KE::begin(view_dest));
|
||||
}
|
||||
|
||||
// overload set 2 (accepting custom binary op)
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
BinaryOp binary_op) {
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
"Kokkos::inclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||
first_dest, binary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, BinaryOp binary_op) {
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(label, ex, first, last,
|
||||
first_dest, binary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp>
|
||||
auto inclusive_scan(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp binary_op) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
"Kokkos::inclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
binary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp>
|
||||
auto inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp binary_op) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), binary_op);
|
||||
}
|
||||
|
||||
// overload set 3
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp, class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
BinaryOp binary_op, ValueType init_value) {
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
"Kokkos::inclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||
first_dest, binary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOp, class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, BinaryOp binary_op,
|
||||
ValueType init_value) {
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
label, ex, first, last, first_dest, binary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp,
|
||||
class ValueType>
|
||||
auto inclusive_scan(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp binary_op, ValueType init_value) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
"Kokkos::inclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
binary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOp,
|
||||
class ValueType>
|
||||
auto inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOp binary_op, ValueType init_value) {
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), binary_op, init_value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// transform_inclusive_scan public API
|
||||
//
|
||||
//////////////////////////////////////
|
||||
|
||||
// overload set 1 (no init value)
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
"Kokkos::transform_inclusive_scan_custom_functors_iterator_api", ex,
|
||||
first, last, first_dest, binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||
UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
|
||||
return Impl::transform_inclusive_scan_impl(label, ex, first, last, first_dest,
|
||||
binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOpType,
|
||||
class UnaryOpType>
|
||||
auto transform_inclusive_scan(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
"Kokkos::transform_inclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
binary_op, unary_op);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOpType,
|
||||
class UnaryOpType>
|
||||
auto transform_inclusive_scan(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), binary_op, unary_op);
|
||||
}
|
||||
|
||||
// overload set 2 (init value)
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||
class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||
InputIteratorType last, OutputIteratorType first_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op,
|
||||
ValueType init_value) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
"Kokkos::transform_inclusive_scan_custom_functors_iterator_api", ex,
|
||||
first, last, first_dest, binary_op, unary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class InputIteratorType,
|
||||
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||
class ValueType>
|
||||
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||
InputIteratorType, OutputIteratorType>::value,
|
||||
OutputIteratorType>
|
||||
transform_inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||
InputIteratorType first, InputIteratorType last,
|
||||
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||
UnaryOpType unary_op, ValueType init_value) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
return Impl::transform_inclusive_scan_impl(label, ex, first, last, first_dest,
|
||||
binary_op, unary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOpType,
|
||||
class UnaryOpType, class ValueType>
|
||||
auto transform_inclusive_scan(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op, ValueType init_value) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
"Kokkos::transform_inclusive_scan_custom_functors_view_api", ex,
|
||||
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||
binary_op, unary_op, init_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class BinaryOpType,
|
||||
class UnaryOpType, class ValueType>
|
||||
auto transform_inclusive_scan(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||
BinaryOpType binary_op, UnaryOpType unary_op, ValueType init_value) {
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
return Impl::transform_inclusive_scan_impl(
|
||||
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||
KE::begin(view_dest), binary_op, unary_op, init_value);
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,326 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERICS_REDUCE_HPP
|
||||
#define KOKKOS_STD_NUMERICS_REDUCE_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "../Kokkos_BeginEnd.hpp"
|
||||
#include "../Kokkos_Constraints.hpp"
|
||||
#include "../Kokkos_Distance.hpp"
|
||||
#include "../Kokkos_ModifyingOperations.hpp"
|
||||
#include "../Kokkos_ReducerWithArbitraryJoinerNoNeutralElement.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
template <class ValueType>
|
||||
struct StdReduceDefaultJoinFunctor {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr ValueType operator()(const volatile ValueType& a,
|
||||
const volatile ValueType& b) const {
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
template <class IteratorType, class ReducerType>
|
||||
struct StdReduceFunctor {
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
|
||||
const IteratorType m_first;
|
||||
const ReducerType m_reducer;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& red_value) const {
|
||||
auto tmp_wrapped_value = red_value_type{m_first[i], false};
|
||||
|
||||
if (red_value.is_initial) {
|
||||
red_value = tmp_wrapped_value;
|
||||
} else {
|
||||
m_reducer.join(red_value, tmp_wrapped_value);
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdReduceFunctor(IteratorType first, ReducerType reducer)
|
||||
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
// reduce_custom_functors_impl
|
||||
//------------------------------
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class JoinerType>
|
||||
ValueType reduce_custom_functors_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ValueType init_reduction_value,
|
||||
JoinerType joiner) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
if (first == last) {
|
||||
// init is returned, unmodified
|
||||
return init_reduction_value;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using reducer_type =
|
||||
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||
using functor_type = StdReduceFunctor<IteratorType, reducer_type>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
|
||||
// run
|
||||
reduction_value_type result;
|
||||
reducer_type reducer(result, joiner);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
functor_type(first, reducer), reducer);
|
||||
|
||||
// fence not needed since reducing into scalar
|
||||
return joiner(result.val, init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||
ValueType reduce_default_functors_impl(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ValueType init_reduction_value) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
using value_type = Kokkos::Impl::remove_cvref_t<ValueType>;
|
||||
using joiner_type = Impl::StdReduceDefaultJoinFunctor<value_type>;
|
||||
return reduce_custom_functors_impl(
|
||||
label, ex, first, last, std::move(init_reduction_value), joiner_type());
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
///////////////////////////////
|
||||
//
|
||||
// reduce public API
|
||||
//
|
||||
///////////////////////////////
|
||||
|
||||
//
|
||||
// overload set 1
|
||||
//
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
typename IteratorType::value_type reduce(const ExecutionSpace& ex,
|
||||
IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::reduce_default_functors_impl(
|
||||
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||
typename IteratorType::value_type());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType>
|
||||
typename IteratorType::value_type reduce(const std::string& label,
|
||||
const ExecutionSpace& ex,
|
||||
IteratorType first,
|
||||
IteratorType last) {
|
||||
return Impl::reduce_default_functors_impl(
|
||||
label, ex, first, last, typename IteratorType::value_type());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto reduce(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
using view_type = ::Kokkos::View<DataType, Properties...>;
|
||||
using value_type = typename view_type::value_type;
|
||||
|
||||
return Impl::reduce_default_functors_impl(
|
||||
"Kokkos::reduce_default_functors_view_api", ex, KE::cbegin(view),
|
||||
KE::cend(view), value_type());
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties>
|
||||
auto reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
using view_type = ::Kokkos::View<DataType, Properties...>;
|
||||
using value_type = typename view_type::value_type;
|
||||
|
||||
return Impl::reduce_default_functors_impl(label, ex, KE::cbegin(view),
|
||||
KE::cend(view), value_type());
|
||||
}
|
||||
|
||||
//
|
||||
// overload set2:
|
||||
//
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||
ValueType reduce(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ValueType init_reduction_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::reduce_default_functors_impl(
|
||||
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||
init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ValueType init_reduction_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::reduce_default_functors_impl(label, ex, first, last,
|
||||
init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType>
|
||||
ValueType reduce(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::reduce_default_functors_impl(
|
||||
"Kokkos::reduce_default_functors_view_api", ex, KE::cbegin(view),
|
||||
KE::cend(view), init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType>
|
||||
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::reduce_default_functors_impl(
|
||||
label, ex, KE::cbegin(view), KE::cend(view), init_reduction_value);
|
||||
}
|
||||
|
||||
//
|
||||
// overload set 3
|
||||
//
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class BinaryOp>
|
||||
ValueType reduce(const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ValueType init_reduction_value,
|
||||
BinaryOp joiner) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::reduce_custom_functors_impl(
|
||||
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||
init_reduction_value, joiner);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class BinaryOp>
|
||||
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first, IteratorType last,
|
||||
ValueType init_reduction_value, BinaryOp joiner) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::reduce_custom_functors_impl(label, ex, first, last,
|
||||
init_reduction_value, joiner);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType, class BinaryOp>
|
||||
ValueType reduce(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value, BinaryOp joiner) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::reduce_custom_functors_impl(
|
||||
"Kokkos::reduce_custom_functors_view_api", ex, KE::cbegin(view),
|
||||
KE::cend(view), init_reduction_value, joiner);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType, class BinaryOp>
|
||||
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value, BinaryOp joiner) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::reduce_custom_functors_impl(label, ex, KE::cbegin(view),
|
||||
KE::cend(view), init_reduction_value,
|
||||
joiner);
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,488 @@
|
||||
/*
|
||||
//@HEADER
|
||||
// ************************************************************************
|
||||
//
|
||||
// Kokkos v. 3.0
|
||||
// Copyright (2020) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the Corporation nor the names of the
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||
//
|
||||
// ************************************************************************
|
||||
//@HEADER
|
||||
*/
|
||||
|
||||
#ifndef KOKKOS_STD_NUMERICS_TRANSFORM_REDUCE_HPP
|
||||
#define KOKKOS_STD_NUMERICS_TRANSFORM_REDUCE_HPP
|
||||
|
||||
#include <Kokkos_Core.hpp>
|
||||
#include "../Kokkos_Constraints.hpp"
|
||||
#include "../Kokkos_Distance.hpp"
|
||||
#include "../Kokkos_ModifyingOperations.hpp"
|
||||
#include "../Kokkos_BeginEnd.hpp"
|
||||
#include "../Kokkos_ReducerWithArbitraryJoinerNoNeutralElement.hpp"
|
||||
|
||||
namespace Kokkos {
|
||||
namespace Experimental {
|
||||
namespace Impl {
|
||||
|
||||
//
|
||||
// helper functors
|
||||
//
|
||||
template <class ValueType>
|
||||
struct StdTranformReduceDefaultBinaryTransformFunctor {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||
return (a * b);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct StdTranformReduceDefaultJoinFunctor {
|
||||
KOKKOS_FUNCTION
|
||||
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
constexpr ValueType operator()(const volatile ValueType& a,
|
||||
const volatile ValueType& b) const {
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
template <class IteratorType, class ReducerType, class TransformType>
|
||||
struct StdTransformReduceSingleIntervalFunctor {
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
using index_type = typename IteratorType::difference_type;
|
||||
|
||||
const IteratorType m_first;
|
||||
const ReducerType m_reducer;
|
||||
const TransformType m_transform;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const index_type i, red_value_type& red_value) const {
|
||||
auto tmp_wrapped_value = red_value_type{m_transform(m_first[i]), false};
|
||||
if (red_value.is_initial) {
|
||||
red_value = tmp_wrapped_value;
|
||||
} else {
|
||||
m_reducer.join(red_value, tmp_wrapped_value);
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdTransformReduceSingleIntervalFunctor(IteratorType first,
|
||||
ReducerType reducer,
|
||||
TransformType transform)
|
||||
: m_first(std::move(first)),
|
||||
m_reducer(std::move(reducer)),
|
||||
m_transform(std::move(transform)) {}
|
||||
};
|
||||
|
||||
template <class IndexType, class IteratorType1, class IteratorType2,
|
||||
class ReducerType, class TransformType>
|
||||
struct StdTransformReduceTwoIntervalsFunctor {
|
||||
using red_value_type = typename ReducerType::value_type;
|
||||
|
||||
const IteratorType1 m_first1;
|
||||
const IteratorType2 m_first2;
|
||||
const ReducerType m_reducer;
|
||||
const TransformType m_transform;
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
void operator()(const IndexType i, red_value_type& red_value) const {
|
||||
auto tmp_wrapped_value =
|
||||
red_value_type{m_transform(m_first1[i], m_first2[i]), false};
|
||||
|
||||
if (red_value.is_initial) {
|
||||
red_value = tmp_wrapped_value;
|
||||
} else {
|
||||
m_reducer.join(red_value, tmp_wrapped_value);
|
||||
}
|
||||
}
|
||||
|
||||
KOKKOS_FUNCTION
|
||||
StdTransformReduceTwoIntervalsFunctor(IteratorType1 first1,
|
||||
IteratorType2 first2,
|
||||
ReducerType reducer,
|
||||
TransformType transform)
|
||||
: m_first1(std::move(first1)),
|
||||
m_first2(std::move(first2)),
|
||||
m_reducer(std::move(reducer)),
|
||||
m_transform(std::move(transform)) {}
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
//
|
||||
// impl functions
|
||||
//
|
||||
//------------------------------
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class JoinerType, class UnaryTransformerType>
|
||||
ValueType transform_reduce_custom_functors_impl(
|
||||
const std::string& label, const ExecutionSpace& ex, IteratorType first,
|
||||
IteratorType last, ValueType init_reduction_value, JoinerType joiner,
|
||||
UnaryTransformerType transformer) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::expect_valid_range(first, last);
|
||||
|
||||
if (first == last) {
|
||||
// init is returned, unmodified
|
||||
return init_reduction_value;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using reducer_type =
|
||||
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||
using functor_type =
|
||||
StdTransformReduceSingleIntervalFunctor<IteratorType, reducer_type,
|
||||
UnaryTransformerType>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
|
||||
// run
|
||||
reduction_value_type result;
|
||||
reducer_type reducer(result, joiner);
|
||||
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||
::Kokkos::parallel_reduce(label,
|
||||
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
functor_type(first, reducer, transformer), reducer);
|
||||
|
||||
// fence not needed since reducing into scalar
|
||||
|
||||
// as per standard, transform is not applied to the init value
|
||||
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||
return joiner(result.val, init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType, class JoinerType, class BinaryTransformerType>
|
||||
ValueType transform_reduce_custom_functors_impl(
|
||||
const std::string& label, const ExecutionSpace& ex, IteratorType1 first1,
|
||||
IteratorType1 last1, IteratorType2 first2, ValueType init_reduction_value,
|
||||
JoinerType joiner, BinaryTransformerType transformer) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first1, first2);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first1, first2);
|
||||
Impl::expect_valid_range(first1, last1);
|
||||
|
||||
if (first1 == last1) {
|
||||
// init is returned, unmodified
|
||||
return init_reduction_value;
|
||||
}
|
||||
|
||||
// aliases
|
||||
using index_type = typename IteratorType1::difference_type;
|
||||
using reducer_type =
|
||||
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||
using functor_type =
|
||||
StdTransformReduceTwoIntervalsFunctor<index_type, IteratorType1,
|
||||
IteratorType2, reducer_type,
|
||||
BinaryTransformerType>;
|
||||
using reduction_value_type = typename reducer_type::value_type;
|
||||
|
||||
// run
|
||||
reduction_value_type result;
|
||||
reducer_type reducer(result, joiner);
|
||||
|
||||
const auto num_elements = Kokkos::Experimental::distance(first1, last1);
|
||||
::Kokkos::parallel_reduce(
|
||||
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||
functor_type(first1, first2, reducer, transformer), reducer);
|
||||
|
||||
// fence not needed since reducing into scalar
|
||||
return joiner(result.val, init_reduction_value);
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType>
|
||||
ValueType transform_reduce_default_functors_impl(
|
||||
const std::string& label, const ExecutionSpace& ex, IteratorType1 first1,
|
||||
IteratorType1 last1, IteratorType2 first2, ValueType init_reduction_value) {
|
||||
// checks
|
||||
Impl::static_assert_random_access_and_accessible(ex, first1, first2);
|
||||
Impl::static_assert_is_not_openmptarget(ex);
|
||||
Impl::static_assert_iterators_have_matching_difference_type(first1, first2);
|
||||
Impl::expect_valid_range(first1, last1);
|
||||
|
||||
// aliases
|
||||
using transformer_type =
|
||||
Impl::StdTranformReduceDefaultBinaryTransformFunctor<ValueType>;
|
||||
using joiner_type = Impl::StdTranformReduceDefaultJoinFunctor<ValueType>;
|
||||
|
||||
return transform_reduce_custom_functors_impl(
|
||||
label, ex, first1, last1, first2, std::move(init_reduction_value),
|
||||
joiner_type(), transformer_type());
|
||||
}
|
||||
|
||||
} // end namespace Impl
|
||||
|
||||
///////////////////////////////
|
||||
//
|
||||
// transform_reduce public API
|
||||
//
|
||||
///////////////////////////////
|
||||
|
||||
// ----------------------------
|
||||
// overload set1:
|
||||
// no custom functors passed, so equivalent to
|
||||
// transform_reduce(first1, last1, first2, init, plus<>(), multiplies<>());
|
||||
// ----------------------------
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType>
|
||||
ValueType transform_reduce(const ExecutionSpace& ex, IteratorType1 first1,
|
||||
IteratorType1 last1, IteratorType2 first2,
|
||||
ValueType init_reduction_value) {
|
||||
return Impl::transform_reduce_default_functors_impl(
|
||||
"Kokkos::transform_reduce_default_functors_iterator_api", ex, first1,
|
||||
last1, first2, std::move(init_reduction_value));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType>
|
||||
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType1 first1, IteratorType1 last1,
|
||||
IteratorType2 first2,
|
||||
ValueType init_reduction_value) {
|
||||
return Impl::transform_reduce_default_functors_impl(
|
||||
label, ex, first1, last1, first2, std::move(init_reduction_value));
|
||||
}
|
||||
|
||||
// overload1 accepting views
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType>
|
||||
ValueType transform_reduce(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||
ValueType init_reduction_value) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||
|
||||
return Impl::transform_reduce_default_functors_impl(
|
||||
"Kokkos::transform_reduce_default_functors_iterator_api", ex,
|
||||
KE::cbegin(first_view), KE::cend(first_view), KE::cbegin(second_view),
|
||||
std::move(init_reduction_value));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType>
|
||||
ValueType transform_reduce(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||
ValueType init_reduction_value) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||
|
||||
return Impl::transform_reduce_default_functors_impl(
|
||||
label, ex, KE::cbegin(first_view), KE::cend(first_view),
|
||||
KE::cbegin(second_view), std::move(init_reduction_value));
|
||||
}
|
||||
|
||||
//
|
||||
// overload set2:
|
||||
// accepts a custom transform and joiner functor
|
||||
//
|
||||
|
||||
// Note the std refers to the arg BinaryReductionOp
|
||||
// but in the Kokkos naming convention, it corresponds
|
||||
// to a "joiner" that knows how to join two values
|
||||
// NOTE: "joiner/transformer" need to be commutative.
|
||||
|
||||
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||
|
||||
// api accepting iterators
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType, class BinaryJoinerType, class BinaryTransform>
|
||||
ValueType transform_reduce(const ExecutionSpace& ex, IteratorType1 first1,
|
||||
IteratorType1 last1, IteratorType2 first2,
|
||||
ValueType init_reduction_value,
|
||||
BinaryJoinerType joiner,
|
||||
BinaryTransform transformer) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
"Kokkos::transform_reduce_custom_functors_iterator_api", ex, first1,
|
||||
last1, first2, std::move(init_reduction_value), std::move(joiner),
|
||||
std::move(transformer));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||
class ValueType, class BinaryJoinerType, class BinaryTransform>
|
||||
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType1 first1, IteratorType1 last1,
|
||||
IteratorType2 first2, ValueType init_reduction_value,
|
||||
BinaryJoinerType joiner,
|
||||
BinaryTransform transformer) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
label, ex, first1, last1, first2, std::move(init_reduction_value),
|
||||
std::move(joiner), std::move(transformer));
|
||||
}
|
||||
|
||||
// accepting views
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryJoinerType, class BinaryTransform>
|
||||
ValueType transform_reduce(
|
||||
const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||
BinaryTransform transformer) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
"Kokkos::transform_reduce_custom_functors_view_api", ex,
|
||||
KE::cbegin(first_view), KE::cend(first_view), KE::cbegin(second_view),
|
||||
std::move(init_reduction_value), std::move(joiner),
|
||||
std::move(transformer));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||
class DataType2, class... Properties2, class ValueType,
|
||||
class BinaryJoinerType, class BinaryTransform>
|
||||
ValueType transform_reduce(
|
||||
const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||
BinaryTransform transformer) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
label, ex, KE::cbegin(first_view), KE::cend(first_view),
|
||||
KE::cbegin(second_view), std::move(init_reduction_value),
|
||||
std::move(joiner), std::move(transformer));
|
||||
}
|
||||
|
||||
//
|
||||
// overload set3:
|
||||
//
|
||||
// accepting iterators
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class BinaryJoinerType, class UnaryTransform>
|
||||
// need this to avoid ambiguous call
|
||||
std::enable_if_t<
|
||||
::Kokkos::Experimental::Impl::are_iterators<IteratorType>::value, ValueType>
|
||||
transform_reduce(const ExecutionSpace& ex, IteratorType first1,
|
||||
IteratorType last1, ValueType init_reduction_value,
|
||||
BinaryJoinerType joiner, UnaryTransform transformer) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
"Kokkos::transform_reduce_custom_functors_iterator_api", ex, first1,
|
||||
last1, std::move(init_reduction_value), std::move(joiner),
|
||||
std::move(transformer));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||
class BinaryJoinerType, class UnaryTransform>
|
||||
// need this to avoid ambiguous call
|
||||
std::enable_if_t<
|
||||
::Kokkos::Experimental::Impl::are_iterators<IteratorType>::value, ValueType>
|
||||
transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
IteratorType first1, IteratorType last1,
|
||||
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||
UnaryTransform transformer) {
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
label, ex, first1, last1, std::move(init_reduction_value),
|
||||
std::move(joiner), std::move(transformer));
|
||||
}
|
||||
|
||||
// accepting views
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType, class BinaryJoinerType, class UnaryTransform>
|
||||
ValueType transform_reduce(const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value,
|
||||
BinaryJoinerType joiner,
|
||||
UnaryTransform transformer) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
"Kokkos::transform_reduce_custom_functors_view_api", ex, KE::cbegin(view),
|
||||
KE::cend(view), std::move(init_reduction_value), std::move(joiner),
|
||||
std::move(transformer));
|
||||
}
|
||||
|
||||
template <class ExecutionSpace, class DataType, class... Properties,
|
||||
class ValueType, class BinaryJoinerType, class UnaryTransform>
|
||||
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||
const ::Kokkos::View<DataType, Properties...>& view,
|
||||
ValueType init_reduction_value,
|
||||
BinaryJoinerType joiner,
|
||||
UnaryTransform transformer) {
|
||||
namespace KE = ::Kokkos::Experimental;
|
||||
static_assert(std::is_move_constructible<ValueType>::value,
|
||||
"ValueType must be move constructible.");
|
||||
|
||||
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||
|
||||
return Impl::transform_reduce_custom_functors_impl(
|
||||
label, ex, KE::cbegin(view), KE::cend(view),
|
||||
std::move(init_reduction_value), std::move(joiner),
|
||||
std::move(transformer));
|
||||
}
|
||||
|
||||
} // namespace Experimental
|
||||
} // namespace Kokkos
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user