Horizontal vs. Vertical vectorization
Once the SIMD vectors are initialized with data, they will be operated upon. When operating on vectors, we need to distinguish two directions of operations: horizontal and vertical. The easiest way to understand the difference is by looking at a following diagram:
In the diagram we can distinguish two directions relating to either data orientation or instruction orientation. Vertical vectorization will be a process of operating in an elementwise manner on elements of each vector. For the first ADD operation, the result will be, as if we executed following list of operations:
c0=a0+b0; c1=a1+b1; c2=a2+b2; c3=a3+b3;
Mind that vertical operations can also operate on a single vector, the same way as SQRT operation:
f0=sqrt(e0); f1=sqrt(e1); f2=sqrt(e2); f3=sqrt(e3);
A horizontal operation, or a reduction , is one involving applying an operator between elements of a vector. From the example above this would be HADD operation, which would have the same meaning as:
Another way of remembering the distinction between horizontal and vertical operations is as follows: vertical operation always returns a vector, while horizontal always returns a scalar. By convention names of hoirzontal operations are prefixed with H- letter, such as in HADD.
Invoking operations in UME::SIMD
When operating on vectors simply use overloaded operators, as if you were working with scalars:
UME::SIMD::SIMDVec<float, 4> a, b, c, d, e, f; ... c = a + b; e = c * d;
For additional operations, the ones that don’t have an equivalent C++ operator, you can either use a special namespace UME::SIMD::FUNCTIONS or a Member Function Interface (MFI) invocation convention:
f = UME::SIMD::FUNCTIONS::sqrt(e); // or f = e.sqrt(); // MFI call
MFI invocation convention is especially useful when using UME::SIMD as a code generation target, as it allows invoking every operation supported by the library in the same way. For regular development I advise using operators and functions as this will result in better code readability.
Invocation of a horizontal operation cannot be done using operator syntax, as the concept of reduction operation is not present in current C++ language. You have to therefor use either FUNCTIONS namespace or MFI:
float x = UME::SIMD::FUNCTIONS::hadd(f); // or float x = e.hadd(); // MFI call
Which syntax convention to use is up to you.