GEOSX
ArrayOfArraysView.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, Lawrence Livermore National Security, LLC and LvArray contributors.
3  * All rights reserved.
4  * See the LICENSE file for details.
5  * SPDX-License-Identifier: (BSD-3-Clause)
6  */
7 
13 #pragma once
14 
15 // Source includes
16 #include "bufferManipulation.hpp"
17 #include "arrayManipulation.hpp"
18 #include "ArraySlice.hpp"
19 #include "typeManipulation.hpp"
20 #include "math.hpp"
21 
22 // TPL includes
23 #include <RAJA/RAJA.hpp>
24 
25 // System includes
26 #include <cstring>
27 
28 #ifdef LVARRAY_BOUNDS_CHECK
29 
35 #define ARRAYOFARRAYS_CHECK_BOUNDS( i ) \
36  LVARRAY_ERROR_IF( !arrayManipulation::isPositive( i ) || i >= this->size(), \
37  "Bounds Check Failed: i=" << i << " size()=" << this->size() )
38 
45 #define ARRAYOFARRAYS_CHECK_BOUNDS2( i, j ) \
46  LVARRAY_ERROR_IF( !arrayManipulation::isPositive( i ) || i >= this->size() || \
47  !arrayManipulation::isPositive( j ) || j >= this->m_sizes[ i ], \
48  "Bounds Check Failed: i=" << i << " size()=" << this->size() << \
49  " j=" << j << " m_sizes[ i ]=" << this->m_sizes[ i ] )
50 
56 #define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS( i ) \
57  LVARRAY_ERROR_IF( !arrayManipulation::isPositive( i ) || i > this->size(), \
58  "Insert Bounds Check Failed: i=" << i << " size()=" << this->size() )
59 
66 #define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS2( i, j ) \
67  LVARRAY_ERROR_IF( !arrayManipulation::isPositive( i ) || i >= this->size() || \
68  !arrayManipulation::isPositive( j ) || j > this->sizeOfArray( i ), \
69  "Insert Bounds Check Failed: i=" << i << " size()=" << this->size() << \
70  " j=" << j << " sizeOfArray( i )=" << this->sizeOfArray( i ) )
71 
78 #define ARRAYOFARRAYS_CAPACITY_CHECK( i, increase ) \
79  LVARRAY_ERROR_IF( this->sizeOfArray( i ) + increase > this->capacityOfArray( i ), \
80  "Capacity Check Failed: i=" << i << " increase=" << increase << \
81  " sizeOfArray( i )=" << this->sizeOfArray( i ) << " capacityOfArray( i )=" << \
82  this->capacityOfArray( i ) )
83 
91 #define ARRAYOFARRAYS_ATOMIC_CAPACITY_CHECK( i, previousSize, increase ) \
92  LVARRAY_ERROR_IF( previousSize + increase > this->capacityOfArray( i ), \
93  "Capacity Check Failed: i=" << i << " increase=" << increase << \
94  " sizeOfArray( i )=" << previousSize << " capacityOfArray( i )=" << \
95  this->capacityOfArray( i ) )
96 
97 #else // LVARRAY_BOUNDS_CHECK
98 
104 #define ARRAYOFARRAYS_CHECK_BOUNDS( i )
105 
112 #define ARRAYOFARRAYS_CHECK_BOUNDS2( i, j )
113 
119 #define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS( i )
120 
127 #define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS2( i, j )
128 
135 #define ARRAYOFARRAYS_CAPACITY_CHECK( i, increase )
136 
144 #define ARRAYOFARRAYS_ATOMIC_CAPACITY_CHECK( i, previousSize, increase )
145 
146 #endif // LVARRAY_BOUNDS_CHECK
147 
148 namespace LvArray
149 {
150 
164 template< typename T,
165  typename INDEX_TYPE,
166  bool CONST_SIZES,
167  template< typename > class BUFFER_TYPE >
169 {
170 protected:
172  using INDEX_TYPE_NC = std::remove_const_t< INDEX_TYPE >;
173 
175  using SIZE_TYPE = std::conditional_t< CONST_SIZES, INDEX_TYPE const, INDEX_TYPE_NC >;
176 
177 public:
178  static_assert( !std::is_const< T >::value || (std::is_const< INDEX_TYPE >::value && CONST_SIZES),
179  "When T is const INDEX_TYPE must also be const and CONST_SIZES must be true" );
180  static_assert( std::is_integral< INDEX_TYPE >::value, "INDEX_TYPE must be integral." );
181 
183  using ValueType = T;
184 
186  using IndexType = INDEX_TYPE;
187 
189  using value_type = T;
190 
192  using size_type = INDEX_TYPE;
193 
197 
203  ArrayOfArraysView() = default;
204 
209  ArrayOfArraysView( ArrayOfArraysView const & ) = default;
210 
215  LVARRAY_HOST_DEVICE constexpr inline
217  m_numArrays( src.m_numArrays ),
218  m_offsets( std::move( src.m_offsets ) ),
219  m_sizes( std::move( src.m_sizes ) ),
220  m_values( std::move( src.m_values ) )
221  { src.m_numArrays = 0; }
222 
230  LVARRAY_HOST_DEVICE constexpr inline
231  ArrayOfArraysView( INDEX_TYPE const numArrays,
232  BUFFER_TYPE< INDEX_TYPE > const & offsets,
233  BUFFER_TYPE< SIZE_TYPE > const & sizes,
234  BUFFER_TYPE< T > const & values ):
235  m_numArrays( numArrays ),
236  m_offsets( offsets ),
237  m_sizes( sizes ),
238  m_values( values )
239  {}
240 
245  inline
246  ArrayOfArraysView & operator=( ArrayOfArraysView const & ) = default;
247 
253  inline
255  {
256  m_numArrays = src.m_numArrays;
257  src.m_numArrays = 0;
258  m_offsets = std::move( src.m_offsets );
259  m_sizes = std::move( src.m_sizes );
260  m_values = std::move( src.m_values );
261  return *this;
262  }
263 
265 
269 
274  LVARRAY_HOST_DEVICE constexpr inline
276  toView() const
277  {
279  this->m_offsets,
280  this->m_sizes,
281  this->m_values );
282  }
283 
287  LVARRAY_HOST_DEVICE constexpr inline
290  {
292  this->m_offsets,
293  this->m_sizes,
294  this->m_values );
295  }
296 
300  LVARRAY_HOST_DEVICE constexpr inline
302  toViewConst() const
303  {
305  this->m_offsets,
306  this->m_sizes,
307  this->m_values );
308  }
309 
311 
315 
320  LVARRAY_HOST_DEVICE constexpr inline
322  { return m_numArrays; }
323 
329  INDEX_TYPE_NC sizeOfArray( INDEX_TYPE const i ) const
330  {
332  return m_sizes[ i ];
333  }
334 
340  {
341  LVARRAY_ASSERT( m_sizes.capacity() < m_offsets.capacity());
342  return m_sizes.capacity();
343  }
344 
350  INDEX_TYPE_NC capacityOfArray( INDEX_TYPE const i ) const
351  {
353  return m_offsets[ i + 1 ] - m_offsets[ i ];
354  }
355 
359  LVARRAY_HOST_DEVICE constexpr inline
361  { return m_values.capacity(); }
362 
364 
368 
376  {
378  return ArraySlice< T, 1, 0, INDEX_TYPE_NC >( m_values.data() + m_offsets[ i ], &m_sizes[ i ], nullptr );
379  }
380 
387  T & operator()( INDEX_TYPE const i, INDEX_TYPE const j ) const
388  {
390  return m_values[m_offsets[ i ] + j];
391  }
392 
394 
398 
408  template< typename ... ARGS >
409  LVARRAY_HOST_DEVICE inline
410  void emplaceBack( INDEX_TYPE const i, ARGS && ... args ) const
411  {
414 
415  T * const ptr = m_values.data() + m_offsets[ i ];
416  arrayManipulation::emplaceBack( ptr, sizeOfArray( i ), std::forward< ARGS >( args ) ... );
417  m_sizes[ i ] += 1;
418  }
419 
429  template< typename POLICY, typename ... ARGS >
430  LVARRAY_HOST_DEVICE inline
431  void emplaceBackAtomic( INDEX_TYPE const i, ARGS && ... args ) const
432  {
434 
435  T * const ptr = m_values.data() + m_offsets[ i ];
436  INDEX_TYPE const previousSize = RAJA::atomicInc< POLICY >( &m_sizes[ i ] );
437  ARRAYOFARRAYS_ATOMIC_CAPACITY_CHECK( i, previousSize, 1 );
438 
439  arrayManipulation::emplaceBack( ptr, previousSize, std::forward< ARGS >( args ) ... );
440  }
441 
451  template< typename ITER >
452  LVARRAY_HOST_DEVICE inline
453  void appendToArray( INDEX_TYPE const i, ITER const first, ITER const last ) const
454  {
456 
457  T * const ptr = m_values.data() + m_offsets[ i ];
458  INDEX_TYPE const n = arrayManipulation::append( ptr, sizeOfArray( i ), first, last );
460  m_sizes[ i ] += n;
461  }
462 
472  template< typename ... ARGS >
473  LVARRAY_HOST_DEVICE inline
474  void emplace( INDEX_TYPE const i, INDEX_TYPE const j, ARGS && ... args ) const
475  {
478 
479  T * const ptr = m_values.data() + m_offsets[ i ];
480  arrayManipulation::emplace( ptr, sizeOfArray( i ), j, std::forward< ARGS >( args )... );
481  m_sizes[ i ]++;
482  }
483 
494  template< typename ITER >
495  LVARRAY_HOST_DEVICE inline
496  void insertIntoArray( INDEX_TYPE const i,
497  INDEX_TYPE const j,
498  ITER const first,
499  ITER const last ) const
500  {
502  INDEX_TYPE const n = arrayManipulation::iterDistance( first, last );
504 
505  T * const ptr = m_values.data() + m_offsets[ i ];
506  arrayManipulation::insert( ptr, sizeOfArray( i ), j, first, n );
507  m_sizes[ i ] += n;
508  }
509 
516  LVARRAY_HOST_DEVICE inline
517  void eraseFromArray( INDEX_TYPE const i, INDEX_TYPE const j, INDEX_TYPE const n=1 ) const
518  {
520 
521  T * const ptr = m_values.data() + m_offsets[ i ];
522  arrayManipulation::erase( ptr, sizeOfArray( i ), j, n );
523  m_sizes[ i ] -= n;
524  }
525 
527 
531 
537  void registerTouch( MemorySpace const space ) const
538  {
539  m_values.registerTouch( space );
540  m_sizes.registerTouch( space );
541  m_offsets.registerTouch( space );
542  }
543 
550  void move( MemorySpace const space, bool touch=true ) const
551  {
552  m_values.move( space, touch );
553  m_sizes.move( space, touch );
554 
555  #if defined(LVARRAY_USE_CUDA)
556  if( space == MemorySpace::GPU ) touch = false;
557  #endif
558  m_offsets.move( space, touch );
559  }
560 
562 
563 protected:
564 
569  template< typename U >
570  using PairOfBuffers = std::pair< BUFFER_TYPE< U > &, BUFFER_TYPE< U > const & >;
571 
577  m_numArrays( 0 ),
578  m_offsets( true ),
579  m_sizes( true ),
580  m_values( true )
581  {}
582 
586 
593  void resize( INDEX_TYPE const newSize, INDEX_TYPE const defaultArrayCapacity=0 )
594  { return resizeImpl( newSize, defaultArrayCapacity ); }
595 
600  void reserve( INDEX_TYPE const newCapacity )
601  {
602  bufferManipulation::reserve( m_offsets, m_numArrays + 1, newCapacity + 1 );
604  }
605 
613  template< class ... BUFFERS >
614  void reserveValues( INDEX_TYPE const newValueCapacity, BUFFERS & ... buffers )
615  {
616  INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ];
617  typeManipulation::forEachArg( [newValueCapacity, maxOffset] ( auto & buffer )
618  {
619  bufferManipulation::reserve( buffer, maxOffset, newValueCapacity );
620  }, m_values, buffers ... );
621  }
622 
630  template< class ... BUFFERS >
631  void compress( BUFFERS & ... buffers )
632  {
633  if( m_numArrays == 0 ) return;
634 
635  for( INDEX_TYPE i = 0; i < m_numArrays - 1; ++i )
636  {
637  INDEX_TYPE const nextOffset = m_offsets[ i + 1 ];
638  INDEX_TYPE const shiftAmount = nextOffset - m_offsets[ i ] - sizeOfArray( i );
639  INDEX_TYPE const sizeOfNextArray = sizeOfArray( i + 1 );
640 
641  // Shift the values in the next array down.
643  [sizeOfNextArray, nextOffset, shiftAmount] ( auto & buffer )
644  {
645  arrayManipulation::uninitializedShiftDown( &buffer[ nextOffset ], sizeOfNextArray, shiftAmount );
646  }, m_values, buffers ... );
647 
648  // And update the offsets.
649  m_offsets[ i + 1 ] -= shiftAmount;
650  }
651 
652  // Update the last offset.
653  m_offsets[ m_numArrays ] = m_offsets[ m_numArrays - 1 ] + sizeOfArray( m_numArrays - 1 );
654  }
655 
665  template< typename POLICY, typename ... BUFFERS >
666  void resizeFromCapacities( INDEX_TYPE const numSubArrays,
667  INDEX_TYPE const * const capacities,
668  BUFFERS & ... buffers )
669  {
671 
672  #ifdef LVARRAY_BOUNDS_CHECK
673  for( INDEX_TYPE i = 0; i < numSubArrays; ++i )
674  {
675  LVARRAY_ERROR_IF_LT( capacities[ i ], 0 );
676  }
677  #endif
678 
679  destroyValues( 0, m_numArrays, buffers ... );
680 
682  std::fill_n( m_sizes.data(), numSubArrays, 0 );
683 
684  INDEX_TYPE const offsetsSize = ( m_numArrays == 0 ) ? 0 : m_numArrays + 1;
685  bufferManipulation::reserve( m_offsets, offsetsSize, numSubArrays + 1 );
686 
687  m_offsets[ 0 ] = 0;
688  // RAJA::inclusive_scan fails on empty input range
689  if( numSubArrays > 0 )
690  {
691  // const_cast needed until for RAJA bug.
692  RAJA::inclusive_scan< POLICY >( const_cast< INDEX_TYPE * >( capacities ),
693  const_cast< INDEX_TYPE * >( capacities + numSubArrays ),
694  m_offsets.data() + 1 );
695  }
696 
697  m_numArrays = numSubArrays;
698  INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ];
699  typeManipulation::forEachArg( [ maxOffset] ( auto & buffer )
700  {
701  bufferManipulation::reserve( buffer, 0, maxOffset );
702  }, m_values, buffers ... );
703  }
704 
706 
710 
717  { *this = std::move( src ); }
718 
725  template< typename ... BUFFERS >
726  void resizeImpl( INDEX_TYPE const newSize, INDEX_TYPE const defaultArrayCapacity, BUFFERS & ... buffers )
727  {
729 
730  INDEX_TYPE const offsetsSize = ( m_numArrays == 0 ) ? 0 : m_numArrays + 1;
731 
732  if( newSize < m_numArrays )
733  {
734  destroyValues( newSize, m_numArrays, buffers ... );
735  bufferManipulation::resize( m_offsets, offsetsSize, newSize + 1, 0 );
737  }
738  else
739  {
740  // The ternary here accounts for the case where m_offsets hasn't been allocated yet (when calling from a
741  // constructor).
742  INDEX_TYPE const originalOffset = (m_numArrays == 0) ? 0 : m_offsets[m_numArrays];
743  bufferManipulation::resize( m_offsets, offsetsSize, newSize + 1, originalOffset );
745 
746  if( defaultArrayCapacity > 0 )
747  {
748  for( INDEX_TYPE i = 1; i < newSize + 1 - m_numArrays; ++i )
749  {
750  m_offsets[ m_numArrays + i ] = originalOffset + i * defaultArrayCapacity;
751  }
752 
753  INDEX_TYPE const totalSize = m_offsets[ newSize ];
754 
755  INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ];
756  typeManipulation::forEachArg( [totalSize, maxOffset]( auto & buffer )
757  {
758  bufferManipulation::reserve( buffer, maxOffset, totalSize );
759  }, m_values, buffers ... );
760  }
761  }
762 
763  m_numArrays = newSize;
764  }
765 
772  template< class ... BUFFERS >
773  void free( BUFFERS & ... buffers )
774  {
775  destroyValues( 0, m_numArrays, buffers ... );
776 
777  typeManipulation::forEachArg( []( auto & buffer )
778  {
779  buffer.free();
780  }, m_sizes, m_offsets, m_values, buffers ... );
781 
782  m_numArrays = 0;
783  }
784 
796  template< class ... PAIRS_OF_BUFFERS >
797  void setEqualTo( INDEX_TYPE const srcNumArrays,
798  INDEX_TYPE const srcMaxOffset,
799  BUFFER_TYPE< INDEX_TYPE > const & srcOffsets,
800  BUFFER_TYPE< INDEX_TYPE > const & srcSizes,
801  BUFFER_TYPE< T > const & srcValues,
802  PAIRS_OF_BUFFERS && ... pairs )
803  {
804  destroyValues( 0, m_numArrays, pairs.first ... );
805 
806  INDEX_TYPE const offsetsSize = ( m_numArrays == 0 ) ? 0 : m_numArrays + 1;
807 
808  bufferManipulation::copyInto( m_offsets, offsetsSize, srcOffsets, srcNumArrays + 1 );
809  bufferManipulation::copyInto( m_sizes, m_numArrays, srcSizes, srcNumArrays );
810 
811  INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ];
812  typeManipulation::forEachArg( [maxOffset, srcMaxOffset]( auto & dstBuffer )
813  {
814  bufferManipulation::reserve( dstBuffer, maxOffset, srcMaxOffset );
815  }, m_values, pairs.first ... );
816 
817  m_numArrays = srcNumArrays;
818 
819  typeManipulation::forEachArg( [this] ( auto & pair )
820  {
821  auto & dstBuffer = pair.first;
822  auto const & srcBuffer = pair.second;
823 
824  for( INDEX_TYPE_NC i = 0; i < m_numArrays; ++i )
825  {
826  INDEX_TYPE const offset = m_offsets[ i ];
827  INDEX_TYPE const arraySize = sizeOfArray( i );
828  arrayManipulation::uninitializedCopy( &srcBuffer[ offset ],
829  &srcBuffer[ offset ] + arraySize,
830  &dstBuffer[ offset ] );
831  }
832  }, PairOfBuffers< T >( m_values, srcValues ), pairs ... );
833  }
834 
843  template< class ... BUFFERS >
844  void setCapacityOfArray( INDEX_TYPE const i, INDEX_TYPE const newCapacity, BUFFERS & ... buffers )
845  {
848 
849  INDEX_TYPE const arrayCapacity = capacityOfArray( i );
850  INDEX_TYPE const capacityIncrease = newCapacity - arrayCapacity;
851  if( capacityIncrease == 0 ) return;
852 
853  if( capacityIncrease > 0 )
854  {
855  INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ];
857  [this, i, maxOffset, capacityIncrease]( auto & buffer )
858  {
859  // Increase the size of the buffer.
860  bufferManipulation::dynamicReserve( buffer, maxOffset, maxOffset + capacityIncrease );
861 
862  // Shift up the values.
863  for( INDEX_TYPE array = m_numArrays - 1; array > i; --array )
864  {
865  INDEX_TYPE const curArraySize = sizeOfArray( array );
866  INDEX_TYPE const curArrayOffset = m_offsets[ array ];
867  arrayManipulation::uninitializedShiftUp( &buffer[ curArrayOffset ], curArraySize, capacityIncrease );
868  }
869  },
870  m_values, buffers ...
871  );
872  }
873  else
874  {
875  INDEX_TYPE const arrayOffset = m_offsets[ i ];
876  INDEX_TYPE const capacityDecrease = -capacityIncrease;
877 
878  INDEX_TYPE const prevArraySize = sizeOfArray( i );
879  INDEX_TYPE const newArraySize = math::min( prevArraySize, newCapacity );
880 
881  m_sizes[ i ] = newArraySize;
883  [this, i, capacityDecrease, arrayOffset, newArraySize, prevArraySize] ( auto & buffer )
884  {
885  // Delete the values at the end of the array.
886  arrayManipulation::destroy( &buffer[ arrayOffset + newArraySize ], prevArraySize - newArraySize );
887 
888  // Shift down the values of subsequent arrays.
889  for( INDEX_TYPE array = i + 1; array < m_numArrays; ++array )
890  {
891  INDEX_TYPE const curArraySize = sizeOfArray( array );
892  INDEX_TYPE const curArrayOffset = m_offsets[array];
893  arrayManipulation::uninitializedShiftDown( &buffer[ curArrayOffset ], curArraySize, capacityDecrease );
894  }
895  },
896  m_values, buffers ...
897  );
898  }
899 
900  // Update the offsets array
901  for( INDEX_TYPE array = i + 1; array < m_numArrays + 1; ++array )
902  {
903  m_offsets[array] += capacityIncrease;
904  }
905 
906  // We need to touch the offsets on the CPU because since it contains const data
907  // when the ArrayOfArraysView gets copy constructed it doesn't get touched even though
908  // it can then be modified via this method when called from a parent non-view class.
909  m_offsets.registerTouch( MemorySpace::CPU );
910  }
911 
917  template< typename U >
918  void setName( std::string const & name )
919  {
920  m_offsets.template setName< U >( name + "/m_offsets" );
921  m_sizes.template setName< U >( name + "/m_sizes" );
922  m_values.template setName< U >( name + "/m_values" );
923  }
924 
926 
929 
932  BUFFER_TYPE< INDEX_TYPE > m_offsets;
933 
935  BUFFER_TYPE< SIZE_TYPE > m_sizes;
936 
939  BUFFER_TYPE< T > m_values;
940 
941 private:
942 
953  template< class ... BUFFERS >
954  void destroyValues( INDEX_TYPE const begin, INDEX_TYPE const end, BUFFERS & ... buffers )
955  {
958 
959  // If the values aren't trivially destructable then the data needs to be moved back to the host.
960  // This moves m_sizes and m_offsets, m_values and buffers are moved inside the loop.
961  if( !typeManipulation::all_of_t< std::is_trivially_destructible< T >,
962  std::is_trivially_destructible< typename BUFFERS::value_type > ... >::value )
963  { move( MemorySpace::CPU, true ); }
964 
965  typeManipulation::forEachArg( [this, begin, end] ( auto & buffer )
966  {
967  if( !std::is_trivially_destructible< std::remove_reference_t< decltype( buffer[ 0 ] ) > >::value )
968  {
969  buffer.move( MemorySpace::CPU, true );
970  for( INDEX_TYPE i = begin; i < end; ++i )
971  {
972  INDEX_TYPE const offset = m_offsets[ i ];
973  INDEX_TYPE const arraySize = sizeOfArray( i );
974  arrayManipulation::destroy( &buffer[ offset ], arraySize );
975  }
976  }
977  }, m_values, buffers ... );
978  }
979 };
980 
981 } /* namespace LvArray */
#define ARRAYOFARRAYS_ATOMIC_CAPACITY_CHECK(i, previousSize, increase)
Check that the capacity of array i isn&#39;t exceeded when the size is increased by increase.
#define LVARRAY_ASSERT(EXP)
Assert EXP is true with no message.
Definition: Macros.hpp:142
constexpr std::iterator_traits< ITER >::difference_type iterDistance(ITER first, ITER const last, std::input_iterator_tag)
constexpr T & operator()(INDEX_TYPE const i, INDEX_TYPE const j) const
void reserve(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
Reserve space in the buffer for at least the given capacity.
void emplace(INDEX_TYPE const i, INDEX_TYPE const j, ARGS &&... args) const
Insert a value into an array.
#define ARRAYOFARRAYS_CHECK_BOUNDS(i)
Check that i is a valid array index.
#define LVARRAY_ERROR_IF_LT(lhs, rhs)
Raise a hard error if one value compares less than the other.
Definition: Macros.hpp:282
void reserve(INDEX_TYPE const newCapacity)
Reserve space for the given number of arrays.
void emplaceBack(INDEX_TYPE const i, ARGS &&... args) const
Append a value to an array.
This class serves to provide a sliced multidimensional interface to the family of LvArray classes...
Definition: ArraySlice.hpp:89
BUFFER_TYPE< INDEX_TYPE > m_offsets
void uninitializedShiftUp(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const amount)
Shift values up into uninitialized memory.
ArrayOfArraysView()=default
A constructor to create an uninitialized ArrayOfArraysView.
constexpr INDEX_TYPE_NC size() const
void dynamicReserve(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
If the buffer&#39;s capacity is greater than newCapacity this is a no-op. Otherwise the buffer&#39;s capacity...
void move(MemorySpace const space, bool touch=true) const
Move this ArrayOfArrays to the given memory space.
Contains templates useful for type manipulation.
ArrayOfArraysView & operator=(ArrayOfArraysView &&src)
Move assignment operator..
void copyInto(DST_BUFFER &dst, std::ptrdiff_t const dstSize, SRC_BUFFER const &src, std::ptrdiff_t const srcSize)
Copy values from the source buffer into the destination buffer.
constexpr INDEX_TYPE_NC capacityOfArray(INDEX_TYPE const i) const
BUFFER_TYPE< SIZE_TYPE > m_sizes
Holds the size of each array.
#define ARRAYOFARRAYS_CHECK_BOUNDS2(i, j)
Check that i is a valid array index and that j is a valid index into that array.
globalIndex const value_type
An alias for the type contained in the inner arrays, here for stl compatability.
void compress(BUFFERS &... buffers)
Compress the arrays so that the values of each array are contiguous with no extra capacity in between...
#define CONSTEXPR_WITHOUT_BOUNDS_CHECK
Expands to constexpr when array bound checking is disabled.
Definition: Macros.hpp:449
constexpr std::enable_if< std::is_signed< INDEX_TYPE >::value, bool >::type isPositive(INDEX_TYPE const i)
void destroy(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destory the values in the array.
void uninitializedCopy(ITER first, ITER const &last, T *LVARRAY_RESTRICT dst)
Copy construct values from the source to the destination.
ArrayOfArraysView & operator=(ArrayOfArraysView const &)=default
Default copy assignment operator.
void resize(INDEX_TYPE const newSize, INDEX_TYPE const defaultArrayCapacity=0)
Set the number of arrays.
Contains the implementation of LvArray::ArraySlice.
constexpr ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, BUFFER_TYPE > toView() const
void setName(std::string const &name)
Set the name to be displayed whenever the underlying Buffer&#39;s user call back is called.
constexpr ArraySlice< T, 1, 0, INDEX_TYPE_NC > operator[](INDEX_TYPE const i) const
This class provides a view into an array of arrays like object.
void emplaceBackAtomic(INDEX_TYPE const i, ARGS &&... args) const
Append a value to an array in a thread safe manner.
#define ARRAYOFARRAYS_CAPACITY_CHECK(i, increase)
Check that the capacity of array i isn&#39;t exceeded when the size is increased by increase.
constexpr ArrayOfArraysView(INDEX_TYPE const numArrays, BUFFER_TYPE< INDEX_TYPE > const &offsets, BUFFER_TYPE< SIZE_TYPE > const &sizes, BUFFER_TYPE< T > const &values)
Construct a new ArrayOfArraysView from the given buffers.
Contains functions for manipulating buffers.
void insertIntoArray(INDEX_TYPE const i, INDEX_TYPE const j, ITER const first, ITER const last) const
Insert values into an array.
Contains some portable math functions.
void resizeImpl(INDEX_TYPE const newSize, INDEX_TYPE const defaultArrayCapacity, BUFFERS &... buffers)
Set the number of arrays.
void emplace(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ARGS &&... args)
Insert into the array constructing the new value in place.
constexpr INDEX_TYPE_NC sizeOfArray(INDEX_TYPE const i) const
void appendToArray(INDEX_TYPE const i, ITER const first, ITER const last) const
Append values to an array.
#define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS(i)
Check that i is a valid index to insert an array at.
CONSTEXPR_WITH_NDEBUG INDEX_TYPE_NC capacity() const
Contains functions for manipulating a contiguous array of values.
constexpr ArrayOfArraysView< T, INDEX_TYPE const, true, BUFFER_TYPE > toViewConstSizes() const
MemorySpace
An enum containing the available memory spaces.
constexpr ArrayOfArraysView(ArrayOfArraysView &&src)
Default move constructor.
The top level namespace.
Definition: Array.hpp:24
std::ptrdiff_t append(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, ITER first, ITER const last)
Append the given values to the array.
void eraseFromArray(INDEX_TYPE const i, INDEX_TYPE const j, INDEX_TYPE const n=1) const
Erase values from an array.
void resizeFromCapacities(INDEX_TYPE const numSubArrays, INDEX_TYPE const *const capacities, BUFFERS &... buffers)
Clears the array and creates a new array with the given number of sub-arrays.
void setEqualTo(INDEX_TYPE const srcNumArrays, INDEX_TYPE const srcMaxOffset, BUFFER_TYPE< INDEX_TYPE > const &srcOffsets, BUFFER_TYPE< INDEX_TYPE > const &srcSizes, BUFFER_TYPE< T > const &srcValues, PAIRS_OF_BUFFERS &&... pairs)
Set this ArrayOfArraysView equal to the provided arrays.
INDEX_TYPE_NC m_numArrays
The number of arrays contained.
ArrayOfArraysView(bool)
Protected constructor to be used by parent classes.
void free(BUFFERS &... buffers)
Destroy all the objects held by this array and free all associated memory.
std::remove_const_t< INDEX_TYPE > INDEX_TYPE_NC
Since INDEX_TYPE should always be const we need an alias for the non const version.
void uninitializedShiftDown(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const amount)
Shift values down into uninitialized memory.
void setCapacityOfArray(INDEX_TYPE const i, INDEX_TYPE const newCapacity, BUFFERS &... buffers)
Set the capacity of the given array.
#define ARRAYOFARRAYS_CHECK_INSERT_BOUNDS2(i, j)
Check that i is a valid array index and that j is a valid insertion index into that array...
void assimilate(ArrayOfArraysView< T, INDEX_TYPE, CONST_SIZES, BUFFER_TYPE > &&src)
Steal the resources of src, clearing it in the process.
void erase(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n=1)
Shift the values in the array at or above the given position down by the given amount overwriting the...
void emplaceBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, ARGS &&... args)
Append the to the array constructing the new value in place.
std::string string
String type.
Definition: DataTypes.hpp:131
std::conditional_t< CONST_SIZES, INDEX_TYPE const, INDEX_TYPE_NC > SIZE_TYPE
The type contained by the m_sizes buffer.
std::pair< BUFFER_TYPE< U > &, BUFFER_TYPE< U > const & > PairOfBuffers
Alias for a std::pair of buffers.
camp::concepts::metalib::all_of_t< TYPES ... > all_of_t
A struct that contains a static constexpr bool value that is true if all of TYPES::value are true...
constexpr std::enable_if_t< std::is_arithmetic< T >::value, T > min(T const a, T const b)
Definition: math.hpp:65
void reserveValues(INDEX_TYPE const newValueCapacity, BUFFERS &... buffers)
Reserve space for the given number of values.
void insert(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ITERATOR first, std::ptrdiff_t const n)
Insert the given values into the array at the given position.
#define CONSTEXPR_WITH_NDEBUG
Expands to constexpr in release builds (when NDEBUG is defined).
Definition: Macros.hpp:466
constexpr INDEX_TYPE_NC valueCapacity() const
void registerTouch(MemorySpace const space) const
Touch the memory in space.
constexpr ArrayOfArraysView< T const, INDEX_TYPE const, true, BUFFER_TYPE > toViewConst() const
constexpr void forEachArg(F &&f)
The recursive base case where no argument is provided.
void resize(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the buffer to the given size.
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389