Skip to content

Commit 198da2a

Browse files
Merge pull request #165 from stephentyrone/complex-elfns-inlinable
Mark all complex elementary functions inlinable
2 parents c5a3504 + 26c51ac commit 198da2a

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

Sources/ComplexModule/ElementaryFunctions.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ extension Complex: ElementaryFunctions {
5151
/// Note that naive evaluation of this expression in floating-point would be prone to premature
5252
/// overflow, since `cos` and `sin` both have magnitude less than 1 for most inputs (i.e.
5353
/// `exp(x)` may be infinity when `exp(x) cos(y)` would not be.
54+
@inlinable
5455
public static func exp(_ z: Complex) -> Complex {
5556
guard z.isFinite else { return z }
5657
// If x < log(greatestFiniteMagnitude), then exp(x) does not overflow.
@@ -65,6 +66,7 @@ extension Complex: ElementaryFunctions {
6566
return Complex(.cos(z.y), .sin(z.y)).multiplied(by: .exp(z.x))
6667
}
6768

69+
@inlinable
6870
public static func expMinusOne(_ z: Complex) -> Complex {
6971
// exp(x + iy) - 1 = (exp(x) cos(y) - 1) + i exp(x) sin(y)
7072
// -------- u --------
@@ -134,6 +136,7 @@ extension Complex: ElementaryFunctions {
134136
// This function and sinh should stay in sync; if you make a
135137
// modification here, you should almost surely make a parallel
136138
// modification to sinh below.
139+
@inlinable
137140
public static func cosh(_ z: Complex) -> Complex {
138141
guard z.isFinite else { return z }
139142
guard z.x.magnitude < -RealType.log(.ulpOfOne) else {
@@ -163,6 +166,7 @@ extension Complex: ElementaryFunctions {
163166
// sinh(x + iy) = sinh(x) cos(y) + i cosh(x) sinh(y)
164167
//
165168
// See cosh above for algorithm details.
169+
@inlinable
166170
public static func sinh(_ z: Complex) -> Complex {
167171
guard z.isFinite else { return z }
168172
guard z.x.magnitude < -RealType.log(.ulpOfOne) else {
@@ -178,6 +182,7 @@ extension Complex: ElementaryFunctions {
178182
}
179183

180184
// tanh(z) = sinh(z) / cosh(z)
185+
@inlinable
181186
public static func tanh(_ z: Complex) -> Complex {
182187
guard z.isFinite else { return z }
183188
// Note that when |x| is larger than -log(.ulpOfOne),
@@ -201,23 +206,27 @@ extension Complex: ElementaryFunctions {
201206
}
202207

203208
// cos(z) = cosh(iz)
209+
@inlinable
204210
public static func cos(_ z: Complex) -> Complex {
205211
return cosh(Complex(-z.y, z.x))
206212
}
207213

208214
// sin(z) = -i*sinh(iz)
215+
@inlinable
209216
public static func sin(_ z: Complex) -> Complex {
210217
let w = sinh(Complex(-z.y, z.x))
211218
return Complex(w.y, -w.x)
212219
}
213220

214221
// tan(z) = -i*tanh(iz)
222+
@inlinable
215223
public static func tan(_ z: Complex) -> Complex {
216224
let w = tanh(Complex(-z.y, z.x))
217225
return Complex(w.y, -w.x)
218226
}
219227

220228
// MARK: - log-like functions
229+
@inlinable
221230
public static func log(_ z: Complex) -> Complex {
222231
// If z is zero or infinite, the phase is undefined, so the result is
223232
// the single exceptional value.
@@ -317,6 +326,7 @@ extension Complex: ElementaryFunctions {
317326
return Complex(.log(onePlus: s)/2, θ)
318327
}
319328

329+
@inlinable
320330
public static func log(onePlus z: Complex) -> Complex {
321331
// If either |x| or |y| is bounded away from the origin, we don't need
322332
// any extra precision, and can just literally compute log(1+z). Note
@@ -348,13 +358,15 @@ extension Complex: ElementaryFunctions {
348358
return Complex(.log(onePlus: s)/2, θ)
349359
}
350360

361+
@inlinable
351362
public static func acos(_ z: Complex) -> Complex {
352363
Complex(
353364
2*RealType.atan2(y: sqrt(1-z).real, x: sqrt(1+z).real),
354365
RealType.asinh((sqrt(1+z).conjugate * sqrt(1-z)).imaginary)
355366
)
356367
}
357368

369+
@inlinable
358370
public static func asin(_ z: Complex) -> Complex {
359371
Complex(
360372
RealType.atan2(y: z.x, x: (sqrt(1-z) * sqrt(1+z)).real),
@@ -363,11 +375,13 @@ extension Complex: ElementaryFunctions {
363375
}
364376

365377
// atan(z) = -i*atanh(iz)
378+
@inlinable
366379
public static func atan(_ z: Complex) -> Complex {
367380
let w = atanh(Complex(-z.y, z.x))
368381
return Complex(w.y, -w.x)
369382
}
370383

384+
@inlinable
371385
public static func acosh(_ z: Complex) -> Complex {
372386
Complex(
373387
RealType.asinh((sqrt(z-1).conjugate * sqrt(z+1)).real),
@@ -376,11 +390,13 @@ extension Complex: ElementaryFunctions {
376390
}
377391

378392
// asinh(z) = -i*asin(iz)
393+
@inlinable
379394
public static func asinh(_ z: Complex) -> Complex {
380395
let w = asin(Complex(-z.y, z.x))
381396
return Complex(w.y, -w.x)
382397
}
383398

399+
@inlinable
384400
public static func atanh(_ z: Complex) -> Complex {
385401
// TODO: Kahan uses a much more complicated expression here; possibly
386402
// simply because he didn't have a complex log(1+z) with good
@@ -395,10 +411,12 @@ extension Complex: ElementaryFunctions {
395411
}
396412

397413
// MARK: - pow-like functions
414+
@inlinable
398415
public static func pow(_ z: Complex, _ w: Complex) -> Complex {
399416
return exp(w * log(z))
400417
}
401418

419+
@inlinable
402420
public static func pow(_ z: Complex, _ n: Int) -> Complex {
403421
if z.isZero { return .zero }
404422
// TODO: this implementation is not quite correct, because n may be
@@ -411,6 +429,7 @@ extension Complex: ElementaryFunctions {
411429
return exp(log(z).multiplied(by: RealType(n)))
412430
}
413431

432+
@inlinable
414433
public static func sqrt(_ z: Complex) -> Complex {
415434
let lengthSquared = z.lengthSquared
416435
if lengthSquared.isNormal {
@@ -439,6 +458,7 @@ extension Complex: ElementaryFunctions {
439458
return Complex.sqrt(z.divided(by: scale)).multiplied(by: .sqrt(scale))
440459
}
441460

461+
@inlinable
442462
public static func root(_ z: Complex, _ n: Int) -> Complex {
443463
if z.isZero { return .zero }
444464
// TODO: this implementation is not quite correct, because n may be

Tests/RealTests/IntegerExponentTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ extension Float {
135135
extension Double {
136136
static func testIntegerExponent() {
137137
testIntegerExponentCommon()
138-
testIntegerExponentDoubleAndSmaller()
139138
// Following tests only make sense (and are only necessary) on 64b platforms.
140139
#if arch(arm64) || arch(x86_64)
140+
testIntegerExponentDoubleAndSmaller()
141141
let u: Double = 1.nextUp
142142
let d: Double = 1.nextDown
143143
// Smallest exponent not exactly representable as Double.

0 commit comments

Comments
 (0)