If you program for macOS or iOS, you may already be familiar with the <simd/simd.h> module, which provides a set of architecture-agnostic "simd vector" and matrix types for C, Objective-C, and C++. A limited subset of that functionality is currently exposed to Swift via the simd overlay.
[A note on the terminology "simd vector": what I mean by this is a small (<= 64B) fixed-size "vector" that provides elementwise arithmetic and comparisons as well as member access and a small set of additional operations. These are not general fixed-size arrays (though they are fixed-size), nor are they precisely elements of a mathematical vector space (though they provide all of those operations). It is best to think of them as just another fundamental data type supported by modern CPU architectures. This family of types and functions makes a uniform semantics available for all target architectures.]
I plan to expose the full set of functionality (plus some additional goodies that are hard to do well in C) as a part of the swift standard library. This pitch is the first step of that process.
There's a work-in progress branch here that you're welcome to play with: https://github.com/stephentyrone/swift/tree/simd
For 5.0, I would like to implement the following two pieces:
(a) getting the full set of basic vector types into the stdlib.
(b) teaching the importer how to map between clang ext_vectors in C / C++ and Swift.
This pitch is mainly about part (a). The set of types defined are as follows:
- Signed and unsigned integer vector types. These have names of the form
[U]IntN.VectorM
. E.g. anInt8.Vector16
is a vector of 16Int8
s. AUInt32.Vector8
is a vector of 8UInt32
s. - Floating-point vector types. These are
Float.VectorM
andDouble.VectorM
. - "Predicate" vector types. These represent masks that result from elementwise comparison operations. These have the form
SIMDPredicateNxM
(this is a placeholder name, but the specific name is not too consequential because you rarely use these types explicitly).
Arbitrary vectors sizes are not supported with any of these types; there is support for vectors of size 2, 3, 4, 8, 16, 32, or 64, with an upper bound of 64B on the total size of the vector. This covers 99% of use cases, but sorry, no support for Vector7.
There is also an associated protocol hierarchy; the base is SIMDVector, which conforms to Collection, Hashable, etc, and also requires some useful inits and a Predicate associatedtype. The bulk of these conformances can be defaulted. This is refined by the following three protocols:
- SIMDIntegerVector: adds comparisons, leading/trailing zeros, popcount, bitwise operations, smart and masking shifts, masking arithmetic operations, ability to create random vectors.
- SIMDFloatingPointVector: adds comparisons, arithmetic, rounding, ability to create random vectors.
- SIMDPredicate: adds boolean operations, ability to create random vectors.
There is also a set of protocols of the form SIMDVectorN, which are used to enforce constraints that some heterogenous operations on vectors require vectors of the same size, as well as provide accessors for halves of vectors and the x
, y
, z
, w
components of 2, 3 and 4 element vectors.
There's quite a bit of other functionality implemented on the types themselves, and I'll be filling in missing details over the next week or two, but I would like to go ahead and get the pitch process started now.
This first post is pretty high-level because I don't know which specific details will interest people. Please let me know what you would like to know more about and I'll write more low-level explanations.