19 #include <type_traits> 21 #include "atlas/array/ArrayUtil.h" 22 #include "atlas/array/ArrayViewDefs.h" 23 #include "atlas/array/helpers/ArraySlicer.h" 24 #include "atlas/library/config.h" 65 template <
typename Value,
int Rank>
68 using is_non_const_value_type =
typename std::is_same<T, typename std::remove_const<Value>::type>;
70 #define ENABLE_IF_NON_CONST \ 71 template <bool EnableBool = true, \ 72 typename std::enable_if<( !std::is_const<Value>::value && EnableBool ), int>::type* = nullptr> 74 #define ENABLE_IF_CONST_WITH_NON_CONST( T ) \ 75 template <typename T, \ 76 typename std::enable_if<( std::is_const<Value>::value && is_non_const_value_type<T>::value ), \ 77 int>::type* = nullptr> 82 using value_type = Value;
83 using return_type = value_type;
85 static constexpr
int RANK{Rank};
88 using slicer_t =
typename helpers::ArraySlicer<LocalView<Value, Rank>>;
89 using const_slicer_t =
typename helpers::ArraySlicer<const LocalView<const Value, Rank>>;
91 template <
typename... Args>
93 using type =
typename slicer_t::template
Slice<Args...>::type;
96 template <
typename... Args>
97 struct const_slice_t {
98 using type =
typename const_slicer_t::template
Slice<Args...>::type;
104 ENABLE_IF_CONST_WITH_NON_CONST( value_type )
105 LocalView( value_type* data,
const idx_t shape[],
const idx_t strides[] ) : data_( data ) {
107 for (
idx_t j = 0; j < Rank; ++j ) {
108 shape_[j] = shape[j];
109 strides_[j] = strides[j];
114 LocalView( value_type* data,
const idx_t shape[],
const idx_t strides[] ) : data_( data ) {
116 for (
idx_t j = 0; j < Rank; ++j ) {
117 shape_[j] = shape[j];
118 strides_[j] = strides[j];
124 ENABLE_IF_CONST_WITH_NON_CONST( value_type )
125 LocalView( value_type* data,
const idx_t shape[] ) : data_( data ) {
127 for (
int j = Rank - 1; j >= 0; --j ) {
128 shape_[j] = shape[j];
134 LocalView( value_type* data,
const idx_t shape[] ) : data_( data ) {
136 for (
int j = Rank - 1; j >= 0; --j ) {
137 shape_[j] = shape[j];
144 template <typename value_type, typename = typename std::enable_if<std::is_const<Value>::value &&
145 !std::is_const<value_type>::value>::type>
146 LocalView( value_type* data,
const ArrayShape& shape ) : data_( data ) {
148 for (
int j = Rank - 1; j >= 0; --j ) {
149 shape_[j] = shape[j];
155 LocalView( value_type* data,
const ArrayShape& shape ) : data_( data ) {
157 for (
int j = Rank - 1; j >= 0; --j ) {
158 shape_[j] = shape[j];
164 ENABLE_IF_CONST_WITH_NON_CONST( value_type )
165 operator const LocalView<value_type, Rank>&()
const {
166 static_assert( std::is_const<Value>::value,
"must be const" );
167 static_assert( !std::is_const<value_type>::value,
"must be non-const" );
168 return (
const LocalView<value_type, Rank>&)( *this );
173 template <
typename... Ints>
174 value_type& operator()( Ints... idx ) {
175 check_bounds( idx... );
176 return data_[index( idx... )];
179 template <
typename... Ints>
180 const value_type& operator()( Ints... idx )
const {
181 check_bounds( idx... );
182 return data_[index( idx... )];
185 template <
typename Int,
bool EnableBool = true>
186 typename std::enable_if<( Rank == 1 && EnableBool ), const value_type&>::type operator[]( Int idx )
const {
191 template <
typename Int,
bool EnableBool = true>
192 typename std::enable_if<( Rank == 1 && EnableBool ), value_type&>::type operator[]( Int idx ) {
197 idx_t size()
const {
return size_; }
199 template <
typename Int>
200 idx_t shape( Int idx )
const {
204 template <
typename Int>
205 idx_t stride( Int idx )
const {
206 return strides_[idx];
209 const idx_t* shape()
const {
return shape_; }
211 const idx_t* strides()
const {
return strides_; }
213 value_type
const* data()
const {
return data_; }
215 value_type* data() {
return data_; }
217 bool contiguous()
const {
return ( size_ == shape_[0] * strides_[0] ?
true :
false ); }
220 void assign(
const value_type& value );
222 void dump( std::ostream& os )
const;
224 static constexpr
idx_t rank() {
return Rank; }
226 template <
typename... Args>
227 typename slice_t<Args...>::type slice( Args... args ) {
228 return slicer_t( *this ).apply( args... );
231 template <
typename... Args>
232 typename const_slice_t<Args...>::type slice( Args... args )
const {
233 return const_slicer_t( *this ).apply( args... );
236 friend std::ostream& operator<<( std::ostream& out,
const LocalView& x ) {
244 template <
int Dim,
typename Int,
typename... Ints>
245 constexpr
idx_t index_part( Int idx, Ints... next_idx )
const {
246 return idx * strides_[Dim] + index_part<Dim + 1>( next_idx... );
249 template <
int Dim,
typename Int>
250 constexpr
idx_t index_part( Int last_idx )
const {
251 return last_idx * strides_[Dim];
254 template <
typename... Ints>
255 constexpr
idx_t index( Ints... idx )
const {
256 return index_part<0>( idx... );
259 #if ATLAS_ARRAYVIEW_BOUNDS_CHECKING 260 template <
typename... Ints>
261 void check_bounds( Ints... idx )
const {
262 static_assert(
sizeof...( idx ) == Rank,
"Expected number of indices is different from rank of array" );
263 return check_bounds_part<0>( idx... );
266 template <
typename... Ints>
267 void check_bounds( Ints... )
const {}
270 template <
typename... Ints>
271 void check_bounds_force( Ints... idx )
const {
272 static_assert(
sizeof...( idx ) == Rank,
"Expected number of indices is different from rank of array" );
273 return check_bounds_part<0>( idx... );
276 template <
int Dim,
typename Int,
typename... Ints>
277 void check_bounds_part( Int idx, Ints... next_idx )
const {
278 if (
idx_t( idx ) >= shape_[Dim] ) {
279 throw_OutOfRange(
"LocalView", array_dim<Dim>(), idx, shape_[Dim] );
281 check_bounds_part<Dim + 1>( next_idx... );
284 template <
int Dim,
typename Int>
285 void check_bounds_part( Int last_idx )
const {
286 if (
idx_t( last_idx ) >= shape_[Dim] ) {
287 throw_OutOfRange(
"LocalView", array_dim<Dim>(), last_idx, shape_[Dim] );
297 idx_t strides_[Rank];
299 #undef ENABLE_IF_NON_CONST 300 #undef ENABLE_IF_CONST_WITH_NON_CONST Definition: test_array_slicer.cc:22
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42