1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2015 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#if defined(__CUDA_ARCH__)
15#include <cfloat>
16#include <math_constants.h>
17#endif
18
19#if EIGEN_COMP_ICC>=1600 && __cplusplus >= 201103L
20#include <cstdint>
21#endif
22
23namespace Eigen {
24
25typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
26
27/**
28 * \brief The Index type as used for the API.
29 * \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
30 * \sa \blank \ref TopicPreprocessorDirectives, StorageIndex.
31 */
32
33typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
34
35namespace internal {
36
37/** \internal
38 * \file Meta.h
39 * This file contains generic metaprogramming classes which are not specifically related to Eigen.
40 * \note In case you wonder, yes we're aware that Boost already provides all these features,
41 * we however don't want to add a dependency to Boost.
42 */
43
44// Only recent versions of ICC complain about using ptrdiff_t to hold pointers,
45// and older versions do not provide *intptr_t types.
46#if EIGEN_COMP_ICC>=1600 && __cplusplus >= 201103L
47typedef std::intptr_t IntPtr;
48typedef std::uintptr_t UIntPtr;
49#else
50typedef std::ptrdiff_t IntPtr;
51typedef std::size_t UIntPtr;
52#endif
53
54struct true_type { enum { value = 1 }; };
55struct false_type { enum { value = 0 }; };
56
57template<bool Condition, typename Then, typename Else>
58struct conditional { typedef Then type; };
59
60template<typename Then, typename Else>
61struct conditional <false, Then, Else> { typedef Else type; };
62
63template<typename T, typename U> struct is_same { enum { value = 0 }; };
64template<typename T> struct is_same<T,T> { enum { value = 1 }; };
65
66template<typename T> struct remove_reference { typedef T type; };
67template<typename T> struct remove_reference<T&> { typedef T type; };
68
69template<typename T> struct remove_pointer { typedef T type; };
70template<typename T> struct remove_pointer<T*> { typedef T type; };
71template<typename T> struct remove_pointer<T*const> { typedef T type; };
72
73template <class T> struct remove_const { typedef T type; };
74template <class T> struct remove_const<const T> { typedef T type; };
75template <class T> struct remove_const<const T[]> { typedef T type[]; };
76template <class T, unsigned int Size> struct remove_const<const T[Size]> { typedef T type[Size]; };
77
78template<typename T> struct remove_all { typedef T type; };
79template<typename T> struct remove_all<const T> { typedef typename remove_all<T>::type type; };
80template<typename T> struct remove_all<T const&> { typedef typename remove_all<T>::type type; };
81template<typename T> struct remove_all<T&> { typedef typename remove_all<T>::type type; };
82template<typename T> struct remove_all<T const*> { typedef typename remove_all<T>::type type; };
83template<typename T> struct remove_all<T*> { typedef typename remove_all<T>::type type; };
84
85template<typename T> struct is_arithmetic { enum { value = false }; };
86template<> struct is_arithmetic<float> { enum { value = true }; };
87template<> struct is_arithmetic<double> { enum { value = true }; };
88template<> struct is_arithmetic<long double> { enum { value = true }; };
89template<> struct is_arithmetic<bool> { enum { value = true }; };
90template<> struct is_arithmetic<char> { enum { value = true }; };
91template<> struct is_arithmetic<signed char> { enum { value = true }; };
92template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
93template<> struct is_arithmetic<signed short> { enum { value = true }; };
94template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
95template<> struct is_arithmetic<signed int> { enum { value = true }; };
96template<> struct is_arithmetic<unsigned int> { enum { value = true }; };
97template<> struct is_arithmetic<signed long> { enum { value = true }; };
98template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
99
100template<typename T> struct is_integral { enum { value = false }; };
101template<> struct is_integral<bool> { enum { value = true }; };
102template<> struct is_integral<char> { enum { value = true }; };
103template<> struct is_integral<signed char> { enum { value = true }; };
104template<> struct is_integral<unsigned char> { enum { value = true }; };
105template<> struct is_integral<signed short> { enum { value = true }; };
106template<> struct is_integral<unsigned short> { enum { value = true }; };
107template<> struct is_integral<signed int> { enum { value = true }; };
108template<> struct is_integral<unsigned int> { enum { value = true }; };
109template<> struct is_integral<signed long> { enum { value = true }; };
110template<> struct is_integral<unsigned long> { enum { value = true }; };
111
112#if EIGEN_HAS_CXX11
113using std::make_unsigned;
114#else
115// TODO: Possibly improve this implementation of make_unsigned.
116// It is currently used only by
117// template<typename Scalar> struct random_default_impl<Scalar, false, true>.
118template<typename> struct make_unsigned;
119template<> struct make_unsigned<char> { typedef unsigned char type; };
120template<> struct make_unsigned<signed char> { typedef unsigned char type; };
121template<> struct make_unsigned<unsigned char> { typedef unsigned char type; };
122template<> struct make_unsigned<signed short> { typedef unsigned short type; };
123template<> struct make_unsigned<unsigned short> { typedef unsigned short type; };
124template<> struct make_unsigned<signed int> { typedef unsigned int type; };
125template<> struct make_unsigned<unsigned int> { typedef unsigned int type; };
126template<> struct make_unsigned<signed long> { typedef unsigned long type; };
127template<> struct make_unsigned<unsigned long> { typedef unsigned long type; };
128#if EIGEN_COMP_MSVC
129template<> struct make_unsigned<signed __int64> { typedef unsigned __int64 type; };
130template<> struct make_unsigned<unsigned __int64> { typedef unsigned __int64 type; };
131#endif
132#endif
133
134template <typename T> struct add_const { typedef const T type; };
135template <typename T> struct add_const<T&> { typedef T& type; };
136
137template <typename T> struct is_const { enum { value = 0 }; };
138template <typename T> struct is_const<T const> { enum { value = 1 }; };
139
140template<typename T> struct add_const_on_value_type { typedef const T type; };
141template<typename T> struct add_const_on_value_type<T&> { typedef T const& type; };
142template<typename T> struct add_const_on_value_type<T*> { typedef T const* type; };
143template<typename T> struct add_const_on_value_type<T* const> { typedef T const* const type; };
144template<typename T> struct add_const_on_value_type<T const* const> { typedef T const* const type; };
145
146
147template<typename From, typename To>
148struct is_convertible_impl
149{
150private:
151 struct any_conversion
152 {
153 template <typename T> any_conversion(const volatile T&);
154 template <typename T> any_conversion(T&);
155 };
156 struct yes {int a[1];};
157 struct no {int a[2];};
158
159 static yes test(const To&, int);
160 static no test(any_conversion, ...);
161
162public:
163 static From ms_from;
164#ifdef __INTEL_COMPILER
165 #pragma warning push
166 #pragma warning ( disable : 2259 )
167#endif
168 enum { value = sizeof(test(ms_from, 0))==sizeof(yes) };
169#ifdef __INTEL_COMPILER
170 #pragma warning pop
171#endif
172};
173
174template<typename From, typename To>
175struct is_convertible
176{
177 enum { value = is_convertible_impl<typename remove_all<From>::type,
178 typename remove_all<To >::type>::value };
179};
180
181/** \internal Allows to enable/disable an overload
182 * according to a compile time condition.
183 */
184template<bool Condition, typename T=void> struct enable_if;
185
186template<typename T> struct enable_if<true,T>
187{ typedef T type; };
188
189#if defined(__CUDA_ARCH__)
190#if !defined(__FLT_EPSILON__)
191#define __FLT_EPSILON__ FLT_EPSILON
192#define __DBL_EPSILON__ DBL_EPSILON
193#endif
194
195namespace device {
196
197template<typename T> struct numeric_limits
198{
199 EIGEN_DEVICE_FUNC
200 static T epsilon() { return 0; }
201 static T (max)() { assert(false && "Highest not supported for this type"); }
202 static T (min)() { assert(false && "Lowest not supported for this type"); }
203 static T infinity() { assert(false && "Infinity not supported for this type"); }
204 static T quiet_NaN() { assert(false && "quiet_NaN not supported for this type"); }
205};
206template<> struct numeric_limits<float>
207{
208 EIGEN_DEVICE_FUNC
209 static float epsilon() { return __FLT_EPSILON__; }
210 EIGEN_DEVICE_FUNC
211 static float (max)() { return CUDART_MAX_NORMAL_F; }
212 EIGEN_DEVICE_FUNC
213 static float (min)() { return FLT_MIN; }
214 EIGEN_DEVICE_FUNC
215 static float infinity() { return CUDART_INF_F; }
216 EIGEN_DEVICE_FUNC
217 static float quiet_NaN() { return CUDART_NAN_F; }
218};
219template<> struct numeric_limits<double>
220{
221 EIGEN_DEVICE_FUNC
222 static double epsilon() { return __DBL_EPSILON__; }
223 EIGEN_DEVICE_FUNC
224 static double (max)() { return DBL_MAX; }
225 EIGEN_DEVICE_FUNC
226 static double (min)() { return DBL_MIN; }
227 EIGEN_DEVICE_FUNC
228 static double infinity() { return CUDART_INF; }
229 EIGEN_DEVICE_FUNC
230 static double quiet_NaN() { return CUDART_NAN; }
231};
232template<> struct numeric_limits<int>
233{
234 EIGEN_DEVICE_FUNC
235 static int epsilon() { return 0; }
236 EIGEN_DEVICE_FUNC
237 static int (max)() { return INT_MAX; }
238 EIGEN_DEVICE_FUNC
239 static int (min)() { return INT_MIN; }
240};
241template<> struct numeric_limits<unsigned int>
242{
243 EIGEN_DEVICE_FUNC
244 static unsigned int epsilon() { return 0; }
245 EIGEN_DEVICE_FUNC
246 static unsigned int (max)() { return UINT_MAX; }
247 EIGEN_DEVICE_FUNC
248 static unsigned int (min)() { return 0; }
249};
250template<> struct numeric_limits<long>
251{
252 EIGEN_DEVICE_FUNC
253 static long epsilon() { return 0; }
254 EIGEN_DEVICE_FUNC
255 static long (max)() { return LONG_MAX; }
256 EIGEN_DEVICE_FUNC
257 static long (min)() { return LONG_MIN; }
258};
259template<> struct numeric_limits<unsigned long>
260{
261 EIGEN_DEVICE_FUNC
262 static unsigned long epsilon() { return 0; }
263 EIGEN_DEVICE_FUNC
264 static unsigned long (max)() { return ULONG_MAX; }
265 EIGEN_DEVICE_FUNC
266 static unsigned long (min)() { return 0; }
267};
268template<> struct numeric_limits<long long>
269{
270 EIGEN_DEVICE_FUNC
271 static long long epsilon() { return 0; }
272 EIGEN_DEVICE_FUNC
273 static long long (max)() { return LLONG_MAX; }
274 EIGEN_DEVICE_FUNC
275 static long long (min)() { return LLONG_MIN; }
276};
277template<> struct numeric_limits<unsigned long long>
278{
279 EIGEN_DEVICE_FUNC
280 static unsigned long long epsilon() { return 0; }
281 EIGEN_DEVICE_FUNC
282 static unsigned long long (max)() { return ULLONG_MAX; }
283 EIGEN_DEVICE_FUNC
284 static unsigned long long (min)() { return 0; }
285};
286
287}
288
289#endif
290
291/** \internal
292 * A base class do disable default copy ctor and copy assignement operator.
293 */
294class noncopyable
295{
296 EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
297 EIGEN_DEVICE_FUNC const noncopyable& operator=(const noncopyable&);
298protected:
299 EIGEN_DEVICE_FUNC noncopyable() {}
300 EIGEN_DEVICE_FUNC ~noncopyable() {}
301};
302
303/** \internal
304 * Convenient struct to get the result type of a unary or binary functor.
305 *
306 * It supports both the current STL mechanism (using the result_type member) as well as
307 * upcoming next STL generation (using a templated result member).
308 * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
309 */
310#if EIGEN_HAS_STD_RESULT_OF
311template<typename T> struct result_of {
312 typedef typename std::result_of<T>::type type1;
313 typedef typename remove_all<type1>::type type;
314};
315#else
316template<typename T> struct result_of { };
317
318struct has_none {int a[1];};
319struct has_std_result_type {int a[2];};
320struct has_tr1_result {int a[3];};
321
322template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
323struct unary_result_of_select {typedef typename internal::remove_all<ArgType>::type type;};
324
325template<typename Func, typename ArgType>
326struct unary_result_of_select<Func, ArgType, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
327
328template<typename Func, typename ArgType>
329struct unary_result_of_select<Func, ArgType, sizeof(has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
330
331template<typename Func, typename ArgType>
332struct result_of<Func(ArgType)> {
333 template<typename T>
334 static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
335 template<typename T>
336 static has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType)>::type const * = 0);
337 static has_none testFunctor(...);
338
339 // note that the following indirection is needed for gcc-3.3
340 enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
341 typedef typename unary_result_of_select<Func, ArgType, FunctorType>::type type;
342};
343
344template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(has_none)>
345struct binary_result_of_select {typedef typename internal::remove_all<ArgType0>::type type;};
346
347template<typename Func, typename ArgType0, typename ArgType1>
348struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_std_result_type)>
349{typedef typename Func::result_type type;};
350
351template<typename Func, typename ArgType0, typename ArgType1>
352struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_tr1_result)>
353{typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
354
355template<typename Func, typename ArgType0, typename ArgType1>
356struct result_of<Func(ArgType0,ArgType1)> {
357 template<typename T>
358 static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
359 template<typename T>
360 static has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1)>::type const * = 0);
361 static has_none testFunctor(...);
362
363 // note that the following indirection is needed for gcc-3.3
364 enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
365 typedef typename binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
366};
367
368template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2, int SizeOf=sizeof(has_none)>
369struct ternary_result_of_select {typedef typename internal::remove_all<ArgType0>::type type;};
370
371template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
372struct ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, sizeof(has_std_result_type)>
373{typedef typename Func::result_type type;};
374
375template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
376struct ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, sizeof(has_tr1_result)>
377{typedef typename Func::template result<Func(ArgType0,ArgType1,ArgType2)>::type type;};
378
379template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
380struct result_of<Func(ArgType0,ArgType1,ArgType2)> {
381 template<typename T>
382 static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
383 template<typename T>
384 static has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1,ArgType2)>::type const * = 0);
385 static has_none testFunctor(...);
386
387 // note that the following indirection is needed for gcc-3.3
388 enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
389 typedef typename ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, FunctorType>::type type;
390};
391#endif
392
393struct meta_yes { char a[1]; };
394struct meta_no { char a[2]; };
395
396// Check whether T::ReturnType does exist
397template <typename T>
398struct has_ReturnType
399{
400 template <typename C> static meta_yes testFunctor(typename C::ReturnType const *);
401 template <typename C> static meta_no testFunctor(...);
402
403 enum { value = sizeof(testFunctor<T>(0)) == sizeof(meta_yes) };
404};
405
406template<typename T> const T* return_ptr();
407
408template <typename T, typename IndexType=Index>
409struct has_nullary_operator
410{
411 template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()())>0)>::type * = 0);
412 static meta_no testFunctor(...);
413
414 enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
415};
416
417template <typename T, typename IndexType=Index>
418struct has_unary_operator
419{
420 template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()(IndexType(0)))>0)>::type * = 0);
421 static meta_no testFunctor(...);
422
423 enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
424};
425
426template <typename T, typename IndexType=Index>
427struct has_binary_operator
428{
429 template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()(IndexType(0),IndexType(0)))>0)>::type * = 0);
430 static meta_no testFunctor(...);
431
432 enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
433};
434
435/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
436 * Usage example: \code meta_sqrt<1023>::ret \endcode
437 */
438template<int Y,
439 int InfX = 0,
440 int SupX = ((Y==1) ? 1 : Y/2),
441 bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
442 // use ?: instead of || just to shut up a stupid gcc 4.3 warning
443class meta_sqrt
444{
445 enum {
446 MidX = (InfX+SupX)/2,
447 TakeInf = MidX*MidX > Y ? 1 : 0,
448 NewInf = int(TakeInf) ? InfX : int(MidX),
449 NewSup = int(TakeInf) ? int(MidX) : SupX
450 };
451 public:
452 enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
453};
454
455template<int Y, int InfX, int SupX>
456class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
457
458
459/** \internal Computes the least common multiple of two positive integer A and B
460 * at compile-time. It implements a naive algorithm testing all multiples of A.
461 * It thus works better if A>=B.
462 */
463template<int A, int B, int K=1, bool Done = ((A*K)%B)==0>
464struct meta_least_common_multiple
465{
466 enum { ret = meta_least_common_multiple<A,B,K+1>::ret };
467};
468template<int A, int B, int K>
469struct meta_least_common_multiple<A,B,K,true>
470{
471 enum { ret = A*K };
472};
473
474/** \internal determines whether the product of two numeric types is allowed and what the return type is */
475template<typename T, typename U> struct scalar_product_traits
476{
477 enum { Defined = 0 };
478};
479
480// FIXME quick workaround around current limitation of result_of
481// template<typename Scalar, typename ArgType0, typename ArgType1>
482// struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
483// typedef typename scalar_product_traits<typename remove_all<ArgType0>::type, typename remove_all<ArgType1>::type>::ReturnType type;
484// };
485
486} // end namespace internal
487
488namespace numext {
489
490#if defined(__CUDA_ARCH__)
491template<typename T> EIGEN_DEVICE_FUNC void swap(T &a, T &b) { T tmp = b; b = a; a = tmp; }
492#else
493template<typename T> EIGEN_STRONG_INLINE void swap(T &a, T &b) { std::swap(a,b); }
494#endif
495
496#if defined(__CUDA_ARCH__)
497using internal::device::numeric_limits;
498#else
499using std::numeric_limits;
500#endif
501
502// Integer division with rounding up.
503// T is assumed to be an integer type with a>=0, and b>0
504template<typename T>
505T div_ceil(const T &a, const T &b)
506{
507 return (a+b-1) / b;
508}
509
510// The aim of the following functions is to bypass -Wfloat-equal warnings
511// when we really want a strict equality comparison on floating points.
512template<typename X, typename Y> EIGEN_STRONG_INLINE
513bool equal_strict(const X& x,const Y& y) { return x == y; }
514
515template<> EIGEN_STRONG_INLINE
516bool equal_strict(const float& x,const float& y) { return std::equal_to<float>()(x,y); }
517
518template<> EIGEN_STRONG_INLINE
519bool equal_strict(const double& x,const double& y) { return std::equal_to<double>()(x,y); }
520
521template<typename X, typename Y> EIGEN_STRONG_INLINE
522bool not_equal_strict(const X& x,const Y& y) { return x != y; }
523
524template<> EIGEN_STRONG_INLINE
525bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to<float>()(x,y); }
526
527template<> EIGEN_STRONG_INLINE
528bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to<double>()(x,y); }
529
530} // end namespace numext
531
532} // end namespace Eigen
533
534#endif // EIGEN_META_H
535