//===--- SIMDVector.swift -------------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2018 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// infix operator .== : ComparisonPrecedence infix operator .!= : ComparisonPrecedence infix operator .< : ComparisonPrecedence infix operator .<= : ComparisonPrecedence infix operator .> : ComparisonPrecedence infix operator .>= : ComparisonPrecedence infix operator .& : LogicalConjunctionPrecedence infix operator .^ : LogicalDisjunctionPrecedence infix operator .| : LogicalDisjunctionPrecedence infix operator .&= : AssignmentPrecedence infix operator .^= : AssignmentPrecedence infix operator .|= : AssignmentPrecedence prefix operator .! /// A type that can function as storage for a SIMD vector type. /// /// The `SIMDStorage` protocol defines a storage layout and provides /// elementwise accesses. Computational operations are defined on the `SIMD` /// protocol, which refines this protocol, and on the concrete types that /// conform to `SIMD`. public protocol SIMDStorage { /// The type of scalars in the vector space. associatedtype Scalar : Codable, Hashable /// The number of scalars, or elements, in the vector. var scalarCount: Int { get } /// Creates a vector with zero in all lanes. init() /// Accesses the element at the specified index. /// /// - Parameter index: The index of the element to access. `index` must be in /// the range `0.. Scalar { get set } } /// A type that can be used as an element in a SIMD vector. public protocol SIMDScalar { associatedtype SIMDMaskScalar : SIMDScalar & FixedWidthInteger & SignedInteger associatedtype SIMD2Storage : SIMDStorage where SIMD2Storage.Scalar == Self associatedtype SIMD4Storage : SIMDStorage where SIMD4Storage.Scalar == Self associatedtype SIMD8Storage : SIMDStorage where SIMD8Storage.Scalar == Self associatedtype SIMD16Storage : SIMDStorage where SIMD16Storage.Scalar == Self associatedtype SIMD32Storage : SIMDStorage where SIMD32Storage.Scalar == Self associatedtype SIMD64Storage : SIMDStorage where SIMD64Storage.Scalar == Self } /// A SIMD vector of a fixed number of elements. public protocol SIMD : SIMDStorage, Codable, Hashable, CustomStringConvertible, ExpressibleByArrayLiteral { /// The mask type resulting from pointwise comparisons of this vector type. associatedtype MaskStorage : SIMD where MaskStorage.Scalar : FixedWidthInteger & SignedInteger } extension SIMD { /// The valid indices for subscripting the vector. @_transparent public var indices: Range { return 0 ..< scalarCount } /// A vector with the specified value in all lanes. @_transparent public init(repeating value: Scalar) { self.init() for i in indices { self[i] = value } } /// Returns a Boolean value indicating whether two vectors are equal. @_transparent public static func ==(lhs: Self, rhs: Self) -> Bool { var result = true for i in lhs.indices { result = result && lhs[i] == rhs[i] } return result } /// Hashes the elements of the vector using the given hasher. @inlinable public func hash(into hasher: inout Hasher) { for i in indices { hasher.combine(self[i]) } } /// Encodes the scalars of this vector into the given encoder in an unkeyed /// container. /// /// This function throws an error if any values are invalid for the given /// encoder's format. /// /// - Parameter encoder: The encoder to write data to. public func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() for i in indices { try container.encode(self[i]) } } /// Creates a new vector by decoding scalars from the given decoder. /// /// This initializer throws an error if reading from the decoder fails, or /// if the data read is corrupted or otherwise invalid. /// /// - Parameter decoder: The decoder to read data from. public init(from decoder: Decoder) throws { self.init() var container = try decoder.unkeyedContainer() guard container.count == scalarCount else { throw DecodingError.dataCorrupted( DecodingError.Context( codingPath: decoder.codingPath, debugDescription: "Expected vector with exactly \(scalarCount) elements." ) ) } for i in indices { self[i] = try container.decode(Scalar.self) } } /// A textual description of the vector. public var description: String { get { return "\(Self.self)(" + indices.map({"\(self[$0])"}).joined(separator: ", ") + ")" } } /// Returns a vector mask with the result of a pointwise equality comparison. @_transparent public static func .==(lhs: Self, rhs: Self) -> SIMDMask { var result = SIMDMask() for i in result.indices { result[i] = lhs[i] == rhs[i] } return result } /// Returns a vector mask with the result of a pointwise inequality /// comparison. @_transparent public static func .!=(lhs: Self, rhs: Self) -> SIMDMask { var result = SIMDMask() for i in result.indices { result[i] = lhs[i] != rhs[i] } return result } /// Replaces elements of this vector with elements of `other` in the lanes /// where `mask` is `true`. @_transparent public mutating func replace(with other: Self, where mask: SIMDMask) { for i in indices { self[i] = mask[i] ? other[i] : self[i] } } /// Creates a vector from the specified elements. /// /// - Parameter scalars: The elements to use in the vector. `scalars` must /// have the same number of elements as the vector type. @inlinable public init(arrayLiteral scalars: Scalar...) { self.init(scalars) } /// Creates a vector from the given sequence. /// /// - Parameter scalars: The elements to use in the vector. `scalars` must /// have the same number of elements as the vector type. @inlinable public init(_ scalars: S) where S.Element == Scalar { self.init() var index = 0 for scalar in scalars { if index == scalarCount { _preconditionFailure("Too many elements in sequence.") } self[index] = scalar index += 1 } if index < scalarCount { _preconditionFailure("Not enough elements in sequence.") } } } // Implementations of comparison operations. These should eventually all // be replaced with @_semantics to lower directly to vector IR nodes. extension SIMD where Scalar : Comparable { /// Returns a vector mask with the result of a pointwise less than /// comparison. @_transparent public static func .<(lhs: Self, rhs: Self) -> SIMDMask { var result = SIMDMask() for i in result.indices { result[i] = lhs[i] < rhs[i] } return result } /// Returns a vector mask with the result of a pointwise less than or equal /// comparison. @_transparent public static func .<=(lhs: Self, rhs: Self) -> SIMDMask { var result = SIMDMask() for i in result.indices { result[i] = lhs[i] <= rhs[i] } return result } } // These operations should never need @_semantics; they should be trivial // wrappers around the core operations defined above. extension SIMD { /// Returns a vector mask with the result of a pointwise equality comparison. @_transparent public static func .==(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .== rhs } /// Returns a vector mask with the result of a pointwise inequality comparison. @_transparent public static func .!=(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .!= rhs } /// Returns a vector mask with the result of a pointwise equality comparison. @_transparent public static func .==(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .== Self(repeating: rhs) } /// Returns a vector mask with the result of a pointwise inequality comparison. @_transparent public static func .!=(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .!= Self(repeating: rhs) } /// Replaces elements of this vector with `other` in the lanes where `mask` /// is `true`. @_transparent public mutating func replace(with other: Scalar, where mask: SIMDMask) { replace(with: Self(repeating: other), where: mask) } /// Returns a copy of this vector, with elements replaced by elements of /// `other` in the lanes where `mask` is `true`. @_transparent public func replacing(with other: Self, where mask: SIMDMask) -> Self { var result = self result.replace(with: other, where: mask) return result } /// Returns a copy of this vector, with elements `other` in the lanes where /// `mask` is `true`. @_transparent public func replacing(with other: Scalar, where mask: SIMDMask) -> Self { return replacing(with: Self(repeating: other), where: mask) } } extension SIMD where Scalar : Comparable { /// Returns a vector mask with the result of a pointwise greater than or /// equal comparison. @_transparent public static func .>=(lhs: Self, rhs: Self) -> SIMDMask { return rhs .<= lhs } /// Returns a vector mask with the result of a pointwise greater than /// comparison. @_transparent public static func .>(lhs: Self, rhs: Self) -> SIMDMask { return rhs .< lhs } /// Returns a vector mask with the result of a pointwise less than comparison. @_transparent public static func .<(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .< rhs } /// Returns a vector mask with the result of a pointwise less than or equal /// comparison. @_transparent public static func .<=(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .<= rhs } /// Returns a vector mask with the result of a pointwise greater than or /// equal comparison. @_transparent public static func .>=(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .>= rhs } /// Returns a vector mask with the result of a pointwise greater than /// comparison. @_transparent public static func .>(lhs: Scalar, rhs: Self) -> SIMDMask { return Self(repeating: lhs) .> rhs } /// Returns a vector mask with the result of a pointwise less than comparison. @_transparent public static func .<(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .< Self(repeating: rhs) } /// Returns a vector mask with the result of a pointwise less than or equal /// comparison. @_transparent public static func .<=(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .<= Self(repeating: rhs) } /// Returns a vector mask with the result of a pointwise greater than or /// equal comparison. @_transparent public static func .>=(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .>= Self(repeating: rhs) } /// Returns a vector mask with the result of a pointwise greater than /// comparison. @_transparent public static func .>(lhs: Self, rhs: Scalar) -> SIMDMask { return lhs .> Self(repeating: rhs) } } extension SIMD where Scalar : FixedWidthInteger { /// A vector with zero in all lanes. @_transparent public static var zero: Self { return Self() } /// Returns a vector with random values from within the specified range in /// all lanes, using the given generator as a source for randomness. @inlinable public static func random( in range: Range, using generator: inout T ) -> Self { var result = Self() for i in result.indices { result[i] = Scalar.random(in: range, using: &generator) } return result } /// Returns a vector with random values from within the specified range in /// all lanes. @inlinable public static func random(in range: Range) -> Self { var g = SystemRandomNumberGenerator() return Self.random(in: range, using: &g) } /// Returns a vector with random values from within the specified range in /// all lanes, using the given generator as a source for randomness. @inlinable public static func random( in range: ClosedRange, using generator: inout T ) -> Self { var result = Self() for i in result.indices { result[i] = Scalar.random(in: range, using: &generator) } return result } /// Returns a vector with random values from within the specified range in /// all lanes. @inlinable public static func random(in range: ClosedRange) -> Self { var g = SystemRandomNumberGenerator() return Self.random(in: range, using: &g) } } extension SIMD where Scalar : FloatingPoint { /// A vector with zero in all lanes. @_transparent public static var zero: Self { return Self() } } extension SIMD where Scalar : BinaryFloatingPoint, Scalar.RawSignificand : FixedWidthInteger { /// Returns a vector with random values from within the specified range in /// all lanes, using the given generator as a source for randomness. @inlinable public static func random( in range: Range, using generator: inout T ) -> Self { var result = Self() for i in result.indices { result[i] = Scalar.random(in: range, using: &generator) } return result } /// Returns a vector with random values from within the specified range in /// all lanes. @inlinable public static func random(in range: Range) -> Self { var g = SystemRandomNumberGenerator() return Self.random(in: range, using: &g) } /// Returns a vector with random values from within the specified range in /// all lanes, using the given generator as a source for randomness. @inlinable public static func random( in range: ClosedRange, using generator: inout T ) -> Self { var result = Self() for i in result.indices { result[i] = Scalar.random(in: range, using: &generator) } return result } /// Returns a vector with random values from within the specified range in /// all lanes. @inlinable public static func random(in range: ClosedRange) -> Self { var g = SystemRandomNumberGenerator() return Self.random(in: range, using: &g) } } @_fixed_layout public struct SIMDMask : SIMD where Storage : SIMD, Storage.Scalar : FixedWidthInteger & SignedInteger { public var _storage : Storage public typealias MaskStorage = Storage public typealias Scalar = Bool @_transparent public var scalarCount: Int { return _storage.scalarCount } @_transparent public init() { _storage = Storage() } @_transparent public init(_ _storage: Storage) { self._storage = _storage } public subscript(index: Int) -> Bool { @_transparent get { _precondition(indices.contains(index)) return _storage[index] < 0 } @_transparent set { _precondition(indices.contains(index)) _storage[index] = newValue ? -1 : 0 } } } extension SIMDMask { /// Returns a vector mask with `true` or `false` randomly assigned in each /// lane, using the given generator as a source for randomness. @inlinable public static func random(using generator: inout T) -> SIMDMask { var result = SIMDMask() for i in result.indices { result[i] = Bool.random(using: &generator) } return result } /// Returns a vector mask with `true` or `false` randomly assigned in each /// lane. @inlinable public static func random() -> SIMDMask { var g = SystemRandomNumberGenerator() return SIMDMask.random(using: &g) } } // Implementations of integer operations. These should eventually all // be replaced with @_semantics to lower directly to vector IR nodes. extension SIMD where Scalar : FixedWidthInteger { @_transparent public var leadingZeroBitCount: Self { var result = Self() for i in indices { result[i] = Scalar(self[i].leadingZeroBitCount) } return result } @_transparent public var trailingZeroBitCount: Self { var result = Self() for i in indices { result[i] = Scalar(self[i].trailingZeroBitCount) } return result } @_transparent public var nonzeroBitCount: Self { var result = Self() for i in indices { result[i] = Scalar(self[i].nonzeroBitCount) } return result } @_transparent public static prefix func ~(rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = ~rhs[i] } return result } @_transparent public static func &(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] & rhs[i] } return result } @_transparent public static func ^(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] ^ rhs[i] } return result } @_transparent public static func |(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] | rhs[i] } return result } @_transparent public static func &<<(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] &<< rhs[i] } return result } @_transparent public static func &>>(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] &>> rhs[i] } return result } @_transparent public static func &+(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] &+ rhs[i] } return result } @_transparent public static func &-(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] &- rhs[i] } return result } @_transparent public static func &*(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] &* rhs[i] } return result } @_transparent public static func /(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] / rhs[i] } return result } @_transparent public static func %(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] % rhs[i] } return result } } // Implementations of floating-point operations. These should eventually all // be replaced with @_semantics to lower directly to vector IR nodes. extension SIMD where Scalar : FloatingPoint { @_transparent public static func +(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] + rhs[i] } return result } @_transparent public static func -(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] - rhs[i] } return result } @_transparent public static func *(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] * rhs[i] } return result } @_transparent public static func /(lhs: Self, rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = lhs[i] / rhs[i] } return result } @_transparent public func addingProduct(_ lhs: Self, _ rhs: Self) -> Self { var result = Self() for i in result.indices { result[i] = self[i].addingProduct(lhs[i], rhs[i]) } return result } @_transparent public func squareRoot( ) -> Self { var result = Self() for i in result.indices { result[i] = self[i].squareRoot() } return result } @_transparent public func rounded(_ rule: FloatingPointRoundingRule) -> Self { var result = Self() for i in result.indices { result[i] = self[i].rounded(rule) } return result } } extension SIMDMask { @_transparent public static prefix func .!(rhs: SIMDMask) -> SIMDMask { return SIMDMask(~rhs._storage) } @_transparent public static func .&(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask { return SIMDMask(lhs._storage & rhs._storage) } @_transparent public static func .^(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask { return SIMDMask(lhs._storage ^ rhs._storage) } @_transparent public static func .|(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask { return SIMDMask(lhs._storage | rhs._storage) } } // These operations should never need @_semantics; they should be trivial // wrappers around the core operations defined above. extension SIMD where Scalar : FixedWidthInteger { @_transparent public static func &(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) & rhs } @_transparent public static func ^(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) ^ rhs } @_transparent public static func |(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) | rhs } @_transparent public static func &<<(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &<< rhs } @_transparent public static func &>>(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &>> rhs } @_transparent public static func &+(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &+ rhs } @_transparent public static func &-(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &- rhs } @_transparent public static func &*(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &* rhs } @_transparent public static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs } @_transparent public static func %(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) % rhs } @_transparent public static func &(lhs: Self, rhs: Scalar) -> Self { return lhs & Self(repeating: rhs) } @_transparent public static func ^(lhs: Self, rhs: Scalar) -> Self { return lhs ^ Self(repeating: rhs) } @_transparent public static func |(lhs: Self, rhs: Scalar) -> Self { return lhs | Self(repeating: rhs) } @_transparent public static func &<<(lhs: Self, rhs: Scalar) -> Self { return lhs &<< Self(repeating: rhs) } @_transparent public static func &>>(lhs: Self, rhs: Scalar) -> Self { return lhs &>> Self(repeating: rhs) } @_transparent public static func &+(lhs: Self, rhs: Scalar) -> Self { return lhs &+ Self(repeating: rhs) } @_transparent public static func &-(lhs: Self, rhs: Scalar) -> Self { return lhs &- Self(repeating: rhs) } @_transparent public static func &*(lhs: Self, rhs: Scalar) -> Self { return lhs &* Self(repeating: rhs) } @_transparent public static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) } @_transparent public static func %(lhs: Self, rhs: Scalar) -> Self { return lhs % Self(repeating: rhs) } @_transparent public static func &=(lhs: inout Self, rhs: Self) { lhs = lhs & rhs } @_transparent public static func ^=(lhs: inout Self, rhs: Self) { lhs = lhs ^ rhs } @_transparent public static func |=(lhs: inout Self, rhs: Self) { lhs = lhs | rhs } @_transparent public static func &<<=(lhs: inout Self, rhs: Self) { lhs = lhs &<< rhs } @_transparent public static func &>>=(lhs: inout Self, rhs: Self) { lhs = lhs &>> rhs } @_transparent public static func &+=(lhs: inout Self, rhs: Self) { lhs = lhs &+ rhs } @_transparent public static func &-=(lhs: inout Self, rhs: Self) { lhs = lhs &- rhs } @_transparent public static func &*=(lhs: inout Self, rhs: Self) { lhs = lhs &* rhs } @_transparent public static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs } @_transparent public static func %=(lhs: inout Self, rhs: Self) { lhs = lhs % rhs } @_transparent public static func &=(lhs: inout Self, rhs: Scalar) { lhs = lhs & rhs } @_transparent public static func ^=(lhs: inout Self, rhs: Scalar) { lhs = lhs ^ rhs } @_transparent public static func |=(lhs: inout Self, rhs: Scalar) { lhs = lhs | rhs } @_transparent public static func &<<=(lhs: inout Self, rhs: Scalar) { lhs = lhs &<< rhs } @_transparent public static func &>>=(lhs: inout Self, rhs: Scalar) { lhs = lhs &>> rhs } @_transparent public static func &+=(lhs: inout Self, rhs: Scalar) { lhs = lhs &+ rhs } @_transparent public static func &-=(lhs: inout Self, rhs: Scalar) { lhs = lhs &- rhs } @_transparent public static func &*=(lhs: inout Self, rhs: Scalar) { lhs = lhs &* rhs } @_transparent public static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs } @_transparent public static func %=(lhs: inout Self, rhs: Scalar) { lhs = lhs % rhs } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead") public static func +(lhs: Self, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead") public static func -(lhs: Self, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead") public static func *(lhs: Self, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead") public static func +(lhs: Self, rhs: Scalar) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead") public static func -(lhs: Self, rhs: Scalar) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead") public static func *(lhs: Self, rhs: Scalar) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead") public static func +(lhs: Scalar, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead") public static func -(lhs: Scalar, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead") public static func *(lhs: Scalar, rhs: Self) -> Self { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead") public static func +=(lhs: inout Self, rhs: Self) { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead") public static func -=(lhs: inout Self, rhs: Self) { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead") public static func *=(lhs: inout Self, rhs: Self) { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead") public static func +=(lhs: inout Self, rhs: Scalar) { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead") public static func -=(lhs: inout Self, rhs: Scalar) { fatalError() } @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead") public static func *=(lhs: inout Self, rhs: Scalar) { fatalError() } } extension SIMD where Scalar : FloatingPoint { @_transparent public static prefix func -(rhs: Self) -> Self { return 0 - rhs } @_transparent public static func +(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) + rhs } @_transparent public static func -(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) - rhs } @_transparent public static func *(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) * rhs } @_transparent public static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs } @_transparent public static func +(lhs: Self, rhs: Scalar) -> Self { return lhs + Self(repeating: rhs) } @_transparent public static func -(lhs: Self, rhs: Scalar) -> Self { return lhs - Self(repeating: rhs) } @_transparent public static func *(lhs: Self, rhs: Scalar) -> Self { return lhs * Self(repeating: rhs) } @_transparent public static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) } @_transparent public static func +=(lhs: inout Self, rhs: Self) { lhs = lhs + rhs } @_transparent public static func -=(lhs: inout Self, rhs: Self) { lhs = lhs - rhs } @_transparent public static func *=(lhs: inout Self, rhs: Self) { lhs = lhs * rhs } @_transparent public static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs } @_transparent public static func +=(lhs: inout Self, rhs: Scalar) { lhs = lhs + rhs } @_transparent public static func -=(lhs: inout Self, rhs: Scalar) { lhs = lhs - rhs } @_transparent public static func *=(lhs: inout Self, rhs: Scalar) { lhs = lhs * rhs } @_transparent public static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs } @_transparent public func addingProduct(_ lhs: Scalar, _ rhs: Self) -> Self { return self.addingProduct(Self(repeating: lhs), rhs) } @_transparent public func addingProduct(_ lhs: Self, _ rhs: Scalar) -> Self { return self.addingProduct(lhs, Self(repeating: rhs)) } @_transparent public mutating func addProduct(_ lhs: Self, _ rhs: Self) { self = self.addingProduct(lhs, rhs) } @_transparent public mutating func addProduct(_ lhs: Scalar, _ rhs: Self) { self = self.addingProduct(lhs, rhs) } @_transparent public mutating func addProduct(_ lhs: Self, _ rhs: Scalar) { self = self.addingProduct(lhs, rhs) } @_transparent public mutating func formSquareRoot( ) { self = self.squareRoot() } @_transparent public mutating func round(_ rule: FloatingPointRoundingRule) { self = self.rounded(rule) } } extension SIMDMask { @_transparent public static func .&(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .& rhs } @_transparent public static func .^(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .^ rhs } @_transparent public static func .|(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .| rhs } @_transparent public static func .&(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .& SIMDMask(repeating: rhs) } @_transparent public static func .^(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .^ SIMDMask(repeating: rhs) } @_transparent public static func .|(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .| SIMDMask(repeating: rhs) } @_transparent public static func .&=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .& rhs } @_transparent public static func .^=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .^ rhs } @_transparent public static func .|=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .| rhs } @_transparent public static func .&=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .& rhs } @_transparent public static func .^=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .^ rhs } @_transparent public static func .|=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .| rhs } }