YAKL
YAKL_FSArray.h
Go to the documentation of this file.
1 
2 #pragma once
3 // Included by YAKL_Array.h
4 
6 namespace yakl {
7 
8  // [S]tatic (compile-time) Array [B]ounds (templated)
9  // It's only used for Fortran, so it takes on Fortran defaults
10  // with lower bound default to 1
18  template <int L, int U=-999> class SB {
19  public:
20  SB() = delete;
21  static constexpr int lower() { return U == -999 ? 1 : L; }
22  static constexpr int upper() { return U == -999 ? L : U; }
23  };
24 
25  /*
26  This is intended to be a simple, low-overhead class to do multi-dimensional arrays
27  without pointer dereferencing. It supports indexing and cout only up to 4-D.
28  */
29 
52  template <class T, int rank, class B0, class B1=SB<1>, class B2=SB<1>, class B3=SB<1>>
53  class FSArray {
54  protected:
56  static int constexpr U0 = B0::upper();
58  static int constexpr L0 = B0::lower();
60  static int constexpr U1 = B1::upper();
62  static int constexpr L1 = B1::lower();
64  static int constexpr U2 = B2::upper();
66  static int constexpr L2 = B2::lower();
68  static int constexpr U3 = B3::upper();
70  static int constexpr L3 = B3::lower();
72  static unsigned constexpr D0 = U0 - L0 + 1;
74  static unsigned constexpr D1 = rank >= 1 ? U1 - L1 + 1 : 1;
76  static unsigned constexpr D2 = rank >= 1 ? U2 - L2 + 1 : 1;
78  static unsigned constexpr D3 = rank >= 1 ? U3 - L3 + 1 : 1;
80  static unsigned constexpr OFF0 = 1;
82  static unsigned constexpr OFF1 = D0;
84  static unsigned constexpr OFF2 = D0*D1;
87  T mutable myData[D0*D1*D2*D3];
88 
89  public :
90  static unsigned constexpr OFF3 = D0*D1*D2;
91 
93  typedef typename std::remove_cv<T>::type type;
95  typedef T value_type;
97  typedef typename std::add_const<type>::type const_value_type;
99  typedef typename std::remove_const<type>::type non_const_value_type;
100 
101  // All copies are deep, so be wary of copies. Use references where possible
103  YAKL_INLINE FSArray(T init_fill) { for (int i=0; i < size(); i++) { myData[i] = init_fill; } }
104  FSArray() = default;
105  ~FSArray() = default;
106 
110  YAKL_INLINE T &operator()(int const i0) const {
111  static_assert(rank==1,"ERROR: Improper number of dimensions specified in operator()");
112  #ifdef YAKL_DEBUG
113  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i0 out of bounds (i0: %d; lb0: %d; ub0: %d",i0,L0,U0); ) } }
114  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { yakl_throw("ERROR: FSArray index out of bounds"); } }
115  #endif
116  return myData[i0-L0];
117  }
121  YAKL_INLINE T &operator()(int const i0, int const i1) const {
122  static_assert(rank==2,"ERROR: Improper number of dimensions specified in operator()");
123  #ifdef YAKL_DEBUG
124  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i0 out of bounds (i0: %d; lb0: %d; ub0: %d",i0,L0,U0); ) } }
125  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i1 out of bounds (i1: %d; lb1: %d; ub1: %d",i1,L1,U1); ) } }
126  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { yakl_throw("ERROR: FSArray index out of bounds"); } }
127  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { yakl_throw("ERROR: FSArray index out of bounds"); } }
128  #endif
129  return myData[(i1-L1)*OFF1 + i0-L0];
130  }
134  YAKL_INLINE T &operator()(int const i0, int const i1, int const i2) const {
135  static_assert(rank==3,"ERROR: Improper number of dimensions specified in operator()");
136  #ifdef YAKL_DEBUG
137  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i0 out of bounds (i0: %d; lb0: %d; ub0: %d",i0,L0,U0); ) } }
138  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i1 out of bounds (i1: %d; lb1: %d; ub1: %d",i1,L1,U1); ) } }
139  if constexpr (rank >= 3) { if (i2<L2 || i2>U2) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i2 out of bounds (i2: %d; lb2: %d; ub2: %d",i2,L2,U2); ) } }
140  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { yakl_throw("ERROR: FSArray index out of bounds"); } }
141  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { yakl_throw("ERROR: FSArray index out of bounds"); } }
142  if constexpr (rank >= 3) { if (i2<L2 || i2>U2) { yakl_throw("ERROR: FSArray index out of bounds"); } }
143  #endif
144  return myData[(i2-L2)*OFF2 + (i1-L1)*OFF1 + i0-L0];
145  }
149  YAKL_INLINE T &operator()(int const i0, int const i1, int const i2, int const i3) const {
150  static_assert(rank==4,"ERROR: Improper number of dimensions specified in operator()");
151  #ifdef YAKL_DEBUG
152  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i0 out of bounds (i0: %d; lb0: %d; ub0: %d",i0,L0,U0); ) } }
153  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i1 out of bounds (i1: %d; lb1: %d; ub1: %d",i1,L1,U1); ) } }
154  if constexpr (rank >= 3) { if (i2<L2 || i2>U2) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i2 out of bounds (i2: %d; lb2: %d; ub2: %d",i2,L2,U2); ) } }
155  if constexpr (rank >= 4) { if (i3<L3 || i3>U3) { YAKL_EXECUTE_ON_HOST_ONLY( printf("FSArray i3 out of bounds (i3: %d; lb3: %d; ub3: %d",i3,L3,U3); ) } }
156  if constexpr (rank >= 1) { if (i0<L0 || i0>U0) { yakl_throw("ERROR: FSArray index out of bounds"); } }
157  if constexpr (rank >= 2) { if (i1<L1 || i1>U1) { yakl_throw("ERROR: FSArray index out of bounds"); } }
158  if constexpr (rank >= 3) { if (i2<L2 || i2>U2) { yakl_throw("ERROR: FSArray index out of bounds"); } }
159  if constexpr (rank >= 4) { if (i3<L3 || i3>U3) { yakl_throw("ERROR: FSArray index out of bounds"); } }
160  #endif
161  return myData[(i3-L3)*OFF3 + (i2-L2)*OFF2 + (i1-L1)*OFF1 + i0-L0];
162  }
163 
164 
166  template <class TLOC , typename std::enable_if<std::is_arithmetic<TLOC>::value,int>::type = 0 >
167  YAKL_INLINE void operator= (TLOC val) { for (int i=0 ; i < totElems() ; i++) { myData[i] = val; } }
168 
169 
171  YAKL_INLINE T *data () const { return myData; }
173  YAKL_INLINE T *get_data() const { return myData; }
175  YAKL_INLINE T *begin() const { return myData; }
177  YAKL_INLINE T *end() const { return begin() + size(); }
179  static unsigned constexpr totElems () { return D3*D2*D1*D0; }
181  static unsigned constexpr get_totElems () { return D3*D2*D1*D0; }
183  static unsigned constexpr get_elem_count() { return D3*D2*D1*D0; }
185  static unsigned constexpr size () { return D3*D2*D1*D0; }
187  static unsigned constexpr get_rank () { return rank; }
189  static bool constexpr span_is_contiguous() { return true; }
191  static bool constexpr initialized() { return true; }
192 
193 
195  inline friend std::ostream &operator<<(std::ostream& os, FSArray const &v) {
196  for (int i=0; i<totElems(); i++) { os << std::setw(12) << v.myData[i] << "\n"; }
197  os << "\n";
198  return os;
199  }
200 
201 
207  if constexpr (rank >= 1) ret(1) = D0;
208  if constexpr (rank >= 2) ret(2) = D1;
209  if constexpr (rank >= 3) ret(3) = D2;
210  if constexpr (rank >= 4) ret(4) = D3;
211  return ret;
212  }
218  if constexpr (rank >= 1) ret(1) = L0;
219  if constexpr (rank >= 2) ret(2) = L1;
220  if constexpr (rank >= 3) ret(3) = L2;
221  if constexpr (rank >= 4) ret(4) = L3;
222  return ret;
223  }
229  if constexpr (rank >= 1) ret(1) = U0;
230  if constexpr (rank >= 2) ret(2) = U1;
231  if constexpr (rank >= 3) ret(3) = U2;
232  if constexpr (rank >= 4) ret(4) = U3;
233  return ret;
234  }
235 
236  };
237 
238 }
240 
241 
yakl::FSArray::non_const_value_type
std::remove_const< type >::type non_const_value_type
This is the type T with const removed from it (if the original type has volatile, then so will this t...
Definition: YAKL_FSArray.h:99
yakl::FSArray::totElems
static constexpr unsigned totElems()
Get the total number of array elements.
Definition: YAKL_FSArray.h:179
yakl::SB::lower
static constexpr int lower()
Definition: YAKL_FSArray.h:21
yakl::FSArray::operator()
YAKL_INLINE T & operator()(int const i0, int const i1, int const i2, int const i3) const
Returns a reference to the indexed element (4-D).
Definition: YAKL_FSArray.h:149
yakl::FSArray::~FSArray
~FSArray()=default
yakl::FSArray::operator<<
friend std::ostream & operator<<(std::ostream &os, FSArray const &v)
Print out the contents of this array. This should be called only from the host.
Definition: YAKL_FSArray.h:195
yakl::FSArray::get_elem_count
static constexpr unsigned get_elem_count()
Get the total number of array elements.
Definition: YAKL_FSArray.h:183
yakl::FSArray::size
static constexpr unsigned size()
Get the total number of array elements.
Definition: YAKL_FSArray.h:185
yakl::FSArray::begin
YAKL_INLINE T * begin() const
Returns pointer to beginning of the data.
Definition: YAKL_FSArray.h:175
yakl::FSArray::operator=
YAKL_INLINE void operator=(TLOC val)
Assign a single arithmetic value to the entire array.
Definition: YAKL_FSArray.h:167
yakl::FSArray::get_data
YAKL_INLINE T * get_data() const
Get the underlying raw data pointer.
Definition: YAKL_FSArray.h:173
__YAKL_NAMESPACE_WRAPPER_END__
#define __YAKL_NAMESPACE_WRAPPER_END__
Definition: YAKL.h:20
yakl::SB::upper
static constexpr int upper()
Definition: YAKL_FSArray.h:22
yakl::SB
This specifies a set of bounds for a dimension when declaring a yakl::FSArray.
Definition: YAKL_FSArray.h:18
__YAKL_NAMESPACE_WRAPPER_BEGIN__
#define __YAKL_NAMESPACE_WRAPPER_BEGIN__
Definition: YAKL.h:19
YAKL_INLINE
#define YAKL_INLINE
Used to decorate functions called from kernels (parallel_for and parallel_outer) or from CPU function...
Definition: YAKL_defines.h:140
yakl::FSArray::get_lbounds
YAKL_INLINE FSArray< int, 1, SB< rank > > get_lbounds() const
Returns the lower bound of each dimension of this array as a yakl::FSArray object.
Definition: YAKL_FSArray.h:216
yakl::FSArray::FSArray
YAKL_INLINE FSArray(T init_fill)
No constructor arguments allowed.
Definition: YAKL_FSArray.h:103
yakl::FSArray::type
std::remove_cv< T >::type type
This is the type T without const and volatile modifiers.
Definition: YAKL_FSArray.h:93
yakl::FSArray::end
YAKL_INLINE T * end() const
Returns pointer to end of the data.
Definition: YAKL_FSArray.h:177
yakl::FSArray::operator()
YAKL_INLINE T & operator()(int const i0, int const i1) const
Returns a reference to the indexed element (2-D).
Definition: YAKL_FSArray.h:121
YAKL_EXECUTE_ON_HOST_ONLY
#define YAKL_EXECUTE_ON_HOST_ONLY(...)
[NOT COMMONLY USED] Macro function used to determine if the current code is compiling for the host.
Definition: YAKL_defines.h:153
yakl::FSArray::operator()
YAKL_INLINE T & operator()(int const i0, int const i1, int const i2) const
Returns a reference to the indexed element (3-D).
Definition: YAKL_FSArray.h:134
yakl::yakl_throw
YAKL_INLINE void yakl_throw(const char *msg)
Throw an error message. Works from the host or device.
Definition: YAKL_error.h:17
yakl::FSArray::span_is_contiguous
static constexpr bool span_is_contiguous()
Always true. All YAKL arrays are contiguous with no padding.
Definition: YAKL_FSArray.h:189
yakl::FSArray::OFF3
static constexpr unsigned OFF3
Definition: YAKL_FSArray.h:90
yakl::FSArray::get_rank
static constexpr unsigned get_rank()
Get the number of dimensions.
Definition: YAKL_FSArray.h:187
yakl::FSArray::get_ubounds
YAKL_INLINE FSArray< int, 1, SB< rank > > get_ubounds() const
Returns the upper bound of each dimension of this array as a yakl::FSArray object.
Definition: YAKL_FSArray.h:227
yakl::FSArray::operator()
YAKL_INLINE T & operator()(int const i0) const
Returns a reference to the indexed element (1-D).
Definition: YAKL_FSArray.h:110
yakl
yakl::FSArray::get_dimensions
YAKL_INLINE FSArray< int, 1, SB< rank > > get_dimensions() const
Returns the dimensions of this array as a yakl::FSArray object.
Definition: YAKL_FSArray.h:205
yakl::SB::SB
SB()=delete
yakl::FSArray::initialized
static constexpr bool initialized()
Always true. yakl::SArray objects are by default always initialized / allocated.
Definition: YAKL_FSArray.h:191
yakl::FSArray::const_value_type
std::add_const< type >::type const_value_type
This is the type T with const added to it (if the original type has volatile, then so will this type)...
Definition: YAKL_FSArray.h:97
yakl::FSArray::data
YAKL_INLINE T * data() const
Get the underlying raw data pointer.
Definition: YAKL_FSArray.h:171
yakl::FSArray::value_type
T value_type
This is the type T exactly as it was defined upon array object creation.
Definition: YAKL_FSArray.h:95
yakl::FSArray::FSArray
FSArray()=default
yakl::FSArray
Fortran-style array on the stack similar in nature to, e.g., float arr[ny][nx];
Definition: YAKL_FSArray.h:53
yakl::FSArray::get_totElems
static constexpr unsigned get_totElems()
Get the total number of array elements.
Definition: YAKL_FSArray.h:181