45 #ifndef KOKKOS_BITSET_HPP
46 #define KOKKOS_BITSET_HPP
48 #include <Kokkos_Core.hpp>
49 #include <Kokkos_Functional.hpp>
51 #include <impl/Kokkos_Bitset_impl.hpp>
57 template <
typename Device = Kokkos::DefaultExecutionSpace>
60 template <
typename Device = Kokkos::DefaultExecutionSpace>
63 template <
typename DstDevice,
typename SrcDevice>
66 template <
typename DstDevice,
typename SrcDevice>
69 template <
typename DstDevice,
typename SrcDevice>
73 template <
typename Device>
76 typedef Device execution_space;
77 typedef unsigned size_type;
79 enum { BIT_SCAN_REVERSE = 1u };
80 enum { MOVE_HINT_BACKWARD = 2u };
83 BIT_SCAN_FORWARD_MOVE_HINT_FORWARD = 0u,
84 BIT_SCAN_REVERSE_MOVE_HINT_FORWARD = BIT_SCAN_REVERSE,
85 BIT_SCAN_FORWARD_MOVE_HINT_BACKWARD = MOVE_HINT_BACKWARD,
86 BIT_SCAN_REVERSE_MOVE_HINT_BACKWARD = BIT_SCAN_REVERSE | MOVE_HINT_BACKWARD
90 enum { block_size =
static_cast<unsigned>(
sizeof(unsigned) * CHAR_BIT) };
91 enum { block_mask = block_size - 1u };
92 enum { block_shift = Kokkos::Impl::integral_power_of_two(block_size) };
99 m_last_block_mask(0u),
100 m_blocks(
"Bitset", ((m_size + block_mask) >> block_shift)) {
101 for (
int i = 0, end = static_cast<int>(m_size & block_mask); i < end; ++i) {
102 m_last_block_mask |= 1u << i;
106 KOKKOS_DEFAULTED_FUNCTION
109 KOKKOS_DEFAULTED_FUNCTION
112 KOKKOS_DEFAULTED_FUNCTION
115 KOKKOS_DEFAULTED_FUNCTION
118 KOKKOS_DEFAULTED_FUNCTION
123 KOKKOS_FORCEINLINE_FUNCTION
124 unsigned size()
const {
return m_size; }
129 Impl::BitsetCount<Bitset<Device> > f(*
this);
138 if (m_last_block_mask) {
140 typedef Kokkos::Impl::DeepCopy<
typename execution_space::memory_space,
143 raw_deep_copy(m_blocks.data() + (m_blocks.
extent(0) - 1u),
144 &m_last_block_mask,
sizeof(
unsigned));
158 KOKKOS_FORCEINLINE_FUNCTION
159 bool set(
unsigned i)
const {
161 unsigned* block_ptr = &m_blocks[i >> block_shift];
162 const unsigned mask = 1u << static_cast<int>(i & block_mask);
164 return !(atomic_fetch_or(block_ptr, mask) & mask);
171 KOKKOS_FORCEINLINE_FUNCTION
174 unsigned* block_ptr = &m_blocks[i >> block_shift];
175 const unsigned mask = 1u << static_cast<int>(i & block_mask);
177 return atomic_fetch_and(block_ptr, ~mask) & mask;
184 KOKKOS_FORCEINLINE_FUNCTION
187 const unsigned block = volatile_load(&m_blocks[i >> block_shift]);
188 const unsigned mask = 1u << static_cast<int>(i & block_mask);
197 KOKKOS_FORCEINLINE_FUNCTION
204 KOKKOS_INLINE_FUNCTION
207 unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD)
const {
208 const unsigned block_idx =
209 (hint >> block_shift) < m_blocks.
extent(0) ? (hint >> block_shift) : 0;
210 const unsigned offset = hint & block_mask;
211 unsigned block = volatile_load(&m_blocks[block_idx]);
212 block = !m_last_block_mask || (block_idx < (m_blocks.
extent(0) - 1))
214 : block & m_last_block_mask;
216 return find_any_helper(block_idx, offset, block, scan_direction);
223 KOKKOS_INLINE_FUNCTION
226 unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD)
const {
227 const unsigned block_idx = hint >> block_shift;
228 const unsigned offset = hint & block_mask;
229 unsigned block = volatile_load(&m_blocks[block_idx]);
230 block = !m_last_block_mask || (block_idx < (m_blocks.
extent(0) - 1))
232 : ~block & m_last_block_mask;
234 return find_any_helper(block_idx, offset, block, scan_direction);
238 KOKKOS_FORCEINLINE_FUNCTION
240 unsigned offset,
unsigned block,
241 unsigned scan_direction)
const {
245 result.second = update_hint(block_idx, offset, scan_direction);
248 scan_block((block_idx << block_shift), offset, block, scan_direction);
253 KOKKOS_FORCEINLINE_FUNCTION
254 unsigned scan_block(
unsigned block_start,
int offset,
unsigned block,
255 unsigned scan_direction)
const {
256 offset = !(scan_direction & BIT_SCAN_REVERSE)
258 : (offset + block_mask) & block_mask;
259 block = Impl::rotate_right(block, offset);
260 return (((!(scan_direction & BIT_SCAN_REVERSE)
261 ? Impl::bit_scan_forward(block)
262 : ::Kokkos::log2(block)) +
268 KOKKOS_FORCEINLINE_FUNCTION
269 unsigned update_hint(
long long block_idx,
unsigned offset,
270 unsigned scan_direction)
const {
271 block_idx += scan_direction & MOVE_HINT_BACKWARD ? -1 : 1;
272 block_idx = block_idx >= 0 ? block_idx : m_blocks.
extent(0) - 1;
274 block_idx < static_cast<long long>(m_blocks.
extent(0)) ? block_idx : 0;
276 return static_cast<unsigned>(block_idx) * block_size + offset;
281 unsigned m_last_block_mask;
282 View<unsigned*, execution_space, MemoryTraits<RandomAccess> > m_blocks;
285 template <
typename DDevice>
288 template <
typename DDevice>
289 friend class ConstBitset;
291 template <
typename Bitset>
292 friend struct Impl::BitsetCount;
294 template <
typename DstDevice,
typename SrcDevice>
295 friend void deep_copy(Bitset<DstDevice>& dst, Bitset<SrcDevice>
const& src);
297 template <
typename DstDevice,
typename SrcDevice>
298 friend void deep_copy(Bitset<DstDevice>& dst,
299 ConstBitset<SrcDevice>
const& src);
304 template <
typename Device>
307 typedef Device execution_space;
308 typedef unsigned size_type;
311 enum { block_size =
static_cast<unsigned>(
sizeof(unsigned) * CHAR_BIT) };
312 enum { block_mask = block_size - 1u };
313 enum { block_shift = Kokkos::Impl::integral_power_of_two(block_size) };
316 ConstBitset() : m_size(0) {}
318 ConstBitset(Bitset<Device>
const& rhs)
319 : m_size(rhs.m_size), m_blocks(rhs.m_blocks) {}
321 ConstBitset(ConstBitset<Device>
const& rhs)
322 : m_size(rhs.m_size), m_blocks(rhs.m_blocks) {}
324 ConstBitset<Device>& operator=(Bitset<Device>
const& rhs) {
325 this->m_size = rhs.m_size;
326 this->m_blocks = rhs.m_blocks;
331 ConstBitset<Device>& operator=(ConstBitset<Device>
const& rhs) {
332 this->m_size = rhs.m_size;
333 this->m_blocks = rhs.m_blocks;
338 KOKKOS_FORCEINLINE_FUNCTION
339 unsigned size()
const {
return m_size; }
341 unsigned count()
const {
342 Impl::BitsetCount<ConstBitset<Device> > f(*
this);
346 KOKKOS_FORCEINLINE_FUNCTION
347 bool test(
unsigned i)
const {
349 const unsigned block = m_blocks[i >> block_shift];
350 const unsigned mask = 1u << static_cast<int>(i & block_mask);
358 View<const unsigned*, execution_space, MemoryTraits<RandomAccess> > m_blocks;
361 template <
typename DDevice>
362 friend class ConstBitset;
364 template <
typename Bitset>
365 friend struct Impl::BitsetCount;
367 template <
typename DstDevice,
typename SrcDevice>
368 friend void deep_copy(Bitset<DstDevice>& dst,
369 ConstBitset<SrcDevice>
const& src);
371 template <
typename DstDevice,
typename SrcDevice>
372 friend void deep_copy(ConstBitset<DstDevice>& dst,
373 ConstBitset<SrcDevice>
const& src);
376 template <
typename DstDevice,
typename SrcDevice>
377 void deep_copy(Bitset<DstDevice>& dst, Bitset<SrcDevice>
const& src) {
378 if (dst.size() != src.size()) {
379 throw std::runtime_error(
380 "Error: Cannot deep_copy bitsets of different sizes!");
383 typedef Kokkos::Impl::DeepCopy<
typename DstDevice::memory_space,
384 typename SrcDevice::memory_space>
386 raw_deep_copy(dst.m_blocks.data(), src.m_blocks.data(),
387 sizeof(unsigned) * src.m_blocks.extent(0));
390 template <
typename DstDevice,
typename SrcDevice>
391 void deep_copy(Bitset<DstDevice>& dst, ConstBitset<SrcDevice>
const& src) {
392 if (dst.size() != src.size()) {
393 throw std::runtime_error(
394 "Error: Cannot deep_copy bitsets of different sizes!");
397 typedef Kokkos::Impl::DeepCopy<
typename DstDevice::memory_space,
398 typename SrcDevice::memory_space>
400 raw_deep_copy(dst.m_blocks.data(), src.m_blocks.data(),
401 sizeof(unsigned) * src.m_blocks.extent(0));
404 template <
typename DstDevice,
typename SrcDevice>
405 void deep_copy(ConstBitset<DstDevice>& dst, ConstBitset<SrcDevice>
const& src) {
406 if (dst.size() != src.size()) {
407 throw std::runtime_error(
408 "Error: Cannot deep_copy bitsets of different sizes!");
411 typedef Kokkos::Impl::DeepCopy<
typename DstDevice::memory_space,
412 typename SrcDevice::memory_space>
414 raw_deep_copy(dst.m_blocks.data(), src.m_blocks.data(),
415 sizeof(unsigned) * src.m_blocks.extent(0));
420 #endif // KOKKOS_BITSET_HPP
A thread safe view to a bitset.
void deep_copy(const View< DT, DP...> &dst, typename ViewTraits< DT, DP...>::const_value_type &value, typename std::enable_if< std::is_same< typename ViewTraits< DT, DP...>::specialize, void >::value >::type *=nullptr)
Deep copy a value from Host memory into a view.
KOKKOS_FORCEINLINE_FUNCTION unsigned max_hint() const
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< std::is_integral< iType >::value, size_t >::type extent(const iType &r) const noexcept
rank() to be implemented
Bitset(unsigned arg_size=0u)
Replacement for std::pair that works on CUDA devices.
KOKKOS_FORCEINLINE_FUNCTION bool reset(unsigned i) const
KOKKOS_FORCEINLINE_FUNCTION bool test(unsigned i) const
Memory management for host memory.
KOKKOS_FORCEINLINE_FUNCTION unsigned size() const
KOKKOS_INLINE_FUNCTION Kokkos::pair< bool, unsigned > find_any_set_near(unsigned hint, unsigned scan_direction=BIT_SCAN_FORWARD_MOVE_HINT_FORWARD) const
KOKKOS_FORCEINLINE_FUNCTION bool set(unsigned i) const
KOKKOS_INLINE_FUNCTION Kokkos::pair< bool, unsigned > find_any_unset_near(unsigned hint, unsigned scan_direction=BIT_SCAN_FORWARD_MOVE_HINT_FORWARD) const