18 #ifndef viskores_cont_ArrayHandleCartesianProduct_h
19 #define viskores_cont_ArrayHandleCartesianProduct_h
39 template <
typename ValueType_,
40 typename PortalTypeFirst_,
41 typename PortalTypeSecond_,
42 typename PortalTypeThird_>
43 class VISKORES_ALWAYS_EXPORT ArrayPortalCartesianProduct
46 using ValueType = ValueType_;
47 using IteratorType = ValueType_;
48 using PortalTypeFirst = PortalTypeFirst_;
49 using PortalTypeSecond = PortalTypeSecond_;
50 using PortalTypeThird = PortalTypeThird_;
52 using set_supported_p1 = viskores::internal::PortalSupportsSets<PortalTypeFirst>;
53 using set_supported_p2 = viskores::internal::PortalSupportsSets<PortalTypeSecond>;
54 using set_supported_p3 = viskores::internal::PortalSupportsSets<PortalTypeThird>;
56 using Writable = std::integral_constant<bool,
57 set_supported_p1::value && set_supported_p2::value &&
58 set_supported_p3::value>;
62 ArrayPortalCartesianProduct()
70 ArrayPortalCartesianProduct(
const PortalTypeFirst& portalfirst,
71 const PortalTypeSecond& portalsecond,
72 const PortalTypeThird& portalthird)
73 : PortalFirst(portalfirst)
74 , PortalSecond(portalsecond)
75 , PortalThird(portalthird)
84 template <
class OtherV,
class OtherP1,
class OtherP2,
class OtherP3>
86 const ArrayPortalCartesianProduct<OtherV, OtherP1, OtherP2, OtherP3>& src)
87 : PortalFirst(src.GetPortalFirst())
88 , PortalSecond(src.GetPortalSecond())
89 , PortalThird(src.GetPortalThird())
97 return this->PortalFirst.GetNumberOfValues() * this->PortalSecond.GetNumberOfValues() *
98 this->PortalThird.GetNumberOfValues();
108 viskores::Id dim1 = this->PortalFirst.GetNumberOfValues();
109 viskores::Id dim2 = this->PortalSecond.GetNumberOfValues();
117 this->PortalFirst.Get(i1), this->PortalSecond.Get(i2), this->PortalThird.Get(i3));
122 template <
typename Writable_ = Writable,
123 typename =
typename std::enable_if<Writable_::value>::type>
129 viskores::Id dim1 = this->PortalFirst.GetNumberOfValues();
130 viskores::Id dim2 = this->PortalSecond.GetNumberOfValues();
138 this->PortalFirst.Set(i1, value[0]);
139 this->PortalSecond.Set(i2, value[1]);
140 this->PortalThird.Set(i3, value[2]);
145 const PortalTypeFirst& GetFirstPortal()
const {
return this->PortalFirst; }
149 const PortalTypeSecond& GetSecondPortal()
const {
return this->PortalSecond; }
153 const PortalTypeThird& GetThirdPortal()
const {
return this->PortalThird; }
156 PortalTypeFirst PortalFirst;
157 PortalTypeSecond PortalSecond;
158 PortalTypeThird PortalThird;
168 template <
typename StorageTag1,
typename StorageTag2,
typename StorageTag3>
179 template <
typename AH1,
typename AH2,
typename AH3>
180 struct ArrayHandleCartesianProductTraits
186 using ComponentType =
typename AH1::ValueType;
188 (std::is_same<ComponentType, typename AH2::ValueType>::value),
189 "All arrays for ArrayHandleCartesianProduct must have the same value type. "
190 "Use ArrayHandleCast as necessary to make types match.");
192 (std::is_same<ComponentType, typename AH3::ValueType>::value),
193 "All arrays for ArrayHandleCartesianProduct must have the same value type. "
194 "Use ArrayHandleCast as necessary to make types match.");
203 typename AH2::StorageTag,
204 typename AH3::StorageTag>;
211 template <
typename T,
typename ST1,
typename ST2,
typename ST3>
216 std::array<std::size_t, 4> BufferOffset;
219 using Storage1 = viskores::cont::internal::Storage<T, ST1>;
220 using Storage2 = viskores::cont::internal::Storage<T, ST2>;
221 using Storage3 = viskores::cont::internal::Storage<T, ST3>;
227 VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> GetBuffers(
228 const std::vector<viskores::cont::internal::Buffer>& buffers,
229 std::size_t subArray)
231 Info info = buffers[0].GetMetaData<Info>();
232 return std::vector<viskores::cont::internal::Buffer>(
233 buffers.begin() + info.BufferOffset[subArray - 1],
234 buffers.begin() + info.BufferOffset[subArray]);
240 using ReadPortalType =
241 viskores::internal::ArrayPortalCartesianProduct<viskores::Vec<T, 3>,
242 typename Storage1::ReadPortalType,
243 typename Storage2::ReadPortalType,
244 typename Storage3::ReadPortalType>;
245 using WritePortalType =
246 viskores::internal::ArrayPortalCartesianProduct<viskores::Vec<T, 3>,
247 typename Storage1::WritePortalType,
248 typename Storage2::WritePortalType,
249 typename Storage3::WritePortalType>;
252 const std::vector<viskores::cont::internal::Buffer>&)
258 const std::vector<viskores::cont::internal::Buffer>& buffers)
260 return (Storage1::GetNumberOfValues(GetBuffers(buffers, 1)) *
261 Storage2::GetNumberOfValues(GetBuffers(buffers, 2)) *
262 Storage3::GetNumberOfValues(GetBuffers(buffers, 3)));
265 VISKORES_CONT static void Fill(
const std::vector<viskores::cont::internal::Buffer>& buffers,
271 if ((startIndex != 0) || (endIndex != GetNumberOfValues(buffers)))
274 "Fill for ArrayHandleCartesianProduct can only be used to fill entire array.");
276 auto subBuffers = GetBuffers(buffers, 1);
277 Storage1::Fill(subBuffers, fillValue[0], 0, Storage1::GetNumberOfValues(subBuffers), token);
278 subBuffers = GetBuffers(buffers, 2);
279 Storage2::Fill(subBuffers, fillValue[1], 0, Storage2::GetNumberOfValues(subBuffers), token);
280 subBuffers = GetBuffers(buffers, 3);
281 Storage3::Fill(subBuffers, fillValue[2], 0, Storage3::GetNumberOfValues(subBuffers), token);
285 const std::vector<viskores::cont::internal::Buffer>& buffers,
289 return ReadPortalType(Storage1::CreateReadPortal(GetBuffers(buffers, 1), device, token),
290 Storage2::CreateReadPortal(GetBuffers(buffers, 2), device, token),
291 Storage3::CreateReadPortal(GetBuffers(buffers, 3), device, token));
295 const std::vector<viskores::cont::internal::Buffer>& buffers,
299 return WritePortalType(Storage1::CreateWritePortal(GetBuffers(buffers, 1), device, token),
300 Storage2::CreateWritePortal(GetBuffers(buffers, 2), device, token),
301 Storage3::CreateWritePortal(GetBuffers(buffers, 3), device, token));
305 const std::vector<viskores::cont::internal::Buffer>& buffers)
307 return Array1(GetBuffers(buffers, 1));
310 const std::vector<viskores::cont::internal::Buffer>& buffers)
312 return Array2(GetBuffers(buffers, 2));
315 const std::vector<viskores::cont::internal::Buffer>& buffers)
317 return Array3(GetBuffers(buffers, 3));
320 VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers(
321 const Array1& array1 = Array1{},
322 const Array2& array2 = Array2{},
323 const Array3& array3 = Array3{})
325 const std::vector<viskores::cont::internal::Buffer>& buffers1 = array1.GetBuffers();
326 const std::vector<viskores::cont::internal::Buffer>& buffers2 = array2.GetBuffers();
327 const std::vector<viskores::cont::internal::Buffer>& buffers3 = array3.GetBuffers();
330 info.BufferOffset[0] = 1;
331 info.BufferOffset[1] = info.BufferOffset[0] + buffers1.size();
332 info.BufferOffset[2] = info.BufferOffset[1] + buffers2.size();
333 info.BufferOffset[3] = info.BufferOffset[2] + buffers3.size();
335 return viskores::cont::internal::CreateBuffers(info, buffers1, buffers2, buffers3);
344 template <
typename FirstHandleType,
typename SecondHandleType,
typename ThirdHandleType>
346 :
public internal::ArrayHandleCartesianProductTraits<FirstHandleType,
360 (
typename internal::ArrayHandleCartesianProductTraits<FirstHandleType,
368 const SecondHandleType& secondArray,
369 const ThirdHandleType& thirdArray)
384 return StorageType::GetArrayHandle1(this->
GetBuffers());
389 return StorageType::GetArrayHandle2(this->
GetBuffers());
394 return StorageType::GetArrayHandle3(this->
GetBuffers());
401 template <
typename FirstHandleType,
typename SecondHandleType,
typename ThirdHandleType>
405 const SecondHandleType& second,
406 const ThirdHandleType& third)
409 first, second, third);
419 template <
typename... STs>
421 : viskores::cont::internal::ArrayExtractComponentImplInherit<STs...>
423 template <
typename T>
436 modulo = dims[component];
453 template <
typename T,
typename ST,
typename CartesianArrayType>
456 const CartesianArrayType& cartesianArray,
462 strideArray = ArrayExtractComponentImpl<ST>{}(componentArray, subIndex, allowCopy);
468 return viskores::cont::internal::ArrayExtractComponentFallback(
469 cartesianArray, (productIndex * NUM_SUB_COMPONENTS) + subIndex, allowCopy);
472 viskores::Id3 dims = { cartesianArray.GetFirstArray().GetNumberOfValues(),
473 cartesianArray.GetSecondArray().GetNumberOfValues(),
474 cartesianArray.GetThirdArray().GetNumberOfValues() };
476 return this->AdjustStrideForComponent(
477 strideArray, dims, productIndex, cartesianArray.GetNumberOfValues());
480 template <
typename T>
492 switch (productIndex)
495 return this->GetStrideForComponentArray(
496 array.GetFirstArray(), array, subIndex, productIndex, allowCopy);
498 return this->GetStrideForComponentArray(
499 array.GetSecondArray(), array, subIndex, productIndex, allowCopy);
501 return this->GetStrideForComponentArray(
502 array.GetThirdArray(), array, subIndex, productIndex, allowCopy);
509 template <
typename T,
typename S>
513 bool computeFiniteRange,
516 template <
typename S>
517 struct ArrayRangeComputeImpl;
519 template <
typename ST1,
typename ST2,
typename ST3>
520 struct VISKORES_CONT_EXPORT
521 ArrayRangeComputeImpl<
viskores::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>
523 template <
typename T>
529 bool computeFiniteRange,
534 return viskores::cont::internal::ArrayRangeComputeGeneric(
535 input_, maskArray, computeFiniteRange, device);
538 const auto& input =
static_cast<
545 ranges[0] = viskores::cont::internal::ArrayRangeComputeImpl<ST1>{}(
546 input.GetFirstArray(), maskArray, computeFiniteRange, device);
547 ranges[1] = viskores::cont::internal::ArrayRangeComputeImpl<ST2>{}(
548 input.GetSecondArray(), maskArray, computeFiniteRange, device);
549 ranges[2] = viskores::cont::internal::ArrayRangeComputeImpl<ST3>{}(
550 input.GetThirdArray(), maskArray, computeFiniteRange, device);
560 for (
viskores::Id j = 0; j < rangePortal.GetNumberOfValues(); ++j, ++index)
562 resultPortal.Set(index, rangePortal.Get(j));
582 template <
typename AH1,
typename AH2,
typename AH3>
583 struct SerializableTypeString<
viskores::cont::ArrayHandleCartesianProduct<AH1, AH2, AH3>>
593 template <
typename T,
typename ST1,
typename ST2,
typename ST3>
594 struct SerializableTypeString<
595 viskores::cont::ArrayHandle<viskores::Vec<T, 3>,
596 viskores::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>>
597 : SerializableTypeString<
598 viskores::cont::ArrayHandleCartesianProduct<viskores::cont::ArrayHandle<T, ST1>,
599 viskores::cont::ArrayHandle<T, ST2>,
600 viskores::cont::ArrayHandle<T, ST3>>>
609 template <
typename AH1,
typename AH2,
typename AH3>
610 struct Serialization<
viskores::cont::ArrayHandleCartesianProduct<AH1, AH2, AH3>>
617 static VISKORES_CONT void save(BinaryBuffer& bb,
const BaseType& obj)
620 viskoresdiy::save(bb, array.GetFirstArray());
621 viskoresdiy::save(bb, array.GetSecondArray());
622 viskoresdiy::save(bb, array.GetThirdArray());
639 template <
typename T,
typename ST1,
typename ST2,
typename ST3>
640 struct Serialization<
641 viskores::cont::ArrayHandle<viskores::Vec<T, 3>,
642 viskores::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>>
643 : Serialization<viskores::cont::ArrayHandleCartesianProduct<viskores::cont::ArrayHandle<T, ST1>,
644 viskores::cont::ArrayHandle<T, ST2>,
645 viskores::cont::ArrayHandle<T, ST3>>>
651 #endif //viskores_cont_ArrayHandleCartesianProduct_h