diff --git a/stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb b/stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb index 0ad49ea7b11e0..73685e224cde6 100644 --- a/stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb +++ b/stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb @@ -513,18 +513,111 @@ public func %=(lhs: inout CGFloat, rhs: CGFloat) { // tgmath //===----------------------------------------------------------------------===// +%from SwiftMathFunctions import * +extension CGFloat: Real { +% for func in ElementaryFunctions + RealFunctions: + + @_alwaysEmitIntoClient + public static func ${func.decl("CGFloat")} { + return CGFloat(NativeType.${func.swiftName}(${func.params("", ".native")})) + } +% end + + @_alwaysEmitIntoClient + public static func pow(_ x: CGFloat, _ y: CGFloat) -> CGFloat { + return CGFloat(NativeType.pow(x.native, y.native)) + } + + @_alwaysEmitIntoClient + public static func pow(_ x: CGFloat, _ n: Int) -> CGFloat { + return CGFloat(NativeType.pow(x.native, n)) + } + + @_alwaysEmitIntoClient + public static func root(_ x: CGFloat, _ n: Int) -> CGFloat { + return CGFloat(NativeType.root(x.native, n)) + } + + @_alwaysEmitIntoClient + public static func atan2(y: CGFloat, x: CGFloat) -> CGFloat { + return CGFloat(NativeType.atan2(y: y.native, x: x.native)) + } + +#if !os(Windows) + @_alwaysEmitIntoClient + public static func logGamma(_ x: CGFloat) -> CGFloat { + return CGFloat(NativeType.logGamma(x.native)) + } +#endif +} + +@available(swift, deprecated: 5.1, message: "Use `root(x, 3)`.") +@_transparent +public func cbrt(_ x: CGFloat) -> CGFloat { + return CGFloat.root(x, 3) +} + +@available(swift, deprecated: 5.1, message: "Use CGFloat.minimum( ) or Swift.min( )") +@_transparent +public func fmin(_ x: CGFloat, _ y: CGFloat) -> CGFloat { + return .minimum(x, y) +} + +@available(swift, deprecated: 5.1, message: "Use CGFloat.maximum( ) or Swift.max( )") +@_transparent +public func fmax(_ x: CGFloat, _ y: CGFloat) -> CGFloat { + return .maximum(x, y) +} + +#if !os(Windows) +@available(swift, deprecated: 5.1, message: "Use (logGamma(x), signGamma(x)).") +@_transparent +public func lgamma(_ x: CGFloat) -> (CGFloat, Int) { + return (CGFloat.logGamma(x), CGFloat.signGamma(x) == .plus ? 1 : -1) +} +#endif + +@available(swift, deprecated: 5.1, message: "Use `x.exponent` or `floor(log2(x))`.") +@_transparent +public func logb(_ x: CGFloat) -> CGFloat { + return CGFloat.log2(x).rounded(.down) +} + +@available(swift, deprecated: 5.1, message: "Swift does not model dynamic rounding modes, use x.rounded(.toNearestOrEven).") +@_transparent +public func nearbyint(_ x: CGFloat) -> CGFloat { + return x.rounded(.toNearestOrEven) +} + +@available(swift, deprecated: 5.1, message: "Use the .nextUp or .nextDown property.") +@_transparent +public func nextafter(_ x: CGFloat, _ y: CGFloat) -> CGFloat { + return y > x ? x.nextUp : (y < x ? x.nextDown : y) +} + +@available(swift, deprecated: 5.1, message: "Swift does not model dynamic rounding modes, use x.rounded(.toNearestOrEven).") +@_transparent +public func rint(_ x: CGFloat) -> CGFloat { + return x.rounded(.toNearestOrEven) +} + +@available(swift, deprecated: 5.1, message: "Use `gamma(x)`.") +@_transparent +public func tgamma(_ x: CGFloat) -> CGFloat { + return CGFloat.gamma(x) +} + %{ UnaryFunctions = [ 'acos', 'asin', 'atan', 'cos', 'sin', 'tan', 'acosh', 'asinh', 'atanh', 'cosh', 'sinh', 'tanh', 'exp', 'exp2', 'expm1', - 'log', 'log10', 'log1p', 'log2', 'logb', - 'cbrt', 'erf', 'erfc', 'tgamma', - 'nearbyint', 'rint' + 'log', 'log10', 'log1p', 'log2', + 'erf', 'erfc', ] BinaryFunctions = [ - 'atan2', 'hypot', 'pow', 'copysign', 'nextafter', 'fdim', 'fmax', 'fmin' + 'atan2', 'hypot', 'pow', 'copysign', 'fdim' ] }% @@ -571,18 +664,12 @@ public func ldexp(_ x: CGFloat, _ n: Int) -> CGFloat { return CGFloat(ldexp(x.native, n)) } -@available(swift, deprecated: 4.2, message: "use the exponent property.") +@available(swift, deprecated: 4.2, obsoleted: 5.1, message: "use the exponent property.") @_transparent public func ilogb(_ x: CGFloat) -> Int { return Int(x.exponent) } -@_transparent -public func lgamma(_ x: CGFloat) -> (CGFloat, Int) { - let (value, sign) = lgamma(x.native) - return (CGFloat(value), sign) -} - @_transparent public func remquo(_ x: CGFloat, _ y: CGFloat) -> (CGFloat, Int) { let (rem, quo) = remquo(x.native, y.native) diff --git a/stdlib/public/Platform/tgmath.swift.gyb b/stdlib/public/Platform/tgmath.swift.gyb index 4f3f279de4f13..dc22df68f1ac6 100644 --- a/stdlib/public/Platform/tgmath.swift.gyb +++ b/stdlib/public/Platform/tgmath.swift.gyb @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -14,11 +14,12 @@ import SwiftShims // Generic functions implementable directly on FloatingPoint. @_transparent -@available(swift, deprecated: 4.2, renamed: "abs") +@available(swift, deprecated: 4.2, obsoleted: 5.1, renamed: "Swift.abs") public func fabs(_ x: T) -> T { return x.magnitude } +@available(swift, obsoleted: 5.1, message: "Use Swift.sqrt(x) or x.squareRoot().") @_transparent public func sqrt(_ x: T) -> T { return x.squareRoot() @@ -112,7 +113,7 @@ public func isnan(_ value: T) -> Bool { fatalError() } @available(*, unavailable, message: "use the sign property.") public func signbit(_ value: T) -> Int { fatalError() } -@available(swift, deprecated: 4.2, message: "use the exponent property.") +@available(swift, deprecated: 4.2, obsoleted: 5.1, message: "use the exponent property.") public func ilogb(_ x: T) -> Int { return Int(x.exponent) } @@ -155,44 +156,20 @@ UnaryFunctions = [ 'acos', 'asin', 'atan', 'tan', 'acosh', 'asinh', 'atanh', 'cosh', 'sinh', 'tanh', 'expm1', - 'log1p', 'logb', - 'cbrt', 'erf', 'erfc', 'tgamma', + 'log1p', + 'erf', 'erfc', ] # These functions have a corresponding LLVM intrinsic -# We call this intrinsic via the Builtin method so keep this list in -# sync with core/BuiltinMath.swift.gyb UnaryIntrinsicFunctions = [ - 'cos', 'sin', - 'exp', 'exp2', - 'log', 'log10', 'log2', - 'nearbyint', 'rint', + 'cos', 'sin', 'exp', 'exp2', 'log', 'log10', 'log2', 'nearbyint', 'rint' ] # (T, T) -> T BinaryFunctions = [ - 'atan2', 'hypot', 'pow', - 'copysign', 'nextafter', 'fdim', 'fmax', 'fmin' + 'atan2', 'hypot', 'fdim', 'copysign' ] -# These functions have special implementations. -OtherFunctions = [ - 'scalbn', 'lgamma', 'remquo', 'nan', 'jn', 'yn' -] - -# These functions are imported correctly as-is. -OkayFunctions = ['j0', 'j1', 'y0', 'y1'] - -# These functions are not supported for various reasons. -UnhandledFunctions = [ - 'math_errhandling', 'scalbln', - 'lrint', 'lround', 'llrint', 'llround', 'nexttoward', - 'isgreater', 'isgreaterequal', 'isless', 'islessequal', - 'islessgreater', 'isunordered', '__exp10', - '__sincos', '__cospi', '__sinpi', '__tanpi', '__sincospi' -] - - def AllFloatTypes(): for bits in allFloatBits: yield floatName(bits), cFloatName(bits), cFuncSuffix(bits) @@ -226,50 +203,74 @@ def TypedBinaryFunctions(): % end @_transparent public func ${ufunc}(_ x: ${T}) -> ${T} { - return ${T}(${ufunc}${f}(${CT}(x))) + return ${T}.${ufunc}(x) } % if T == 'Float80': #endif % end % end +@available(swift, deprecated: 5.1, message: "Use `root(x, 3)`.") +@_transparent +public func cbrt(_ x: Float) -> Float { + return Float.root(x, 3) +} + +@available(swift, deprecated: 5.1, message: "Use `x.exponent` or `floor(log2(x))`.") +@_transparent +public func logb(_ x: Float) -> Float { + return Float.log2(x).rounded(.down) +} + +@available(swift, deprecated: 5.1, message: "Use `gamma(x)`.") +@_transparent +public func tgamma(_ x: Float) -> Float { + return Float.gamma(x) +} + +#if (arch(i386) || arch(x86_64)) && !os(Windows) +@available(swift, deprecated: 5.1, message: "Use `root(x, 3)`.") +@_transparent +public func cbrt(_ x: Float80) -> Float80 { + return Float80.root(x, 3) +} + +@available(swift, deprecated: 5.1, message: "Use `x.exponent` or `floor(log2(x))`.") +@_transparent +public func logb(_ x: Float80) -> Float80 { + return Float80.log2(x).rounded(.down) +} + +@available(swift, deprecated: 5.1, message: "Use `gamma(x)`.") +@_transparent +public func tgamma(_ x: Float80) -> Float80 { + return Float80.gamma(x) +} +#endif -#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) // Unary intrinsic functions // Note these have a corresponding LLVM intrinsic % for T, ufunc in TypedUnaryIntrinsicFunctions(): % if T == 'Float80': #if (arch(i386) || arch(x86_64)) && !os(Windows) % end +% if ufunc[-3:] != 'int': @_transparent public func ${ufunc}(_ x: ${T}) -> ${T} { - return _${ufunc}(x) + return ${T}.${ufunc}(x) } -% if T == 'Float80': -#endif -% end - -% end -#else -// FIXME: As of now, we cannot declare 64-bit (Double/CDouble) overlays here. -// Since CoreFoundation also exports libc functions, they will conflict with -// Swift overlays when building Foundation. For now, just like normal -// UnaryFunctions, we define overlays only for OverlayFloatTypes. -% for ufunc in UnaryIntrinsicFunctions: -% for T, CT, f in OverlayFloatTypes(): -% if T == 'Float80': -#if (arch(i386) || arch(x86_64)) && !os(Windows) -% end +% else: +@available(swift, deprecated: 5.1, message: "Swift does not model dynamic rounding modes, use x.rounded(.toNearestOrEven) instead.") @_transparent public func ${ufunc}(_ x: ${T}) -> ${T} { - return ${T}(${ufunc}${f}(${CT}(x))) + return x.rounded(.toNearestOrEven) } -% if T == 'Float80': +% end +% if T == 'Float80': #endif -% end % end + % end -#endif // Binary functions @@ -287,6 +288,54 @@ public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} { % end +@_transparent +public func pow(_ x: Float, _ y: Float) -> Float { + return Float.pow(x, y) +} + +@available(swift, deprecated: 5.1, message: "Use the .nextUp and .nextDown properties.") +@_transparent +public func nextafter(_ x: Float, _ y: Float) -> Float { + return y > x ? x.nextUp : (y < x ? x.nextDown : y) +} + +@available(swift, deprecated: 5.1, message: "Use Float.minimum( ) or Swift.min( )") +@_transparent +public func fmin(_ x: Float, _ y: Float) -> Float { + return .minimum(x, y) +} + +@available(swift, deprecated: 5.1, message: "Use Float.maximum( ) or Swift.max( )") +@_transparent +public func fmax(_ x: Float, _ y: Float) -> Float { + return .maximum(x, y) +} + +#if (arch(i386) || arch(x86_64)) && !os(Windows) +@_transparent +public func pow(_ x: Float80, _ y: Float80) -> Float80 { + return Float80.pow(x, y) +} + +@available(swift, deprecated: 5.1, message: "Use the .nextUp and .nextDown properties.") +@_transparent +public func nextafter(_ x: Float80, _ y: Float80) -> Float80 { + return y > x ? x.nextUp : (y < x ? x.nextDown : y) +} + +@available(swift, deprecated: 5.1, message: "Use Float80.minimum( ) or Swift.min( )") +@_transparent +public func fmin(_ x: Float80, _ y: Float80) -> Float80 { + return Float80.minimum(x, y) +} + +@available(swift, deprecated: 5.1, message: "Use Float80.maximum( ) or Swift.max( )") +@_transparent +public func fmax(_ x: Float80, _ y: Float80) -> Float80 { + return Float80.maximum(x, y) +} +#endif + % # This is AllFloatTypes not OverlayFloatTypes because of the tuple return. % for T, CT, f in AllFloatTypes(): % if T == 'Float80': @@ -295,11 +344,10 @@ public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} { // lgamma not available on Windows, apparently? #if !os(Windows) % end +@available(swift, deprecated: 5.1, message: "Use (logGamma(x), signGamma(x)).") @_transparent public func lgamma(_ x: ${T}) -> (${T}, Int) { - var sign = Int32(0) - let value = lgamma${f}_r(${CT}(x), &sign) - return (${T}(value), Int(sign)) + return (${T}.logGamma(x), ${T}.signGamma(x) == .plus ? 1 : -1) } #endif @@ -326,8 +374,8 @@ public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) { % if T == 'Float80': #if (arch(i386) || arch(x86_64)) && !os(Windows) % end -@available(swift, deprecated: 4.2, message: - "use ${T}(nan: ${T}.RawSignificand) instead.") +@available(swift, deprecated: 4.2, obsoleted: 5.1, message: + "use ${T}(nan: ${T}.RawSignificand).") @_transparent public func nan(_ tag: String) -> ${T} { return ${T}(nan${f}(tag)) diff --git a/stdlib/public/SwiftShims/LibcShims.h b/stdlib/public/SwiftShims/LibcShims.h index ff99bc796ccd6..e495d56501c91 100644 --- a/stdlib/public/SwiftShims/LibcShims.h +++ b/stdlib/public/SwiftShims/LibcShims.h @@ -127,45 +127,337 @@ static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) { // Math library functions static inline SWIFT_ALWAYS_INLINE -float _stdlib_remainderf(float _self, float _other) { - return __builtin_remainderf(_self, _other); +float _swift_stdlib_remainderf(float _self, float other) { + return __builtin_remainderf(_self, other); } static inline SWIFT_ALWAYS_INLINE -float _stdlib_squareRootf(float _self) { +float _swift_stdlib_squareRootf(float _self) { return __builtin_sqrtf(_self); } + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_tanf(float x) { + return __builtin_tanf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_acosf(float x) { + return __builtin_acosf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_asinf(float x) { + return __builtin_asinf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_atanf(float x) { + return __builtin_atanf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_atan2f(float y, float x) { + return __builtin_atan2f(y, x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_coshf(float x) { + return __builtin_coshf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_sinhf(float x) { + return __builtin_sinhf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_tanhf(float x) { + return __builtin_tanhf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_acoshf(float x) { + return __builtin_acoshf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_asinhf(float x) { + return __builtin_asinhf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_atanhf(float x) { + return __builtin_atanhf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_exp10f(float x) { +#if defined __APPLE__ + extern float __exp10f(float); + return __exp10f(x); +#else + return __builtin_powf(10, x); +#endif +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_expm1f(float x) { + return __builtin_expm1f(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_log1pf(float x) { + return __builtin_log1pf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_hypotf(float x, float y) { + return __builtin_hypotf(x, y); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_erff(float x) { + return __builtin_erff(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_erfcf(float x) { + return __builtin_erfcf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_tgammaf(float x) { + return __builtin_tgammaf(x); +} + +static inline SWIFT_ALWAYS_INLINE +float _swift_stdlib_lgammaf(float x) { + extern float lgammaf_r(float x, int *psigngam); + int dontCare; + return lgammaf_r(x, &dontCare); +} static inline SWIFT_ALWAYS_INLINE -double _stdlib_remainder(double _self, double _other) { - return __builtin_remainder(_self, _other); +double _swift_stdlib_remainder(double _self, double other) { + return __builtin_remainder(_self, other); } static inline SWIFT_ALWAYS_INLINE -double _stdlib_squareRoot(double _self) { +double _swift_stdlib_squareRoot(double _self) { return __builtin_sqrt(_self); } -#if !defined _WIN32 && (defined __i386__ || defined __x86_64__) static inline SWIFT_ALWAYS_INLINE -long double _stdlib_remainderl(long double _self, long double _other) { - return __builtin_remainderl(_self, _other); +double _swift_stdlib_tan(double x) { + return __builtin_tan(x); } static inline SWIFT_ALWAYS_INLINE -long double _stdlib_squareRootl(long double _self) { - return __builtin_sqrtl(_self); +double _swift_stdlib_acos(double x) { + return __builtin_acos(x); } + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_asin(double x) { + return __builtin_asin(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_atan(double x) { + return __builtin_atan(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_atan2(double y, double x) { + return __builtin_atan2(y, x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_cosh(double x) { + return __builtin_cosh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_sinh(double x) { + return __builtin_sinh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_tanh(double x) { + return __builtin_tanh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_acosh(double x) { + return __builtin_acosh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_asinh(double x) { + return __builtin_asinh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_atanh(double x) { + return __builtin_atanh(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_exp10(double x) { +#if defined __APPLE__ + extern double __exp10(double); + return __exp10(x); +#else + return __builtin_pow(10, x); #endif +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_expm1(double x) { + return __builtin_expm1(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_log1p(double x) { + return __builtin_log1p(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_hypot(double x, double y) { + return __builtin_hypot(x, y); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_erf(double x) { + return __builtin_erf(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_erfc(double x) { + return __builtin_erfc(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_tgamma(double x) { + return __builtin_tgamma(x); +} + +static inline SWIFT_ALWAYS_INLINE +double _swift_stdlib_lgamma(double x) { + extern double lgamma_r(double x, int *psigngam); + int dontCare; + return lgamma_r(x, &dontCare); +} -// Apple's math.h does not declare lgamma_r() etc by default, but they're -// unconditionally exported by libsystem_m.dylib in all OS versions that -// support Swift development; we simply need to provide declarations here. -#if defined(__APPLE__) -float lgammaf_r(float x, int *psigngam); -double lgamma_r(double x, int *psigngam); -long double lgammal_r(long double x, int *psigngam); -#endif // defined(__APPLE__) +#if !defined _WIN32 && (defined __i386__ || defined __x86_64__) +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_remainderl(long double _self, long double other) { + return __builtin_remainderl(_self, other); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_squareRootl(long double _self) { + return __builtin_sqrtl(_self); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_tanl(long double x) { + return __builtin_tanl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_acosl(long double x) { + return __builtin_acosl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_asinl(long double x) { + return __builtin_asinl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_atanl(long double x) { + return __builtin_atanl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_atan2l(long double y, long double x) { + return __builtin_atan2l(y, x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_coshl(long double x) { + return __builtin_coshl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_sinhl(long double x) { + return __builtin_sinhl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_tanhl(long double x) { + return __builtin_tanhl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_acoshl(long double x) { + return __builtin_acoshl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_asinhl(long double x) { + return __builtin_asinhl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_atanhl(long double x) { + return __builtin_atanhl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_exp10l(long double x) { + return __builtin_powl(10, x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_expm1l(long double x) { + return __builtin_expm1l(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_log1pl(long double x) { + return __builtin_log1pl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_hypotl(long double x, long double y) { + return __builtin_hypotl(x, y); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_erfl(long double x) { + return __builtin_erfl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_erfcl(long double x) { + return __builtin_erfcl(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_tgammal(long double x) { + return __builtin_tgammal(x); +} + +static inline SWIFT_ALWAYS_INLINE +long double _swift_stdlib_lgammal(long double x) { + extern long double lgammal_r(long double x, int *psigngam); + int dontCare; + return lgammal_r(x, &dontCare); +} +#endif #ifdef __cplusplus }} // extern "C", namespace swift diff --git a/stdlib/public/core/BuiltinMath.swift.gyb b/stdlib/public/core/BuiltinMath.swift.gyb deleted file mode 100644 index 69db331f4cb53..0000000000000 --- a/stdlib/public/core/BuiltinMath.swift.gyb +++ /dev/null @@ -1,78 +0,0 @@ -//===--- BuiltinMath.swift.gyb --------------------------------*- swift -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -%{ - -# Don't need 64-bit (Double/CDouble) overlays. The ordinary C imports work fine. -overlayFloatBits = [32, 80] -allFloatBits = [32, 64, 80] - -def floatName(bits): - if bits == 32: - return 'Float' - if bits == 64: - return 'Double' - if bits == 80: - return 'Float80' - -def cFloatName(bits): - if bits == 32: - return 'CFloat' - if bits == 64: - return 'CDouble' - if bits == 80: - return 'CLongDouble' - -def cFuncSuffix(bits): - if bits == 32: - return 'f' - if bits == 64: - return '' - if bits == 80: - return 'l' - -# Each of the following lists is ordered to match math.h - -# These functions have a corresponding LLVM intrinsic -# Note, keep this up to date with Darwin/tgmath.swift.gyb -UnaryIntrinsicFunctions = [ - 'cos', 'sin', - 'exp', 'exp2', - 'log', 'log10', 'log2', - 'nearbyint', 'rint', -] - -def TypedUnaryIntrinsicFunctions(): - for ufunc in UnaryIntrinsicFunctions: - for bits in allFloatBits: - yield floatName(bits), cFloatName(bits), bits, ufunc - -}% - -// Unary intrinsic functions -// Note these have a corresponding LLVM intrinsic -% for T, CT, bits, ufunc in TypedUnaryIntrinsicFunctions(): -% if bits == 80: -#if !os(Windows) && (arch(i386) || arch(x86_64)) -% end -@_transparent -public func _${ufunc}(_ x: ${T}) -> ${T} { - return ${T}(Builtin.int_${ufunc}_FPIEEE${bits}(x._value)) -} -% if bits == 80: -#endif -% end -% end - -// ${'Local Variables'}: -// eval: (read-only-mode 1) -// End: diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index f7874df471288..849a883920f0d 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -184,7 +184,6 @@ set(SWIFTLIB_ESSENTIAL set(SWIFTLIB_ESSENTIAL_GYB_SOURCES AtomicInt.swift.gyb - BuiltinMath.swift.gyb Codable.swift.gyb FixedArray.swift.gyb FloatingPointParsing.swift.gyb @@ -218,10 +217,11 @@ set(SWIFTLIB_SOURCES ) set(SWIFTLIB_GYB_SOURCES - ${SWIFTLIB_ESSENTIAL_GYB_SOURCES} - ExistentialCollection.swift.gyb - SIMDVectorTypes.swift.gyb - Tuple.swift.gyb + ${SWIFTLIB_ESSENTIAL_GYB_SOURCES} + ExistentialCollection.swift.gyb + MathFunctions.swift.gyb + SIMDVectorTypes.swift.gyb + Tuple.swift.gyb ) set(GROUP_INFO_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/GroupInfo.json) set(swift_core_link_flags "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}") diff --git a/stdlib/public/core/FloatingPoint.swift b/stdlib/public/core/FloatingPoint.swift index 6933ca3ce82f4..ccb4fdd788c52 100644 --- a/stdlib/public/core/FloatingPoint.swift +++ b/stdlib/public/core/FloatingPoint.swift @@ -1898,10 +1898,6 @@ extension FloatingPoint { /// other is NaN. @inlinable public static func minimum(_ x: Self, _ y: Self) -> Self { - if x.isSignalingNaN || y.isSignalingNaN { - // Produce a quiet NaN matching platform arithmetic behavior. - return x + y - } if x <= y || y.isNaN { return x } return y } @@ -1935,10 +1931,6 @@ extension FloatingPoint { /// other is NaN. @inlinable public static func maximum(_ x: Self, _ y: Self) -> Self { - if x.isSignalingNaN || y.isSignalingNaN { - // Produce a quiet NaN matching platform arithmetic behavior. - return x + y - } if x > y || y.isNaN { return x } return y } @@ -1974,10 +1966,6 @@ extension FloatingPoint { /// a number if the other is NaN. @inlinable public static func minimumMagnitude(_ x: Self, _ y: Self) -> Self { - if x.isSignalingNaN || y.isSignalingNaN { - // Produce a quiet NaN matching platform arithmetic behavior. - return x + y - } if x.magnitude <= y.magnitude || y.isNaN { return x } return y } @@ -2013,10 +2001,6 @@ extension FloatingPoint { /// a number if the other is NaN. @inlinable public static func maximumMagnitude(_ x: Self, _ y: Self) -> Self { - if x.isSignalingNaN || y.isSignalingNaN { - // Produce a quiet NaN matching platform arithmetic behavior. - return x + y - } if x.magnitude > y.magnitude || y.isNaN { return x } return y } diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index 6c7c9b4f6919a..074d88c5798e0 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -1115,7 +1115,7 @@ extension ${Self}: BinaryFloatingPoint { @inlinable // FIXME(inline-always) @inline(__always) public mutating func formRemainder(dividingBy other: ${Self}) { - self = _stdlib_remainder${cFuncSuffix}(self, other) + self = _swift_stdlib_remainder${cFuncSuffix}(self, other) } /// Replaces this value with the remainder of itself divided by the given @@ -1157,7 +1157,7 @@ extension ${Self}: BinaryFloatingPoint { /// value. @_transparent public mutating func formSquareRoot( ) { - self = _stdlib_squareRoot${cFuncSuffix}(self) + self = _swift_stdlib_squareRoot${cFuncSuffix}(self) } /// Adds the product of the two given values to this value in place, computed diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json index 06ba858a9f666..aa250689af7ad 100644 --- a/stdlib/public/core/GroupInfo.json +++ b/stdlib/public/core/GroupInfo.json @@ -158,7 +158,7 @@ ], "Math": [ "SetAlgebra.swift", - "BuiltinMath.swift", + "MathFunctions.swift", { "Integers": [ "Integers.swift", diff --git a/stdlib/public/core/MathFunctions.swift.gyb b/stdlib/public/core/MathFunctions.swift.gyb new file mode 100644 index 0000000000000..78ca7245b7324 --- /dev/null +++ b/stdlib/public/core/MathFunctions.swift.gyb @@ -0,0 +1,329 @@ +//===--- MathFunctions.swift ----------------------------------*- swift -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2019 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftShims +%from SwiftMathFunctions import * +%from SwiftFloatingPointTypes import all_floating_point_types + +/// A type that has elementary functions available. +/// +/// An ["elementary function"][elfn] is a function built up from powers, roots, +/// exponentials, logarithms, trigonometric functions (sin, cos, tan) and +/// their inverses, and the hyperbolic functions (sinh, cosh, tanh) and their +/// inverses. +/// +/// Conformance to this protocol means that all of these building blocks are +/// available as static functions on the type. +/// +/// ```swift +/// let x: Float = 1 +/// let y = Float.sin(x) // 0.84147096 +/// ``` +/// +/// All of these are made available as free functions by importing the Math +/// module: +/// +/// ```swift +/// import Math +/// let y = sin(x) // 0.84147096 +/// ``` +/// +/// Additional operations, such as `atan2(y:x:)`, `hypot(_:_:)` and some +/// special functions, are provided on the Real protocol, which refines both +/// ElementaryFunctions and FloatingPoint. +/// +/// [elfn]: http://en.wikipedia.org/wiki/Elementary_function +public protocol ElementaryFunctions { + +%for func in ElementaryFunctions: + + ${func.comment} + static func ${func.decl("Self")} +%end + + /// `exp(y log(x))` computed without loss of intermediate precision. + /// + /// For real types, if `x` is negative the result is NaN, even if `y` has + /// an integral value. For complex types, there is a branch cut on the + /// negative real axis. + static func pow(_ x: Self, _ y: Self) -> Self + + /// `x` raised to the `n`th power. + static func pow(_ x: Self, _ n: Int) -> Self + + /// The `n`th root of `x`. + /// + /// For real types, if `x` is negative and `n` is even, the result is NaN. + /// For complex types, there is a branch cut along the negative real axis. + static func root(_ x: Self, _ n: Int) -> Self +} + +/// A type that models the real numbers. +public protocol Real: ElementaryFunctions, FloatingPoint { +%for func in RealFunctions: + + ${func.comment} + static func ${func.decl("Self")} +%end + + /// `atan(y/x)` with quadrant fixup. + /// + /// There is an infinite family of angles whose tangent is `y/x`. `atan2` + /// selects the representative that is the angle between the vector `(x, y)` + /// and the real axis in the range [-π, π]. + static func atan2(y: Self, x: Self) -> Self + +#if !os(Windows) + // lgamma is not available on Windows. + // TODO: provide an implementation of lgamma with the stdlib to support + // Windows so we can vend a uniform interface. + + /// `log(gamma(x))` computed without undue overflow. + /// + /// `log(abs(gamma(x)))` is returned. To get the sign of `gamma(x)` cheaply, + /// use `signGamma(x)`. + static func logGamma(_ x: Self) -> Self +#endif +} + +extension Real { +#if !os(Windows) + // lgamma is not available on Windows; no lgamma means signGamma + // is basically useless, so don't bother exposing it. + + /// The sign of `gamma(x)`. + /// + /// This function is typically used in conjunction with `logGamma(x)`, which + /// computes `log(abs(gamma(x)))`, to recover the sign information that is + /// lost to the absolute value. + /// + /// `gamma(x)` has a simple pole at each non-positive integer and an + /// essential singularity at infinity; we arbitrarily choose to return + /// `.plus` for the sign in those cases. For all other values, `signGamma(x)` + /// is `.plus` if `x >= 0` or `trunc(x)` is odd, and `.minus` otherwise. + @_alwaysEmitIntoClient + public static func signGamma(_ x: Self) -> FloatingPointSign { + if x >= 0 { return .plus } + let trunc = x.rounded(.towardZero) + // Treat poles as gamma(x) == +inf. This is arbitrary, but we need to + // pick one sign or the other. + if x == trunc { return .plus } + // Result is .minus if trunc is even, .plus otherwise. To figure out if + // trunc is even or odd, check if trunc/2 is an integer. + let halfTrunc = trunc/2 + if halfTrunc == halfTrunc.rounded(.towardZero) { return .minus } + return .plus + } +#endif +} + +%for type in all_floating_point_types(): +% if type.bits == 80: +#if (arch(i386) || arch(x86_64)) && !os(Windows) +% end +% Self = type.stdlib_name +extension ${Self}: Real { +% for func in ElementaryFunctions + RealFunctions: + + @_alwaysEmitIntoClient + public static func ${func.decl(Self)} { + return ${func.impl(type)} + } +% end + + @_alwaysEmitIntoClient + public static func pow(_ x: ${Self}, _ y: ${Self}) -> ${Self} { + guard x >= 0 else { return .nan } + return ${Self}(Builtin.int_pow_FPIEEE${type.bits}(x._value, y._value)) + } + + @_alwaysEmitIntoClient + public static func pow(_ x: ${Self}, _ n: Int) -> ${Self} { + // TODO: this implementation isn't quite right for n so large that + // the conversion to `${Self}` rounds. We could also consider using + // a multiply-chain implementation for small `n`; this would be faster + // for static `n`, but less accurate on platforms with a good `pow` + // implementation. + return ${Self}(Builtin.int_pow_FPIEEE${type.bits}(x._value, ${Self}(n)._value)) + } + + @_alwaysEmitIntoClient + public static func root(_ x: ${Self}, _ n: Int) -> ${Self} { + guard x >= 0 || n % 2 != 0 else { return .nan } + // TODO: this implementation isn't quite right for n so large that + // the conversion to `${Self}` rounds. + return ${Self}(signOf: x, magnitudeOf: pow(x, 1/${Self}(n))) + } + + @_alwaysEmitIntoClient + public static func atan2(y: ${Self}, x: ${Self}) -> ${Self} { + return _swift_stdlib_atan2${type.cFuncSuffix}(y, x) + } + +#if !os(Windows) + @_alwaysEmitIntoClient + public static func logGamma(_ x: ${Self}) -> ${Self} { + return _swift_stdlib_lgamma${type.cFuncSuffix}(x) + } +#endif +} +% if type.bits == 80: +#endif +% end +%end + +// MARK: - Free functions defined on ElementaryFunctions: +%from SwiftMathFunctions import * +%for func in ElementaryFunctions: + +% if func.name == 'sqrt': +// sqrt requires availability because it was previous generic on FloatingPoint. +@available(swift, introduced: 5.1) +% end +@_alwaysEmitIntoClient +public func ${func.free_decl()} { + return T.${func.swiftName}(${func.params()}) +} + +@_alwaysEmitIntoClient +public func ${func.free_decl("T: SIMD, T.Scalar: ElementaryFunctions")} { + var r = T() + for i in r.indices { r[i] = T.Scalar.${func.swiftName}(${func.params("","[i]")}) } + return r +} +%end + +@_alwaysEmitIntoClient +public func pow(_ x: T, _ y: T) -> T where T: ElementaryFunctions { + return T.pow(x, y) +} + +@_alwaysEmitIntoClient +public func pow(_ x: T, _ y: T) -> T where T: SIMD, T.Scalar: ElementaryFunctions { + var r = T() + for i in r.indices { r[i] = T.Scalar.pow(x[i], y[i]) } + return r +} + +@_alwaysEmitIntoClient +public func pow(_ x: T, _ n: Int) -> T where T: ElementaryFunctions { + return T.pow(x, n) +} + +@_alwaysEmitIntoClient +public func pow(_ x: T, _ n: Int) -> T where T: SIMD, T.Scalar: ElementaryFunctions { + var r = T() + for i in r.indices { r[i] = T.Scalar.pow(x[i], n) } + return r +} + +@_alwaysEmitIntoClient +public func root(_ x: T, _ n: Int) -> T where T: ElementaryFunctions { + return T.root(x, n) +} + +@_alwaysEmitIntoClient +public func root(_ x: T, _ n: Int) -> T where T: SIMD, T.Scalar: ElementaryFunctions { + var r = T() + for i in r.indices { r[i] = T.Scalar.root(x[i], n) } + return r +} + +// MARK: - Free functions defined on Real: +%for func in RealFunctions: + +@_alwaysEmitIntoClient +public func ${func.free_decl("T: Real")} { + return T.${func.swiftName}(${func.params()}) +} + +@_alwaysEmitIntoClient +public func ${func.free_decl("T: SIMD, T.Scalar: Real")} { + var r = T() + for i in r.indices { r[i] = T.Scalar.${func.swiftName}(${func.params("","[i]")}) } + return r +} +%end + +@_alwaysEmitIntoClient +public func atan2(y: T, x: T) -> T where T: Real { + return T.atan2(y: y, x: x) +} + +@_alwaysEmitIntoClient +public func atan2(y: T, x: T) -> T where T: SIMD, T.Scalar: Real { + var r = T() + for i in r.indices { r[i] = T.Scalar.atan2(y: y[i], x: x[i]) } + return r +} + +// logGamma is not available on Windows. +// TODO: logGamma, signGamma for SIMD types. +#if !os(Windows) +@_alwaysEmitIntoClient +public func logGamma(_ x: T) -> T where T: Real { + return T.logGamma(x) +} + +@_alwaysEmitIntoClient +public func signGamma(_ x: T) -> FloatingPointSign where T: Real { + return T.signGamma(x) +} +#endif + +// MARK: - Free functions defined on FloatingPoint: +% for (func,dir) in [("ceil", ".up"), ("floor", ".down"), ("round", ""), ("trunc", ".towardZero")]: + +@_alwaysEmitIntoClient +public func ${func}(_ x: T) -> T where T: FloatingPoint { + return x.rounded(${dir}) +} + +@_alwaysEmitIntoClient +public func ${func}(_ x: T) -> T where T: SIMD, T.Scalar: FloatingPoint { + return x.rounded(${dir}) +} +%end + +@_alwaysEmitIntoClient +public func fma(_ x: T, _ y: T, _ z: T) -> T where T: FloatingPoint { + return z.addingProduct(x, y) +} + +@_alwaysEmitIntoClient +public func fma(_ x: T, _ y: T, _ z: T) -> T where T: SIMD, T.Scalar: FloatingPoint { + return z.addingProduct(x, y) +} + +@_alwaysEmitIntoClient +public func remainder(_ dividend: T, _ divisor: T) -> T where T: FloatingPoint { + return dividend.remainder(dividingBy: divisor) +} + +@_alwaysEmitIntoClient +public func remainder(_ dividend: T, _ divisor: T) -> T where T: SIMD, T.Scalar: FloatingPoint { + var r = T() + for i in r.indices { r[i] = dividend[i].remainder(dividingBy: divisor[i]) } + return r +} + +@_alwaysEmitIntoClient +public func copysign(_ magnitude: T, _ sign: T) -> T where T: FloatingPoint { + return T(signOf: sign, magnitudeOf: magnitude) +} + +@_alwaysEmitIntoClient +public func copysign(_ magnitude: T, _ sign: T) -> T where T: SIMD, T.Scalar: FloatingPoint { + var r = T() + for i in r.indices { r[i] = copysign(magnitude[i], sign[i]) } + return r +} diff --git a/stdlib/public/core/SIMDVector.swift b/stdlib/public/core/SIMDVector.swift index dce9b3355b674..5bb63081c06bb 100644 --- a/stdlib/public/core/SIMDVector.swift +++ b/stdlib/public/core/SIMDVector.swift @@ -652,7 +652,7 @@ extension SIMD where Scalar : FloatingPoint { } @_transparent - public func rounded(_ rule: FloatingPointRoundingRule) -> Self { + public func rounded(_ rule: FloatingPointRoundingRule = .toNearestOrEven) -> Self { var result = Self() for i in result.indices { result[i] = self[i].rounded(rule) } return result diff --git a/test/IDE/complete_repl_identifier_prefix_1.swift b/test/IDE/complete_repl_identifier_prefix_1.swift index 6d2bb2527bdd9..99119f30619a8 100644 --- a/test/IDE/complete_repl_identifier_prefix_1.swift +++ b/test/IDE/complete_repl_identifier_prefix_1.swift @@ -2,6 +2,8 @@ // CHECK: Begin completions // CHECK-NEXT: {{^}}true: Bool{{$}} +// CHECK-NEXT: {{^}}trunc(x: FloatingPoint) -> FloatingPoint +// CHECK-NEXT: {{^}}trunc(x: SIMD) -> SIMD // CHECK-NEXT: End completions tru diff --git a/test/IRGen/builtin_math.swift b/test/IRGen/builtin_math.swift index 93a7938f69389..b1d4afca51c21 100644 --- a/test/IRGen/builtin_math.swift +++ b/test/IRGen/builtin_math.swift @@ -13,13 +13,7 @@ // Make sure we use an intrinsic for functions such as exp. // CHECK-LABEL: define {{.*}}test1 -// CHECK-ios: call float @llvm.exp.f32 -// CHECK-macosx: call float @llvm.exp.f32 -// CHECK-tvos: call float @llvm.exp.f32 -// CHECK-watchos: call float @llvm.exp.f32 -// CHECK-darwin: call float @llvm.exp.f32 -// CHECK-linux-gnu: call float @expf -// CHECK-windows: call float @expf +// CHECK: call float @llvm.exp.f32 public func test1(f : Float) -> Float { return exp(f) @@ -29,7 +23,7 @@ public func test1(f : Float) -> Float { // CHECK: call double @llvm.exp.f64 public func test2(f : Double) -> Double { - return _exp(f) + return exp(f) } // CHECK-LABEL: define {{.*}}test3 diff --git a/test/Parse/recovery.swift b/test/Parse/recovery.swift index 1712d39a7adf2..ca41457e249b2 100644 --- a/test/Parse/recovery.swift +++ b/test/Parse/recovery.swift @@ -33,8 +33,7 @@ func useContainer() -> () { func exists() -> Bool { return true } } -// expected-note @+2 {{did you mean 'test'?}} -// expected-note @+1 {{'test' declared here}} +// expected-note @+1 {{did you mean 'test'?}} func test(a: BadAttributes) -> () { _ = a.exists() // no-warning } @@ -619,7 +618,7 @@ func foo1(bar!=baz) {} // expected-note {{did you mean 'foo1'?}} func foo2(bar! = baz) {}// expected-note {{did you mean 'foo2'?}} // rdar://19605567 -// expected-error@+1{{use of unresolved identifier 'esp'; did you mean 'test'?}} +// expected-error@+1{{use of unresolved identifier 'esp'; did you mean 'exp'?}} switch esp { case let (jeb): // expected-error@+5{{top-level statement cannot begin with a closure expression}} diff --git a/test/SourceKit/Sema/sema_symlink.swift.response b/test/SourceKit/Sema/sema_symlink.swift.response index 87aebf74e748e..782720eee456c 100644 --- a/test/SourceKit/Sema/sema_symlink.swift.response +++ b/test/SourceKit/Sema/sema_symlink.swift.response @@ -12,7 +12,7 @@ key.column: 16, key.filepath: real.swift, key.severity: source.diagnostic.severity.error, - key.description: "use of unresolved identifier 'goo'; did you mean 'Bool'?", + key.description: "use of unresolved identifier 'goo'", key.diagnostic_stage: source.diagnostic.stage.swift.sema, key.ranges: [ { @@ -20,20 +20,27 @@ key.length: 3 } ], - key.fixits: [ - { - key.offset: 15, - key.length: 3, - key.sourcetext: "Bool" - } - ], key.diagnostics: [ { key.line: 1, key.column: 16, key.filepath: real.swift, key.severity: source.diagnostic.severity.note, - key.description: "'Bool' declared here (Swift.Bool)" + key.description: "did you mean 'root'? (Swift.root)" + }, + { + key.line: 1, + key.column: 16, + key.filepath: real.swift, + key.severity: source.diagnostic.severity.note, + key.description: "did you mean 'root'? (Swift.root)" + }, + { + key.line: 1, + key.column: 16, + key.filepath: real.swift, + key.severity: source.diagnostic.severity.note, + key.description: "did you mean 'Bool'? (Swift.Bool)" } ] } diff --git a/test/api-digester/Outputs/stability-stdlib-abi.swift.expected b/test/api-digester/Outputs/stability-stdlib-abi.swift.expected index 8b137891791fe..345e89537256c 100644 --- a/test/api-digester/Outputs/stability-stdlib-abi.swift.expected +++ b/test/api-digester/Outputs/stability-stdlib-abi.swift.expected @@ -1 +1,51 @@ - +Func _cos(_:) has been removed +Func _cos(_:) has been renamed to Func cos(_:) +Func _cos(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _cos(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _cos(_:) has parameter 0 type change from Double to τ_0_0 +Func _cos(_:) has parameter 0 type change from Float to τ_0_0 +Func _cos(_:) has return type change from Double to τ_0_0 +Func _cos(_:) has return type change from Float to τ_0_0 +Func _exp(_:) has been removed +Func _exp(_:) has been renamed to Func exp(_:) +Func _exp(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _exp(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _exp(_:) has parameter 0 type change from Double to τ_0_0 +Func _exp(_:) has parameter 0 type change from Float to τ_0_0 +Func _exp(_:) has return type change from Double to τ_0_0 +Func _exp(_:) has return type change from Float to τ_0_0 +Func _exp2(_:) has been removed +Func _exp2(_:) has been renamed to Func exp2(_:) +Func _exp2(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _exp2(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _exp2(_:) has parameter 0 type change from Double to τ_0_0 +Func _exp2(_:) has parameter 0 type change from Float to τ_0_0 +Func _exp2(_:) has return type change from Double to τ_0_0 +Func _exp2(_:) has return type change from Float to τ_0_0 +Func _log(_:) has been removed +Func _log10(_:) has been removed +Func _log10(_:) has been renamed to Func log10(_:) +Func _log10(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _log10(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _log10(_:) has parameter 0 type change from Double to τ_0_0 +Func _log10(_:) has parameter 0 type change from Float to τ_0_0 +Func _log10(_:) has return type change from Double to τ_0_0 +Func _log10(_:) has return type change from Float to τ_0_0 +Func _log2(_:) has been removed +Func _log2(_:) has been renamed to Func log2(_:) +Func _log2(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _log2(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _log2(_:) has parameter 0 type change from Double to τ_0_0 +Func _log2(_:) has parameter 0 type change from Float to τ_0_0 +Func _log2(_:) has return type change from Double to τ_0_0 +Func _log2(_:) has return type change from Float to τ_0_0 +Func _nearbyint(_:) has been removed +Func _rint(_:) has been removed +Func _sin(_:) has been removed +Func _sin(_:) has been renamed to Func sin(_:) +Func _sin(_:) has generic signature change from to <τ_0_0 where τ_0_0 : ElementaryFunctions> +Func _sin(_:) has generic signature change from to <τ_0_0 where τ_0_0 : SIMD, τ_0_0.Scalar : ElementaryFunctions> +Func _sin(_:) has parameter 0 type change from Double to τ_0_0 +Func _sin(_:) has parameter 0 type change from Float to τ_0_0 +Func _sin(_:) has return type change from Double to τ_0_0 +Func _sin(_:) has return type change from Float to τ_0_0 diff --git a/test/stdlib/MathFunctions.swift.gyb b/test/stdlib/MathFunctions.swift.gyb new file mode 100644 index 0000000000000..03d6b8eff91bf --- /dev/null +++ b/test/stdlib/MathFunctions.swift.gyb @@ -0,0 +1,168 @@ +//===--- Math.swift.gyb ---------------------------------------*- swift -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// -*- swift -*- +// RUN: %empty-directory(%t) +// RUN: %gyb %s -o %t/tgmath.swift +// RUN: %line-directive %t/tgmath.swift -- %target-build-swift %t/tgmath.swift -o %t/a.out +// RUN: %target-codesign %t/a.out +// RUN: %line-directive %t/tgmath.swift -- %target-run %t/a.out +// REQUIRES: executable_test + +#if (arch(i386) || arch(x86_64)) && !os(Windows) + typealias TestLiteralType = Float80 +#else + typealias TestLiteralType = Double +#endif + +import StdlibUnittest + +let MathTests = TestSuite("Math") + +func expectEqualWithTolerance(_ expected: TestLiteralType, _ actual: T, + ulps allowed: T = 3, + file: String = #file, line: UInt = #line) + where T: BinaryFloatingPoint { + if actual == T(expected) || actual.isNaN && expected.isNaN { + return + } + // Compute error in ulp, compare to tolerance. + let absoluteError = T(abs(TestLiteralType(actual) - expected)) + let ulpError = absoluteError / T(expected).ulp + expectTrue(ulpError <= allowed, + "\(actual) != \(expected) as \(T.self)" + + "\n \(ulpError)-ulp error exceeds \(allowed)-ulp tolerance.", + file: file, line: line) +} + +%from SwiftMathFunctions import * + +internal extension ElementaryFunctions where Self: BinaryFloatingPoint { + static func elementaryFunctionTests() { + /* Default tolerance is 3 ulps unless specified otherwise. It's OK to relax + * this as needed for new platforms, as these tests are *not* intended to + * validate the math library--they are only intended to check that the + * Swift bindings are calling the right functions in the math library. */ + expectEqualWithTolerance(1.1863995522992575361931268186727044683, Self.acos(0.375)) + expectEqualWithTolerance(0.3843967744956390830381948729670469737, Self.asin(0.375)) + expectEqualWithTolerance(0.3587706702705722203959200639264604997, Self.atan(0.375)) + expectEqualWithTolerance(0.9305076219123142911494767922295555080, Self.cos(0.375)) + expectEqualWithTolerance(0.3662725290860475613729093517162641571, Self.sin(0.375)) + expectEqualWithTolerance(0.3936265759256327582294137871012180981, Self.tan(0.375)) + expectEqualWithTolerance(0.4949329230945269058895630995767185785, Self.acosh(1.125)) + expectEqualWithTolerance(0.9670596312833237113713762009167286709, Self.asinh(1.125)) + expectEqualWithTolerance(0.7331685343967135223291211023213964500, Self.atanh(0.625)) + expectEqualWithTolerance(1.0711403467045867672994980155670160493, Self.cosh(0.375)) + expectEqualWithTolerance(0.3838510679136145687542956764205024589, Self.sinh(0.375)) + expectEqualWithTolerance(0.3583573983507859463193602315531580424, Self.tanh(0.375)) + expectEqualWithTolerance(1.4549914146182013360537936919875185083, Self.exp(0.375)) + expectEqualWithTolerance(1.2968395546510096659337541177924511598, Self.exp2(0.375)) + expectEqualWithTolerance(2.3713737056616552616517527574788898386, Self.exp10(0.375)) + expectEqualWithTolerance(0.4549914146182013360537936919875185083, Self.expm1(0.375)) + expectEqualWithTolerance(-0.980829253011726236856451127452003999, Self.log(0.375)) + expectEqualWithTolerance(-1.415037499278843818546261056052183491, Self.log2(0.375)) + expectEqualWithTolerance(0.3184537311185346158102472135905995955, Self.log1p(0.375)) + expectEqualWithTolerance(-0.425968732272281148346188780918363771, Self.log10(0.375)) + expectEqualWithTolerance(0.7211247851537041911608191553900547941, Self.root(0.375, 3)) + expectEqualWithTolerance(0.6123724356957945245493210186764728479, Self.sqrt(0.375)) + expectEqualWithTolerance(0.54171335479545025876069682133938570, Self.pow(0.375, 0.625)) + expectEqualWithTolerance(-0.052734375, Self.pow(-0.375, 3)) + + expectEqual(Self.acos(0.375), acos(0.375)) + expectEqual(Self.asin(0.375), asin(0.375)) + expectEqual(Self.atan(0.375), atan(0.375)) + expectEqual(Self.cos(0.375), cos(0.375)) + expectEqual(Self.sin(0.375), sin(0.375)) + expectEqual(Self.tan(0.375), tan(0.375)) + expectEqual(Self.acosh(1.125), acosh(1.125)) + expectEqual(Self.asinh(1.125), asinh(1.125)) + expectEqual(Self.atanh(0.625), atanh(0.625)) + expectEqual(Self.cosh(0.375), cosh(0.375)) + expectEqual(Self.sinh(0.375), sinh(0.375)) + expectEqual(Self.tanh(0.375), tanh(0.375)) + expectEqual(Self.exp(0.375), exp(0.375)) + expectEqual(Self.exp2(0.375), exp2(0.375)) + expectEqual(Self.exp10(0.375), exp10(0.375)) + expectEqual(Self.expm1(0.375), expm1(0.375)) + expectEqual(Self.log(0.375), log(0.375)) + expectEqual(Self.log2(0.375), log2(0.375)) + expectEqual(Self.log1p(0.375), log1p(0.375)) + expectEqual(Self.log10(0.375), log10(0.375)) + expectEqual(Self.sqrt(0.375), sqrt(0.375)) + expectEqual(Self.pow(0.375, 0.625), pow(0.375, 0.625)) + expectEqual(Self.root(0.375, 3), root(0.375, 3)) + expectEqual(Self.pow(-0.375, 3), pow(-0.375, 3)) + } +} + +internal extension Real where Self: BinaryFloatingPoint { + static func realFunctionTests() { + expectEqualWithTolerance(0.54041950027058415544357836460859991, Self.atan2(y: 0.375, x: 0.625)) + expectEqualWithTolerance(0.72886898685566255885926910969319788, Self.hypot(0.375, 0.625)) + expectEqualWithTolerance(0.4041169094348222983238250859191217675, Self.erf(0.375)) + expectEqualWithTolerance(0.5958830905651777016761749140808782324, Self.erfc(0.375)) + expectEqualWithTolerance(2.3704361844166009086464735041766525098, Self.gamma(0.375)) +#if !os(Windows) + expectEqualWithTolerance( -0.11775527074107877445136203331798850, Self.logGamma(1.375), ulps: 16) + expectEqual(.plus, Self.signGamma(1.375)) + expectEqual(.minus, Self.signGamma(-2.375)) +#endif + + expectEqual(Self.atan2(y: 0.375, x: 0.625), atan2(y: 0.375, x: 0.625)) + expectEqual(Self.hypot(0.375, 0.625), hypot(0.375, 0.625)) + expectEqual(Self.erf(0.375), erf(0.375)) + expectEqual(Self.erfc(0.375), erfc(0.375)) + expectEqual(Self.gamma(0.375), gamma(0.375)) +#if !os(Windows) + expectEqual(Self.logGamma(1.375), logGamma(1.375)) + expectEqual(Self.signGamma(1.375), signGamma(1.375)) + expectEqual(Self.signGamma(-2.375), signGamma(-2.375)) +#endif + } +} + +internal extension BinaryFloatingPoint { + static func floatingPointFunctionTests() { + expectEqual(1 as Self, ceil(0.375)) + expectEqual(0 as Self, floor(0.375)) + expectEqual(0 as Self, Swift.round(0.375)) + expectEqual(0 as Self, trunc(0.375)) + expectEqual(0 as Self, ceil(-0.625)) + expectEqual(-1 as Self, floor(-0.625)) + expectEqual(-1 as Self, Swift.round(-0.625)) + expectEqual(0 as Self, trunc(-0.625)) + expectEqual(1 as Self, ceil(0.5)) + expectEqual(0 as Self, floor(0.5)) + expectEqual(1 as Self, Swift.round(0.5)) + expectEqual(0 as Self, trunc(0.5)) + } +} + +%for T in ['Float', 'Double', 'CGFloat', 'Float80']: +% if T == 'Float80': +#if (arch(i386) || arch(x86_64)) && !os(Windows) +% elif T == 'CGFloat': +#if canImport(CoreGraphics) + import CoreGraphics +% end + +MathTests.test("${T}") { + ${T}.elementaryFunctionTests() + ${T}.realFunctionTests() + ${T}.floatingPointFunctionTests() +} + +% if T in ['CGFloat', 'Float80']: +#endif +% end +%end + +runAllTests() diff --git a/test/stdlib/tgmath.swift.gyb b/test/stdlib/tgmath.swift.gyb index c3382face8e38..91748cbe6bf99 100644 --- a/test/stdlib/tgmath.swift.gyb +++ b/test/stdlib/tgmath.swift.gyb @@ -18,7 +18,7 @@ // REQUIRES: executable_test #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) - import Darwin.C.tgmath + import Darwin #elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku) import Glibc #elseif os(Windows) @@ -61,7 +61,7 @@ unary = [ 'cosh', 'sinh', 'tanh', 'exp', 'exp2', 'expm1', 'log', 'log2', 'log1p', 'log10', 'logb', - 'fabs', 'cbrt', 'sqrt', + 'fabs', 'cbrt', 'erf', 'erfc', 'tgamma', 'ceil', 'floor', 'nearbyint', 'rint', 'trunc', @@ -118,7 +118,6 @@ internal extension TGMath { expectEqual(-2, Self._logb(0.375)) expectEqual(0.375, Self._fabs(-0.375)) expectEqualWithTolerance(0.7211247851537041911608191553900547941, Self._cbrt(0.375)) - expectEqualWithTolerance(0.6123724356957945245493210186764728479, Self._sqrt(0.375)) expectEqualWithTolerance(0.4041169094348222983238250859191217675, Self._erf(0.375)) expectEqualWithTolerance(0.5958830905651777016761749140808782324, Self._erfc(0.375)) expectEqualWithTolerance(2.3704361844166009086464735041766525098, Self._tgamma(0.375)) @@ -181,21 +180,49 @@ internal extension TGMath { % end extension ${T}: TGMath { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +% Module = 'CoreGraphics' if T == 'CGFloat' else 'Darwin' % for f in unary: - static func _${f}(_ x: ${T}) -> ${T} { return ${f}(x) } + static func _${f}(_ x: ${T}) -> ${T} { return ${Module}.${f}(x) } % end %for f in binary: - static func _${f}(_ x: ${T}, _ y: ${T}) -> ${T} { return ${f}(x, y) } + static func _${f}(_ x: ${T}, _ y: ${T}) -> ${T} { return ${Module}.${f}(x, y) } %end - static func _remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) { return remquo(x, y) } - static func _fma(_ x: ${T}, _ y: ${T}, _ z: ${T}) -> ${T} { return fma(x, y, z) } -#if !os(Windows) - static func _lgamma(_ x: ${T}) -> (${T}, Int) { return lgamma(x) } + static func _remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) { return ${Module}.remquo(x, y) } + static func _fma(_ x: ${T}, _ y: ${T}, _ z: ${T}) -> ${T} { return ${Module}.fma(x, y, z) } + static func _lgamma(_ x: ${T}) -> (${T}, Int) { return ${Module}.lgamma(x) } + static func _modf(_ x: ${T}) -> (${T}, ${T}) { return ${Module}.modf(x) } + static func _scalbn(_ x: ${T}, _ n: Int) -> ${T} { return ${Module}.scalbn(x, n) } + static func _frexp(_ x: ${T}) -> (${T}, Int) { return ${Module}.frexp(x) } + static func _ilogb(_ x: ${T}) -> Int { return ${Module}.ilogb(x) } +#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku) +% for f in unary: + static func _${f}(_ x: ${T}) -> ${T} { return Glibc.${f}(x) } +% end +%for f in binary: + static func _${f}(_ x: ${T}, _ y: ${T}) -> ${T} { return Glibc.${f}(x, y) } +%end + static func _remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) { return Glibc.remquo(x, y) } + static func _fma(_ x: ${T}, _ y: ${T}, _ z: ${T}) -> ${T} { return Glibc.fma(x, y, z) } + static func _lgamma(_ x: ${T}) -> (${T}, Int) { return Glibc.lgamma(x) } + static func _modf(_ x: ${T}) -> (${T}, ${T}) { return Glibc.modf(x) } + static func _scalbn(_ x: ${T}, _ n: Int) -> ${T} { return Glibc.scalbn(x, n) } + static func _frexp(_ x: ${T}) -> (${T}, Int) { return Glibc.frexp(x) } + static func _ilogb(_ x: ${T}) -> Int { return Glibc.ilogb(x) } +#elseif os(Windows) +% for f in unary: + static func _${f}(_ x: ${T}) -> ${T} { return MSVCRT.${f}(x) } +% end +%for f in binary: + static func _${f}(_ x: ${T}, _ y: ${T}) -> ${T} { return MSVCRT.${f}(x, y) } +%end + static func _remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) { return MSVCRT.remquo(x, y) } + static func _fma(_ x: ${T}, _ y: ${T}, _ z: ${T}) -> ${T} { return MSVCRT.fma(x, y, z) } + static func _modf(_ x: ${T}) -> (${T}, ${T}) { return MSVCRT.modf(x) } + static func _scalbn(_ x: ${T}, _ n: Int) -> ${T} { return MSVCRT.scalbn(x, n) } + static func _frexp(_ x: ${T}) -> (${T}, Int) { return MSVCRT.frexp(x) } + static func _ilogb(_ x: ${T}) -> Int { return MSVCRT.ilogb(x) } #endif - static func _modf(_ x: ${T}) -> (${T}, ${T}) { return modf(x) } - static func _scalbn(_ x: ${T}, _ n: Int) -> ${T} { return scalbn(x, n) } - static func _frexp(_ x: ${T}) -> (${T}, Int) { return frexp(x) } - static func _ilogb(_ x: ${T}) -> Int { return ilogb(x) } } MathTests.test("${T}") { diff --git a/utils/SwiftMathFunctions.py b/utils/SwiftMathFunctions.py new file mode 100644 index 0000000000000..c1b82b22e9c6f --- /dev/null +++ b/utils/SwiftMathFunctions.py @@ -0,0 +1,74 @@ +class SwiftMathFunction(object): + def __init__(self, name, kind=None, swiftName=None, args="x", comment=None, + platforms=None): + self.name = name + self.swiftName = swiftName if swiftName is not None else name + self.kind = kind if kind is not None else "library" + self.args = args + if comment is not None: + self.comment = comment + else: + self.comment = "/// The " + str(self.swiftName) + " function." + self.platforms = platforms + + def params(self, prefix="", suffix=""): + return ", ".join(map(lambda a: prefix + a + suffix, self.args)) + + def decl(self, type): + return self.swiftName + "(" + self.params("_ ", ": " + type) + \ + ") -> " + type + + def free_decl(self, constraint="T: ElementaryFunctions"): + return self.swiftName + "(" + self.params("_ ", ": T") + \ + ") -> T where " + constraint + + def impl(self, type): + if self.kind == "intrinsic": + builtin = "Builtin.int_" + self.name + "_FPIEEE" + str(type.bits) + return type.stdlib_name + "(" + builtin + "(" + \ + self.params("", "._value") + "))" + return "_swift_stdlib_" + self.name + type.cFuncSuffix + "(" + \ + self.params() + ")" + + +ElementaryFunctions = [ + SwiftMathFunction(name="sqrt", kind="intrinsic", + comment="/// The square root of `x`."), + SwiftMathFunction(name="cos", kind="intrinsic", + comment="/// The cosine of `x`."), + SwiftMathFunction(name="sin", kind="intrinsic", + comment="/// The sine of `x`."), + SwiftMathFunction(name="tan", + comment="/// The tangent of `x`."), + SwiftMathFunction(name="acos"), + SwiftMathFunction(name="asin"), + SwiftMathFunction(name="atan"), + SwiftMathFunction(name="cosh"), + SwiftMathFunction(name="sinh"), + SwiftMathFunction(name="tanh"), + SwiftMathFunction(name="acosh"), + SwiftMathFunction(name="asinh"), + SwiftMathFunction(name="atanh"), + SwiftMathFunction(name="exp", kind="intrinsic"), + SwiftMathFunction(name="exp2", kind="intrinsic"), + SwiftMathFunction(name="exp10"), + SwiftMathFunction(name="expm1"), + SwiftMathFunction(name="log", kind="intrinsic"), + SwiftMathFunction(name="log2", kind="intrinsic"), + SwiftMathFunction(name="log10", kind="intrinsic"), + SwiftMathFunction(name="log1p"), + # SwiftMathFunction(name="pow", kind="intrinsic", args="xy"), Handled + # separately for edge cases. + # SwiftMathFunction(name="root", args="xn"), Handled separately for + # implementation. +] + +RealFunctions = [ + # SwiftMathFunction(name="atan2"), Handled separately for explicit + # argument labels. + SwiftMathFunction(name="erf"), + SwiftMathFunction(name="erfc"), + SwiftMathFunction(name="hypot", args="xy"), + SwiftMathFunction(name="tgamma", swiftName="gamma"), + # SwiftMathFunction(name="lgamma"), Handled separately for sign result. +]