GEOSX
arrayManipulation.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 #include "Macros.hpp"
16 
17 #ifdef LVARRAY_BOUNDS_CHECK
18 
24 #define ARRAYMANIPULATION_CHECK_BOUNDS( index ) \
25  LVARRAY_ERROR_IF( !isPositive( index ) || index >= size, \
26  "Array Bounds Check Failed: index=" << index << " size()=" << size )
27 
33 #define ARRAYMANIPULATION_CHECK_INSERT_BOUNDS( index ) \
34  LVARRAY_ERROR_IF( !isPositive( index ) || index > size, \
35  "Array Bounds Insert Check Failed: index=" << index << " size()=" << size )
36 
37 #else // LVARRAY_BOUNDS_CHECK
38 
44 #define ARRAYMANIPULATION_CHECK_BOUNDS( index )
45 
51 #define ARRAYMANIPULATION_CHECK_INSERT_BOUNDS( index )
52 
53 #endif // LVARRAY_BOUNDS_CHECK
54 
55 namespace LvArray
56 {
57 
65 namespace arrayManipulation
66 {
67 
73 template< typename INDEX_TYPE >
74 LVARRAY_HOST_DEVICE inline constexpr
75 typename std::enable_if< std::is_signed< INDEX_TYPE >::value, bool >::type
76 isPositive( INDEX_TYPE const i )
77 { return i >= 0; }
78 
83 template< typename INDEX_TYPE >
84 LVARRAY_HOST_DEVICE inline constexpr
85 typename std::enable_if< !std::is_signed< INDEX_TYPE >::value, bool >::type
86 isPositive( INDEX_TYPE )
87 { return true; }
88 
96 template< typename ITER >
97 inline constexpr LVARRAY_HOST_DEVICE
98 typename std::iterator_traits< ITER >::difference_type
99 iterDistance( ITER first, ITER const last, std::input_iterator_tag )
100 {
101  typename std::iterator_traits< ITER >::difference_type n = 0;
102  while( first != last )
103  {
104  ++first;
105  ++n;
106  }
107 
108  return n;
109 }
110 
118 template< typename RandomAccessIterator >
119 inline constexpr LVARRAY_HOST_DEVICE
120 typename std::iterator_traits< RandomAccessIterator >::difference_type
121 iterDistance( RandomAccessIterator first, RandomAccessIterator last, std::random_access_iterator_tag )
122 { return last - first; }
123 
131 template< typename ITER >
132 inline constexpr LVARRAY_HOST_DEVICE
133 typename std::iterator_traits< ITER >::difference_type
134 iterDistance( ITER const first, ITER const last )
135 { return iterDistance( first, last, typename std::iterator_traits< ITER >::iterator_category() ); }
136 
144 template< typename T >
145 LVARRAY_HOST_DEVICE inline
146 void destroy( T * const LVARRAY_RESTRICT ptr,
147  std::ptrdiff_t const size )
148 {
149  LVARRAY_ASSERT( ptr != nullptr || size == 0 );
150 
151  for( std::ptrdiff_t i = 0; i < size; ++i )
152  {
153  ptr[ i ].~T();
154  }
155 }
156 
166 template< typename ITER, typename T >
167 LVARRAY_HOST_DEVICE inline
168 void uninitializedCopy( ITER first,
169  ITER const & last,
170  T * LVARRAY_RESTRICT dst )
171 {
172  LVARRAY_ASSERT( dst != nullptr || first == last );
173 
174  while( first != last )
175  {
176  new ( dst ) T( *first );
177  ++dst;
178  ++first;
179  }
180 }
181 
190 template< typename T >
191 LVARRAY_HOST_DEVICE inline
192 void uninitializedMove( T * const LVARRAY_RESTRICT dst,
193  std::ptrdiff_t const size,
194  T * const LVARRAY_RESTRICT src )
195 {
196  LVARRAY_ASSERT( dst != nullptr || size == 0 );
197  LVARRAY_ASSERT( isPositive( size ) );
198  LVARRAY_ASSERT( src != nullptr || size == 0 );
199 
200  for( std::ptrdiff_t i = 0; i < size; ++i )
201  {
202  new (dst + i) T( std::move( src[ i ] ) );
203  }
204 }
205 
214 template< typename T >
215 LVARRAY_HOST_DEVICE inline
216 void uninitializedShiftDown( T * const LVARRAY_RESTRICT ptr,
217  std::ptrdiff_t const size,
218  std::ptrdiff_t const amount )
219 {
220  LVARRAY_ASSERT( ptr != nullptr || size == 0 );
221  LVARRAY_ASSERT( isPositive( size ) );
222  LVARRAY_ASSERT( isPositive( amount ) );
223 
224  if( amount == 0 )
225  return;
226 
227  for( std::ptrdiff_t j = 0; j < size; ++j )
228  {
229  new ( ptr + j - amount ) T( std::move( ptr[ j ] ) );
230  ptr[ j ].~T();
231  }
232 }
233 
242 template< typename T >
243 LVARRAY_HOST_DEVICE inline
244 void uninitializedShiftUp( T * const LVARRAY_RESTRICT ptr,
245  std::ptrdiff_t const size,
246  std::ptrdiff_t const amount )
247 {
248  LVARRAY_ASSERT( ptr != nullptr || size == 0 );
249  LVARRAY_ASSERT( isPositive( size ) );
250  LVARRAY_ASSERT( isPositive( amount ) );
251 
252  if( amount == 0 )
253  return;
254 
255  for( std::ptrdiff_t j = size - 1; j >= 0; --j )
256  {
257  new ( ptr + amount + j ) T( std::move( ptr[ j ] ) );
258  ptr[ j ].~T();
259  }
260 }
261 
272 template< typename T, typename ... ARGS >
273 LVARRAY_HOST_DEVICE inline
274 void resize( T * const LVARRAY_RESTRICT ptr,
275  std::ptrdiff_t const size,
276  std::ptrdiff_t const newSize,
277  ARGS && ... args )
278 {
279  LVARRAY_ASSERT( ptr != nullptr || (size == 0 && newSize == 0) );
280  LVARRAY_ASSERT( isPositive( size ) );
281  LVARRAY_ASSERT( isPositive( newSize ) );
282 
283  // Delete things between newSize and size.
284  destroy( ptr + newSize, size - newSize );
285 
286  // Initialize things between size and newSize.
287  for( std::ptrdiff_t i = size; i < newSize; ++i )
288  {
289  new ( ptr + i ) T( std::forward< ARGS >( args )... );
290  }
291 }
292 
303 template< typename T >
304 LVARRAY_HOST_DEVICE inline
305 void shiftUp( T * const LVARRAY_RESTRICT ptr,
306  std::ptrdiff_t const size,
307  std::ptrdiff_t const index,
308  std::ptrdiff_t const n )
309 {
310  LVARRAY_ASSERT( ptr != nullptr || (size == 0 && n == 0) );
311  LVARRAY_ASSERT( isPositive( size ) );
312  LVARRAY_ASSERT( isPositive( n ) );
314 
315  if( n == 0 )
316  return;
317 
318  // Move the existing values up by n.
319  for( std::ptrdiff_t i = size; i > index; --i )
320  {
321  std::ptrdiff_t const curIndex = i - 1;
322  new ( ptr + curIndex + n ) T( std::move( ptr[ curIndex ] ) );
323  }
324 
325  // Delete the values moved out of.
326  std::ptrdiff_t const bounds = (index + n < size) ? index + n : size;
327  destroy( ptr + index, bounds - index );
328 }
329 
340 template< typename T >
341 LVARRAY_HOST_DEVICE inline
342 void shiftDown( T * const LVARRAY_RESTRICT ptr,
343  std::ptrdiff_t const size,
344  std::ptrdiff_t const index,
345  std::ptrdiff_t const n )
346 {
348  LVARRAY_ASSERT( ptr != nullptr || (size == 0 && n == 0) );
349  LVARRAY_ASSERT( isPositive( size ) );
350  LVARRAY_ASSERT( isPositive( n ) );
351  LVARRAY_ASSERT( index >= n );
352 
353  if( n == 0 )
354  return;
355 
356  // Move the existing down by n.
357  for( std::ptrdiff_t i = index; i < size; ++i )
358  {
359  ptr[i - n] = std::move( ptr[i] );
360  }
361 }
362 
373 template< typename T >
374 LVARRAY_HOST_DEVICE inline
375 void erase( T * const LVARRAY_RESTRICT ptr,
376  std::ptrdiff_t const size,
377  std::ptrdiff_t const index,
378  std::ptrdiff_t const n=1 )
379 {
380  LVARRAY_ASSERT( isPositive( n ) );
381  if( n == 0 )
382  return;
383 
385  ARRAYMANIPULATION_CHECK_BOUNDS( index + n - 1 );
386 
387  shiftDown( ptr, size, std::ptrdiff_t( index + n ), n );
388 
389  // Delete the values that were moved out of at the end of the array.
390  destroy( ptr + size - n, n );
391 }
392 
402 template< typename T, typename ... ARGS >
403 LVARRAY_HOST_DEVICE inline
404 void emplaceBack( T * const LVARRAY_RESTRICT ptr,
405  std::ptrdiff_t const size,
406  ARGS && ... args )
407 {
408  LVARRAY_ASSERT( ptr != nullptr );
409  LVARRAY_ASSERT( isPositive( size ) );
410  new ( ptr + size ) T( std::forward< ARGS >( args ) ... );
411 }
412 
424 template< typename T, typename ITER >
425 LVARRAY_HOST_DEVICE inline
426 std::ptrdiff_t append( T * const LVARRAY_RESTRICT ptr,
427  std::ptrdiff_t const size,
428  ITER first,
429  ITER const last )
430 {
431  LVARRAY_ASSERT( ptr != nullptr || (size == 0 && first == last) );
432  LVARRAY_ASSERT( isPositive( size ) );
433 
434  std::ptrdiff_t i = 0;
435  while( first != last )
436  {
437  new( ptr + size + i ) T( *first );
438  ++first;
439  ++i;
440  }
441 
442  return i;
443 }
444 
455 template< typename T, typename ... ARGS >
456 LVARRAY_HOST_DEVICE inline
457 void emplace( T * const LVARRAY_RESTRICT ptr,
458  std::ptrdiff_t const size,
459  std::ptrdiff_t const index,
460  ARGS && ... args )
461 {
462  LVARRAY_ASSERT( ptr != nullptr );
463  LVARRAY_ASSERT( isPositive( size ) );
465 
466  // Create space for the new value.
467  shiftUp( ptr, size, index, std::ptrdiff_t( 1 ) );
468  new ( ptr + index ) T( std::forward< ARGS >( args ) ... );
469 }
470 
482 template< typename T, typename ITERATOR >
483 LVARRAY_HOST_DEVICE inline
484 void insert( T * const LVARRAY_RESTRICT ptr,
485  std::ptrdiff_t const size,
486  std::ptrdiff_t const index,
487  ITERATOR first,
488  std::ptrdiff_t const n )
489 {
490  LVARRAY_ASSERT( ptr != nullptr );
491  LVARRAY_ASSERT( isPositive( size ) );
493 
494  shiftUp( ptr, size, index, n );
495 
496  for( std::ptrdiff_t i = 0; i < n; ++i )
497  {
498  new ( ptr + index + i ) T( *first );
499  ++first;
500  }
501 }
502 
510 template< typename T >
511 LVARRAY_HOST_DEVICE inline
512 void popBack( T * const LVARRAY_RESTRICT ptr,
513  std::ptrdiff_t const size )
514 {
515  LVARRAY_ASSERT( ptr != nullptr );
516  LVARRAY_ASSERT( size > 0 );
517  ptr[ size - 1 ].~T();
518 }
519 
520 } // namespace arrayManipulation
521 } // namespace LvArray
#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)
void uninitializedShiftUp(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const amount)
Shift values up into uninitialized memory.
void uninitializedMove(T *const LVARRAY_RESTRICT dst, std::ptrdiff_t const size, T *const LVARRAY_RESTRICT src)
Move construct values from the source to the destination.
void shiftUp(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n)
Shift the values in the array at or above the given position up by the given amount. New uninitialized values take their place.
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.
#define ARRAYMANIPULATION_CHECK_BOUNDS(index)
Check that index is a valid into into the array.
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.
void popBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destroy the value at the end of the array.
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 resize(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the give array.
Contains a bunch of macro definitions.
void uninitializedShiftDown(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const amount)
Shift values down into uninitialized memory.
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.
void shiftDown(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n)
Shift the values in the array at or above the given position down by the given amount overwriting the...
#define DISABLE_HD_WARNING
Disable host device warnings.
Definition: Macros.hpp:401
#define ARRAYMANIPULATION_CHECK_INSERT_BOUNDS(index)
Check that index is a valid insertion position in the array.
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 LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389