1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
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(__CUDACC__) || 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) { return values[index]; }
25 EIGEN_DEVICE_FUNC
26 EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { return values[index]; }
27
28 EIGEN_DEVICE_FUNC
front()29 EIGEN_STRONG_INLINE T& front() { return values[0]; }
30 EIGEN_DEVICE_FUNC
front()31 EIGEN_STRONG_INLINE const T& front() const { return values[0]; }
32
33 EIGEN_DEVICE_FUNC
back()34 EIGEN_STRONG_INLINE T& back() { return values[n-1]; }
35 EIGEN_DEVICE_FUNC
back()36 EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; }
37
38 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
size()39 static std::size_t size() { return n; }
40
41 T values[n];
42
43 EIGEN_DEVICE_FUNC
array()44 EIGEN_STRONG_INLINE array() { }
45 EIGEN_DEVICE_FUNC
array(const T & v)46 EIGEN_STRONG_INLINE array(const T& v) {
47 EIGEN_STATIC_ASSERT(n==1, YOU_MADE_A_PROGRAMMING_MISTAKE)
48 values[0] = v;
49 }
50 EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2)51 EIGEN_STRONG_INLINE array(const T& v1, const T& v2) {
52 EIGEN_STATIC_ASSERT(n==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
53 values[0] = v1;
54 values[1] = v2;
55 }
56 EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3)57 EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3) {
58 EIGEN_STATIC_ASSERT(n==3, YOU_MADE_A_PROGRAMMING_MISTAKE)
59 values[0] = v1;
60 values[1] = v2;
61 values[2] = v3;
62 }
63 EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4)64 EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3,
65 const T& v4) {
66 EIGEN_STATIC_ASSERT(n==4, YOU_MADE_A_PROGRAMMING_MISTAKE)
67 values[0] = v1;
68 values[1] = v2;
69 values[2] = v3;
70 values[3] = v4;
71 }
72 EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5)73 EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
74 const T& v5) {
75 EIGEN_STATIC_ASSERT(n==5, YOU_MADE_A_PROGRAMMING_MISTAKE)
76 values[0] = v1;
77 values[1] = v2;
78 values[2] = v3;
79 values[3] = v4;
80 values[4] = v5;
81 }
82 EIGEN_DEVICE_FUNC
array(const T & v1,const T & v2,const T & v3,const T & v4,const T & v5,const T & v6)83 EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
84 const T& v5, const T& v6) {
85 EIGEN_STATIC_ASSERT(n==6, YOU_MADE_A_PROGRAMMING_MISTAKE)
86 values[0] = v1;
87 values[1] = v2;
88 values[2] = v3;
89 values[3] = v4;
90 values[4] = v5;
91 values[5] = v6;
92 }
93 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)94 EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
95 const T& v5, const T& v6, const T& v7) {
96 EIGEN_STATIC_ASSERT(n==7, YOU_MADE_A_PROGRAMMING_MISTAKE)
97 values[0] = v1;
98 values[1] = v2;
99 values[2] = v3;
100 values[3] = v4;
101 values[4] = v5;
102 values[5] = v6;
103 values[6] = v7;
104 }
105 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)106 EIGEN_STRONG_INLINE array(
107 const T& v1, const T& v2, const T& v3, const T& v4,
108 const T& v5, const T& v6, const T& v7, const T& v8) {
109 EIGEN_STATIC_ASSERT(n==8, YOU_MADE_A_PROGRAMMING_MISTAKE)
110 values[0] = v1;
111 values[1] = v2;
112 values[2] = v3;
113 values[3] = v4;
114 values[4] = v5;
115 values[5] = v6;
116 values[6] = v7;
117 values[7] = v8;
118 }
119
120 #if EIGEN_HAS_VARIADIC_TEMPLATES
121 EIGEN_DEVICE_FUNC
array(std::initializer_list<T> l)122 EIGEN_STRONG_INLINE array(std::initializer_list<T> l) {
123 eigen_assert(l.size() == n);
124 internal::smart_copy(l.begin(), l.end(), values);
125 }
126 #endif
127 };
128
129
130 // Specialize array for zero size
131 template <typename T> class array<T, 0> {
132 public:
133 EIGEN_DEVICE_FUNC
134 EIGEN_STRONG_INLINE T& operator[] (size_t) {
135 eigen_assert(false && "Can't index a zero size array");
136 return dummy;
137 }
138 EIGEN_DEVICE_FUNC
139 EIGEN_STRONG_INLINE const T& operator[] (size_t) const {
140 eigen_assert(false && "Can't index a zero size array");
141 return dummy;
142 }
143
144 EIGEN_DEVICE_FUNC
front()145 EIGEN_STRONG_INLINE T& front() {
146 eigen_assert(false && "Can't index a zero size array");
147 return dummy;
148 }
149 EIGEN_DEVICE_FUNC
front()150 EIGEN_STRONG_INLINE const T& front() const {
151 eigen_assert(false && "Can't index a zero size array");
152 return dummy;
153 }
154 EIGEN_DEVICE_FUNC
back()155 EIGEN_STRONG_INLINE T& back() {
156 eigen_assert(false && "Can't index a zero size array");
157 return dummy;
158 }
159 EIGEN_DEVICE_FUNC
back()160 EIGEN_STRONG_INLINE const T& back() const {
161 eigen_assert(false && "Can't index a zero size array");
162 return dummy;
163 }
164
size()165 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; }
166
167 EIGEN_DEVICE_FUNC
array()168 EIGEN_STRONG_INLINE array() : dummy() { }
169
170 #if EIGEN_HAS_VARIADIC_TEMPLATES
array(std::initializer_list<T> l)171 EIGEN_DEVICE_FUNC array(std::initializer_list<T> l) : dummy() {
172 eigen_assert(l.size() == 0);
173 }
174 #endif
175
176 private:
177 T dummy;
178 };
179
180 // Comparison operator
181 // Todo: implement !=, <, <=, >, and >=
182 template<class T, std::size_t N>
183 EIGEN_DEVICE_FUNC bool operator==(const array<T,N>& lhs, const array<T,N>& rhs) {
184 for (std::size_t i = 0; i < N; ++i) {
185 if (lhs[i] != rhs[i]) {
186 return false;
187 }
188 }
189 return true;
190 }
191
192
193 namespace internal {
194 template<std::size_t I, class T, std::size_t N>
array_get(array<T,N> & a)195 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array<T,N>& a) {
196 return a[I];
197 }
198 template<std::size_t I, class T, std::size_t N>
array_get(const array<T,N> & a)199 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
200 return a[I];
201 }
202
203 template <typename T> struct array_size;
204 template<class T, std::size_t N> struct array_size<array<T,N> > {
205 static const size_t value = N;
206 };
207 template <typename T> struct array_size;
208 template<class T, std::size_t N> struct array_size<array<T,N>& > {
209 static const size_t value = N;
210 };
211 template <typename T> struct array_size;
212 template<class T, std::size_t N> struct array_size<const array<T,N> > {
213 static const size_t value = N;
214 };
215 template <typename T> struct array_size;
216 template<class T, std::size_t N> struct array_size<const array<T,N>& > {
217 static const size_t value = N;
218 };
219
220 } // end namespace internal
221 } // end namespace Eigen
222
223 #else
224
225 // The compiler supports c++11, and we're not targetting cuda: use std::array as Eigen::array
226 #include <array>
227 namespace Eigen {
228
229 template <typename T, std::size_t N> using array = std::array<T, N>;
230
231 namespace internal {
232 /* std::get is only constexpr in C++14, not yet in C++11
233 * - libstdc++ from version 4.7 onwards has it nevertheless,
234 * so use that
235 * - libstdc++ older versions: use _M_instance directly
236 * - libc++ all versions so far: use __elems_ directly
237 * - all other libs: use std::get to be portable, but
238 * this may not be constexpr
239 */
240 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20120322
241 #define STD_GET_ARR_HACK a._M_instance[I]
242 #elif defined(_LIBCPP_VERSION)
243 #define STD_GET_ARR_HACK a.__elems_[I]
244 #else
245 #define STD_GET_ARR_HACK std::template get<I, T, N>(a)
246 #endif
247
248 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; }
249 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; }
250 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; }
251
252 #undef STD_GET_ARR_HACK
253
254 template <typename T> struct array_size;
255 template<class T, std::size_t N> struct array_size<const std::array<T,N> > {
256 static const size_t value = N;
257 };
258 template <typename T> struct array_size;
259 template<class T, std::size_t N> struct array_size<std::array<T,N> > {
260 static const size_t value = N;
261 };
262 } // end namespace internal
263 } // end namespace Eigen
264
265 #endif
266
267 #endif // EIGEN_EMULATE_ARRAY_H
268