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 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 //  Copyright 2014 UT-Battelle, LLC.
11 //  Copyright 2014 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_ArrayHandleCounting_h
21 #define vtk_m_cont_ArrayHandleCounting_h
22 
23 #include <vtkm/cont/ArrayHandle.h>
24 #include <vtkm/cont/StorageImplicit.h>
25 
26 #include <vtkm/VecTraits.h>
27 
28 namespace vtkm
29 {
30 namespace cont
31 {
32 
33 namespace internal
34 {
35 
36 /// \brief An implicit array portal that returns an counting value.
37 template <class CountingValueType>
38 class VTKM_ALWAYS_EXPORT ArrayPortalCounting
39 {
40   using ComponentType = typename vtkm::VecTraits<CountingValueType>::ComponentType;
41 
42 public:
43   using ValueType = CountingValueType;
44 
45   VTKM_EXEC_CONT
ArrayPortalCounting()46   ArrayPortalCounting()
47     : Start(0)
48     , Step(1)
49     , NumberOfValues(0)
50   {
51   }
52 
53   VTKM_EXEC_CONT
ArrayPortalCounting(ValueType start,ValueType step,vtkm::Id numValues)54   ArrayPortalCounting(ValueType start, ValueType step, vtkm::Id numValues)
55     : Start(start)
56     , Step(step)
57     , NumberOfValues(numValues)
58   {
59   }
60 
61   template <typename OtherValueType>
ArrayPortalCounting(const ArrayPortalCounting<OtherValueType> & src)62   VTKM_EXEC_CONT ArrayPortalCounting(const ArrayPortalCounting<OtherValueType>& src)
63     : Start(src.Start)
64     , Step(src.Step)
65     , NumberOfValues(src.NumberOfValues)
66   {
67   }
68 
69   template <typename OtherValueType>
70   VTKM_EXEC_CONT ArrayPortalCounting<ValueType>& operator=(
71     const ArrayPortalCounting<OtherValueType>& src)
72   {
73     this->Start = src.Start;
74     this->Step = src.Step;
75     this->NumberOfValues = src.NumberOfValues;
76     return *this;
77   }
78 
79   VTKM_EXEC_CONT
GetStart()80   ValueType GetStart() const { return this->Start; }
81 
82   VTKM_EXEC_CONT
GetStep()83   ValueType GetStep() const { return this->Step; }
84 
85   VTKM_EXEC_CONT
GetNumberOfValues()86   vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
87 
88   VTKM_EXEC_CONT
Get(vtkm::Id index)89   ValueType Get(vtkm::Id index) const
90   {
91     return ValueType(this->Start + this->Step * ValueType(static_cast<ComponentType>(index)));
92   }
93 
94   VTKM_EXEC_CONT
Set(vtkm::Id vtkmNotUsed (index),const ValueType & vtkmNotUsed (value))95   void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const
96   {
97     VTKM_ASSERT(false && "Cannot write to read-only counting array.");
98   }
99 
100 private:
101   ValueType Start;
102   ValueType Step;
103   vtkm::Id NumberOfValues;
104 };
105 
106 /// A convenience class that provides a typedef to the appropriate tag for
107 /// a counting storage.
108 template <typename ConstantValueType>
109 struct ArrayHandleCountingTraits
110 {
111   using Tag =
112     vtkm::cont::StorageTagImplicit<vtkm::cont::internal::ArrayPortalCounting<ConstantValueType>>;
113 };
114 
115 } // namespace internal
116 
117 /// ArrayHandleCounting is a specialization of ArrayHandle. By default it
118 /// contains a increment value, that is increment for each step between zero
119 /// and the passed in length
120 template <typename CountingValueType>
121 class ArrayHandleCounting : public vtkm::cont::ArrayHandle<
122                               CountingValueType,
123                               typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag>
124 {
125 public:
126   VTKM_ARRAY_HANDLE_SUBCLASS(
127     ArrayHandleCounting,
128     (ArrayHandleCounting<CountingValueType>),
129     (vtkm::cont::ArrayHandle<
130       CountingValueType,
131       typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag>));
132 
133   VTKM_CONT
ArrayHandleCounting(CountingValueType start,CountingValueType step,vtkm::Id length)134   ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::Id length)
135     : Superclass(typename Superclass::PortalConstControl(start, step, length))
136   {
137   }
138 };
139 
140 /// A convenience function for creating an ArrayHandleCounting. It takes the
141 /// value to start counting from and and the number of times to increment.
142 template <typename CountingValueType>
143 VTKM_CONT vtkm::cont::ArrayHandleCounting<CountingValueType>
make_ArrayHandleCounting(CountingValueType start,CountingValueType step,vtkm::Id length)144 make_ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::Id length)
145 {
146   return vtkm::cont::ArrayHandleCounting<CountingValueType>(start, step, length);
147 }
148 }
149 } // namespace vtkm::cont
150 
151 //=============================================================================
152 // Specializations of serialization related classes
153 namespace vtkm
154 {
155 namespace cont
156 {
157 
158 template <typename T>
159 struct TypeString<vtkm::cont::ArrayHandleCounting<T>>
160 {
161   static VTKM_CONT const std::string& Get()
162   {
163     static std::string name = "AH_Counting<" + TypeString<T>::Get() + ">";
164     return name;
165   }
166 };
167 
168 template <typename T>
169 struct TypeString<
170   vtkm::cont::ArrayHandle<T, typename vtkm::cont::ArrayHandleCounting<T>::StorageTag>>
171   : TypeString<vtkm::cont::ArrayHandleCounting<T>>
172 {
173 };
174 }
175 } // vtkm::cont
176 
177 namespace diy
178 {
179 
180 template <typename T>
181 struct Serialization<vtkm::cont::ArrayHandleCounting<T>>
182 {
183 private:
184   using Type = vtkm::cont::ArrayHandleCounting<T>;
185   using BaseType = vtkm::cont::ArrayHandle<typename Type::ValueType, typename Type::StorageTag>;
186 
187 public:
188   static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
189   {
190     auto portal = obj.GetPortalConstControl();
191     diy::save(bb, portal.GetStart());
192     diy::save(bb, portal.GetStep());
193     diy::save(bb, portal.GetNumberOfValues());
194   }
195 
196   static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
197   {
198     T start{}, step{};
199     vtkm::Id count = 0;
200 
201     diy::load(bb, start);
202     diy::load(bb, step);
203     diy::load(bb, count);
204 
205     obj = vtkm::cont::make_ArrayHandleCounting(start, step, count);
206   }
207 };
208 
209 template <typename T>
210 struct Serialization<
211   vtkm::cont::ArrayHandle<T, typename vtkm::cont::ArrayHandleCounting<T>::StorageTag>>
212   : Serialization<vtkm::cont::ArrayHandleCounting<T>>
213 {
214 };
215 } // diy
216 
217 #endif //vtk_m_cont_ArrayHandleCounting_h
218