11 #ifndef vtk_m_cont_BitField_h 
   12 #define vtk_m_cont_BitField_h 
   15 #include <vtkm/cont/vtkm_cont_export.h> 
   24 #include <type_traits> 
   36 struct StorageTagBitField;
 
   54   constexpr 
static vtkm::Id BlockSize = VTKM_ALLOCATION_ALIGNMENT;
 
   61   template <
typename WordType>
 
   62   using IsValidWordType =
 
   63     std::integral_constant<bool,
 
   65                            std::is_unsigned<WordType>::value &&
 
   67                              sizeof(WordType) <= 
static_cast<size_t>(BlockSize) &&
 
   69                              static_cast<size_t>(BlockSize) % 
sizeof(WordType) == 0>;
 
   73   template <
typename WordType>
 
   74   using IsValidWordTypeAtomic =
 
   75     std::integral_constant<bool,
 
   77                            std::is_unsigned<WordType>::value &&
 
   79                              sizeof(WordType) <= 
static_cast<size_t>(BlockSize) &&
 
   81                              static_cast<size_t>(BlockSize) % 
sizeof(WordType) == 0 &&
 
  100 template <
bool IsConst>
 
  105   template <
typename PortalType,
 
  106             typename PointerType = decltype(std::declval<PortalType>().GetIteratorBegin())>
 
  107   struct HasPointerAccess : 
public std::is_pointer<PointerType>
 
  112   template <
typename T>
 
  113   using MaybeConstPointer = 
typename std::conditional<IsConst, T const*, T*>::type;
 
  114   using BufferType = MaybeConstPointer<void>; 
 
  121   template <
typename WordType>
 
  122   using IsValidWordType = BitFieldTraits::IsValidWordType<WordType>;
 
  125   template <
typename WordType>
 
  126   using IsValidWordTypeAtomic = BitFieldTraits::IsValidWordTypeAtomic<WordType>;
 
  129                          "Internal error: Default word type is invalid.");
 
  131                          "Device-specific fast word type is invalid.");
 
  134                          "Internal error: Default word type is invalid.");
 
  136                          "Device-specific fast word type is invalid for atomic operations.");
 
  140   friend class vtkm::cont::internal::Storage<bool, 
vtkm::cont::internal::StorageTagBitField>;
 
  143   VTKM_CONT BitPortalBase(BufferType rawArray, vtkm::Id numberOfBits)
 
  145     , NumberOfBits{ numberOfBits }
 
  150   BitPortalBase() noexcept = default;
 
  151   BitPortalBase(const BitPortalBase&) noexcept = default;
 
  152   BitPortalBase(BitPortalBase&&) noexcept = default;
 
  153   BitPortalBase& operator=(const BitPortalBase&) noexcept = default;
 
  154   BitPortalBase& operator=(BitPortalBase&&) noexcept = default;
 
  158   vtkm::
Id GetNumberOfBits() const noexcept { 
return this->NumberOfBits; }
 
  163   template <
typename WordType = WordTypePreferred>
 
  167     static constexpr 
vtkm::Id WordSize = 
static_cast<vtkm::Id>(
sizeof(WordType));
 
  168     static constexpr 
vtkm::Id WordBits = WordSize * CHAR_BIT;
 
  169     return (this->NumberOfBits + WordBits - 1) / WordBits;
 
  174   template <
typename WordType = WordTypePreferred>
 
  177     if (this->NumberOfBits == 0)
 
  179       return WordType{ 0 };
 
  183       static_cast<vtkm::Int32>(
sizeof(WordType) * CHAR_BIT);
 
  185     const auto maxBit = this->NumberOfBits - 1;
 
  186     const auto coord = this->GetBitCoordinateFromIndex<WordType>(maxBit);
 
  187     const vtkm::Int32 shift = BitsPerWord - coord.BitOffset - 1;
 
  188     return (~WordType{ 0 }) >> shift;
 
  193   template <
typename WordType = WordTypePreferred>
 
  197     static constexpr 
