ROOT  6.06/09
Reference Guide
types.h
Go to the documentation of this file.
1 /* This file is part of the Vc library. {{{
2 
3  Copyright (C) 2012 Matthias Kretz <kretz@kde.org>
4 
5  Vc is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as
7  published by the Free Software Foundation, either version 3 of
8  the License, or (at your option) any later version.
9 
10  Vc is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with Vc. If not, see <http://www.gnu.org/licenses/>.
17 
18 }}}*/
19 
20 #ifndef VC_COMMON_TYPES_H
21 #define VC_COMMON_TYPES_H
22 
23 #ifdef VC_CHECK_ALIGNMENT
24 #include <cstdlib>
25 #include <cstdio>
26 #endif
27 
28 namespace ROOT {
29 namespace Vc
30 {
31 
32 // helper type to implement sfloat_v (Vector<Vc::sfloat>)
33 struct sfloat {};
34 
35 template<typename T> struct DetermineEntryType { typedef T Type; };
36 template<> struct DetermineEntryType<sfloat> { typedef float Type; };
37 
38 template<typename T> struct NegateTypeHelper { typedef T Type; };
39 template<> struct NegateTypeHelper<unsigned char > { typedef char Type; };
40 template<> struct NegateTypeHelper<unsigned short> { typedef short Type; };
41 template<> struct NegateTypeHelper<unsigned int > { typedef int Type; };
42 
43 namespace VectorSpecialInitializerZero { enum ZEnum { Zero = 0 }; }
44 namespace VectorSpecialInitializerOne { enum OEnum { One = 1 }; }
45 namespace VectorSpecialInitializerIndexesFromZero { enum IEnum { IndexesFromZero }; }
46 
47 template<typename V, size_t Size1, size_t Size2> class Memory;
48 #ifdef VC_MSVC
49 # if defined(VC_IMPL_Scalar)
50 namespace Scalar {
51  template<typename T> class Vector;
52  template<unsigned int VectorSize> class Mask;
53 }
54 #define _Vector Vc::Scalar::Vector
55 # elif defined(VC_IMPL_SSE)
56 namespace SSE {
57  template<typename T> class Vector;
58  template<unsigned int VectorSize> class Mask;
59  class Float8Mask;
60 }
61 #define _Vector Vc::SSE::Vector
62 # elif defined(VC_IMPL_AVX)
63 namespace AVX {
64  template<typename T> class Vector;
65  template<unsigned int VectorSize, size_t RegisterWidth> class Mask;
66 }
67 #define _Vector Vc::AVX::Vector
68 # else
69 # error "Sorry, MSVC is a nasty compiler and needs extra care. Please help."
70 # endif
71 #endif
72 namespace
73 {
74  template<bool Test, typename T = void> struct EnableIf { typedef T Value; };
75  template<typename T> struct EnableIf<false, T> {};
76 
77  template<typename T> struct IsSignedInteger { enum { Value = 0 }; };
78  template<> struct IsSignedInteger<signed char> { enum { Value = 1 }; };
79  template<> struct IsSignedInteger<short> { enum { Value = 1 }; };
80  template<> struct IsSignedInteger<int> { enum { Value = 1 }; };
81  template<> struct IsSignedInteger<long> { enum { Value = 1 }; };
82  template<> struct IsSignedInteger<long long> { enum { Value = 1 }; };
83 
84  template<typename T> struct IsUnsignedInteger { enum { Value = 0 }; };
85  template<> struct IsUnsignedInteger<unsigned char> { enum { Value = 1 }; };
86  template<> struct IsUnsignedInteger<unsigned short> { enum { Value = 1 }; };
87  template<> struct IsUnsignedInteger<unsigned int> { enum { Value = 1 }; };
88  template<> struct IsUnsignedInteger<unsigned long> { enum { Value = 1 }; };
89  template<> struct IsUnsignedInteger<unsigned long long> { enum { Value = 1 }; };
90 
91  template<typename T> struct IsInteger { enum { Value = IsSignedInteger<T>::Value | IsUnsignedInteger<T>::Value }; };
92 
93  template<typename T> struct IsReal { enum { Value = 0 }; };
94  template<> struct IsReal<float> { enum { Value = 1 }; };
95  template<> struct IsReal<double> { enum { Value = 1 }; };
96 
97  template<typename T, typename U> struct IsEqualType { enum { Value = 0 }; };
98  template<typename T> struct IsEqualType<T, T> { enum { Value = 1 }; };
99 
100  template<typename T, typename List0, typename List1 = void, typename List2 = void, typename List3 = void, typename List4 = void, typename List5 = void, typename List6 = void>
101  struct IsInTypelist { enum { Value = false }; };
102  template<typename T, typename List1, typename List2, typename List3, typename List4, typename List5, typename List6> struct IsInTypelist<T, T, List1, List2, List3, List4, List5, List6> { enum { Value = true }; };
103  template<typename T, typename List0, typename List2, typename List3, typename List4, typename List5, typename List6> struct IsInTypelist<T, List0, T, List2, List3, List4, List5, List6> { enum { Value = true }; };
104  template<typename T, typename List0, typename List1, typename List3, typename List4, typename List5, typename List6> struct IsInTypelist<T, List0, List1, T, List3, List4, List5, List6> { enum { Value = true }; };
105  template<typename T, typename List0, typename List1, typename List2, typename List4, typename List5, typename List6> struct IsInTypelist<T, List0, List1, List2, T, List4, List5, List6> { enum { Value = true }; };
106  template<typename T, typename List0, typename List1, typename List2, typename List3, typename List5, typename List6> struct IsInTypelist<T, List0, List1, List2, List3, T, List5, List6> { enum { Value = true }; };
107  template<typename T, typename List0, typename List1, typename List2, typename List3, typename List4, typename List6> struct IsInTypelist<T, List0, List1, List2, List3, List4, T, List6> { enum { Value = true }; };
108  template<typename T, typename List0, typename List1, typename List2, typename List3, typename List4, typename List5> struct IsInTypelist<T, List0, List1, List2, List3, List4, List5, T> { enum { Value = true }; };
109 
110  template<typename Arg0, typename Arg1, typename T0, typename T1> struct IsCombinationOf { enum { Value = false }; };
111  template<typename Arg0, typename Arg1> struct IsCombinationOf<Arg0, Arg1, Arg0, Arg1> { enum { Value = true }; };
112  template<typename Arg0, typename Arg1> struct IsCombinationOf<Arg0, Arg1, Arg1, Arg0> { enum { Value = true }; };
113 
114  namespace
115  {
116  struct yes { char x; };
117  struct no { yes x, y; };
118  } // anonymous namespace
119 
120  template<typename From, typename To> struct HasImplicitCast
121  {
122 #ifdef VC_MSVC
123  // MSVC can't compile this code if we pass a type that has large alignment restrictions by
124  // value
125  // clang OTOH warns about this code if we pass a null-reference, thus we ifdef the const-ref
126  // for MSVC only
127  static yes test(const To &) { return yes(); }
128 #else
129  static yes test( To) { return yes(); }
130 #endif
131  static no test(...) { return no(); }
132  enum {
133 #ifdef VC_MSVC
134  // I want to test whether implicit cast works. If it works MSVC thinks it should give a warning. Wrong. Shut up.
135 #pragma warning(suppress : 4257 4267)
136 #endif
137  Value = !!(sizeof(test(*static_cast<From *>(0))) == sizeof(yes))
138  };
139  };
140 #if defined(VC_GCC) && VC_GCC < 0x40300
141  // GCC 4.1 is very noisy because of the float->int and double->int type trait tests. We get
142  // around this noise with a little specialization.
143  template<> struct HasImplicitCast<float , int> { enum { Value = true }; };
144  template<> struct HasImplicitCast<double, int> { enum { Value = true }; };
145 #endif
146 
147 #ifdef VC_MSVC
148  // MSVC is such a broken compiler :'(
149  // HasImplicitCast breaks if From has an __declspec(align(#)) modifier and has no implicit cast
150  // to To. That's because it'll call test(...) as test(From) and not test(const From &).
151  // This results in C2718. And MSVC is too stupid to see that it should just shut up and
152  // everybody would be happy.
153  //
154  // Because the HasImplicitCast specializations can only be implemented after the Vector class
155  // was declared we have to write some nasty hacks.
156  template<typename T1, typename T2> struct HasImplicitCast<_Vector<T1>, T2> { enum { Value = false }; };
157 #if defined(VC_IMPL_Scalar)
158  template<unsigned int VS, typename T2> struct HasImplicitCast<Vc::Scalar::Mask<VS>, T2> { enum { Value = false }; };
159  template<unsigned int VS> struct HasImplicitCast<Vc::Scalar::Mask<VS>, Vc::Scalar::Mask<VS> > { enum { Value = true }; };
160 #elif defined(VC_IMPL_SSE)
161  template<unsigned int VS, typename T2> struct HasImplicitCast<Vc::SSE::Mask<VS>, T2> { enum { Value = false }; };
162  template<unsigned int VS> struct HasImplicitCast<Vc::SSE::Mask<VS>, Vc::SSE::Mask<VS> > { enum { Value = true }; };
163  template<typename T2> struct HasImplicitCast<Vc::SSE::Float8Mask, T2> { enum { Value = false }; };
164  template<> struct HasImplicitCast<Vc::SSE::Float8Mask, Vc::SSE::Float8Mask> { enum { Value = true }; };
165 #elif defined(VC_IMPL_AVX)
166  template<unsigned int VectorSize, size_t RegisterWidth, typename T2> struct HasImplicitCast<Vc::AVX::Mask<VectorSize, RegisterWidth>, T2> { enum { Value = false }; };
167  template<unsigned int VectorSize, size_t RegisterWidth> struct HasImplicitCast<Vc::AVX::Mask<VectorSize, RegisterWidth>, Vc::AVX::Mask<VectorSize, RegisterWidth> > { enum { Value = true }; };
168 #endif
169  template<typename T> struct HasImplicitCast<_Vector<T>, _Vector<T> > { enum { Value = true }; };
170  //template<> struct HasImplicitCast<_Vector< int>, _Vector< unsigned int>> { enum { Value = true }; };
171  //template<> struct HasImplicitCast<_Vector< unsigned int>, _Vector< int>> { enum { Value = true }; };
172  //template<> struct HasImplicitCast<_Vector< short>, _Vector<unsigned short>> { enum { Value = true }; };
173  //template<> struct HasImplicitCast<_Vector<unsigned short>, _Vector< short>> { enum { Value = true }; };
174  template<typename V, size_t Size1, size_t Size2, typename T2> struct HasImplicitCast<Vc::Memory<V, Size1, Size2>, T2> { enum { Value = false }; };
175  template<typename V, size_t Size1, size_t Size2> struct HasImplicitCast<Vc::Memory<V, Size1, Size2>, Vc::Memory<V, Size1, Size2> > { enum { Value = true }; };
176 #undef _Vector
177 #endif
178 
179  template<typename T> struct CanConvertToInt : public HasImplicitCast<T, int> {};
180  template<> struct CanConvertToInt<bool> { enum { Value = 0 }; };
181  //template<> struct CanConvertToInt<float> { enum { Value = 0 }; };
182  //template<> struct CanConvertToInt<double> { enum { Value = 0 }; };
183 
184  enum TestEnum {};
185  VC_STATIC_ASSERT(CanConvertToInt<int>::Value == 1, CanConvertToInt_is_broken);
186  VC_STATIC_ASSERT(CanConvertToInt<unsigned char>::Value == 1, CanConvertToInt_is_broken);
187  VC_STATIC_ASSERT(CanConvertToInt<bool>::Value == 0, CanConvertToInt_is_broken);
188  VC_STATIC_ASSERT(CanConvertToInt<float>::Value == 1, CanConvertToInt_is_broken);
189  VC_STATIC_ASSERT(CanConvertToInt<double>::Value == 1, CanConvertToInt_is_broken);
190  VC_STATIC_ASSERT(CanConvertToInt<float*>::Value == 0, CanConvertToInt_is_broken);
191  VC_STATIC_ASSERT(CanConvertToInt<TestEnum>::Value == 1, CanConvertToInt_is_broken);
192 
193  typedef HasImplicitCast<TestEnum, short> HasImplicitCastTest0;
194  typedef HasImplicitCast<int *, void *> HasImplicitCastTest1;
195  typedef HasImplicitCast<int *, const void *> HasImplicitCastTest2;
196  typedef HasImplicitCast<const int *, const void *> HasImplicitCastTest3;
197  typedef HasImplicitCast<const int *, int *> HasImplicitCastTest4;
198 
199  VC_STATIC_ASSERT(HasImplicitCastTest0::Value == true, HasImplicitCast0_is_broken);
200  VC_STATIC_ASSERT(HasImplicitCastTest1::Value == true, HasImplicitCast1_is_broken);
201  VC_STATIC_ASSERT(HasImplicitCastTest2::Value == true, HasImplicitCast2_is_broken);
202  VC_STATIC_ASSERT(HasImplicitCastTest3::Value == true, HasImplicitCast3_is_broken);
203  VC_STATIC_ASSERT(HasImplicitCastTest4::Value == false, HasImplicitCast4_is_broken);
204 
205  template<typename T> struct IsLikeInteger { enum { Value = !IsReal<T>::Value && CanConvertToInt<T>::Value }; };
206  template<typename T> struct IsLikeSignedInteger { enum { Value = IsLikeInteger<T>::Value && !IsUnsignedInteger<T>::Value }; };
207 } // anonymous namespace
208 
209 #ifndef VC_CHECK_ALIGNMENT
210 template<typename _T> static Vc_ALWAYS_INLINE void assertCorrectAlignment(const _T *){}
211 #else
212 template<typename _T> static Vc_ALWAYS_INLINE void assertCorrectAlignment(const _T *ptr)
213 {
214  const size_t s = Vc_ALIGNOF(_T);
215  if((reinterpret_cast<size_t>(ptr) & ((s ^ (s & (s - 1))) - 1)) != 0) {
216  fprintf(stderr, "A vector with incorrect alignment has just been created. Look at the stacktrace to find the guilty object.\n");
217  abort();
218  }
219 }
220 #endif
221 
222 } // namespace Vc
223 } // namespace ROOT
224 
225 #endif // VC_COMMON_TYPES_H
yes y
Definition: types.h:117
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
double T(double x)
Definition: ChebyshevPol.h:34
ClassImp(TIterator) Bool_t TIterator return false
Compare two iterator objects.
Definition: TIterator.cxx:20
char x
Definition: types.h:116
#define AVX
Definition: global.h:90
static Vc_ALWAYS_INLINE void assertCorrectAlignment(const _T *)
Definition: types.h:210
#define Scalar
Definition: global.h:83
A helper class for fixed-size two-dimensional arrays.
Definition: memory.h:120
#define Vc_ALWAYS_INLINE
Definition: macros.h:130
#define Vc_ALIGNOF(_TYPE_)
Definition: macros.h:50
#define T2
Definition: md5.inl:146
#define SSE
Definition: global.h:84
#define T1
Definition: md5.inl:145
#define VC_STATIC_ASSERT(cond, msg)
Definition: macros.h:246
Definition: casts.h:28
const char * Value
Definition: TXMLSetup.cxx:73