ArrayHandleTransform.h 18.8 KB
Newer Older
Kenneth Moreland's avatar
Kenneth Moreland committed
1 2 3 4 5 6 7 8 9 10
//=============================================================================
//
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt 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.
//
Kenneth Moreland's avatar
Kenneth Moreland committed
11
//  Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
Kenneth Moreland's avatar
Kenneth Moreland committed
12
//  Copyright 2015 UT-Battelle, LLC.
13
//  Copyright 2015 Los Alamos National Security.
Kenneth Moreland's avatar
Kenneth Moreland committed
14
//
Kenneth Moreland's avatar
Kenneth Moreland committed
15
//  Under the terms of Contract DE-NA0003525 with NTESS,
Kenneth Moreland's avatar
Kenneth Moreland committed
16 17 18 19 20 21 22 23 24 25
//  the U.S. Government retains certain rights in this software.
//  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
//  Laboratory (LANL), the U.S. Government retains certain rights in
//  this software.
//
//=============================================================================
#ifndef vtk_m_cont_ArrayHandleTransform_h
#define vtk_m_cont_ArrayHandleTransform_h

#include <vtkm/cont/ArrayHandle.h>
David C. Lonie's avatar
David C. Lonie committed
26 27
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorInternal.h>
Kenneth Moreland's avatar
Kenneth Moreland committed
28

29 30 31 32 33 34
namespace vtkm
{
namespace cont
{
namespace internal
{
35 36

/// Tag used in place of an inverse functor.
37 38 39
struct NullFunctorType
{
};
40 41 42 43
}
}
} // namespace vtkm::cont::internal

