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@inria.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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   enum { Defined = 0 };
192 };
193 
194 template<typename T> struct scalar_product_traits<T,T>
195 {
196   enum {
197     // Cost = NumTraits<T>::MulCost,
198     Defined = 1
199   };
200   typedef T ReturnType;
201 };
202 
203 template<typename T> struct scalar_product_traits<T,std::complex<T> >
204 {
205   enum {
206     // Cost = 2*NumTraits<T>::MulCost,
207     Defined = 1
208   };
209   typedef std::complex<T> ReturnType;
210 };
211 
212 template<typename T> struct scalar_product_traits<std::complex<T>, T>
213 {
214   enum {
215     // Cost = 2*NumTraits<T>::MulCost,
216     Defined = 1
217   };
218   typedef std::complex<T> ReturnType;
219 };
220 
221 // FIXME quick workaround around current limitation of result_of
222 // template<typename Scalar, typename ArgType0, typename ArgType1>
223 // struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
224 // typedef typename scalar_product_traits<typename remove_all<ArgType0>::type, typename remove_all<ArgType1>::type>::ReturnType type;
225 // };
226 
227 template<typename T> struct is_diagonal
228 { enum { ret = false }; };
229 
230 template<typename T> struct is_diagonal<DiagonalBase<T> >
231 { enum { ret = true }; };
232 
233 template<typename T> struct is_diagonal<DiagonalWrapper<T> >
234 { enum { ret = true }; };
235 
236 template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
237 { enum { ret = true }; };
238 
239 } // end namespace internal
240 
241 } // end namespace Eigen
242 
243 #endif // EIGEN_META_H
244