vtkArrayDispatch.h 17.3 KB
 David C. Lonie committed Mar 03, 2016 1 2 3 4 5 6 7 8 9 10 11 12 13 14 /*========================================================================= Program: Visualization Toolkit Module: vtkArrayDispatch.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/  David DeMarle committed Sep 23, 2016 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 /** * @class vtkArrayDispatch * @brief vtkDataArray code generator/dispatcher. * * vtkArrayDispatch implements a mechanism for generating optimized code for * multiple subclasses of vtkDataArray at once. Using a TypeList based * approach (see vtkTypeList), a templated worker implementation is generated * for a restricted or unrestricted set of vtkDataArray subclasses. * * A more detailed description of this class and related tools can be found * \ref VTK-7-1-ArrayDispatch "here". * * The primary goals of this class are to simplify multi-array dispatch * implementations, and provide tools to lower compilation time and binary * size (i.e. avoiding 'template explosions'). * * vtkArrayDispatch is also intended to replace code that currently relies on * the encapsulation-breaking vtkDataArray::GetVoidPointer method. Not all * subclasses of vtkDataArray use the memory layout assumed by GetVoidPointer; * calling this method on, e.g. a vtkSOADataArrayTemplate will trigger a deep * copy of the array data into an AOS buffer. This is very inefficient and * should be avoided. *  Allison Vacanti committed Nov 07, 2019 38  * The vtkDataArrayRange.h utilities are worth mentioning here, as they allow  David DeMarle committed Sep 23, 2016 39 40 41 42 43 44 45 46 47 48 49 50 51 52  * vtkArrayDispatch workers to operate on selected concrete subclasses for * 'fast paths', yet fallback to using the slower vtkDataArray API for uncommon * array types. This helps mitigate the "template explosion" issues that can * result from instantiating a large worker functions for many array types. * * These dispatchers extend the basic functionality of vtkTemplateMacro with * the following features: * - Multiarray dispatch: A single call can dispatch up to 3 arrays at once. * - Array restriction: The set of valid arrays for a particular dispatch * can be restricted. For example, if only vtkDoubleArray or vtkFloatArray * will be passed into the call, the dispatcher will only generate code paths * that use those arrays. * - ValueType restriction: If both SoA and AoS arrays need to be supported, * but only certain ValueTypes are expected, the dispatcher can restrict  luz.paz committed Jan 03, 2018 53  * itself to only use arrays that match this criteria.  David DeMarle committed Sep 23, 2016 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110  * - Application-wide array restrictions: If a VTK application uses only a few * arraytype / valuetype combinations, certain dispatchers will eliminate * paths using unsupported arrays at compile time. * * The basic Dispatch implementation will generate code paths for all arrays * in the application-wide array list, and operates on a single array. * * Dispatchers that start with Dispatch2 operate on 2 arrays simultaneously, * while those that begin with Dispatch3 operate on 3 arrays. * * To reduce compile time and binary size, the following dispatchers can be * used to restrict the set of arrays that will be used. There are versions of * these that operate on 1, 2, or 3 arrays: * * - DispatchByArray: * Accepts an explicit TypeList of arrays to consider. * These dispatchers do NOT respect the application-wide array restrictions. * Example usecase: A filter that creates either vtkFloatArray or * vtkDoubleArray depending on configuration can use this to restrict itself * to only these specific types. * Note that these should not be used for operating on filter inputs, instead * use DispatchByValueType, which also considers variations in vtkDataArray * subclasses and respects the application-wide array restrictions. * * - DispatchByValueType: * Accepts an explicit TypeList of ValueTypes to consider. * These dispatchers respect the application-wide array restrictions. * Example usecase: An image filter that operates on an input array that must * have either a float or unsigned char ValueType. * * - DispatchNByArrayWithSameValueType: * Multiarray dispatcher that accepts an explicit TypeList of arrays for * consideration. Generated code paths are further restricted to enforce that * all dispatched arrays will have the same ValueType. * Example usecase: A filter that creates and operates on multiple arrays at * the same time, where the arrays are guaranteed to have the same ValueType. * Note that these should not be used for operating on filter inputs, instead * use DispatchNBySameValueType, which also considers variations in * vtkDataArray subclasses and respects the application-wide array * restrictions. * * - DispatchNBySameValueType: * Multiarray dispatcher that accepts an explicit TypeList of ValueTypes to * consider. Generated code paths are further restricted to enforce that * all dispatched arrays will have the same ValueType. * Example usecase: A filter that creates a modified version of an input * array using NewInstance(). Both arrays may be passed into the dispatcher * using a worker function that produces the output from the input. * * Execution: * There are three components to a dispatch: The dispatcher, the worker, and * the array(s). They are combined like so: * * @code * bool result = Dispatcher<...>::Execute(array, worker); * @endcode *  Allison Vacanti committed Nov 08, 2019 111  * For convenience, the dispatcher may be aliased to a shorter name, e.g.:  David DeMarle committed Sep 23, 2016 112 113  * * @code  Allison Vacanti committed Nov 08, 2019 114  * using MyDispatcher = vtkArrayDispatch::SomeDispatcher<...>;  David DeMarle committed Sep 23, 2016 115  * MyWorker worker;  Allison Vacanti committed Nov 08, 2019 116  * bool result = MyDispatcher::Execute(array, worker);  David DeMarle committed Sep 23, 2016 117 118 119 120 121 122 123 124 125 126  * @endcode * * Return value: * The Execute method of the dispatcher will return true if a code path matching * the array arguments is found, or false if the arrays are not supported. If * false is returned, the arrays will not be modified, and the worker will not * be executed. * * Workers: * The dispatch requires a Worker functor that performs the work.  Robert Maynard committed Nov 12, 2019 127 128 129  * For single array, the functor must be callable where the first parameter is * an array object. For 2-array dispatch, the first two arguments must be (array1, array2). * For 3-array dispatch, the first three arguments must be (array1, array2, array3).  David DeMarle committed Sep 23, 2016 130  * Workers are passed by reference, so stateful functors are permitted if  Robert Maynard committed Nov 12, 2019 131 132  * additional input/output data is needed and not being passed as additional * parameters to the Execute method.  David DeMarle committed Sep 23, 2016 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149  * * A simple worker implementation for triple dispatch: * @code * struct MyWorker * { * template * void operator()(Array1T *array1, Array2T *array2, Array3T *array3) * { * // Do work using vtkGenericDataArray API... * } * }; * @endcode * * Note that optimized implementations (e.g. for AoS arrays vs SoA arrays) can * be supported by providing overloads of operator() that have more restrictive * template parameters. *  Allison Vacanti committed Nov 07, 2019 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186  * A worker's operator() implementation can accept additional parameters that * follow the arrays. These parameters are passed to the dispatcher during * execution. For instance, this worker scales an array by a runtime-value, * writing it into a second array: * * @code * struct ScaleArray * { * template * void operator()(ArraySrc *srcArray, ArrayDst *dstArray, * double scaleFactor) const * { * using SrcType = vtk::GetAPIType; * using DstType = vtk::GetAPIType; * * const auto srcRange = vtk::DataArrayValueRange(srcArray); * auto dstRange = vtk::DataArrayValueRange(dstArray); * * assert(srcRange.size() == dstRange.size()); * * auto dstIter = dstRange.begin(); * for (SrcType srcVal : srcRange) * { * *dstIter++ = static_cast(srcVal * scaleFactor); * } * } * }; * * vtkDataArray *src = ...; * vtkDataArray *dst = ...; * // Scale src by 3 (scaleFactor) and store in dst: * if (!vtkArrayDispatch::Dispatch2::Execute(src, dst, ScaleArray, 3)) * { * scaleArray(src, dst, 3); * } * @endcode *  David DeMarle committed Sep 23, 2016 187  * Examples:  Allison Vacanti committed Nov 07, 2019 188 189  * See TestArrayDispatchers.cxx for examples of each dispatch type and * ExampleDataArrayRangeDispatch.cxx for more real-world examples.  David DeMarle committed Sep 23, 2016 190 191 192  * * @sa * vtkDataArrayAccessor  Kitware Robot committed Nov 18, 2019 193  */  David C. Lonie committed Mar 03, 2016 194 195 196 197 198 199 200 201  #ifndef vtkArrayDispatch_h #define vtkArrayDispatch_h #include "vtkArrayDispatchArrayList.h" #include "vtkType.h" #include "vtkTypeList.h"  Kitware Robot committed Nov 18, 2019 202 203 namespace vtkArrayDispatch {  Ryan Krattiger committed Sep 20, 2022 204 VTK_ABI_NAMESPACE_BEGIN  David C. Lonie committed Mar 03, 2016 205   David DeMarle committed Sep 23, 2016 206 207 208 /** * A TypeList containing all real ValueTypes. */  Allison Vacanti committed Nov 06, 2019 209 typedef vtkTypeList::Create Reals;  David C. Lonie committed Mar 03, 2016 210   David DeMarle committed Sep 23, 2016 211 212 213 /** * A Typelist containing all integral ValueTypes. */  David C. Lonie committed Mar 03, 2016 214 typedef vtkTypeList::Unique<  Kitware Robot committed Nov 18, 2019 215  vtkTypeList::Create>::Result Integrals;  David C. Lonie committed Mar 03, 2016 217   David DeMarle committed Sep 23, 2016 218 219 220 /** * A Typelist containing all standard VTK array ValueTypes. */  David C. Lonie committed Mar 03, 2016 221 typedef vtkTypeList::Append::Result AllTypes;  David C. Lonie committed Mar 03, 2016 222 223  //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 224 225 226 227 228 229 /** * Dispatch a single array against all array types in the application-wide * vtkArrayDispatch::Arrays list. * The entry point is: * bool Dispatch::Execute(vtkDataArray *array, Worker &worker). */  David C. Lonie committed Mar 03, 2016 230 231 232 struct Dispatch; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 233 234 235 236 237 238 /** * Dispatch a single array against all array types mentioned in the ArrayList * template parameter. * The entry point is: * bool DispatchByArray<...>::Execute(vtkDataArray *array, Worker &worker). */  David C. Lonie committed Mar 03, 2016 239 240 241 242 template struct DispatchByArray; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 243 244 245 246 247 248 249 /** * Dispatch a single array against all array types in the application-wide * vtkArrayDispatch::Arrays list with the added restriction that the array * must have a type that appears the ValueTypeList TypeList. * The entry point is: * bool DispatchByValueType<...>::Execute(vtkDataArray *array, Worker &worker). */  David C. Lonie committed Mar 03, 2016 250 251 252 253 template struct DispatchByValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 254 255 256 257 258 259 260 /** * Dispatch two arrays using all array types in the application-wide * vtkArrayDispatch::Arrays list. * The entry point is: * bool Dispatch2::Execute(vtkDataArray *array, vtkDataArray *array2, * Worker &worker). */  David C. Lonie committed Mar 03, 2016 261 262 263 struct Dispatch2; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 264 265 266 267 268 269 270 271 /** * Dispatch two arrays, restricting the valid code paths to use only arrays that * have the same ValueType. * All application-wide arrays in vtkArrayDispatch::Arrays are used. * The entry point is: * bool Dispatch2SameValueType::Execute( * vtkDataArray *a1, vtkDataArray *a2, Worker &worker). */  David C. Lonie committed Mar 03, 2016 272 273 274 struct Dispatch2SameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 275 276 277 278 279 280 281 282 283 /** * Dispatch two arrays with the restriction that the type of the first array is * in the ArrayList1 TypeList, and the second is in ArrayList2. * If all application-wide arrays are desired, use vtkArrayDispatch::Arrays for * the first two template parameters. * The entry point is: * bool Dispatch2ByArray<...>::Execute(vtkDataArray *a1, vtkDataArray *a2, * Worker &worker). */  Kitware Robot committed Nov 18, 2019 284 template  David C. Lonie committed Mar 03, 2016 285 286 287 struct Dispatch2ByArray; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 288 289 290 291 292 293 294 295 296 297 298 /** * Dispatch two arrays, restricting the valid code paths to use * ValueType-filtered versions of the application-wide vtkArrayDispatch::Arrays * TypeList. The first array's ValueType must be in the ValueTypeList1 TypeList, * and the second's must be in ValueTypeList2. * If all types are to be considered, use vtkArrayDispatch::AllTypes for the * first two template parameters. * The entry point is: * bool Dispatch2ByValueType<...>::Execute(vtkDataArray *a1, vtkDataArray *a2, * Worker &worker). */  Kitware Robot committed Nov 18, 2019 299 template  David C. Lonie committed Mar 03, 2016 300 301 302 struct Dispatch2ByValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 303 304 305 306 307 308 309 310 311 312 /** * Dispatch two arrays, restricting the valid code paths to use only array types * specified in the ArrayList TypeList, additionally enforcing that all arrays * must have the same ValueType. * If all application-wide arrays are desired, use vtkArrayDispatch::Arrays for * the first two template parameters. * The entry point is: * bool Dispatch2ByArrayWithSameValueType<...>::Execute( * vtkDataArray *a1, vtkDataArray *a2, Worker &worker). */  Kitware Robot committed Nov 18, 2019 313 template  David C. Lonie committed Mar 03, 2016 314 315 316 struct Dispatch2ByArrayWithSameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 317 318 319 320 321 322 323 324 325 326 327 /** * Dispatch two arrays, restricting the valid code paths to use only array types * found in application-wide vtkArrayDispatch::Arrays TypeList that have a * ValueType contained in the ValueTypeList TypeList. This dispatcher also * enforces that all arrays have the same ValueType. * If all types are to be considered, use vtkArrayDispatch::AllTypes for the * first two template parameters. * The entry point is: * bool Dispatch2BySameValueType<...>::Execute( * vtkDataArray *a1, vtkDataArray *a2, Worker &worker). */  David C. Lonie committed Mar 03, 2016 328 329 330 331 template struct Dispatch2BySameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 332 333 334 335 336 337 338 /** * Dispatch three arrays using all array types in the application-wide * vtkArrayDispatch::Arrays list. * The entry point is: * bool Dispatch3::Execute(vtkDataArray *array1, vtkDataArray *array2, * vtkDataArray *array3, Worker &worker). */  David C. Lonie committed Mar 03, 2016 339 340 341 struct Dispatch3; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 342 343 344 345 346 347 348 349 /** * Dispatch three arrays, restricting the valid code paths to use only arrays * that have the same ValueType. * All application-wide arrays in vtkArrayDispatch::Arrays are used. * The entry point is: * bool Dispatch3SameValueType::Execute( * vtkDataArray *a1, vtkDataArray *a2, vtkDataArray *a3, Worker &worker). */  David C. Lonie committed Mar 03, 2016 350 351 352 struct Dispatch3SameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 353 354 355 356 357 358 359 360 361 362 /** * Dispatch three arrays with the restriction that the type of the first array * is in the ArrayList1 TypeList, the second is in ArrayList2, and the third * is in ArrayList3. * If all application-wide arrays are desired, use vtkArrayDispatch::Arrays for * the first three template parameters. * The entry point is: * bool Dispatch3ByArray::Execute<...>(vtkDataArray *a1, vtkDataArray *a2, * vtkDataArray *a3, Worker &worker). */  Kitware Robot committed Nov 18, 2019 363 template  David C. Lonie committed Mar 03, 2016 364 365 366 struct Dispatch3ByArray; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 367 368 369 370 371 372 373 374 375 376 377 378 /** * Dispatch three arrays, restricting the valid code paths to use * ValueType-filtered versions of the application-wide vtkArrayDispatch::Arrays * TypeList. The first array's ValueType must be in the ValueTypeList1 TypeList, * the second's must be in ValueTypeList2, and the third's must be in * ValueTypeList3. * If all types are to be considered, use vtkArrayDispatch::AllTypes for the * first three template parameters. * The entry point is: * bool Dispatch3ByValueType<...>::Execute(vtkDataArray *a1, vtkDataArray *a2, * vtkDataArray *a3, Worker &worker). */  Kitware Robot committed Nov 18, 2019 379 template  David C. Lonie committed Mar 03, 2016 380 381 382 struct Dispatch3ByValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 383 384 385 386 387 388 389 390 391 392 /** * Dispatch three arrays, restricting the valid code paths to use only array * types specified in the ArrayList TypeList, additionally enforcing that all * arrays must have the same ValueType. * If all application-wide arrays are desired, use vtkArrayDispatch::Arrays for * the first three template parameters. * The entry point is: * bool Dispatch3ByArrayWithSameValueType<...>::Execute( * vtkDataArray *a1, vtkDataArray *a2, vtkDataArray *a3, Worker &worker). */  Kitware Robot committed Nov 18, 2019 393 template  David C. Lonie committed Mar 03, 2016 394 395 396 struct Dispatch3ByArrayWithSameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 397 398 399 400 401 402 403 404 405 406 407 /** * Dispatch three arrays, restricting the valid code paths to use only array * types found in application-wide vtkArrayDispatch::Arrays TypeList that have a * ValueType contained in the ValueTypeList TypeList. This dispatcher also * enforces that all arrays have the same ValueType. * If all types are to be considered, use vtkArrayDispatch::AllTypes for the * first three template parameters. * The entry point is: * bool Dispatch3BySameValueType<...>::Execute( * vtkDataArray *a1, vtkDataArray *a2, vtkDataArray *a3, Worker &worker). */  David C. Lonie committed Mar 03, 2016 408 409 410 411 template struct Dispatch3BySameValueType; //------------------------------------------------------------------------------  David DeMarle committed Sep 23, 2016 412 413 414 415 /** * Filter the ArrayList to contain only arrays with ArrayType::ValueType that * exist in ValueList. The result TypeList is stored in Result. */  David C. Lonie committed Mar 03, 2016 416 417 418 template struct FilterArraysByValueType;  Ryan Krattiger committed Sep 20, 2022 419 VTK_ABI_NAMESPACE_END  David C. Lonie committed Mar 03, 2016 420 421 422 423 424 425 } // end namespace vtkArrayDispatch #include "vtkArrayDispatch.txx" #endif // vtkArrayDispatch_h // VTK-HeaderTest-Exclude: vtkArrayDispatch.h