/* This file is part of the Vc library. Copyright (C) 2009-2012 Matthias Kretz Vc is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Vc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Vc. If not, see . */ #ifndef SCALAR_VECTOR_H #define SCALAR_VECTOR_H #include #include #include #ifdef _MSC_VER #include #endif #include "../common/memoryfwd.h" #include "macros.h" #include "types.h" #include "mask.h" #include "writemaskedvector.h" namespace AliRoot { namespace Vc { namespace Scalar { enum VectorAlignmentEnum { VectorAlignment = 4 }; template class Vector { friend class WriteMaskedVector; public: typedef typename DetermineEntryType::Type EntryType; protected: EntryType m_data; public: typedef Vc::Memory, 1> Memory; typedef Vector IndexType; typedef Scalar::Mask<1u> Mask; typedef Vector AsArg; Vc_ALWAYS_INLINE EntryType &data() { return m_data; } Vc_ALWAYS_INLINE EntryType data() const { return m_data; } enum Constants { Size = 1 }; /////////////////////////////////////////////////////////////////////////////////////////// // uninitialized Vc_ALWAYS_INLINE Vector() {} /////////////////////////////////////////////////////////////////////////////////////////// // constants Vc_ALWAYS_INLINE Vector(VectorSpecialInitializerZero::ZEnum) : m_data(0) {} Vc_ALWAYS_INLINE Vector(VectorSpecialInitializerOne::OEnum) : m_data(1) {} Vc_ALWAYS_INLINE Vector(VectorSpecialInitializerIndexesFromZero::IEnum) : m_data(0) {} static Vc_ALWAYS_INLINE Vector Zero() { Vector r; r.m_data = 0; return r; } static Vc_ALWAYS_INLINE Vector One() { Vector r; r.m_data = 1; return r; } static Vc_ALWAYS_INLINE Vector IndexesFromZero() { return Zero(); } static Vc_INTRINSIC_L Vector Random() Vc_INTRINSIC_R; /////////////////////////////////////////////////////////////////////////////////////////// // static_cast / copy ctor template explicit Vc_ALWAYS_INLINE Vector(const Vector &x) : m_data(static_cast(x.data())) {} // implicit cast template Vc_ALWAYS_INLINE_L Vector &operator=(const Vector &x) Vc_ALWAYS_INLINE_R; // copy assignment Vc_ALWAYS_INLINE Vector &operator=(Vector v) { m_data = v.data(); return *this; } /////////////////////////////////////////////////////////////////////////////////////////// // broadcast explicit Vc_ALWAYS_INLINE Vector(EntryType x) : m_data(x) {} template Vc_ALWAYS_INLINE Vector(TT x, VC_EXACT_TYPE(TT, EntryType, void *) = 0) : m_data(x) {} Vc_ALWAYS_INLINE Vector &operator=(EntryType a) { m_data = a; return *this; } /////////////////////////////////////////////////////////////////////////////////////////// // load ctors explicit Vc_ALWAYS_INLINE Vector(const EntryType *x) : m_data(x[0]) {} template Vc_ALWAYS_INLINE Vector(const EntryType *x, A) : m_data(x[0]) {} template explicit Vc_ALWAYS_INLINE Vector(const Other *x) : m_data(x[0]) {} template Vc_ALWAYS_INLINE Vector(const Other *x, A) : m_data(x[0]) {} /////////////////////////////////////////////////////////////////////////////////////////// // expand 1 float_v to 2 double_v XXX rationale? remove it for release? XXX template Vc_ALWAYS_INLINE void expand(Vector *x) const { x->data() = static_cast(m_data); } template explicit Vc_ALWAYS_INLINE Vector(const Vector *a) : m_data(static_cast(a->data())) {} /////////////////////////////////////////////////////////////////////////////////////////// // zeroing Vc_ALWAYS_INLINE void setZero() { m_data = 0; } Vc_ALWAYS_INLINE void setZero(Mask k) { if (k) m_data = 0; } Vc_INTRINSIC_L void setQnan() Vc_INTRINSIC_R; Vc_INTRINSIC_L void setQnan(Mask m) Vc_INTRINSIC_R; /////////////////////////////////////////////////////////////////////////////////////////// // load member functions template Vc_ALWAYS_INLINE void load(const Other *mem) { m_data = mem[0]; } template Vc_ALWAYS_INLINE void load(const Other *mem, A) { m_data = mem[0]; } template Vc_ALWAYS_INLINE void load(const Other *mem, Mask m) { if (m.data()) m_data = mem[0]; } Vc_ALWAYS_INLINE void load(const EntryType *mem) { m_data = mem[0]; } template Vc_ALWAYS_INLINE void load(const EntryType *mem, A) { m_data = mem[0]; } Vc_ALWAYS_INLINE void load(const EntryType *mem, Mask m) { if (m.data()) m_data = mem[0]; } /////////////////////////////////////////////////////////////////////////////////////////// // stores Vc_ALWAYS_INLINE void store(EntryType *mem) const { mem[0] = m_data; } Vc_ALWAYS_INLINE void store(EntryType *mem, Mask m) const { if (m.data()) mem[0] = m_data; } template Vc_ALWAYS_INLINE void store(EntryType *mem, A) const { store(mem); } template Vc_ALWAYS_INLINE void store(EntryType *mem, Mask m, A) const { store(mem, m); } /////////////////////////////////////////////////////////////////////////////////////////// // swizzles Vc_INTRINSIC const Vector &abcd() const { return *this; } Vc_INTRINSIC const Vector cdab() const { return *this; } Vc_INTRINSIC const Vector badc() const { return *this; } Vc_INTRINSIC const Vector aaaa() const { return *this; } Vc_INTRINSIC const Vector bbbb() const { return *this; } Vc_INTRINSIC const Vector cccc() const { return *this; } Vc_INTRINSIC const Vector dddd() const { return *this; } Vc_INTRINSIC const Vector bcad() const { return *this; } Vc_INTRINSIC const Vector bcda() const { return *this; } Vc_INTRINSIC const Vector dabc() const { return *this; } Vc_INTRINSIC const Vector acbd() const { return *this; } Vc_INTRINSIC const Vector dbca() const { return *this; } Vc_INTRINSIC const Vector dcba() const { return *this; } /////////////////////////////////////////////////////////////////////////////////////////// // gathers template Vc_ALWAYS_INLINE Vector(const EntryType *array, const IndexT *indexes) : m_data(array[indexes[0]]) {} template Vc_ALWAYS_INLINE Vector(const EntryType *array, Vector indexes) : m_data(array[indexes[0]]) {} template Vc_ALWAYS_INLINE Vector(const EntryType *array, IndexT indexes, Mask m) : m_data(m.data() ? array[indexes[0]] : 0) {} template Vc_ALWAYS_INLINE Vector(const S1 *array, const EntryType S1::* member1, IT indexes, Mask mask = Mask(true)) : m_data(mask.data() ? (&array[indexes[0]])->*(member1) : 0) {} template Vc_ALWAYS_INLINE Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes, Mask mask = Mask(true)) : m_data(mask.data() ? array[indexes[0]].*(member1).*(member2) : 0) {} template Vc_ALWAYS_INLINE Vector(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndex, IT2 innerIndex, Mask mask = Mask(true)) : m_data(mask.data() ? (array[outerIndex[0]].*(ptrMember1))[innerIndex[0]] : 0) {} template Vc_ALWAYS_INLINE void gather(const EntryType *array, IT indexes, Mask mask = Mask(true)) { if (mask.data()) m_data = array[indexes[0]]; } template Vc_ALWAYS_INLINE void gather(const S1 *array, const EntryType S1::* member1, IT indexes, Mask mask = Mask(true)) { if (mask.data()) m_data = (&array[indexes[0]])->*(member1); } template Vc_ALWAYS_INLINE void gather(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes, Mask mask = Mask(true)) { if (mask.data()) m_data = array[indexes[0]].*(member1).*(member2); } template Vc_ALWAYS_INLINE void gather(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndex, IT2 innerIndex, Mask mask = Mask(true)) { if (mask.data()) m_data = (array[outerIndex[0]].*(ptrMember1))[innerIndex[0]]; } /////////////////////////////////////////////////////////////////////////////////////////// // scatters Vc_ALWAYS_INLINE void scatter(EntryType *array, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]] = m_data; } template Vc_ALWAYS_INLINE void scatter(S1 *array, EntryType S1::* member, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]].*(member) = m_data; } template Vc_ALWAYS_INLINE void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]].*(member1).*(member2) = m_data; } Vc_ALWAYS_INLINE void scatter(EntryType *array, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]] = m_data; } template Vc_ALWAYS_INLINE void scatter(S1 *array, EntryType S1::* member, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]].*(member) = m_data; } template Vc_ALWAYS_INLINE void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, const Vector &indexes, Mask m = Mask(true)) const { if (m.data()) array[indexes[0]].*(member1).*(member2) = m_data; } //prefix Vc_ALWAYS_INLINE Vector &operator++() { ++m_data; return *this; } Vc_ALWAYS_INLINE Vector &operator--() { --m_data; return *this; } //postfix Vc_ALWAYS_INLINE Vector operator++(int) { return m_data++; } Vc_ALWAYS_INLINE Vector operator--(int) { return m_data--; } Vc_ALWAYS_INLINE EntryType &operator[](size_t index) { assert(index == 0); if(index) {} return m_data; } Vc_ALWAYS_INLINE EntryType operator[](size_t index) const { assert(index == 0); if(index) {} return m_data; } Vc_ALWAYS_INLINE Vector operator~() const { return Vector(~m_data); } Vc_ALWAYS_INLINE Vector::Type> operator-() const { return Vector::Type>(-m_data); } Vc_INTRINSIC Vector Vc_PURE operator+() const { return *this; } #define OPshift(symbol) \ Vc_ALWAYS_INLINE Vector &operator symbol##=(const Vector &x) { m_data symbol##= x.m_data; return *this; } \ Vc_ALWAYS_INLINE Vector &operator symbol##=(EntryType x) { return operator symbol##=(Vector(x)); } \ Vc_ALWAYS_INLINE Vector operator symbol(const Vector &x) const { return Vector(m_data symbol x.m_data); } #define OPshift_int(symbol) \ Vc_ALWAYS_INLINE Vector operator symbol(int x) const { return Vector(m_data symbol x); } #define OP(symbol) \ OPshift(symbol) \ template Vc_ALWAYS_INLINE VC_EXACT_TYPE(TT, EntryType, Vector) operator symbol(TT x) const { return operator symbol(Vector(x)); } #define OPcmp(symbol) \ Vc_ALWAYS_INLINE Mask operator symbol(const Vector &x) const { return Mask(m_data symbol x.m_data); } \ template Vc_ALWAYS_INLINE VC_EXACT_TYPE(TT, EntryType, Mask) operator symbol(TT x) const { return Mask(m_data symbol x); } VC_ALL_ARITHMETICS(OP) VC_ALL_BINARY(OP) VC_ALL_SHIFTS(OPshift) VC_ALL_SHIFTS(OPshift_int) VC_ALL_COMPARES(OPcmp) #undef OP #undef OPcmp #undef OPshift #undef OPshift_int Vc_INTRINSIC_L Vc_PURE_L Mask isNegative() const Vc_PURE_R Vc_INTRINSIC_R; Vc_ALWAYS_INLINE void fusedMultiplyAdd(const Vector &factor, const Vector &summand) { m_data = m_data * factor.data() + summand.data(); } Vc_ALWAYS_INLINE void assign(const Vector &v, const Mask &m) { if (m.data()) m_data = v.m_data; } template Vc_ALWAYS_INLINE V2 staticCast() const { return V2(static_cast(m_data)); } template Vc_ALWAYS_INLINE V2 reinterpretCast() const { typedef typename V2::EntryType AliasT2 Vc_MAY_ALIAS; return V2(*reinterpret_cast(&m_data)); } Vc_ALWAYS_INLINE WriteMaskedVector operator()(Mask m) { return WriteMaskedVector(this, m); } Vc_ALWAYS_INLINE bool pack(Mask &m1, Vector &v2, Mask &m2) { if (!m1.data() && m2.data()) { m_data = v2.m_data; m1 = true; m2 = false; return true; } return m1; } Vc_ALWAYS_INLINE EntryType min() const { return m_data; } Vc_ALWAYS_INLINE EntryType max() const { return m_data; } Vc_ALWAYS_INLINE EntryType product() const { return m_data; } Vc_ALWAYS_INLINE EntryType sum() const { return m_data; } Vc_ALWAYS_INLINE EntryType min(Mask) const { return m_data; } Vc_ALWAYS_INLINE EntryType max(Mask) const { return m_data; } Vc_ALWAYS_INLINE EntryType product(Mask) const { return m_data; } Vc_ALWAYS_INLINE EntryType sum(Mask m) const { if (m) return m_data; return static_cast(0); } Vc_INTRINSIC Vector shifted(int amount) const { return amount == 0 ? *this : Zero(); } Vc_INTRINSIC Vector rotated(int) const { return *this; } Vector sorted() const { return *this; } template void callWithValuesSorted(F &f) { f(m_data); } template Vc_INTRINSIC void call(const F &f) const { f(m_data); } template Vc_INTRINSIC void call(F &f) const { f(m_data); } template Vc_INTRINSIC void call(const F &f, Mask mask) const { if (mask) { f(m_data); } } template Vc_INTRINSIC void call(F &f, Mask mask) const { if (mask) { f(m_data); } } template Vc_INTRINSIC Vector apply(const F &f) const { return Vector(f(m_data)); } template Vc_INTRINSIC Vector apply(F &f) const { return Vector(f(m_data)); } template Vc_INTRINSIC Vector apply(const F &f, Mask mask) const { if (mask) { return Vector(f(m_data)); } else { return *this; } } template Vc_INTRINSIC Vector apply(F &f, Mask mask) const { if (mask) { return Vector(f(m_data)); } else { return *this; } } template Vc_INTRINSIC void fill(EntryType (&f)(IndexT)) { m_data = f(0); } Vc_INTRINSIC void fill(EntryType (&f)()) { m_data = f(); } Vc_INTRINSIC_L Vector copySign(Vector reference) const Vc_INTRINSIC_R; Vc_INTRINSIC_L Vector exponent() const Vc_INTRINSIC_R; }; typedef Vector double_v; typedef Vector float_v; typedef Vector sfloat_v; typedef Vector int_v; typedef Vector uint_v; typedef Vector short_v; typedef Vector ushort_v; typedef double_v::Mask double_m; typedef float_v::Mask float_m; typedef sfloat_v::Mask sfloat_m; typedef int_v::Mask int_m; typedef uint_v::Mask uint_m; typedef short_v::Mask short_m; typedef ushort_v::Mask ushort_m; template class SwizzledVector : public Vector {}; #ifdef _MSC_VER template static Vc_ALWAYS_INLINE void forceToRegisters(const Vector &) { } #else template static Vc_ALWAYS_INLINE void forceToRegisters(const Vector &x01) { __asm__ __volatile__(""::"r"(x01.data())); } template<> Vc_ALWAYS_INLINE void forceToRegisters(const Vector &x01) { __asm__ __volatile__(""::"x"(x01.data())); } template<> Vc_ALWAYS_INLINE void forceToRegisters(const Vector &x01) { __asm__ __volatile__(""::"x"(x01.data())); } #endif template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &x01, const Vector &x02) { forceToRegisters(x01); forceToRegisters(x02); } template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} template static Vc_ALWAYS_INLINE void forceToRegisters( const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &) {} } // namespace Scalar } // namespace Vc } // namespace AliRoot #include "vector.tcc" #include "math.h" #include "undomacros.h" #endif // SCALAR_VECTOR_H