LvArray
ArraySlice.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021, 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(LVARRAY_DEVICE_COMPILE) && defined(LVARRAY_BOUNDS_CHECK)
130  ArraySlice::TV_ttf_display_type( nullptr );
131 #endif
132  }
133 
135 
139 
144  LVARRAY_HOST_DEVICE inline constexpr
146  toSliceConst() const noexcept
148 
152  template< typename U=T >
153  LVARRAY_HOST_DEVICE inline constexpr
154  operator std::enable_if_t< !std::is_const< U >::value,
156  () const noexcept
157  { return toSliceConst(); }
158 
160 
164 
169  LVARRAY_HOST_DEVICE inline constexpr
170  INDEX_TYPE size() const noexcept
171  {
172  #if defined( __ibmxl__ )
173  // Note: This used to be done with a recursive template but XL-release would produce incorrect results.
174  // Specifically in exampleArray it would return an "old" size even after being updated, strange.
175  INDEX_TYPE val = m_dims[ 0 ];
176  for( int i = 1; i < NDIM; ++i )
177  { val *= m_dims[ i ]; }
178 
179  return val;
180  #else
181  return indexing::multiplyAll< NDIM >( m_dims );
182  #endif
183  }
184 
190  INDEX_TYPE size( int const dim ) const noexcept
191  {
192 #ifdef LVARRAY_BOUNDS_CHECK
193  LVARRAY_ERROR_IF_GE( dim, NDIM );
194 #endif
195  return m_dims[ dim ];
196  }
197 
203  INDEX_TYPE stride( int const dim ) const noexcept
204  {
205 #ifdef LVARRAY_BOUNDS_CHECK
206  LVARRAY_ERROR_IF_GE( dim, NDIM );
207 #endif
208  return m_strides[ dim ];
209  }
210 
215  LVARRAY_HOST_DEVICE inline constexpr
216  bool isContiguous() const
217  {
218  if( USD < 0 ) return false;
219  if( NDIM == 1 && USD == 0 ) return true;
220 
221  bool rval = true;
222  for( int i = 0; i < NDIM; ++i )
223  {
224  if( i == USD ) continue;
225  INDEX_TYPE prod = 1;
226  for( int j = 0; j < NDIM; ++j )
227  {
228  if( j != i ) prod *= m_dims[j];
229  }
230  rval &= (m_strides[i] <= prod);
231  }
232  return rval;
233  }
234 
240  template< typename ... INDICES >
242  INDEX_TYPE linearIndex( INDICES... indices ) const
243  {
244  static_assert( sizeof ... (INDICES) == NDIM, "number of indices does not match NDIM" );
245 #ifdef LVARRAY_BOUNDS_CHECK
246  indexing::checkIndices( m_dims, indices ... );
247 #endif
248  return indexing::getLinearIndex< USD >( m_strides, indices ... );
249  }
250 
252 
256 
262  template< int NDIM_=NDIM, int USD_=USD >
263  LVARRAY_HOST_DEVICE constexpr inline
264  operator std::enable_if_t< NDIM_ == 1 && USD_ == 0, T * const LVARRAY_RESTRICT >
265  () const noexcept
266  { return m_data; }
267 
273  template< int U=NDIM >
275  std::enable_if_t< (U > 1), ArraySlice< T, NDIM - 1, USD - 1, INDEX_TYPE > >
276  operator[]( INDEX_TYPE const index ) const noexcept
277  {
278  ARRAY_SLICE_CHECK_BOUNDS( index );
279  return ArraySlice< T, NDIM-1, USD-1, INDEX_TYPE >( m_data + indexing::ConditionalMultiply< USD == 0 >::multiply( index, m_strides[ 0 ] ),
280  m_dims + 1,
281  m_strides + 1 );
282  }
283 
289  template< int U=NDIM >
291  std::enable_if_t< U == 1, T & >
292  operator[]( INDEX_TYPE const index ) const noexcept
293  {
294  ARRAY_SLICE_CHECK_BOUNDS( index );
296  }
297 
303  template< typename ... INDICES >
304  LVARRAY_HOST_DEVICE inline constexpr
305  T & operator()( INDICES... indices ) const
306  {
307  static_assert( sizeof ... (INDICES) == NDIM, "number of indices does not match NDIM" );
308  return m_data[ linearIndex( indices ... ) ];
309  }
310 
316  template< int USD_ = USD >
317  LVARRAY_HOST_DEVICE inline
318  T * dataIfContiguous() const
319  {
320  // Note: need both compile-time and runtime checks as USD >= 0 does not guarantee contiguous data.
321  static_assert( USD_ >= 0, "Direct data access not supported for non-contiguous slices" );
322  LVARRAY_ERROR_IF( !isContiguous(), "Direct data access not supported for non-contiguous slices" );
323  return m_data;
324  }
325 
330  LVARRAY_HOST_DEVICE inline constexpr
331  T * begin() const
332  { return dataIfContiguous(); }
333 
338  LVARRAY_HOST_DEVICE inline constexpr
339  T * end() const
340  { return dataIfContiguous() + size(); }
341 
343 
344 #if defined(LVARRAY_USE_TOTALVIEW_OUTPUT) && !defined(LVARRAY_DEVICE_COMPILE) && defined(LVARRAY_BOUNDS_CHECK)
345 
350  static int TV_ttf_display_type( ArraySlice const * av )
351  {
352  if( av!=nullptr )
353  {
354  int constexpr ndim = NDIM;
355  //std::cout<<"Totalview using ("<<totalview::format<T,INDEX_TYPE>(NDIM, av->m_dims )<<") for display of
356  // m_data;"<<std::endl;
357  TV_ttf_add_row( "tv(m_data)", totalview::format< T, INDEX_TYPE >( NDIM, av->m_dims ).c_str(), (av->m_data) );
358  TV_ttf_add_row( "m_data", totalview::format< T, INDEX_TYPE >( 1, av->m_dims ).c_str(), (av->m_data) );
359  TV_ttf_add_row( "m_dims", totalview::format< INDEX_TYPE, int >( 1, &ndim ).c_str(), (av->m_dims) );
360  TV_ttf_add_row( "m_strides", totalview::format< INDEX_TYPE, int >( 1, &ndim ).c_str(), (av->m_strides) );
361  }
362  return 0;
363  }
364 #endif
365 
366 protected:
368  T * const LVARRAY_RESTRICT m_data;
369 
371  INDEX_TYPE const * const LVARRAY_RESTRICT m_dims;
372 
374  INDEX_TYPE const * const LVARRAY_RESTRICT m_strides;
375 
376 };
377 
378 } // namespace LvArray
INDEX_TYPE IndexType
The integer type used for indexing.
Definition: ArraySlice.hpp:105
LVARRAY_HOST_DEVICE T * dataIfContiguous() const
Definition: ArraySlice.hpp:318
#define LVARRAY_ERROR_IF(EXP, MSG)
Abort execution if EXP is true.
Definition: Macros.hpp:155
This class serves to provide a sliced multidimensional interface to the family of LvArray classes...
Definition: ArraySlice.hpp:89
LVARRAY_HOST_DEVICE constexpr INDEX_TYPE size() const noexcept
Definition: ArraySlice.hpp:170
LVARRAY_HOST_DEVICE constexpr T * begin() const
Definition: ArraySlice.hpp:331
T *const LVARRAY_RESTRICT m_data
pointer to beginning of data for this array, or sub-array.
Definition: ArraySlice.hpp:368
#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:662
LVARRAY_HOST_DEVICE constexpr bool isContiguous() const
Check if the slice is contiguous in memory.
Definition: ArraySlice.hpp:216
LVARRAY_HOST_DEVICE constexpr ArraySlice< T const, NDIM, USD, INDEX_TYPE > toSliceConst() const noexcept
Definition: ArraySlice.hpp:146
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK INDEX_TYPE linearIndex(INDICES... indices) const
Definition: ArraySlice.hpp:242
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK INDEX_TYPE stride(int const dim) const noexcept
Definition: ArraySlice.hpp:203
static LVARRAY_HOST_DEVICE constexpr auto multiply(A const a, B const b)
Definition: indexing.hpp:47
LVARRAY_HOST_DEVICE 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
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:424
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK std::enable_if_t< U==1, T &> operator[](INDEX_TYPE const index) const noexcept
Definition: ArraySlice.hpp:292
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:371
LVARRAY_HOST_DEVICE constexpr T & operator()(INDICES... indices) const
Definition: ArraySlice.hpp:305
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:374
static constexpr int NDIM
The number of dimensions.
Definition: ArraySlice.hpp:99
LVARRAY_HOST_DEVICE constexpr T * end() const
Definition: ArraySlice.hpp:339
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK 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
ArraySlice()=delete
deleted default constructor
Contains functions to aid in multidimensional indexing.
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK INDEX_TYPE size(int const dim) const noexcept
Definition: ArraySlice.hpp:190
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:600