atlas
NativeIndexView.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 
38 
39 #pragma once
40 
41 #include <iosfwd>
42 
43 #include "atlas/array/ArrayUtil.h"
44 #include "atlas/library/config.h"
45 
46 //------------------------------------------------------------------------------------------------------
47 
48 namespace atlas {
49 namespace array {
50 
51 //------------------------------------------------------------------------------------------------------
52 
53 namespace detail {
54 // FortranIndex:
55 // Helper class that does +1 and -1 operations on stored values
56 template <typename Value>
57 class FortranIndex {
58 public:
59  enum
60  {
61  BASE = 1
62  };
63 
64 public:
65  FortranIndex( Value* idx ) : idx_( idx ) {}
66  void set( const Value& value ) { *( idx_ ) = value + BASE; }
67  Value get() const { return *(idx_)-BASE; }
68  void operator =( const Value& value ) { set( value ); }
69  FortranIndex<Value>& operator=( const FortranIndex<Value>& other ) {
70  set( other.get() );
71  return *this;
72  }
73  FortranIndex<Value>& operator--() {
74  --( *( idx_ ) );
75  return *this;
76  }
77  FortranIndex<Value>& operator++() {
78  ++( *( idx_ ) );
79  return *this;
80  }
81 
82  // implicit conversion
83  operator Value() const { return get(); }
84 
85 private:
86  Value* idx_;
87 };
88 
89 } // namespace detail
90 
91 #if ATLAS_HAVE_FORTRAN
92 #define INDEX_REF Index
93 #define FROM_FORTRAN -1
94 #define TO_FORTRAN +1
95 #else
96 #define INDEX_REF *
97 #define FROM_FORTRAN
98 #define TO_FORTRAN
99 #endif
100 
101 //------------------------------------------------------------------------------------------------------
102 
113 template <typename Value, int Rank>
114 class IndexView {
115 public:
116  using value_type = typename remove_const<Value>::type;
117 
118 #if ATLAS_HAVE_FORTRAN
119  typedef detail::FortranIndex<Value> Index;
120 #else
121  typedef Value& Index;
122 #endif
123 
124 public:
125 #ifndef DOXYGEN_SHOULD_SKIP_THIS
126  IndexView( Value* data, const idx_t shape[Rank] );
127 
128  IndexView( Value* data, const idx_t shape[Rank], const idx_t strides[Rank] );
129 #endif
130  // -- Access methods
131 
133  template <typename... Idx>
134  Index operator()( Idx... idx ) {
135  check_bounds( idx... );
136  return INDEX_REF( &data_[index( idx... )] );
137  }
138 
140  template <typename... Ints>
141  const value_type operator()( Ints... idx ) const {
142  return data_[index( idx... )] FROM_FORTRAN;
143  }
144 
145 private:
146  // -- Private methods
147 
148  template <int Dim, typename Int, typename... Ints>
149  constexpr idx_t index_part( Int idx, Ints... next_idx ) const {
150  return idx * strides_[Dim] + index_part<Dim + 1>( next_idx... );
151  }
152 
153  template <int Dim, typename Int>
154  constexpr idx_t index_part( Int last_idx ) const {
155  return last_idx * strides_[Dim];
156  }
157 
158  template <typename... Ints>
159  constexpr idx_t index( Ints... idx ) const {
160  return index_part<0>( idx... );
161  }
162 
163 #if ATLAS_INDEXVIEW_BOUNDS_CHECKING
164  template <typename... Ints>
165  void check_bounds( Ints... idx ) const {
166  static_assert( sizeof...( idx ) == Rank, "Expected number of indices is different from rank of array" );
167  return check_bounds_part<0>( idx... );
168  }
169 #else
170  template <typename... Ints>
171  void check_bounds( Ints... ) const {}
172 #endif
173 
174  template <typename... Ints>
175  void check_bounds_force( Ints... idx ) const {
176  static_assert( sizeof...( idx ) == Rank, "Expected number of indices is different from rank of array" );
177  return check_bounds_part<0>( idx... );
178  }
179 
180  template <int Dim, typename Int, typename... Ints>
181  void check_bounds_part( Int idx, Ints... next_idx ) const {
182  if ( idx_t( idx ) >= shape_[Dim] ) {
183  throw_OutOfRange( "IndexView", array_dim<Dim>(), idx, shape_[Dim] );
184  }
185  check_bounds_part<Dim + 1>( next_idx... );
186  }
187 
188  template <int Dim, typename Int>
189  void check_bounds_part( Int last_idx ) const {
190  if ( idx_t( last_idx ) >= shape_[Dim] ) {
191  throw_OutOfRange( "IndexView", array_dim<Dim>(), last_idx, shape_[Dim] );
192  }
193  }
194 
195  idx_t size() const { return shape_[0]; }
196 
197  void dump( std::ostream& os ) const;
198 
199 private:
200  Value* data_;
201  idx_t strides_[Rank];
202  idx_t shape_[Rank];
203 };
204 
205 template <typename Value, int Rank>
206 class LocalIndexView : public IndexView<Value, Rank> {
207  using Base = IndexView<Value, Rank>;
208 
209 public:
210  using Base::Base;
211 };
212 
213 #undef INDEX_REF
214 #undef FROM_FORTRAN
215 #undef TO_FORTRAN
216 
217 
218 //------------------------------------------------------------------------------------------------------
219 
220 } // namespace array
221 } // namespace atlas
Definition: GridToolsIndexView.h:136
Index operator()(Idx... idx)
Multidimensional index operator: view(i,j,k,...)
Definition: NativeIndexView.h:134
const value_type operator()(Ints... idx) const
Multidimensional index operator: view(i,j,k,...)
Definition: NativeIndexView.h:141
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