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) 2008-2009 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1 (at) gmail.com>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_META_H
     12 #define EIGEN_META_H
     13 
     14 namespace Eigen {
     15 
     16 namespace internal {
     17 
     18 /** \internal
     19   * \file Meta.h
     20   * This file contains generic metaprogramming classes which are not specifically related to Eigen.
     21   * \note In case you wonder, yes we're aware that Boost already provides all these features,
     22   * we however don't want to add a dependency to Boost.
     23   */
     24 
     25 struct true_type {  enum { value = 1 }; };
     26 struct false_type { enum { value = 0 }; };
     27 
     28 template<bool Condition, typename Then, typename Else>
     29 struct conditional { typedef Then type; };
     30 
     31 template<typename Then, typename Else>
     32 struct conditional <false, Then, Else> { typedef Else type; };
     33 
     34 template<typename T, typename U> struct is_same { enum { value = 0 }; };
     35 template<typename T> struct is_same<T,T> { enum { value = 1 }; };
     36 
     37 template<typename T> struct remove_reference { typedef T type; };
     38 template<typename T> struct remove_reference<T&> { typedef T type; };
     39 
     40 template<typename T> struct remove_pointer { typedef T type; };
     41 template<typename T> struct remove_pointer<T*> { typedef T type; };
     42 template<typename T> struct remove_pointer<T*const> { typedef T type; };
     43 
     44 template <class T> struct remove_const { typedef T type; };
     45 template <class T> struct remove_const<const T> { typedef T type; };
     46 template <class T> struct remove_const<const T[]> { typedef T type[]; };
     47 template <class T, unsigned int Size> struct remove_const<const T[Size]> { typedef T type[Size]; };
     48 
     49 template<typename T> struct remove_all { typedef T type; };
     50 template<typename T> struct remove_all<const T>   { typedef typename remove_all<T>::type type; };
     51 template<typename T> struct remove_all<T const&>  { typedef typename remove_all<T>::type type; };
     52 template<typename T> struct remove_all<T&>        { typedef typename remove_all<T>::type type; };
     53 template<typename T> struct remove_all<T const*>  { typedef typename remove_all<T>::type type; };
     54 template<typename T> struct remove_all<T*>        { typedef typename remove_all<T>::type type; };
     55 
     56 template<typename T> struct is_arithmetic      { enum { value = false }; };
     57 template<> struct is_arithmetic<float>         { enum { value = true }; };
     58 template<> struct is_arithmetic<double>        { enum { value = true }; };
     59 template<> struct is_arithmetic<long double>   { enum { value = true }; };
     60 template<> struct is_arithmetic<bool>          { enum { value = true }; };
     61 template<> struct is_arithmetic<char>          { enum { value = true }; };
     62 template<> struct is_arithmetic<signed char>   { enum { value = true }; };
     63 template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
     64 template<> struct is_arithmetic<signed short>  { enum { value = true }; };
     65 template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
     66 template<> struct is_arithmetic<signed int>    { enum { value = true }; };
     67 template<> struct is_arithmetic<unsigned int>  { enum { value = true }; };
     68 template<> struct is_arithmetic<signed long>   { enum { value = true }; };
     69 template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
     70 
     71 template <typename T> struct add_const { typedef const T type; };
     72 template <typename T> struct add_const<T&> { typedef T& type; };
     73 
     74 template <typename T> struct is_const { enum { value = 0 }; };
     75 template <typename T> struct is_const<T const> { enum { value = 1 }; };
     76 
     77 template<typename T> struct add_const_on_value_type            { typedef const T type;  };
     78 template<typename T> struct add_const_on_value_type<T&>        { typedef T const& type; };
     79 template<typename T> struct add_const_on_value_type<T*>        { typedef T const* type; };
     80 template<typename T> struct add_const_on_value_type<T* const>  { typedef T const* const type; };
     81 template<typename T> struct add_const_on_value_type<T const* const>  { typedef T const* const type; };
     82 
     83 /** \internal Allows to enable/disable an overload
     84   * according to a compile time condition.
     85   */
     86 template<bool Condition, typename T> struct enable_if;
     87 
     88 template<typename T> struct enable_if<true,T>
     89 { typedef T type; };
     90 
     91 
     92 
     93 /** \internal
     94   * A base class do disable default copy ctor and copy assignement operator.
     95   */
     96 class noncopyable
     97 {
     98   noncopyable(const noncopyable&);
     99   const noncopyable& operator=(const noncopyable&);
    100 protected:
    101   noncopyable() {}
    102   ~noncopyable() {}
    103 };
    104 
    105 
    106 /** \internal
    107   * Convenient struct to get the result type of a unary or binary functor.
    108   *
    109   * It supports both the current STL mechanism (using the result_type member) as well as
    110   * upcoming next STL generation (using a templated result member).
    111   * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
    112   */
    113 template<typename T> struct result_of {};
    114 
    115 struct has_none {int a[1];};
    116 struct has_std_result_type {int a[2];};
    117 struct has_tr1_result {int a[3];};
    118 
    119 template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
    120 struct unary_result_of_select {typedef ArgType type;};
    121 
    122 template<typename Func, typename ArgType>
    123 struct unary_result_of_select<Func, ArgType, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
    124 
    125 template<typename Func, typename ArgType>
    126 struct unary_result_of_select<Func, ArgType, sizeof(has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
    127 
    128 template<typename Func, typename ArgType>
    129 struct result_of<Func(ArgType)> {
    130     template<typename T>
    131     static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
    132     template<typename T>
    133     static has_tr1_result      testFunctor(T const *, typename T::template result<T(ArgType)>::type const * = 0);
    134     static has_none            testFunctor(...);
    135 
    136     // note that the following indirection is needed for gcc-3.3
    137     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
    138     typedef typename unary_result_of_select<Func, ArgType, FunctorType>::type type;
    139 };
    140 
    141 template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(has_none)>
    142 struct binary_result_of_select {typedef ArgType0 type;};
    143 
    144 template<typename Func, typename ArgType0, typename ArgType1>
    145 struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_std_result_type)>
    146 {typedef typename Func::result_type type;};
    147 
    148 template<typename Func, typename ArgType0, typename ArgType1>
    149 struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_tr1_result)>
    150 {typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
    151 
    152 template<typename Func, typename ArgType0, typename ArgType1>
    153 struct result_of<Func(ArgType0,ArgType1)> {
    154     template<typename T>
    155     static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
    156     template<typename T>
    157     static has_tr1_result      testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1)>::type const * = 0);
    158     static has_none            testFunctor(...);
    159 
    160     // note that the following indirection is needed for gcc-3.3
    161     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
    162     typedef typename binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
    163 };
    164 
    165 /** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
    166   * Usage example: \code meta_sqrt<1023>::ret \endcode
    167   */
    168 template<int Y,
    169          int InfX = 0,
    170          int SupX = ((Y==1) ? 1 : Y/2),
    171          bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
    172                                 // use ?: instead of || just to shut up a stupid gcc 4.3 warning
    173 class meta_sqrt
    174 {
    175     enum {
    176       MidX = (InfX+SupX)/2,
    177       TakeInf = MidX*MidX > Y ? 1 : 0,
    178       NewInf = int(TakeInf) ? InfX : int(MidX),
    179       NewSup = int(TakeInf) ? int(MidX) : SupX
    180     };
    181   public:
    182     enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
    183 };
    184 
    185 template<int Y, int InfX, int SupX>
    186 class meta_sqrt<Y, InfX, SupX, true> { public:  enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
    187 
    188 /** \internal determines whether the product of two numeric types is allowed and what the return type is */
    189 template<typename T, typename U> struct scalar_product_traits;
    190 
    191 template<typename T> struct scalar_product_traits<T,T>
    192 {
    193   //enum { Cost = NumTraits<T>::MulCost };
    194   typedef T ReturnType;
    195 };
    196 
    197 template<typename T> struct scalar_product_traits<T,std::complex<T> >
    198 {
    199   //enum { Cost = 2*NumTraits<T>::MulCost };
    200   typedef std::complex<T> ReturnType;
    201 };
    202 
    203 template<typename T> struct scalar_product_traits<std::complex<T>, T>
    204 {
    205   //enum { Cost = 2*NumTraits<T>::MulCost  };
    206   typedef std::complex<T> ReturnType;
    207 };
    208 
    209 // FIXME quick workaround around current limitation of result_of
    210 // template<typename Scalar, typename ArgType0, typename ArgType1>
    211 // struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
    212 // typedef typename scalar_product_traits<typename remove_all<ArgType0>::type, typename remove_all<ArgType1>::type>::ReturnType type;
    213 // };
    214 
    215 template<typename T> struct is_diagonal
    216 { enum { ret = false }; };
    217 
    218 template<typename T> struct is_diagonal<DiagonalBase<T> >
    219 { enum { ret = true }; };
    220 
    221 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
    222 { enum { ret = true }; };
    223 
    224 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
    225 { enum { ret = true }; };
    226 
    227 } // end namespace internal
    228 
    229 } // end namespace Eigen
    230 
    231 #endif // EIGEN_META_H
    232