Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The future is now #136

Merged
merged 21 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a35f5ba
Add Real conformance for Float16.
stephentyrone Apr 8, 2020
29d25b6
Merge pull request #106 from stephentyrone/Float16-support
stephentyrone Apr 8, 2020
9e1645a
Additional test coverage for pow with integer exponents.
stephentyrone Apr 10, 2020
75e4116
Additional test coverage for Float16 power with integer exponents.
stephentyrone Apr 10, 2020
ee082ef
Fix bug for very large exponents pow(Float/Double, Int).
stephentyrone Apr 10, 2020
5944434
Somewhat better implementation of pow(x,n) for Float16.
stephentyrone Apr 10, 2020
8978159
Merge pull request #108 from stephentyrone/better-pown-float16
stephentyrone Apr 10, 2020
a5cc950
Merge pull request #111 from rxwei/complex-derivatives
stephentyrone Apr 22, 2020
93b8e9f
Float16 is unavailable on macOS 11.
stephentyrone Jun 29, 2020
e97070e
file -> filePath, too.
stephentyrone Jun 29, 2020
085f6da
Merge branch 'master' into swift-5.3
stephentyrone Jul 1, 2020
40b5a03
Merge pull request #105 from compnerd/cmake
stephentyrone Jul 3, 2020
13b74ae
Merge branch 'master' into swift-5.3
stephentyrone Jul 27, 2020
4cd1155
Add Float16 tests for Approximate Equality.
stephentyrone Jul 27, 2020
66ac021
Don't test approximate equality for Float80 on platforms that don't h…
stephentyrone Jul 27, 2020
336740b
Also mark Complex<Float80> test unavailable where needed.
stephentyrone Jul 27, 2020
4771ef2
Remove float16 tests for approx equality for now.
stephentyrone Jul 27, 2020
1ec79f5
Add Swift version check for differentiable features.
stephentyrone Aug 4, 2020
7e032e2
Merge remote-tracking branch 'upstream/swift-5.3'
stephentyrone Aug 4, 2020
d368762
Add swift version checks for Float16.
stephentyrone Aug 4, 2020
9782441
Disable Float16 tests on swift < 5.3
stephentyrone Aug 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Sources/ComplexModule/Differentiable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//
//===----------------------------------------------------------------------===//

#if canImport(_Differentiation)
#if swift(>=5.3) && canImport(_Differentiation)
import _Differentiation

