• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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