Skip to content

Add set accessors to SIMD subscripts #73344

Open
@JessyCatterwaul

Description

@JessyCatterwaul

Motivation

SIMD has subscripts available for accessing components at various indices. This offers some of the standard swizzling capabilities that you'd find in a shading language like Metal, but not enough to be considered fully-featured. This makes working with vectors cumbersome in Swift.

Metal:

float3 vector = {1, 2, 3};
vector.xy;
vector.xy = {4, 5};

Swift:

var vector: SIMD3<Float> = [1, 2, 3]
vector[[0, 1] as SIMD2]  // ✅
vector[[0, 1]] = [4, 5] // ❌ Cannot assign through subscript: subscript is get-only

Proposed solution

  1. Add set accessors to the existing subscripts.
  2. Also, add defaults, to make assigning to the early parts of a vector especially easy.
  3. Add overloads for using indices directly, instead of having to pass in SIMDs.
    vector[0, 2] is better than vector[[0, 2]].

That would replace and add to the following, which we can use presently:

// TODO: Use macros to support all SIMD types.
public extension SIMD where Scalar: SIMDScalar {
  /// The ".xy" of a vector.
  ///
  /// - Note: Acts as a default for the subscript that accesses elements based on a `SIMD2<Index>`,
  ///   and adds write capability to it.
  subscript(index0: Int = 0, index1: Int = 1) -> SIMD2<Scalar> {
    get { self[[index0, index1]] }
    set {
      for index in [index0, index1].indexed() {
        self[index.element] = newValue[index.index]
      }
    }
  }

  /// The ".xyz" of a vector.
  ///
  /// - Note: Acts as a default for the subscript that accesses elements based on a `SIMD3<Index>`,
  ///   and adds write capability to it.
  subscript(index0: Int = 0, index1: Int = 1, index2: Int = 2) -> SIMD3<Scalar> {
    get { self[[index0, index1, index2]] }
    set {
      for index in [index0, index1, index2].indexed() {
        self[index.element] = newValue[index.index]
      }
    }
  }
}
var double3 = SIMD3((10...12).map(Double.init))
var double4 = SIMD4((1...4).map(Double.init))

XCTAssertEqual(double3[], [10, 11] as SIMD2)
XCTAssertEqual(double4[], [1, 2, 3] as SIMD3)

double4[] += double3
XCTAssertEqual(double4, [11, 13, 15, 4])

double3[] += [0, 1] as SIMD2
XCTAssertEqual(double3, [10, 12, 12])

double3[1, 2] = [-1, -2]
XCTAssertEqual(double3, [10, -1, -2])

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureA feature request or implementationsimdstandard libraryArea: Standard library umbrella

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions