ROOT  6.06/09
Reference Guide
operators.h
Go to the documentation of this file.
1 #ifndef VC_ICC
2 // ICC ICEs if the following type-traits are in the anonymous namespace
3 namespace
4 {
5 #endif
6 template<typename Cond, typename T> struct EnableIfNeitherIntegerNorVector : public EnableIf<!CanConvertToInt<Cond>::Value, T> {};
7 template<typename Cond, typename T> struct EnableIfNeitherIntegerNorVector<Vector<Cond>, T>;
8 
9 template<typename T> struct IsVector { enum { Value = false }; };
10 template<typename T> struct IsVector<Vector<T> > { enum { Value = true }; };
11 
12 template<typename T0, typename T1, typename V0, typename V1> struct IsTypeCombinationOf
13 {
14  enum {
15  Value = IsVector<V0>::Value ? (IsVector<V1>::Value ? ( // Vec × Vec
20  ) : ( // Vec × Scalar
23  )) : (IsVector<V1>::Value ? ( // Scalar × Vec
26  ) : ( // Scalar × Scalar
27  ( IsEqualType<T0, V0>::Value && IsEqualType<T1, V1>::Value) ||
28  ( IsEqualType<T0, V1>::Value && IsEqualType<T1, V0>::Value)
29  ))
30  };
31 };
32 
33 template<typename T0, typename T1, typename V> struct IsVectorOperands
34 {
35  enum {
38  };
39 };
40 #ifndef VC_ICC
41 }
42 #endif
43 
44 // float-int arithmetic operators //{{{1
45 // These operators must be very picky about the exact types they want to handle. Once (uncontrolled)
46 // implicit type conversions get involved, ambiguous overloads will occur. E.g. a simple int × enum
47 // will become ambiguous because it can convert both to a vector type, which then can execute the
48 // operator. We can't argue that such code should not be used - it could break existing code, not
49 // under control of the developer, just by putting the Vc header somewhere on top.
50 //
51 // The following type combinations are safe (always symmetric):
52 // 1. Vector × Vector
53 // 2. Vector × Scalar (int, float, enum value, ...)
54 // 3. Some object that has a vector cast operator × Vector
55 // 4. Some object that has a vector cast operator × Scalar
56 //
57 // Additionally there are restrictions on which types combine to what resulting type:
58 // 1.a. float × double_v -> double_v
59 // 1.b. any int × double_v -> double_v
60 // 2.a. (u)int_v × float_v -> float_v
61 // 2.b. (u)int_v × float -> float_v
62 // 2.c. any int × float_v -> float_v
63 // 3.a. (u)short_v × sfloat_v -> sfloat_v
64 // 3.b. (u)short_v × float -> sfloat_v
65 // 3.c. short × sfloat_v -> sfloat_v
66 // 4.a. int_v × uint_v -> uint_v
67 // 4.b. any int × uint_v -> uint_v
68 // 4.c. unsigned int × int_v -> uint_v
69 // 4.d. signed int × int_v -> int_v
70 // 5. shorts like ints
71 
72 #define VC_OPERATOR_FORWARD_(ret, op) \
73 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
74  IsVectorOperands<T0, T1, double_v>::Value || \
75  ((IsEqualType<T0, float>::Value || IsLikeInteger<T0>::Value) && HasImplicitCast<T1, double_v>::Value && !HasImplicitCast<T1, int>::Value) || \
76  ((IsEqualType<T1, float>::Value || IsLikeInteger<T1>::Value) && HasImplicitCast<T0, double_v>::Value && !HasImplicitCast<T0, int>::Value) || \
77  false, double_##ret>::Value operator op(const T0 &x, const T1 &y) { return double_v(x) op double_v(y); } \
78 \
79 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
80  IsVectorOperands<T0, T1, float_v>::Value || \
81  IsTypeCombinationOf<T0, T1, int_v, float_v>::Value || \
82  IsTypeCombinationOf<T0, T1, uint_v, float_v>::Value || \
83  IsTypeCombinationOf<T0, T1, int_v, float>::Value || \
84  IsTypeCombinationOf<T0, T1, uint_v, float>::Value || \
85  (IsLikeInteger<T0>::Value && HasImplicitCast<T1, float_v>::Value && !HasImplicitCast<T1, int>::Value) || \
86  (IsLikeInteger<T1>::Value && HasImplicitCast<T0, float_v>::Value && !HasImplicitCast<T0, int>::Value) || \
87  false, float_##ret>::Value operator op(const T0 &x, const T1 &y) { return float_v(x) op float_v(y); } \
88 \
89 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
90  IsVectorOperands<T0, T1, sfloat_v>::Value || \
91  IsTypeCombinationOf<T0, T1, short_v, sfloat_v>::Value || \
92  IsTypeCombinationOf<T0, T1, ushort_v, sfloat_v>::Value || \
93  IsTypeCombinationOf<T0, T1, short_v, float>::Value || \
94  IsTypeCombinationOf<T0, T1, ushort_v, float>::Value || \
95  (IsLikeInteger<T0>::Value && HasImplicitCast<T1, sfloat_v>::Value && !HasImplicitCast<T1, int>::Value) || \
96  (IsLikeInteger<T1>::Value && HasImplicitCast<T0, sfloat_v>::Value && !HasImplicitCast<T0, int>::Value) || \
97  false, sfloat_##ret>::Value operator op(const T0 &x, const T1 &y) { return sfloat_v(x) op sfloat_v(y); } \
98 \
99 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
100  IsVectorOperands<T0, T1, uint_v>::Value || \
101  IsTypeCombinationOf<T0, T1, int_v, uint_v>::Value || \
102  (IsUnsignedInteger<T0>::Value && HasImplicitCast<T1, int_v>::Value && !HasImplicitCast<T1, int>::Value) || \
103  (IsUnsignedInteger<T1>::Value && HasImplicitCast<T0, int_v>::Value && !HasImplicitCast<T0, int>::Value) || \
104  (IsLikeInteger<T0>::Value && !IsEqualType<T0, unsigned int>::Value && HasImplicitCast<T1, uint_v>::Value && !HasImplicitCast<T1, int>::Value) || \
105  (IsLikeInteger<T1>::Value && !IsEqualType<T1, unsigned int>::Value && HasImplicitCast<T0, uint_v>::Value && !HasImplicitCast<T0, int>::Value) || \
106  false, uint_##ret>::Value operator op(const T0 &x, const T1 &y) { return uint_v(x) op uint_v(y); } \
107 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
108  IsVectorOperands<T0, T1, int_v>::Value || \
109  (IsLikeSignedInteger<T0>::Value && !IsEqualType<T0, int>::Value && HasImplicitCast<T1, int_v>::Value && !HasImplicitCast<T1, int>::Value) || \
110  (IsLikeSignedInteger<T1>::Value && !IsEqualType<T1, int>::Value && HasImplicitCast<T0, int_v>::Value && !HasImplicitCast<T0, int>::Value) || \
111  false, int_##ret>::Value operator op(const T0 &x, const T1 &y) { return int_v(x) op int_v(y); } \
112 \
113 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
114  IsVectorOperands<T0, T1, ushort_v>::Value || \
115  IsTypeCombinationOf<T0, T1, short_v, ushort_v>::Value || \
116  (IsUnsignedInteger<T0>::Value && HasImplicitCast<T1, short_v>::Value && !HasImplicitCast<T1, int>::Value) || \
117  (IsUnsignedInteger<T1>::Value && HasImplicitCast<T0, short_v>::Value && !HasImplicitCast<T0, int>::Value) || \
118  (IsLikeInteger<T0>::Value && !IsEqualType<T0, unsigned short>::Value && HasImplicitCast<T1, ushort_v>::Value && !HasImplicitCast<T1, int>::Value) || \
119  (IsLikeInteger<T1>::Value && !IsEqualType<T1, unsigned short>::Value && HasImplicitCast<T0, ushort_v>::Value && !HasImplicitCast<T0, int>::Value) || \
120  false, ushort_##ret>::Value operator op(const T0 &x, const T1 &y) { return ushort_v(x) op ushort_v(y); } \
121 template<typename T0, typename T1> static Vc_ALWAYS_INLINE typename EnableIf< \
122  IsVectorOperands<T0, T1, short_v>::Value || \
123  (IsLikeSignedInteger<T0>::Value && !IsEqualType<T0, short>::Value && HasImplicitCast<T1, short_v>::Value && !HasImplicitCast<T1, int>::Value) || \
124  (IsLikeSignedInteger<T1>::Value && !IsEqualType<T1, short>::Value && HasImplicitCast<T0, short_v>::Value && !HasImplicitCast<T0, int>::Value) || \
125  false, short_##ret>::Value operator op(const T0 &x, const T1 &y) { return short_v(x) op short_v(y); }
126 
127 
128 // break incorrect combinations
129 #define VC_OPERATOR_INTENTIONAL_ERROR_1(V, op) \
130 template<typename T> static inline typename EnableIfNeitherIntegerNorVector<T, Vc::Error::invalid_operands_of_types<V, T> >::Value operator op(const V &, const T &) { return Vc::Error::invalid_operands_of_types<V, T>(); } \
131 template<typename T> static inline typename EnableIfNeitherIntegerNorVector<T, Vc::Error::invalid_operands_of_types<T, V> >::Value operator op(const T &, const V &) { return Vc::Error::invalid_operands_of_types<T, V>(); }
132 
133 #define VC_OPERATOR_INTENTIONAL_ERROR_2(V1, V2, op) \
134 static inline Vc::Error::invalid_operands_of_types<V1, V2> operator op(V1::AsArg, V2::AsArg) { return Vc::Error::invalid_operands_of_types<V1, V2>(); } \
135 static inline Vc::Error::invalid_operands_of_types<V2, V1> operator op(V2::AsArg, V1::AsArg) { return Vc::Error::invalid_operands_of_types<V2, V1>(); }
136 
137 #define VC_OPERATOR_INTENTIONAL_ERROR_3(V, _T, op) \
138 template<typename T> static inline typename EnableIf<IsEqualType<T, _T>::Value, Vc::Error::invalid_operands_of_types<V, T> >::Value operator op(const V &, const T &) { return Vc::Error::invalid_operands_of_types<V, T>(); } \
139 template<typename T> static inline typename EnableIf<IsEqualType<T, _T>::Value, Vc::Error::invalid_operands_of_types<T, V> >::Value operator op(const T &, const V &) { return Vc::Error::invalid_operands_of_types<T, V>(); }
140 
141 //#define VC_EXTRA_CHECKING
142 #ifdef VC_EXTRA_CHECKING
143 #define VC_OPERATOR_INTENTIONAL_ERROR(op) \
144  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, sfloat_v, op) \
145  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, float_v, op) \
146  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, int_v, op) \
147  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, uint_v, op) \
148  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, short_v, op) \
149  VC_OPERATOR_INTENTIONAL_ERROR_2(double_v, ushort_v, op) \
150  VC_OPERATOR_INTENTIONAL_ERROR_2( int_v, short_v, op) \
151  VC_OPERATOR_INTENTIONAL_ERROR_2( uint_v, short_v, op) \
152  VC_OPERATOR_INTENTIONAL_ERROR_2( int_v, ushort_v, op) \
153  VC_OPERATOR_INTENTIONAL_ERROR_2( uint_v, ushort_v, op) \
154  VC_APPLY_1(VC_LIST_VECTOR_TYPES, VC_OPERATOR_INTENTIONAL_ERROR_1, op) \
155  VC_OPERATOR_INTENTIONAL_ERROR_2( float_v, short_v, op) \
156  VC_OPERATOR_INTENTIONAL_ERROR_2( float_v, ushort_v, op) \
157  VC_OPERATOR_INTENTIONAL_ERROR_2(sfloat_v, float_v, op) \
158  VC_OPERATOR_INTENTIONAL_ERROR_2(sfloat_v, int_v, op) \
159  VC_OPERATOR_INTENTIONAL_ERROR_2(sfloat_v, uint_v, op) \
160  VC_OPERATOR_INTENTIONAL_ERROR_3( float_v, double, op) \
161  VC_OPERATOR_INTENTIONAL_ERROR_3(sfloat_v, double, op)
162 #else
163 #define VC_OPERATOR_INTENTIONAL_ERROR(op)
164 #endif
165 
166 #define VC_OPERATOR_FORWARD_COMMUTATIVE(ret, op, op2) \
167 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, double, double_##ret) operator op(T x, double_v::AsArg y) { return y op2 x; } \
168 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, float, sfloat_##ret) operator op(T x, sfloat_v::AsArg y) { return y op2 x; } \
169 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, float, float_##ret) operator op(T x, float_v::AsArg y) { return y op2 x; } \
170 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, int, int_##ret) operator op(T x, int_v::AsArg y) { return y op2 x; } \
171 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, unsigned int, uint_##ret) operator op(T x, uint_v::AsArg y) { return y op2 x; } \
172 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, short, short_##ret) operator op(T x, short_v::AsArg y) { return y op2 x; } \
173 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, unsigned short, ushort_##ret) operator op(T x, ushort_v::AsArg y) { return y op2 x; } \
174 VC_OPERATOR_FORWARD_(ret, op) \
175 VC_OPERATOR_INTENTIONAL_ERROR(op)
176 
177 #define VC_OPERATOR_FORWARD(ret, op) \
178 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, double, double_##ret) operator op(T x, double_v::AsArg y) { return double_v(x) op y; } \
179 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, float, sfloat_##ret) operator op(T x, sfloat_v::AsArg y) { return sfloat_v(x) op y; } \
180 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, float, float_##ret) operator op(T x, float_v::AsArg y) { return float_v(x) op y; } \
181 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, int, int_##ret) operator op(T x, int_v::AsArg y) { return int_v(x) op y; } \
182 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, unsigned int, uint_##ret) operator op(T x, uint_v::AsArg y) { return uint_v(x) op y; } \
183 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, short, short_##ret) operator op(T x, short_v::AsArg y) { return short_v(x) op y; } \
184 template<typename T> static Vc_ALWAYS_INLINE VC_EXACT_TYPE(T, unsigned short, ushort_##ret) operator op(T x, ushort_v::AsArg y) { return ushort_v(x) op y; } \
185 VC_OPERATOR_FORWARD_(ret, op) \
186 VC_OPERATOR_INTENTIONAL_ERROR(op)
187 
201 
202 #undef VC_OPERATOR_FORWARD_
203 #undef VC_OPERATOR_INTENTIONAL_ERROR_1
204 #undef VC_OPERATOR_INTENTIONAL_ERROR_2
205 #undef VC_OPERATOR_INTENTIONAL_ERROR
206 #undef VC_OPERATOR_FORWARD_COMMUTATIVE
207 #undef VC_OPERATOR_FORWARD
208 
209 // }}}1
#define VC_OPERATOR_FORWARD(ret, op)
Definition: operators.h:177
double T(double x)
Definition: ChebyshevPol.h:34
#define VC_OPERATOR_FORWARD_COMMUTATIVE(ret, op, op2)
Definition: operators.h:166
#define T1
Definition: md5.inl:145
const char * Value
Definition: TXMLSetup.cxx:73