CPUs often support specialized vector types and vector operations (aka media instructions). Vector types are a fixed array of floating or integer types, and vector operations operate simultaneously on them.
alias int4 = __vector(int[4]);
All the basic integer types can be used as base types, both as signed and as
unsigned: byte, short, int, long. In addition,
float and double can be used to build floating-point vector
types, and void to build vectors of untyped data. Only sizes that are
positive power-of-two multiples of the base type size are currently allowed.
The core.simd module has the following shorthand aliases for commonly
supported vector types:
byte8, byte16, byte32, byte64,
double1, double2, double4, double8,
float2, float4, float8, float16,
int2, int4, int8, int16,
long1, long2, long4, long8,
short4, short8, short16, short32,
ubyte8, ubyte16, ubyte32, ubyte64,
uint2, uint4, uint8, uint16,
ulong1, ulong2, ulong4, ulong8,
ushort4, ushort8, ushort16, ushort32,
void8, void16, void32, void64.
All these aliases correspond to __vector(type[N]).
Which vector types are supported depends on the target. Only vector types that are implemented for the current architecture are supported at compile-time. Vector operations that are not supported in hardware cause GNU D to synthesize the instructions using a narrower mode.
alias v4i = __vector(int[4]); alias v128f = __vector(float[128]); // Error: not supported on this platform int4 a, b, c; c = a * b; // Natively supported on x86 with SSE4 c = a / b; // Always synthesized
Vector types can be used with a subset of normal D operations. Currently, GNU
D allows using the following operators on these types: +, -, *, /,
unary+, unary-.
alias int4 = __vector(int[4]); int4 a, b, c; c = a + b;
It is also possible to use shifting operators <<, >>, the modulus
operator %, logical operations &, |, ^, and the complement
operator unary~ on integer-type vectors.
For convenience, it is allowed to use a binary vector operation where one operand is a scalar. In that case the compiler transforms the scalar operand into a vector where each element is the scalar from the operation. The transformation happens only if the scalar could be safely converted to the vector-element type. Consider the following code.
alias int4 = __vector(int[4]); int4 a, b; long l; a = b + 1; // a = b + [1,1,1,1]; a = 2 * b; // a = [2,2,2,2] * b; a = l + a; // Error, incompatible types.
Vector comparison is supported with standard comparison operators:
==, !=, <, <=, >, >=. Comparison operands can be vector expressions of
integer-type or real-type. Comparison between integer-type vectors and
real-type vectors are not supported. The result of the comparison is a vector
of the same width and number of elements as the comparison operands with a
signed integral element type.
Vectors are compared element-wise producing 0 when comparison is false and -1 (constant of the appropriate type where all bits are set) otherwise. Consider the following example.
alias int4 = __vector(int[4]); int4 a = [1,2,3,4]; int4 b = [3,2,1,4]; int4 c; c = a > b; // The result would be [0, 0,-1, 0] c = a == b; // The result would be [0,-1, 0,-1]