File indexing completed on 2025-01-30 10:25:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef VC_COMMON_WHERE_H_
0029 #define VC_COMMON_WHERE_H_
0030
0031 #include "types.h"
0032 #include "macros.h"
0033
0034 namespace Vc_VERSIONED_NAMESPACE
0035 {
0036
0037 namespace WhereImpl
0038 {
0039
0040
0041
0042
0043
0044 template<typename _Mask, typename _LValue> struct MaskedLValue
0045 {
0046 typedef _Mask Mask;
0047 typedef _LValue LValue;
0048
0049 const Mask &mask;
0050 LValue &lhs;
0051
0052
0053 constexpr MaskedLValue(const Mask &m, LValue &l) : mask(m), lhs(l) {}
0054 MaskedLValue(const MaskedLValue &) = delete;
0055 #ifndef __cpp_guaranteed_copy_elision
0056 constexpr MaskedLValue(MaskedLValue &&) = default;
0057 #endif
0058
0059
0060
0061
0062
0063 template<typename T> Vc_ALWAYS_INLINE void operator =(T &&rhs) { conditional_assign<Operator:: Assign>(lhs, mask, std::forward<T>(rhs)); }
0064 template<typename T> Vc_ALWAYS_INLINE void operator +=(T &&rhs) { conditional_assign<Operator:: PlusAssign>(lhs, mask, std::forward<T>(rhs)); }
0065 template<typename T> Vc_ALWAYS_INLINE void operator -=(T &&rhs) { conditional_assign<Operator:: MinusAssign>(lhs, mask, std::forward<T>(rhs)); }
0066 template<typename T> Vc_ALWAYS_INLINE void operator *=(T &&rhs) { conditional_assign<Operator:: MultiplyAssign>(lhs, mask, std::forward<T>(rhs)); }
0067 template<typename T> Vc_ALWAYS_INLINE void operator /=(T &&rhs) { conditional_assign<Operator:: DivideAssign>(lhs, mask, std::forward<T>(rhs)); }
0068 template<typename T> Vc_ALWAYS_INLINE void operator %=(T &&rhs) { conditional_assign<Operator:: RemainderAssign>(lhs, mask, std::forward<T>(rhs)); }
0069 template<typename T> Vc_ALWAYS_INLINE void operator ^=(T &&rhs) { conditional_assign<Operator:: XorAssign>(lhs, mask, std::forward<T>(rhs)); }
0070 template<typename T> Vc_ALWAYS_INLINE void operator &=(T &&rhs) { conditional_assign<Operator:: AndAssign>(lhs, mask, std::forward<T>(rhs)); }
0071 template<typename T> Vc_ALWAYS_INLINE void operator |=(T &&rhs) { conditional_assign<Operator:: OrAssign>(lhs, mask, std::forward<T>(rhs)); }
0072 template<typename T> Vc_ALWAYS_INLINE void operator<<=(T &&rhs) { conditional_assign<Operator:: LeftShiftAssign>(lhs, mask, std::forward<T>(rhs)); }
0073 template<typename T> Vc_ALWAYS_INLINE void operator>>=(T &&rhs) { conditional_assign<Operator::RightShiftAssign>(lhs, mask, std::forward<T>(rhs)); }
0074 Vc_ALWAYS_INLINE void operator++() { conditional_assign<Operator:: PreIncrement>(lhs, mask); }
0075 Vc_ALWAYS_INLINE void operator++(int) { conditional_assign<Operator::PostIncrement>(lhs, mask); }
0076 Vc_ALWAYS_INLINE void operator--() { conditional_assign<Operator:: PreDecrement>(lhs, mask); }
0077 Vc_ALWAYS_INLINE void operator--(int) { conditional_assign<Operator::PostDecrement>(lhs, mask); }
0078
0079
0080 template <class T, class IV, class S>
0081 Vc_INTRINSIC void operator=(Common::SubscriptOperation<T, IV, S, true> &&rhs)
0082 {
0083 lhs.gather(std::move(rhs).gatherArguments(), mask);
0084 }
0085 template <class T, class IV, class S>
0086 void operator+=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0087 template <class T, class IV, class S>
0088 void operator-=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0089 template <class T, class IV, class S>
0090 void operator*=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0091 template <class T, class IV, class S>
0092 void operator/=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0093 template <class T, class IV, class S>
0094 void operator%=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0095 template <class T, class IV, class S>
0096 void operator^=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0097 template <class T, class IV, class S>
0098 void operator&=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0099 template <class T, class IV, class S>
0100 void operator|=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0101 template <class T, class IV, class S>
0102 void operator<<=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0103 template <class T, class IV, class S>
0104 void operator>>=(Common::SubscriptOperation<T, IV, S, true> &&rhs) = delete;
0105 };
0106
0107 template <typename _Mask, typename T_, typename I_, typename S_>
0108 struct MaskedLValue<_Mask, Common::SubscriptOperation<T_, I_, S_, true>>
0109 {
0110 typedef _Mask Mask;
0111 typedef Common::SubscriptOperation<T_, I_, S_, true> SO;
0112
0113 const Mask &mask;
0114 SO &lhs;
0115
0116 template <typename T> using Decay = typename std::decay<T>::type;
0117
0118
0119 constexpr MaskedLValue(const Mask &m, SO &&l) : mask(m), lhs(l) {}
0120 MaskedLValue(const MaskedLValue &) = delete;
0121 #ifndef __cpp_guaranteed_copy_elision
0122 constexpr MaskedLValue(MaskedLValue &&) = default;
0123 #endif
0124
0125
0126
0127
0128
0129 template <class T> Vc_ALWAYS_INLINE void operator=(T &&rhs) &&
0130 {
0131 std::forward<T>(rhs).scatter(std::move(lhs).scatterArguments(), mask);
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 };
0156
0157 template<typename _LValue> struct MaskedLValue<bool, _LValue>
0158 {
0159 typedef bool Mask;
0160 typedef _LValue LValue;
0161
0162 const Mask &mask;
0163 LValue &lhs;
0164
0165
0166 constexpr MaskedLValue(const Mask &m, LValue &l) : mask(m), lhs(l) {}
0167 MaskedLValue(const MaskedLValue &) = delete;
0168 constexpr MaskedLValue(MaskedLValue &&) = default;
0169
0170 template<typename T> Vc_ALWAYS_INLINE void operator =(T &&rhs) { if (mask) lhs = std::forward<T>(rhs); }
0171 template<typename T> Vc_ALWAYS_INLINE void operator +=(T &&rhs) { if (mask) lhs += std::forward<T>(rhs); }
0172 template<typename T> Vc_ALWAYS_INLINE void operator -=(T &&rhs) { if (mask) lhs -= std::forward<T>(rhs); }
0173 template<typename T> Vc_ALWAYS_INLINE void operator *=(T &&rhs) { if (mask) lhs *= std::forward<T>(rhs); }
0174 template<typename T> Vc_ALWAYS_INLINE void operator /=(T &&rhs) { if (mask) lhs /= std::forward<T>(rhs); }
0175 template<typename T> Vc_ALWAYS_INLINE void operator %=(T &&rhs) { if (mask) lhs %= std::forward<T>(rhs); }
0176 template<typename T> Vc_ALWAYS_INLINE void operator ^=(T &&rhs) { if (mask) lhs ^= std::forward<T>(rhs); }
0177 template<typename T> Vc_ALWAYS_INLINE void operator &=(T &&rhs) { if (mask) lhs &= std::forward<T>(rhs); }
0178 template<typename T> Vc_ALWAYS_INLINE void operator |=(T &&rhs) { if (mask) lhs |= std::forward<T>(rhs); }
0179 template<typename T> Vc_ALWAYS_INLINE void operator<<=(T &&rhs) { if (mask) lhs <<= std::forward<T>(rhs); }
0180 template<typename T> Vc_ALWAYS_INLINE void operator>>=(T &&rhs) { if (mask) lhs >>= std::forward<T>(rhs); }
0181 Vc_ALWAYS_INLINE void operator++() { if (mask) ++lhs; }
0182 Vc_ALWAYS_INLINE void operator++(int) { if (mask) lhs++; }
0183 Vc_ALWAYS_INLINE void operator--() { if (mask) --lhs; }
0184 Vc_ALWAYS_INLINE void operator--(int) { if (mask) lhs--; }
0185 };
0186
0187 template<typename _Mask> struct WhereMask
0188 {
0189 typedef _Mask Mask;
0190 const Mask &mask;
0191
0192
0193 constexpr WhereMask(const Mask &m) : mask(m) {}
0194 WhereMask(const WhereMask &) = delete;
0195
0196 template <typename T, typename I, typename S>
0197 constexpr Vc_WARN_UNUSED_RESULT
0198 MaskedLValue<Mask, Common::SubscriptOperation<T, I, S, true>>
0199 operator|(Common::SubscriptOperation<T, I, S, true> &&lhs) const
0200 {
0201 static_assert(!std::is_const<T>::value,
0202 "masked scatter to constant memory not possible.");
0203 return {mask, std::move(lhs)};
0204 }
0205
0206 template<typename T> constexpr Vc_WARN_UNUSED_RESULT MaskedLValue<Mask, T> operator|(T &&lhs) const
0207 {
0208 static_assert(std::is_lvalue_reference<T>::value, "Syntax error: Incorrect use of Vc::where. Maybe operator precedence got you by surprise. Examples of correct usage:\n"
0209 " Vc::where(x < 2) | x += 1;\n"
0210 " (Vc::where(x < 2) | x)++;\n"
0211 " Vc::where(x < 2)(x) += 1;\n"
0212 " Vc::where(x < 2)(x)++;\n"
0213 );
0214 return { mask, lhs };
0215 }
0216
0217 template <class T,
0218 class = decltype(std::declval<T>() = std::declval<const T &>())>
0219 constexpr Vc_WARN_UNUSED_RESULT MaskedLValue<Mask, T> operator()(T &&lhs) const
0220 {
0221 return operator|(std::forward<T>(lhs));
0222 }
0223 };
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 template<typename M> constexpr Vc_WARN_UNUSED_RESULT WhereImpl::WhereMask<M> where(const M &mask)
0266 {
0267 return { mask };
0268 }
0269
0270 template <class M, class V>
0271 constexpr Vc_WARN_UNUSED_RESULT WhereImpl::MaskedLValue<M, V> where(const M &mask,
0272 V &value)
0273 {
0274 return {mask, value};
0275 }
0276
0277
0278
0279 template <class M, class T, class IT, class Scale>
0280 constexpr Vc_WARN_UNUSED_RESULT
0281 WhereImpl::MaskedLValue<M, Common::SubscriptOperation<T, IT, Scale, true>>
0282 where(const M &mask, Common::SubscriptOperation<T, IT, Scale, true> &&value)
0283 {
0284 return {mask, std::move(value)};
0285 }
0286
0287 template<typename M> constexpr Vc_WARN_UNUSED_RESULT WhereImpl::WhereMask<M> _if(const M &m)
0288 {
0289 return { m };
0290 }
0291
0292 }
0293
0294 #endif