Skip to content

Commit 262cbea

Browse files
committed
review feedback.
1 parent 84c41a0 commit 262cbea

File tree

2 files changed

+85
-86
lines changed

2 files changed

+85
-86
lines changed

Sources/ComplexModule/Complex+AlgebraicField.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Numerics open source project
44
//
5-
// Copyright (c) 2019-2021 Apple Inc. and the Swift Numerics project authors
5+
// Copyright (c) 2019-2024 Apple Inc. and the Swift Numerics project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -96,7 +96,7 @@ extension Complex: AlgebraicField {
9696
//
9797
// Note that our final assembly of the result is different from Priest;
9898
// he applies s to w twice, instead of once to w and once to z, and
99-
// does the product as (zw̅ʺ)*1/|wʹ|², while we do zʹ(w̅ʹ/|wʹ|²). We
99+
// does the product as (zw̅ʺ)*(1/|wʹ|²), while we do zʹ(w̅ʹ/|wʹ|²). We
100100
// prefer our version for three reasons:
101101
//
102102
// 1. it extracts a little more ILP

Tests/ComplexTests/ArithmeticTests.swift

Lines changed: 83 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Numerics open source project
44
//
5-
// Copyright (c) 2019 Apple Inc. and the Swift Numerics project authors
5+
// Copyright (c) 2019-2024 Apple Inc. and the Swift Numerics project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -83,92 +83,91 @@ final class ArithmeticTests: XCTestCase {
8383
func testPolar<T>(_ type: T.Type)
8484
where T: BinaryFloatingPoint, T: Real,
8585
T.Exponent: FixedWidthInteger, T.RawSignificand: FixedWidthInteger {
86-
87-
// In order to support round-tripping from rectangular to polar coordinate
88-
// systems, as a special case phase can be non-finite when length is
89-
// either zero or infinity.
90-
XCTAssertEqual(Complex<T>(length: .zero, phase: .infinity), .zero)
91-
XCTAssertEqual(Complex<T>(length: .zero, phase:-.infinity), .zero)
92-
XCTAssertEqual(Complex<T>(length: .zero, phase: .nan ), .zero)
93-
XCTAssertEqual(Complex<T>(length: .infinity, phase: .infinity), .infinity)
94-
XCTAssertEqual(Complex<T>(length: .infinity, phase:-.infinity), .infinity)
95-
XCTAssertEqual(Complex<T>(length: .infinity, phase: .nan ), .infinity)
96-
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .infinity), .infinity)
97-
XCTAssertEqual(Complex<T>(length:-.infinity, phase:-.infinity), .infinity)
98-
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .nan ), .infinity)
99-
100-
let exponentRange =
101-
T.leastNormalMagnitude.exponent ... T.greatestFiniteMagnitude.exponent
102-
let inputs = (0..<100).map { _ in
103-
Polar(length: T(
104-
sign: .plus,
105-
exponent: T.Exponent.random(in: exponentRange),
106-
significand: T.random(in: 1 ..< 2)
107-
), phase: T.random(in: -.pi ... .pi))
108-
}
109-
for p in inputs {
110-
// first test that each value can round-trip between rectangular and
111-
// polar coordinates with reasonable accuracy. We'll probably need to
112-
// relax this for some platforms (currently we're using the default
113-
// RNG, which means we don't get the same sequence of values each time;
114-
// this is good--more test coverage!--and bad, because without tight
115-
// bounds on every platform's libm, we can't get tight bounds on the
116-
// accuracy of these operations, so we need to relax them gradually).
117-
let z = Complex(length: p.length, phase: p.phase)
118-
if !closeEnough(z.length, p.length, ulps: 16) {
119-
print("p = \(p)\nz = \(z)\nz.length = \(z.length)")
120-
XCTFail()
121-
}
122-
if !closeEnough(z.phase, p.phase, ulps: 16) {
123-
print("p = \(p)\nz = \(z)\nz.phase = \(z.phase)")
124-
XCTFail()
125-
}
126-
// Complex(length: -r, phase: θ) = -Complex(length: r, phase: θ).
127-
let w = Complex(length: -p.length, phase: p.phase)
128-
if w != -z {
129-
print("p = \(p)\nw = \(w)\nz = \(z)")
130-
XCTFail()
131-
}
132-
XCTAssertEqual(w, -z)
133-
// if length*length is normal, it should be lengthSquared, up
134-
// to small error.
135-
if (p.length*p.length).isNormal {
136-
if !closeEnough(z.lengthSquared, p.length*p.length, ulps: 16) {
137-
print("p = \(p)\nz = \(z)\nz.lengthSquared = \(z.lengthSquared)")
138-
XCTFail()
139-
}
140-
}
141-
// Test reciprocal and normalized:
142-
let r = Complex(length: 1/p.length, phase: -p.phase)
143-
if r.isNormal {
144-
if relativeError(r, z.reciprocal!) > 16 {
145-
print("p = \(p)\nz = \(z)\nz.reciprocal = \(r)")
146-
XCTFail()
147-
}
148-
} else { XCTAssertNil(z.reciprocal) }
149-
let n = Complex(length: 1, phase: p.phase)
150-
if relativeError(n, z.normalized!) > 16 {
151-
print("p = \(p)\nz = \(z)\nz.normalized = \(n)")
152-
XCTFail()
153-
}
154-
155-
// Now test multiplication and division using the polar inputs:
156-
for q in inputs {
157-
let w = Complex(length: q.length, phase: q.phase)
158-
var product = Complex(length: p.length, phase: p.phase + q.phase)
159-
product.real *= q.length
160-
product.imaginary *= q.length
161-
if checkMultiply(z, w, expected: product, ulps: 16) { XCTFail() }
162-
var quotient = Complex(length: p.length, phase: p.phase - q.phase)
163-
quotient.real /= q.length
164-
quotient.imaginary /= q.length
165-
if checkDivide(z, w, expected: quotient, ulps: 16) { XCTFail() }
166-
}
167-
}
86+
// In order to support round-tripping from rectangular to polar coordinate
87+
// systems, as a special case phase can be non-finite when length is
88+
// either zero or infinity.
89+
XCTAssertEqual(Complex<T>(length: .zero, phase: .infinity), .zero)
90+
XCTAssertEqual(Complex<T>(length: .zero, phase:-.infinity), .zero)
91+
XCTAssertEqual(Complex<T>(length: .zero, phase: .nan ), .zero)
92+
XCTAssertEqual(Complex<T>(length: .infinity, phase: .infinity), .infinity)
93+
XCTAssertEqual(Complex<T>(length: .infinity, phase:-.infinity), .infinity)
94+
XCTAssertEqual(Complex<T>(length: .infinity, phase: .nan ), .infinity)
95+
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .infinity), .infinity)
96+
XCTAssertEqual(Complex<T>(length:-.infinity, phase:-.infinity), .infinity)
97+
XCTAssertEqual(Complex<T>(length:-.infinity, phase: .nan ), .infinity)
98+
99+
let exponentRange =
100+
T.leastNormalMagnitude.exponent ... T.greatestFiniteMagnitude.exponent
101+
let inputs = (0..<100).map { _ in
102+
Polar(length: T(
103+
sign: .plus,
104+
exponent: T.Exponent.random(in: exponentRange),
105+
significand: T.random(in: 1 ..< 2)
106+
), phase: T.random(in: -.pi ... .pi))
107+
}
108+
for p in inputs {
109+
// first test that each value can round-trip between rectangular and
110+
// polar coordinates with reasonable accuracy. We'll probably need to
111+
// relax this for some platforms (currently we're using the default
112+
// RNG, which means we don't get the same sequence of values each time;
113+
// this is good--more test coverage!--and bad, because without tight
114+
// bounds on every platform's libm, we can't get tight bounds on the
115+
// accuracy of these operations, so we need to relax them gradually).
116+
let z = Complex(length: p.length, phase: p.phase)
117+
if !closeEnough(z.length, p.length, ulps: 16) {
118+
print("p = \(p)\nz = \(z)\nz.length = \(z.length)")
119+
XCTFail()
120+
}
121+
if !closeEnough(z.phase, p.phase, ulps: 16) {
122+
print("p = \(p)\nz = \(z)\nz.phase = \(z.phase)")
123+
XCTFail()
124+
}
125+
// Complex(length: -r, phase: θ) = -Complex(length: r, phase: θ).
126+
let w = Complex(length: -p.length, phase: p.phase)
127+
if w != -z {
128+
print("p = \(p)\nw = \(w)\nz = \(z)")
129+
XCTFail()
130+
}
131+
XCTAssertEqual(w, -z)
132+
// if length*length is normal, it should be lengthSquared, up
133+
// to small error.
134+
if (p.length*p.length).isNormal {
135+
if !closeEnough(z.lengthSquared, p.length*p.length, ulps: 16) {
136+
print("p = \(p)\nz = \(z)\nz.lengthSquared = \(z.lengthSquared)")
137+
XCTFail()
138+
}
139+
}
140+
// Test reciprocal and normalized:
141+
let r = Complex(length: 1/p.length, phase: -p.phase)
142+
if r.isNormal {
143+
if relativeError(r, z.reciprocal!) > 16 {
144+
print("p = \(p)\nz = \(z)\nz.reciprocal = \(r)")
145+
XCTFail()
168146
}
147+
} else { XCTAssertNil(z.reciprocal) }
148+
let n = Complex(length: 1, phase: p.phase)
149+
if relativeError(n, z.normalized!) > 16 {
150+
print("p = \(p)\nz = \(z)\nz.normalized = \(n)")
151+
XCTFail()
152+
}
153+
154+
// Now test multiplication and division using the polar inputs:
155+
for q in inputs {
156+
let w = Complex(length: q.length, phase: q.phase)
157+
var product = Complex(length: p.length, phase: p.phase + q.phase)
158+
product.real *= q.length
159+
product.imaginary *= q.length
160+
if checkMultiply(z, w, expected: product, ulps: 16) { XCTFail() }
161+
var quotient = Complex(length: p.length, phase: p.phase - q.phase)
162+
quotient.real /= q.length
163+
quotient.imaginary /= q.length
164+
if checkDivide(z, w, expected: quotient, ulps: 16) { XCTFail() }
165+
}
166+
}
167+
}
169168

170169
func testPolar() {
171-
#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
170+
#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) && LONG_TESTS
172171
if #available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) {
173172
testPolar(Float16.self)
174173
}

0 commit comments

Comments
 (0)