@@ -202,136 +202,6 @@ extension Quaternion/*: ElementaryFunctions */ {
202
202
let p = Quaternion ( imaginary: â)
203
203
return - p * tanh( q * p)
204
204
}
205
-
206
- // MARK: - log-like functions
207
- @inlinable
208
- public static func log( _ q: Quaternion ) -> Quaternion {
209
- // If q is zero or infinite, the phase is undefined, so the result is
210
- // the single exceptional value.
211
- guard q. isFinite && !q. isZero else { return . infinity }
212
-
213
- let argument = q. imaginary. length
214
- let axis = q. imaginary / argument
215
-
216
- // We deliberatly choose log(length) over the (faster)
217
- // log(lengthSquared) / 2 which is used for complex numbers; as
218
- // the squared length of quaternions is more prone to overflows than the
219
- // squared length of complex numbers.
220
- return Quaternion ( real: . log( q. length) , imaginary: axis * q. halfAngle)
221
- }
222
-
223
- @inlinable
224
- public static func log( onePlus q: Quaternion ) -> Quaternion {
225
- // If either |r| or ||v||₁ is bounded away from the origin, we don't need
226
- // any extra precision, and can just literally compute log(1+z). Note
227
- // that this includes part of the sphere |1+q| = 1 where log(onePlus:)
228
- // vanishes (where r <= -0.5), but on this portion of the sphere 1+r
229
- // is always exact by Sterbenz' lemma, so as long as log( ) produces
230
- // a good result, log(1+q) will too.
231
- guard 2 * q. real. magnitude < 1 && q. imaginary. oneNorm < 1 else {
232
- return log ( . one + q)
233
- }
234
- // q is in (±0.5, ±1), so we need to evaluate more carefully.
235
- // The imaginary part is straightforward:
236
- let argument = ( . one + q) . halfAngle
237
- let ( â, _) = q. imaginary. unitAxisAndLength
238
- let imaginary = â * argument
239
- // For the real part, we _could_ use the same approach that we do for
240
- // log( ), but we'd need an extra-precise (1+r)², which can potentially
241
- // be quite painful to calculate. Instead, we can use an approach that
242
- // NevinBR suggested on the Swift forums for complex numbers:
243
- //
244
- // Re(log 1+q) = (log 1+q + log 1+q̅)/2
245
- // = log((1+q)(1+q̅)/2
246
- // = log(1 + q + q̅ + qq̅)/2
247
- // = log1p((2+r)r + x² + y² + z²)/2
248
- //
249
- // So now we need to evaluate (2+r)r + x² + y² + z² accurately. To do this,
250
- // we employ augmented arithmetic;
251
- // (2+r)r + x² + y² + z²
252
- // --↓--
253
- let rp2 = Augmented . fastTwoSum ( 2 , q. real) // Known that 2 > |r|
254
- var ( head, δ) = Augmented . twoProdFMA ( q. real, rp2. head)
255
- var tail = δ
256
- // head + x² + y² + z²
257
- // ----↓----
258
- let x ² = Augmented . twoProdFMA ( q. imaginary. x, q. imaginary. x)
259
- ( head, δ) = Augmented . twoSum ( head, x ². head)
260
- tail += ( δ + x ². tail)
261
- // head + y² + z²
262
- // ----↓----
263
- let y ² = Augmented . twoProdFMA ( q. imaginary. y, q. imaginary. y)
264
- ( head, δ) = Augmented . twoSum ( head, y ². head)
265
- tail += ( δ + y ². tail)
266
- // head + z²
267
- // ----↓----
268
- let z ² = Augmented . twoProdFMA ( q. imaginary. z, q. imaginary. z)
269
- ( head, δ) = Augmented . twoSum ( head, z ². head)
270
- tail += ( δ + z ². tail)
271
-
272
- let s = ( head + tail) . addingProduct ( q. real, rp2. tail)
273
- return Quaternion ( real: . log( onePlus: s) / 2 , imaginary: imaginary)
274
- }
275
-
276
- //
277
- // MARK: - pow-like functions
278
-
279
- @inlinable
280
- public static func pow( _ q: Quaternion , _ p: Quaternion ) -> Quaternion {
281
- // Mathematically, this operation can be expanded in terms of the
282
- // quaternionic `exp` and `log` operations as follows:
283
- //
284
- // ```
285
- // pow(q, p) = exp(log(pow(q, p)))
286
- // = exp(p * log(q))
287
- // ```
288
- exp ( p * log( q) )
289
- }
290
-
291
- @inlinable
292
- public static func pow( _ q: Quaternion , _ n: Int ) -> Quaternion {
293
- // Mathematically, this operation can be expanded in terms of the
294
- // quaternionic `exp` and `log` operations as follows:
295
- //
296
- // ```
297
- // pow(q, n) = exp(log(pow(q, n)))
298
- // = exp(log(q) * n)
299
- // ```
300
- guard !q. isZero else { return . zero }
301
- // TODO: this implementation is not quite correct, because n may be
302
- // rounded in conversion to RealType. This only effects very extreme
303
- // cases, so we'll leave it alone for now.
304
- return exp ( log ( q) . multiplied ( by: RealType ( n) ) )
305
- }
306
-
307
- @inlinable
308
- public static func sqrt( _ q: Quaternion ) -> Quaternion < RealType > {
309
- // Mathematically, this operation can be expanded in terms of the
310
- // quaternionic `exp` and `log` operations as follows:
311
- //
312
- // ```
313
- // sqrt(q) = q^(1/2) = exp(log(q^(1/2)))
314
- // = exp(log(q) * (1/2))
315
- // ```
316
- guard !q. isZero else { return . zero }
317
- return exp ( log ( q) . divided ( by: 2 ) )
318
- }
319
-
320
- @inlinable
321
- public static func root( _ q: Quaternion , _ n: Int ) -> Quaternion {
322
- // Mathematically, this operation can be expanded in terms of the
323
- // quaternionic `exp` and `log` operations as follows:
324
- //
325
- // ```
326
- // root(q, n) = exp(log(root(q, n)))
327
- // = exp(log(q) / n)
328
- // ```
329
- guard !q. isZero else { return . zero }
330
- // TODO: this implementation is not quite correct, because n may be
331
- // rounded in conversion to RealType. This only effects very extreme
332
- // cases, so we'll leave it alone for now.
333
- return exp ( log ( q) . divided ( by: RealType ( n) ) )
334
- }
335
205
}
336
206
337
207
extension SIMD3 where Scalar: FloatingPoint {
@@ -349,18 +219,3 @@ extension SIMD3 where Scalar: FloatingPoint {
349
219
return ( self / length, length)
350
220
}
351
221
}
352
-
353
- extension Augmented {
354
-
355
- // TODO: Move to Augmented.swift
356
- @usableFromInline @_transparent
357
- internal static func twoSum< T: Real > ( _ a: T , _ b: T ) -> ( head: T , tail: T ) {
358
- let head = a + b
359
- let x = head - b
360
- let y = head - x
361
- let ax = a - x
362
- let by = b - y
363
- let tail = ax + by
364
- return ( head, tail)
365
- }
366
- }
0 commit comments