mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
612 lines
18 KiB
Swift
612 lines
18 KiB
Swift
//===----------------------------------------------------------*- 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
|