Skip to content

Commit 0b4571e

Browse files
committed
Move imaginary helper functions into a distinct file
1 parent 5ac7546 commit 0b4571e

File tree

3 files changed

+81
-39
lines changed

3 files changed

+81
-39
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===--- ImaginaryHelper.swift --------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2019-2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// Provides common vector operations on SIMD3 to ease the use of the quaternions
14+
// imaginary/vector components internally to the module, and in tests.
15+
extension SIMD3 where Scalar: FloatingPoint {
16+
/// Returns a vector with infinity in all lanes
17+
@usableFromInline @inline(__always)
18+
internal static var infinity: Self {
19+
SIMD3(repeating: .infinity)
20+
}
21+
22+
/// Returns a vector with nan in all lanes
23+
@usableFromInline @inline(__always)
24+
internal static var nan: Self {
25+
SIMD3(repeating: .nan)
26+
}
27+
28+
/// True if all values of this instance are finite
29+
@usableFromInline @inline(__always)
30+
internal var isFinite: Bool {
31+
x.isFinite && y.isFinite && z.isFinite
32+
}
33+
34+
/// The ∞-norm of the value (`max(abs(x), abs(y), abs(z))`).
35+
@usableFromInline @inline(__always)
36+
internal var magnitude: Scalar {
37+
max()
38+
}
39+
40+
/// The Euclidean norm (a.k.a. 2-norm, `sqrt(x*x + y*y + z*z)`).
41+
@usableFromInline @inline(__always)
42+
internal var length: Scalar {
43+
let naive = lengthSquared
44+
guard naive.isNormal else { return carefulLength }
45+
return naive.squareRoot()
46+
}
47+
48+
// Implementation detail of `length`, moving slow path off of the
49+
// inline function.
50+
@usableFromInline
51+
internal var carefulLength: Scalar {
52+
guard isFinite else { return .infinity }
53+
guard !magnitude.isZero else { return .zero }
54+
// Unscale the vector, calculate its length and rescale the result
55+
return (self / magnitude).length * magnitude
56+
}
57+
58+
/// Returns the squared length of this instance.
59+
@usableFromInline @inline(__always)
60+
internal var lengthSquared: Scalar {
61+
dot(self)
62+
}
63+
64+
/// Returns the scalar/dot product of this vector with `other`.
65+
@usableFromInline @inline(__always)
66+
internal func dot(_ other: SIMD3<Scalar>) -> Scalar {
67+
(self * other).sum()
68+
}
69+
70+
/// Returns the vector/cross product of this vector with `other`.
71+
@usableFromInline @inline(__always)
72+
internal func cross(_ other: SIMD3<Scalar>) -> SIMD3<Scalar> {
73+
let yzx = SIMD3<Int>(1,2,0)
74+
let zxy = SIMD3<Int>(2,0,1)
75+
return (self[yzx] * other[zxy]) - (self[zxy] * other[yzx])
76+
}
77+
}

Sources/QuaternionModule/Transformation.swift

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ extension Quaternion {
381381
/// [wiki]: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Using_quaternion_as_rotations
382382
@inlinable
383383
public func act(on vector: SIMD3<RealType>) -> SIMD3<RealType> {
384-
guard vector.isFinite else { return SIMD3(repeating: .infinity) }
384+
guard vector.isFinite else { return .infinity }
385385
guard vector != .zero else { return .zero }
386386

387387
// The following expression have been split up so the type-checker
@@ -452,36 +452,3 @@ extension Quaternion {
452452
self.init(real: .cos(halfAngle), imaginary: unitAxis * .sin(halfAngle))
453453
}
454454
}
455-
456-
// MARK: - SIMD Helper
457-
//
458-
// Provides common vector operations on SIMD3 to ease the use of "imaginary"
459-
// and *(x,y,z)* axis representations internally to the module.
460-
extension SIMD3 where Scalar: FloatingPoint {
461-
462-
/// True if all values of this instance are finite
463-
@usableFromInline @inline(__always)
464-
internal var isFinite: Bool {
465-
x.isFinite && y.isFinite && z.isFinite
466-
}
467-
468-
/// Returns the squared length of this instance.
469-
@usableFromInline @inline(__always)
470-
internal var lengthSquared: Scalar {
471-
dot(self)
472-
}
473-
474-
/// Returns the scalar/dot product of this vector with `other`.
475-
@usableFromInline @inline(__always)
476-
internal func dot(_ other: SIMD3<Scalar>) -> Scalar {
477-
(self * other).sum()
478-
}
479-
480-
/// Returns the vector/cross product of this vector with `other`.
481-
@usableFromInline @inline(__always)
482-
internal func cross(_ other: SIMD3<Scalar>) -> SIMD3<Scalar> {
483-
let yzx = SIMD3<Int>(1,2,0)
484-
let zxy = SIMD3<Int>(2,0,1)
485-
return (self[yzx] * other[zxy]) - (self[zxy] * other[yzx])
486-
}
487-
}

Tests/QuaternionTests/TransformationTests.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,9 @@ final class TransformationTests: XCTestCase {
306306
let q = Quaternion(angle: .pi, axis: SIMD3(1,0,0))
307307
XCTAssertEqual(q.act(on: .zero), .zero)
308308
XCTAssertEqual(q.act(on: -.zero), .zero)
309-
XCTAssertEqual(q.act(on: .nan ), SIMD3(repeating: .infinity))
310-
XCTAssertEqual(q.act(on: .infinity), SIMD3(repeating: .infinity))
311-
XCTAssertEqual(q.act(on: -.infinity), SIMD3(repeating: .infinity))
309+
XCTAssertEqual(q.act(on: .nan ), .infinity)
310+
XCTAssertEqual(q.act(on: .infinity), .infinity)
311+
XCTAssertEqual(q.act(on: -.infinity), .infinity)
312312
}
313313

314314
func testActOnVectorEdgeCase() {
@@ -369,8 +369,6 @@ final class TransformationTests: XCTestCase {
369369

370370
// MARK: - Helper
371371
extension SIMD3 where Scalar: FloatingPoint {
372-
fileprivate static var infinity: Self { SIMD3(.infinity,0,0) }
373-
fileprivate static var nan: Self { SIMD3(.nan,0,0) }
374372
fileprivate var isNaN: Bool { x.isNaN && y.isNaN && z.isNaN }
375373
}
376374

0 commit comments

Comments
 (0)