Skip to content

Commit 18945d7

Browse files
committed
Update implementations of sin/cos/tan
1 parent c3361c7 commit 18945d7

File tree

1 file changed

+12
-58
lines changed

1 file changed

+12
-58
lines changed

Sources/QuaternionModule/ElementaryFunctions.swift

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -181,72 +181,26 @@ extension Quaternion/*: ElementaryFunctions */ {
181181

182182
@inlinable
183183
public static func cos(_ q: Quaternion) -> Quaternion {
184-
// Mathematically, this operation can be expanded in terms of
185-
// trigonometric `Real` operations as follows (`let θ = ||v||`):
186-
//
187-
// ```
188-
// cos(r + v) = (exp(q * (v/θ)) + exp(-q * (v/θ))) / 2
189-
// = cos(r) cosh(θ) - (v/θ) sin(r) sinh(θ)
190-
// ```
191-
guard q.isFinite else { return q }
192-
let (â, θ) = q.imaginary.unitAxisAndLength
193-
guard θ.magnitude < -RealType.log(.ulpOfOne) else {
194-
let rotation = Quaternion(halfAngle: q.real, unitAxis: â)
195-
let firstScale = RealType.exp(θ.magnitude/2)
196-
let secondScale = firstScale/2
197-
return rotation.multiplied(by: firstScale).multiplied(by: secondScale)
198-
}
199-
return Quaternion(
200-
real: .cosh(θ) * .cos(q.real),
201-
imaginary: -â * .sinh(θ) * .sin(q.real)
202-
)
184+
// cos(q) = cosh(q * (v/θ)))
185+
let (â,_) = q.imaginary.unitAxisAndLength
186+
let p = Quaternion(imaginary: â)
187+
return cosh(q * p)
203188
}
204189

205190
@inlinable
206191
public static func sin(_ q: Quaternion) -> Quaternion {
207-
// Mathematically, this operation can be expanded in terms of
208-
// trigonometric `Real` operations as follows (`let θ = ||v||`):
209-
//
210-
// ```
211-
// sin(r + v) = -((exp(q * (v/θ)) - exp(-q * (v/θ))) (v/θ * 2)
212-
// = sin(r) cosh(θ) + (v/θ) cos(r) sinh(θ)
213-
// ```
214-
guard q.isFinite else { return q }
215-
let (â, θ) = q.imaginary.unitAxisAndLength
216-
guard θ.magnitude < -RealType.log(.ulpOfOne) else {
217-
let rotation = Quaternion(halfAngle: q.real, unitAxis: â)
218-
let firstScale = RealType.exp(θ.magnitude/2)
219-
let secondScale = RealType(signOf: θ, magnitudeOf: firstScale/2)
220-
return rotation.multiplied(by: firstScale).multiplied(by: secondScale)
221-
}
222-
return Quaternion(
223-
real: .cosh(θ) * .sin(q.real),
224-
imaginary: â * .sinh(θ) * .cos(q.real)
225-
)
192+
// sin(q) = -(v/θ) * sinh(q * (v/θ)))
193+
let (â,_) = q.imaginary.unitAxisAndLength
194+
let p = Quaternion(imaginary: â)
195+
return -p * sinh(q * p)
226196
}
227197

228198
@inlinable
229199
public static func tan(_ q: Quaternion) -> Quaternion {
230-
// Mathematically, this operation can be expanded in terms of
231-
// trigonometric `Real` operations as follows (`let θ = ||v||`):
232-
//
233-
// ```
234-
// tan(q) = sin(q) / cos(q)
235-
// ```
236-
guard q.isFinite else { return q }
237-
// Note that when |θ| is larger than -log(.ulpOfOne),
238-
// sin(r + v) == ±cos(r + v), so tan(r + v) is just ±1.
239-
guard q.imaginary.length.magnitude < -RealType.log(.ulpOfOne) else {
240-
let r = RealType(signOf: q.components.w, magnitudeOf: 1)
241-
return Quaternion(
242-
real: r,
243-
imaginary:
244-
RealType(signOf: q.components.x, magnitudeOf: 0),
245-
RealType(signOf: q.components.y, magnitudeOf: 0),
246-
RealType(signOf: q.components.z, magnitudeOf: 0)
247-
).multiplied(by: r)
248-
}
249-
return sin(q) / cos(q)
200+
// tan(q) = -(v/θ) * tanh(q * (v/θ)))
201+
let (â,_) = q.imaginary.unitAxisAndLength
202+
let p = Quaternion(imaginary: â)
203+
return -p * tanh(q * p)
250204
}
251205

252206
// MARK: - log-like functions

0 commit comments

Comments
 (0)