OpenVDB  7.0.0
PagedArray.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
14 
15 #ifndef OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
16 #define OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
17 
18 #include <openvdb/version.h>
19 #include <openvdb/Types.h>// SharedPtr
20 #include <deque>
21 #include <cassert>
22 #include <iostream>
23 #include <algorithm>// std::swap
24 #include <tbb/atomic.h>
25 #include <tbb/spin_mutex.h>
26 #include <tbb/parallel_for.h>
27 #include <tbb/parallel_sort.h>
28 
29 namespace openvdb {
31 namespace OPENVDB_VERSION_NAME {
32 namespace util {
33 
35 
36 
154 
155 template<typename ValueT, size_t Log2PageSize = 10UL>
157 {
158 private:
159  class Page;
160 
161  // must allow mutiple threads to call operator[] as long as only one thread calls push_back
162  using PageTableT = std::deque<Page*>;
163 
164 public:
165  using ValueType = ValueT;
167 
169  PagedArray() : mCapacity{0} { mSize = 0; }
170 
172  ~PagedArray() { this->clear(); }
173 
174  // Disallow copy construction and assignment
175  PagedArray(const PagedArray&) = delete;
176  PagedArray& operator=(const PagedArray&) = delete;
177 
179  static Ptr create() { return Ptr(new PagedArray); }
180 
189  class ValueBuffer;
190 
192  class ConstIterator;
193 
195  class Iterator;
196 
204  size_t push_back(const ValueType& value)
205  {
206  const size_t index = mSize.fetch_and_increment();
207  if (index >= mCapacity) this->grow(index);
208  (*mPageTable[index >> Log2PageSize])[index] = value;
209  return index;
210  }
211 
219  size_t push_back_unsafe(const ValueType& value)
220  {
221  const size_t index = mSize.fetch_and_increment();
222  if (index >= mCapacity) {
223  mPageTable.push_back( new Page() );
224  mCapacity += Page::Size;
225  }
226  (*mPageTable[index >> Log2PageSize])[index] = value;
227  return index;
228  }
229 
233  void shrink_to_fit();
234 
243  {
244  assert(i<mCapacity);
245  return (*mPageTable[i>>Log2PageSize])[i];
246  }
247 
255  const ValueType& operator[](size_t i) const
256  {
257  assert(i<mCapacity);
258  return (*mPageTable[i>>Log2PageSize])[i];
259  }
260 
266  void fill(const ValueType& v)
267  {
268  auto op = [&](const tbb::blocked_range<size_t>& r){
269  for(size_t i=r.begin(); i!=r.end(); ++i) mPageTable[i]->fill(v);
270  };
271  tbb::parallel_for(tbb::blocked_range<size_t>(0, this->pageCount()), op);
272  }
273 
281  bool copy(ValueType *p, size_t count) const
282  {
283  size_t last_page = count >> Log2PageSize;
284  if (last_page >= this->pageCount()) return false;
285  auto op = [&](const tbb::blocked_range<size_t>& r){
286  for (size_t i=r.begin(); i!=r.end(); ++i) {
287  mPageTable[i]->copy(p+i*Page::Size, Page::Size);
288  }
289  };
290  if (size_t m = count & Page::Mask) {//count is not divisible by page size
291  tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page, 32), op);
292  mPageTable[last_page]->copy(p+last_page*Page::Size, m);
293  } else {
294  tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page+1, 32), op);
295  }
296  return true;
297  }
298  void copy(ValueType *p) const { this->copy(p, mSize); }
299 
314  void resize(size_t size)
315  {
316  mSize = size;
317  if (size > mCapacity) {
318  this->grow(size-1);
319  } else {
320  this->shrink_to_fit();
321  }
322  }
323 
339  void resize(size_t size, const ValueType& v)
340  {
341  this->resize(size);
342  this->fill(v);
343  }
344 
346  size_t size() const { return mSize; }
347 
350  size_t capacity() const { return mCapacity; }
351 
354  size_t freeCount() const { return mCapacity - mSize; }
355 
357  size_t pageCount() const { return mPageTable.size(); }
358 
360  static size_t pageSize() { return Page::Size; }
361 
363  static size_t log2PageSize() { return Log2PageSize; }
364 
366  size_t memUsage() const
367  {
368  return sizeof(*this) + mPageTable.size() * Page::memUsage();
369  }
370 
372  bool isEmpty() const { return mSize == 0; }
373 
380  bool isPartiallyFull() const { return (mSize & Page::Mask) > 0; }
381 
385  void clear()
386  {
387  for (size_t i=0, n=mPageTable.size(); i<n; ++i) delete mPageTable[i];
388  PageTableT().swap(mPageTable);
389  mSize = 0;
390  mCapacity = 0;
391  }
392 
394  Iterator begin() { return Iterator(*this, 0); }
395 
401  Iterator end() { return Iterator(*this, mSize); }
402 
404  ConstIterator cbegin() const { return ConstIterator(*this, 0); }
406  ConstIterator begin() const { return ConstIterator(*this, 0); }
408 
410  ConstIterator cend() const { return ConstIterator(*this, mSize); }
416  ConstIterator end() const { return ConstIterator(*this, mSize); }
418 
420  void sort() { tbb::parallel_sort(this->begin(), this->end(), std::less<ValueT>() ); }
421 
423  void invSort() { tbb::parallel_sort(this->begin(), this->end(), std::greater<ValueT>()); }
424 
426  template <typename Functor>
431  void sort(Functor func) { tbb::parallel_sort(this->begin(), this->end(), func ); }
433 
441  void merge(PagedArray& other);
442 
444  void print(std::ostream& os = std::cout) const
445  {
446  os << "PagedArray:\n"
447  << "\tSize: " << this->size() << " elements\n"
448  << "\tPage table: " << this->pageCount() << " pages\n"
449  << "\tPage size: " << this->pageSize() << " elements\n"
450  << "\tCapacity: " << this->capacity() << " elements\n"
451  << "\tFootprint: " << this->memUsage() << " bytes\n";
452  }
453 
454 private:
455 
456  friend class ValueBuffer;
457 
458  void grow(size_t index)
459  {
460  tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
461  while(index >= mCapacity) {
462  mPageTable.push_back( new Page() );
463  mCapacity += Page::Size;
464  }
465  }
466 
467  void add_full(Page*& page, size_t size);
468 
469  void add_partially_full(Page*& page, size_t size);
470 
471  void add(Page*& page, size_t size) {
472  tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
473  if (size == Page::Size) {//page is full
474  this->add_full(page, size);
475  } else if (size>0) {//page is only partially full
476  this->add_partially_full(page, size);
477  }
478  }
479  PageTableT mPageTable;//holds points to allocated pages
480  tbb::atomic<size_t> mSize;// current number of elements in array
481  size_t mCapacity;//capacity of array given the current page count
482  tbb::spin_mutex mGrowthMutex;//Mutex-lock required to grow pages
483 }; // Public class PagedArray
484 
486 
487 template <typename ValueT, size_t Log2PageSize>
489 {
490  if (mPageTable.size() > (mSize >> Log2PageSize) + 1) {
491  tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
492  const size_t pageCount = (mSize >> Log2PageSize) + 1;
493  if (mPageTable.size() > pageCount) {
494  delete mPageTable.back();
495  mPageTable.pop_back();
496  mCapacity -= Page::Size;
497  }
498  }
499 }
500 
501 template <typename ValueT, size_t Log2PageSize>
503 {
504  if (&other != this && !other.isEmpty()) {
505  tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
506  // extract last partially full page if it exists
507  Page* page = nullptr;
508  const size_t size = mSize & Page::Mask; //number of elements in the last page
509  if ( size > 0 ) {
510  page = mPageTable.back();
511  mPageTable.pop_back();
512  mSize -= size;
513  }
514  // transfer all pages from the other page table
515  mPageTable.insert(mPageTable.end(), other.mPageTable.begin(), other.mPageTable.end());
516  mSize += other.mSize;
517  mCapacity = Page::Size*mPageTable.size();
518  other.mSize = 0;
519  other.mCapacity = 0;
520  PageTableT().swap(other.mPageTable);
521  // add back last partially full page
522  if (page) this->add_partially_full(page, size);
523  }
524 }
525 
526 template <typename ValueT, size_t Log2PageSize>
527 void PagedArray<ValueT, Log2PageSize>::add_full(Page*& page, size_t size)
528 {
529  assert(size == Page::Size);//page must be full
530  if (mSize & Page::Mask) {//page-table is partially full
531  Page*& tmp = mPageTable.back();
532  std::swap(tmp, page);//swap last table entry with page
533  }
534  mPageTable.push_back(page);
535  mCapacity += Page::Size;
536  mSize += size;
537  page = nullptr;
538 }
539 
540 template <typename ValueT, size_t Log2PageSize>
542 {
543  assert(size > 0 && size < Page::Size);//page must be partially full
544  if (size_t m = mSize & Page::Mask) {//page table is also partially full
545  ValueT *s = page->data(), *t = mPageTable.back()->data() + m;
546  for (size_t i=std::min(mSize+size, mCapacity)-mSize; i; --i) *t++ = *s++;
547  if (mSize+size > mCapacity) {//grow page table
548  mPageTable.push_back( new Page() );
549  t = mPageTable.back()->data();
550  for (size_t i=mSize+size-mCapacity; i; --i) *t++ = *s++;
551  mCapacity += Page::Size;
552  }
553  } else {//page table is full so simply append page
554  mPageTable.push_back( page );
555  mCapacity += Page::Size;
556  page = nullptr;
557  }
558  mSize += size;
559 }
560 
562 
563 // Public member-class of PagedArray
564 template <typename ValueT, size_t Log2PageSize>
565 class PagedArray<ValueT, Log2PageSize>::
567 {
568 public:
571  ValueBuffer(PagedArray& parent) : mParent(&parent), mPage(new Page()), mSize(0) {}
574  ValueBuffer(const ValueBuffer& other) : mParent(other.mParent), mPage(new Page()), mSize(0) {}
576  ~ValueBuffer() { mParent->add(mPage, mSize); delete mPage; }
577 
578  ValueBuffer& operator=(const ValueBuffer&) = delete;// disallow copy assignment
579 
584  void push_back(const ValueT& v) {
585  (*mPage)[mSize++] = v;
586  if (mSize == Page::Size) this->flush();
587  }
593  void flush() {
594  mParent->add(mPage, mSize);
595  if (mPage == nullptr) mPage = new Page();
596  mSize = 0;
597  }
599  PagedArrayType& parent() const { return *mParent; }
601  size_t size() const { return mSize; }
602 private:
603  PagedArray* mParent;
604  Page* mPage;
605  size_t mSize;
606 };// Public class PagedArray::ValueBuffer
607 
609 
610 // Const std-compliant iterator
611 // Public member-class of PagedArray
612 template <typename ValueT, size_t Log2PageSize>
613 class PagedArray<ValueT, Log2PageSize>::
614 ConstIterator : public std::iterator<std::random_access_iterator_tag, ValueT>
615 {
616 public:
617  using BaseT = std::iterator<std::random_access_iterator_tag, ValueT>;
618  using difference_type = typename BaseT::difference_type;
619  // constructors and assignment
620  ConstIterator() : mPos(0), mParent(nullptr) {}
621  ConstIterator(const PagedArray& parent, size_t pos=0) : mPos(pos), mParent(&parent) {}
622  ConstIterator(const ConstIterator& other) : mPos(other.mPos), mParent(other.mParent) {}
624  mPos=other.mPos;
625  mParent=other.mParent;
626  return *this;
627  }
628  // prefix
629  ConstIterator& operator++() { ++mPos; return *this; }
630  ConstIterator& operator--() { --mPos; return *this; }
631  // postfix
632  ConstIterator operator++(int) { ConstIterator tmp(*this); ++mPos; return tmp; }
633  ConstIterator operator--(int) { ConstIterator tmp(*this); --mPos; return tmp; }
634  // value access
635  const ValueT& operator*() const { return (*mParent)[mPos]; }
636  const ValueT* operator->() const { return &(this->operator*()); }
637  const ValueT& operator[](const difference_type& pos) const { return (*mParent)[mPos+pos]; }
638  // offset
639  ConstIterator& operator+=(const difference_type& pos) { mPos += pos; return *this; }
640  ConstIterator& operator-=(const difference_type& pos) { mPos -= pos; return *this; }
641  ConstIterator operator+(const difference_type &pos) const { return Iterator(*mParent,mPos+pos); }
642  ConstIterator operator-(const difference_type &pos) const { return Iterator(*mParent,mPos-pos); }
643  difference_type operator-(const ConstIterator& other) const { return mPos - other.pos(); }
644  // comparisons
645  bool operator==(const ConstIterator& other) const { return mPos == other.mPos; }
646  bool operator!=(const ConstIterator& other) const { return mPos != other.mPos; }
647  bool operator>=(const ConstIterator& other) const { return mPos >= other.mPos; }
648  bool operator<=(const ConstIterator& other) const { return mPos <= other.mPos; }
649  bool operator< (const ConstIterator& other) const { return mPos < other.mPos; }
650  bool operator> (const ConstIterator& other) const { return mPos > other.mPos; }
651  // non-std methods
652  bool isValid() const { return mParent != nullptr && mPos < mParent->size(); }
653  size_t pos() const { return mPos; }
654 private:
655  size_t mPos;
656  const PagedArray* mParent;
657 };// Public class PagedArray::ConstIterator
658 
660 
661 // Non-const std-compliant iterator
662 // Public member-class of PagedArray
663 template <typename ValueT, size_t Log2PageSize>
664 class PagedArray<ValueT, Log2PageSize>::
665 Iterator : public std::iterator<std::random_access_iterator_tag, ValueT>
666 {
667 public:
668  using BaseT = std::iterator<std::random_access_iterator_tag, ValueT>;
669  using difference_type = typename BaseT::difference_type;
670  // constructors and assignment
671  Iterator() : mPos(0), mParent(nullptr) {}
672  Iterator(PagedArray& parent, size_t pos=0) : mPos(pos), mParent(&parent) {}
673  Iterator(const Iterator& other) : mPos(other.mPos), mParent(other.mParent) {}
674  Iterator& operator=(const Iterator& other) {
675  mPos=other.mPos;
676  mParent=other.mParent;
677  return *this;
678  }
679  // prefix
680  Iterator& operator++() { ++mPos; return *this; }
681  Iterator& operator--() { --mPos; return *this; }
682  // postfix
683  Iterator operator++(int) { Iterator tmp(*this); ++mPos; return tmp; }
684  Iterator operator--(int) { Iterator tmp(*this); --mPos; return tmp; }
685  // value access
686  ValueT& operator*() const { return (*mParent)[mPos]; }
687  ValueT* operator->() const { return &(this->operator*()); }
688  ValueT& operator[](const difference_type& pos) const { return (*mParent)[mPos+pos]; }
689  // offset
690  Iterator& operator+=(const difference_type& pos) { mPos += pos; return *this; }
691  Iterator& operator-=(const difference_type& pos) { mPos -= pos; return *this; }
692  Iterator operator+(const difference_type &pos) const { return Iterator(*mParent, mPos+pos); }
693  Iterator operator-(const difference_type &pos) const { return Iterator(*mParent, mPos-pos); }
694  difference_type operator-(const Iterator& other) const { return mPos - other.pos(); }
695  // comparisons
696  bool operator==(const Iterator& other) const { return mPos == other.mPos; }
697  bool operator!=(const Iterator& other) const { return mPos != other.mPos; }
698  bool operator>=(const Iterator& other) const { return mPos >= other.mPos; }
699  bool operator<=(const Iterator& other) const { return mPos <= other.mPos; }
700  bool operator< (const Iterator& other) const { return mPos < other.mPos; }
701  bool operator> (const Iterator& other) const { return mPos > other.mPos; }
702  // non-std methods
703  bool isValid() const { return mParent != nullptr && mPos < mParent->size(); }
704  size_t pos() const { return mPos; }
705  private:
706  size_t mPos;
707  PagedArray* mParent;
708 };// Public class PagedArray::Iterator
709 
711 
712 // Private member-class of PagedArray implementing a memory page
713 template <typename ValueT, size_t Log2PageSize>
714 class PagedArray<ValueT, Log2PageSize>::
715 Page
716 {
717 public:
718  static const size_t Size = 1UL << Log2PageSize;
719  static const size_t Mask = Size - 1UL;
720  static size_t memUsage() { return sizeof(ValueT)*Size; }
721  // Raw memory allocation without any initialization
722  Page() : mData(reinterpret_cast<ValueT*>(new char[sizeof(ValueT)*Size])) {}
723  ~Page() { delete [] mData; }
724  Page(const Page&) = delete;//copy construction is not implemented
725  Page& operator=(const Page&) = delete;//copy assignment is not implemented
726  ValueT& operator[](const size_t i) { return mData[i & Mask]; }
727  const ValueT& operator[](const size_t i) const { return mData[i & Mask]; }
728  void fill(const ValueT& v) {
729  ValueT* dst = mData;
730  for (size_t i=Size; i; --i) *dst++ = v;
731  }
732  ValueT* data() { return mData; }
733  // Copy the first n elements of this Page to dst (which is assumed to large
734  // enough to hold the n elements).
735  void copy(ValueType *dst, size_t n) const {
736  const ValueT* src = mData;
737  for (size_t i=n; i; --i) *dst++ = *src++;
738  }
739 protected:
740  ValueT* mData;
741 };// Private class PagedArray::Page
742 
744 
745 } // namespace util
746 } // namespace OPENVDB_VERSION_NAME
747 } // namespace openvdb
748 
749 #endif // OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
ValueBuffer(PagedArray &parent)
Constructor from a PageArray.
Definition: PagedArray.h:571
void resize(size_t size, const ValueType &v)
Resize this array to the specified size and initialize all values to v.
Definition: PagedArray.h:339
static Ptr create()
Return a shared pointer to a new instance of this class.
Definition: PagedArray.h:179
bool operator<=(const Iterator &other) const
Definition: PagedArray.h:699
ValueT & operator*() const
Definition: PagedArray.h:686
bool operator==(const Iterator &other) const
Definition: PagedArray.h:696
Definition: PagedArray.h:714
ConstIterator begin() const
Return a const iterator pointing to the first element.
Definition: PagedArray.h:406
size_t push_back(const ValueType &value)
Thread safe insertion, adds a new element at the end and increases the container size by one and retu...
Definition: PagedArray.h:204
Iterator operator--(int)
Definition: PagedArray.h:684
typename BaseT::difference_type difference_type
Definition: PagedArray.h:669
size_t size() const
Return the number of elements in this array.
Definition: PagedArray.h:346
ValueType & operator[](size_t i)
Return a reference to the value at the specified offset.
Definition: PagedArray.h:242
typename BaseT::difference_type difference_type
Definition: PagedArray.h:618
void push_back(const ValueT &v)
Add a value to the buffer and increment the size.
Definition: PagedArray.h:584
bool operator>=(const ConstIterator &other) const
Definition: PagedArray.h:647
difference_type operator-(const Iterator &other) const
Definition: PagedArray.h:694
std::shared_ptr< T > SharedPtr
Definition: Types.h:91
bool operator>=(const Iterator &other) const
Definition: PagedArray.h:698
void resize(size_t size)
Resize this array to the specified size.
Definition: PagedArray.h:314
ValueT * data()
Definition: PagedArray.h:732
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:668
static size_t memUsage()
Definition: PagedArray.h:720
void clear()
Removes all elements from the array and delete all pages.
Definition: PagedArray.h:385
ValueT * operator->() const
Definition: PagedArray.h:687
void copy(ValueType *p) const
Definition: PagedArray.h:298
Iterator & operator=(const Iterator &other)
Definition: PagedArray.h:674
size_t pos() const
Definition: PagedArray.h:704
bool operator==(const ConstIterator &other) const
Definition: PagedArray.h:645
Iterator end()
Return a non-const iterator pointing to the past-the-last element.
Definition: PagedArray.h:401
PagedArrayType & parent() const
Return a reference to the parent PagedArray.
Definition: PagedArray.h:599
void sort(Functor func)
Parallel sort of all the elements based on a custom functor with the api:
Definition: PagedArray.h:431
SharedPtr< PagedArray > Ptr
Definition: PagedArray.h:166
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:192
Page()
Definition: PagedArray.h:722
ConstIterator(const ConstIterator &other)
Definition: PagedArray.h:622
void sort()
Parallel sort of all the elements in ascending order.
Definition: PagedArray.h:420
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
ConstIterator operator--(int)
Definition: PagedArray.h:633
const ValueType & operator[](size_t i) const
Return a const-reference to the value at the specified offset.
Definition: PagedArray.h:255
const ValueT * operator->() const
Definition: PagedArray.h:636
Iterator & operator++()
Definition: PagedArray.h:680
Iterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:690
void fill(const ValueType &v)
Set all elements in the page table to the specified value.
Definition: PagedArray.h:266
Iterator operator+(const difference_type &pos) const
Definition: PagedArray.h:692
ConstIterator end() const
Return a const iterator pointing to the past-the-last element.
Definition: PagedArray.h:416
size_t memUsage() const
Return the memory footprint of this array in bytes.
Definition: PagedArray.h:366
~ValueBuffer()
Destructor that transfers an buffered values to the parent PagedArray.
Definition: PagedArray.h:576
void flush()
Manually transfers the values in this buffer to the parent PagedArray.
Definition: PagedArray.h:593
ConstIterator operator-(const difference_type &pos) const
Definition: PagedArray.h:642
Definition: Exceptions.h:13
static size_t pageSize()
Return the number of elements per memory page.
Definition: PagedArray.h:360
ConstIterator(const PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:621
ConstIterator & operator=(const ConstIterator &other)
Definition: PagedArray.h:623
ValueT ValueType
Definition: PagedArray.h:165
size_t freeCount() const
Return the number of additional elements that can be added to this array without allocating more memo...
Definition: PagedArray.h:354
ConstIterator & operator++()
Definition: PagedArray.h:629
Iterator(PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:672
~PagedArray()
Destructor removed all allocated pages.
Definition: PagedArray.h:172
bool isPartiallyFull() const
Return true if the page table is partially full, i.e. the last non-empty page contains less than page...
Definition: PagedArray.h:380
void invSort()
Parallel sort of all the elements in descending order.
Definition: PagedArray.h:423
Iterator operator-(const difference_type &pos) const
Definition: PagedArray.h:693
const ValueT & operator[](const size_t i) const
Definition: PagedArray.h:727
Library and file format version numbers.
size_t pos() const
Definition: PagedArray.h:653
ValueT * mData
Definition: PagedArray.h:740
size_t push_back_unsafe(const ValueType &value)
Slightly faster than the thread-safe push_back above.
Definition: PagedArray.h:219
void copy(ValueType *dst, size_t n) const
Definition: PagedArray.h:735
~Page()
Definition: PagedArray.h:723
void fill(const ValueT &v)
Definition: PagedArray.h:728
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:180
Iterator()
Definition: PagedArray.h:671
size_t capacity() const
Return the maximum number of elements that this array can contain without allocating more memory page...
Definition: PagedArray.h:350
bool isEmpty() const
Return true if the container contains no elements.
Definition: PagedArray.h:372
const ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:637
const ValueT & operator*() const
Definition: PagedArray.h:635
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:102
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:618
ConstIterator operator+(const difference_type &pos) const
Definition: PagedArray.h:641
bool operator!=(const Iterator &other) const
Definition: PagedArray.h:697
ConstIterator & operator--()
Definition: PagedArray.h:630
Iterator & operator--()
Definition: PagedArray.h:681
ConstIterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:639
ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:688
ConstIterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:640
Iterator(const Iterator &other)
Definition: PagedArray.h:673
void print(std::ostream &os=std::cout) const
Print information for debugging.
Definition: PagedArray.h:444
ConstIterator operator++(int)
Definition: PagedArray.h:632
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
bool operator<=(const ConstIterator &other) const
Definition: PagedArray.h:648
size_t size() const
Return the current number of elements cached in this buffer.
Definition: PagedArray.h:601
bool isValid() const
Definition: PagedArray.h:652
Definition: PagedArray.h:664
size_t pageCount() const
Return the number of allocated memory pages.
Definition: PagedArray.h:357
ValueBuffer(const ValueBuffer &other)
Definition: PagedArray.h:574
bool copy(ValueType *p, size_t count) const
Copy the first count values in this PageArray into a raw c-style array, assuming it to be at least co...
Definition: PagedArray.h:281
Iterator begin()
Return a non-const iterator pointing to the first element.
Definition: PagedArray.h:394
Concurrent, page-based, dynamically-sized linear data structure with O(1) random access and STL-compl...
Definition: PagedArray.h:156
static size_t log2PageSize()
Return log2 of the number of elements per memory page.
Definition: PagedArray.h:363
bool isValid() const
Definition: PagedArray.h:703
PagedArray()
Default constructor.
Definition: PagedArray.h:169
Iterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:691
ValueT & operator[](const size_t i)
Definition: PagedArray.h:726
bool operator!=(const ConstIterator &other) const
Definition: PagedArray.h:646
difference_type operator-(const ConstIterator &other) const
Definition: PagedArray.h:643
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:617
ConstIterator()
Definition: PagedArray.h:620
Iterator operator++(int)
Definition: PagedArray.h:683