XdmfArray.tpp 19.9 KB
Newer Older
Kenneth Leiter's avatar
Kenneth Leiter committed
1
/*****************************************************************************/
2 3
/*                                    Xdmf                                   */
/*                       Extensible Data Model and Format                    */
Kenneth Leiter's avatar
Kenneth Leiter committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*                                                                           */
/*  Id : XdmfArray.tpp                                                       */
/*                                                                           */
/*  Author:                                                                  */
/*     Kenneth Leiter                                                        */
/*     kenneth.leiter@arl.army.mil                                           */
/*     US Army Research Laboratory                                           */
/*     Aberdeen Proving Ground, MD                                           */
/*                                                                           */
/*     Copyright @ 2011 US Army Research Laboratory                          */
/*     All Rights Reserved                                                   */
/*     See Copyright.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.                                                 */
/*                                                                           */
/*****************************************************************************/

24 25
#include <functional>
#include <numeric>
26
#include <sstream>
27 28
#include "XdmfArray.hpp"

29 30 31 32 33 34 35 36 37 38
template <typename T>
class XdmfArray::GetValue : public boost::static_visitor<T> {
public:

  GetValue(const unsigned int index) :
    mIndex(index)
  {
  }

  T
39
  operator()(const boost::blank &) const
40
  {
41
    return 0;
42 43
  }

44 45 46 47 48 49
  T
  operator()(const shared_ptr<std::vector<std::string> > & array) const
  {
    return (T)atof(array->operator[](mIndex).c_str());
  }

50 51 52 53 54 55 56
  template<typename U>
  T
  operator()(const shared_ptr<std::vector<U> > & array) const
  {
    return (T)array->operator[](mIndex);
  }

57 58 59 60 61 62 63
  template<typename U>
  T
  operator()(const boost::shared_array<const U> & array) const
  {
    return (T)array[mIndex];
  }

64 65 66 67 68
private:

  const unsigned int mIndex;
};

69
template <>
70
class XdmfArray::GetValue<std::string> :
71 72 73 74 75 76 77 78 79
  public boost::static_visitor<std::string> {
public:

  GetValue(const unsigned int index) :
    mIndex(index)
  {
  }

  std::string
80
  operator()(const boost::blank &) const
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 111 112 113 114 115 116 117 118 119
  {
    return "";
  }

  std::string
  operator()(const shared_ptr<std::vector<std::string> > & array) const
  {
    return array->operator[](mIndex);
  }

  template<typename U>
  std::string
  operator()(const shared_ptr<std::vector<U> > & array) const
  {
    std::stringstream value;
    value << array->operator[](mIndex);
    return value.str();
  }

  std::string
  operator()(const boost::shared_array<const std::string> & array) const
  {
    return array[mIndex];
  }

  template<typename U>
  std::string
  operator()(const boost::shared_array<const U> & array) const
  {
    std::stringstream value;
    value << array[mIndex];
    return value.str();
  }

private:

  const unsigned int mIndex;
};

120
template <typename T>
121
class XdmfArray::GetValues : public boost::static_visitor<void> {
122 123
public:

124 125 126 127 128 129 130 131 132 133 134 135 136 137
  GetValues(const unsigned int startIndex,
            T * valuesPointer,
            const unsigned int numValues,
            const unsigned int arrayStride,
            const unsigned int valuesStride) :
    mStartIndex(startIndex),
    mValuesPointer(valuesPointer),
    mNumValues(numValues),
    mArrayStride(arrayStride),
    mValuesStride(valuesStride)
  {
  }

