Skip to content

Commit

Permalink
Merge pull request #78 from stephentyrone/lengthSquared
Browse files Browse the repository at this point in the history
Rename unsafeLengthSquared -> lengthSquared
  • Loading branch information
stephentyrone committed Nov 20, 2019
2 parents f1d78c4 + f6c2c34 commit 2b63fc8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 23 deletions.
8 changes: 4 additions & 4 deletions Sources/Complex/Arithmetic.swift
Expand Up @@ -73,9 +73,9 @@ extension Complex: Numeric {
// Try the naive expression z/w = z*conj(w) / |w|^2; if we can compute
// this without over/underflow, everything is fine and the result is
// correct. If not, we have to rescale and do the computation carefully.
let lengthSquared = w.unsafeLengthSquared
guard lengthSquared.isNormal else { return rescaledDivide(z, w) }
return z * (w.conjugate.divided(by: lengthSquared))
let lenSq = w.lengthSquared
guard lenSq.isNormal else { return rescaledDivide(z, w) }
return z * (w.conjugate.divided(by: lenSq))
}

@_transparent
Expand All @@ -98,7 +98,7 @@ extension Complex: Numeric {
let wScale = w.magnitude
let zNorm = z.divided(by: zScale)
let wNorm = w.divided(by: wScale)
let r = (zNorm * wNorm.conjugate).divided(by: wNorm.unsafeLengthSquared)
let r = (zNorm * wNorm.conjugate).divided(by: wNorm.lengthSquared)
// At this point, the result is (r * zScale)/wScale computed without
// undue overflow or underflow. We know that r is close to unity, so
// the question is simply what order in which to do this computation
Expand Down
23 changes: 13 additions & 10 deletions Sources/Complex/Complex.swift
Expand Up @@ -208,7 +208,7 @@ extension Complex {

/// The ∞-norm of the value (`max(abs(real), abs(imaginary))`).
///
/// If you need the euclidean norm (a.k.a. 2-norm) use the `length` or `unsafeLengthSquared`
/// If you need the euclidean norm (a.k.a. 2-norm) use the `length` or `lengthSquared`
/// properties instead.
///
/// Edge cases:
Expand All @@ -220,7 +220,7 @@ extension Complex {
/// See also:
/// -
/// - `.length`
/// - `.unsafeLengthSquared`
/// - `.lengthSquared`
@_transparent
public var magnitude: RealType {
guard isFinite else { return .infinity }
Expand Down Expand Up @@ -394,13 +394,13 @@ extension Complex {
/// See also:
/// -
/// - `.magnitude`
/// - `.unsafeLengthSquared`
/// - `.lengthSquared`
/// - `.phase`
/// - `.polar`
/// - `init(r:θ:)`
@_transparent
public var length: RealType {
let naive = unsafeLengthSquared
let naive = lengthSquared
guard naive.isNormal else { return carefulLength }
return .sqrt(naive)
}
Expand All @@ -419,7 +419,7 @@ extension Complex {
///
/// This property is more efficient to compute than `length`, but is
/// highly prone to overflow or underflow; for finite values that are
/// not well-scaled, `unsafeLengthSquared` is often either zero or
/// not well-scaled, `lengthSquared` is often either zero or
/// infinity, even when `length` is a finite number. Use this property
/// only when you are certain that this value is well-scaled.
///
Expand All @@ -431,10 +431,13 @@ extension Complex {
/// - `.length`
/// - `.magnitude`
@_transparent
public var unsafeLengthSquared: RealType {
public var lengthSquared: RealType {
x*x + y*y
}

@available(*, unavailable, renamed: "lengthSquared")
public var unsafeLengthSquared: RealType { lengthSquared }

/// The phase (angle, or "argument").
///
/// Returns the angle (measured above the real axis) in radians. If
Expand Down Expand Up @@ -484,9 +487,9 @@ extension Complex {
/// ```
/// Complex(length: .zero, phase: θ) == .zero
/// ```
/// - For any `θ`, even `.infinity` or `.nan`:
/// - For any `θ`, even `.infinity` or `.nan`, if `r` is infinite then:
/// ```
/// Complex(length: .infinity, phase: θ) == .infinity
/// Complex(length: r, phase: θ) == .infinity
/// ```
/// - Otherwise, `θ` must be finite, or a precondition failure occurs.
///
Expand All @@ -501,8 +504,8 @@ extension Complex {
self = Complex(.cos(phase), .sin(phase)).multiplied(by: length)
} else {
precondition(
length == 0 || length == .infinity,
"Either phase must be finite, or length must be zero or infinity."
length.isZero || length.isInfinite,
"Either phase must be finite, or length must be zero or infinite."
)
self = Complex(length)
}
Expand Down
21 changes: 12 additions & 9 deletions Tests/ComplexTests/ArithmeticTests.swift
Expand Up @@ -67,12 +67,15 @@ final class ArithmeticTests: XCTestCase {
// In order to support round-tripping from rectangular to polar coordinate
// systems, as a special case phase can be non-finite when length is
// either zero or infinity.
XCTAssertEqual(Complex<T>(length: .zero, phase: .infinity), .zero)
XCTAssertEqual(Complex<T>(length: .zero, phase: -.infinity), .zero)
XCTAssertEqual(Complex<T>(length: .zero, phase: .nan ), .zero)
XCTAssertEqual(Complex<T>(length: .infinity, phase: .infinity), .infinity)
XCTAssertEqual(Complex<T>(length: .infinity, phase: -.infinity), .infinity)
XCTAssertEqual(Complex<T>(length: .infinity, phase: .nan ), .infinity)
XCTAssertEqual(Complex<T>(length: .zero, phase: .infinity), .zero)
XCTAssertEqual(Complex<T>(length: .zero, phase:-.infinity), .zero)
XCTAssertEqual(Complex<T>(length: .zero, phase: .nan ), .zero)
XCTAssertEqual(Complex<T>(length: .infinity, phase: .infinity), .infinity)
XCTAssertEqual(Complex<T>(length: .infinity, phase:-.infinity), .infinity)
XCTAssertEqual(Complex<T>(length: .infinity, phase: .nan ), .infinity)
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .infinity), .infinity)
XCTAssertEqual(Complex<T>(length:-.infinity, phase:-.infinity), .infinity)
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .nan ), .infinity)

let exponentRange =
(T.leastNormalMagnitude.exponent + T.Exponent(T.significandBitCount)) ...
Expand Down Expand Up @@ -108,11 +111,11 @@ final class ArithmeticTests: XCTestCase {
XCTFail()
}
XCTAssertEqual(w, -z)
// if length*length is normal, it should be unsafeLengthSquared, up
// if length*length is normal, it should be lengthSquared, up
// to small error.
if (p.length*p.length).isNormal {
if !closeEnough(z.unsafeLengthSquared, p.length*p.length, ulps: 16) {
print("p = \(p)\nz = \(z)\nz.unsafeLengthSquared = \(z.unsafeLengthSquared)")
if !closeEnough(z.lengthSquared, p.length*p.length, ulps: 16) {
print("p = \(p)\nz = \(z)\nz.lengthSquared = \(z.lengthSquared)")
XCTFail()
}
}
Expand Down

0 comments on commit 2b63fc8

Please sign in to comment.