1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkScaledSOADataArrayTemplate.h
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #ifndef vtkScaledSOADataArrayTemplate_txx
17 #define vtkScaledSOADataArrayTemplate_txx
18
19 #ifdef VTK_SCALED_SOA_DATA_ARRAY_TEMPLATE_INSTANTIATING
20 #define VTK_GDA_VALUERANGE_INSTANTIATING
21 #include "vtkDataArrayPrivate.txx"
22 #undef VTK_GDA_VALUERANGE_INSTANTIATING
23 #endif
24
25 #include "vtkScaledSOADataArrayTemplate.h"
26
27 #include "vtkArrayIteratorTemplate.h"
28 #include "vtkBuffer.h"
29
30 #include <cassert>
31
32 //-----------------------------------------------------------------------------
33 template <class ValueType>
New()34 vtkScaledSOADataArrayTemplate<ValueType>* vtkScaledSOADataArrayTemplate<ValueType>::New()
35 {
36 VTK_STANDARD_NEW_BODY(vtkScaledSOADataArrayTemplate<ValueType>);
37 }
38
39 //-----------------------------------------------------------------------------
40 template <class ValueType>
vtkScaledSOADataArrayTemplate()41 vtkScaledSOADataArrayTemplate<ValueType>::vtkScaledSOADataArrayTemplate()
42 : AoSCopy(nullptr)
43 , Scale(1)
44 {
45 }
46
47 //-----------------------------------------------------------------------------
48 template <class ValueType>
~vtkScaledSOADataArrayTemplate()49 vtkScaledSOADataArrayTemplate<ValueType>::~vtkScaledSOADataArrayTemplate()
50 {
51 for (size_t cc = 0; cc < this->Data.size(); ++cc)
52 {
53 this->Data[cc]->Delete();
54 }
55 this->Data.clear();
56 if (this->AoSCopy)
57 {
58 this->AoSCopy->Delete();
59 this->AoSCopy = nullptr;
60 }
61 }
62
63 //-----------------------------------------------------------------------------
64 template <class ValueType>
SetNumberOfComponents(int val)65 void vtkScaledSOADataArrayTemplate<ValueType>::SetNumberOfComponents(int val)
66 {
67 this->GenericDataArrayType::SetNumberOfComponents(val);
68 size_t numComps = static_cast<size_t>(this->GetNumberOfComponents());
69 assert(numComps >= 1);
70 while (this->Data.size() > numComps)
71 {
72 this->Data.back()->Delete();
73 this->Data.pop_back();
74 }
75 while (this->Data.size() < numComps)
76 {
77 this->Data.push_back(vtkBuffer<ValueType>::New());
78 }
79 }
80
81 //-----------------------------------------------------------------------------
82 template <class ValueType>
NewIterator()83 vtkArrayIterator* vtkScaledSOADataArrayTemplate<ValueType>::NewIterator()
84 {
85 vtkArrayIterator* iter = vtkArrayIteratorTemplate<ValueType>::New();
86 iter->Initialize(this);
87 return iter;
88 }
89
90 //-----------------------------------------------------------------------------
91 template <class ValueType>
ShallowCopy(vtkDataArray * other)92 void vtkScaledSOADataArrayTemplate<ValueType>::ShallowCopy(vtkDataArray* other)
93 {
94 SelfType* o = SelfType::FastDownCast(other);
95 if (o)
96 {
97 this->Size = o->Size;
98 this->MaxId = o->MaxId;
99 this->SetName(o->Name);
100 this->SetNumberOfComponents(o->NumberOfComponents);
101 this->CopyComponentNames(o);
102 this->Scale = o->Scale;
103 assert(this->Data.size() == o->Data.size());
104 for (size_t cc = 0; cc < this->Data.size(); ++cc)
105 {
106 vtkBuffer<ValueType>* thisBuffer = this->Data[cc];
107 vtkBuffer<ValueType>* otherBuffer = o->Data[cc];
108 if (thisBuffer != otherBuffer)
109 {
110 thisBuffer->Delete();
111 this->Data[cc] = otherBuffer;
112 otherBuffer->Register(nullptr);
113 }
114 }
115 this->DataChanged();
116 }
117 else
118 {
119 this->Superclass::ShallowCopy(other);
120 }
121 }
122
123 //-----------------------------------------------------------------------------
124 template <class ValueType>
InsertTuples(vtkIdType dstStart,vtkIdType n,vtkIdType srcStart,vtkAbstractArray * source)125 void vtkScaledSOADataArrayTemplate<ValueType>::InsertTuples(
126 vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, vtkAbstractArray* source)
127 {
128 // First, check for the common case of typeid(source) == typeid(this). This
129 // way we don't waste time redoing the other checks in the superclass, and
130 // can avoid doing a dispatch for the most common usage of this method.
131 SelfType* other = vtkArrayDownCast<SelfType>(source);
132 if (!other)
133 {
134 // Let the superclass handle dispatch/fallback.
135 this->Superclass::InsertTuples(dstStart, n, srcStart, source);
136 return;
137 }
138
139 if (n == 0)
140 {
141 return;
142 }
143
144 int numComps = this->GetNumberOfComponents();
145 if (other->GetNumberOfComponents() != numComps)
146 {
147 vtkErrorMacro("Number of components do not match: Source: "
148 << other->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents());
149 return;
150 }
151
152 vtkIdType maxSrcTupleId = srcStart + n - 1;
153 vtkIdType maxDstTupleId = dstStart + n - 1;
154
155 if (maxSrcTupleId >= other->GetNumberOfTuples())
156 {
157 vtkErrorMacro("Source array too small, requested tuple at index "
158 << maxSrcTupleId << ", but there are only " << other->GetNumberOfTuples()
159 << " tuples in the array.");
160 return;
161 }
162
163 vtkIdType newSize = (maxDstTupleId + 1) * this->NumberOfComponents;
164 if (this->Size < newSize)
165 {
166 if (!this->Resize(maxDstTupleId + 1))
167 {
168 vtkErrorMacro("Resize failed.");
169 return;
170 }
171 }
172
173 this->MaxId = std::max(this->MaxId, newSize - 1);
174
175 std::vector<ValueType> vals(numComps);
176 for (vtkIdType i = 0; i < n; i++)
177 {
178 other->GetTypedTuple(i + srcStart, vals.data());
179 this->SetTypedTuple(i + dstStart, vals.data()); // will automatically scale data
180 }
181 }
182
183 //-----------------------------------------------------------------------------
184 template <class ValueType>
FillTypedComponent(int compIdx,ValueType value)185 void vtkScaledSOADataArrayTemplate<ValueType>::FillTypedComponent(int compIdx, ValueType value)
186 {
187 ValueType* buffer = this->Data[compIdx]->GetBuffer();
188 value /= this->Scale;
189 std::fill(buffer, buffer + this->GetNumberOfTuples(), value);
190 }
191
192 //-----------------------------------------------------------------------------
193 template <class ValueType>
SetArray(int comp,ValueType * array,vtkIdType size,bool updateMaxId,bool save,int deleteMethod)194 void vtkScaledSOADataArrayTemplate<ValueType>::SetArray(
195 int comp, ValueType* array, vtkIdType size, bool updateMaxId, bool save, int deleteMethod)
196 {
197 const int numComps = this->GetNumberOfComponents();
198 if (comp >= numComps || comp < 0)
199 {
200 vtkErrorMacro("Invalid component number '"
201 << comp
202 << "' specified. "
203 "Use `SetNumberOfComponents` first to set the number of components.");
204 return;
205 }
206
207 this->Data[comp]->SetBuffer(array, size);
208
209 if (deleteMethod == VTK_DATA_ARRAY_DELETE)
210 {
211 this->Data[comp]->SetFreeFunction(save != 0, ::operator delete[]);
212 }
213 else if (deleteMethod == VTK_DATA_ARRAY_ALIGNED_FREE)
214 {
215 #ifdef _WIN32
216 this->Data[comp]->SetFreeFunction(save != 0, _aligned_free);
217 #else
218 this->Data[comp]->SetFreeFunction(save != 0, free);
219 #endif
220 }
221 else if (deleteMethod == VTK_DATA_ARRAY_USER_DEFINED || deleteMethod == VTK_DATA_ARRAY_FREE)
222 {
223 this->Data[comp]->SetFreeFunction(save != 0, free);
224 }
225
226 if (updateMaxId)
227 {
228 this->Size = numComps * size;
229 this->MaxId = this->Size - 1;
230 }
231 this->DataChanged();
232 }
233
234 //-----------------------------------------------------------------------------
235 template <class ValueType>
SetArrayFreeFunction(void (* callback)(void *))236 void vtkScaledSOADataArrayTemplate<ValueType>::SetArrayFreeFunction(void (*callback)(void*))
237 {
238 const int numComps = this->GetNumberOfComponents();
239 for (int i = 0; i < numComps; ++i)
240 {
241 this->SetArrayFreeFunction(i, callback);
242 }
243 }
244
245 //-----------------------------------------------------------------------------
246 template <class ValueType>
SetArrayFreeFunction(int comp,void (* callback)(void *))247 void vtkScaledSOADataArrayTemplate<ValueType>::SetArrayFreeFunction(
248 int comp, void (*callback)(void*))
249 {
250 const int numComps = this->GetNumberOfComponents();
251 if (comp >= numComps || comp < 0)
252 {
253 vtkErrorMacro("Invalid component number '"
254 << comp
255 << "' specified. "
256 "Use `SetNumberOfComponents` first to set the number of components.");
257 return;
258 }
259 this->Data[comp]->SetFreeFunction(false, callback);
260 }
261
262 //-----------------------------------------------------------------------------
263 template <class ValueType>
264 typename vtkScaledSOADataArrayTemplate<ValueType>::ValueType*
GetComponentArrayPointer(int comp)265 vtkScaledSOADataArrayTemplate<ValueType>::GetComponentArrayPointer(int comp)
266 {
267 const int numComps = this->GetNumberOfComponents();
268 if (comp >= numComps || comp < 0)
269 {
270 vtkErrorMacro("Invalid component number '" << comp << "' specified.");
271 return nullptr;
272 }
273
274 return this->Data[comp]->GetBuffer();
275 }
276
277 //-----------------------------------------------------------------------------
278 template <class ValueType>
AllocateTuples(vtkIdType numTuples)279 bool vtkScaledSOADataArrayTemplate<ValueType>::AllocateTuples(vtkIdType numTuples)
280 {
281 for (size_t cc = 0, max = this->Data.size(); cc < max; ++cc)
282 {
283 if (!this->Data[cc]->Allocate(numTuples))
284 {
285 return false;
286 }
287 }
288 return true;
289 }
290
291 //-----------------------------------------------------------------------------
292 template <class ValueType>
ReallocateTuples(vtkIdType numTuples)293 bool vtkScaledSOADataArrayTemplate<ValueType>::ReallocateTuples(vtkIdType numTuples)
294 {
295 for (size_t cc = 0, max = this->Data.size(); cc < max; ++cc)
296 {
297 if (!this->Data[cc]->Reallocate(numTuples))
298 {
299 return false;
300 }
301 }
302 return true;
303 }
304
305 //-----------------------------------------------------------------------------
306 template <class ValueType>
GetVoidPointer(vtkIdType valueIdx)307 void* vtkScaledSOADataArrayTemplate<ValueType>::GetVoidPointer(vtkIdType valueIdx)
308 {
309 // Allow warnings to be silenced:
310 const char* silence = getenv("VTK_SILENCE_GET_VOID_POINTER_WARNINGS");
311 if (!silence)
312 {
313 vtkWarningMacro(<< "GetVoidPointer called. This is very expensive for "
314 "non-array-of-structs subclasses, as the scalar array "
315 "must be generated for each call. Using the "
316 "vtkGenericDataArray API with vtkArrayDispatch are "
317 "preferred. Define the environment variable "
318 "VTK_SILENCE_GET_VOID_POINTER_WARNINGS to silence "
319 "this warning. Additionally, for the vtkScaledSOADataArrayTemplate "
320 "class we also set Scale to 1 since we've scaled how "
321 "we're storing the data in memory now. ");
322 }
323
324 size_t numValues = this->GetNumberOfValues();
325
326 if (!this->AoSCopy)
327 {
328 this->AoSCopy = vtkBuffer<ValueType>::New();
329 }
330
331 if (!this->AoSCopy->Allocate(static_cast<vtkIdType>(numValues)))
332 {
333 vtkErrorMacro(<< "Error allocating a buffer of " << numValues << " '"
334 << this->GetDataTypeAsString() << "' elements.");
335 return nullptr;
336 }
337
338 this->ExportToVoidPointer(static_cast<void*>(this->AoSCopy->GetBuffer()));
339
340 // This is the hacky thing with this class that we now need to set the scale
341 // to 1 since we internally are storing the memory in an unscaled manner
342 this->Scale = 1.0;
343
344 return static_cast<void*>(this->AoSCopy->GetBuffer() + valueIdx);
345 }
346
347 //-----------------------------------------------------------------------------
348 template <class ValueType>
ExportToVoidPointer(void * voidPtr)349 void vtkScaledSOADataArrayTemplate<ValueType>::ExportToVoidPointer(void* voidPtr)
350 {
351 vtkIdType numTuples = this->GetNumberOfTuples();
352 if (this->NumberOfComponents * numTuples == 0)
353 {
354 // Nothing to do.
355 return;
356 }
357
358 if (!voidPtr)
359 {
360 vtkErrorMacro(<< "Buffer is nullptr.");
361 return;
362 }
363
364 ValueType* ptr = static_cast<ValueType*>(voidPtr);
365 for (vtkIdType t = 0; t < numTuples; ++t)
366 {
367 for (int c = 0; c < this->NumberOfComponents; ++c)
368 {
369 *ptr++ = this->Data[c]->GetBuffer()[t] * this->Scale;
370 }
371 }
372 }
373
374 #endif
375