  void
138
  operator()(const boost::blank &) const
139
  {
140
    return;
141 142
  }

143 144 145 146 147 148 149 150 151
  void
  operator()(const shared_ptr<std::vector<std::string> > & array) const
  {
    for(unsigned int i=0; i<mNumValues; ++i) {
      mValuesPointer[i*mValuesStride] =
        (T)atof(array->operator[](mStartIndex + i*mArrayStride).c_str());
    }
  }

152 153
  template<typename U>
  void
154
  operator()(const shared_ptr<std::vector<U> > & array) const
155 156 157 158 159 160
  {
    for(unsigned int i=0; i<mNumValues; ++i) {
      mValuesPointer[i*mValuesStride] =
        (T)array->operator[](mStartIndex + i*mArrayStride);
    }
  }
161

162 163 164 165 166 167 168 169 170
  template<typename U>
  void
  operator()(const boost::shared_array<const U> & array) const
  {
    for(unsigned int i=0; i<mNumValues; ++i) {
      mValuesPointer[i*mValuesStride] = (T)array[mStartIndex + i*mArrayStride];
    }
  }

171 172
private:

173 174 175 176 177
  const unsigned int mStartIndex;
  T * mValuesPointer;
  const unsigned int mNumValues;
  const unsigned int mArrayStride;
  const unsigned int mValuesStride;
178 179
};

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
template <>
class XdmfArray::GetValues<std::string> : public boost::static_visitor<void> {
public:

  GetValues(const unsigned int startIndex,
            std::string * valuesPointer,
            const unsigned int numValues,
            const unsigned int arrayStride,
            const unsigned int valuesStride) :
    mStartIndex(startIndex),
    mValuesPointer(valuesPointer),
    mNumValues(numValues),
    mArrayStride(arrayStride),
    mValuesStride(valuesStride)
  {
  }

  void
198
  operator()(const boost::blank &) const
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
  {
    return;
  }

  template<typename U>
  void
  operator()(const shared_ptr<std::vector<U> > & array) const
  {
    for(unsigned int i=0; i<mNumValues; ++i) {
      std::stringstream value;
      value << array->operator[](mStartIndex + i*mArrayStride);
      mValuesPointer[i*mValuesStride] = value.str();
    }
  }

  template<typename U>
  void
  operator()(const boost::shared_array<const U> & array) const
  {
    for(unsigned int i=0; i<mNumValues; ++i) {
      std::stringstream value;
      value << array[mStartIndex + i*mArrayStride];
      mValuesPointer[i*mValuesStride] = value.str();
    }
  }

private:

  const unsigned int mStartIndex;
  std::string * mValuesPointer;
  const unsigned int mNumValues;
  const unsigned int mArrayStride;
  const unsigned int mValuesStride;
};

234
template <typename T>
235
class XdmfArray::Insert : public boost::static_visitor<void> {
236 237
public:

238 239
  Insert(XdmfArray * const array,
         const unsigned int startIndex,
240 241 242
         const T * const valuesPointer,
         const unsigned int numValues,
         const unsigned int arrayStride,
243 244
         const unsigned int valuesStride,
         std::vector<unsigned int> & dimensions) :
245
    mArray(array),
246 247 248 249
    mStartIndex(startIndex),
    mValuesPointer(valuesPointer),
    mNumValues(numValues),
    mArrayStride(arrayStride),
250 251
    mValuesStride(valuesStride),
    mDimensions(dimensions)
252 253 254
  {
  }

255
  void
256
  operator()(const boost::blank &) const
257 258 259 260 261 262
  {
    mArray->initialize<T>();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

263 264 265
  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
266
    unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1;
267 268 269 270 271 272 273 274 275 276 277
    if(array->size() < size) {
      array->resize(size);
      mDimensions.clear();
    }
    for(unsigned int i=0; i<mNumValues; ++i) {
      std::stringstream value;
      value << mValuesPointer[i*mValuesStride];
      array->operator[](mStartIndex + i*mArrayStride) = value.str();
    }
  }

278 279
  template<typename U>
  void
280
  operator()(shared_ptr<std::vector<U> > & array) const
281
  {
282
    unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1;
283 284
    if(array->size() < size) {
      array->resize(size);
285
      mDimensions.clear();
286 287 288 289 290 291
    }
    for(unsigned int i=0; i<mNumValues; ++i) {
      array->operator[](mStartIndex + i*mArrayStride) =
        (U)mValuesPointer[i*mValuesStride];
    }
  }
292

293 294
  template<typename U>
  void
295
  operator()(boost::shared_array<const U> &) const
296 297 298 299 300 301
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

302 303
private:

304
  XdmfArray * const mArray;
305 306 307 308 309
  const unsigned int mStartIndex;
  const T * const mValuesPointer;
  const unsigned int mNumValues;
  const unsigned int mArrayStride;
  const unsigned int mValuesStride;
310
  std::vector<unsigned int> & mDimensions;
311 312
};

