Viskores  1.0
ArrayHandleBitField.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 //
14 // This software is distributed WITHOUT ANY WARRANTY; without even
15 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 // PURPOSE. See the above copyright notice for more information.
17 //============================================================================
18 #ifndef viskores_cont_ArrayHandleBitField_h
19 #define viskores_cont_ArrayHandleBitField_h
20 
22 #include <viskores/cont/BitField.h>
23 #include <viskores/cont/Storage.h>
24 
25 namespace viskores
26 {
27 namespace cont
28 {
29 
30 namespace internal
31 {
32 
33 template <typename BitPortalType>
34 class ArrayPortalBitField
35 {
36 public:
37  using ValueType = bool;
38 
40  explicit ArrayPortalBitField(const BitPortalType& portal) noexcept
41  : BitPortal{ portal }
42  {
43  }
44 
46  explicit ArrayPortalBitField(BitPortalType&& portal) noexcept
47  : BitPortal{ std::move(portal) }
48  {
49  }
50 
51  ArrayPortalBitField() noexcept = default;
52  ArrayPortalBitField(const ArrayPortalBitField&) noexcept = default;
53  ArrayPortalBitField(ArrayPortalBitField&&) noexcept = default;
54  ArrayPortalBitField& operator=(const ArrayPortalBitField&) noexcept = default;
55  ArrayPortalBitField& operator=(ArrayPortalBitField&&) noexcept = default;
56 
58  viskores::Id GetNumberOfValues() const noexcept { return this->BitPortal.GetNumberOfBits(); }
59 
61  ValueType Get(viskores::Id index) const noexcept { return this->BitPortal.GetBit(index); }
62 
64  void Set(viskores::Id index, ValueType value) const
65  {
66  // Use an atomic set so we don't clash with other threads writing nearby
67  // bits.
68  this->BitPortal.SetBitAtomic(index, value);
69  }
70 
71 private:
72  BitPortalType BitPortal;
73 };
74 
75 struct VISKORES_ALWAYS_EXPORT StorageTagBitField
76 {
77 };
78 
79 template <>
80 class Storage<bool, StorageTagBitField>
81 {
82  using BitPortalType = viskores::cont::detail::BitPortal;
83  using BitPortalConstType = viskores::cont::detail::BitPortalConst;
84 
85  using WordType = viskores::WordTypeDefault;
86  static constexpr viskores::Id BlockSize = viskores::cont::detail::BitFieldTraits::BlockSize;
87  VISKORES_STATIC_ASSERT(BlockSize >= static_cast<viskores::Id>(sizeof(WordType)));
88 
89 public:
90  using ReadPortalType = viskores::cont::internal::ArrayPortalBitField<BitPortalConstType>;
91  using WritePortalType = viskores::cont::internal::ArrayPortalBitField<BitPortalType>;
92 
93  VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers()
94  {
95  return std::vector<viskores::cont::internal::Buffer>(1);
96  }
97 
98  VISKORES_CONT static void ResizeBuffers(
99  viskores::Id numberOfBits,
100  const std::vector<viskores::cont::internal::Buffer>& buffers,
101  viskores::CopyFlag preserve,
102  viskores::cont::Token& token)
103  {
104  const viskores::Id bytesNeeded = (numberOfBits + CHAR_BIT - 1) / CHAR_BIT;
105  const viskores::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
106  const viskores::Id numBytes = blocksNeeded * BlockSize;
107 
109  "BitField Allocation: %llu bits, blocked up to %s bytes.",
110  static_cast<unsigned long long>(numberOfBits),
111  viskores::cont::GetSizeString(static_cast<viskores::UInt64>(numBytes)).c_str());
112 
113  buffers[0].SetNumberOfBytes(numBytes, preserve, token);
114  buffers[0].GetMetaData<viskores::cont::internal::BitFieldMetaData>().NumberOfBits =
115  numberOfBits;
116  }
117 
118  VISKORES_CONT static viskores::IdComponent GetNumberOfComponentsFlat(
119  const std::vector<viskores::cont::internal::Buffer>&)
120  {
121  return 1;
122  }
123 
124  VISKORES_CONT static viskores::Id GetNumberOfValues(
125  const std::vector<viskores::cont::internal::Buffer>& buffers)
126  {
127  VISKORES_ASSERT(buffers.size() == 1);
128  viskores::Id numberOfBits =
129  buffers[0].GetMetaData<viskores::cont::internal::BitFieldMetaData>().NumberOfBits;
130  VISKORES_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
131  return numberOfBits;
132  }
133 
134  VISKORES_CONT static void Fill(const std::vector<viskores::cont::internal::Buffer>& buffers,
135  bool fillValue,
136  viskores::Id startBit,
137  viskores::Id endBit,
138  viskores::cont::Token& token)
139  {
140  VISKORES_ASSERT(buffers.size() == 1);
141  constexpr viskores::BufferSizeType wordTypeSize =
142  static_cast<viskores::BufferSizeType>(sizeof(WordType));
143  constexpr viskores::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT;
144  // Special case where filling to end of array.
145  viskores::Id totalBitsInArray = GetNumberOfValues(buffers);
146  if (endBit >= totalBitsInArray)
147  {
148  endBit = ((totalBitsInArray + (wordNumBits - 1)) / wordNumBits) * wordNumBits;
149  }
150  if (((startBit % wordNumBits) == 0) && ((endBit % wordNumBits) == 0))
151  {
152  WordType fillWord = (fillValue ? ~WordType{ 0 } : WordType{ 0 });
153  buffers[0].Fill(&fillWord, wordTypeSize, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
154  }
155  else if (((startBit % CHAR_BIT) == 0) && ((endBit % CHAR_BIT) == 0))
156  {
157  viskores::UInt8 fillWord = (fillValue ? ~viskores::UInt8{ 0 } : viskores::UInt8{ 0 });
158  buffers[0].Fill(&fillWord, 1, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
159  }
160  else
161  {
162  throw viskores::cont::ErrorBadValue("Can only fill ArrayHandleBitField on 8-bit boundaries.");
163  }
164  }
165 
166  VISKORES_CONT static ReadPortalType CreateReadPortal(
167  const std::vector<viskores::cont::internal::Buffer>& buffers,
169  viskores::cont::Token& token)
170  {
171  VISKORES_ASSERT(buffers.size() == 1);
172  viskores::Id numberOfBits = GetNumberOfValues(buffers);
173  VISKORES_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
174 
175  return ReadPortalType(
176  BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
177  }
178 
179  VISKORES_CONT static WritePortalType CreateWritePortal(
180  const std::vector<viskores::cont::internal::Buffer>& buffers,
182  viskores::cont::Token& token)
183  {
184  VISKORES_ASSERT(buffers.size() == 1);
185  viskores::Id numberOfBits = GetNumberOfValues(buffers);
186  VISKORES_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
187 
188  return WritePortalType(
189  BitPortalType(buffers[0].WritePointerDevice(device, token), numberOfBits));
190  }
191 };
192 
193 } // end namespace internal
194 
195 
199 class ArrayHandleBitField : public ArrayHandle<bool, internal::StorageTagBitField>
200 {
201 public:
204 
207  : Superclass(std::vector<viskores::cont::internal::Buffer>(1, bitField.GetBuffer()))
208  {
209  }
210 };
211 
213  const viskores::cont::BitField& bitField)
214 {
215  return ArrayHandleBitField{ bitField };
216 }
217 
219  viskores::cont::BitField&& bitField) noexcept
220 {
221  return ArrayHandleBitField{ std::move(bitField) };
222 }
223 }
224 } // end namespace viskores::cont
225 
226 #endif // viskores_cont_ArrayHandleBitField_h
ArrayHandle.h
BitField.h
viskores::cont::ArrayHandleBitField::ArrayHandleBitField
ArrayHandleBitField(const viskores::cont::BitField &bitField)
Definition: ArrayHandleBitField.h:206
VISKORES_ARRAY_HANDLE_SUBCLASS_NT
#define VISKORES_ARRAY_HANDLE_SUBCLASS_NT(classname, superclass)
Macro to make default methods in ArrayHandle subclasses.
Definition: ArrayHandle.h:279
Storage.h
viskores::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:313
viskores::IdComponent
viskores::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:202
VISKORES_LOG_F
#define VISKORES_LOG_F(level,...)
Writes a message using printf syntax to the indicated log level.
Definition: Logging.h:217
VISKORES_EXEC_CONT
#define VISKORES_EXEC_CONT
Definition: ExportMacros.h:60
viskores::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
VISKORES_CONT
#define VISKORES_CONT
Definition: ExportMacros.h:65
viskores::cont::BitField
Definition: BitField.h:507
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::cont::ArrayHandleBitField::Superclass
viskores::cont::detail::GetTypeInParentheses< void(ArrayHandle< bool, internal::StorageTagBitField >) >::type Superclass
Definition: ArrayHandleBitField.h:203
VISKORES_ASSERT
#define VISKORES_ASSERT(condition)
Definition: Assert.h:51
viskores::BufferSizeType
viskores::Int64 BufferSizeType
Definition: DeviceAdapterMemoryManager.h:35
viskores::cont::LogLevel::MemCont
@ MemCont
Host-side resource allocations/frees (e.g. ArrayHandle control buffers).
viskores::UInt64
unsigned long long UInt64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:215
viskores::UInt8
uint8_t UInt8
Base type to use for 8-bit unsigned integer numbers.
Definition: Types.h:177
viskores::cont::DeviceAdapterId
An object used to specify a device.
Definition: DeviceAdapterTag.h:66
viskores::cont::ErrorBadValue
This class is thrown when a Viskores function or method encounters an invalid value that inhibits pro...
Definition: ErrorBadValue.h:33
viskores::Get
auto Get(const viskores::Tuple< Ts... > &tuple)
Retrieve the object from a viskores::Tuple at the given index.
Definition: Tuple.h:89
viskores::WordTypeDefault
viskores::UInt32 WordTypeDefault
The default word size used for atomic bitwise operations.
Definition: Types.h:206
viskores::cont::make_ArrayHandleBitField
viskores::cont::ArrayHandleBitField make_ArrayHandleBitField(const viskores::cont::BitField &bitField)
Definition: ArrayHandleBitField.h:212
viskores::CopyFlag
CopyFlag
Identifier used to specify whether a function should deep copy data.
Definition: Flags.h:25
viskores::cont::GetSizeString
std::string GetSizeString(viskores::UInt64 bytes, int prec=2)
Returns "%1 (%2 bytes)" where %1 is the result from GetHumanReadableSize and %2 is the exact number o...
viskores::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:43
viskores::cont::ArrayHandleBitField
The ArrayHandleBitField class is a boolean-valued ArrayHandle that is backed by a BitField.
Definition: ArrayHandleBitField.h:199
VISKORES_STATIC_ASSERT
#define VISKORES_STATIC_ASSERT(condition)
Definition: StaticAssert.h:24