GEOSX
ArraySlice.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 #if !defined( NDEBUG ) && !defined( __APPLE__ ) && !defined( __ibmxl__ )
16 
21 #define DEFINE_GDB_PY_SCRIPT( script_name ) \
22  asm (".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n \
23  .byte 1 /* Python */\n \
24  .asciz \"" script_name "\"\n \
25  .popsection \n" );
26 #else
27 
31 #define DEFINE_GDB_PY_SCRIPT( script_name )
32 #endif
33 
35 DEFINE_GDB_PY_SCRIPT( "scripts/gdb-printers.py" )
36 
37 // Source includes
38 #include "LvArrayConfig.hpp"
39 #include "indexing.hpp"
40 #include "Macros.hpp"
41 
42 // System includes
43 #ifndef NDEBUG
45  #include "totalview/tv_helpers.hpp"
46 #endif
47 
48 #ifdef LVARRAY_BOUNDS_CHECK
49 
55 #define ARRAY_SLICE_CHECK_BOUNDS( index ) \
56  LVARRAY_ERROR_IF( index < 0 || index >= m_dims[ 0 ], \
57  "Array Bounds Check Failed: index=" << index << " m_dims[0]=" << m_dims[0] )
58 
59 #else // LVARRAY_BOUNDS_CHECK
60 
66 #define ARRAY_SLICE_CHECK_BOUNDS( index )
67 
68 #endif // LVARRAY_BOUNDS_CHECK
69 
70 
71 namespace LvArray
72 {
73 
88 template< typename T, int NDIM_TPARAM, int USD_TPARAM, typename INDEX_TYPE >
90 {
91 public:
92 
93  static_assert( USD_TPARAM < NDIM_TPARAM, "USD must be less than NDIM." );
94 
96  using ValueType = T;
97 
99  static constexpr int NDIM = NDIM_TPARAM;
100 
102  static constexpr int USD = USD_TPARAM;
103 
105  using IndexType = INDEX_TYPE;
106 
110 
113  ArraySlice() = delete;
114 
122  ArraySlice( T * const LVARRAY_RESTRICT inputData,
123  INDEX_TYPE const * const LVARRAY_RESTRICT inputDimensions,
124  INDEX_TYPE const * const LVARRAY_RESTRICT inputStrides ) noexcept:
125  m_data( inputData ),
126  m_dims( inputDimensions ),
127  m_strides( inputStrides )
128  {
129 #if defined(LVARRAY_USE_TOTALVIEW_OUTPUT) && !defined(__CUDA_ARCH__) && defined(LVARRAY_BOUNDS_CHECK)
130  ArraySlice::TV_ttf_display_type( nullptr );
131 #endif
132  }
133 
135 
139 
144  template< typename U=T >
145  LVARRAY_HOST_DEVICE inline constexpr
147  toSliceConst() const noexcept
149 
153  template< typename U=T >
154  LVARRAY_HOST_DEVICE inline constexpr
155  operator std::enable_if_t< !std::is_const< U >::value,
157  () const noexcept
158  { return toSliceConst(); }
159 
161 
165 
170  LVARRAY_HOST_DEVICE inline constexpr
171  INDEX_TYPE size() const noexcept
172  {
173  #if defined( __ibmxl__ )
174  // Note: This used to be done with a recursive template but XL-release would produce incorrect results.
175  // Specifically in exampleArray it would return an "old" size even after being updated, strange.
176  INDEX_TYPE val = m_dims[ 0 ];
177  for( int i = 1; i < NDIM; ++i )
178  { val *= m_dims[ i ]; }
179 
180  return val;
181  #else
182  return indexing::multiplyAll< NDIM >( m_dims );
183  #endif
184  }
185 
191  INDEX_TYPE size( int dim ) const noexcept
192  {
193 #ifdef LVARRAY_BOUNDS_CHECK
194  LVARRAY_ERROR_IF_GE( dim, NDIM );
195 #endif
196  return m_dims[dim];
197  }
198 
204  template< int _USD = USD >
205  LVARRAY_HOST_DEVICE inline constexpr
206  std::enable_if_t< ( _USD >= 0), bool >
207  isContiguous() const
208  {
209  if( NDIM == 1 && USD == 0 ) return true;
210 
211  bool rval = true;
212  for( int i = 0; i < NDIM; ++i )
213  {
214  if( i == USD ) continue;
215  INDEX_TYPE prod = 1;
216  for( int j = 0; j < NDIM; ++j )
217  {
218  if( j != i ) prod *= m_dims[j];
219  }
220  rval &= (m_strides[i] <= prod);
221  }
222  return rval;
223  }
224 
231  template< int USD_ = USD >
232  LVARRAY_HOST_DEVICE inline constexpr
233  std::enable_if_t< (USD_ < 0), bool >
234  isContiguous() const
235  { return false; }
236 
242  template< typename ... INDICES >
244  INDEX_TYPE linearIndex( INDICES... indices ) const
245  {
246  static_assert( sizeof ... (INDICES) == NDIM, "number of indices does not match NDIM" );
247 #ifdef LVARRAY_BOUNDS_CHECK
248  indexing::checkIndices( m_dims, indices ... );
249 #endif
250  return indexing::getLinearIndex< USD >( m_strides, indices ... );
251  }
252 
254 
258 
264  template< int _NDIM=NDIM, int _USD=USD >
265  LVARRAY_HOST_DEVICE constexpr inline
266  operator std::enable_if_t< _NDIM == 1 && _USD == 0, T * const LVARRAY_RESTRICT >
267  () const noexcept
268  { return m_data; }
269 
275  template< int U=NDIM >
277  std::enable_if_t< (U > 1), ArraySlice< T, NDIM - 1, USD - 1, INDEX_TYPE > >
278  operator[]( INDEX_TYPE const index ) const noexcept
279  {
280  ARRAY_SLICE_CHECK_BOUNDS( index );
281  return ArraySlice< T, NDIM-1, USD-1, INDEX_TYPE >( m_data + indexing::ConditionalMultiply< USD == 0 >::multiply( index, m_strides[ 0 ] ),
282  m_dims + 1,
283  m_strides + 1 );
284  }
285 
291  template< int U=NDIM >
293  std::enable_if_t< U == 1, T & >
294  operator[]( INDEX_TYPE const index ) const noexcept
295  {
296  ARRAY_SLICE_CHECK_BOUNDS( index );
298  }
299 
305  template< typename ... INDICES >
306  LVARRAY_HOST_DEVICE inline constexpr
307  T & operator()( INDICES... indices ) const
308  {
309  static_assert( sizeof ... (INDICES) == NDIM, "number of indices does not match NDIM" );
310  return m_data[ linearIndex( indices ... ) ];
311  }
312 
317  LVARRAY_HOST_DEVICE inline
318  T * dataIfContiguous() const
319  {
320  LVARRAY_ERROR_IF( !isContiguous(), "The slice must be contiguous for direct data access" );
321  return m_data;
322  }
323 
328  LVARRAY_HOST_DEVICE inline constexpr
329  T * begin() const
330  { return dataIfContiguous(); }
331 
336  LVARRAY_HOST_DEVICE inline constexpr
337  T * end() const
338  { return dataIfContiguous() + size(); }
339 
341 
342 #if defined(LVARRAY_USE_TOTALVIEW_OUTPUT) && !defined(__CUDA_ARCH__) && defined(LVARRAY_BOUNDS_CHECK)
343 
348  static int TV_ttf_display_type( ArraySlice const * av )
349  {
350  if( av!=nullptr )
351  {
352  int constexpr ndim = NDIM;
353  //std::cout<<"Totalview using ("<<totalview::format<T,INDEX_TYPE>(NDIM, av->m_dims )<<") for display of
354  // m_data;"<<std::endl;
355  TV_ttf_add_row( "tv(m_data)", totalview::format< T, INDEX_TYPE >( NDIM, av->m_dims ).c_str(), (av->m_data) );
356  TV_ttf_add_row( "m_data", totalview::format< T, INDEX_TYPE >( 1, av->m_dims ).c_str(), (av->m_data) );
357  TV_ttf_add_row( "m_dims", totalview::format< INDEX_TYPE, int >( 1, &ndim ).c_str(), (av->m_dims) );
358  TV_ttf_add_row( "m_strides", totalview::format< INDEX_TYPE, int >( 1, &ndim ).c_str(), (av->m_strides) );
359  }
360  return 0;
361  }
362 #endif
363 
364 protected:
366  T * const LVARRAY_RESTRICT m_data;
367 
369  INDEX_TYPE const * const LVARRAY_RESTRICT m_dims;
370 
372  INDEX_TYPE const * const LVARRAY_RESTRICT m_strides;
373 
374 };
375 
376 } // namespace LvArray
INDEX_TYPE IndexType
The integer type used for indexing.
Definition: ArraySlice.hpp:105
constexpr std::enable_if_t< U==1, T &> operator[](INDEX_TYPE const index) const noexcept
Definition: ArraySlice.hpp:294
constexpr ArraySlice< T const, NDIM, USD, INDEX_TYPE > toSliceConst() const noexcept
Definition: ArraySlice.hpp:147
constexpr INDEX_TYPE size(int dim) const noexcept
Definition: ArraySlice.hpp:191
#define LVARRAY_ERROR_IF(EXP, MSG)
Abort execution if EXP is true.
Definition: Macros.hpp:101
constexpr T & operator()(INDICES... indices) const
Definition: ArraySlice.hpp:307
This class serves to provide a sliced multidimensional interface to the family of LvArray classes...
Definition: ArraySlice.hpp:89
constexpr INDEX_TYPE linearIndex(INDICES... indices) const
Definition: ArraySlice.hpp:244
void checkIndices(INDEX_TYPE const *const LVARRAY_RESTRICT dims, INDICES const ... indices)
Check that the indices are with dims , if not the program is aborted.
Definition: indexing.hpp:208
T *const LVARRAY_RESTRICT m_data
pointer to beginning of data for this array, or sub-array.
Definition: ArraySlice.hpp:366
#define ARRAY_SLICE_CHECK_BOUNDS(index)
Point GDB at the scripts/gdb-printers.py.
Definition: ArraySlice.hpp:66
#define CONSTEXPR_WITHOUT_BOUNDS_CHECK
Expands to constexpr when array bound checking is disabled.
Definition: Macros.hpp:449
constexpr std::enable_if_t<(USD_< 0), bool > isContiguous() const
Check if the slice is contiguous in memory.
Definition: ArraySlice.hpp:234
constexpr T * end() const
Definition: ArraySlice.hpp:337
constexpr INDEX_TYPE size() const noexcept
Definition: ArraySlice.hpp:171
constexpr T * begin() const
Definition: ArraySlice.hpp:329
static constexpr auto multiply(A const a, B const b)
Definition: indexing.hpp:47
constexpr ArraySlice(T *const LVARRAY_RESTRICT inputData, INDEX_TYPE const *const LVARRAY_RESTRICT inputDimensions, INDEX_TYPE const *const LVARRAY_RESTRICT inputStrides) noexcept
Construct a new ArraySlice.
Definition: ArraySlice.hpp:122
The top level namespace.
Definition: Array.hpp:24
T ValueType
The type of the value in the ArraySlice.
Definition: ArraySlice.hpp:96
Contains a bunch of macro definitions.
#define LVARRAY_ERROR_IF_GE(lhs, rhs)
Raise a hard error if one value compares greater than or equal to the other.
Definition: Macros.hpp:267
INDEX_TYPE const *const LVARRAY_RESTRICT m_dims
pointer to array of length NDIM that contains the lengths of each array dimension ...
Definition: ArraySlice.hpp:369
constexpr std::enable_if_t<(_USD >=0), bool > isContiguous() const
Check if the slice is contiguous in memory.
Definition: ArraySlice.hpp:207
static constexpr int USD
The unit stride dimension.
Definition: ArraySlice.hpp:102
#define DEFINE_GDB_PY_SCRIPT(script_name)
Add GDB pretty printers the given script.
Definition: ArraySlice.hpp:21
INDEX_TYPE const *const LVARRAY_RESTRICT m_strides
pointer to array of length NDIM that contains the strides of each array dimension ...
Definition: ArraySlice.hpp:372
static constexpr int NDIM
The number of dimensions.
Definition: ArraySlice.hpp:99
ArraySlice()=delete
deleted default constructor
Contains functions to aid in multidimensional indexing.
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389
T * dataIfContiguous() const
Definition: ArraySlice.hpp:318