xref: /aosp_15_r20/external/eigen/unsupported/Eigen/CXX11/src/util/EmulateArray.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <[email protected]>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_EMULATE_ARRAY_H
11 #define EIGEN_EMULATE_ARRAY_H
12 
13 
14 
15 // The array class is only available starting with cxx11. Emulate our own here
16 // if needed. Beware, msvc still doesn't advertise itself as a c++11 compiler!
17 // Moreover, CUDA doesn't support the STL containers, so we use our own instead.
18 #if (__cplusplus <= 199711L && EIGEN_COMP_MSVC < 1900) || defined(EIGEN_GPUCC) || defined(EIGEN_AVOID_STL_ARRAY)
19 
20 namespace Eigen {
21 template <typename T, size_t n> class array {
22  public:
23   EIGEN_DEVICE_FUNC
24   EIGEN_STRONG_INLINE T& operator[] (size_t index) { eigen_internal_assert(index < size()); return values[index]; }
25   EIGEN_DEVICE_FUNC
26   EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { eigen_internal_assert(index < size()); return values[index]; }
27 
28   EIGEN_DEVICE_FUNC
at(size_t index)29   EIGEN_STRONG_INLINE T& at(size_t index) { eigen_assert(index < size()); return values[index]; }
30   EIGEN_DEVICE_FUNC
at(size_t index)31   EIGEN_STRONG_INLINE const T& at(size_t index) const { eigen_assert(index < size()); return values[index]; }
32 
33   EIGEN_DEVICE_FUNC
front()34   EIGEN_STRONG_INLINE T& front() { return values[0]; }
35   EIGEN_DEVICE_FUNC
front()36   EIGEN_STRONG_INLINE const T& front() const { return values[0]; }
37 
38   EIGEN_DEVICE_FUNC
back()39   EIGEN_STRONG_INLINE T& back() { return values[n-1]; }
40   EIGEN_DEVICE_FUNC
back()41   EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; }
42 
43   EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
size()44   static std::size_t size() { return n; }
45 
46   T values[n];
47 
48   EIGEN_DEVICE_FUNC
array()49   EIGEN_STRONG_INLINE array() { }
50   EIGEN_DEVICE_FUNC
array(const T & v)51   EIGEN_STRONG_INLINE array(const T& v) {
52     EIGEN_STATIC_ASSERT(n==1, YOU_MADE_A_PROGRAMMING_MISTAKE)
53     values[0] = v;
54   }
55   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2)56   EIGEN_STRONG_INLINE array(const T& v1, const T& v2) {
57     EIGEN_STATIC_ASSERT(n==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
58     values[0] = v1;
59     values[1] = v2;
60   }
61   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3)62   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3) {
63     EIGEN_STATIC_ASSERT(n==3, YOU_MADE_A_PROGRAMMING_MISTAKE)
64     values[0] = v1;
65     values[1] = v2;
66     values[2] = v3;
67   }
68   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4)69   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3,
70                             const T& v4) {
71     EIGEN_STATIC_ASSERT(n==4, YOU_MADE_A_PROGRAMMING_MISTAKE)
72     values[0] = v1;
73     values[1] = v2;
74     values[2] = v3;
75     values[3] = v4;
76   }
77   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5)78   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
79                             const T& v5) {
80     EIGEN_STATIC_ASSERT(n==5, YOU_MADE_A_PROGRAMMING_MISTAKE)
81     values[0] = v1;
82     values[1] = v2;
83     values[2] = v3;
84     values[3] = v4;
85     values[4] = v5;
86   }
87   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5,const T & v6)88   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
89                             const T& v5, const T& v6) {
90     EIGEN_STATIC_ASSERT(n==6, YOU_MADE_A_PROGRAMMING_MISTAKE)
91     values[0] = v1;
92     values[1] = v2;
93     values[2] = v3;
94     values[3] = v4;
95     values[4] = v5;
96     values[5] = v6;
97   }
98   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5,const T & v6,const T & v7)99   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
100                             const T& v5, const T& v6, const T& v7) {
101     EIGEN_STATIC_ASSERT(n==7, YOU_MADE_A_PROGRAMMING_MISTAKE)
102     values[0] = v1;
103     values[1] = v2;
104     values[2] = v3;
105     values[3] = v4;
106     values[4] = v5;
107     values[5] = v6;
108     values[6] = v7;
109   }
110   EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5,const T & v6,const T & v7,const T & v8)111   EIGEN_STRONG_INLINE array(
112       const T& v1, const T& v2, const T& v3, const T& v4,
113       const T& v5, const T& v6, const T& v7, const T& v8) {
114     EIGEN_STATIC_ASSERT(n==8, YOU_MADE_A_PROGRAMMING_MISTAKE)
115     values[0] = v1;
116     values[1] = v2;
117     values[2] = v3;
118     values[3] = v4;
119     values[4] = v5;
120     values[5] = v6;
121     values[6] = v7;
122     values[7] = v8;
123   }
124 
125 #if EIGEN_HAS_VARIADIC_TEMPLATES
126   EIGEN_DEVICE_FUNC
array(std::initializer_list<T> l)127   EIGEN_STRONG_INLINE array(std::initializer_list<T> l) {
128     eigen_assert(l.size() == n);
129     internal::smart_copy(l.begin(), l.end(), values);
130   }
131 #endif
132 };
133 
134 
135 // Specialize array for zero size
136 template <typename T> class array<T, 0> {
137  public:
138   EIGEN_DEVICE_FUNC
139   EIGEN_STRONG_INLINE T& operator[] (size_t) {
140     eigen_assert(false && "Can't index a zero size array");
141     return dummy;
142   }
143   EIGEN_DEVICE_FUNC
144   EIGEN_STRONG_INLINE const T& operator[] (size_t) const {
145     eigen_assert(false && "Can't index a zero size array");
146     return dummy;
147   }
148 
149   EIGEN_DEVICE_FUNC
front()150   EIGEN_STRONG_INLINE T& front() {
151     eigen_assert(false && "Can't index a zero size array");
152     return dummy;
153   }
154   EIGEN_DEVICE_FUNC
front()155   EIGEN_STRONG_INLINE const T& front() const {
156     eigen_assert(false && "Can't index a zero size array");
157     return dummy;
158   }
159   EIGEN_DEVICE_FUNC
back()160   EIGEN_STRONG_INLINE T& back() {
161     eigen_assert(false && "Can't index a zero size array");
162     return dummy;
163   }
164   EIGEN_DEVICE_FUNC
back()165   EIGEN_STRONG_INLINE const T& back() const {
166     eigen_assert(false && "Can't index a zero size array");
167     return dummy;
168   }
169 
size()170   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; }
171 
172   EIGEN_DEVICE_FUNC
array()173   EIGEN_STRONG_INLINE array() : dummy() { }
174 
175 #if EIGEN_HAS_VARIADIC_TEMPLATES
array(std::initializer_list<T> l)176   EIGEN_DEVICE_FUNC array(std::initializer_list<T> l) : dummy() {
177     EIGEN_UNUSED_VARIABLE(l);
178     eigen_assert(l.size() == 0);
179   }
180 #endif
181 
182  private:
183   T dummy;
184 };
185 
186 // Comparison operator
187 // Todo: implement !=, <, <=, >,  and >=
188 template<class T, std::size_t N>
189 EIGEN_DEVICE_FUNC bool operator==(const array<T,N>& lhs, const array<T,N>& rhs) {
190   for (std::size_t i = 0; i < N; ++i) {
191     if (lhs[i] != rhs[i]) {
192       return false;
193     }
194   }
195   return true;
196 }
197 
198 
199 namespace internal {
200 template<std::size_t I_, class T, std::size_t N>
array_get(array<T,N> & a)201 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array<T,N>& a) {
202   return a[I_];
203 }
204 template<std::size_t I_, class T, std::size_t N>
array_get(const array<T,N> & a)205 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
206   return a[I_];
207 }
208 
209 template<class T, std::size_t N> struct array_size<array<T,N> > {
210   enum { value = N };
211 };
212 template<class T, std::size_t N> struct array_size<array<T,N>& > {
213   enum { value = N };
214 };
215 template<class T, std::size_t N> struct array_size<const array<T,N> > {
216   enum { value = N };
217 };
218 template<class T, std::size_t N> struct array_size<const array<T,N>& > {
219   enum { value = N };
220 };
221 
222 }  // end namespace internal
223 }  // end namespace Eigen
224 
225 #else
226 
227 // The compiler supports c++11, and we're not targeting cuda: use std::array as Eigen::array
228 #include <array>
229 namespace Eigen {
230 
231 template <typename T, std::size_t N> using array = std::array<T, N>;
232 
233 namespace internal {
234 /* std::get is only constexpr in C++14, not yet in C++11
235  *     - libstdc++ from version 4.7 onwards has it nevertheless,
236  *                                          so use that
237  *     - libstdc++ older versions: use _M_instance directly
238  *     - libc++ all versions so far: use __elems_ directly
239  *     - all other libs: use std::get to be portable, but
240  *                       this may not be constexpr
241  */
242 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20120322
243 #define STD_GET_ARR_HACK             a._M_instance[I_]
244 #elif defined(_LIBCPP_VERSION)
245 #define STD_GET_ARR_HACK             a.__elems_[I_]
246 #else
247 #define STD_GET_ARR_HACK             std::template get<I_, T, N>(a)
248 #endif
249 
250 template<std::size_t I_, class T, std::size_t N> constexpr inline T&       array_get(std::array<T,N>&       a) { return (T&)       STD_GET_ARR_HACK; }
251 template<std::size_t I_, class T, std::size_t N> constexpr inline T&&      array_get(std::array<T,N>&&      a) { return (T&&)      STD_GET_ARR_HACK; }
252 template<std::size_t I_, class T, std::size_t N> constexpr inline T const& array_get(std::array<T,N> const& a) { return (T const&) STD_GET_ARR_HACK; }
253 
254 #undef STD_GET_ARR_HACK
255 
256 }  // end namespace internal
257 }  // end namespace Eigen
258 
259 #endif
260 
261 #endif  // EIGEN_EMULATE_ARRAY_H
262