Meta.h revision c981c48f5bc9aefeffc0bcb0cc3934c2fae179dd
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This file is part of Eigen, a lightweight C++ template library
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// for linear algebra.
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This Source Code Form is subject to the terms of the Mozilla
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Public License v. 2.0. If a copy of the MPL was not distributed
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef EIGEN_META_H
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#define EIGEN_META_H
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace Eigen {
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace internal {
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/** \internal
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  * \file Meta.h
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  * This file contains generic metaprogramming classes which are not specifically related to Eigen.
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  * \note In case you wonder, yes we're aware that Boost already provides all these features,
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  * we however don't want to add a dependency to Boost.
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  */
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct true_type {  enum { value = 1 }; };
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct false_type { enum { value = 0 }; };
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<bool Condition, typename Then, typename Else>
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct conditional { typedef Then type; };
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename Then, typename Else>
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct conditional <false, Then, Else> { typedef Else type; };
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template<typename T, typename U> struct is_same { enum { value = 0 }; };
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct is_same<T,T> { enum { value = 1 }; };
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct remove_reference { typedef T type; };
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct remove_reference<T&> { typedef T type; };
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct remove_pointer { typedef T type; };
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<typename T> struct remove_pointer<T*> { typedef T type; };
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct remove_pointer<T*const> { typedef T type; };
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template <class T> struct remove_const { typedef T type; };
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template <class T> struct remove_const<const T> { typedef T type; };
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template <class T> struct remove_const<const T[]> { typedef T type[]; };
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template <class T, unsigned int Size> struct remove_const<const T[Size]> { typedef T type[Size]; };
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template<typename T> struct remove_all { typedef T type; };
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template<typename T> struct remove_all<const T>   { typedef typename remove_all<T>::type type; };
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template<typename T> struct remove_all<T const&>  { typedef typename remove_all<T>::type type; };
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template<typename T> struct remove_all<T&>        { typedef typename remove_all<T>::type type; };
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<typename T> struct remove_all<T const*>  { typedef typename remove_all<T>::type type; };
5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template<typename T> struct remove_all<T*>        { typedef typename remove_all<T>::type type; };
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<typename T> struct is_arithmetic      { enum { value = false }; };
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<> struct is_arithmetic<float>         { enum { value = true }; };
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<double>        { enum { value = true }; };
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<long double>   { enum { value = true }; };
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template<> struct is_arithmetic<bool>          { enum { value = true }; };
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template<> struct is_arithmetic<char>          { enum { value = true }; };
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<signed char>   { enum { value = true }; };
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<signed short>  { enum { value = true }; };
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<> struct is_arithmetic<signed int>    { enum { value = true }; };
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<> struct is_arithmetic<unsigned int>  { enum { value = true }; };
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<> struct is_arithmetic<signed long>   { enum { value = true }; };
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <typename T> struct add_const { typedef const T type; };
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template <typename T> struct add_const<T&> { typedef T& type; };
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template <typename T> struct is_const { enum { value = 0 }; };
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <typename T> struct is_const<T const> { enum { value = 1 }; };
766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template<typename T> struct add_const_on_value_type            { typedef const T type;  };
786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template<typename T> struct add_const_on_value_type<T&>        { typedef T const& type; };
796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template<typename T> struct add_const_on_value_type<T*>        { typedef T const* type; };
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T> struct add_const_on_value_type<T* const>  { typedef T const* const type; };
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T> struct add_const_on_value_type<T const* const>  { typedef T const* const type; };
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** \internal Allows to enable/disable an overload
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * according to a compile time condition.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  */
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<bool Condition, typename T> struct enable_if;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T> struct enable_if<true,T>
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){ typedef T type; };
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** \internal
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * A base class do disable default copy ctor and copy assignement operator.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  */
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class noncopyable
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  noncopyable(const noncopyable&);
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const noncopyable& operator=(const noncopyable&);
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)protected:
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  noncopyable() {}
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ~noncopyable() {}
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** \internal
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * Convenient struct to get the result type of a unary or binary functor.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * It supports both the current STL mechanism (using the result_type member) as well as
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * upcoming next STL generation (using a templated result member).
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  */
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T> struct result_of {};
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct has_none {int a[1];};
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct has_std_result_type {int a[2];};
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct has_tr1_result {int a[3];};
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct unary_result_of_select {typedef ArgType type;};
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename Func, typename ArgType>
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct unary_result_of_select<Func, ArgType, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename Func, typename ArgType>
126struct unary_result_of_select<Func, ArgType, sizeof(has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
127
128template<typename Func, typename ArgType>
129struct 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
141template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(has_none)>
142struct binary_result_of_select {typedef ArgType0 type;};
143
144template<typename Func, typename ArgType0, typename ArgType1>
145struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_std_result_type)>
146{typedef typename Func::result_type type;};
147
148template<typename Func, typename ArgType0, typename ArgType1>
149struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_tr1_result)>
150{typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
151
152template<typename Func, typename ArgType0, typename ArgType1>
153struct 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  */
168template<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
173class 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
185template<int Y, int InfX, int SupX>
186class 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 */
189template<typename T, typename U> struct scalar_product_traits;
190
191template<typename T> struct scalar_product_traits<T,T>
192{
193  //enum { Cost = NumTraits<T>::MulCost };
194  typedef T ReturnType;
195};
196
197template<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
203template<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
215template<typename T> struct is_diagonal
216{ enum { ret = false }; };
217
218template<typename T> struct is_diagonal<DiagonalBase<T> >
219{ enum { ret = true }; };
220
221template<typename T> struct is_diagonal<DiagonalWrapper<T> >
222{ enum { ret = true }; };
223
224template<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