OTB  9.0.0
Orfeo Toolbox
otbExtents.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 #ifndef otbExtents_h
21 #define otbExtents_h
22 
23 // #include <boost/hana.hpp> // boost.hana requires boost 1.61.0
24 #include <boost/mpl/vector_c.hpp>
25 #include <boost/mpl/count.hpp>
26 #include <cstddef>
27 #include <array>
28 #include <algorithm>
29 #include <cassert>
30 
31 namespace otb
32 {
33 enum : std::ptrdiff_t { dynamic_extent = -1 };
34 
35 namespace details
36 {
37 
38 template< std::ptrdiff_t ... StaticExtents >
39 constexpr std::size_t rank_dynamic() noexcept
40 {
41 #if 0
42  return boost::hana::count(
43  boost::hana::make_tuple(StaticExtents...),
45 #else
46  using v = boost::mpl::vector_c<std::ptrdiff_t, StaticExtents...>;
47  using c = boost::mpl::count<v, boost::mpl::integral_c<std::ptrdiff_t, dynamic_extent>>;
48  return c::value;
49 #endif
50 }
51 
52 } // details namespace
53 
54 
60 template<std::ptrdiff_t... StaticExtents>
61 class extents
62 {
63 public:
64  // types
65  using index_type = std::ptrdiff_t;
66 
67 private:
68  using dynamic_extents_t = std::array<index_type, details::rank_dynamic<StaticExtents...>()>;
70 
71  static constexpr size_t dynamic_rank(size_t i) noexcept
72  {
73  assert(i < rank());
74  constexpr auto static_extent_ = std::array<index_type, rank()>{StaticExtents...};
75  return std::count(&static_extent_[0], &static_extent_[i+1], dynamic_extent);
76  }
77 
78 public:
79 
80  // [mdspan.extents.cons], Constructors and assignment
81  constexpr extents() noexcept {}
82  constexpr extents(extents const&) noexcept = default;
83  constexpr extents(extents &&) noexcept = default ;
84 
85  template<class... IndexType>
86  constexpr explicit extents(index_type dn, IndexType... dynamic) noexcept
87  : dynamic_extents_{dn, dynamic...}
88  { static_assert( 1+sizeof...(dynamic) == rank_dynamic() , "" ); }
89 
90  template<class IndexType>
91  constexpr extents(const std::array<IndexType, details::rank_dynamic<StaticExtents...>()>& dynamic) noexcept
92  : dynamic_extents_(dynamic)
93  {}
94 
95 #if 0
96  template<std::ptrdiff_t... OtherExtents>
97  constexpr extents(const extents<OtherExtents...>& other) noexcept;
98 #endif
99 
100  constexpr extents& operator=(extents const&) noexcept = default;
101  constexpr extents& operator=(extents &&) noexcept = default;
102 #if 0
103  template<std::ptrdiff_t... OtherExtents>
104  constexpr extents& operator=(const extents<OtherExtents...>& other) noexcept;
105 #endif
106 
107  ~extents() = default;
108 
109  // [mdspan.extents.obs], Observers of the domain multidimensional index space
110  static constexpr size_t rank() noexcept
111  { return sizeof...(StaticExtents); }
112 
113  static constexpr std::size_t rank_dynamic() noexcept
114  { return details::rank_dynamic<StaticExtents...>() ; }
115 
116  static constexpr index_type static_extent(size_t k) noexcept
117  {
118  constexpr auto se = std::array<index_type, rank()>{StaticExtents...};
119  return k<rank() ? se[k] : 1;
120  }
121 
122  constexpr index_type extent(size_t k) const noexcept
123  {
124  // less optimizer friendly than the recursive approach
125  // GCC 7.1 is less efficient to resolve constexpr search, than
126  // clang or GCC 6.x
127  constexpr auto se = std::array<index_type, rank()>{StaticExtents...};
128  return k >= rank() ? 1
129  : se[k] == dynamic_extent ? dynamic_extents_[dynamic_rank(k)-1]
130  : se[k]
131  ;
132  }
133 
134  // Tells whether an extent is fully contained in another one
135  template<std::ptrdiff_t... StaticExtentsR>
136  constexpr bool contains(extents<StaticExtentsR...> const& rhs) const noexcept
137  {
138  auto const& lhs = *this;
139  assert(lhs.rank() == rhs.rank());
140  const auto r = lhs.rank();
141  for (std::size_t k=0; k!=r; ++k)
142  if (lhs.extent(k) > rhs.extent(k))
143  return false;
144  return true;
145  }
146 
147 };
148 
149 template<std::ptrdiff_t... StaticExtentsL, std::ptrdiff_t... StaticExtentsR>
150 constexpr bool operator==(
151  extents<StaticExtentsL...> const& lhs,
152  extents<StaticExtentsR...> const& rhs)
153 {
154  if (lhs.rank() != rhs.rank())
155  return false;
156  const auto r = lhs.rank();
157  for (std::size_t k=0; k!=r; ++k)
158  if (lhs.extent(k) != rhs.extent(k))
159  return false;
160  return true;
161 }
162 
163 template<std::ptrdiff_t... StaticExtentsL, std::ptrdiff_t... StaticExtentsR>
164 constexpr bool operator!=(
165  extents<StaticExtentsL...> const& lhs,
166  extents<StaticExtentsR...> const& rhs)
167 {
168  return ! (lhs == rhs);
169 }
170 
171 } // otb namespace
172 
173 #endif // otbExtents_h
otb::extents::dynamic_rank
static constexpr vcl_size_t dynamic_rank(vcl_size_t i) noexcept
Definition: otbExtents.h:71
otb::extents
Definition: otbExtents.h:61
otb::dynamic_extent
@ dynamic_extent
Definition: otbExtents.h:33
otb::extents::extents
constexpr extents(const std::array< IndexType, details::rank_dynamic< StaticExtents... >()> &dynamic) noexcept
Definition: otbExtents.h:91
otb::extents::static_extent
static constexpr index_type static_extent(vcl_size_t k) noexcept
Definition: otbExtents.h:116
otb::extents::rank
static constexpr vcl_size_t rank() noexcept
Definition: otbExtents.h:110
otb::extents::extents
constexpr extents() noexcept
Definition: otbExtents.h:81
otb::extents::operator=
constexpr extents & operator=(extents const &) noexcept=default
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::extents::rank_dynamic
static constexpr std::vcl_size_t rank_dynamic() noexcept
Definition: otbExtents.h:113
otb::extents::index_type
std::ptrdiff_t index_type
Definition: otbExtents.h:65
otb::operator==
constexpr bool operator==(extents< StaticExtentsL... > const &lhs, extents< StaticExtentsR... > const &rhs)
Definition: otbExtents.h:150
otb::extents::extent
constexpr index_type extent(vcl_size_t k) const noexcept
Definition: otbExtents.h:122
otb::extents::dynamic_extents_
dynamic_extents_t dynamic_extents_
Definition: otbExtents.h:69
otb::extents::contains
constexpr bool contains(extents< StaticExtentsR... > const &rhs) const noexcept
Definition: otbExtents.h:136
otb::extents::dynamic_extents_t
std::array< index_type, details::rank_dynamic< StaticExtents... >()> dynamic_extents_t
Definition: otbExtents.h:68
otb::operator!=
constexpr bool operator!=(extents< StaticExtentsL... > const &lhs, extents< StaticExtentsR... > const &rhs)
Definition: otbExtents.h:164
otb::details::rank_dynamic
constexpr std::vcl_size_t rank_dynamic() noexcept
Definition: otbExtents.h:39
otb::extents::~extents
~extents()=default