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

Math functions for Swift #23140

Merged
merged 11 commits into from
Apr 3, 2019
109 changes: 98 additions & 11 deletions stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
]
}%

Expand Down Expand Up @@ -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)
Expand Down
164 changes: 106 additions & 58 deletions stdlib/public/Platform/tgmath.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<T: FloatingPoint>(_ x: T) -> T {
return x.magnitude
}

@available(swift, obsoleted: 5.1, message: "Use Swift.sqrt(x) or x.squareRoot().")
@_transparent
public func sqrt<T: FloatingPoint>(_ x: T) -> T {
return x.squareRoot()
Expand Down Expand Up @@ -112,7 +113,7 @@ public func isnan<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
@available(*, unavailable, message: "use the sign property.")
public func signbit<T: FloatingPoint>(_ 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<T: BinaryFloatingPoint>(_ x: T) -> Int {
return Int(x.exponent)
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand All @@ -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':
Expand All @@ -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

Expand All @@ -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))
Expand Down
Loading