44 45 46 47 48 49
namespace vtkm
{
namespace exec
{
namespace internal
{
50

51
using NullFunctorType = vtkm::cont::internal::NullFunctorType;
52

Kenneth Moreland's avatar
Kenneth Moreland committed
53 54
/// \brief An array portal that transforms a value from another portal.
///
55 56 57
template <typename ValueType_,
          typename PortalType_,
          typename FunctorType_,
58
          typename InverseFunctorType_ = NullFunctorType>
59
class VTKM_ALWAYS_EXPORT ArrayPortalTransform;
60

61 62 63
template <typename ValueType_, typename PortalType_, typename FunctorType_>
class VTKM_ALWAYS_EXPORT
  ArrayPortalTransform<ValueType_, PortalType_, FunctorType_, NullFunctorType>
Kenneth Moreland's avatar
Kenneth Moreland committed
64 65
{
public:
66 67 68
  using PortalType = PortalType_;
  using ValueType = ValueType_;
  using FunctorType = FunctorType_;
Kenneth Moreland's avatar
Kenneth Moreland committed
69

70
  VTKM_SUPPRESS_EXEC_WARNINGS
71
  VTKM_EXEC_CONT
72 73 74 75 76 77
  ArrayPortalTransform(const PortalType& portal = PortalType(),
                       const FunctorType& functor = FunctorType())
    : Portal(portal)
    , Functor(functor)
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
78

79
  /// Copy constructor for any other ArrayPortalTransform with an iterator
80 81
  /// type that can be copied to this iterator type. This allows us to do any
  /// type casting that the iterators do (like the non-const to const cast).
Kenneth Moreland's avatar
Kenneth Moreland committed
82
  ///
83
  VTKM_SUPPRESS_EXEC_WARNINGS
84 85 86 87 88 89
  template <class OtherV, class OtherP, class OtherF>
  VTKM_EXEC_CONT ArrayPortalTransform(const ArrayPortalTransform<OtherV, OtherP, OtherF>& src)
    : Portal(src.GetPortal())
    , Functor(src.GetFunctor())
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
90

91
  VTKM_SUPPRESS_EXEC_WARNINGS
92
  VTKM_EXEC_CONT
93
  vtkm::Id GetNumberOfValues() const { return this->Portal.GetNumberOfValues(); }
Kenneth Moreland's avatar
Kenneth Moreland committed
94

95
  VTKM_SUPPRESS_EXEC_WARNINGS
96
  VTKM_EXEC_CONT
97
  ValueType Get(vtkm::Id index) const { return this->Functor(this->Portal.Get(index)); }
Kenneth Moreland's avatar
Kenneth Moreland committed
98

99 100
  VTKM_SUPPRESS_EXEC_WARNINGS
  VTKM_EXEC_CONT
101
  void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const
102
  {
103
#if !(defined(VTKM_MSVC) && defined(VTKM_CUDA))
104 105
    VTKM_ASSERT(false &&
                "Cannot write to read-only transform array. (No inverse transform given.)");
106
#endif
107 108
  }

109
  VTKM_SUPPRESS_EXEC_WARNINGS
110
  VTKM_EXEC_CONT
111
  const PortalType& GetPortal() const { return this->Portal; }
Kenneth Moreland's avatar
Kenneth Moreland committed
112

113
  VTKM_SUPPRESS_EXEC_WARNINGS
114
  VTKM_EXEC_CONT
115
  const FunctorType& GetFunctor() const { return this->Functor; }
Kenneth Moreland's avatar
Kenneth Moreland committed
116

117
protected:
Kenneth Moreland's avatar
Kenneth Moreland committed
118 119 120 121
  PortalType Portal;
  FunctorType Functor;
};

122 123 124
template <typename ValueType_,
          typename PortalType_,
          typename FunctorType_,
125 126 127
          typename InverseFunctorType_>
class VTKM_ALWAYS_EXPORT ArrayPortalTransform
  : public ArrayPortalTransform<ValueType_, PortalType_, FunctorType_, NullFunctorType>
128 129
{
public:
130 131 132 133 134
  using Superclass = ArrayPortalTransform<ValueType_, PortalType_, FunctorType_, NullFunctorType>;
  using PortalType = PortalType_;
  using ValueType = ValueType_;
  using FunctorType = FunctorType_;
  using InverseFunctorType = InverseFunctorType_;
135

136
  VTKM_SUPPRESS_EXEC_WARNINGS
137
  VTKM_EXEC_CONT
138 139 140 141 142 143 144
  ArrayPortalTransform(const PortalType& portal = PortalType(),
                       const FunctorType& functor = FunctorType(),
                       const InverseFunctorType& inverseFunctor = InverseFunctorType())
    : Superclass(portal, functor)
    , InverseFunctor(inverseFunctor)
  {
  }
145

146
  VTKM_SUPPRESS_EXEC_WARNINGS
147 148 149 150 151 152 153
  template <class OtherV, class OtherP, class OtherF, class OtherInvF>
  VTKM_EXEC_CONT ArrayPortalTransform(
    const ArrayPortalTransform<OtherV, OtherP, OtherF, OtherInvF>& src)
    : Superclass(src)
    , InverseFunctor(src.GetInverseFunctor())
  {
  }
154

155
  VTKM_SUPPRESS_EXEC_WARNINGS
156
  VTKM_EXEC_CONT
157 158 159
  void Set(vtkm::Id index, const ValueType& value) const
  {
    return this->Portal.Set(index, this->InverseFunctor(value));
160 161
  }

162
  VTKM_SUPPRESS_EXEC_WARNINGS
163
  VTKM_EXEC_CONT
164
  const InverseFunctorType& GetInverseFunctor() const { return this->InverseFunctor; }
165 166 167 168

private:
  InverseFunctorType InverseFunctor;
};
169 170 171 172
}
}
} // namespace vtkm::exec::internal

