@@ -30,10 +30,10 @@ func checkMultiply<T>(
30
30
) -> Bool {
31
31
let observed = a*b
32
32
let rel = relativeError ( observed, expected)
33
- if rel > allowed {
33
+ guard rel <= allowed else {
34
34
print ( " Over-large error in \( a) * \( b) " )
35
35
print ( " Expected: \( expected) \n Observed: \( observed) " )
36
- print ( " Relative error was \( rel) (tolerance: \( allowed) . " )
36
+ print ( " Relative error was \( rel) (tolerance: \( allowed) ) ." )
37
37
return true
38
38
}
39
39
return false
@@ -44,10 +44,10 @@ func checkDivide<T>(
44
44
) -> Bool {
45
45
let observed = a/ b
46
46
let rel = relativeError ( observed, expected)
47
- if rel > allowed {
47
+ guard rel <= allowed else {
48
48
print ( " Over-large error in \( a) / \( b) " )
49
49
print ( " Expected: \( expected) \n Observed: \( observed) " )
50
- print ( " Relative error was \( rel) (tolerance: \( allowed) . " )
50
+ print ( " Relative error was \( rel) (tolerance: \( allowed) ) ." )
51
51
return true
52
52
}
53
53
return false
@@ -63,93 +63,99 @@ final class ArithmeticTests: XCTestCase {
63
63
func testPolar< T> ( _ type: T . Type )
64
64
where T: BinaryFloatingPoint , T: Real ,
65
65
T. Exponent: FixedWidthInteger , T. RawSignificand: FixedWidthInteger {
66
-
67
- // In order to support round-tripping from rectangular to polar coordinate
68
- // systems, as a special case phase can be non-finite when length is
69
- // either zero or infinity.
70
- XCTAssertEqual ( Complex < T > ( length: . zero, phase: . infinity) , . zero)
71
- XCTAssertEqual ( Complex < T > ( length: . zero, phase: - . infinity) , . zero)
72
- XCTAssertEqual ( Complex < T > ( length: . zero, phase: . nan ) , . zero)
73
- XCTAssertEqual ( Complex < T > ( length: . infinity, phase: . infinity) , . infinity)
74
- XCTAssertEqual ( Complex < T > ( length: . infinity, phase: - . infinity) , . infinity)
75
- XCTAssertEqual ( Complex < T > ( length: . infinity, phase: . nan ) , . infinity)
76
- XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: . infinity) , . infinity)
77
- XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: - . infinity) , . infinity)
78
- XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: . nan ) , . infinity)
79
66
80
- let exponentRange =
81
- ( T . leastNormalMagnitude. exponent + T. Exponent ( T . significandBitCount) ) ...
82
- T . greatestFiniteMagnitude. exponent
83
- let inputs = ( 0 ..< 100 ) . map { _ in
84
- Polar ( length: T (
85
- sign: . plus,
86
- exponent: T . Exponent. random ( in: exponentRange) ,
87
- significand: T . random ( in: 1 ..< 2 )
88
- ) , phase: T . random ( in: - . pi ... . pi) )
89
- }
90
- for p in inputs {
91
- // first test that each value can round-trip between rectangular and
92
- // polar coordinates with reasonable accuracy. We'll probably need to
93
- // relax this for some platforms (currently we're using the default
94
- // RNG, which means we don't get the same sequence of values each time;
95
- // this is good--more test coverage!--and bad, because without tight
96
- // bounds on every platform's libm, we can't get tight bounds on the
97
- // accuracy of these operations, so we need to relax them gradually).
98
- let z = Complex ( length: p. length, phase: p. phase)
99
- if !closeEnough( z. length, p. length, ulps: 16 ) {
100
- print ( " p = \( p) \n z = \( z) \n z.length = \( z. length) " )
101
- XCTFail ( )
102
- }
103
- if !closeEnough( z. phase, p. phase, ulps: 16 ) {
104
- print ( " p = \( p) \n z = \( z) \n z.phase = \( z. phase) " )
105
- XCTFail ( )
106
- }
107
- // Complex(length: -r, phase: θ) = -Complex(length: r, phase: θ).
108
- let w = Complex ( length: - p. length, phase: p. phase)
109
- if w != - z {
110
- print ( " p = \( p) \n w = \( w) \n z = \( z) " )
111
- XCTFail ( )
112
- }
113
- XCTAssertEqual ( w, - z)
114
- // if length*length is normal, it should be lengthSquared, up
115
- // to small error.
116
- if ( p. length*p. length) . isNormal {
117
- if !closeEnough( z. lengthSquared, p. length*p. length, ulps: 16 ) {
118
- print ( " p = \( p) \n z = \( z) \n z.lengthSquared = \( z. lengthSquared) " )
119
- XCTFail ( )
120
- }
121
- }
122
- // Test reciprocal and normalized:
123
- let r = Complex ( length: 1 / p. length, phase: - p. phase)
124
- if r. isNormal {
125
- if relativeError ( r, z. reciprocal!) > 16 {
126
- print ( " p = \( p) \n z = \( z) \n z.reciprocal = \( r) " )
127
- XCTFail ( )
67
+ // In order to support round-tripping from rectangular to polar coordinate
68
+ // systems, as a special case phase can be non-finite when length is
69
+ // either zero or infinity.
70
+ XCTAssertEqual ( Complex < T > ( length: . zero, phase: . infinity) , . zero)
71
+ XCTAssertEqual ( Complex < T > ( length: . zero, phase: - . infinity) , . zero)
72
+ XCTAssertEqual ( Complex < T > ( length: . zero, phase: . nan ) , . zero)
73
+ XCTAssertEqual ( Complex < T > ( length: . infinity, phase: . infinity) , . infinity)
74
+ XCTAssertEqual ( Complex < T > ( length: . infinity, phase: - . infinity) , . infinity)
75
+ XCTAssertEqual ( Complex < T > ( length: . infinity, phase: . nan ) , . infinity)
76
+ XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: . infinity) , . infinity)
77
+ XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: - . infinity) , . infinity)
78
+ XCTAssertEqual ( Complex < T > ( length: - . infinity, phase: . nan ) , . infinity)
79
+
80
+ let exponentRange =
81
+ T . leastNormalMagnitude. exponent ... T . greatestFiniteMagnitude. exponent
82
+ let inputs = ( 0 ..< 100 ) . map { _ in
83
+ Polar ( length: T (
84
+ sign: . plus,
85
+ exponent: T . Exponent. random ( in: exponentRange) ,
86
+ significand: T . random ( in: 1 ..< 2 )
87
+ ) , phase: T . random ( in: - . pi ... . pi) )
88
+ }
89
+ for p in inputs {
90
+ // first test that each value can round-trip between rectangular and
91
+ // polar coordinates with reasonable accuracy. We'll probably need to
92
+ // relax this for some platforms (currently we're using the default
93
+ // RNG, which means we don't get the same sequence of values each time;
94
+ // this is good--more test coverage!--and bad, because without tight
95
+ // bounds on every platform's libm, we can't get tight bounds on the
96
+ // accuracy of these operations, so we need to relax them gradually).
97
+ let z = Complex ( length: p. length, phase: p. phase)
98
+ if !closeEnough( z. length, p. length, ulps: 16 ) {
99
+ print ( " p = \( p) \n z = \( z) \n z.length = \( z. length) " )
100
+ XCTFail ( )
101
+ }
102
+ if !closeEnough( z. phase, p. phase, ulps: 16 ) {
103
+ print ( " p = \( p) \n z = \( z) \n z.phase = \( z. phase) " )
104
+ XCTFail ( )
105
+ }
106
+ // Complex(length: -r, phase: θ) = -Complex(length: r, phase: θ).
107
+ let w = Complex ( length: - p. length, phase: p. phase)
108
+ if w != - z {
109
+ print ( " p = \( p) \n w = \( w) \n z = \( z) " )
110
+ XCTFail ( )
111
+ }
112
+ XCTAssertEqual ( w, - z)
113
+ // if length*length is normal, it should be lengthSquared, up
114
+ // to small error.
115
+ if ( p. length*p. length) . isNormal {
116
+ if !closeEnough( z. lengthSquared, p. length*p. length, ulps: 16 ) {
117
+ print ( " p = \( p) \n z = \( z) \n z.lengthSquared = \( z. lengthSquared) " )
118
+ XCTFail ( )
119
+ }
120
+ }
121
+ // Test reciprocal and normalized:
122
+ let r = Complex ( length: 1 / p. length, phase: - p. phase)
123
+ if r. isNormal {
124
+ if relativeError ( r, z. reciprocal!) > 16 {
125
+ print ( " p = \( p) \n z = \( z) \n z.reciprocal = \( r) " )
126
+ XCTFail ( )
127
+ }
128
+ } else { XCTAssertNil ( z. reciprocal) }
129
+ let n = Complex ( length: 1 , phase: p. phase)
130
+ if relativeError ( n, z. normalized!) > 16 {
131
+ print ( " p = \( p) \n z = \( z) \n z.normalized = \( n) " )
132
+ XCTFail ( )
133
+ }
134
+
135
+ // Now test multiplication and division using the polar inputs:
136
+ for q in inputs {
137
+ let w = Complex ( length: q. length, phase: q. phase)
138
+ var product = Complex ( length: p. length, phase: p. phase + q. phase)
139
+ product. real *= q. length
140
+ product. imaginary *= q. length
141
+ if checkMultiply ( z, w, expected: product, ulps: 16 ) { XCTFail ( ) }
142
+ var quotient = Complex ( length: p. length, phase: p. phase - q. phase)
143
+ quotient. real /= q. length
144
+ quotient. imaginary /= q. length
145
+ if checkDivide ( z, w, expected: quotient, ulps: 16 ) { XCTFail ( ) }
146
+ }
147
+ }
128
148
}
129
- } else { XCTAssertNil ( z. reciprocal) }
130
- let n = Complex ( length: 1 , phase: p. phase)
131
- if relativeError ( n, z. normalized!) > 16 {
132
- print ( " p = \( p) \n z = \( z) \n z.normalized = \( n) " )
133
- XCTFail ( )
134
- }
135
-
136
- // Now test multiplication and division using the polar inputs:
137
- for q in inputs {
138
- let w = Complex ( length: q. length, phase: q. phase)
139
- let product = Complex ( length: p. length * q. length, phase: p. phase + q. phase)
140
- if checkMultiply ( z, w, expected: product, ulps: 16 ) { XCTFail ( ) }
141
- let quotient = Complex ( length: p. length / q. length, phase: p. phase - q. phase)
142
- if checkDivide ( z, w, expected: quotient, ulps: 16 ) { XCTFail ( ) }
143
- }
144
- }
145
- }
146
149
147
150
func testPolar( ) {
151
+ #if (arch(arm64))
152
+ // testPolar(Float16.self)
153
+ #endif
148
154
testPolar ( Float . self)
149
155
testPolar ( Double . self)
150
- #if (arch(i386) || arch(x86_64)) && !os(Windows) && !os(Android)
156
+ #if (arch(i386) || arch(x86_64)) && !os(Windows) && !os(Android)
151
157
testPolar ( Float80 . self)
152
- #endif
158
+ #endif
153
159
}
154
160
155
161
func testBaudinSmith( ) {
@@ -191,16 +197,49 @@ final class ArithmeticTests: XCTestCase {
191
197
Complex ( 1.02951151789360578e-84 , 6.97145987515076231e-220 ) ) ,
192
198
]
193
199
for test in vectors {
194
- if checkDivide ( test. a, test. b, expected: test. c, ulps: 0.5 ) { XCTFail ( ) }
200
+ if checkDivide ( test. a, test. b, expected: test. c, ulps: 1.0 ) { XCTFail ( ) }
195
201
if checkDivide ( test. a, test. c, expected: test. b, ulps: 1.0 ) { XCTFail ( ) }
196
202
if checkMultiply ( test. b, test. c, expected: test. a, ulps: 1.0 ) { XCTFail ( ) }
197
203
}
198
204
}
199
-
205
+
200
206
func testDivisionByZero( ) {
201
207
XCTAssertFalse ( ( Complex ( 0 , 0 ) / Complex( 0 , 0 ) ) . isFinite)
202
208
XCTAssertFalse ( ( Complex ( 1 , 1 ) / Complex( 0 , 0 ) ) . isFinite)
203
209
XCTAssertFalse ( ( Complex . infinity / Complex( 0 , 0 ) ) . isFinite)
204
210
XCTAssertFalse ( ( Complex . i / Complex( 0 , 0 ) ) . isFinite)
211
+
212
+ }
213
+
214
+ #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
215
+
216
+ /*
217
+ @available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
218
+ func testFloat16DivisionSemiExhaustive() {
219
+ func complex(bitPattern: UInt32) -> Complex<Float16> {
220
+ Complex(
221
+ Float16(bitPattern: UInt16(truncatingIfNeeded: bitPattern)),
222
+ Float16(bitPattern: UInt16(truncatingIfNeeded: bitPattern >> 16))
223
+ )
224
+ }
225
+ for bits in 0 ... UInt32.max {
226
+ let a = complex(bitPattern: bits)
227
+ if bits & 0xfffff == 0 { print(a) }
228
+ let b = complex(bitPattern: UInt32.random(in: 0 ... .max))
229
+ var q = Complex<Float>(a)/Complex<Float>(b)
230
+ if checkDivide(a, b, expected: Complex<Float16>(q), ulps: 32) { XCTFail() }
231
+ q = Complex<Float>(b)/Complex<Float>(a)
232
+ if checkDivide(b, a, expected: Complex<Float16>(q), ulps: 32) { XCTFail() }
233
+ }
234
+ }
235
+ */
236
+
237
+ @available ( macOS 11 . 0 , iOS 14 . 0 , tvOS 14 . 0 , watchOS 7 . 0 , * )
238
+ func testSpecificFloat16Value( ) {
239
+ let a = Complex < Float16 > ( 4.66 , 3e-07 )
240
+ let b = Complex < Float16 > ( - 4.32e-05 , 4.977e-05 )
241
+ let q = a / b
242
+ XCTAssertEqual ( q, Complex < Float16 > ( - 46368.0 , - 53376.0 ) )
205
243
}
244
+ #endif
206
245
}
0 commit comments