extension Complex: Differentiable
Expand All @@ -24,6 +24,16 @@ where RealType: Differentiable, RealType.TangentVector == RealType {

extension Complex
where RealType: Differentiable, RealType.TangentVector == RealType {
@derivative(of: init(_:_:))
@usableFromInline
static func _derivativeInit(
_ real: RealType,
_ imaginary: RealType
) -> (value: Complex, pullback: (Complex) -> (RealType, RealType)) {
(value: .init(real, imaginary), pullback: { v in
(v.real, v.imaginary)
})
}

@derivative(of: real)
@usableFromInline
Expand Down
176 changes: 176 additions & 0 deletions Sources/RealModule/Float16+Real.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
//===--- Float16+Real.swift -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift Numerics open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift Numerics project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

#if swift(>=5.3)
import _NumericsShims

@available(iOS 14.0, tvOS 14.0, watchOS 7.0, *)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
extension Float16: Real {
@_transparent
public static func cos(_ x: Float16) -> Float16 {
Float16(.cos(Float(x)))
}

@_transparent
public static func sin(_ x: Float16) -> Float16 {
Float16(.sin(Float(x)))
}

@_transparent
public static func tan(_ x: Float16) -> Float16 {
Float16(.tan(Float(x)))
}

@_transparent
public static func acos(_ x: Float16) -> Float16 {
Float16(.acos(Float(x)))
}

@_transparent
public static func asin(_ x: Float16) -> Float16 {
Float16(.asin(Float(x)))
}

@_transparent
public static func atan(_ x: Float16) -> Float16 {
Float16(.atan(Float(x)))
}

@_transparent
public static func cosh(_ x: Float16) -> Float16 {
Float16(.cosh(Float(x)))
}

@_transparent
public static func sinh(_ x: Float16) -> Float16 {
Float16(.sinh(Float(x)))
}

@_transparent
public static func tanh(_ x: Float16) -> Float16 {
Float16(.tanh(Float(x)))
}

@_transparent
public static func acosh(_ x: Float16) -> Float16 {
Float16(.acosh(Float(x)))
}

@_transparent
public static func asinh(_ x: Float16) -> Float16 {
Float16(.asinh(Float(x)))
}

@_transparent
public static func atanh(_ x: Float16) -> Float16 {
Float16(.atanh(Float(x)))
}

@_transparent
public static func exp(_ x: Float16) -> Float16 {
Float16(.exp(Float(x)))
}

@_transparent
public static func expMinusOne(_ x: Float16) -> Float16 {
Float16(.expMinusOne(Float(x)))
}

@_transparent
public static func log(_ x: Float16) -> Float16 {
Float16(.log(Float(x)))
}

@_transparent
public static func log(onePlus x: Float16) -> Float16 {
Float16(.log(onePlus: Float(x)))
}

@_transparent
public static func erf(_ x: Float16) -> Float16 {
Float16(.erf(Float(x)))
}

@_transparent
public static func erfc(_ x: Float16) -> Float16 {
Float16(.erfc(Float(x)))
}

@_transparent
public static func exp2(_ x: Float16) -> Float16 {
Float16(.exp2(Float(x)))
}

@_transparent
public static func exp10(_ x: Float16) -> Float16 {
Float16(.exp10(Float(x)))
}

@_transparent
public static func hypot(_ x: Float16, _ y: Float16) -> Float16 {
if x.isInfinite || y.isInfinite { return .infinity }
let xf = Float(x)
let yf = Float(y)
return Float16(.sqrt(xf*xf + yf*yf))
}

@_transparent
public static func gamma(_ x: Float16) -> Float16 {
Float16(.gamma(Float(x)))
}

@_transparent
public static func log2(_ x: Float16) -> Float16 {
Float16(.log2(Float(x)))
}

@_transparent
public static func log10(_ x: Float16) -> Float16 {
Float16(.log10(Float(x)))
}

@_transparent
public static func pow(_ x: Float16, _ y: Float16) -> Float16 {
Float16(.pow(Float(x), Float(y)))
}

@_transparent
public static func pow(_ x: Float16, _ n: Int) -> Float16 {
// Float16 is simpler than Float or Double, because the range of
// "interesting" exponents is pretty small; anything outside of
// -22707 ... 34061 simply overflows or underflows for every
// x that isn't zero or one. This whole range is representable
// as Float, so we can just use powf as long as we're a little
// bit (get it?) careful to preserve parity.
let clamped = min(max(n, -0x10000), 0x10000) | (n & 1)
return Float16(libm_powf(Float(x), Float(clamped)))
}

@_transparent
public static func root(_ x: Float16, _ n: Int) -> Float16 {
Float16(.root(Float(x), n))
}

@_transparent
public static func atan2(y: Float16, x: Float16) -> Float16 {
Float16(.atan2(y: Float(y), x: Float(x)))
}

#if !os(Windows)
@_transparent
public static func logGamma(_ x: Float16) -> Float16 {
Float16(.logGamma(Float(x)))
}
#endif
}
#endif
11 changes: 4 additions & 7 deletions Sources/_NumericsShims/include/_NumericsShims.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// This source file is part of the Swift Numerics open source project
//
// Copyright (c) 2019 Apple Inc. and the Swift Numerics project authors
// Copyright (c) 2019-2020 Apple Inc. and the Swift Numerics project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -383,11 +383,9 @@ HEADER_SHIM long double libm_lgammal(long double x, int *signp) {
#endif

// MARK: - shims to import C complex operations for timing purposes
// Clang doesn't provide complex arithmetic on Windows (because MSVC
// doesn't), so we can't define these there, or we'll get link errors.
#if !defined _WIN32
// Clang doesn't have support for complex arithmetic on Windows, so
// it doesn't make sense to benchmark against it (and these will
// fail to link if used there).

typedef struct { double real; double imag; } CComplex;

HEADER_SHIM CComplex libm_cdiv(CComplex z, CComplex w) {
Expand All @@ -403,5 +401,4 @@ HEADER_SHIM CComplex libm_cmul(CComplex z, CComplex w) {
double _Complex c = a*b;
return (CComplex){ __real__ c, __imag__ c };
}

#endif
#endif // !defined _WIN32
14 changes: 13 additions & 1 deletion Tests/ComplexTests/DifferentiableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//
//===----------------------------------------------------------------------===//

#if canImport(_Differentiation)
#if swift(>=5.3) && canImport(_Differentiation)

import XCTest
import ComplexModule
Expand All @@ -28,6 +28,18 @@ final class DifferentiableTests: XCTestCase {
Complex(5, 2))
}

func testInitializer() {
let φ1 = pullback(at: 4, -3) { r, i in Complex<Float>(r, i) }
let tan1 = φ1(Complex(-1, 2))
XCTAssertEqual(tan1.0, -1)
XCTAssertEqual(tan1.1, 2)

let φ2 = pullback(at: 4, -3) { r, i in Complex<Float>(r * r, i + i) }
let tan2 = φ2(Complex(-1, 1))
XCTAssertEqual(tan2.0, -8)
XCTAssertEqual(tan2.1, 2)
}

func testConjugate() {
let φ = pullback(at: Complex<Float>(20, -4)) { x in x.conjugate }
XCTAssertEqual(φ(Complex(1, 0)), Complex(1, 0))
Expand Down
40 changes: 40 additions & 0 deletions Tests/RealTests/IntegerExponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,36 @@ internal extension Real where Self: FixedWidthFloatingPoint {
}
}

#if swift(>=5.3)
@available(iOS 14.0, watchOS 14.0, tvOS 7.0, *)
@available(macOS, unavailable)
extension Float16 {
static func testIntegerExponent() {
testIntegerExponentCommon()
testIntegerExponentDoubleAndSmaller()
let u = Float16(1).nextUp
let d = Float16(1).nextDown
// Smallest exponents not exactly representable as Float16.
assertClose(-7.3890572722436554354625993393835304, Float16.pow(-u, 0x801))
assertClose(-0.3676100238077049750885141244927184, Float16.pow(-d, 0x801))
// Exponents close to overflow boundary.
assertClose( 65403.86633107, Float16.pow(-u, 11360))
assertClose(-65467.73729429, Float16.pow(-u, 11361))
assertClose( 65531.67063149, Float16.pow(-u, 11362))
assertClose( 65487.96799785, Float16.pow(-d, -22706))
assertClose(-65519.96016590, Float16.pow(-d, -22707))
assertClose( 65551.96796276, Float16.pow(-d, -22708))
// Exponents close to underflow boundary.
assertClose( 5.966876499900e-8, Float16.pow(-u, -17042))
assertClose(-5.961055156973e-8, Float16.pow(-u, -17043))
assertClose( 5.955239493405e-8, Float16.pow(-u, -17044))
assertClose( 5.964109628044e-8, Float16.pow(-d, 34060))
assertClose(-5.961197465140e-8, Float16.pow(-d, 34061))
assertClose( 5.958286724190e-8, Float16.pow(-d, 34062))
}
}
#endif

extension Float {
static func testIntegerExponent() {
testIntegerExponentCommon()
Expand Down Expand Up @@ -134,6 +164,16 @@ extension Double {
}

final class IntegerExponentTests: XCTestCase {

#if swift(>=5.3)
@available(iOS 14.0, watchOS 14.0, tvOS 7.0, *)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
func testFloat16() {
Float16.testIntegerExponent()
}
#endif

func testFloat() {
Float.testIntegerExponent()
}
Expand Down
7 changes: 7 additions & 0 deletions Tests/RealTests/RealTestSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ internal protocol FixedWidthFloatingPoint: BinaryFloatingPoint
where Exponent: FixedWidthInteger,
RawSignificand: FixedWidthInteger { }

#if swift(>=5.3)
@available(iOS 14.0, watchOS 14.0, tvOS 7.0, *)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
extension Float16: FixedWidthFloatingPoint { }
#endif

extension Float: FixedWidthFloatingPoint { }
extension Double: FixedWidthFloatingPoint { }
#if (arch(i386) || arch(x86_64)) && !os(Windows) && !os(Android)
Expand Down
9 changes: 9 additions & 0 deletions Tests/RealTests/RealTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ internal extension Real where Self: BinaryFloatingPoint {

final class ElementaryFunctionChecks: XCTestCase {

#if swift(>=5.3) && !os(macOS)
func testFloat16() {
if #available(iOS 14.0, watchOS 14.0, tvOS 7.0, *) {
stephentyrone marked this conversation as resolved.
Show resolved Hide resolved
Float16.elementaryFunctionChecks()
Float16.realFunctionChecks()
}
}
#endif

func testFloat() {
Float.elementaryFunctionChecks()
Float.realFunctionChecks()
Expand Down
20 changes: 9 additions & 11 deletions Tests/WindowsMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@ extension ArithmeticTests {
])
}

#if canImport(_Differentiation)
extension DifferentiableTests {
static var all = testCase([
("testComponentGetter", DifferentiableTests.testComponentGetter),
("testConjugate", DifferentiableTests.testConjugate),
("testArithmetics", DifferentiableTests.testArithmetics),
])
}
#endif

extension PropertyTests {
static var all = testCase([
("testProperties", PropertyTests.testProperties),
Expand All @@ -65,7 +55,15 @@ var testCases = [
PropertyTests.all,
]

#if canImport(_Differentiation)
#if swift(>=5.3) && canImport(_Differentiation)
extension DifferentiableTests {
static var all = testCase([
("testComponentGetter", DifferentiableTests.testComponentGetter),
("testConjugate", DifferentiableTests.testConjugate),
("testArithmetics", DifferentiableTests.testArithmetics),
])
}

testCases += [
DifferentiableTests.all
]
Expand Down