Viskores  1.0
Keys.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_worklet_Keys_h
19 #define viskores_worklet_Keys_h
20 
28 #include <viskores/cont/Logging.h>
29 
30 #include <viskores/Deprecated.h>
31 #include <viskores/Hash.h>
32 
34 
40 
42 
45 
47 
48 namespace viskores
49 {
50 namespace worklet
51 {
52 
53 namespace internal
54 {
55 
56 class VISKORES_WORKLET_EXPORT KeysBase
57 {
58 public:
59  KeysBase(const KeysBase&) = default;
60  KeysBase& operator=(const KeysBase&) = default;
61  ~KeysBase() = default;
62 
64  viskores::Id GetInputRange() const { return this->Offsets.GetNumberOfValues() - 1; }
65 
67  viskores::cont::ArrayHandle<viskores::Id> GetSortedValuesMap() const
68  {
69  return this->SortedValuesMap;
70  }
71 
73  viskores::cont::ArrayHandle<viskores::Id> GetOffsets() const { return this->Offsets; }
74 
76  "Use the `GetOffsets()` array in an `ArrayHandleOffsetsToNumComponents`.")
78  viskores::cont::ArrayHandle<viskores::IdComponent> GetCounts() const;
79 
81  viskores::Id GetNumberOfValues() const { return this->SortedValuesMap.GetNumberOfValues(); }
82 
83  using ExecLookup = viskores::exec::internal::ReduceByKeyLookupBase<
86 
87  VISKORES_CONT ExecLookup PrepareForInput(viskores::cont::DeviceAdapterId device,
88  viskores::cont::Token& token) const
89  {
90  return ExecLookup(this->SortedValuesMap.PrepareForInput(device, token),
91  this->Offsets.PrepareForInput(device, token));
92  }
93 
95  bool operator==(const viskores::worklet::internal::KeysBase& other) const
96  {
97  return ((this->SortedValuesMap == other.SortedValuesMap) && (this->Offsets == other.Offsets) &&
98  (this->Offsets == other.Offsets));
99  }
100 
102  bool operator!=(const viskores::worklet::internal::KeysBase& other) const
103  {
104  return !(*this == other);
105  }
106 
107 protected:
108  KeysBase() = default;
109 
112 };
113 
114 } // namespace internal
115 
119 enum class KeysSortType
120 {
121  Unstable = 0,
122  Stable = 1
123 };
124 
141 template <typename T>
142 class VISKORES_ALWAYS_EXPORT Keys : public internal::KeysBase
143 {
144 public:
145  using KeyType = T;
147 
149  Keys();
150 
160  template <typename KeyStorage>
163  {
164  this->BuildArrays(keys, KeysSortType::Unstable, device);
165  }
166 
170  template <typename KeyArrayType>
171  VISKORES_CONT void BuildArrays(
172  const KeyArrayType& keys,
173  KeysSortType sort,
175 
179  template <typename KeyArrayType>
180  VISKORES_CONT void BuildArraysInPlace(
181  KeyArrayType& keys,
182  KeysSortType sort,
184 
188  KeyArrayHandleType GetUniqueKeys() const { return this->UniqueKeys; }
189 
190 #ifdef VISKORES_DOXYGEN_ONLY
191  // Document the superclass' methods as methods in this class.
192 
196  viskores::Id GetInputRange() const;
197 
204  viskores::cont::ArrayHandle<viskores::Id> GetSortedValuesMap() const;
205 
213 
217  viskores::Id GetNumberOfValues() const;
218 #endif
219 
220  using ExecLookup = viskores::exec::internal::ReduceByKeyLookup<
221  typename KeyArrayHandleType::ReadPortalType,
224 
226  viskores::cont::Token& token) const
227  {
228  return ExecLookup(this->UniqueKeys.PrepareForInput(device, token),
229  this->SortedValuesMap.PrepareForInput(device, token),
230  this->Offsets.PrepareForInput(device, token));
231  }
232 
235  {
236  return ((this->UniqueKeys == other.UniqueKeys) &&
237  (this->SortedValuesMap == other.SortedValuesMap) && (this->Offsets == other.Offsets));
238  }
239 
241  bool operator!=(const viskores::worklet::Keys<KeyType>& other) const { return !(*this == other); }
242 
243 private:
245  KeyArrayHandleType UniqueKeys;
246 
247  template <typename KeyArrayType>
248  VISKORES_CONT void BuildArraysInternal(KeyArrayType& keys,
250 
251  template <typename KeyArrayType>
252  VISKORES_CONT void BuildArraysInternalStable(const KeyArrayType& keys,
255 };
256 
257 template <typename T>
258 VISKORES_CONT Keys<T>::Keys() = default;
259 
260 namespace internal
261 {
262 
263 template <typename KeyType>
264 inline auto SchedulingRange(const viskores::worklet::Keys<KeyType>& inputDomain)
265  -> decltype(inputDomain.GetInputRange())
266 {
267  return inputDomain.GetInputRange();
268 }
269 
270 template <typename KeyType>
271 inline auto SchedulingRange(const viskores::worklet::Keys<KeyType>* const inputDomain)
272  -> decltype(inputDomain->GetInputRange())
273 {
274  return inputDomain->GetInputRange();
275 }
276 
277 inline auto SchedulingRange(const viskores::worklet::internal::KeysBase& inputDomain)
278  -> decltype(inputDomain.GetInputRange())
279 {
280  return inputDomain.GetInputRange();
281 }
282 
283 inline auto SchedulingRange(const viskores::worklet::internal::KeysBase* const inputDomain)
284  -> decltype(inputDomain->GetInputRange())
285 {
286  return inputDomain->GetInputRange();
287 }
288 } // namespace internal
289 }
290 } // namespace viskores::worklet
291 
292 // Here we implement the type checks and transports that rely on the Keys
293 // class. We implement them here because the Keys class is not accessible to
294 // the arg classes. (The worklet package depends on the cont and exec packages,
295 // not the other way around.)
296 
297 namespace viskores
298 {
299 namespace cont
300 {
301 namespace arg
302 {
303 
304 template <typename KeyType>
306 {
307  static constexpr bool value = std::is_base_of<viskores::worklet::internal::KeysBase,
308  typename std::decay<KeyType>::type>::value;
309 };
310 
311 template <typename KeyType, typename Device>
313 {
314  using ContObjectType = KeyType;
315  using ExecObjectType = typename ContObjectType::ExecLookup;
316 
319  const ContObjectType& inputDomain,
320  viskores::Id,
321  viskores::Id,
322  viskores::cont::Token& token) const
323  {
324  if (object != inputDomain)
325  {
326  throw viskores::cont::ErrorBadValue("A Keys object must be the input domain.");
327  }
328 
329  return object.PrepareForInput(Device(), token);
330  }
331 
332  // If you get a compile error here, it means that you have used a KeysIn
333  // tag in your ControlSignature that was not marked as the InputDomain.
334  template <typename InputDomainType>
335  VISKORES_CONT ExecObjectType operator()(const ContObjectType&,
336  const InputDomainType&,
337  viskores::Id,
338  viskores::Id) const = delete;
339 };
340 
341 template <typename ArrayHandleType, typename Device>
342 struct Transport<viskores::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device>
343 {
344  VISKORES_IS_ARRAY_HANDLE(ArrayHandleType);
345 
346  using ContObjectType = ArrayHandleType;
347 
350  using GroupedArrayType =
352 
354 
356  const viskores::worklet::internal::KeysBase& keys,
357  viskores::Id,
358  viskores::Id,
359  viskores::cont::Token& token) const
360  {
361  if (object.GetNumberOfValues() != keys.GetNumberOfValues())
362  {
363  throw viskores::cont::ErrorBadValue("Input values array is wrong size.");
364  }
365 
366  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
367  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
368  // There is a bit of an issue here where groupedArray goes out of scope,
369  // and array portals usually rely on the associated array handle
370  // maintaining the resources it points to. However, the entire state of the
371  // portal should be self contained except for the data managed by the
372  // object argument, which should stay in scope.
373  return groupedArray.PrepareForInput(Device(), token);
374  }
375 };
376 
377 template <typename ArrayHandleType, typename Device>
379 {
380  VISKORES_IS_ARRAY_HANDLE(ArrayHandleType);
381 
382  using ContObjectType = ArrayHandleType;
383 
386  using GroupedArrayType =
388 
390 
392  const viskores::worklet::internal::KeysBase& keys,
393  viskores::Id,
394  viskores::Id,
395  viskores::cont::Token& token) const
396  {
397  if (object.GetNumberOfValues() != keys.GetNumberOfValues())
398  {
399  throw viskores::cont::ErrorBadValue("Input/output values array is wrong size.");
400  }
401 
402  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
403  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
404  // There is a bit of an issue here where groupedArray goes out of scope,
405  // and array portals usually rely on the associated array handle
406  // maintaining the resources it points to. However, the entire state of the
407  // portal should be self contained except for the data managed by the
408  // object argument, which should stay in scope.
409  return groupedArray.PrepareForInPlace(Device(), token);
410  }
411 };
412 
413 template <typename ArrayHandleType, typename Device>
415 {
416  VISKORES_IS_ARRAY_HANDLE(ArrayHandleType);
417 
418  using ContObjectType = ArrayHandleType;
419 
422  using GroupedArrayType =
424 
426 
428  const viskores::worklet::internal::KeysBase& keys,
429  viskores::Id,
430  viskores::Id,
431  viskores::cont::Token& token) const
432  {
433  // The PrepareForOutput for ArrayHandleGroupVecVariable and
434  // ArrayHandlePermutation cannot determine the actual size expected for the
435  // target array (object), so we have to make sure it gets allocated here.
436  object.PrepareForOutput(keys.GetNumberOfValues(), Device(), token);
437 
438  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
439  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
440  // There is a bit of an issue here where groupedArray goes out of scope,
441  // and array portals usually rely on the associated array handle
442  // maintaining the resources it points to. However, the entire state of the
443  // portal should be self contained except for the data managed by the
444  // object argument, which should stay in scope.
445  return groupedArray.PrepareForOutput(keys.GetInputRange(), Device(), token);
446  }
447 };
448 }
449 }
450 } // namespace viskores::cont::arg
451 
452 #ifndef viskores_worklet_Keys_cxx
453 
454 #define VISKORES_KEYS_EXPORT(T) \
455  extern template class VISKORES_WORKLET_TEMPLATE_EXPORT viskores::worklet::Keys<T>; \
456  extern template VISKORES_WORKLET_TEMPLATE_EXPORT VISKORES_CONT void \
457  viskores::worklet::Keys<T>::BuildArrays(const viskores::cont::ArrayHandle<T>& keys, \
458  viskores::worklet::KeysSortType sort, \
459  viskores::cont::DeviceAdapterId device)
460 
461 VISKORES_KEYS_EXPORT(viskores::UInt8);
462 VISKORES_KEYS_EXPORT(viskores::HashType);
463 VISKORES_KEYS_EXPORT(viskores::Id);
464 VISKORES_KEYS_EXPORT(viskores::Id2);
465 VISKORES_KEYS_EXPORT(viskores::Id3);
467 VISKORES_KEYS_EXPORT(Pair_UInt8_Id2);
468 #ifdef VISKORES_USE_64BIT_IDS
469 VISKORES_KEYS_EXPORT(viskores::IdComponent);
470 #endif
471 
472 #undef VISKORES_KEYS_EXPORT
473 
474 #endif // !viskores_worklet_Keys_cxx
475 
476 #endif //viskores_worklet_Keys_h
viskores::cont::ArrayHandleGroupVecVariable::ReadPortalType
typename Superclass::ReadPortalType ReadPortalType
Definition: ArrayHandleGroupVecVariable.h:299
TransportTagKeyedValuesInOut.h
ArrayHandle.h
viskores::operator==
bool operator==(const viskores::Matrix< T, NumRow, NumCol > &a, const viskores::Matrix< T, NumRow, NumCol > &b)
Definition: Matrix.h:632
TransportTagKeyedValuesIn.h
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeysIn, KeyType, Device >::ExecObjectType
typename ContObjectType::ExecLookup ExecObjectType
Definition: Keys.h:315
StableSortIndices.h
ArrayHandleCast.h
TransportTagKeyedValuesOut.h
viskores::cont::ArrayHandle::PrepareForInput
ReadPortalType PrepareForInput(viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:615
viskores::worklet::Keys::PrepareForInput
ExecLookup PrepareForInput(viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Definition: Keys.h:225
viskores::worklet::Keys::KeyType
T KeyType
Definition: Keys.h:145
viskores::cont::arg::Transport
Class for transporting from the control to the execution environment.
Definition: Transport.h:46
viskores::cont::arg::TransportTagKeyedValuesOut
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesOut.h:36
VISKORES_IS_ARRAY_HANDLE
#define VISKORES_IS_ARRAY_HANDLE(T)
Checks that the given type is a viskores::cont::ArrayHandle.
Definition: ArrayHandle.h:145
viskores::cont::arg::Transport::ExecObjectType
typename ContObjectType::ReadPortalType ExecObjectType
The type used in the execution environment.
Definition: Transport.h:56
DispatcherBase.h
viskores::cont::ArrayHandle< viskores::Id >
ArrayHandleConstant.h
viskores::worklet::Keys::GetUniqueKeys
KeyArrayHandleType GetUniqueKeys() const
Returns an array of unique keys.
Definition: Keys.h:188
viskores::worklet::Keys::operator!=
bool operator!=(const viskores::worklet::Keys< KeyType > &other) const
Definition: Keys.h:241
viskores::cont::DeviceAdapterTagAny
Tag for a device adapter used to specify that any device may be used for an operation.
Definition: DeviceAdapterTag.h:194
viskores::cont::ArrayHandle::ReadPortalType
typename StorageType::ReadPortalType ReadPortalType
The type of portal used when accessing data in a read-only mode.
Definition: ArrayHandle.h:325
viskores::IdComponent
viskores::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:202
viskores::worklet::Keys
Manage keys for a viskores::worklet::WorkletReduceByKey.
Definition: Keys.h:142
viskores::worklet::KeysSortType
KeysSortType
Select the type of sort for BuildArrays calls.
Definition: Keys.h:119
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::WritePortalType ExecObjectType
Definition: Keys.h:389
viskores_worklet_export.h
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
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::worklet::Keys::Keys
Keys(const viskores::cont::ArrayHandle< KeyType, KeyStorage > &keys, viskores::cont::DeviceAdapterId device=viskores::cont::DeviceAdapterTagAny())
Construct a Keys class from an array of keys.
Definition: Keys.h:161
ArrayHandlePermutation.h
Algorithm.h
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeysIn, KeyType, Device >::operator()
ExecObjectType operator()(const ContObjectType &object, const ContObjectType &inputDomain, viskores::Id, viskores::Id, viskores::cont::Token &token) const
Definition: Keys.h:318
viskores::cont::ArrayHandle::PrepareForInPlace
WritePortalType PrepareForInPlace(viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares this array to be used in an in-place operation (both as input and output) in the execution e...
Definition: ArrayHandle.h:634
ArrayHandleIndex.h
viskores::cont::arg::TransportTagKeyedValuesInOut
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesInOut.h:36
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::operator()
ExecObjectType operator()(ContObjectType object, const viskores::worklet::internal::KeysBase &keys, viskores::Id, viskores::Id, viskores::cont::Token &token) const
Definition: Keys.h:427
VISKORES_DEPRECATED
#define VISKORES_DEPRECATED(...)
Definition: Deprecated.h:156
TransportTagKeysIn.h
viskores::cont::arg::TransportTagKeyedValuesIn
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesIn.h:36
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::operator()
ExecObjectType operator()(const ContObjectType &object, const viskores::worklet::internal::KeysBase &keys, viskores::Id, viskores::Id, viskores::cont::Token &token) const
Definition: Keys.h:355
viskores::cont::ArrayHandle::PrepareForOutput
WritePortalType PrepareForOutput(viskores::Id numberOfValues, viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares (allocates) this array to be used as an output from an operation in the execution environmen...
Definition: ArrayHandle.h:654
viskores::worklet::KeysSortType::Unstable
@ Unstable
viskores::Pair
A viskores::Pair is essentially the same as an STL pair object except that the methods (constructors ...
Definition: Pair.h:37
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:382
BinaryOperators.h
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::arg::TransportTagKeysIn
Transport tag for keys in a reduce by key.
Definition: TransportTagKeysIn.h:36
viskores::cont::arg::TypeCheckTagKeys
Check for a Keys object.
Definition: TypeCheckTagKeys.h:32
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::cont::arg::Transport< viskores::cont::arg::TransportTagKeysIn, KeyType, Device >::ContObjectType
KeyType ContObjectType
Definition: Keys.h:314
Deprecated.h
viskores::worklet::Keys::Keys
Keys()
viskores::operator!=
bool operator!=(const viskores::Matrix< T, NumRow, NumCol > &a, const viskores::Matrix< T, NumRow, NumCol > &b)
Definition: Matrix.h:646
viskores::worklet::Keys::operator==
bool operator==(const viskores::worklet::Keys< KeyType > &other) const
Definition: Keys.h:234
ArrayHandleGroupVecVariable.h
viskores::cont::ArrayHandleGroupVecVariable::WritePortalType
typename Superclass::WritePortalType WritePortalType
Definition: ArrayHandleGroupVecVariable.h:299
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::WritePortalType ExecObjectType
Definition: Keys.h:425
Logging.h
Logging utilities.
TypeCheckTagKeys.h
Hash.h
viskores::worklet::KeysSortType::Stable
@ Stable
viskores::cont::ArrayHandleGroupVecVariable
Fancy array handle that groups values into vectors of different sizes.
Definition: ArrayHandleGroupVecVariable.h:279
viskores::cont::arg::Transport::operator()
VISKORES_CONT ExecObjectType operator()(const ContObjectType contData, const InputDomainType &inputDomain viskores::Id outputSize) const
Send data to the execution environment.
viskores::Vec< viskores::Id, 2 >
viskores::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:43
viskores::cont::arg::TypeCheck::value
static constexpr bool value
The static constant boolean value is set to true if the type is valid for the given check tag and fal...
Definition: TypeCheck.h:47
viskores::HashType
viskores::UInt32 HashType
Definition: Hash.h:28
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:346
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::ReadPortalType ExecObjectType
Definition: Keys.h:353
ReduceByKeyLookup.h
viskores::cont::ArrayHandlePermutation
Implicitly permutes the values in an array.
Definition: ArrayHandlePermutation.h:242
viskores::cont::arg::TypeCheck
Class for checking that a type matches the semantics for an argument.
Definition: TypeCheck.h:42
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:418
viskores::cont::arg::Transport< viskores::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::operator()
ExecObjectType operator()(ContObjectType object, const viskores::worklet::internal::KeysBase &keys, viskores::Id, viskores::Id, viskores::cont::Token &token) const
Definition: Keys.h:391