1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 // This software is distributed WITHOUT ANY WARRANTY; without even
6 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 // PURPOSE. See the above copyright notice for more information.
8 //
9 // Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 // Copyright 2017 UT-Battelle, LLC.
11 // Copyright 2017 Los Alamos National Security.
12 //
13 // Under the terms of Contract DE-NA0003525 with NTESS,
14 // the U.S. Government retains certain rights in this software.
15 //
16 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 // Laboratory (LANL), the U.S. Government retains certain rights in
18 // this software.
19 //============================================================================
20 #ifndef vtk_m_cont_ArrayRangeCompute_hxx
21 #define vtk_m_cont_ArrayRangeCompute_hxx
22
23 #include <vtkm/cont/ArrayRangeCompute.h>
24
25 #include <vtkm/BinaryOperators.h>
26 #include <vtkm/VecTraits.h>
27
28 #include <vtkm/cont/Algorithm.h>
29
30 #include <limits>
31
32 namespace vtkm
33 {
34 namespace cont
35 {
36
37 namespace detail
38 {
39
40 struct ArrayRangeComputeFunctor
41 {
42 template <typename Device, typename T, typename S>
operator ()vtkm::cont::detail::ArrayRangeComputeFunctor43 VTKM_CONT bool operator()(Device,
44 const vtkm::cont::ArrayHandle<T, S>& handle,
45 const vtkm::Vec<T, 2>& initialValue,
46 vtkm::Vec<T, 2>& result) const
47 {
48 VTKM_IS_DEVICE_ADAPTER_TAG(Device);
49 using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<Device>;
50 result = Algorithm::Reduce(handle, initialValue, vtkm::MinAndMax<T>());
51 return true;
52 }
53 };
54
55 template <typename T, typename S>
ArrayRangeComputeImpl(const vtkm::cont::ArrayHandle<T,S> & input,vtkm::cont::RuntimeDeviceTracker & tracker)56 inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
57 const vtkm::cont::ArrayHandle<T, S>& input,
58 vtkm::cont::RuntimeDeviceTracker& tracker)
59 {
60 using VecTraits = vtkm::VecTraits<T>;
61 using CT = typename VecTraits::ComponentType;
62 //We want to minimize the amount of code that we do in try execute as
63 //it is repeated for each
64 vtkm::cont::ArrayHandle<vtkm::Range> range;
65 range.Allocate(VecTraits::NUM_COMPONENTS);
66
67 if (input.GetNumberOfValues() < 1)
68 {
69 auto portal = range.GetPortalControl();
70 for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
71 {
72 portal.Set(i, vtkm::Range());
73 }
74 }
75 else
76 {
77 //We used the limits, so that we don't need to sync the array handle
78 //
79 vtkm::Vec<T, 2> result;
80 vtkm::Vec<T, 2> initial;
81 initial[0] = T(std::numeric_limits<CT>::max());
82 initial[1] = T(std::numeric_limits<CT>::lowest());
83
84 const bool rangeComputed =
85 vtkm::cont::TryExecute(detail::ArrayRangeComputeFunctor{}, tracker, input, initial, result);
86 if (!rangeComputed)
87 {
88 ThrowArrayRangeComputeFailed();
89 }
90 else
91 {
92 auto portal = range.GetPortalControl();
93 for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
94 {
95 portal.Set(i,
96 vtkm::Range(VecTraits::GetComponent(result[0], i),
97 VecTraits::GetComponent(result[1], i)));
98 }
99 }
100 }
101 return range;
102 }
103
104 } // namespace detail
105
106 template <typename ArrayHandleType>
ArrayRangeCompute(const ArrayHandleType & input,vtkm::cont::RuntimeDeviceTracker tracker)107 inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
108 const ArrayHandleType& input,
109 vtkm::cont::RuntimeDeviceTracker tracker)
110 {
111 VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
112 return detail::ArrayRangeComputeImpl(input, tracker);
113 }
114 }
115 } // namespace vtkm::cont
116
117 #endif //vtk_m_cont_ArrayRangeCompute_hxx
118