From 97852afaf5fa2e807e439733fe2813feeccb5ff4 Mon Sep 17 00:00:00 2001 From: "Steve (Numerics) Canon" Date: Fri, 19 Feb 2021 15:53:15 -0500 Subject: [PATCH] Adjust Float16 availability for Swift 5.4 toolchains. In older toolchains, Float16 is marked unavailable on all mac targets; starting with the 5.4 toolchain, it is available starting in macOS 11.0 when targeting Apple Silicon. --- Sources/RealModule/Float16+Real.swift | 171 +++++++++++++++++- Sources/_TestSupport/RealTestSupport.swift | 4 +- .../RealTests/ElementaryFunctionChecks.swift | 4 +- Tests/RealTests/IntegerExponentTests.swift | 10 +- Tests/WindowsMain.swift | 18 +- 5 files changed, 188 insertions(+), 19 deletions(-) diff --git a/Sources/RealModule/Float16+Real.swift b/Sources/RealModule/Float16+Real.swift index 2e30d0e8..c83f4947 100644 --- a/Sources/RealModule/Float16+Real.swift +++ b/Sources/RealModule/Float16+Real.swift @@ -9,9 +9,177 @@ // //===----------------------------------------------------------------------===// -#if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) import _NumericsShims +// When building with a Swift 5.4 or later toolchain, Float16 is available on +// non-x86 macOS from 11.0 onward. +#if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) + +@available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) +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 +} + +// When building with older Swift toolchains for macOS, Float16 is not +// available. We will drop support for these older toolchains at some +// future point and remove this duplication. +#elseif swift(>=5.3) && !(os(macOS) || targetEnvironment(macCatalyst)) + @available(iOS 14.0, tvOS 14.0, watchOS 7.0, *) extension Float16: Real { @_transparent @@ -171,4 +339,5 @@ extension Float16: Real { } #endif } + #endif diff --git a/Sources/_TestSupport/RealTestSupport.swift b/Sources/_TestSupport/RealTestSupport.swift index 5c2634f5..ccabeaeb 100644 --- a/Sources/_TestSupport/RealTestSupport.swift +++ b/Sources/_TestSupport/RealTestSupport.swift @@ -15,8 +15,8 @@ public protocol FixedWidthFloatingPoint: BinaryFloatingPoint where Exponent: FixedWidthInteger, RawSignificand: FixedWidthInteger { } -#if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) -@available(iOS 14.0, watchOS 14.0, tvOS 7.0, *) +#if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) +@available(macOS 11.0, iOS 14.0, watchOS 14.0, tvOS 7.0, *) extension Float16: FixedWidthFloatingPoint { } #endif diff --git a/Tests/RealTests/ElementaryFunctionChecks.swift b/Tests/RealTests/ElementaryFunctionChecks.swift index a1c0ea8a..7dfd7caf 100644 --- a/Tests/RealTests/ElementaryFunctionChecks.swift +++ b/Tests/RealTests/ElementaryFunctionChecks.swift @@ -130,9 +130,9 @@ internal extension Real where Self: BinaryFloatingPoint { final class ElementaryFunctionChecks: XCTestCase { - #if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) + #if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) func testFloat16() { - if #available(iOS 14.0, watchOS 14.0, tvOS 7.0, *) { + if #available(macOS 11.0, iOS 14.0, watchOS 14.0, tvOS 7.0, *) { Float16.elementaryFunctionChecks() Float16.realFunctionChecks() } diff --git a/Tests/RealTests/IntegerExponentTests.swift b/Tests/RealTests/IntegerExponentTests.swift index 1c235076..2d4a3a7d 100644 --- a/Tests/RealTests/IntegerExponentTests.swift +++ b/Tests/RealTests/IntegerExponentTests.swift @@ -77,8 +77,8 @@ internal extension Real where Self: FixedWidthFloatingPoint { } } -#if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) -@available(iOS 14.0, watchOS 14.0, tvOS 7.0, *) +#if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) +@available(macOS 11.0, iOS 14.0, watchOS 14.0, tvOS 7.0, *) extension Float16 { static func testIntegerExponent() { testIntegerExponentCommon() @@ -174,9 +174,11 @@ extension Double { final class IntegerExponentTests: XCTestCase { - #if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) + #if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) func testFloat16() { - Float16.testIntegerExponent() + if #available(macOS 11.0, iOS 14.0, watchOS 14.0, tvOS 7.0, *) { + Float16.testIntegerExponent() + } } #endif diff --git a/Tests/WindowsMain.swift b/Tests/WindowsMain.swift index d7431c4f..c0e60027 100644 --- a/Tests/WindowsMain.swift +++ b/Tests/WindowsMain.swift @@ -32,7 +32,7 @@ extension RealTests.ApproximateEqualityTests { ]) } -#if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) +#if swift(>=5.4) && !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) extension ElementaryFunctionChecks { static var all = testCase([ ("testFloat16", ElementaryFunctionChecks.testFloat16), @@ -40,16 +40,7 @@ extension ElementaryFunctionChecks { ("testDouble", ElementaryFunctionChecks.testDouble), ]) } -#else -extension ElementaryFunctionChecks { - static var all = testCase([ - ("testFloat", ElementaryFunctionChecks.testFloat), - ("testDouble", ElementaryFunctionChecks.testDouble), - ]) -} -#endif -#if swift(>=5.3) && !(os(macOS) || os(iOS) && targetEnvironment(macCatalyst)) extension IntegerExponentTests { static var all = testCase([ ("testFloat16", IntegerExponentTests.testFloat16), @@ -58,6 +49,13 @@ extension IntegerExponentTests { ]) } #else +extension ElementaryFunctionChecks { + static var all = testCase([ + ("testFloat", ElementaryFunctionChecks.testFloat), + ("testDouble", ElementaryFunctionChecks.testDouble), + ]) +} + extension IntegerExponentTests { static var all = testCase([ ("testFloat", IntegerExponentTests.testFloat),