File indexing completed on 2025-01-31 10:25:42
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_SCALAR_VECTOR_H_
0029 #define VC_SCALAR_VECTOR_H_
0030
0031 #include <assert.h>
0032 #include <algorithm>
0033 #include <cmath>
0034
0035 #ifdef _MSC_VER
0036 #include <float.h>
0037 #endif
0038
0039 #include "types.h"
0040 #include "detail.h"
0041 #include "mask.h"
0042
0043 #include "macros.h"
0044
0045 namespace Vc_VERSIONED_NAMESPACE
0046 {
0047 #define Vc_CURRENT_CLASS_NAME Vector
0048 template <typename T> class Vector<T, VectorAbi::Scalar>
0049 {
0050 static_assert(std::is_arithmetic<T>::value,
0051 "Vector<T> only accepts arithmetic builtin types as template parameter T.");
0052
0053 public:
0054 using abi = VectorAbi::Scalar;
0055 using EntryType = T;
0056 using VectorEntryType = EntryType;
0057 using value_type = EntryType;
0058 using VectorType = EntryType;
0059 using vector_type = VectorType;
0060 using reference = Detail::ElementReference<Vector>;
0061
0062 protected:
0063 VectorType m_data = VectorType();
0064 template <typename U> using V = Vector<U, abi>;
0065
0066 public:
0067 typedef Scalar::Mask<T> Mask;
0068 using MaskType = Mask;
0069 using mask_type = Mask;
0070 typedef Mask MaskArgument;
0071 typedef Vector AsArg;
0072
0073 Vc_ALWAYS_INLINE VectorType &data() { return m_data; }
0074 Vc_ALWAYS_INLINE const VectorType &data() const { return m_data; }
0075
0076 static constexpr size_t Size = 1;
0077 static constexpr size_t MemoryAlignment = alignof(VectorType);
0078 using IndexType = fixed_size_simd<int, 1>;
0079 using index_type = IndexType;
0080
0081 #include "../common/generalinterface.h"
0082
0083 static Vc_INTRINSIC_L Vector Random() Vc_INTRINSIC_R;
0084
0085
0086 template <typename U>
0087 Vc_INTRINSIC Vector(
0088 V<U> x, typename std::enable_if<Traits::is_implicit_cast_allowed<U, T>::value,
0089 void *>::type = nullptr)
0090 : m_data(static_cast<EntryType>(x.data()))
0091 {
0092 }
0093
0094 #if Vc_IS_VERSION_1
0095
0096 template <typename U>
0097 Vc_DEPRECATED("use simd_cast instead of explicit type casting to convert between "
0098 "vector types") Vc_INTRINSIC
0099 explicit Vector(
0100 V<U> x,
0101 typename std::enable_if<!Traits::is_implicit_cast_allowed<U, T>::value,
0102 void *>::type = nullptr)
0103 : m_data(static_cast<EntryType>(x.data()))
0104 {
0105 }
0106 #endif
0107
0108 Vc_INTRINSIC explicit Vector(reference a) : Vector(static_cast<EntryType>(a)) {}
0109
0110
0111
0112 Vc_INTRINSIC Vector(EntryType a) : m_data(a) {}
0113 template <typename U>
0114 Vc_INTRINSIC Vector(U a,
0115 typename std::enable_if<std::is_same<U, int>::value &&
0116 !std::is_same<U, EntryType>::value,
0117 void *>::type = nullptr)
0118 : Vector(static_cast<EntryType>(a))
0119 {
0120 }
0121
0122 #include "../common/loadinterface.h"
0123 #include "../common/storeinterface.h"
0124
0125
0126
0127 Vc_ALWAYS_INLINE void setZero() { m_data = 0; }
0128 Vc_ALWAYS_INLINE void setZero(Mask k) { if (k.data()) m_data = 0; }
0129 Vc_ALWAYS_INLINE void setZeroInverted(Mask k) { if (!k.data()) m_data = 0; }
0130
0131 Vc_INTRINSIC_L void setQnan() Vc_INTRINSIC_R;
0132 Vc_INTRINSIC_L void setQnan(Mask m) Vc_INTRINSIC_R;
0133
0134 #include "../common/gatherinterface.h"
0135 #include "../common/scatterinterface.h"
0136
0137
0138 Vc_ALWAYS_INLINE Vector &operator++() { ++m_data; return *this; }
0139 Vc_ALWAYS_INLINE Vector &operator--() { --m_data; return *this; }
0140
0141 Vc_ALWAYS_INLINE Vector operator++(int) { return m_data++; }
0142 Vc_ALWAYS_INLINE Vector operator--(int) { return m_data--; }
0143
0144 private:
0145 friend reference;
0146 Vc_INTRINSIC static value_type get(const Vector &o, int i) noexcept
0147 {
0148 Vc_ASSERT(i == 0); if (i) {}
0149 return o.m_data;
0150 }
0151 template <typename U>
0152 Vc_INTRINSIC static void set(Vector &o, int i, U &&v) noexcept(
0153 noexcept(std::declval<value_type &>() = v))
0154 {
0155 Vc_ASSERT(i == 0); if (i) {}
0156 o.m_data = v;
0157 }
0158
0159 public:
0160
0161
0162
0163
0164
0165
0166 Vc_ALWAYS_INLINE reference operator[](size_t index) noexcept
0167 {
0168 static_assert(noexcept(reference{std::declval<Vector &>(), int()}), "");
0169 return {*this, int(index)};
0170 }
0171 Vc_ALWAYS_INLINE value_type operator[](size_t index) const noexcept
0172 {
0173 Vc_ASSERT(index == 0); if (index) {}
0174 return m_data;
0175 }
0176
0177 Vc_ALWAYS_INLINE Mask operator!() const
0178 {
0179 return Mask(!m_data);
0180 }
0181 Vc_ALWAYS_INLINE Vector operator~() const
0182 {
0183 #ifndef Vc_ENABLE_FLOAT_BIT_OPERATORS
0184 static_assert(std::is_integral<T>::value, "bit-complement can only be used with Vectors of integral type");
0185 #endif
0186 return Vector(~m_data);
0187 }
0188
0189 Vc_ALWAYS_INLINE Vector operator-() const
0190 {
0191 return -m_data;
0192 }
0193 Vc_INTRINSIC Vector Vc_PURE operator+() const { return *this; }
0194
0195 #define Vc_OP(symbol) \
0196 Vc_ALWAYS_INLINE Vc_PURE Vector operator symbol(const Vector &x) const { return Vector(m_data symbol x.m_data); }
0197 Vc_ALL_SHIFTS(Vc_OP);
0198 #undef Vc_OP
0199
0200 Vc_DEPRECATED("use isnegative(x) instead") Vc_INTRINSIC Vc_PURE Mask
0201 isNegative() const
0202 {
0203 return Vc::isnegative(*this);
0204 }
0205
0206 Vc_ALWAYS_INLINE void assign(const Vector &v, const Mask &m) {
0207 if (m.data()) m_data = v.m_data;
0208 }
0209
0210 template <typename V2>
0211 Vc_DEPRECATED("Use simd_cast instead of Vector::staticCast") Vc_ALWAYS_INLINE V2
0212 staticCast() const
0213 {
0214 return V2(static_cast<typename V2::EntryType>(m_data));
0215 }
0216
0217
0218
0219
0220
0221
0222
0223
0224 Vc_ALWAYS_INLINE Common::WriteMaskedVector<Vector, Mask> operator()(Mask m)
0225 {
0226 return {*this, m};
0227 }
0228
0229 Vc_ALWAYS_INLINE EntryType min() const { return m_data; }
0230 Vc_ALWAYS_INLINE EntryType max() const { return m_data; }
0231 Vc_ALWAYS_INLINE EntryType product() const { return m_data; }
0232 Vc_ALWAYS_INLINE EntryType sum() const { return m_data; }
0233 Vc_ALWAYS_INLINE Vector partialSum() const { return *this; }
0234 Vc_ALWAYS_INLINE EntryType min(Mask) const { return m_data; }
0235 Vc_ALWAYS_INLINE EntryType max(Mask) const { return m_data; }
0236 Vc_ALWAYS_INLINE EntryType product(Mask m) const
0237 {
0238 if (m.data()) {
0239 return m_data;
0240 } else {
0241 return EntryType(1);
0242 }
0243 }
0244 Vc_ALWAYS_INLINE EntryType sum(Mask m) const { if (m.data()) return m_data; return static_cast<EntryType>(0); }
0245
0246 Vc_INTRINSIC Vector Vc_VDECL shifted(int amount, Vector shiftIn) const {
0247 Vc_ASSERT(amount >= -1 && amount <= 1);
0248 return amount == 0 ? *this : shiftIn;
0249 }
0250 Vc_INTRINSIC Vector shifted(int amount) const { return amount == 0 ? *this : Zero(); }
0251 Vc_INTRINSIC Vector rotated(int) const { return *this; }
0252 Vc_INTRINSIC Vector reversed() const { return *this; }
0253 Vc_INTRINSIC Vector sorted() const { return *this; }
0254
0255 template <typename F> void callWithValuesSorted(F &&f) { f(m_data); }
0256
0257 template <typename F> Vc_INTRINSIC void call(F &&f) const { f(m_data); }
0258
0259 template <typename F> Vc_INTRINSIC void call(F &&f, Mask mask) const
0260 {
0261 if (mask.data()) {
0262 f(m_data);
0263 }
0264 }
0265
0266 template <typename F> Vc_INTRINSIC Vector apply(F &&f) const { return Vector(f(m_data)); }
0267
0268 template <typename F> Vc_INTRINSIC Vector apply(F &&f, Mask mask) const
0269 {
0270 if (mask.data()) {
0271 return Vector(f(m_data));
0272 } else {
0273 return *this;
0274 }
0275 }
0276
0277 template<typename IndexT> Vc_INTRINSIC void fill(EntryType (&f)(IndexT)) {
0278 m_data = f(0);
0279 }
0280 Vc_INTRINSIC void fill(EntryType (&f)()) {
0281 m_data = f();
0282 }
0283
0284 template <typename G> static Vc_INTRINSIC Vector generate(G gen)
0285 {
0286 return gen(0);
0287 }
0288
0289 Vc_DEPRECATED("use copysign(x, y) instead") Vc_INTRINSIC Vector Vc_VDECL
0290 copySign(Vector x) const
0291 {
0292 return Vc::copysign(*this, x);
0293 }
0294
0295 Vc_DEPRECATED("use exponent(x) instead") Vc_INTRINSIC Vector exponent() const
0296 {
0297 return Vc::exponent(*this);
0298 }
0299
0300 Vc_INTRINSIC Vector Vc_VDECL interleaveLow(Vector) const { return *this; }
0301 Vc_INTRINSIC Vector Vc_VDECL interleaveHigh(Vector x) const { return x; }
0302 };
0303 #undef Vc_CURRENT_CLASS_NAME
0304 template <typename T> constexpr size_t Vector<T, VectorAbi::Scalar>::Size;
0305 template <typename T> constexpr size_t Vector<T, VectorAbi::Scalar>::MemoryAlignment;
0306
0307 #define Vc_OP(symbol) \
0308 template <typename T, typename U, \
0309 typename = decltype(std::declval<T &>() symbol## = std::declval<T>())> \
0310 Vc_INTRINSIC enable_if<std::is_convertible<U, Vector<T, VectorAbi::Scalar>>::value, \
0311 Vector<T, VectorAbi::Scalar>> \
0312 &operator symbol##=(Vector<T, VectorAbi::Scalar> &lhs, U &&rhs) \
0313 { \
0314 lhs.data() symbol## = Vector<T, VectorAbi::Scalar>(std::forward<U>(rhs)).data(); \
0315 return lhs; \
0316 }
0317 Vc_ALL_SHIFTS(Vc_OP);
0318 #undef Vc_OP
0319
0320 #define Vc_CONDITIONAL_ASSIGN(name_, op_) \
0321 template <Operator O, typename T, typename M, typename U> \
0322 Vc_INTRINSIC enable_if<O == Operator::name_, void> conditional_assign( \
0323 Vector<T, VectorAbi::Scalar> &lhs, M &&mask, U &&rhs) \
0324 { \
0325 if (mask.isFull()) { \
0326 lhs op_ std::forward<U>(rhs); \
0327 } \
0328 } \
0329 Vc_NOTHING_EXPECTING_SEMICOLON
0330 Vc_CONDITIONAL_ASSIGN( Assign, =);
0331 Vc_CONDITIONAL_ASSIGN( PlusAssign, +=);
0332 Vc_CONDITIONAL_ASSIGN( MinusAssign, -=);
0333 Vc_CONDITIONAL_ASSIGN( MultiplyAssign, *=);
0334 Vc_CONDITIONAL_ASSIGN( DivideAssign, /=);
0335 Vc_CONDITIONAL_ASSIGN( RemainderAssign, %=);
0336 Vc_CONDITIONAL_ASSIGN( XorAssign, ^=);
0337 Vc_CONDITIONAL_ASSIGN( AndAssign, &=);
0338 Vc_CONDITIONAL_ASSIGN( OrAssign, |=);
0339 Vc_CONDITIONAL_ASSIGN( LeftShiftAssign,<<=);
0340 Vc_CONDITIONAL_ASSIGN(RightShiftAssign,>>=);
0341 #undef Vc_CONDITIONAL_ASSIGN
0342
0343 #define Vc_CONDITIONAL_ASSIGN(name_, expr_) \
0344 template <Operator O, typename T, typename M> \
0345 Vc_INTRINSIC enable_if<O == Operator::name_, Vector<T, VectorAbi::Scalar>> \
0346 conditional_assign(Vector<T, VectorAbi::Scalar> &lhs, M &&mask) \
0347 { \
0348 return mask.isFull() ? (expr_) : lhs; \
0349 } \
0350 Vc_NOTHING_EXPECTING_SEMICOLON
0351 Vc_CONDITIONAL_ASSIGN(PostIncrement, lhs++);
0352 Vc_CONDITIONAL_ASSIGN( PreIncrement, ++lhs);
0353 Vc_CONDITIONAL_ASSIGN(PostDecrement, lhs--);
0354 Vc_CONDITIONAL_ASSIGN( PreDecrement, --lhs);
0355 #undef Vc_CONDITIONAL_ASSIGN
0356
0357 }
0358
0359 #include "vector.tcc"
0360 #include "simd_cast.h"
0361
0362 #endif