vtkm::Id BitsPerWord = 
static_cast<vtkm::Id>(
sizeof(WordType) * CHAR_BIT);
 
  198     return { 
static_cast<vtkm::Id>(bitIdx / BitsPerWord),
 
  207   void SetBit(
vtkm::Id bitIdx, 
bool val) 
const noexcept
 
  210     using WordType = WordTypePreferred;
 
  211     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  212     const auto mask = WordType(1) << coord.BitOffset;
 
  213     WordType* wordAddr = this->GetWordAddress<WordType>(coord.WordIndex);
 
  227   void SetBitAtomic(
vtkm::Id bitIdx, 
bool val)
 const 
  230     using WordType = WordTypePreferred;
 
  231     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  232     const auto mask = WordType(1) << coord.BitOffset;
 
  235       this->OrWordAtomic(coord.WordIndex, mask);
 
  239       this->AndWordAtomic(coord.WordIndex, ~mask);
 
  246   bool GetBit(
vtkm::Id bitIdx) 
const noexcept
 
  248     using WordType = WordTypePreferred;
 
  249     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  250     const auto word = this->GetWord<WordType>(coord.WordIndex);
 
  251     const auto mask = WordType(1) << coord.BitOffset;
 
  252     return (word & mask) != WordType(0);
 
  259   bool GetBitAtomic(
vtkm::Id bitIdx)
 const 
  261     using WordType = WordTypePreferred;
 
  262     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  263     const auto word = this->GetWordAtomic<WordType>(coord.WordIndex);
 
  264     const auto mask = WordType(1) << coord.BitOffset;
 
  265     return (word & mask) != WordType(0);
 
  270   template <
typename WordType = WordTypePreferred>
 
  274     *this->GetWordAddress<WordType>(wordIdx) = word;
 
  279   template <
typename WordType = WordTypePreferred>
 
  284                            "Requested WordType does not support atomic" 
  285                            " operations on target execution platform.");
 
  291   template <
typename WordType = WordTypePreferred>
 
  294     return *this->GetWordAddress<WordType>(wordIdx);
 
  299   template <
typename WordType = WordTypePreferred>
 
  303                            "Requested WordType does not support atomic" 
  304                            " operations on target execution platform.");
 
  311   bool NotBitAtomic(
vtkm::Id bitIdx)
 const 
  314     using WordType = WordTypePreferred;
 
  315     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  316     const auto mask = WordType(1) << coord.BitOffset;
 
  317     const auto oldWord = this->XorWordAtomic(coord.WordIndex, mask);
 
  318     return (oldWord & mask) != WordType(0);
 
  323   template <
typename WordType = WordTypePreferred>
 
  328                            "Requested WordType does not support atomic" 
  329                            " operations on target execution platform.");
 
  330     WordType* addr = this->GetWordAddress<WordType>(wordIdx);
 
  338   bool AndBitAtomic(
vtkm::Id bitIdx, 
bool val)
 const 
  341     using WordType = WordTypePreferred;
 
  342     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  343     const auto bitmask = WordType(1) << coord.BitOffset;
 
  345     const auto wordmask = val ? ~WordType(0) : ~bitmask;
 
  346     const auto oldWord = this->AndWordAtomic(coord.WordIndex, wordmask);
 
  347     return (oldWord & bitmask) != WordType(0);
 
  353   template <
typename WordType = WordTypePreferred>
 
  358                            "Requested WordType does not support atomic" 
  359                            " operations on target execution platform.");
 
  360     WordType* addr = this->GetWordAddress<WordType>(wordIdx);
 
  368   bool OrBitAtomic(
vtkm::Id bitIdx, 
bool val)
 const 
  371     using WordType = WordTypePreferred;
 
  372     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  373     const auto bitmask = WordType(1) << coord.BitOffset;
 
  375     const auto wordmask = val ? bitmask : WordType(0);
 
  376     const auto oldWord = this->OrWordAtomic(coord.WordIndex, wordmask);
 
  377     return (oldWord & bitmask) != WordType(0);
 
  383   template <
