atlas
LocalView.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2013 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation
8  * nor does it submit to any jurisdiction.
9  */
10 
15 
16 #pragma once
17 
18 #include <cstddef>
19 #include <type_traits>
20 
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"
25 
26 //------------------------------------------------------------------------------------------------------
27 
28 namespace atlas {
29 namespace array {
30 
63 
64 
65 template <typename Value, int Rank>
66 class LocalView {
67  template <typename T>
68  using is_non_const_value_type = typename std::is_same<T, typename std::remove_const<Value>::type>;
69 
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>
73 
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>
78 
79 
80 public:
81  // -- Type definitions
82  using value_type = Value;
83  using return_type = value_type;
84 
85  static constexpr int RANK{Rank};
86 
87 private:
88  using slicer_t = typename helpers::ArraySlicer<LocalView<Value, Rank>>;
89  using const_slicer_t = typename helpers::ArraySlicer<const LocalView<const Value, Rank>>;
90 
91  template <typename... Args>
92  struct slice_t {
93  using type = typename slicer_t::template Slice<Args...>::type;
94  };
95 
96  template <typename... Args>
97  struct const_slice_t {
98  using type = typename const_slicer_t::template Slice<Args...>::type;
99  };
100 
101 public:
102  // -- Constructors
103 
104  ENABLE_IF_CONST_WITH_NON_CONST( value_type )
105  LocalView( value_type* data, const idx_t shape[], const idx_t strides[] ) : data_( data ) {
106  size_ = 1;
107  for ( idx_t j = 0; j < Rank; ++j ) {
108  shape_[j] = shape[j];
109  strides_[j] = strides[j];
110  size_ *= shape_[j];
111  }
112  }
113 
114  LocalView( value_type* data, const idx_t shape[], const idx_t strides[] ) : data_( data ) {
115  size_ = 1;
116  for ( idx_t j = 0; j < Rank; ++j ) {
117  shape_[j] = shape[j];
118  strides_[j] = strides[j];
119  size_ *= shape_[j];
120  }
121  }
122 
123 
124  ENABLE_IF_CONST_WITH_NON_CONST( value_type )
125  LocalView( value_type* data, const idx_t shape[] ) : data_( data ) {
126  size_ = 1;
127  for ( int j = Rank - 1; j >= 0; --j ) {
128  shape_[j] = shape[j];
129  strides_[j] = size_;
130  size_ *= shape_[j];
131  }
132  }
133 
134  LocalView( value_type* data, const idx_t shape[] ) : data_( data ) {
135  size_ = 1;
136  for ( int j = Rank - 1; j >= 0; --j ) {
137  shape_[j] = shape[j];
138  strides_[j] = size_;
139  size_ *= shape_[j];
140  }
141  }
142 
143 
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 ) {
147  size_ = 1;
148  for ( int j = Rank - 1; j >= 0; --j ) {
149  shape_[j] = shape[j];
150  strides_[j] = size_;
151  size_ *= shape_[j];
152  }
153  }
154 
155  LocalView( value_type* data, const ArrayShape& shape ) : data_( data ) {
156  size_ = 1;
157  for ( int j = Rank - 1; j >= 0; --j ) {
158  shape_[j] = shape[j];
159  strides_[j] = size_;
160  size_ *= shape_[j];
161  }
162  }
163 
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 );
169  }
170 
171  // -- Access methods
172 
173  template <typename... Ints>
174  value_type& operator()( Ints... idx ) {
175  check_bounds( idx... );
176  return data_[index( idx... )];
177  }
178 
179  template <typename... Ints>
180  const value_type& operator()( Ints... idx ) const {
181  check_bounds( idx... );
182  return data_[index( idx... )];
183  }
184 
185  template <typename Int, bool EnableBool = true>
186  typename std::enable_if<( Rank == 1 && EnableBool ), const value_type&>::type operator[]( Int idx ) const {
187  check_bounds( idx );
188  return data_[idx];
189  }
190 
191  template <typename Int, bool EnableBool = true>
192  typename std::enable_if<( Rank == 1 && EnableBool ), value_type&>::type operator[]( Int idx ) {
193  check_bounds( idx );
194  return data_[idx];
195  }
196 
197  idx_t size() const { return size_; }
198 
199  template <typename Int>
200  idx_t shape( Int idx ) const {
201  return shape_[idx];
202  }
203 
204  template <typename Int>
205  idx_t stride( Int idx ) const {
206  return strides_[idx];
207  }
208 
209  const idx_t* shape() const { return shape_; }
210 
211  const idx_t* strides() const { return strides_; }
212 
213  value_type const* data() const { return data_; }
214 
215  value_type* data() { return data_; }
216 
217  bool contiguous() const { return ( size_ == shape_[0] * strides_[0] ? true : false ); }
218 
219  ENABLE_IF_NON_CONST
220  void assign( const value_type& value );
221 
222  void dump( std::ostream& os ) const;
223 
224  static constexpr idx_t rank() { return Rank; }
225 
226  template <typename... Args>
227  typename slice_t<Args...>::type slice( Args... args ) {
228  return slicer_t( *this ).apply( args... );
229  }
230 
231  template <typename... Args>
232  typename const_slice_t<Args...>::type slice( Args... args ) const {
233  return const_slicer_t( *this ).apply( args... );
234  }
235 
236  friend std::ostream& operator<<( std::ostream& out, const LocalView& x ) {
237  x.dump( out );
238  return out;
239  }
240 
241 private:
242  // -- Private methods
243 
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... );
247  }
248 
249  template <int Dim, typename Int>
250  constexpr idx_t index_part( Int last_idx ) const {
251  return last_idx * strides_[Dim];
252  }
253 
254  template <typename... Ints>
255  constexpr idx_t index( Ints... idx ) const {
256  return index_part<0>( idx... );
257  }
258 
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... );
264  }
265 #else
266  template <typename... Ints>
267  void check_bounds( Ints... ) const {}
268 #endif
269 
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... );
274  }
275 
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] );
280  }
281  check_bounds_part<Dim + 1>( next_idx... );
282  }
283 
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] );
288  }
289  }
290 
291 private:
292  // -- Private data
293 
294  value_type* data_;
295  idx_t size_;
296  idx_t shape_[Rank];
297  idx_t strides_[Rank];
298 
299 #undef ENABLE_IF_NON_CONST
300 #undef ENABLE_IF_CONST_WITH_NON_CONST
301 };
302 
303 } // namespace array
304 } // namespace atlas
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