1
- import TensorFlow
2
- // T : FloatingPoint & Differentiable
3
1
public struct Complex < T : FloatingPoint > {
4
- // ---------------------------------------------------------------------------
5
- // MARK: Stored Properties
6
- // ---------------------------------------------------------------------------
7
-
8
- /// The real component of the complex value.
9
2
public var real : T
10
-
11
- /// The imaginary component of the complex value.
12
3
public var imaginary : T
13
4
14
- // ---------------------------------------------------------------------------
15
- // MARK: Initializers
16
- // ---------------------------------------------------------------------------
17
5
public init ( real: T = 0 , imaginary: T = 0 ) {
18
6
self . real = real
19
7
self . imaginary = imaginary
20
8
}
21
9
}
22
10
23
- extension Complex : Differentiable where T : Differentiable /*, T.TangentVector == T*/ {
24
- // ---------------------------------------------------------------------------
25
- // MARK: Differentiability
26
- // ---------------------------------------------------------------------------
11
+ extension Complex : Differentiable where T : Differentiable {
27
12
public typealias TangentVector = Complex
28
13
public typealias AllDifferentiableVariables = Complex
29
14
}
30
15
31
16
extension Complex {
32
- // ---------------------------------------------------------------------------
33
- // MARK: Static Properties
34
- // ---------------------------------------------------------------------------
35
-
36
- /// The imaginary unit _i_.
37
17
@inlinable
38
18
public static var i : Complex {
39
19
return Complex ( real: 0 , imaginary: 1 )
40
20
}
41
21
42
- /// A Boolean value indicating whether the instance is finite.
43
- ///
44
- /// A complex value is finite if its real and imaginary components are both
45
- /// finite. A component is finite if it is not infinity or NaN.
46
22
@inlinable
47
23
public var isFinite : Bool {
48
24
return real. isFinite && imaginary. isFinite
49
25
}
50
26
51
- /// A Boolean value indicating whether the instance is infinite.
52
- ///
53
- /// A complex value is infinite if at least one of its components (real or
54
- /// imaginary) is infinite, even if the other component is NaN.
55
- ///
56
- /// Note that `isFinite` and `isInfinite` do not form a dichotomy because NaN
57
- /// is neither finite nor infinite.
58
27
@inlinable
59
28
public var isInfinite : Bool {
60
29
return real. isInfinite || imaginary. isInfinite
61
30
}
62
31
63
- /// A Boolean value indicating whether the instance is NaN ("not a number").
64
- ///
65
- /// A complex value is NaN if at least one of its components (real or
66
- /// imaginary) is NaN and the other component is not infinite.
67
- ///
68
- /// Because NaN is not equal to any value, including NaN, use this property
69
- /// instead of the equal-to operator (`==`) or not-equal-to operator (`!=`) to
70
- /// test whether a value is or is not NaN.
71
- ///
72
- /// This property is `true` for both quiet and signaling NaNs.
73
32
@inlinable
74
33
public var isNaN : Bool {
75
34
return ( real. isNaN && !imaginary. isInfinite) ||
76
35
( imaginary. isNaN && !real. isInfinite)
77
36
}
78
37
79
- /// A Boolean value indicating whether the instance is equal to zero.
80
- ///
81
- /// A complex value is equal to zero if its real and imaginary components both
82
- /// represent either `-0.0` or `+0.0`.
83
38
@inlinable
84
39
public var isZero : Bool {
85
40
return real. isZero && imaginary. isZero
86
41
}
87
42
}
88
43
89
44
extension Complex : ExpressibleByIntegerLiteral {
90
- // ---------------------------------------------------------------------------
91
- // MARK: ExpressibleByIntegerLiteral
92
- // ---------------------------------------------------------------------------
93
-
94
45
@inlinable
95
46
public init ( integerLiteral value: Int ) {
96
47
self . real = T ( value)
@@ -99,16 +50,9 @@ extension Complex : ExpressibleByIntegerLiteral {
99
50
}
100
51
101
52
extension Complex : CustomStringConvertible {
102
- // ---------------------------------------------------------------------------
103
- // MARK: CustomStringConvertible
104
- // ---------------------------------------------------------------------------
105
-
106
53
@inlinable
107
54
public var description : String {
108
55
return real. isNaN && real. sign == . minus
109
- // At present, -NaN is described as "nan", which is acceptable for real
110
- // values. However, it is arguably misleading to describe -NaN - NaNi as
111
- // "nan + nani" or "nan - nani". Therefore, handle this case separately.
112
56
? imaginary. sign == . minus
113
57
? " - \( - real) - \( - imaginary) i "
114
58
: " - \( - real) + \( imaginary) i "
@@ -119,21 +63,13 @@ extension Complex : CustomStringConvertible {
119
63
}
120
64
121
65
extension Complex : Equatable {
122
- // ---------------------------------------------------------------------------
123
- // MARK: Equatable
124
- // ---------------------------------------------------------------------------
125
-
126
66
@inlinable
127
67
public static func == ( lhs: Complex , rhs: Complex ) -> Bool {
128
68
return lhs. real == rhs. real && lhs. imaginary == rhs. imaginary
129
69
}
130
70
}
131
71
132
72
extension Complex : AdditiveArithmetic {
133
- // ---------------------------------------------------------------------------
134
- // MARK: AdditiveArithmetic
135
- // ---------------------------------------------------------------------------
136
-
137
73
@inlinable
138
74
@differentiable ( vjp: _vjpAdd ( lhs: rhs: ) where T : Differentiable)
139
75
public static func + ( lhs: Complex , rhs: Complex ) -> Complex {
@@ -164,10 +100,6 @@ extension Complex : AdditiveArithmetic {
164
100
}
165
101
166
102
extension Complex : Numeric {
167
- // ---------------------------------------------------------------------------
168
- // MARK: Numeric
169
- // ---------------------------------------------------------------------------
170
-
171
103
public init ? < U> ( exactly source: U ) where U : BinaryInteger {
172
104
guard let t = T ( exactly: source) else { return nil }
173
105
self . real = t
@@ -181,20 +113,17 @@ extension Complex : Numeric {
181
113
let ac = a * c, bd = b * d, ad = a * d, bc = b * c
182
114
let x = ac - bd
183
115
let y = ad + bc
184
- // Recover infinities that computed as NaN + iNaN.
185
- // See C11 Annex G.
116
+
186
117
if x. isNaN && y. isNaN {
187
118
var recalculate = false
188
119
if a. isInfinite || b. isInfinite {
189
- // "Box" the infinity and change NaNs in the other operand to 0.
190
120
a = T ( signOf: a, magnitudeOf: a. isInfinite ? 1 : 0 )
191
121
b = T ( signOf: b, magnitudeOf: b. isInfinite ? 1 : 0 )
192
122
if c. isNaN { c = T ( signOf: c, magnitudeOf: 0 ) }
193
123
if d. isNaN { d = T ( signOf: d, magnitudeOf: 0 ) }
194
124
recalculate = true
195
125
}
196
126
if c. isInfinite || d. isInfinite {
197
- // "Box" the infinity and change NaNs in the other operand to 0.
198
127
if a. isNaN { a = T ( signOf: a, magnitudeOf: 0 ) }
199
128
if b. isNaN { b = T ( signOf: b, magnitudeOf: 0 ) }
200
129
c = T ( signOf: c, magnitudeOf: c. isInfinite ? 1 : 0 )
@@ -203,7 +132,6 @@ extension Complex : Numeric {
203
132
}
204
133
if !recalculate &&
205
134
( ac. isInfinite || bd. isInfinite || ad. isInfinite || bc. isInfinite) {
206
- // Recover infinities from overflow by changing NaNs to 0.
207
135
if a. isNaN { a = T ( signOf: a, magnitudeOf: 0 ) }
208
136
if b. isNaN { b = T ( signOf: b, magnitudeOf: 0 ) }
209
137
if c. isNaN { c = T ( signOf: c, magnitudeOf: 0 ) }
@@ -239,10 +167,6 @@ extension Complex : Numeric {
239
167
}
240
168
241
169
extension Complex : SignedNumeric {
242
- // ---------------------------------------------------------------------------
243
- // MARK: SignedNumeric
244
- // ---------------------------------------------------------------------------
245
-
246
170
@inlinable
247
171
@differentiable ( vjp: _vjpNegate where T : Differentiable)
248
172
public static prefix func - ( operand: Complex ) -> Complex {
@@ -257,17 +181,12 @@ extension Complex : SignedNumeric {
257
181
}
258
182
259
183
extension Complex {
260
- // ---------------------------------------------------------------------------
261
- // MARK: Division
262
- // ---------------------------------------------------------------------------
263
-
264
184
@inlinable
265
185
@differentiable ( vjp: _vjpDivide ( lhs: rhs: ) where T : Differentiable)
266
186
public static func / ( lhs: Complex , rhs: Complex ) -> Complex {
267
187
var a = lhs. real, b = lhs. imaginary, c = rhs. real, d = rhs. imaginary
268
188
var x : T
269
189
var y : T
270
- // Prevent avoidable overflow; see Numerical Recipes.
271
190
if c. magnitude >= d. magnitude {
272
191
let ratio = d / c
273
192
let denominator = c + d * ratio
@@ -279,12 +198,10 @@ extension Complex {
279
198
x = ( a * ratio + b) / denominator
280
199
y = ( b * ratio - a) / denominator
281
200
}
282
- // Recover infinities and zeros that computed as NaN + iNaN.
283
- // See C11 Annex G.
284
201
if x. isNaN && y. isNaN {
285
202
if c == 0 && d == 0 && ( !a. isNaN || !b. isNaN) {
286
203
x = T ( signOf: c, magnitudeOf: . infinity) * a
287
- y = T ( signOf: c /* sic */ , magnitudeOf: . infinity) * b
204
+ y = T ( signOf: c, magnitudeOf: . infinity) * b
288
205
} else if ( a. isInfinite || b. isInfinite) && c. isFinite && d. isFinite {
289
206
a = T ( signOf: a, magnitudeOf: a. isInfinite ? 1 : 0 )
290
207
b = T ( signOf: b, magnitudeOf: b. isInfinite ? 1 : 0 )
@@ -313,7 +230,6 @@ extension Complex {
313
230
}
314
231
}
315
232
316
- /// Returns the absolute value (magnitude, modulus) of `z`.
317
233
@inlinable
318
234
public func abs< T> ( _ z: Complex < T > ) -> Complex < T > {
319
235
return Complex ( real: z. magnitude)
@@ -353,7 +269,7 @@ extension Complex {
353
269
}
354
270
}
355
271
356
- extension Complex where T : Differentiable /*, T.TangentVector == T*/ {
272
+ extension Complex where T : Differentiable {
357
273
@inlinable
358
274
static func _vjpAdd( lhs: Complex , rhs: Complex )
359
275
-> ( Complex , ( Complex ) -> ( Complex , Complex ) ) {
0 commit comments