//===--- SIMDConcreteOperations.swift -------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2021 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 // //===----------------------------------------------------------------------===// %{ from __future__ import division from SwiftIntTypes import all_integer_types word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 storagescalarCounts = [2,4,8,16,32,64] vectorscalarCounts = storagescalarCounts + [3] }% %for int in all_integer_types(word_bits): % Scalar = int.stdlib_name % for n in vectorscalarCounts: % Vector = "SIMD" + str(n) + "<" + Scalar + ">" % storageN = 4 if n == 3 else n % s = "s" if int.is_signed else "u" % Builtin = "Vec" + str(storageN) + "xInt" + str(int.bits) % MaskExt = "Builtin.sext_Vec" + str(storageN) + "xInt1_" + Builtin % if int.is_signed: extension SIMDMask where Storage == ${Vector} { @_alwaysEmitIntoClient internal init(_ _builtin: Builtin.${Builtin}) { _storage = ${Vector}(_builtin) } @_alwaysEmitIntoClient internal static var allTrue: Self { let zero = ${Vector}() return zero .== zero } /// A vector mask that is the pointwise logical negation of the input. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = !a[i] /// } /// ``` @_alwaysEmitIntoClient public static prefix func .!(a: Self) -> Self { a .^ .allTrue } /// A vector mask that is the pointwise logical conjunction of the inputs. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = a[i] && b[i] /// } /// ``` /// /// Note that unlike the scalar `&&` operator, the SIMD `.&` operator /// always fully evaluates both arguments. @_alwaysEmitIntoClient public static func .&(a: Self, b: Self) -> Self { Self(${Vector}(Builtin.and_${Builtin}( a._storage._storage._value, b._storage._storage._value ))) } /// Replaces `a` with the pointwise logical conjuction of `a` and `b`. /// /// Equivalent to: /// ``` /// for i in a.indices { /// a[i] = a[i] && b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .&=(a: inout Self, b: Self) { a = a .& b } /// A vector mask that is the pointwise exclusive or of the inputs. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = a[i] != b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .^(a: Self, b: Self) -> Self { Self(${Vector}(Builtin.xor_${Builtin}( a._storage._storage._value, b._storage._storage._value ))) } /// Replaces `a` with the pointwise exclusive or of `a` and `b`. /// /// Equivalent to: /// ``` /// for i in a.indices { /// a[i] = a[i] != b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .^=(a: inout Self, b: Self) { a = a .^ b } /// A vector mask that is the pointwise logical disjunction of the inputs. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = a[i] || b[i] /// } /// ``` /// /// Note that unlike the scalar `||` operator, the SIMD `.|` operator /// always fully evaluates both arguments. @_alwaysEmitIntoClient public static func .|(a: Self, b: Self) -> Self { Self(${Vector}(Builtin.or_${Builtin}( a._storage._storage._value, b._storage._storage._value ))) } /// Replaces `a` with the pointwise logical disjunction of `a` and `b`. /// /// Equivalent to: /// ``` /// for i in a.indices { /// a[i] = a[i] || b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .|=(a: inout Self, b: Self) { a = a .| b } /// A vector mask with the result of a pointwise equality comparison. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = a[i] == b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .==(a: Self, b: Self) -> Self { .!(a .^ b) } /// A vector mask with the result of a pointwise inequality comparison. /// /// Equivalent to: /// ``` /// var result = SIMDMask<${Vector}>() /// for i in result.indices { /// result[i] = a[i] != b[i] /// } /// ``` @_alwaysEmitIntoClient public static func .!=(a: Self, b: Self) -> Self { a .^ b } /// Replaces elements of this vector with elements of `other` in the lanes /// where `mask` is `true`. /// /// Equivalent to: /// ``` /// for i in indices { /// if mask[i] { self[i] = other[i] } /// } /// ``` @_alwaysEmitIntoClient public mutating func replace(with other: Self, where mask: Self) { self = replacing(with: other, where: mask) } /// Returns a copy of this vector, with elements replaced by elements of /// `other` in the lanes where `mask` is `true`. /// /// Equivalent to: /// ``` /// var result = Self() /// for i in indices { /// result[i] = mask[i] ? other[i] : self[i] /// } /// ``` @_alwaysEmitIntoClient public func replacing(with other: Self, where mask: Self) -> Self { (self .& .!mask) .| (other .& mask) } } % end extension SIMD${n} where Scalar == ${Scalar} { @_alwaysEmitIntoClient internal init(_ _builtin: Builtin.${Builtin}) { _storage = ${Scalar}.SIMD${storageN}Storage(_builtin) } /// A vector mask with the result of a pointwise equality comparison. @_alwaysEmitIntoClient public static func .==(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_eq_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise inequality comparison. @_alwaysEmitIntoClient public static func .!=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_ne_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise less-than comparison. @_alwaysEmitIntoClient public static func .<(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_${s}lt_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise less-than-or-equal-to comparison. @_alwaysEmitIntoClient public static func .<=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_${s}le_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise greater-than comparison. @_alwaysEmitIntoClient public static func .>(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_${s}gt_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise greater-than-or-equal-to comparison. @_alwaysEmitIntoClient public static func .>=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.cmp_${s}ge_${Builtin}(a._storage._value, b._storage._value) )) } /// The wrapping sum of two vectors. @_alwaysEmitIntoClient public static func &+(a: Self, b: Self) -> Self { Self(Builtin.add_${Builtin}(a._storage._value, b._storage._value)) } /// The wrapping difference of two vectors. @_alwaysEmitIntoClient public static func &-(a: Self, b: Self) -> Self { Self(Builtin.sub_${Builtin}(a._storage._value, b._storage._value)) } /// The pointwise wrapping product of two vectors. @_alwaysEmitIntoClient public static func &*(a: Self, b: Self) -> Self { Self(Builtin.mul_${Builtin}(a._storage._value, b._storage._value)) } /// Updates the left hand side with the wrapping sum of the two /// vectors. @_alwaysEmitIntoClient public static func &+=(a: inout Self, b: Self) { a = a &+ b } /// Updates the left hand side with the wrapping difference of the two /// vectors. @_alwaysEmitIntoClient public static func &-=(a: inout Self, b: Self) { a = a &- b } /// Updates the left hand side with the pointwise wrapping product of two /// vectors. @_alwaysEmitIntoClient public static func &*=(a: inout Self, b: Self) { a = a &* b } } % end %end %for (Scalar, bits) in [('Float16',16), ('Float',32), ('Double',64)]: % for n in vectorscalarCounts: % Vector = "SIMD" + str(n) + "<" + Scalar + ">" % storageN = 4 if n == 3 else n % Builtin = "Vec" + str(storageN) + "xFPIEEE" + str(bits) % VecPre = "Vec" + str(storageN) + "x" % MaskExt = "Builtin.sext_" + VecPre + "Int1_" + VecPre + "Int" + str(bits) % if bits == 16: #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) @available(SwiftStdlib 5.3, *) % end extension SIMD${n} where Scalar == ${Scalar} { @_alwaysEmitIntoClient internal init(_ _builtin: Builtin.${Builtin}) { _storage = ${Scalar}.SIMD${storageN}Storage(_builtin) } /// A vector mask with the result of a pointwise equality comparison. @_alwaysEmitIntoClient public static func .==(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_oeq_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise inequality comparison. @_alwaysEmitIntoClient public static func .!=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_une_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise less-than comparison. @_alwaysEmitIntoClient public static func .<(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_olt_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise less-than-or-equal-to comparison. @_alwaysEmitIntoClient public static func .<=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_ole_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise greater-than comparison. @_alwaysEmitIntoClient public static func .>(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_ogt_${Builtin}(a._storage._value, b._storage._value) )) } /// A vector mask with the result of a pointwise greater-than-or-equal-to comparison. @_alwaysEmitIntoClient public static func .>=(a: Self, b: Self) -> SIMDMask { SIMDMask(${MaskExt}( Builtin.fcmp_oge_${Builtin}(a._storage._value, b._storage._value) )) } } % if bits == 16: #endif % end % end %end