Skip to content

Commit 7cd7508

Browse files
committed
Add more comments and clean up comments and variable names
1 parent cdc35be commit 7cd7508

File tree

4 files changed

+32
-28
lines changed

4 files changed

+32
-28
lines changed

Sources/ComplexModule/ElementaryFunctions.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
// Except where derivations are given, the expressions used here are all
3333
// adapted from Kahan's 1986 paper "Branch Cuts for Complex Elementary
3434
// Functions; or: Much Ado About Nothing's Sign Bit".
35+
//
36+
// As quaternions share the same goals and use adoptions of the elementary
37+
// functions: If you make a modification to either of the following functions,
38+
// you should almost surely make a parallel modification to the same elementary
39+
// function of quaternions (See ElementaryFunctions.swift in QuaternionModule).
3540

3641
import RealModule
3742

Sources/QuaternionModule/ElementaryFunctions.swift

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,43 @@
1212

1313
import RealModule
1414

15+
// As the following elementary functions algorithms are adoptions of the
16+
// elementary functions of complex numbers: If you make a modification to either
17+
// of the following functions, you should almost surely make a parallel
18+
// modification to the same elementary function of complex numbers (See
19+
// ElementaryFunctions.swift in ComplexModule).
1520
extension Quaternion/*: ElementaryFunctions */ {
1621

1722
// MARK: - exp-like functions
1823

19-
/// The quaternion exponential function e^q whose base `e` is the base of the
20-
/// natural logarithm.
21-
///
22-
/// Mathematically, this operation can be expanded in terms of the `Real`
23-
/// operations `exp`, `cos` and `sin` as follows:
24-
/// ```
25-
/// exp(r + xi + yj + zk) = exp(r + v) = exp(r) exp(v)
26-
/// = exp(r) (cos(θ) + (v/θ) sin(θ)) where θ = ||v||
27-
/// ```
28-
/// Note that naive evaluation of this expression in floating-point would be
29-
/// prone to premature overflow, since `cos` and `sin` both have magnitude
30-
/// less than 1 for most inputs (i.e. `exp(r)` may be infinity when
31-
/// `exp(r) cos(θ)` would not be).
32-
public static func exp(_ q: Quaternion<RealType>) -> Quaternion<RealType> {
24+
// Mathematically, this operation can be expanded in terms of the `Real`
25+
// operations `exp`, `cos` and `sin` as follows:
26+
// ```
27+
// exp(r + xi + yj + zk) = exp(r + v) = exp(r) exp(v)
28+
// = exp(r) (cos(||v||) + (v/||v||) sin(||v||))
29+
// ```
30+
// Note that naive evaluation of this expression in floating-point would be
31+
// prone to premature overflow, since `cos` and `sin` both have magnitude
32+
// less than 1 for most inputs (i.e. `exp(r)` may be infinity when
33+
// `exp(r) cos(θ)` would not be).
34+
@inlinable
35+
public static func exp(_ q: Quaternion) -> Quaternion {
3336
guard q.isFinite else { return q }
3437
// For real quaternions we can skip phase and axis calculations
3538
// TODO: Replace q.imaginary == .zero with `q.isReal`
36-
let phase = q.imaginary == .zero ? .zero : q.imaginary.length
37-
let unitAxis = q.imaginary == .zero ? .zero : (q.imaginary / phase)
39+
let θ = q.imaginary == .zero ? .zero : q.imaginary.length // θ = ||v||
40+
let = q.imaginary == .zero ? .zero : (q.imaginary / θ) // n̂ = v / ||v||
3841
// If real < log(greatestFiniteMagnitude), then exp(q.real) does not overflow.
3942
// To protect ourselves against sketchy log or exp implementations in
4043
// an unknown host library, or slight rounding disagreements between
4144
// the two, subtract one from the bound for a little safety margin.
4245
guard q.real < RealType.log(.greatestFiniteMagnitude) - 1 else {
4346
let halfScale = RealType.exp(q.real/2)
44-
let rotation = Quaternion(
45-
halfAngle: phase,
46-
unitAxis: unitAxis
47-
)
47+
let rotation = Quaternion(halfAngle: θ, unitAxis:)
48+
return rotation.multiplied(by: halfScale).multiplied(by: halfScale)
49+
}
50+
return Quaternion(halfAngle: θ, unitAxis:).multiplied(by: .exp(q.real))
51+
}
4852
return rotation.multiplied(by: halfScale).multiplied(by: halfScale)
4953
}
5054
return Quaternion(

Sources/QuaternionModule/Transformation.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -407,13 +407,8 @@ extension Quaternion {
407407
}
408408
}
409409

410-
// MARK: - Transformation Helper
411-
//
412-
// While Angle/Axis, Rotation Vector and Polar are different representations
413-
// of transformations, they have common properties such as being based on a
414-
// rotation *angle* about a rotation axis of unit length.
415-
//
416-
// The following extension provides these common operation internally.
410+
// MARK: - Operations for working with polar form
411+
417412
extension Quaternion {
418413
/// The half rotation angle in radians within *[0, π]* range.
419414
///

Tests/QuaternionTests/ElementaryFunctionTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class ElementaryFunctionTests: XCTestCase {
2323
XCTAssertEqual(1, Quaternion<T>.exp(Quaternion(real:-0, imaginary: 0, 0, 0)))
2424
XCTAssertEqual(1, Quaternion<T>.exp(Quaternion(real:-0, imaginary:-0,-0,-0)))
2525
XCTAssertEqual(1, Quaternion<T>.exp(Quaternion(real: 0, imaginary:-0,-0,-0)))
26-
// In general, exp(Quaternion(r, 0, 0, 0)) should be exp(r), but that breaks
26+
// In general, exp(Quaternion(r,0,0,0)) should be exp(r), but that breaks
2727
// down when r is infinity or NaN, because we want all non-finite
2828
// quaternions to be semantically a single point at infinity. This is fine
2929
// for most inputs, but exp(Quaternion(-.infinity, 0, 0, 0)) would produce

0 commit comments

Comments
 (0)