Skip to content

Commit 964e62c

Browse files
committed
Merge branch 'main' into quaternion/sync
2 parents 8ada4cf + 0dc8fef commit 964e62c

38 files changed

+581
-1075
lines changed

Package.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.0
1+
// swift-tools-version:5.4
22
//===--- Package.swift ----------------------------------------*- swift -*-===//
33
//
44
// This source file is part of the Swift Numerics open source project
@@ -61,8 +61,8 @@ let package = Package(
6161
// MARK: - Implementation details
6262
.target(
6363
name: "_NumericsShims",
64-
dependencies: [],
65-
exclude: excludedFilenames
64+
exclude: excludedFilenames,
65+
linkerSettings: [.linkedLibrary("m", .when(platforms: [.linux, .android]))]
6666
),
6767

6868
.target(
@@ -96,13 +96,13 @@ let package = Package(
9696
),
9797

9898
// MARK: - Test executables
99-
.target(
99+
.executableTarget(
100100
name: "ComplexLog",
101101
dependencies: ["Numerics", "_TestSupport"],
102102
path: "Tests/Executable/ComplexLog"
103103
),
104104

105-
.target(
105+
.executableTarget(
106106
name: "ComplexLog1p",
107107
dependencies: ["Numerics", "_TestSupport"],
108108
path: "Tests/Executable/ComplexLog1p"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ To use Swift Numerics in a SwiftPM project:
5959
## Source stability
6060

6161
The Swift Numerics package is source stable; version numbers follow [Semantic Versioning](https://semver.org).
62-
The public API of the `swift-numerics` package consists of non-underscored declarations that are marked either `public` or `usableFromInline` in modules re-exported by the top-level `Numerics` module, *excepting any API that involves a conformance to Differentiable (because Differentiable itself is not stable in Swift)*.
62+
The public API of the `swift-numerics` package consists of non-underscored declarations that are marked either `public` or `usableFromInline` in modules re-exported by the top-level `Numerics` module.
6363
Interfaces that aren't part of the public API may continue to change in any release, including patch releases.
6464

6565
Note that contents of the `_NumericsShims` and `_TestSupport` modules, as well as contents of the `Tests` directory, explicitly are not public API.

Sources/ComplexModule/CMakeLists.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ See https://swift.org/LICENSE.txt for license information
88
#]]
99

1010
add_library(ComplexModule
11-
Arithmetic.swift
1211
Complex.swift
13-
Differentiable.swift
14-
ElementaryFunctions.swift)
12+
Complex+AdditiveArithmetic.swift
13+
Complex+AlgebraicField.swift
14+
Complex+Codable.swift
15+
Complex+ElementaryFunctions.swift
16+
Complex+Hashable.swift
17+
Complex+IntegerLiteral.swift
18+
Complex+Numeric.swift
19+
Complex+StringConvertible.swift
20+
Polar.swift
21+
Scale.swift)
1522
set_target_properties(ComplexModule PROPERTIES
1623
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
1724
target_link_libraries(ComplexModule PUBLIC
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===--- Complex+AdditiveArithmetic.swift ---------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Numerics open source project
4+
//
5+
// Copyright (c) 2019-2021 Apple Inc. and the Swift Numerics project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import RealModule
13+
14+
extension Complex: AdditiveArithmetic {
15+
/// The additive identity, with real and imaginary parts both zero.
16+
///
17+
/// See also: `one`, `i`, `infinity`
18+
@_transparent
19+
public static var zero: Complex {
20+
Complex(0, 0)
21+
}
22+
23+
@_transparent
24+
public static func +(z: Complex, w: Complex) -> Complex {
25+
return Complex(z.x + w.x, z.y + w.y)
26+
}
27+
28+
@_transparent
29+
public static func -(z: Complex, w: Complex) -> Complex {
30+
return Complex(z.x - w.x, z.y - w.y)
31+
}
32+
33+
@_transparent
34+
public static func +=(z: inout Complex, w: Complex) {
35+
z = z + w
36+
}
37+
38+
@_transparent
39+
public static func -=(z: inout Complex, w: Complex) {
40+
z = z - w
41+
}
42+
}

Sources/ComplexModule/Arithmetic.swift renamed to Sources/ComplexModule/Complex+AlgebraicField.swift

Lines changed: 12 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
//===--- Arithmetic.swift -------------------------------------*- swift -*-===//
1+
//===--- Complex+AlgebraicField.swift -------------------------*- swift -*-===//
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-2021 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
@@ -11,81 +11,19 @@
1111

1212
import RealModule
1313

14-
// MARK: - Additive structure
15-
extension Complex: AdditiveArithmetic {
16-
@_transparent
17-
public static func +(z: Complex, w: Complex) -> Complex {
18-
return Complex(z.x + w.x, z.y + w.y)
19-
}
20-
21-
@_transparent
22-
public static func -(z: Complex, w: Complex) -> Complex {
23-
return Complex(z.x - w.x, z.y - w.y)
24-
}
25-
14+
extension Complex: AlgebraicField {
15+
/// The multiplicative identity `1 + 0i`.
2616
@_transparent
27-
public static func +=(z: inout Complex, w: Complex) {
28-
z = z + w
17+
public static var one: Complex {
18+
Complex(1, 0)
2919
}
3020

21+
/// The [complex conjugate][conj] of this value.
22+
///
23+
/// [conj]: https://en.wikipedia.org/wiki/Complex_conjugate
3124
@_transparent
32-
public static func -=(z: inout Complex, w: Complex) {
33-
z = z - w
34-
}
35-
}
36-
37-
// MARK: - Vector space structure
38-
//
39-
// Policy: deliberately not using the * and / operators for these at the
40-
// moment, because then there's an ambiguity in expressions like 2*z; is
41-
// that Complex(2) * z or is it RealType(2) * z? This is especially
42-
// problematic in type inference: suppose we have:
43-
//
44-
// let a: RealType = 1
45-
// let b = 2*a
46-
//
47-
// what is the type of b? If we don't have a type context, it's ambiguous.
48-
// If we have a Complex type context, then b will be inferred to have type
49-
// Complex! Obviously, that doesn't help anyone.
50-
//
51-
// TODO: figure out if there's some way to avoid these surprising results
52-
// and turn these into operators if/when we have it.
53-
// (https://github.com/apple/swift-numerics/issues/12)
54-
extension Complex {
55-
/// `self` scaled by `a`.
56-
@usableFromInline @_transparent
57-
internal func multiplied(by a: RealType) -> Complex {
58-
// This can be viewed in two different ways, which are mathematically
59-
// equivalent: either we are computing `self * Complex(a)` (i.e.
60-
// converting `a` to be a complex value, and then using the complex
61-
// multiplication) or we are using the scalar product of the vector
62-
// space structure: `Complex(a*real, a*imaginary)`.
63-
//
64-
// Although these two interpretations are _mathematically_ equivalent,
65-
// they will generate different representations of the point at
66-
// infinity in general. For example, suppose `self` is represented by
67-
// `(infinity, 0)`. Then `self * Complex(1)` would evaluate as
68-
// `(1*infinity - 0*0, 0*infinity + 1*0) = (infinity, nan)`, but
69-
// the vector space interpretation produces `(infinity, 0)`. This does
70-
// not matter much, because these are two representations of the same
71-
// semantic value, but note that one requires four multiplies and two
72-
// additions, while the one we use requires only two real multiplications.
73-
Complex(x*a, y*a)
74-
}
75-
76-
/// `self` unscaled by `a`.
77-
@usableFromInline @_transparent
78-
internal func divided(by a: RealType) -> Complex {
79-
// See implementation notes for `multiplied` above.
80-
Complex(x/a, y/a)
81-
}
82-
}
83-
84-
// MARK: - Multiplicative structure
85-
extension Complex: AlgebraicField {
86-
@_transparent
87-
public static func *(z: Complex, w: Complex) -> Complex {
88-
return Complex(z.x*w.x - z.y*w.y, z.x*w.y + z.y*w.x)
25+
public var conjugate: Complex {
26+
Complex(x, -y)
8927
}
9028

9129
@_transparent
@@ -98,11 +36,6 @@ extension Complex: AlgebraicField {
9836
return z * (w.conjugate.divided(by: lenSq))
9937
}
10038

101-
@_transparent
102-
public static func *=(z: inout Complex, w: Complex) {
103-
z = z * w
104-
}
105-
10639
@_transparent
10740
public static func /=(z: inout Complex, w: Complex) {
10841
z = z / w
@@ -178,7 +111,7 @@ extension Complex: AlgebraicField {
178111
/// ```
179112
///
180113
/// Error Bounds:
181-
/// -
114+
///
182115
/// Unlike real types, when working with complex types, multiplying by the
183116
/// reciprocal instead of dividing cannot change the result. If the
184117
/// reciprocal is non-nil, the two computations are always equivalent.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===--- Complex+Codable.swift --------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Numerics open source project
4+
//
5+
// Copyright (c) 2019 - 2021 Apple Inc. and the Swift Numerics project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import RealModule
13+
14+
// FloatingPoint does not refine Codable, so this is a conditional conformance.
15+
extension Complex: Decodable where RealType: Decodable {
16+
public init(from decoder: Decoder) throws {
17+
var unkeyedContainer = try decoder.unkeyedContainer()
18+
let x = try unkeyedContainer.decode(RealType.self)
19+
let y = try unkeyedContainer.decode(RealType.self)
20+
self.init(x, y)
21+
}
22+
}
23+
24+
extension Complex: Encodable where RealType: Encodable {
25+
public func encode(to encoder: Encoder) throws {
26+
var unkeyedContainer = encoder.unkeyedContainer()
27+
try unkeyedContainer.encode(x)
28+
try unkeyedContainer.encode(y)
29+
}
30+
}

Sources/ComplexModule/ElementaryFunctions.swift renamed to Sources/ComplexModule/Complex+ElementaryFunctions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- ElementaryFunctions.swift ----------------------------*- swift -*-===//
1+
//===--- Complex+ElementaryFunctions.swift --------------------*- swift -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===--- Complex+Hashable.swift -------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Numerics open source project
4+
//
5+
// Copyright (c) 2019 - 2021 Apple Inc. and the Swift Numerics project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import RealModule
13+
14+
extension Complex: Hashable {
15+
@_transparent
16+
public static func ==(a: Complex, b: Complex) -> Bool {
17+
// Identify all numbers with either component non-finite as a single
18+
// "point at infinity".
19+
guard a.isFinite || b.isFinite else { return true }
20+
// For finite numbers, equality is defined componentwise. Cases where
21+
// only one of a or b is infinite fall through to here as well, but this
22+
// expression correctly returns false for them so we don't need to handle
23+
// them explicitly.
24+
return a.x == b.x && a.y == b.y
25+
}
26+
27+
@_transparent
28+
public func hash(into hasher: inout Hasher) {
29+
// There are two equivalence classes to which we owe special attention:
30+
// All zeros should hash to the same value, regardless of sign, and all
31+
// non-finite numbers should hash to the same value, regardless of
32+
// representation. The correct behavior for zero falls out for free from
33+
// the hash behavior of floating-point, but we need to use a
34+
// representative member for any non-finite values.
35+
if isFinite {
36+
hasher.combine(x)
37+
hasher.combine(y)
38+
} else {
39+
hasher.combine(RealType.infinity)
40+
}
41+
}
42+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===--- Complex+IntegerLiteral.swift -------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Numerics open source project
4+
//
5+
// Copyright (c) 2019 - 2021 Apple Inc. and the Swift Numerics project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
extension Complex: ExpressibleByIntegerLiteral {
13+
public typealias IntegerLiteralType = RealType.IntegerLiteralType
14+
15+
@inlinable
16+
public init(integerLiteral value: IntegerLiteralType) {
17+
self.init(RealType(integerLiteral: value))
18+
}
19+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===--- Complex+Numeric.swift --------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Numerics open source project
4+
//
5+
// Copyright (c) 2019 - 2021 Apple Inc. and the Swift Numerics project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
extension Complex: Numeric {
13+
14+
@_transparent
15+
public static func *(z: Complex, w: Complex) -> Complex {
16+
return Complex(z.x*w.x - z.y*w.y, z.x*w.y + z.y*w.x)
17+
}
18+
19+
@_transparent
20+
public static func *=(z: inout Complex, w: Complex) {
21+
z = z * w
22+
}
23+
24+
/// The complex number with specified real part and zero imaginary part.
25+
///
26+
/// Equivalent to `Complex(RealType(real), 0)`.
27+
@inlinable
28+
public init<Other: BinaryInteger>(_ real: Other) {
29+
self.init(RealType(real), 0)
30+
}
31+
32+
/// The complex number with specified real part and zero imaginary part,
33+
/// if it can be constructed without rounding.
34+
@inlinable
35+
public init?<Other: BinaryInteger>(exactly real: Other) {
36+
guard let real = RealType(exactly: real) else { return nil }
37+
self.init(real, 0)
38+
}
39+
40+
/// The ∞-norm of the value (`max(abs(real), abs(imaginary))`).
41+
///
42+
/// If you need the Euclidean norm (a.k.a. 2-norm) use the `length` or
43+
/// `lengthSquared` properties instead.
44+
///
45+
/// Edge cases:
46+
/// - If `z` is not finite, `z.magnitude` is `.infinity`.
47+
/// - If `z` is zero, `z.magnitude` is `0`.
48+
/// - Otherwise, `z.magnitude` is finite and non-zero.
49+
///
50+
/// See also `.length` and `.lengthSquared`.
51+
@_transparent
52+
public var magnitude: RealType {
53+
guard isFinite else { return .infinity }
54+
return max(abs(x), abs(y))
55+
}
56+
}

0 commit comments

Comments
 (0)