<div dir="ltr">protocol VectorStorage {<br>    associatedtype A<br>    associatedtype B<br>    associatedtype C<br>    associatedtype D<br>    var elements: (A, B, C, D) { get set }<br>    init(elements: (A, B, C, D))<br>}<br>struct VectorStorage2&lt;T&gt; : VectorStorage {<br>    var elements: (T, T, Void, Void)<br>}<br>struct VectorStorage3&lt;T&gt; : VectorStorage {<br>    var elements: (T, T, T, Void)<br>}<br><br>protocol VectorIndex {<br>    associatedtype StorageOf8BitElements: VectorStorage<br>    associatedtype StorageOf16BitElements: VectorStorage<br>    associatedtype StorageOf32BitElements: VectorStorage<br>    associatedtype StorageOf64BitElements: VectorStorage<br>    static func vectorStorage&lt;V: Vector&gt;(for: V.Type, from fn: (Self) -&gt; V.Element) -&gt; V.Storage<br>        where V.Index == Self<br>    func getElement&lt;V: Vector&gt;(from: V) -&gt; V.Element where V.Index == Self<br>    func setElement&lt;V: Vector&gt;(of vector: inout V, to value: V.Element) where V.Index == Self<br>}<br>enum Index2 : VectorIndex {<br>    typealias StorageOf8BitElements = VectorStorage2&lt;UInt8&gt;<br>    typealias StorageOf16BitElements = VectorStorage2&lt;UInt16&gt;<br>    typealias StorageOf32BitElements = VectorStorage2&lt;UInt32&gt;<br>    typealias StorageOf64BitElements = VectorStorage2&lt;UInt64&gt;<br>    case i0, i1<br>    static func vectorStorage&lt;V: Vector&gt;(for: V.Type, from fn: (Index2) -&gt; V.Element) -&gt; V.Storage<br>        where V.Index == Index2<br>    {<br>        let storage = V.Storage.init(elements: (<br>            unsafeBitCast(fn(.i0), to: V.Storage.A.self),<br>            unsafeBitCast(fn(.i1), to: V.Storage.B.self),<br>            () as! V.Storage.C,<br>            () as! V.Storage.D<br>        ))<br>        return storage<br>    }<br>    func getElement&lt;V: Vector&gt;(from vector: V) -&gt; V.Element where V.Index == Index2 {<br>        switch self {<br>        case .i0: return unsafeBitCast(vector.storage.elements.0, to: V.Element.self)<br>        case .i1: return unsafeBitCast(vector.storage.elements.1, to: V.Element.self)<br>        }<br>    }<br>    func setElement&lt;V: Vector&gt;(of vector: inout V, to value: V.Element) where V.Index == Index2 {<br>        switch self {<br>        case .i0: vector.storage.elements.0 = unsafeBitCast(value, to: V.Storage.A.self)<br>        case .i1: vector.storage.elements.1 = unsafeBitCast(value, to: V.Storage.B.self)<br>        }<br>    }<br>}<br>enum Index3 : VectorIndex {<br>    typealias StorageOf8BitElements = VectorStorage3&lt;UInt8&gt;<br>    typealias StorageOf16BitElements = VectorStorage3&lt;UInt16&gt;<br>    typealias StorageOf32BitElements = VectorStorage3&lt;UInt32&gt;<br>    typealias StorageOf64BitElements = VectorStorage3&lt;UInt64&gt;<br>    case i0, i1, i2<br>    static func vectorStorage&lt;V: Vector&gt;(for: V.Type, from fn: (Index3) -&gt; V.Element) -&gt; V.Storage<br>        where V.Index == Index3<br>    {<br>        let storage = V.Storage.init(elements: (<br>            unsafeBitCast(fn(.i0), to: V.Storage.A.self),<br>            unsafeBitCast(fn(.i1), to: V.Storage.B.self),<br>            unsafeBitCast(fn(.i2), to: V.Storage.C.self),<br>            () as! V.Storage.D<br>        ))<br>        return storage<br>    }<br>    func getElement&lt;V: Vector&gt;(from vector: V) -&gt; V.Element where V.Index == Index3 {<br>        switch self {<br>        case .i0: return unsafeBitCast(vector.storage.elements.0, to: V.Element.self)<br>        case .i1: return unsafeBitCast(vector.storage.elements.1, to: V.Element.self)<br>        case .i2: return unsafeBitCast(vector.storage.elements.2, to: V.Element.self)<br>        }<br>    }<br>    func setElement&lt;V: Vector&gt;(of vector: inout V, to value: V.Element) where V.Index == Index3 {<br>        switch self {<br>        case .i0: vector.storage.elements.0 = unsafeBitCast(value, to: V.Storage.A.self)<br>        case .i1: vector.storage.elements.1 = unsafeBitCast(value, to: V.Storage.B.self)<br>        case .i2: vector.storage.elements.2 = unsafeBitCast(value, to: V.Storage.C.self)<br>        }<br>    }<br>}<br>protocol Vector {<br>    associatedtype Index: VectorIndex<br>    associatedtype Element<br>    associatedtype Storage: VectorStorage<br>    var storage: Storage { get set }<br>    init(elementForIndex: (Index) -&gt; Element)<br>}<br>extension Vector {<br>    subscript(index: Index) -&gt; Element {<br>        get { return index.getElement(from: self) }<br>        set { index.setElement(of: &amp;self, to: newValue) }<br>    }<br>    func map&lt;NewElement&gt;(transform: (Element) -&gt; NewElement) -&gt; SV32&lt;Index, NewElement&gt; {<br>        return SV32&lt;Index, NewElement&gt; { index in transform(self[index]) }<br>    }<br>    func map&lt;NewElement&gt;(transform: (Element) -&gt; NewElement) -&gt; SV64&lt;Index, NewElement&gt; {<br>        return SV64&lt;Index, NewElement&gt; { index in transform(self[index]) }<br>    }<br>}<br><br>protocol VectorElement {<br>    associatedtype BitPattern<br>}<br><br><br>extension UInt8 : VectorElement { typealias BitPattern = UInt8 }<br>extension UInt16 : VectorElement { typealias BitPattern = UInt16 }<br>extension UInt32 : VectorElement { typealias BitPattern = UInt32 }<br>extension UInt64 : VectorElement { typealias BitPattern = UInt64 }<br>extension Int : VectorElement { typealias BitPattern = UInt64 }<br>extension Double : VectorElement { typealias BitPattern = UInt64 }<br>extension Float : VectorElement { typealias BitPattern = UInt32 }<br><br><br>struct SV32&lt;I: VectorIndex, E: VectorElement&gt; : Vector where<br>    E.BitPattern == UInt32<br>{<br>    typealias Index = I<br>    typealias Element = E<br>    var storage: Index.StorageOf32BitElements<br>    init(elementForIndex: (Index) -&gt; Element) {<br>        self.storage = Index.vectorStorage(for: SV32.self, from: elementForIndex)<br>    }<br>}<br>struct SV64&lt;I: VectorIndex, E: VectorElement&gt; : Vector where<br>    E.BitPattern == UInt64<br>{<br>    typealias Index = I<br>    typealias Element = E<br>    var storage: Index.StorageOf64BitElements<br>    init(elementForIndex: (Index) -&gt; Element) {<br>        self.storage = Index.vectorStorage(for: SV64.self, from: elementForIndex)<br>    }<br>}<br><br>protocol DoubleConvertible {<br>    var double: Double { get }<br>}<br>extension Float : DoubleConvertible {<br>    var double: Double { return Double(self) }<br>}<br>extension Vector where Element: DoubleConvertible {<br>    var doubleVector: SV64&lt;Index, Double&gt; { return self.map { $0.double }  }<br>}<br>extension Vector {<br>    func casted&lt;V: Vector&gt;(to _: V.Type) -&gt; V {<br>        fatalError()<br>    }<br>}<br><br>func test() {<br>    var v = SV32&lt;Index3, Float&gt; { _ in 0.0 }<br>    <br>    v[.i0] = 1.1<br>    v[.i1] = 2.2<br>    v[.i2] = 3.3<br>    <br>    let dv = v.doubleVector<br>    <br>    print(dv[.i0])<br>    print(dv[.i1])<br>    print(dv[.i2])<br>}<br>test()</div>