313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
template <>
class XdmfArray::Insert<std::string> : public boost::static_visitor<void> {
public:

  Insert(XdmfArray * const array,
         const unsigned int startIndex,
         const std::string * const valuesPointer,
         const unsigned int numValues,
         const unsigned int arrayStride,
         const unsigned int valuesStride,
         std::vector<unsigned int> & dimensions) :
    mArray(array),
    mStartIndex(startIndex),
    mValuesPointer(valuesPointer),
    mNumValues(numValues),
    mArrayStride(arrayStride),
    mValuesStride(valuesStride),
    mDimensions(dimensions)
  {
  }

  void
335
  operator()(const boost::blank &) const
336 337 338 339 340 341 342 343 344
  {
    mArray->initialize<std::string>();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
345
    unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1;
346 347 348 349 350 351 352 353 354 355 356 357 358 359
    if(array->size() < size) {
      array->resize(size);
      mDimensions.clear();
    }
    for(unsigned int i=0; i<mNumValues; ++i) {
      array->operator[](mStartIndex + i*mArrayStride) =
        mValuesPointer[i*mValuesStride].c_str();
    }
  }

  template<typename U>
  void
  operator()(shared_ptr<std::vector<U> > & array) const
  {
360
    unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1;
361 362 363 364 365 366 367 368 369 370 371 372
    if(array->size() < size) {
      array->resize(size);
      mDimensions.clear();
    }
    for(unsigned int i=0; i<mNumValues; ++i) {
      array->operator[](mStartIndex + i*mArrayStride) =
        (U)atof(mValuesPointer[i*mValuesStride].c_str());
    }
  }

  template<typename U>
  void
373
  operator()(boost::shared_array<const U> &) const
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

private:

  XdmfArray * const mArray;
  const unsigned int mStartIndex;
  const std::string * const mValuesPointer;
  const unsigned int mNumValues;
  const unsigned int mArrayStride;
  const unsigned int mValuesStride;
  std::vector<unsigned int> & mDimensions;
};

391
template <typename T>
392
class XdmfArray::PushBack : public boost::static_visitor<void> {
393 394
public:

395 396 397 398 399 400 401 402
  PushBack(const T & val,
           XdmfArray * const array) :
    mVal(val),
    mArray(array)
  {
  }

  void
403
  operator()(const boost::blank &) const
404
  {
405 406 407
    mArray->initialize<T>();
    boost::apply_visitor(*this,
                         mArray->mArray);
408
  }
409

410 411 412 413 414 415 416 417 418
  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
    std::stringstream value;
    value << mVal;
    array->push_back(value.str());
    mArray->mDimensions.clear();
  }

419 420
  template<typename U>
  void
421
  operator()(shared_ptr<std::vector<U> > & array) const
422 423
  {
    array->push_back((U)mVal);
424 425 426 427 428
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
429
  operator()(const boost::shared_array<const U> &) const
430 431 432 433
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
434
  }
435 436 437

private:

438
  const T & mVal;
439
  XdmfArray * const mArray;
440 441
};

442 443 444 445 446 447 448 449 450 451 452 453
template <>
class XdmfArray::PushBack<std::string> : public boost::static_visitor<void> {
public:

  PushBack(const std::string & val,
           XdmfArray * const array) :
    mVal(val),
    mArray(array)
  {
  }

