Vc
1.0.0-dev
SIMD Vector Classes for C++
|
|
The main vector class for expressing data parallelism.
are specializations of this class. For most cases there are no API differences for the specializations. Make use of Vector<T> for generic programming, otherwise you might prefer to use the *_v
aliases.
#include <Vc/vector.h>
Public Types | |
using | abi = Abi |
The ABI tag type of the current template instantiation. | |
using | EntryType = typename VectorTraits< T, Abi >::EntryType |
The type of the entries in the vector. | |
using | value_type = EntryType |
The type of the entries in the vector. More... | |
using | MaskType = Vc::Mask< T, Abi > |
The type of the mask used for masked operations and returned from comparisons. | |
using | mask_type = MaskType |
The type of the mask used for masked operations and returned from comparisons. More... | |
using | IndexType = Vc::SimdArray< int, size()> |
The type of the vector used for indexes in gather and scatter operations. | |
using | index_type = IndexType |
The type of the vector used for indexes in gather and scatter operations. More... | |
Public Member Functions | |||||||
void | setZero () | ||||||
Set all entries to zero. | |||||||
void | setZero (MaskType mask) | ||||||
Set all entries to zero where the mask is set. More... | |||||||
void | setZeroInverted (MaskType mask) | ||||||
Set all entries to zero where the mask is not set. More... | |||||||
void | setQnan () | ||||||
Set all entries to the bit representation of a QNaN. | |||||||
void | setQnan (MaskType mask) | ||||||
Set all entries to the bit representation of a QNaN where the mask is set. More... | |||||||
MaskType | isNegative () const | ||||||
Returns for each vector component whether it stores a negative value. | |||||||
template<typename V2 > | |||||||
V2 | reinterpretCast () const | ||||||
reinterpret_cast the vector components to construct a vector of type V2 . | |||||||
Common::WriteMaskedVector< Vector, MaskType > | operator() (MaskType mask) | ||||||
Writemask the vector before an assignment. More... | |||||||
Vector | sorted () const | ||||||
Return a sorted copy of the vector. More... | |||||||
Vector | exponent () const | ||||||
Returns the exponents of the floating-point values in the vector. | |||||||
Compile-Time Constant Initialization | |||||||
Vector ()=default | |||||||
Construct a zero-initialized vector object. More... | |||||||
Vector (VectorSpecialInitializerZero) | |||||||
Construct a vector with the entries initialized to zero. More... | |||||||
Vector (VectorSpecialInitializerOne) | |||||||
Construct a vector with the entries initialized to one. More... | |||||||
Vector (VectorSpecialInitializerIndexesFromZero) | |||||||
Construct a vector with the entries initialized to 0, 1, 2, 3, 4, 5, ... More... | |||||||
Conversion/Broadcast Constructors | |||||||
template<typename U > | |||||||
Vector (Vector< U, abi > x, enable_if< Traits::is_implicit_cast_allowed< U, T >::value >=nullarg) | |||||||
Implict conversion from compatible Vector<U, Abi> types. | |||||||
template<typename U > | |||||||
Vector (Vector< U, abi > x, enable_if<!Traits::is_implicit_cast_allowed< U, T >::value >=nullarg) | |||||||
Explicit conversion (i.e. More... | |||||||
Vector (EntryType a) | |||||||
Broadcast Constructor. More... | |||||||
template<typename U > | |||||||
Vector (U a, enable_if< std::is_same< U, int >::value &&!std::is_same< U, EntryType >::value >=nullarg) | |||||||
Loads & Stores | |||||||
Vector (const EntryType *mem) | |||||||
Construct a vector from loading its entries from the array at mem . More... | |||||||
template<typename Flags , typename = enable_if<Traits::is_load_store_flag<Flags>::value>> | |||||||
Vector (const EntryType *mem, Flags flags) | |||||||
Construct a vector from loading its entries from the array at mem . More... | |||||||
template<typename U , typename Flags = DefaultLoadTag, typename = enable_if< (!std::is_integral<U>::value || !std::is_integral<EntryType>::value || sizeof(EntryType) >= sizeof(U)> | |||||||
Vector (const U *x, Flags flags=Flags()) | |||||||
void | load (const EntryType *mem) | ||||||
Load the vector entries from mem , overwriting the previous values. More... | |||||||
template<typename Flags , typename = enable_if<Traits::is_load_store_flag<Flags>::value>> | |||||||
void | load (const EntryType *mem, Flags flags) | ||||||
Load the vector entries from mem , overwriting the previous values. More... | |||||||
template<typename U , typename Flags = DefaultLoadTag, typename = enable_if< (!std::is_integral<U>::value || !std::is_integral<EntryType>::value || sizeof(EntryType) >= sizeof(U)> | |||||||
void | load (const U *mem, Flags=Flags()) 1 | ||||||
template<typename U , typename Flags = DefaultStoreTag, typename = enable_if<std::is_arithmetic<U>::value &&Traits::is_load_store_flag<Flags>::value>> | |||||||
void | store (U *mem, Flags flags=Flags()) const 1 | ||||||
Store the vector data to mem . More... | |||||||
template<typename U , typename Flags = DefaultStoreTag, typename = enable_if<std::is_arithmetic<U>::value &&Traits::is_load_store_flag<Flags>::value>> | |||||||
void | store (U *mem, MaskType mask, Flags flags=Flags()) const 1 | ||||||
Store the vector data to mem where mask is set. More... | |||||||
void | store (EntryType *mem) const | ||||||
The following store overloads support classes that have a cast operator to EntryType * . | |||||||
template<typename Flags , typename = enable_if<Traits::is_load_store_flag<Flags>::value>> | |||||||
void | store (EntryType *mem, Flags flags) const | ||||||
void | store (EntryType *mem, MaskType mask) const | ||||||
template<typename Flags , typename = enable_if<Traits::is_load_store_flag<Flags>::value>> | |||||||
void | store (EntryType *mem, MaskType mask, Flags flags) const | ||||||
Gather constructors and member functions | |||||||
Constructs or loads a vector from the objects at All gather functions optionally take a mask as last argument. In that case only the entries that are selected in the mask are accessed in memory and copied to the vector. This enables invalid indexes in the Gathers from structured data (AoS: arrays of struct) are possible via a special subscript operator of the container (array). You can use Vc::array and Vc::vector as drop-in replacements for Vc::vector<float> data(100);
std::iota(data.begin(), data.end(), 0.f); // fill with values 0, 1, 2, ...
auto indexes = float_v::IndexType::IndexesFromZero();
float_v gathered = data[indexes]; // gathered == [0, 1, 2, ...]
Alternatively, you can use Vc::Common::AdaptSubscriptOperator to extend a given container class with the necessary subscript operator. Example: template <typename T, typename Allocator = std::allocator<T>>
using my_vector = Vc::Common::AdaptSubscriptOperator<std::vector<T, Allocator>>;
| |||||||
template<typename MT , typename IT , typename = enable_if<Traits::has_subscript_operator<IT>::value>> | |||||||
Vector (const MT *mem, IT &&indexes) | |||||||
Gather constructor. | |||||||
template<typename MT , typename IT , typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>> | |||||||
Vector (const MT *mem, IT &&indexes, MaskArgument mask) | |||||||
Masked gather constructor. | |||||||
template<typename MT , typename IT , typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>> | |||||||
void | gather (const MT *mem, IT &&indexes) | ||||||
Gather function. | |||||||
template<typename MT , typename IT , typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>> | |||||||
void | gather (const MT *mem, IT &&indexes, MaskArgument mask) | ||||||
Masked gather function. | |||||||
Scatter functions | |||||||
Stores a vector to the objects at
| |||||||
template<typename MT , typename IT , typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>> | |||||||
void | scatter (MT *mem, IT &&indexes) const | ||||||
Scatter function. | |||||||
template<typename MT , typename IT , typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>> | |||||||
void | scatter (MT *mem, IT &&indexes, MaskArgument mask) const | ||||||
Masked scatter function. | |||||||
Scalar Subscript Operators | |||||||
EntryType & | operator[] (size_t index) | ||||||
This operator can be used to modify scalar entries of the vector. More... | |||||||
EntryType | operator[] (size_t index) const | ||||||
This operator can be used to read scalar entries of the vector. More... | |||||||
Unary Operators | |||||||
MaskType | operator! () const | ||||||
Determine where the vector is null. More... | |||||||
Vector | operator~ () const | ||||||
Inverts all bits. More... | |||||||
Vector | operator- () const | ||||||
Returns a new vector object with all entries negated. | |||||||
Vector | operator+ () const | ||||||
Returns a copy of the vector object. | |||||||
Increment and Decrement Operators | |||||||
The increment and decrement operators apply the increment/decrement operation per component. The semantics are equal to the semantics of the fundamental arithmetics type
| |||||||
Vector & | operator++ () | ||||||
Vector | operator++ (int) | ||||||
Vector & | operator-- () | ||||||
Vector | operator-- (int) | ||||||
Arithmetic Operations | |||||||
The arithmetic operations are implemented as component-wise application of the operator on the two vector objects. Example:
| |||||||
Vector & | operator+= (const Vector &x) | ||||||
Vector | operator+ (const Vector &x) const | ||||||
Vector & | operator-= (const Vector &x) | ||||||
Vector | operator- (const Vector &x) const | ||||||
Vector & | operator*= (const Vector &x) | ||||||
Vector | operator* (const Vector &x) const | ||||||
Vector & | operator/= (const Vector &x) | ||||||
Vector | operator/ (const Vector &x) const | ||||||
Vector & | operator%= (const Vector &x) | ||||||
Vector | operator% (const Vector &x) const | ||||||
Binary Operations | |||||||
The binary operations are implemented as component-wise application of the operator on the two vector objects. Example:
| |||||||
Vector & | operator|= (const Vector &x) | ||||||
Vector | operator| (const Vector &x) const | ||||||
Vector & | operator&= (const Vector &x) | ||||||
Vector | operator& (const Vector &x) const | ||||||
Vector & | operator^= (const Vector &x) | ||||||
Vector | operator^ (const Vector &x) const | ||||||
Shift Operations | |||||||
The shift operations are implemented as component-wise application of the operator on the two vector objects. Example:
| |||||||
Vector & | operator<<= (const Vector &x) | ||||||
Vector | operator<< (const Vector &x) const | ||||||
Vector & | operator>>= (const Vector &x) | ||||||
Vector | operator>> (const Vector &x) const | ||||||
Comparisons | |||||||
MaskType | operator== (const Vector &x) const | ||||||
MaskType | operator!= (const Vector &x) const | ||||||
MaskType | operator<= (const Vector &x) const | ||||||
MaskType | operator>= (const Vector &x) const | ||||||
MaskType | operator< (const Vector &x) const | ||||||
MaskType | operator> (const Vector &x) const | ||||||
Horizontal Reduction Operations | |||||||
EntryType | min () const | ||||||
Returns the smallest entry in the vector. | |||||||
EntryType | max () const | ||||||
Returns the largest entry in the vector. | |||||||
EntryType | product () const | ||||||
Returns the product of all entries in the vector. | |||||||
EntryType | sum () const | ||||||
Returns the sum of all entries in the vector. | |||||||
Vector | partialSum () const | ||||||
Returns a vector containing the sum of all entries with smaller index. | |||||||
EntryType | min (MaskType mask) const | ||||||
Returns the smallest entry of the vector components selected by mask . | |||||||
EntryType | max (MaskType mask) const | ||||||
Returns the largest entry of the vector components selected by mask . | |||||||
EntryType | product (MaskType mask) const | ||||||
Returns the product of the vector components selected by mask . | |||||||
EntryType | sum (MaskType mask) const | ||||||
Returns the sum of the vector components selected by mask . | |||||||
Shift and Rotate | |||||||
These functions allow to shift or rotate the entries in a vector. All functions with an Example: using namespace Vc;
int_v x;
x = foo.shifted( 1); // [2, 3, 4, 0]
x = foo.shifted( 2); // [3, 4, 0, 0]
x = foo.shifted( 3); // [4, 0, 0, 0]
x = foo.shifted( 4); // [0, 0, 0, 0]
x = foo.shifted(-1); // [0, 1, 2, 3]
x = foo.shifted(-2); // [0, 0, 1, 2]
x = foo.shifted(-3); // [0, 0, 0, 1]
x = foo.shifted(-4); // [0, 0, 0, 0]
x = foo.rotated( 1); // [2, 3, 4, 1]
x = foo.rotated( 2); // [3, 4, 1, 2]
x = foo.rotated( 3); // [4, 1, 2, 3]
x = foo.rotated( 4); // [1, 2, 3, 4]
x = foo.rotated(-1); // [4, 1, 2, 3]
x = foo.rotated(-2); // [3, 4, 1, 2]
x = foo.rotated(-3); // [2, 3, 4, 1]
x = foo.rotated(-4); // [1, 2, 3, 4]
These functions are slightly related to the above swizzles. In any case, they are often useful for communication between SIMD lanes or binary decoding operations.
| |||||||
Vector | shifted (int amount) const | ||||||
Shift vector entries to the left by amount ; shifting in zeros. | |||||||
Vector | shifted (int amount, Vector shiftIn) const | ||||||
Shift vector entries to the left by amount ; shifting in values from shiftIn (instead of zeros). More... | |||||||
Vector | rotated (int amount) const | ||||||
Rotate vector entries to the left by amount . | |||||||
Vector | reversed () const | ||||||
Returns a vector with all components reversed. | |||||||
Apply/Call/Fill Functions | |||||||
There are still many situations where the code needs to switch from SIMD operations to scalar execution. In this case you can, of course rely on operator[]. But there are also a number of functions that can help with common patterns. The apply functions expect a function that returns a scalar value, i.e. a function of the form "T f(T)". The call functions do not return a value and thus the function passed does not need a return value. The fill functions are used to serially set the entries of the vector from the return values of a function. Example: void foo(float_v v) {
}
Of course, you can also use lambdas here:
| |||||||
template<typename F > | |||||||
void | callWithValuesSorted (F &&f) | ||||||
Call f sequentially, starting with the minimum up to the maximum value. | |||||||
template<typename F > | |||||||
void | call (F &&f) const | ||||||
Call f with the scalar entries of the vector. | |||||||
template<typename F > | |||||||
void | call (F &&f, MaskType mask) const | ||||||
As above, but skip the entries where mask is not set. | |||||||
template<typename F > | |||||||
Vector | apply (F &&f) const | ||||||
Call f on every entry of the vector and return the results as a new vector. | |||||||
template<typename F > | |||||||
Vector | apply (F &&f, MaskType mask) const | ||||||
As above, but skip the entries where mask is not set. | |||||||
template<typename IndexT > | |||||||
void | fill (EntryType(&f)(IndexT)) | ||||||
Fill the vector with the values [f(0), f(1), f(2), ...]. | |||||||
void | fill (EntryType(&f)()) | ||||||
Fill the vector with the values [f(), f(), f(), ...]. | |||||||
Static Public Member Functions | |
static constexpr size_t | size () |
Returns the number of scalar components ( \(\mathcal{W}_\mathtt{T}\)) in a vector of this type. More... | |
Generators | |
static Vector | Zero () |
Returns a vector with the entries initialized to zero. | |
static Vector | One () |
Returns a vector with the entries initialized to one. | |
static Vector | IndexesFromZero () |
Returns a vector with the entries initialized to 0, 1, 2, 3, 4, 5, ... | |
static Vector | Random () |
Returns a vector with pseudo-random entries. More... | |
template<typename G > | |
static Vector | generate (G gen) |
Generate a vector object from return values of gen (static variant of fill). | |
Static Public Attributes | |
static constexpr size_t | MemoryAlignment = VectorTraits<T, Abi>::memoryAlignment() |
Specifies the alignment requirement for aligned load and store calls for objects of this vector type. | |
Deprecated Members | |
static constexpr size_t | Size = VectorTraits<T, Abi>::size() |
Returns the number of scalar components ( \(\mathcal{W}_\mathtt{T}\)) in a vector of this type. More... | |
template<typename V2 > | |
V2 | staticCast () const |
Casts the current object to V2 . More... | |
Vector | copySign (Vector reference) const |
Copies the signs of the components of reference to the components of the current vector, returning the result. More... | |
using value_type = EntryType |
using index_type = IndexType |
|
inlinedefault |
Construct a zero-initialized vector object.
This constructor follows the behavior of the underlying arithmetic type T
in that the expression T()
zero-initializes the object. On the other hand the variable x
in T x;
is uninitialized. Since, for class types, both expressions call the default constructor Vector<T> x
must zero-initialize x
as well.
|
inlineexplicit |
|
inlineexplicit |
|
inlineexplicit |
Construct a vector with the entries initialized to 0, 1, 2, 3, 4, 5, ...
|
inlineexplicit |
Explicit conversion (i.e.
static_cast
) from the remaining Vector<U, Abi> types.
x | A vector object to use for initialization of the new vector object. If x contains more entries than the new object the high components will be ignored. If x contains fewer entries than the new object the high components of the new object will be zero-initialized. Type conversion is done according to the standard conversion rules for the underlying fundamental arithmetic types. |
Broadcast Constructor.
Constructs a vector with all entries of the vector filled with the given value.
a | The scalar value to broadcast to all entries of the constructed vector. |
Construct a vector from loading its entries from the array at mem
.
mem | A pointer to data. The pointer must not be aligned on a MemoryAlignment boundary unless you add the Vc::Aligned flag as a second argument. |
Construct a vector from loading its entries from the array at mem
.
mem | A pointer to data. If flags contains the Vc::Aligned flag, the pointer must be aligned on a MemoryAlignment boundary. |
flags | A (combination of) flag object(s), such as Vc::Aligned, Vc::Streaming, Vc::Unaligned, and/or Vc::PrefetchDefault. |
|
inlinestatic |
Returns the number of scalar components ( \(\mathcal{W}_\mathtt{T}\)) in a vector of this type.
The size of the vector. I.e. the number of scalar entries in the vector. Do not make any assumptions about the size of vectors. If you need a vector of float vs. integer of the same size make use of IndexType instead. Note that this still does not guarantee the same size (e.g. double_v on SSE has two entries but there exists no 64 bit integer vector type in Vc - which would have two entries; thus double_v::IndexType is uint_v).
In addition, you can easily use if clauses that compare sizes. The compiler can statically evaluate and fully optimize dead code away (very much like #ifdef, but with syntax checking).
|
inlinestatic |
Returns a vector with pseudo-random entries.
Currently the state of the random number generator cannot be modified and starts off with the same state. Thus you will get the same sequence of numbers for the same sequence of calls.
|
inline |
Load the vector entries from mem
, overwriting the previous values.
mem | A pointer to data. The pointer must not be aligned on a MemoryAlignment boundary unless you add the Vc::Aligned flag as a second argument. |
|
inline |
Load the vector entries from mem
, overwriting the previous values.
mem | A pointer to data. If flags contains the Vc::Aligned flag, the pointer must be aligned on a MemoryAlignment boundary. |
flags | A (combination of) flag object(s), such as Vc::Aligned, Vc::Streaming, Vc::Unaligned, and/or Vc::PrefetchDefault. |
|
inline |
Store the vector data to mem
.
mem | A pointer to memory, where \(\mathcal{W}_\mathtt{T}\) consecutive values will be stored. |
flags | The flags parameter can be used to select e.g. the Vc::Aligned, Vc::Unaligned, Vc::Streaming, and/or Vc::PrefetchDefault flags. |
|
inline |
Store the vector data to mem
where mask
is set.
mem | A pointer to memory, where \(\mathcal{W}_\mathtt{T}\) consecutive values will be stored. |
mask | A mask object that determines which entries of the vector should be stored to mem . |
flags | The flags parameter can be used to select e.g. the Vc::Aligned, Vc::Unaligned, Vc::Streaming, and/or Vc::PrefetchDefault flags. |
i
will be stored to mem[i]
, independent of whether mask[j]
for any j < i
is false
.
|
inline |
Set all entries to zero where the mask is set.
A 4-vector with a mask of [0111]
therefore would set the last three entries to 0.
mask | Selects the entries to be set to zero. |
|
inline |
Set all entries to zero where the mask is not set.
A 4-vector with a mask of [0111]
therefore would set only the first entry to 0.
mask | Selects the entries to not be set to zero. |
|
inline |
Set all entries to the bit representation of a QNaN where the mask is set.
mask | Selects the entries to be set to QNaN. |
|
inline |
This operator can be used to modify scalar entries of the vector.
index | A value between 0 and Size. This value is not checked internally so you must make/be sure it is in range. |
index
.
|
inline |
This operator can be used to read scalar entries of the vector.
index | A value between 0 and Size. This value is not checked internally so you must make/be sure it is in range. |
index
.
|
inline |
Determine where the vector is null.
|
inline |
Inverts all bits.
v & ~v == 0
.T
. Writemask the vector before an assignment.
mask | The writemask to be used. |
The returned object is only to be used for assignments and should not be assigned to a variable.
Examples:
Shift vector entries to the left by amount
; shifting in values from shiftIn (instead of zeros).
This function can be used to create vectors from unaligned memory locations.
Example:
amount | The number of entries to shift by. amount must be between -Size and Size , otherwise the result is undefined. |
shiftIn | The vector of values to shift in. |
this
and shiftIn
concatenated and then shifted by amount
.
|
inline |
Return a sorted copy of the vector.
v[0] <= v[1] <= v[2] <= v[3] ...
Example:
With SSE the output would be:
[1513634383, -963914658, 1763536262, -1285037745] [-1285037745, -963914658, 1513634383, 1763536262]
With the Scalar implementation:
[1513634383] [1513634383]
|
inline |
Casts the current object to V2
.
Vc
.Copies the signs of the components of reference
to the components of the current vector, returning the result.
reference | A vector object that determines the sign of the the result. |
reference
and absolute value taken from the current vector object.
|
static |
Returns the number of scalar components ( \(\mathcal{W}_\mathtt{T}\)) in a vector of this type.
The size of the vector. I.e. the number of scalar entries in the vector. Do not make any assumptions about the size of vectors. If you need a vector of float vs. integer of the same size make use of IndexType instead. Note that this still does not guarantee the same size (e.g. double_v on SSE has two entries but there exists no 64 bit integer vector type in Vc - which would have two entries; thus double_v::IndexType is uint_v).
In addition, you can easily use if clauses that compare sizes. The compiler can statically evaluate and fully optimize dead code away (very much like #ifdef, but with syntax checking).