blob: c20d44e0b1d6d2cd747137b4aa9afcfe7157aa8d [file] [log] [blame]
//===----------------------------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 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 module overlays for Swift
//===----------------------------------------------------------------------===//
import Swift
import Darwin
import SIMDOperators
@_exported import simd
%for scalar in ['Float','Double']:
% quat = 'simd_quat' + ('f' if scalar == 'Float' else 'd')
% vec3 = str.lower(scalar) + '3'
% vec4 = str.lower(scalar) + '4'
% mat3 = 'simd_' + str.lower(scalar) + '3x3'
% mat4 = 'simd_' + str.lower(scalar) + '4x4'
extension ${quat} {
/// Construct a quaternion from components.
///
/// - Parameters:
/// - ix: The x-component of the imaginary (vector) part.
/// - iy: The y-component of the imaginary (vector) part.
/// - iz: The z-component of the imaginary (vector) part.
/// - r: The real (scalar) part.
@_transparent
public init(ix: ${scalar}, iy: ${scalar}, iz: ${scalar}, r: ${scalar}) {
self.init(vector: ${vec4}(ix, iy, iz, r))
}
/// Construct a quaternion from real and imaginary parts.
@_transparent
public init(real: ${scalar}, imag: ${vec3}) {
self.init(vector: simd_make_${vec4}(imag, real))
}
/// A quaternion whose action is a rotation by `angle` radians about `axis`.
///
/// - Parameters:
/// - angle: The angle to rotate by measured in radians.
/// - axis: The axis to rotate around.
@_transparent
public init(angle: ${scalar}, axis: ${vec3}) {
self = simd_quaternion(angle, axis)
}
/// A quaternion whose action rotates the vector `from` onto the vector `to`.
@_transparent
public init(from: ${vec3}, to: ${vec3}) {
self = simd_quaternion(from, to)
}
/// Construct a quaternion from `rotationMatrix`.
@_transparent
public init(_ rotationMatrix: ${mat3}) {
self = simd_quaternion(rotationMatrix)
}
/// Construct a quaternion from `rotationMatrix`.
@_transparent
public init(_ rotationMatrix: ${mat4}) {
self = simd_quaternion(rotationMatrix)
}
/// The real (scalar) part of `self`.
public var real: ${scalar} {
@_transparent
get { return vector.w }
@_transparent
set { vector.w = newValue }
}
/// The imaginary (vector) part of `self`.
public var imag: ${vec3} {
@_transparent
get { return simd_make_${vec3}(vector) }
@_transparent
set { vector = simd_make_${vec4}(newValue, vector.w) }
}
/// The angle (in radians) by which `self`'s action rotates.
@_transparent
public var angle: ${scalar} {
return simd_angle(self)
}
/// The normalized axis about which `self`'s action rotates.
@_transparent
public var axis: ${vec3} {
return simd_axis(self)
}
/// The conjugate of `self`.
@_transparent
public var conjugate: ${quat} {
return simd_conjugate(self)
}
/// The inverse of `self`.
@_transparent
public var inverse: ${quat} {
return simd_inverse(self)
}
/// The unit quaternion obtained by normalizing `self`.
@_transparent
public var normalized: ${quat} {
return simd_normalize(self)
}
/// The length of the quaternion interpreted as a 4d vector.
@_transparent
public var length: ${scalar} {
return simd_length(self)
}
/// Applies the rotation represented by a unit quaternion to the vector and
/// returns the result.
@_transparent
public func act(_ vector: ${vec3}) -> ${vec3} {
return simd_act(self, vector)
}
}
extension ${mat3} {
/// Construct a 3x3 matrix from `quaternion`.
public init(_ quaternion: ${quat}) {
self = simd_matrix3x3(quaternion)
}
}
extension ${mat4} {
/// Construct a 4x4 matrix from `quaternion`.
public init(_ quaternion: ${quat}) {
self = simd_matrix4x4(quaternion)
}
}
extension ${quat} : CustomDebugStringConvertible {
public var debugDescription: String {
return "${quat}(real: \(real), imag: \(imag))"
}
}
extension ${quat} : Equatable {
@_transparent
public static func ==(lhs: ${quat}, rhs: ${quat}) -> Bool {
return lhs.vector == rhs.vector
}
}
extension ${quat} {
/// The sum of `lhs` and `rhs`.
@_transparent
public static func +(lhs: ${quat}, rhs: ${quat}) -> ${quat} {
return simd_add(lhs, rhs)
}
/// Add `rhs` to `lhs`.
@_transparent
public static func +=(lhs: inout ${quat}, rhs: ${quat}) {
lhs = lhs + rhs
}
/// The difference of `lhs` and `rhs`.
@_transparent
public static func -(lhs: ${quat}, rhs: ${quat}) -> ${quat} {
return simd_sub(lhs, rhs)
}
/// Subtract `rhs` from `lhs`.
@_transparent
public static func -=(lhs: inout ${quat}, rhs: ${quat}) {
lhs = lhs - rhs
}
/// The negation of `rhs`.
@_transparent
public static prefix func -(rhs: ${quat}) -> ${quat} {
return simd_sub(${quat}(), rhs)
}
/// The product of `lhs` and `rhs`.
@_transparent
public static func *(lhs: ${quat}, rhs: ${quat}) -> ${quat} {
return simd_mul(lhs, rhs)
}
/// The product of `lhs` and `rhs`.
@_transparent
public static func *(lhs: ${scalar}, rhs: ${quat}) -> ${quat} {
return simd_mul(lhs, rhs)
}
/// The product of `lhs` and `rhs`.
@_transparent
public static func *(lhs: ${quat}, rhs: ${scalar}) -> ${quat} {
return simd_mul(lhs, rhs)
}
/// Multiply `lhs` by `rhs`.
@_transparent
public static func *=(lhs: inout ${quat}, rhs: ${quat}) {
lhs = lhs * rhs
}
/// Multiply `lhs` by `rhs`.
@_transparent
public static func *=(lhs: inout ${quat}, rhs: ${scalar}) {
lhs = lhs * rhs
}
/// The quotient of `lhs` and `rhs`.
@_transparent
public static func /(lhs: ${quat}, rhs: ${quat}) -> ${quat} {
return simd_mul(lhs, rhs.inverse)
}
/// The quotient of `lhs` and `rhs`.
@_transparent
public static func /(lhs: ${quat}, rhs: ${scalar}) -> ${quat} {
return ${quat}(vector: lhs.vector/rhs)
}
/// Divide `lhs` by `rhs`.
@_transparent
public static func /=(lhs: inout ${quat}, rhs: ${quat}) {
lhs = lhs / rhs
}
/// Divide `lhs` by `rhs`.
@_transparent
public static func /=(lhs: inout ${quat}, rhs: ${scalar}) {
lhs = lhs / rhs
}
}
/// The dot product of the quaternions `p` and `q` interpreted as
/// four-dimensional vectors.
@_transparent
public func dot(_ lhs: ${quat}, _ rhs: ${quat}) -> ${scalar} {
return simd_dot(lhs, rhs)
}
/// Logarithm of the quaternion `q`.
///
/// We can write a quaternion `q` in the form: `r(cos(t) + sin(t)v)` where
/// `r` is the length of `q`, `t` is an angle, and `v` is a unit 3-vector.
/// The logarithm of `q` is `log(r) + tv`, just like the logarithm of the
/// complex number `r*(cos(t) + i sin(t))` is `log(r) + it`.
public func log(_ q: ${quat}) -> ${quat} {
return __tg_log(q)
}
/// Inverse function of `log`; the exponential map on quaternions.
@_transparent
public func exp(_ q: ${quat}) -> ${quat} {
return __tg_exp(q)
}
%end # for scalar