EmulateArray.h (8155B)
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(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 29 EIGEN_STRONG_INLINE T& at(size_t index) { eigen_assert(index < size()); return values[index]; } 30 EIGEN_DEVICE_FUNC 31 EIGEN_STRONG_INLINE const T& at(size_t index) const { eigen_assert(index < size()); return values[index]; } 32 33 EIGEN_DEVICE_FUNC 34 EIGEN_STRONG_INLINE T& front() { return values[0]; } 35 EIGEN_DEVICE_FUNC 36 EIGEN_STRONG_INLINE const T& front() const { return values[0]; } 37 38 EIGEN_DEVICE_FUNC 39 EIGEN_STRONG_INLINE T& back() { return values[n-1]; } 40 EIGEN_DEVICE_FUNC 41 EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; } 42 43 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE 44 static std::size_t size() { return n; } 45 46 T values[n]; 47 48 EIGEN_DEVICE_FUNC 49 EIGEN_STRONG_INLINE array() { } 50 EIGEN_DEVICE_FUNC 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 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 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 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 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 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 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 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 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 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 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 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 165 EIGEN_STRONG_INLINE const T& back() const { 166 eigen_assert(false && "Can't index a zero size array"); 167 return dummy; 168 } 169 170 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; } 171 172 EIGEN_DEVICE_FUNC 173 EIGEN_STRONG_INLINE array() : dummy() { } 174 175 #if EIGEN_HAS_VARIADIC_TEMPLATES 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> 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> 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