173 174 175 176
namespace vtkm
{
namespace cont
{
177

178 179
namespace internal
{
180

181
template <typename ArrayHandleType,
182
          typename FunctorType,
183 184 185
          typename InverseFunctorType = NullFunctorType>
struct VTKM_ALWAYS_EXPORT StorageTagTransform
{
186
  using ValueType = decltype(FunctorType{}(typename ArrayHandleType::ValueType{}));
187
};
Kenneth Moreland's avatar
Kenneth Moreland committed
188

189 190 191
template <typename ArrayHandleType, typename FunctorType>
class Storage<typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueType,
              StorageTagTransform<ArrayHandleType, FunctorType>>
Kenneth Moreland's avatar
Kenneth Moreland committed
192 193
{
public:
194
  using ValueType = typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueType;
Kenneth Moreland's avatar
Kenneth Moreland committed
195

196 197 198 199
  // This is meant to be invalid. Because Transform arrays are read only, you
  // should only be able to use the const version.
  struct PortalType
  {
200 201
    using ValueType = void*;
    using IteratorType = void*;
202 203
  };

204 205 206 207
  using PortalConstType =
    vtkm::exec::internal::ArrayPortalTransform<ValueType,
                                               typename ArrayHandleType::PortalConstControl,
                                               FunctorType>;
Kenneth Moreland's avatar
Kenneth Moreland committed
208

209
  VTKM_CONT
210 211 212 213
  Storage()
    : Valid(false)
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
214

215
  VTKM_CONT
216 217 218 219 220 221
  Storage(const ArrayHandleType& array, const FunctorType& functor = FunctorType())
    : Array(array)
    , Functor(functor)
    , Valid(true)
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
222

223
  VTKM_CONT
224 225
  PortalType GetPortal()
  {
226
    VTKM_ASSERT(this->Valid);
227
    return PortalType(this->Array.GetPortalControl(), this->Functor);
Kenneth Moreland's avatar
Kenneth Moreland committed
228 229
  }

230
  VTKM_CONT
231 232
  PortalConstType GetPortalConst() const
  {
233
    VTKM_ASSERT(this->Valid);
234
    return PortalConstType(this->Array.GetPortalConstControl(), this->Functor);
Kenneth Moreland's avatar
Kenneth Moreland committed
235 236
  }

237
  VTKM_CONT
238 239
  vtkm::Id GetNumberOfValues() const
  {
240
    VTKM_ASSERT(this->Valid);
Kenneth Moreland's avatar
Kenneth Moreland committed
241 242 243
    return this->Array.GetNumberOfValues();
  }

244
  VTKM_CONT
245 246 247
  void Allocate(vtkm::Id vtkmNotUsed(numberOfValues))
  {
    throw vtkm::cont::ErrorBadType("ArrayHandleTransform is read only. It cannot be allocated.");
Kenneth Moreland's avatar
Kenneth Moreland committed
248 249
  }

250
  VTKM_CONT
251 252 253
  void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
  {
    throw vtkm::cont::ErrorBadType("ArrayHandleTransform is read only. It cannot shrink.");
Kenneth Moreland's avatar
Kenneth Moreland committed
254 255
  }

256
  VTKM_CONT
257 258
  void ReleaseResources()
  {
Kenneth Moreland's avatar
Kenneth Moreland committed
259 260 261 262 263
    // This request is ignored since it is asking to release the resources
    // of the delegate array, which may be used elsewhere. Should the behavior
    // be different?
  }

264
  VTKM_CONT
265 266
  const ArrayHandleType& GetArray() const
  {
267
    VTKM_ASSERT(this->Valid);
Kenneth Moreland's avatar
Kenneth Moreland committed
268 269 270
    return this->Array;
  }

271
  VTKM_CONT
272
  const FunctorType& GetFunctor() const { return this->Functor; }
273

Kenneth Moreland's avatar
Kenneth Moreland committed
274 275 276 277 278 279
private:
  ArrayHandleType Array;
  FunctorType Functor;
  bool Valid;
};

280 281 282 283
template <typename ArrayHandleType, typename FunctorType, typename InverseFunctorType>
class Storage<
  typename StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>::ValueType,
  StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>>
284 285
{
public:
286 287
  using ValueType =
    typename StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>::ValueType;
288

289 290 291 292 293 294 295 296 297 298
  using PortalType =
    vtkm::exec::internal::ArrayPortalTransform<ValueType,
                                               typename ArrayHandleType::PortalControl,
                                               FunctorType,
                                               InverseFunctorType>;
  using PortalConstType =
    vtkm::exec::internal::ArrayPortalTransform<ValueType,
                                               typename ArrayHandleType::PortalConstControl,
                                               FunctorType,
                                               InverseFunctorType>;
299

300
  VTKM_CONT
301 302 303 304
  Storage()
    : Valid(false)
  {
  }
305

306
  VTKM_CONT
307 308
  Storage(const ArrayHandleType& array,
          const FunctorType& functor,
309 310 311 312 313 314 315
          const InverseFunctorType& inverseFunctor)
    : Array(array)
    , Functor(functor)
    , InverseFunctor(inverseFunctor)
    , Valid(true)
  {
  }
316

317
  VTKM_CONT
318 319
  PortalType GetPortal()
  {
320
    VTKM_ASSERT(this->Valid);
321
    return PortalType(this->Array.GetPortalControl(), this->Functor, this->InverseFunctor);
322 323
  }

324
  VTKM_CONT
325 326
  PortalConstType GetPortalConst() const
  {
327
    VTKM_ASSERT(this->Valid);
328 329
    return PortalConstType(
      this->Array.GetPortalConstControl(), this->Functor, this->InverseFunctor);
330 331
  }

332
  VTKM_CONT
333 334
  vtkm::Id GetNumberOfValues() const
  {
335
    VTKM_ASSERT(this->Valid);
336 337 338
    return this->Array.GetNumberOfValues();
  }

339
  VTKM_CONT
340 341
  void Allocate(vtkm::Id numberOfValues)
  {
342 343 344 345
    this->Array.Allocate(numberOfValues);
    this->Valid = true;
  }

346
  VTKM_CONT
347
  void Shrink(vtkm::Id numberOfValues) { this->Array.Shrink(numberOfValues); }
348

349
  VTKM_CONT
350 351
  void ReleaseResources()
  {
352 353 354 355
    this->Array.ReleaseResources();
    this->Valid = false;
  }

356
  VTKM_CONT
357 358
  const ArrayHandleType& GetArray() const
  {
359
    VTKM_ASSERT(this->Valid);
360 361 362
    return this->Array;
  }

363
  VTKM_CONT
364
  const FunctorType& GetFunctor() const { return this->Functor; }
365

366
  VTKM_CONT
367
  const InverseFunctorType& GetInverseFunctor() const { return this->InverseFunctor; }
368 369 370 371 372 373 374 375

private:
  ArrayHandleType Array;
  FunctorType Functor;
  InverseFunctorType InverseFunctor;
  bool Valid;
};

376 377 378 379
template <typename ArrayHandleType, typename FunctorType, typename Device>
class ArrayTransfer<typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueType,
                    StorageTagTransform<ArrayHandleType, FunctorType>,
                    Device>
Kenneth Moreland's avatar
Kenneth Moreland committed
380
{
381
  using StorageTag = StorageTagTransform<ArrayHandleType, FunctorType>;
Kenneth Moreland's avatar
Kenneth Moreland committed
382 383

public:
384 385
  using ValueType = typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueType;
  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
Kenneth Moreland's avatar
Kenneth Moreland committed
386

387 388
  using PortalControl = typename StorageType::PortalType;
  using PortalConstControl = typename StorageType::PortalConstType;
Kenneth Moreland's avatar
Kenneth Moreland committed
389

390
  //meant to be an invalid writeable execution portal
391 392
  using PortalExecution = typename StorageType::PortalType;
  using PortalConstExecution = vtkm::exec::internal::ArrayPortalTransform<
393 394
    ValueType,
    typename ArrayHandleType::template ExecutionTypes<Device>::PortalConst,
395
    FunctorType>;
Kenneth Moreland's avatar
Kenneth Moreland committed
396

397
  VTKM_CONT
398 399 400 401 402
  ArrayTransfer(StorageType* storage)
    : Array(storage->GetArray())
    , Functor(storage->GetFunctor())
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
403

404
  VTKM_CONT
405
  vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
Kenneth Moreland's avatar
Kenneth Moreland committed
406

407
  VTKM_CONT
408 409
  PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
  {
410
    return PortalConstExecution(this->Array.PrepareForInput(Device()), this->Functor);
Kenneth Moreland's avatar
Kenneth Moreland committed
411 412
  }

413
  VTKM_CONT
414 415 416 417
  PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
  {
    throw vtkm::cont::ErrorBadType("ArrayHandleTransform read only. "
                                   "Cannot be used for in-place operations.");
Kenneth Moreland's avatar
Kenneth Moreland committed
418 419
  }

420
  VTKM_CONT
421 422 423
  PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
  {
    throw vtkm::cont::ErrorBadType("ArrayHandleTransform read only. Cannot be used as output.");
Kenneth Moreland's avatar
Kenneth Moreland committed
424 425
  }

426
  VTKM_CONT
427 428
  void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
  {
David C. Lonie's avatar
David C. Lonie committed
429
    throw vtkm::cont::ErrorInternal(
430
      "ArrayHandleTransform read only. "
luz.paz's avatar
luz.paz committed
431
      "There should be no occurrence of the ArrayHandle trying to pull "
432
      "data from the execution environment.");
Kenneth Moreland's avatar
Kenneth Moreland committed
433 434
  }

435
  VTKM_CONT
436 437 438
  void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
  {
    throw vtkm::cont::ErrorBadType("ArrayHandleTransform read only. Cannot shrink.");
Kenneth Moreland's avatar
Kenneth Moreland committed
439 440
  }

441
  VTKM_CONT
442
  void ReleaseResources() { this->Array.ReleaseResourcesExecution(); }
Kenneth Moreland's avatar
Kenneth Moreland committed
443 444 445

private:
  ArrayHandleType Array;
446
  FunctorType Functor;
Kenneth Moreland's avatar
Kenneth Moreland committed
447 448
};

449
template <typename ArrayHandleType,
450 451
          typename FunctorType,
          typename InverseFunctorType,
452
          typename Device>
453 454 455 456
class ArrayTransfer<
  typename StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>::ValueType,
  StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>,
  Device>
457
{
458
  using StorageTag = StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>;
459 460

public:
461 462
  using ValueType = typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueType;
  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
463

464 465
  using PortalControl = typename StorageType::PortalType;
  using PortalConstControl = typename StorageType::PortalConstType;
466

467
  using PortalExecution = vtkm::exec::internal::ArrayPortalTransform<
468 469 470
    ValueType,
    typename ArrayHandleType::template ExecutionTypes<Device>::Portal,
    FunctorType,
471 472
    InverseFunctorType>;
  using PortalConstExecution = vtkm::exec::internal::ArrayPortalTransform<
473 474 475
    ValueType,
    typename ArrayHandleType::template ExecutionTypes<Device>::PortalConst,
    FunctorType,
476
    InverseFunctorType>;
477

478
  VTKM_CONT
479 480 481 482 483 484
  ArrayTransfer(StorageType* storage)
    : Array(storage->GetArray())
    , Functor(storage->GetFunctor())
    , InverseFunctor(storage->GetInverseFunctor())
  {
  }
485

486
  VTKM_CONT
487
  vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
488

489
  VTKM_CONT
490 491
  PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
  {
492 493
    return PortalConstExecution(
      this->Array.PrepareForInput(Device()), this->Functor, this->InverseFunctor);
494 495
  }

496
  VTKM_CONT
497 498
  PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
  {
499 500
    return PortalExecution(
      this->Array.PrepareForInPlace(Device()), this->Functor, this->InverseFunctor);
501 502
  }

503
  VTKM_CONT
504 505
  PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
  {
506 507
    return PortalExecution(
      this->Array.PrepareForOutput(numberOfValues, Device()), this->Functor, this->InverseFunctor);
508 509
  }

510
  VTKM_CONT
511 512
  void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
  {
513 514 515 516
    // Implementation of this method should be unnecessary. The internal
    // array handle should automatically retrieve the output data as necessary.
  }

517
  VTKM_CONT
518
  void Shrink(vtkm::Id numberOfValues) { this->Array.Shrink(numberOfValues); }
519

520
  VTKM_CONT
521
  void ReleaseResources() { this->Array.ReleaseResourcesExecution(); }
522 523 524 525 526 527 528

private:
  ArrayHandleType Array;
  FunctorType Functor;
  InverseFunctorType InverseFunctor;
};

Kenneth Moreland's avatar
Kenneth Moreland committed
529 530 531 532 533 534 535 536 537 538 539 540 541
} // namespace internal

/// \brief Implicitly transform values of one array to another with a functor.
///
/// ArrayHandleTransforms is a specialization of ArrayHandle. It takes a
/// delegate array handle and makes a new handle that calls a given unary
/// functor with the element at a given index and returns the result of the
/// functor as the value of this array at that position. This transformation is
/// done on demand. That is, rather than make a new copy of the array with new
/// values, the transformation is done as values are read from the array. Thus,
/// the functor operator should work in both the control and execution
/// environments.
///
542
template <typename ArrayHandleType,
543
          typename FunctorType,
544
          typename InverseFunctorType = internal::NullFunctorType>
545 546
class ArrayHandleTransform;

547 548 549 550 551
template <typename ArrayHandleType, typename FunctorType>
class ArrayHandleTransform<ArrayHandleType, FunctorType, internal::NullFunctorType>
  : public vtkm::cont::ArrayHandle<
      typename internal::StorageTagTransform<ArrayHandleType, FunctorType>::ValueType,
      internal::StorageTagTransform<ArrayHandleType, FunctorType>>
Kenneth Moreland's avatar
Kenneth Moreland committed
552 553 554 555 556
{
  // If the following line gives a compile error, then the ArrayHandleType
  // template argument is not a valid ArrayHandle type.
  VTKM_IS_ARRAY_HANDLE(ArrayHandleType);

557
public:
558
  VTKM_ARRAY_HANDLE_SUBCLASS(
559
    ArrayHandleTransform,
560 561 562 563
    (ArrayHandleTransform<ArrayHandleType, FunctorType>),
    (vtkm::cont::ArrayHandle<
      typename internal::StorageTagTransform<ArrayHandleType, FunctorType>::ValueType,
      internal::StorageTagTransform<ArrayHandleType, FunctorType>>));
564 565

private:
566
  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
Kenneth Moreland's avatar
Kenneth Moreland committed
567

568
public:
569
  VTKM_CONT
570 571 572 573
  ArrayHandleTransform(const ArrayHandleType& handle, const FunctorType& functor = FunctorType())
    : Superclass(StorageType(handle, functor))
  {
  }
Kenneth Moreland's avatar
Kenneth Moreland committed
574 575 576 577 578
};

/// make_ArrayHandleTransform is convenience function to generate an
/// ArrayHandleTransform.  It takes in an ArrayHandle and a functor
/// to apply to each element of the Handle.
579 580
template <typename HandleType, typename FunctorType>
VTKM_CONT vtkm::cont::ArrayHandleTransform<HandleType, FunctorType> make_ArrayHandleTransform(
581 582
  HandleType handle,
  FunctorType functor)
Kenneth Moreland's avatar
Kenneth Moreland committed
583
{
584
  return ArrayHandleTransform<HandleType, FunctorType>(handle, functor);
Kenneth Moreland's avatar
Kenneth Moreland committed
585 586
}

587 588
// ArrayHandleTransform with inverse functors enabled (no need to subclass from
// ArrayHandleTransform without inverse functors: nothing to inherit).
589
template <typename ArrayHandleType, typename FunctorType, typename InverseFunctorType>
590
class ArrayHandleTransform
591
  : public vtkm::cont::ArrayHandle<
592 593 594
      typename internal::StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>::
        ValueType,
      internal::StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>>
595 596 597 598 599
{
  VTKM_IS_ARRAY_HANDLE(ArrayHandleType);

public:
  VTKM_ARRAY_HANDLE_SUBCLASS(
600
    ArrayHandleTransform,
601
    (ArrayHandleTransform<ArrayHandleType, FunctorType, InverseFunctorType>),
602
    (vtkm::cont::ArrayHandle<
603 604 605
      typename internal::StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>::
        ValueType,
      internal::StorageTagTransform<ArrayHandleType, FunctorType, InverseFunctorType>>));
606 607

private:
608
  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
609

610
public:
611 612
  ArrayHandleTransform(const ArrayHandleType& handle,
                       const FunctorType& functor = FunctorType(),
613 614 615 616
                       const InverseFunctorType& inverseFunctor = InverseFunctorType())
    : Superclass(StorageType(handle, functor, inverseFunctor))
  {
  }
617 618
};

619 620
template <typename HandleType, typename FunctorType, typename InverseFunctorType>
VTKM_CONT vtkm::cont::ArrayHandleTransform<HandleType, FunctorType, InverseFunctorType>
621 622
make_ArrayHandleTransform(HandleType handle, FunctorType functor, InverseFunctorType inverseFunctor)
{
623
  return ArrayHandleTransform<HandleType, FunctorType, InverseFunctorType>(
624
    handle, functor, inverseFunctor);
625
}
Kenneth Moreland's avatar
Kenneth Moreland committed
626
}
627

Kenneth Moreland's avatar
Kenneth Moreland committed
628 629 630
} // namespace vtkm::cont

#endif //vtk_m_cont_ArrayHandleTransform_h