Home | History | Annotate | Download | only in util
      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 (at) 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
     29   EIGEN_STRONG_INLINE T& front() { return values[0]; }
     30   EIGEN_DEVICE_FUNC
     31   EIGEN_STRONG_INLINE const T& front() const { return values[0]; }
     32 
     33   EIGEN_DEVICE_FUNC
     34   EIGEN_STRONG_INLINE T& back() { return values[n-1]; }
     35   EIGEN_DEVICE_FUNC
     36   EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; }
     37 
     38   EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
     39   static std::size_t size() { return n; }
     40 
     41   T values[n];
     42 
     43   EIGEN_DEVICE_FUNC
     44   EIGEN_STRONG_INLINE array() { }
     45   EIGEN_DEVICE_FUNC
     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
     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
     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
     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
     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
     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
     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
    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
    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
    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
    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
    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
    160   EIGEN_STRONG_INLINE const T& back() const {
    161     eigen_assert(false && "Can't index a zero size array");
    162     return dummy;
    163   }
    164 
    165   static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; }
    166 
    167   EIGEN_DEVICE_FUNC
    168   EIGEN_STRONG_INLINE array() : dummy() { }
    169 
    170 #if EIGEN_HAS_VARIADIC_TEMPLATES
    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>
    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>
    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