diff --git a/Sources/SGLMath/Complex.swift b/Sources/SGLMath/Complex.swift index 20971d9..d9c82eb 100644 --- a/Sources/SGLMath/Complex.swift +++ b/Sources/SGLMath/Complex.swift @@ -34,6 +34,8 @@ extension Float { public struct Complex: MatrixType, ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral, ExpressibleByArrayLiteral { public typealias Element = T + public static var elementCount: Int { 2 } + public var real: T public var imag: T diff --git a/Sources/SGLMath/Matrix2x2.swift b/Sources/SGLMath/Matrix2x2.swift index f887577..21401ad 100644 --- a/Sources/SGLMath/Matrix2x2.swift +++ b/Sources/SGLMath/Matrix2x2.swift @@ -26,6 +26,8 @@ import simd public struct Matrix2x2: MatrixType { public typealias Element = T + public static var elementCount: Int { 2 * 2 } + private var x: Vector2, y: Vector2 public subscript(column: Int) -> Vector2 { diff --git a/Sources/SGLMath/Matrix2x3.swift b/Sources/SGLMath/Matrix2x3.swift index 30bed1b..574422f 100644 --- a/Sources/SGLMath/Matrix2x3.swift +++ b/Sources/SGLMath/Matrix2x3.swift @@ -22,6 +22,8 @@ public struct Matrix2x3: MatrixType { public typealias Element = T + public static var elementCount: Int { 2 * 3 } + private var x: Vector3, y: Vector3 public subscript(column: Int) -> Vector3 { diff --git a/Sources/SGLMath/Matrix2x4.swift b/Sources/SGLMath/Matrix2x4.swift index 05ba9b4..4ecdab4 100644 --- a/Sources/SGLMath/Matrix2x4.swift +++ b/Sources/SGLMath/Matrix2x4.swift @@ -26,6 +26,8 @@ import simd public struct Matrix2x4: MatrixType { public typealias Element = T + public static var elementCount: Int { 2 * 4 } + private var x: Vector4, y: Vector4 public subscript(column: Int) -> Vector4 { diff --git a/Sources/SGLMath/Matrix3x2.swift b/Sources/SGLMath/Matrix3x2.swift index c623de6..f9195f0 100644 --- a/Sources/SGLMath/Matrix3x2.swift +++ b/Sources/SGLMath/Matrix3x2.swift @@ -22,6 +22,8 @@ public struct Matrix3x2: MatrixType { public typealias Element = T + public static var elementCount: Int { 3 * 2 } + private var x: Vector2, y: Vector2, z: Vector2 public subscript(column: Int) -> Vector2 { diff --git a/Sources/SGLMath/Matrix3x3.swift b/Sources/SGLMath/Matrix3x3.swift index aee7791..5a072b1 100644 --- a/Sources/SGLMath/Matrix3x3.swift +++ b/Sources/SGLMath/Matrix3x3.swift @@ -22,6 +22,8 @@ public struct Matrix3x3: MatrixType { public typealias Element = T + public static var elementCount: Int { 3 * 3 } + private var x: Vector3, y: Vector3, z: Vector3 public subscript(column: Int) -> Vector3 { diff --git a/Sources/SGLMath/Matrix3x4.swift b/Sources/SGLMath/Matrix3x4.swift index 3d3c8d4..d39a67b 100644 --- a/Sources/SGLMath/Matrix3x4.swift +++ b/Sources/SGLMath/Matrix3x4.swift @@ -22,6 +22,8 @@ public struct Matrix3x4: MatrixType { public typealias Element = T + public static var elementCount: Int { 3 * 4 } + private var x: Vector4, y: Vector4, z: Vector4 public subscript(column: Int) -> Vector4 { diff --git a/Sources/SGLMath/Matrix4x2.swift b/Sources/SGLMath/Matrix4x2.swift index 1fd5f4f..dec05fb 100644 --- a/Sources/SGLMath/Matrix4x2.swift +++ b/Sources/SGLMath/Matrix4x2.swift @@ -26,6 +26,8 @@ import simd public struct Matrix4x2: MatrixType { public typealias Element = T + public static var elementCount: Int { 4 * 2 } + private var x: Vector2, y: Vector2, z: Vector2, w: Vector2 public subscript(column: Int) -> Vector2 { diff --git a/Sources/SGLMath/Matrix4x3.swift b/Sources/SGLMath/Matrix4x3.swift index c1259d6..3964fe7 100644 --- a/Sources/SGLMath/Matrix4x3.swift +++ b/Sources/SGLMath/Matrix4x3.swift @@ -22,6 +22,8 @@ public struct Matrix4x3: MatrixType { public typealias Element = T + public static var elementCount: Int { 4 * 3 } + private var x: Vector3, y: Vector3, z: Vector3, w: Vector3 public subscript(column: Int) -> Vector3 { diff --git a/Sources/SGLMath/Matrix4x4.swift b/Sources/SGLMath/Matrix4x4.swift index 11dc24f..f1107e2 100644 --- a/Sources/SGLMath/Matrix4x4.swift +++ b/Sources/SGLMath/Matrix4x4.swift @@ -26,6 +26,8 @@ import simd public struct Matrix4x4: MatrixType { public typealias Element = T + public static var elementCount: Int { 4 * 4 } + private var x: Vector4, y: Vector4, z: Vector4, w: Vector4 public subscript(column: Int) -> Vector4 { diff --git a/Sources/SGLMath/Protocols.swift b/Sources/SGLMath/Protocols.swift index e9dda63..5c8c09d 100644 --- a/Sources/SGLMath/Protocols.swift +++ b/Sources/SGLMath/Protocols.swift @@ -104,6 +104,41 @@ public protocol MatrixType: Hashable, CustomDebugStringConvertible, Sequence whe static func %(_: Self, _: Element) -> Self static func %=(_: inout Self, _: Element) var elements: [Element] { get } + + static var elementCount: Int { get } +} + +// Unsafe pointer access +public extension MatrixType { + func withUnsafePointer(_ body: (UnsafePointer) throws -> R) rethrows -> R { + try Swift.withUnsafePointer(to: self) { pointer in + try pointer.withMemoryRebound(to: Element.self, capacity: Self.elementCount) { + try body($0) + } + } + } + + mutating func withUnsafeMutablePointer(_ body: (UnsafeMutablePointer) throws -> R) rethrows -> R { + try Swift.withUnsafeMutablePointer(to: &self) { pointer in + try pointer.withMemoryRebound(to: Element.self, capacity: Self.elementCount) { + try body($0) + } + } + } + + func withUnsafeBufferPointer(_ body: (UnsafeBufferPointer) throws -> R) rethrows -> R { + try withUnsafeBytes(of: self) { rawBuffer in + let buffer = UnsafeBufferPointer(start: rawBuffer.baseAddress!.assumingMemoryBound(to: Element.self), count: Self.elementCount) + return try body(buffer) + } + } + + mutating func withUnsafeMutableBufferPointer(_ body: (UnsafeMutableBufferPointer) throws -> R) rethrows -> R { + try withUnsafeMutableBytes(of: &self) { rawBuffer in + let buffer = UnsafeMutableBufferPointer(start: rawBuffer.baseAddress!.assumingMemoryBound(to: Element.self), count: Self.elementCount) + return try body(buffer) + } + } } // This protocol is only Vector2, Vector3, and Vector4 diff --git a/Sources/SGLMath/Quaternion.swift b/Sources/SGLMath/Quaternion.swift index 36c2e9f..b8d5195 100644 --- a/Sources/SGLMath/Quaternion.swift +++ b/Sources/SGLMath/Quaternion.swift @@ -22,6 +22,8 @@ public struct Quaternion: MatrixType, ExpressibleByArrayLiteral { public typealias Element = T + public static var elementCount: Int { 4 } + public var x: T, y: T, z: T, w: T public var elements: [Element] { diff --git a/Sources/SGLMath/Vector2.swift b/Sources/SGLMath/Vector2.swift index 896aabc..31388a0 100644 --- a/Sources/SGLMath/Vector2.swift +++ b/Sources/SGLMath/Vector2.swift @@ -27,6 +27,8 @@ public struct Vector2: VectorType { public typealias UInt32Vector = Vector2 public typealias BooleanVector = Vector2b + public static var elementCount: Int { 2 } + public var x: T, y: T public var r: T { get { return x } set { x = newValue } } diff --git a/Sources/SGLMath/Vector2b.swift b/Sources/SGLMath/Vector2b.swift index fe16713..8d91f5d 100644 --- a/Sources/SGLMath/Vector2b.swift +++ b/Sources/SGLMath/Vector2b.swift @@ -22,6 +22,8 @@ public struct Vector2b: BooleanVectorType { public typealias BooleanVector = Vector2b + public static var elementCount: Int { 2 } + public var x: Bool, y: Bool public var r: Bool { get { return x } set { x = newValue } } diff --git a/Sources/SGLMath/Vector3.swift b/Sources/SGLMath/Vector3.swift index 2c5a6bd..cad6e01 100644 --- a/Sources/SGLMath/Vector3.swift +++ b/Sources/SGLMath/Vector3.swift @@ -27,6 +27,8 @@ public struct Vector3: VectorType { public typealias UInt32Vector = Vector3 public typealias BooleanVector = Vector3b + public static var elementCount: Int { 3 } + public var x: T, y: T, z: T public var r: T { get { return x } set { x = newValue } } diff --git a/Sources/SGLMath/Vector3b.swift b/Sources/SGLMath/Vector3b.swift index 1ff1f5c..6cfcbac 100644 --- a/Sources/SGLMath/Vector3b.swift +++ b/Sources/SGLMath/Vector3b.swift @@ -22,6 +22,8 @@ public struct Vector3b: BooleanVectorType { public typealias BooleanVector = Vector3b + public static var elementCount: Int { 3 } + public var x: Bool, y: Bool, z: Bool public var r: Bool { get { return x } set { x = newValue } } diff --git a/Sources/SGLMath/Vector4.swift b/Sources/SGLMath/Vector4.swift index 8376c1f..56ddf89 100644 --- a/Sources/SGLMath/Vector4.swift +++ b/Sources/SGLMath/Vector4.swift @@ -27,6 +27,8 @@ public struct Vector4: VectorType { public typealias UInt32Vector = Vector4 public typealias BooleanVector = Vector4b + public static var elementCount: Int { 4 } + public var x: T, y: T, z: T, w: T public var r: T { get { return x } set { x = newValue } } diff --git a/Sources/SGLMath/Vector4b.swift b/Sources/SGLMath/Vector4b.swift index 4358e31..477bbe9 100644 --- a/Sources/SGLMath/Vector4b.swift +++ b/Sources/SGLMath/Vector4b.swift @@ -22,6 +22,8 @@ public struct Vector4b: BooleanVectorType { public typealias BooleanVector = Vector4b + public static var elementCount: Int { 4 } + public var x: Bool, y: Bool, z: Bool, w: Bool public var r: Bool { get { return x } set { x = newValue } } diff --git a/Tests/SGLMathTests/Matrix4x4Tests.swift b/Tests/SGLMathTests/Matrix4x4Tests.swift index 7799544..de1e09b 100644 --- a/Tests/SGLMathTests/Matrix4x4Tests.swift +++ b/Tests/SGLMathTests/Matrix4x4Tests.swift @@ -119,12 +119,49 @@ class Matrix4x4Tests: XCTestCase { XCTAssertEqual(m0, m1) } + func testPointers() { + var m0 = mat4( + vec4(0, 1, 2, 3), + vec4(4, 5, 6, 7), + vec4(8, 9, 10, 11), + vec4(12, 13, 14, 15) + ) + + let m1 = mat4( + vec4(20, 21, 22, 23), + vec4(24, 25, 26, 27), + vec4(28, 29, 30, 31), + vec4(32, 33, 34, 35) + ) + + m0.withUnsafePointer { pointer in + for i in 0..<16 { + XCTAssertEqual(pointer[i], Float(i)) + } + } + + m0.withUnsafeMutablePointer { pointer in + for i in 0..<16 { + pointer[i] += 20 + } + } + + m0.withUnsafeBufferPointer { buffer in + for (i, element) in buffer.enumerated() { + XCTAssertEqual(element, Float(i + 20)) + } + } + + XCTAssertEqual(m0, m1) + } + static var allTests = [ ("testIdentityInits", testIdentityInits), ("testCommmonInits", testCommmonInits), ("testDivide", testDivide), ("testMultiplyWith2x4", testMultiplyWith2x4), ("testMultiplyVector", testMultiplyVector), - ("testMultiArray", testMultiArray) + ("testMultiArray", testMultiArray), + ("testPointers", testPointers) ] } diff --git a/Tests/SGLMathTests/Vector4Tests.swift b/Tests/SGLMathTests/Vector4Tests.swift index abe25fe..c839ef5 100644 --- a/Tests/SGLMathTests/Vector4Tests.swift +++ b/Tests/SGLMathTests/Vector4Tests.swift @@ -110,6 +110,31 @@ class Vector4Tests: XCTestCase { XCTAssertEqual(v1/v2, v3) } + func testPointers() { + var v0 = vec4(0, 1, 2, 3) + let v1 = vec4(20, 21, 22, 23) + + v0.withUnsafePointer { pointer in + for i in 0..<4 { + XCTAssertEqual(pointer[i], Float(i)) + } + } + + v0.withUnsafeMutablePointer { pointer in + for i in 0..<4 { + pointer[i] += 20 + } + } + + v0.withUnsafeBufferPointer { buffer in + for (i, element) in buffer.enumerated() { + XCTAssertEqual(element, Float(i + 20)) + } + } + + XCTAssertEqual(v0, v1) + } + static var allTests = [ ("testInit", testInit), ("testAddFloat", testAddFloat), @@ -120,6 +145,7 @@ class Vector4Tests: XCTestCase { ("testMulInt", testMulInt), ("testMulUInt", testMulUInt), ("testDivFloat", testDivFloat), - ("testDivInt", testDivInt) + ("testDivInt", testDivInt), + ("testPointers", testPointers) ] }