typename WordType = WordTypePreferred>
 
  388                            "Requested WordType does not support atomic" 
  389                            " operations on target execution platform.");
 
  390     WordType* addr = this->GetWordAddress<WordType>(wordIdx);
 
  398   bool XorBitAtomic(
vtkm::Id bitIdx, 
bool val)
 const 
  401     using WordType = WordTypePreferred;
 
  402     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  403     const auto bitmask = WordType(1) << coord.BitOffset;
 
  405     const auto wordmask = val ? bitmask : WordType(0);
 
  406     const auto oldWord = this->XorWordAtomic(coord.WordIndex, wordmask);
 
  407     return (oldWord & bitmask) != WordType(0);
 
  413   template <
typename WordType = WordTypePreferred>
 
  418                            "Requested WordType does not support atomic" 
  419                            " operations on target execution platform.");
 
  420     WordType* addr = this->GetWordAddress<WordType>(wordIdx);
 
  431   bool CompareExchangeBitAtomic(
vtkm::Id bitIdx, 
bool* oldBit, 
bool newBit)
 const 
  434     using WordType = WordTypePreferred;
 
  435     const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
 
  436     const auto bitmask = WordType(1) << coord.BitOffset;
 
  438     WordType oldWord = this->GetWord<WordType>(coord.WordIndex);
 
  441       bool actualBit = (oldWord & bitmask) != WordType(0);
 
  442       if (actualBit != *oldBit)
 
  447       else if (actualBit == newBit)
 
  455     } 
while (!this->CompareExchangeWordAtomic(coord.WordIndex, &oldWord, oldWord ^ bitmask));
 
  466   template <
typename WordType = WordTypePreferred>
 
  469                                                 WordType newWord)
 const 
  473                            "Requested WordType does not support atomic" 
  474                            " operations on target execution platform.");
 
  475     WordType* addr = this->GetWordAddress<WordType>(wordIdx);
 
  480   template <
typename WordType>
 
  484     return reinterpret_cast<MaybeConstPointer<WordType>
>(this->Data) + wordId;
 
  487   BufferType Data{ 
nullptr };
 
  491 using BitPortal = BitPortalBase<false>;
 
  493 using BitPortalConst = BitPortalBase<true>;
 
  499   static constexpr 
vtkm::Id BlockSize = detail::BitFieldTraits::BlockSize;
 
  510   template <
typename Device>
 
  524   template <
typename WordType>
 
  528   template <
typename WordType, 
typename Device = 
void>
 
  539   bool operator==(const 
BitField& rhs)
 const { 
return this->Buffer == rhs.Buffer; }
 
  552   template <
typename WordType>
 
  556     static constexpr 
vtkm::Id WordBits = 
static_cast<vtkm::Id>(
sizeof(WordType) * CHAR_BIT);
 
  557     return (this->GetNumberOfBits() + WordBits - 1) / WordBits;
 
  570     this->Allocate(numberOfBits, preserve, token);
 
  574   template <
typename ValueType>
 
  580     this->Fill(value, token);
 
  582   template <
typename ValueType>
 
  586     this->AllocateAndFill(numberOfBits, value, token);
 
  590   VTKM_CONT void FillImpl(
const void* word,
 
  596   template <
typename WordType>
 
  601   template <
typename WordType>
 
  605     this->Fill(word, token);
 
  612     this->Fill(value ? ~WordType{ 0 } : WordType{ 0 }, token);
 
  617     this->Fill(value, token);
 
  621   VTKM_CONT void ReleaseResourcesExecution();
 
  639     return this->IsOnDevice(vtkm::cont::DeviceAdapterTagUndefined{});
 
  645   VTKM_CONT WritePortalType WritePortal() 
const;
 
  650   VTKM_CONT ReadPortalType ReadPortal() 
const;
 
  679   mutable vtkm::cont::internal::Buffer 
Buffer;
 
  684 #endif // vtk_m_cont_BitField_h