//===----------------------------------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// // simd.h overlays for Swift //===----------------------------------------------------------------------===// import Swift import Darwin @_exported import simd public extension SIMD { @available(swift, deprecated:5, renamed: "init(repeating:)") @_transparent init(_ scalar: Scalar) { self.init(repeating: scalar) } } internal extension SIMD2 { var _descriptionAsArray: String { return "[\(x), \(y)]" } } internal extension SIMD3 { var _descriptionAsArray: String { return "[\(x), \(y), \(z)]" } } internal extension SIMD4 { var _descriptionAsArray: String { return "[\(x), \(y), \(z), \(w)]" } } public extension SIMD where Scalar : FixedWidthInteger { @available(swift, deprecated:5, message: "use 0 &- rhs") @_transparent static prefix func -(rhs: Self) -> Self { return 0 &- rhs } } %{ component = ['x','y','z','w'] scalar_types = ['Float','Double','Int32','UInt32'] ctype = { 'Float':'float', 'Double':'double', 'Int32':'int', 'UInt32':'uint'} floating_types = ['Float','Double'] }% %for scalar in scalar_types: % for count in [2, 3, 4]: % vectype = "SIMD" + str(count) + "<" + scalar + ">" % vecsize = (8 if scalar == 'Double' else 4) * (4 if count == 3 else count) % vecalign = (16 if vecsize > 16 else vecsize) % is_floating = scalar in floating_types % is_signed = scalar[0] != 'U' % wrap = "" if is_floating else "&" @available(swift, deprecated: 5.1, message: "Use SIMD${count}<${scalar}>") public typealias ${ctype[scalar]}${count} = ${vectype} % if is_signed: /// Elementwise absolute value of a vector. The result is a vector of the same /// length with all elements positive. @_transparent public func abs(_ x: ${vectype}) -> ${vectype} { return simd_abs(x) } % end /// Elementwise minimum of two vectors. Each component of the result is the /// smaller of the corresponding component of the inputs. @_transparent public func min(_ x: ${vectype}, _ y: ${vectype}) -> ${vectype} { return simd_min(x, y) } /// Elementwise maximum of two vectors. Each component of the result is the /// larger of the corresponding component of the inputs. @_transparent public func max(_ x: ${vectype}, _ y: ${vectype}) -> ${vectype} { return simd_max(x, y) } /// Vector-scalar minimum. Each component of the result is the minimum of the /// corresponding element of the input vector and the scalar. @_transparent public func min(_ vector: ${vectype}, _ scalar: ${scalar}) -> ${vectype} { return min(vector, ${vectype}(repeating: scalar)) } /// Vector-scalar maximum. Each component of the result is the maximum of the /// corresponding element of the input vector and the scalar. @_transparent public func max(_ vector: ${vectype}, _ scalar: ${scalar}) -> ${vectype} { return max(vector, ${vectype}(repeating: scalar)) } /// Each component of the result is the corresponding element of `x` clamped to /// the range formed by the corresponding elements of `min` and `max`. Any /// lanes of `x` that contain NaN will end up with the `min` value. @_transparent public func clamp(_ x: ${vectype}, min: ${vectype}, max: ${vectype}) -> ${vectype} { return simd.min(simd.max(x, min), max) } /// Clamp each element of `x` to the range [`min`, max]. If any lane of `x` is /// NaN, the corresponding lane of the result is `min`. @_transparent public func clamp(_ x: ${vectype}, min: ${scalar}, max: ${scalar}) -> ${vectype} { return simd.min(simd.max(x, min), max) } /// Sum of the elements of the vector. @_transparent public func reduce_add(_ x: ${vectype}) -> ${scalar} { return simd_reduce_add(x) } /// Minimum element of the vector. @_transparent public func reduce_min(_ x: ${vectype}) -> ${scalar} { return simd_reduce_min(x) } /// Maximum element of the vector. @_transparent public func reduce_max(_ x: ${vectype}) -> ${scalar} { return simd_reduce_max(x) } % if is_floating: /// Sign of a vector. Each lane contains -1 if the corresponding lane of `x` /// is less than zero, +1 if the corresponding lane of `x` is greater than /// zero, and 0 otherwise. @_transparent public func sign(_ x: ${vectype}) -> ${vectype} { return simd_sign(x) } /// Linear interpolation between `x` (at `t=0`) and `y` (at `t=1`). May be /// used with `t` outside of [0, 1] as well. @_transparent public func mix(_ x: ${vectype}, _ y: ${vectype}, t: ${vectype}) -> ${vectype} { return x + t*(y-x) } /// Linear interpolation between `x` (at `t=0`) and `y` (at `t=1`). May be /// used with `t` outside of [0, 1] as well. @_transparent public func mix(_ x: ${vectype}, _ y: ${vectype}, t: ${scalar}) -> ${vectype} { return x + t*(y-x) } /// Elementwise reciprocal. @_transparent public func recip(_ x: ${vectype}) -> ${vectype} { return simd_recip(x) } /// Elementwise reciprocal square root. @_transparent public func rsqrt(_ x: ${vectype}) -> ${vectype} { return simd_rsqrt(x) } /// Alternate name for minimum of two floating-point vectors. @_transparent public func fmin(_ x: ${vectype}, _ y: ${vectype}) -> ${vectype} { return min(x, y) } /// Alternate name for maximum of two floating-point vectors. @_transparent public func fmax(_ x: ${vectype}, _ y: ${vectype}) -> ${vectype} { return max(x, y) } /// Each element of the result is the smallest integral value greater than or /// equal to the corresponding element of the input. @_transparent public func ceil(_ x: ${vectype}) -> ${vectype} { return __tg_ceil(x) } /// Each element of the result is the largest integral value less than or equal /// to the corresponding element of the input. @_transparent public func floor(_ x: ${vectype}) -> ${vectype} { return __tg_floor(x) } /// Each element of the result is the closest integral value with magnitude /// less than or equal to that of the corresponding element of the input. @_transparent public func trunc(_ x: ${vectype}) -> ${vectype} { return __tg_trunc(x) } /// `x - floor(x)`, clamped to lie in the range [0,1). Without this clamp step, /// the result would be 1.0 when `x` is a very small negative number, which may /// result in out-of-bounds table accesses in common usage. @_transparent public func fract(_ x: ${vectype}) -> ${vectype} { return simd_fract(x) } /// 0.0 if `x < edge`, and 1.0 otherwise. @_transparent public func step(_ x: ${vectype}, edge: ${vectype}) -> ${vectype} { return simd_step(edge, x) } /// 0.0 if `x < edge0`, 1.0 if `x > edge1`, and cubic interpolation between /// 0 and 1 in the interval [edge0, edge1]. @_transparent public func smoothstep(_ x: ${vectype}, edge0: ${vectype}, edge1: ${vectype}) -> ${vectype} { return simd_smoothstep(edge0, edge1, x) } /// Dot product of `x` and `y`. @_transparent public func dot(_ x: ${vectype}, _ y: ${vectype}) -> ${scalar} { return reduce_add(x * y) } /// Projection of `x` onto `y`. @_transparent public func project(_ x: ${vectype}, _ y: ${vectype}) -> ${vectype} { return simd_project(x, y) } /// Length of `x`, squared. This is more efficient to compute than the length, /// so you should use it if you only need to compare lengths to each other. /// I.e. instead of writing: /// /// if (length(x) < length(y)) { ... } /// /// use: /// /// if (length_squared(x) < length_squared(y)) { ... } /// /// Doing it this way avoids one or two square roots, which is a fairly costly /// operation. @_transparent public func length_squared(_ x: ${vectype}) -> ${scalar} { return dot(x, x) } /// Length (two-norm or "Euclidean norm") of `x`. @_transparent public func length(_ x: ${vectype}) -> ${scalar} { return sqrt(length_squared(x)) } /// The one-norm (or "taxicab norm") of `x`. @_transparent public func norm_one(_ x: ${vectype}) -> ${scalar} { return reduce_add(abs(x)) } /// The infinity-norm (or "sup norm") of `x`. @_transparent public func norm_inf(_ x: ${vectype}) -> ${scalar} { return reduce_max(abs(x)) } /// Distance between `x` and `y`, squared. @_transparent public func distance_squared(_ x: ${vectype}, _ y: ${vectype}) -> ${scalar} { return length_squared(x - y) } /// Distance between `x` and `y`. @_transparent public func distance(_ x: ${vectype}, _ y: ${vectype}) -> ${scalar} { return length(x - y) } /// Unit vector pointing in the same direction as `x`. @_transparent public func normalize(_ x: ${vectype}) -> ${vectype} { return simd_normalize(x) } /// `x` reflected through the hyperplane with unit normal vector `n`, passing /// through the origin. E.g. if `x` is [1,2,3] and `n` is [0,0,1], the result /// is [1,2,-3]. @_transparent public func reflect(_ x: ${vectype}, n: ${vectype}) -> ${vectype} { return simd_reflect(x, n) } /// The refraction direction given unit incident vector `x`, unit surface /// normal `n`, and index of refraction `eta`. If the angle between the /// incident vector and the surface is so small that total internal reflection /// occurs, zero is returned. @_transparent public func refract(_ x: ${vectype}, n: ${vectype}, eta: ${scalar}) -> ${vectype} { return simd_refract(x, n, eta) } % end # if is_floating % end # for count in [2, 3, 4] % if is_floating: // Scalar versions of common operations: /// Returns -1 if `x < 0`, +1 if `x > 0`, and 0 otherwise (`sign(NaN)` is 0). @_transparent public func sign(_ x: ${scalar}) -> ${scalar} { return simd_sign(x) } /// Reciprocal. @_transparent public func recip(_ x: ${scalar}) -> ${scalar} { return simd_recip(x) } /// Reciprocal square root. @_transparent public func rsqrt(_ x: ${scalar}) -> ${scalar} { return simd_rsqrt(x) } /// Returns 0.0 if `x < edge`, and 1.0 otherwise. @_transparent public func step(_ x: ${scalar}, edge: ${scalar}) -> ${scalar} { return simd_step(edge, x) } /// Interprets two two-dimensional vectors as three-dimensional vectors in the /// xy-plane and computes their cross product, which lies along the z-axis. @_transparent public func cross(_ x: SIMD2<${scalar}>, _ y: SIMD2<${scalar}>) -> SIMD3<${scalar}> { return simd_cross(x,y) } /// Cross-product of two three-dimensional vectors. The resulting vector is /// perpendicular to the plane determined by `x` and `y`, with length equal to /// the oriented area of the parallelogram they determine. @_transparent public func cross(_ x: SIMD3<${scalar}>, _ y: SIMD3<${scalar}>) -> SIMD3<${scalar}> { return simd_cross(x,y) } % end # is_floating %end # for scalar in scalar_types %for type in floating_types: % for rows in [2,3,4]: % for cols in [2,3,4]: % mattype = 'simd_' + ctype[type] + str(cols) + 'x' + str(rows) % diagsize = rows if rows < cols else cols % coltype = "SIMD" + str(rows) + "<" + type + ">" % rowtype = "SIMD" + str(cols) + "<" + type + ">" % diagtype = "SIMD" + str(diagsize) + "<" + type + ">" % transtype = ctype[type] + str(rows) + 'x' + str(cols) public typealias ${ctype[type]}${cols}x${rows} = ${mattype} extension ${mattype} { /// Initialize matrix to have `scalar` on main diagonal, zeros elsewhere. public init(_ scalar: ${type}) { self.init(diagonal: ${diagtype}(repeating: scalar)) } /// Initialize matrix to have specified `diagonal`, and zeros elsewhere. public init(diagonal: ${diagtype}) { self.init() % for i in range(diagsize): self.columns.${i}.${component[i]} = diagonal.${component[i]} % end } /// Initialize matrix to have specified `columns`. public init(_ columns: [${coltype}]) { precondition(columns.count == ${cols}, "Requires array of ${cols} vectors") self.init() % for i in range(cols): self.columns.${i} = columns[${i}] % end } /// Initialize matrix to have specified `rows`. public init(rows: [${rowtype}]) { precondition(rows.count == ${rows}, "Requires array of ${rows} vectors") self = ${transtype}(rows).transpose } /// Initialize matrix to have specified `columns`. public init(${', '.join(['_ col' + str(i) + ': ' + coltype for i in range(cols)])}) { self.init() % for i in range(cols): self.columns.${i} = col${i} % end } /// Initialize matrix from corresponding C matrix type. @available(swift, deprecated: 4, message: "This conversion is no longer necessary; use `cmatrix` directly.") @_transparent public init(_ cmatrix: ${mattype}) { self = cmatrix } /// Get the matrix as the corresponding C matrix type. @available(swift, deprecated: 4, message: "This property is no longer needed; use the matrix itself.") @_transparent public var cmatrix: ${mattype} { return self } /// Access to individual columns. public subscript(column: Int) -> ${coltype} { get { switch(column) { % for i in range(cols): case ${i}: return columns.${i} % end default: preconditionFailure("Column index out of range") } } set (value) { switch(column) { % for i in range(cols): case ${i}: columns.${i} = value % end default: preconditionFailure("Column index out of range") } } } /// Access to individual elements. public subscript(column: Int, row: Int) -> ${type} { get { return self[column][row] } set (value) { self[column][row] = value } } } extension ${mattype} : CustomDebugStringConvertible { public var debugDescription: String { return "${mattype}([${', '.join(map(lambda i: \ '\(columns.' + str(i) + '._descriptionAsArray)', range(cols)))}])" } } extension ${mattype} : Equatable { @_transparent public static func ==(lhs: ${mattype}, rhs: ${mattype}) -> Bool { return simd_equal(lhs, rhs) } } extension ${mattype} { /// Transpose of the matrix. @_transparent public var transpose: ${transtype} { return simd_transpose(self) } % if rows == cols: /// Inverse of the matrix if it exists, otherwise the contents of the /// resulting matrix are undefined. @available(macOS 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *) @_transparent public var inverse: ${mattype} { return simd_inverse(self) } /// Determinant of the matrix. @_transparent public var determinant: ${type} { return simd_determinant(self) } % end /// Sum of two matrices. @_transparent public static func +(lhs: ${mattype}, rhs: ${mattype}) -> ${mattype} { return simd_add(lhs, rhs) } /// Negation of a matrix. @_transparent public static prefix func -(rhs: ${mattype}) -> ${mattype} { return ${mattype}() - rhs } /// Difference of two matrices. @_transparent public static func -(lhs: ${mattype}, rhs: ${mattype}) -> ${mattype} { return simd_sub(lhs, rhs) } @_transparent public static func +=(lhs: inout ${mattype}, rhs: ${mattype}) -> Void { lhs = lhs + rhs } @_transparent public static func -=(lhs: inout ${mattype}, rhs: ${mattype}) -> Void { lhs = lhs - rhs } /// Scalar-Matrix multiplication. @_transparent public static func *(lhs: ${type}, rhs: ${mattype}) -> ${mattype} { return simd_mul(lhs, rhs) } /// Matrix-Scalar multiplication. @_transparent public static func *(lhs: ${mattype}, rhs: ${type}) -> ${mattype} { return rhs*lhs } @_transparent public static func *=(lhs: inout ${mattype}, rhs: ${type}) -> Void { lhs = lhs*rhs } /// Matrix-Vector multiplication. Keep in mind that matrix types are named /// `${type}NxM` where `N` is the number of *columns* and `M` is the number of /// *rows*, so we multiply a `${type}3x2 * ${type}3` to get a `${type}2`, for /// example. @_transparent public static func *(lhs: ${mattype}, rhs: ${rowtype}) -> ${coltype} { return simd_mul(lhs, rhs) } /// Vector-Matrix multiplication. @_transparent public static func *(lhs: ${coltype}, rhs: ${mattype}) -> ${rowtype} { return simd_mul(lhs, rhs) } % for k in [2,3,4]: /// Matrix multiplication (the "usual" matrix product, not the elementwise /// product). % restype = ctype[type] + str(k) + 'x' + str(rows) % rhstype = ctype[type] + str(k) + 'x' + str(cols) @_transparent public static func *(lhs: ${mattype}, rhs: ${rhstype}) -> ${restype} { return simd_mul(lhs, rhs) } % end # for k in [2,3,4] % rhstype = ctype[type] + str(cols) + 'x' + str(cols) /// Matrix multiplication (the "usual" matrix product, not the elementwise /// product). @_transparent public static func *=(lhs: inout ${mattype}, rhs: ${rhstype}) -> Void { lhs = lhs*rhs } } // Make old-style C free functions with the `matrix_` prefix available but // deprecated in Swift 4. % if rows == cols: @available(swift, deprecated: 4, renamed: "${mattype}(diagonal:)") public func matrix_from_diagonal(_ d: ${diagtype}) -> ${mattype} { return ${mattype}(diagonal: d) } @available(swift, deprecated: 4, message: "Use the .inverse property instead.") @available(macOS 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *) public func matrix_invert(_ x: ${mattype}) -> ${mattype} { return x.inverse } @available(swift, deprecated: 4, message: "Use the .determinant property instead.") public func matrix_determinant(_ x: ${mattype}) -> ${type} { return x.determinant } % end # rows == cols @available(swift, deprecated: 4, renamed: "${mattype}") public func matrix_from_columns(${', '.join(['_ col' + str(i) + ': ' + coltype for i in range(cols)])}) -> ${mattype} { return ${mattype}(${', '.join(['col' + str(i) for i in range(cols)])}) } public func matrix_from_rows(${', '.join(['_ row' + str(i) + ': ' + rowtype for i in range(rows)])}) -> ${mattype} { return ${transtype}(${', '.join(['row' + str(i) for i in range(rows)])}).transpose } @available(swift, deprecated: 4, message: "Use the .transpose property instead.") public func matrix_transpose(_ x: ${mattype}) -> ${transtype} { return x.transpose } @available(swift, deprecated: 4, renamed: "==") public func matrix_equal(_ lhs: ${mattype}, _ rhs: ${mattype}) -> Bool { return lhs == rhs } % end # for cols in [2,3,4] % end # for rows in [2,3,4] %end # for type in floating_types