| %{ |
| 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 n in vectorscalarCounts: |
| % storageN = 4 if n == 3 else n |
| @_fixed_layout |
| public struct SIMD${n}<Scalar> : SIMD where Scalar: SIMDScalar { |
| |
| public var _storage: Scalar.SIMD${storageN}Storage |
| |
| public typealias MaskStorage = SIMD${n}<Scalar.SIMDMaskScalar> |
| |
| @_transparent |
| public var scalarCount: Int { |
| return ${n} |
| } |
| |
| @_transparent |
| public init() { |
| _storage = Scalar.SIMD${storageN}Storage() |
| } |
| |
| public subscript(index: Int) -> Scalar { |
| @_transparent get { |
| _precondition(indices.contains(index)) |
| return _storage[index] |
| } |
| @_transparent set { |
| _precondition(indices.contains(index)) |
| _storage[index] = newValue |
| } |
| } |
| |
| @_transparent |
| public init(${', '.join(['_ v' + str(i) + ': Scalar' for i in range(n)])}) { |
| self.init() |
| % for i in range(n): |
| self[${i}] = v${i} |
| % end |
| } |
| |
| % if n <= 4: |
| @_transparent |
| public init(${', '.join([c + ': Scalar' for c in 'xyzw'[:n]])}) { |
| self.init(${', '.join('xyzw'[:n])}) |
| } |
| |
| % for i in range(n): |
| @_transparent |
| public var ${'xyzw'[i]}: Scalar { |
| @_transparent get { return self[${i}]} |
| @_transparent set { self[${i}] = newValue } |
| } |
| |
| % end |
| % end |
| % if n >= 4: |
| @_transparent |
| public init(lowHalf: SIMD${n/2}<Scalar>, highHalf: SIMD${n/2}<Scalar>) { |
| self.init() |
| self.lowHalf = lowHalf |
| self.highHalf = highHalf |
| } |
| |
| % for (half,indx) in [('low','i'), ('high',str(n/2)+'+i'), ('even','2*i'), ('odd','2*i+1')]: |
| public var ${half}Half: SIMD${n/2}<Scalar> { |
| @inlinable get { |
| var result = SIMD${n/2}<Scalar>() |
| for i in result.indices { result[i] = self[${indx}] } |
| return result |
| } |
| @inlinable set { |
| for i in newValue.indices { self[${indx}] = newValue[i] } |
| } |
| } |
| |
| % end |
| % end |
| } |
| |
| public extension SIMD${n} where Scalar : FixedWidthInteger { |
| @inlinable |
| init<Other>(truncatingIfNeeded other: SIMD${n}<Other>) |
| where Other : FixedWidthInteger { |
| self.init() |
| for i in indices { self[i] = Scalar(truncatingIfNeeded: other[i]) } |
| } |
| |
| @inlinable |
| init<Other>(clamping other: SIMD${n}<Other>) |
| where Other : FixedWidthInteger { |
| self.init() |
| for i in indices { self[i] = Scalar(clamping: other[i]) } |
| } |
| |
| @inlinable |
| init<Other>( |
| _ other: SIMD${n}<Other>, |
| rounding rule: FloatingPointRoundingRule = .towardZero |
| ) |
| where Other : BinaryFloatingPoint { |
| self.init() |
| // TODO: this should clamp |
| for i in indices { self[i] = Scalar(other[i].rounded(rule)) } |
| } |
| } |
| |
| |
| public extension SIMD${n} where Scalar : BinaryFloatingPoint { |
| @inlinable |
| init<Other>(_ other: SIMD${n}<Other>) |
| where Other : FixedWidthInteger { |
| self.init() |
| for i in indices { self[i] = Scalar(other[i]) } |
| } |
| |
| @inlinable |
| init<Other>(_ other: SIMD${n}<Other>) |
| where Other : BinaryFloatingPoint { |
| self.init() |
| for i in indices { self[i] = Scalar(other[i]) } |
| } |
| } |
| |
| %end |
| |
| %for self_type in all_integer_types(word_bits): |
| % Self = self_type.stdlib_name |
| % BuiltinName = self_type.builtin_name |
| % Mask = Self if self_type.is_signed else self_type.get_opposite_signedness().stdlib_name |
| extension ${Self} : SIMDScalar { |
| |
| public typealias SIMDMaskScalar = ${Mask} |
| |
| % for n in storagescalarCounts: |
| % bytes = n * self_type.bits / 8 |
| @_fixed_layout |
| @_alignment(${bytes if bytes <= 16 else 16}) |
| public struct SIMD${n}Storage : SIMDStorage { |
| |
| public var _value: Builtin.Vec${n}x${BuiltinName} |
| |
| @_transparent |
| public var scalarCount: Int { |
| return ${n} |
| } |
| |
| @_transparent |
| public init() { |
| _value = Builtin.zeroInitializer() |
| } |
| |
| public subscript(index: Int) -> ${Self} { |
| @_transparent |
| get { |
| return ${Self}(Builtin.extractelement_Vec${n}x${BuiltinName}_Int32( |
| _value, Int32(truncatingIfNeeded: index)._value |
| )) |
| } |
| @_transparent |
| set { |
| _value = Builtin.insertelement_Vec${n}x${BuiltinName}_${BuiltinName}_Int32( |
| _value, newValue._value, Int32(truncatingIfNeeded: index)._value |
| ) |
| } |
| } |
| } |
| |
| % end |
| } |
| |
| %end |
| |
| %for (Self, bits) in [('Float',32), ('Double',64)]: |
| extension ${Self} : SIMDScalar { |
| |
| public typealias SIMDMaskScalar = Int${bits} |
| |
| % for n in storagescalarCounts: |
| % bytes = n * bits / 8 |
| @_fixed_layout |
| @_alignment(${bytes if bytes <= 16 else 16}) |
| public struct SIMD${n}Storage : SIMDStorage { |
| |
| public var _value: Builtin.Vec${n}xFPIEEE${bits} |
| |
| @_transparent |
| public var scalarCount: Int { |
| return ${n} |
| } |
| |
| @_transparent |
| public init() { |
| _value = Builtin.zeroInitializer() |
| } |
| |
| public subscript(index: Int) -> ${Self} { |
| @_transparent |
| get { |
| return ${Self}(Builtin.extractelement_Vec${n}xFPIEEE${bits}_Int32( |
| _value, Int32(truncatingIfNeeded: index)._value |
| )) |
| } |
| @_transparent |
| set { |
| _value = Builtin.insertelement_Vec${n}xFPIEEE${bits}_FPIEEE${bits}_Int32( |
| _value, newValue._value, Int32(truncatingIfNeeded: index)._value |
| ) |
| } |
| } |
| } |
| |
| % end |
| } |
| |
| %end |