  void
454
  operator()(const boost::blank &) const
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
  {
    mArray->initialize<std::string>();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
    array->push_back(mVal);
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
  operator()(shared_ptr<std::vector<U> > & array) const
  {
    array->push_back((U)atof(mVal.c_str()));
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
478
  operator()(const boost::shared_array<const U> &) const
479 480 481 482 483 484 485 486 487 488 489 490
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

private:

  const std::string & mVal;
  XdmfArray * const mArray;
};

491
template <typename T>
492
class XdmfArray::Resize : public boost::static_visitor<void> {
493 494
public:

495 496
  Resize(XdmfArray * const array,
         const unsigned int numValues,
497
         const T & val) :
498
    mArray(array),
499 500 501 502
    mNumValues(numValues),
    mVal(val)
  {
  }
503

504
  void
505
  operator()(const boost::blank &) const
506 507 508 509 510 511
  {
    mArray->initialize<T>();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

512 513 514 515 516 517 518 519 520
  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
    std::stringstream value;
    value << mVal;
    array->resize(mNumValues, value.str());
    mArray->mDimensions.clear();
  }

521 522
  template<typename U>
  void
523
  operator()(shared_ptr<std::vector<U> > & array) const
524 525
  {
    array->resize(mNumValues, (U)mVal);
526 527 528 529 530
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
531
  operator()(const boost::shared_array<const U> &) const
532 533 534 535
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
536
  }
537 538 539

private:

540
  XdmfArray * mArray;
541 542
  const unsigned int mNumValues;
  const T & mVal;
543 544
};

545 546 547 548 549 550 551 552 553 554 555 556 557 558
template <>
class XdmfArray::Resize<std::string> : public boost::static_visitor<void> {
public:

  Resize(XdmfArray * const array,
         const unsigned int numValues,
         const std::string & val) :
    mArray(array),
    mNumValues(numValues),
    mVal(val)
  {
  }

  void
559
  operator()(const boost::blank &) const
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
  {
    mArray->initialize<std::string>();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

  void
  operator()(shared_ptr<std::vector<std::string> > & array) const
  {
    array->resize(mNumValues, mVal);
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
  operator()(shared_ptr<std::vector<U> > & array) const
  {
    array->resize(mNumValues, (U)atof(mVal.c_str()));
    mArray->mDimensions.clear();
  }

  template<typename U>
  void
583
  operator()(const boost::shared_array<const U> &) const
584 585 586 587 588 589 590 591 592 593 594 595 596
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

private:

  XdmfArray * mArray;
  const unsigned int mNumValues;
  const std::string & mVal;
};

597
struct XdmfArray::NullDeleter
598
{
599 600 601 602
  void
  operator()(void const *) const
  {
  }
603 604
};

605
template <typename T>
606 607
T
XdmfArray::getValue(const unsigned int index) const
608
{
609 610
  return boost::apply_visitor(GetValue<T>(index),
                              mArray);
611 612
}

613
template <typename T>
614 615 616 617 618 619
void
XdmfArray::getValues(const unsigned int startIndex,
                     T * const valuesPointer,
                     const unsigned int numValues,
                     const unsigned int arrayStride,
                     const unsigned int valuesStride) const
620
{
621 622 623 624 625 626
  boost::apply_visitor(GetValues<T>(startIndex,
                                    valuesPointer,
                                    numValues,
                                    arrayStride,
                                    valuesStride),
                       mArray);
627 628
}

629
template <typename T>
630
shared_ptr<std::vector<T> >
631
XdmfArray::getValuesInternal()
632
{
633
  this->internalizeArrayPointer();
634
  try {
635 636
    shared_ptr<std::vector<T> > currArray =
      boost::get<shared_ptr<std::vector<T> > >(mArray);
637 638 639
    return currArray;
  }
  catch(const boost::bad_get & exception) {
640
    return shared_ptr<std::vector<T> >();
641
  }
642 643
}

644
template <typename T>
645
shared_ptr<std::vector<T> >
646
XdmfArray::initialize(const unsigned int size)
647
{
648
  // Set type of variant to type of pointer
649
  shared_ptr<std::vector<T> > newArray(new std::vector<T>(size));
650 651 652 653 654
  if(mTmpReserveSize > 0) {
    newArray->reserve(mTmpReserveSize);
    mTmpReserveSize = 0;
  }
  mArray = newArray;
655
  this->setIsChanged(true);
656
  return newArray;
657 658
}

659
template <typename T>
660
shared_ptr<std::vector<T> >
661 662 663
XdmfArray::initialize(const std::vector<unsigned int> & dimensions)
{
  mDimensions = dimensions;
664 665
  const unsigned int size = static_cast<unsigned int>(
    std::accumulate(dimensions.begin(),
666 667
                                            dimensions.end(),
                                            1,
668
                    std::multiplies<unsigned int>()));
669 670 671
  return this->initialize<T>(size);
}

672
template<typename T>
673 674 675
void
XdmfArray::insert(const unsigned int index,
                  const T & value)
676
{
677
  boost::apply_visitor(Insert<T>(this,
678 679 680 681 682 683
                                 index,
                                 &value,
                                 1,
                                 0,
                                 0,
                                 mDimensions),
684
                       mArray);
685 686
}

687
template <typename T>
688 689 690 691 692 693
void
XdmfArray::insert(const unsigned int startIndex,
                  const T * const valuesPointer,
                  const unsigned int numValues,
                  const unsigned int arrayStride,
                  const unsigned int valuesStride)
694
{
695 696
  boost::apply_visitor(Insert<T>(this,
                                 startIndex,
697 698 699
                                 valuesPointer,
                                 numValues,
                                 arrayStride,
700 701
                                 valuesStride,
                                 mDimensions),
702
                       mArray);
703
  this->setIsChanged(true);
704 705
}

706
template <typename T>
707 708
void
XdmfArray::pushBack(const T & value)
709
{
710
  return boost::apply_visitor(PushBack<T>(value,
711 712
                                          this),
                              mArray);
713
  this->setIsChanged(true);
714 715
}

716
template<typename T>
717 718 719
void
XdmfArray::resize(const unsigned int numValues,
                  const T & value)
720
{
721
  return boost::apply_visitor(Resize<T>(this,
722 723
                                        numValues,
                                        value),
724
                              mArray);
725
  this->setIsChanged(true);
726 727
}

728
template<typename T>
729
void
730 731 732
XdmfArray::resize(const std::vector<unsigned int> & dimensions,
                  const T & value)
{
733 734
  const unsigned int size = static_cast<unsigned int>(
    std::accumulate(dimensions.begin(),
735 736
                                            dimensions.end(),
                                            1,
737
                    std::multiplies<unsigned int>()));
738 739
  this->resize(size, value);
  mDimensions = dimensions;
740
  this->setIsChanged(true);
741 742
}

743
template <typename T>
744 745 746 747
void
XdmfArray::setValuesInternal(const T * const arrayPointer,
                             const unsigned int numValues,
                             const bool transferOwnership)
748
{
749 750 751
  // Remove contents of internal array.
  if(transferOwnership) {
    const boost::shared_array<const T> newArrayPointer(arrayPointer);
752
    mArray = newArrayPointer;
753 754 755 756
  }
  else {
    const boost::shared_array<const T> newArrayPointer(arrayPointer,
                                                       NullDeleter());
757
    mArray = newArrayPointer;
758 759
  }
  mArrayPointerNumValues = numValues;
760
  this->setIsChanged(true);
761 762
}

763
template <typename T>
764 765 766
void
XdmfArray::setValuesInternal(std::vector<T> & array,
                             const bool transferOwnership)
767
{
768
  if(transferOwnership) {
769
    shared_ptr<std::vector<T> > newArray(&array);
770 771 772
    mArray = newArray;
  }
  else {
773
    shared_ptr<std::vector<T> > newArray(&array, NullDeleter());
774 775
    mArray = newArray;
  }
776
  this->setIsChanged(true);
777 778
}

779
template <typename T>
780
void
781
XdmfArray::setValuesInternal(const shared_ptr<std::vector<T> > array)
782
{
783
  mArray = array;
784
  this->setIsChanged(true);
785 786
}

787
template <typename T>
788 789
bool
XdmfArray::swap(std::vector<T> & array)
790
{
791 792 793
  this->internalizeArrayPointer();
  if(!this->isInitialized()) {
    this->initialize<T>();
794
  }
795
  try {
796 797
    shared_ptr<std::vector<T> > currArray =
      boost::get<shared_ptr<std::vector<T> > >(mArray);
798 799 800
    currArray->swap(array);
    return true;
  }
801
  catch(const boost::bad_get & exception) {
802 803
    return false;
  }
804
  this->setIsChanged(true);
805 806
}

807
template <typename T>
808
bool
809
XdmfArray::swap(const shared_ptr<std::vector<T> > array)
810
{
811
  return this->swap(*array.get());
812
}