EmulateArray.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_EMULATE_ARRAY_H
00011 #define EIGEN_EMULATE_ARRAY_H
00012 
00013 
00014 
00015 // The array class is only available starting with cxx11. Emulate our own here
00016 // if needed. Beware, msvc still doesn't advertise itself as a c++11 compiler!
00017 // Moreover, CUDA doesn't support the STL containers, so we use our own instead.
00018 #if (__cplusplus <= 199711L && EIGEN_COMP_MSVC < 1900) || defined(__CUDACC__) || defined(EIGEN_AVOID_STL_ARRAY)
00019 
00020 namespace Eigen {
00021 template <typename T, size_t n> class array {
00022  public:
00023   EIGEN_DEVICE_FUNC
00024   EIGEN_STRONG_INLINE T& operator[] (size_t index) { return values[index]; }
00025   EIGEN_DEVICE_FUNC
00026   EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { return values[index]; }
00027 
00028   EIGEN_DEVICE_FUNC
00029   EIGEN_STRONG_INLINE T& front() { return values[0]; }
00030   EIGEN_DEVICE_FUNC
00031   EIGEN_STRONG_INLINE const T& front() const { return values[0]; }
00032 
00033   EIGEN_DEVICE_FUNC
00034   EIGEN_STRONG_INLINE T& back() { return values[n-1]; }
00035   EIGEN_DEVICE_FUNC
00036   EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; }
00037 
00038   EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
00039   static std::size_t size() { return n; }
00040 
00041   T values[n];
00042 
00043   EIGEN_DEVICE_FUNC
00044   EIGEN_STRONG_INLINE array() { }
00045   EIGEN_DEVICE_FUNC
00046   EIGEN_STRONG_INLINE array(const T& v) {
00047     EIGEN_STATIC_ASSERT(n==1, YOU_MADE_A_PROGRAMMING_MISTAKE)
00048     values[0] = v;
00049   }
00050   EIGEN_DEVICE_FUNC
00051   EIGEN_STRONG_INLINE array(const T& v1, const T& v2) {
00052     EIGEN_STATIC_ASSERT(n==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00053     values[0] = v1;
00054     values[1] = v2;
00055   }
00056   EIGEN_DEVICE_FUNC
00057   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3) {
00058     EIGEN_STATIC_ASSERT(n==3, YOU_MADE_A_PROGRAMMING_MISTAKE)
00059     values[0] = v1;
00060     values[1] = v2;
00061     values[2] = v3;
00062   }
00063   EIGEN_DEVICE_FUNC
00064   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3,
00065                             const T& v4) {
00066     EIGEN_STATIC_ASSERT(n==4, YOU_MADE_A_PROGRAMMING_MISTAKE)
00067     values[0] = v1;
00068     values[1] = v2;
00069     values[2] = v3;
00070     values[3] = v4;
00071   }
00072   EIGEN_DEVICE_FUNC
00073   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
00074                             const T& v5) {
00075     EIGEN_STATIC_ASSERT(n==5, YOU_MADE_A_PROGRAMMING_MISTAKE)
00076     values[0] = v1;
00077     values[1] = v2;
00078     values[2] = v3;
00079     values[3] = v4;
00080     values[4] = v5;
00081   }
00082   EIGEN_DEVICE_FUNC
00083   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
00084                             const T& v5, const T& v6) {
00085     EIGEN_STATIC_ASSERT(n==6, YOU_MADE_A_PROGRAMMING_MISTAKE)
00086     values[0] = v1;
00087     values[1] = v2;
00088     values[2] = v3;
00089     values[3] = v4;
00090     values[4] = v5;
00091     values[5] = v6;
00092   }
00093   EIGEN_DEVICE_FUNC
00094   EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
00095                             const T& v5, const T& v6, const T& v7) {
00096     EIGEN_STATIC_ASSERT(n==7, YOU_MADE_A_PROGRAMMING_MISTAKE)
00097     values[0] = v1;
00098     values[1] = v2;
00099     values[2] = v3;
00100     values[3] = v4;
00101     values[4] = v5;
00102     values[5] = v6;
00103     values[6] = v7;
00104   }
00105   EIGEN_DEVICE_FUNC
00106   EIGEN_STRONG_INLINE array(
00107       const T& v1, const T& v2, const T& v3, const T& v4,
00108       const T& v5, const T& v6, const T& v7, const T& v8) {
00109     EIGEN_STATIC_ASSERT(n==8, YOU_MADE_A_PROGRAMMING_MISTAKE)
00110     values[0] = v1;
00111     values[1] = v2;
00112     values[2] = v3;
00113     values[3] = v4;
00114     values[4] = v5;
00115     values[5] = v6;
00116     values[6] = v7;
00117     values[7] = v8;
00118   }
00119 
00120 #if EIGEN_HAS_VARIADIC_TEMPLATES
00121   EIGEN_DEVICE_FUNC
00122   EIGEN_STRONG_INLINE array(std::initializer_list<T> l) {
00123     eigen_assert(l.size() == n);
00124     internal::smart_copy(l.begin(), l.end(), values);
00125   }
00126 #endif
00127 };
00128 
00129 
00130 // Specialize array for zero size
00131 template <typename T> class array<T, 0> {
00132  public:
00133   EIGEN_DEVICE_FUNC
00134   EIGEN_STRONG_INLINE T& operator[] (size_t) {
00135     eigen_assert(false && "Can't index a zero size array");
00136     return dummy;
00137   }
00138   EIGEN_DEVICE_FUNC
00139   EIGEN_STRONG_INLINE const T& operator[] (size_t) const {
00140     eigen_assert(false && "Can't index a zero size array");
00141     return dummy;
00142   }
00143 
00144   EIGEN_DEVICE_FUNC
00145   EIGEN_STRONG_INLINE T& front() {
00146     eigen_assert(false && "Can't index a zero size array");
00147     return dummy;
00148   }
00149   EIGEN_DEVICE_FUNC
00150   EIGEN_STRONG_INLINE const T& front() const {
00151     eigen_assert(false && "Can't index a zero size array");
00152     return dummy;
00153   }
00154   EIGEN_DEVICE_FUNC
00155   EIGEN_STRONG_INLINE T& back() {
00156     eigen_assert(false && "Can't index a zero size array");
00157     return dummy;
00158   }
00159   EIGEN_DEVICE_FUNC
00160   EIGEN_STRONG_INLINE const T& back() const {
00161     eigen_assert(false && "Can't index a zero size array");
00162     return dummy;
00163   }
00164 
00165   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; }
00166 
00167   EIGEN_DEVICE_FUNC
00168   EIGEN_STRONG_INLINE array() : dummy() { }
00169 
00170 #if EIGEN_HAS_VARIADIC_TEMPLATES
00171   EIGEN_DEVICE_FUNC array(std::initializer_list<T> l) : dummy() {
00172     eigen_assert(l.size() == 0);
00173   }
00174 #endif
00175 
00176  private:
00177   T dummy;
00178 };
00179 
00180 // Comparison operator
00181 // Todo: implement !=, <, <=, >,  and >=
00182 template<class T, std::size_t N>
00183 EIGEN_DEVICE_FUNC bool operator==(const array<T,N>& lhs, const array<T,N>& rhs) {
00184   for (std::size_t i = 0; i < N; ++i) {
00185     if (lhs[i] != rhs[i]) {
00186       return false;
00187     }
00188   }
00189   return true;
00190 }
00191 
00192 
00193 namespace internal {
00194 template<std::size_t I, class T, std::size_t N>
00195 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array<T,N>& a) {
00196   return a[I];
00197 }
00198 template<std::size_t I, class T, std::size_t N>
00199 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
00200   return a[I];
00201 }
00202 
00203 template <typename T> struct array_size;
00204 template<class T, std::size_t N> struct array_size<array<T,N> > {
00205   static const size_t value = N;
00206 };
00207 template <typename T> struct array_size;
00208 template<class T, std::size_t N> struct array_size<array<T,N>& > {
00209   static const size_t value = N;
00210 };
00211 template <typename T> struct array_size;
00212 template<class T, std::size_t N> struct array_size<const array<T,N> > {
00213   static const size_t value = N;
00214 };
00215 template <typename T> struct array_size;
00216 template<class T, std::size_t N> struct array_size<const array<T,N>& > {
00217   static const size_t value = N;
00218 };
00219 
00220 }  // end namespace internal
00221 }  // end namespace Eigen
00222 
00223 #else
00224 
00225 // The compiler supports c++11, and we're not targetting cuda: use std::array as Eigen::array
00226 #include <array>
00227 namespace Eigen {
00228 
00229 template <typename T, std::size_t N> using array = std::array<T, N>;
00230 
00231 namespace internal {
00232 /* std::get is only constexpr in C++14, not yet in C++11
00233  *     - libstdc++ from version 4.7 onwards has it nevertheless,
00234  *                                          so use that
00235  *     - libstdc++ older versions: use _M_instance directly
00236  *     - libc++ all versions so far: use __elems_ directly
00237  *     - all other libs: use std::get to be portable, but
00238  *                       this may not be constexpr
00239  */
00240 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20120322
00241 #define STD_GET_ARR_HACK             a._M_instance[I]
00242 #elif defined(_LIBCPP_VERSION)
00243 #define STD_GET_ARR_HACK             a.__elems_[I]
00244 #else
00245 #define STD_GET_ARR_HACK             std::template get<I, T, N>(a)
00246 #endif
00247 
00248 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; }
00249 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; }
00250 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; }
00251 
00252 #undef STD_GET_ARR_HACK
00253 
00254 template <typename T> struct array_size;
00255 template<class T, std::size_t N> struct array_size<const std::array<T,N> > {
00256   static const size_t value = N;
00257 };
00258 template <typename T> struct array_size;
00259 template<class T, std::size_t N> struct array_size<std::array<T,N> > {
00260   static const size_t value = N;
00261 };
00262 }  // end namespace internal
00263 }  // end namespace Eigen
00264 
00265 #endif
00266 
00267 #endif  // EIGEN_EMULATE_ARRAY_H
 All Classes Functions Variables Typedefs Enumerator