atlas
GridToolsIndexView.h
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 
11 #pragma once
12 #include <type_traits>
13 
14 #include "atlas/array/gridtools/GridToolsTraits.h"
15 #include "atlas/library/config.h"
16 
17 //------------------------------------------------------------------------------------------------------
18 
19 namespace atlas {
20 namespace array {
21 
22 //------------------------------------------------------------------------------------------------------
23 
24 namespace detail {
25 
26 // FortranIndex:
27 // Helper class that does +1 and -1 operations on stored values
28 template <typename Value>
29 class FortranIndex {
30 public:
31  enum
32  {
33  BASE = 1
34  };
35 
36 public:
37  ATLAS_HOST_DEVICE
38  FortranIndex( Value* idx ) : idx_( idx ) {}
39  ATLAS_HOST_DEVICE
40  void set( const Value& value ) { *( idx_ ) = value + BASE; }
41  ATLAS_HOST_DEVICE
42  Value get() const { return *(idx_)-BASE; }
43  ATLAS_HOST_DEVICE
44  void operator=( const Value& value ) { set( value ); }
45  ATLAS_HOST_DEVICE
46  FortranIndex<Value>& operator=( const FortranIndex<Value>& other ) {
47  set( other.get() );
48  return *this;
49  }
50  ATLAS_HOST_DEVICE
51  FortranIndex<Value>& operator--() {
52  --( *( idx_ ) );
53  return *this;
54  }
55  ATLAS_HOST_DEVICE
56  FortranIndex<Value>& operator++() {
57  ++( *( idx_ ) );
58  return *this;
59  }
60 
61  // implicit conversion
62  ATLAS_HOST_DEVICE
63  operator Value() const { return get(); }
64 
65 private:
66  Value* idx_;
67 };
68 
69 } // namespace detail
70 
71 //------------------------------------------------------------------------------------------------------
72 
73 template <typename Value, int Rank>
74 class IndexView {
75 public:
76 // -- Type definitions
77 #if ATLAS_HAVE_FORTRAN
78  typedef detail::FortranIndex<Value> Index;
79 #define INDEX_REF Index
80 #define FROM_FORTRAN -1
81 #define TO_FORTRAN +1
82 #else
83  typedef Value& Index;
84 #define INDEX_REF *
85 #define FROM_FORTRAN
86 #define TO_FORTRAN
87 #endif
88  using data_view_t =
89  gridtools::data_view_tt<typename std::remove_const<Value>::type, Rank, gridtools::get_access_mode<Value>()>;
90 
91 public:
92  IndexView( data_view_t data_view ) : gt_data_view_( data_view ) {
93  if ( data_view.valid() )
94  size_ = gt_data_view_.storage_info().total_length();
95  else
96  size_ = 0;
97  }
98 
99  template <typename... Coords, typename = typename std::enable_if<( sizeof...( Coords ) == Rank ), int>::type>
100  Index ATLAS_HOST_DEVICE operator()( Coords... c ) {
101  assert( sizeof...( Coords ) == Rank );
102  return INDEX_REF( &gt_data_view_( c... ) );
103  }
104 
105  template <typename... Coords, typename = typename std::enable_if<( sizeof...( Coords ) == Rank ), int>::type>
106  ATLAS_HOST_DEVICE Value const operator()( Coords... c ) const {
107  return gt_data_view_( c... ) FROM_FORTRAN;
108  }
109 
110  idx_t size() const { return size_; }
111 
112  void dump( std::ostream& os ) const;
113 
114 private:
115  data_view_t gt_data_view_;
116  idx_t size_;
117 
118 #undef INDEX_REF
119 #undef TO_FORTRAN
120 #undef FROM_FORTRAN
121 };
122 
123 
124 #if ATLAS_HAVE_FORTRAN
125 #define INDEX_REF Index
126 #define FROM_FORTRAN -1
127 #define TO_FORTRAN +1
128 #else
129 #define INDEX_REF *
130 #define FROM_FORTRAN
131 #define TO_FORTRAN
132 #endif
133 
134 
135 template <typename Value, int Rank>
137 public:
138  using value_type = typename remove_const<Value>::type;
139 
140 #if ATLAS_HAVE_FORTRAN
141  typedef detail::FortranIndex<Value> Index;
142 #else
143  typedef Value& Index;
144 #endif
145 
146 public:
147  LocalIndexView( Value* data, const idx_t shape[Rank] );
148 
149  LocalIndexView( Value* data, const idx_t shape[Rank], const idx_t strides[Rank] );
150 
151  // -- Access methods
152 
153  template <typename... Ints, typename = typename std::enable_if<( sizeof...( Ints ) == Rank ), int>::type>
154  Index operator()( Ints... idx ) {
155  check_bounds( idx... );
156  return INDEX_REF( &data_[index( idx... )] );
157  }
158 
159  template <typename... Ints, typename = typename std::enable_if<( sizeof...( Ints ) == Rank ), int>::type>
160  const value_type operator()( Ints... idx ) const {
161  return data_[index( idx... )] FROM_FORTRAN;
162  }
163 
164 private:
165  // -- Private methods
166 
167  template <int Dim, typename Int, typename... Ints>
168  constexpr idx_t index_part( Int idx, Ints... next_idx ) const {
169  return idx * strides_[Dim] + index_part<Dim + 1>( next_idx... );
170  }
171 
172  template <int Dim, typename Int>
173  constexpr idx_t index_part( Int last_idx ) const {
174  return last_idx * strides_[Dim];
175  }
176 
177  template <typename... Ints>
178  constexpr idx_t index( Ints... idx ) const {
179  return index_part<0>( idx... );
180  }
181 
182 #if ATLAS_INDEXVIEW_BOUNDS_CHECKING
183  template <typename... Ints>
184  void check_bounds( Ints... idx ) const {
185  static_assert( sizeof...( idx ) == Rank, "Expected number of indices is different from rank of array" );
186  return check_bounds_part<0>( idx... );
187  }
188 #else
189  template <typename... Ints>
190  void check_bounds( Ints... ) const {}
191 #endif
192 
193  template <typename... Ints>
194  void check_bounds_force( Ints... idx ) const {
195  static_assert( sizeof...( idx ) == Rank, "Expected number of indices is different from rank of array" );
196  return check_bounds_part<0>( idx... );
197  }
198 
199  template <int Dim, typename Int, typename... Ints>
200  void check_bounds_part( Int idx, Ints... next_idx ) const {
201  if ( idx_t( idx ) >= shape_[Dim] ) {
202  throw_OutOfRange( "IndexView", array_dim<Dim>(), idx, shape_[Dim] );
203  }
204  check_bounds_part<Dim + 1>( next_idx... );
205  }
206 
207  template <int Dim, typename Int>
208  void check_bounds_part( Int last_idx ) const {
209  if ( idx_t( last_idx ) >= shape_[Dim] ) {
210  throw_OutOfRange( "IndexView", array_dim<Dim>(), last_idx, shape_[Dim] );
211  }
212  }
213 
214  idx_t size() const { return shape_[0]; }
215 
216  void dump( std::ostream& os ) const;
217 
218 private:
219  Value* data_;
220  idx_t strides_[Rank];
221  idx_t shape_[Rank];
222 };
223 
224 #undef INDEX_REF
225 #undef FROM_FORTRAN
226 #undef TO_FORTRAN
227 
228 //------------------------------------------------------------------------------------------------------
229 
230 } // namespace array
231 } // namespace atlas
Definition: GridToolsIndexView.h:29
Definition: GridToolsIndexView.h:136
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
Multidimensional access to Array or Field objects containing index fields that are compatible with Fo...
Definition: GridToolsIndexView.h:74
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42
Definition: ArrayViewDefs.h:20