diff --git a/Math/Math.xcodeproj/project.pbxproj b/Math/Math.xcodeproj/project.pbxproj index 44d3ca6..925b4fd 100644 --- a/Math/Math.xcodeproj/project.pbxproj +++ b/Math/Math.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ C005E0051BE1CBA800F1BD3C /* Math.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C005DFFA1BE1CBA700F1BD3C /* Math.framework */; }; C005E00A1BE1CBA800F1BD3C /* MathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C005E0091BE1CBA800F1BD3C /* MathTests.swift */; }; C005E0391BE1CC7A00F1BD3C /* Matrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = C005E0381BE1CC7A00F1BD3C /* Matrix.swift */; }; + C04449C11BE26A0700ABF046 /* Vector.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04449C01BE26A0700ABF046 /* Vector.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -31,6 +32,7 @@ C005E0091BE1CBA800F1BD3C /* MathTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MathTests.swift; sourceTree = ""; }; C005E00B1BE1CBA800F1BD3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C005E0381BE1CC7A00F1BD3C /* Matrix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matrix.swift; sourceTree = ""; }; + C04449C01BE26A0700ABF046 /* Vector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vector.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,6 +77,7 @@ children = ( C005DFFD1BE1CBA700F1BD3C /* Math.h */, C005E0381BE1CC7A00F1BD3C /* Matrix.swift */, + C04449C01BE26A0700ABF046 /* Vector.swift */, C005DFFF1BE1CBA700F1BD3C /* Info.plist */, ); path = Math; @@ -197,6 +200,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C04449C11BE26A0700ABF046 /* Vector.swift in Sources */, C005E0391BE1CC7A00F1BD3C /* Matrix.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Math/Math/Matrix.swift b/Math/Math/Matrix.swift index 04faa0a..8311288 100644 --- a/Math/Math/Matrix.swift +++ b/Math/Math/Matrix.swift @@ -20,21 +20,6 @@ protocol Matrix { subscript(row: Int, col: Int) -> ElementType { get set } } -/** A vector. */ -protocol Vector { - init() - - /** Number of elements in the vector. */ - var count: Int { get } - /** Element access by index. */ - subscript(idx: Int) -> Float { get set } - - /** Length of the vector. */ - var length2: Float { get } - /** Length-squared of the vector. */ - var length: Float { get } -} - // MARK: - Matrices public struct Matrix4: Matrix { @@ -90,107 +75,7 @@ struct Matrix3 { // MARK: Vectors -public struct Vector3: Vector { - private var data: [Float] - init() { - self.init(x: 0.0, y: 0.0, z: 0.0) - } - - init(x: Float, y: Float, z: Float) { - data = [x, y, z] - } - - var length: Float { - return sqrtf(length2) - } - - var length2: Float { - return data.reduce(0.0) { $0 + $1 * $1 } - } - - // MARK: Sequence-ish - - var count: Int { - return 3 - } - - public subscript(idx: Int) -> Float { - get { - return data[idx] - } - set(value) { - data[idx] = value - } - } - - // MARK: Element access - - var x: Float { - return data[0] - } - - var y: Float { - return data[1] - } - - var z: Float { - return data[2] - } -} - -public struct Vector4: Vector { - private var data: [Float] - - init() { - self.init(x: 0.0, y: 0.0, z: 0.0) - } - - init(x: Float, y: Float, z: Float, w: Float = 1.0) { - data = [x, y, z, w] - } - - var length: Float { - return sqrtf(length2) - } - - var length2: Float { - return data.reduce(0.0) { $0 + $1 * $1 } - } - - // MARK: SequenceType-ish - - var count: Int { - return data.count - } - - public subscript(idx: Int) -> Float { - get { - return data[idx] - } - set(value) { - data[idx] = value - } - } - - // MARK: Element access - - var x: Float { - return data[0] - } - - var y: Float { - return data[1] - } - - var z: Float { - return data[2] - } - - var w: Float { - return data[3] - } -} // MARK: - Matrix-Scalar Multiplication diff --git a/Math/Math/Vector.swift b/Math/Math/Vector.swift new file mode 100644 index 0000000..9fbabf9 --- /dev/null +++ b/Math/Math/Vector.swift @@ -0,0 +1,252 @@ +// +// Vector.swift +// Math +// +// Created by Eryn Wells on 10/29/15. +// Copyright © 2015 Eryn Wells. All rights reserved. +// + +import Foundation + +public typealias Float = Swift.Float + +/** A vector. */ +public protocol Vector { + init() + + /** Number of elements in the vector. */ + var count: Int { get } + /** Element access by index. */ + subscript(idx: Int) -> Float { get set } + + /** Length of the vector. */ + var length2: Float { get } + /** Length-squared of the vector. */ + var length: Float { get } + /** A normalized copy of the vector. */ + var normalized: Self { get } + + /** The dot product of this vector with another. */ + func dot(lhs: Self) -> Float +} + +extension Vector { + public var length: Float { + return sqrtf(length2) + } + + public var length2: Float { + var l2: Float = 0.0 + for i in 0.. Float { + get { + return data[idx] + } + set(value) { + data[idx] = value + } + } + + // MARK: Element access + + public var x: Float { + get { + return data[0] + } + set(value) { + data[0] = value + } + } + + public var y: Float { + get { + return data[1] + } + set(value) { + data[1] = value + } + } + + public var z: Float { + get { + return data[2] + } + set(value) { + data[2] = value + } + } + + // MARK: Operators + + public func cross(rhs: Vector3) -> Vector3 { + return Vector3(x: data[1] * rhs.data[2] - data[2] * rhs.data[1], + y: data[2] * rhs.data[0] - data[0] * rhs.data[2], + z: data[0] * rhs.data[1] - data[1] * rhs.data[0]) + } +} + +//------------------------------------------------------------------------------ + +public struct Vector4: Vector { + private var data: [Float] + + public init() { + self.init(x: 0.0, y: 0.0, z: 0.0) + } + + public init(v: Vector3, w: Float = 1.0) { + self.init(x: v.x, y: v.y, z: v.z, w: w) + } + + public init(x: Float, y: Float, z: Float, w: Float = 1.0) { + data = [x, y, z, w] + } + + // MARK: SequenceType-ish + + public var count: Int { + return data.count + } + + public subscript(idx: Int) -> Float { + get { + return data[idx] + } + set(value) { + data[idx] = value + } + } + + // MARK: Element access + + public var x: Float { + return data[0] + } + + public var y: Float { + return data[1] + } + + public var z: Float { + return data[2] + } + + public var w: Float { + return data[3] + } +} + +// MARK: - Operators + +extension Vector { + public func dot(rhs: Self) -> Float { + var sum: Float = 0.0 + for i in 0..(v: T) -> T { + var out = v + for i in 0..(inout rhs: T, lhs: T) { + for i in 0..(rhs: T, lhs: T) -> T { + var out = rhs + out += lhs + return out +} + +public func -=(inout rhs: T, lhs: T) { + for i in 0..(rhs: T, lhs: T) -> T { + var out = rhs + out -= lhs + return out +} + +public func *=(inout rhs: T, lhs: Float) { + for i in 0..(lhs: Float, rhs: T) -> T { + var out = rhs + out *= lhs + return out +} + +public func *(lhs: T, rhs: Float) -> T { + return rhs * lhs +} + +public func /=(inout rhs: T, lhs: Float) { + rhs *= (1.0 / lhs) +} + +public func /(lhs: T, rhs: Float) -> T { + return lhs * (1.0 / rhs) +} + +infix operator ∙ { associativity left precedence 150 } +public func ∙(rhs: T, lhs: T) -> Float { + return rhs.dot(lhs) +} + +infix operator ×= { associativity left precedence 150 } +public func ×=(inout rhs: Vector3, lhs: Vector3) { + rhs = rhs.cross(lhs) +} + +infix operator × { associativity left precedence 150 } +public func ×(rhs: Vector3, lhs: Vector3) -> Vector3 { + return rhs.cross(lhs) +} \ No newline at end of file