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