Skip to content

Mathable for 5.1 branch #25302

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
68 changes: 68 additions & 0 deletions stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,66 @@ public func %=(lhs: inout CGFloat, rhs: CGFloat) {
fatalError("%= is not available.")
}

//===----------------------------------------------------------------------===//
// Real conformance
//===----------------------------------------------------------------------===//

%from SwiftMathFunctions import *

extension CGFloat: ElementaryFunctions {
% 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 {
guard x >= 0 else { return .nan }
return CGFloat(NativeType.pow(x.native, y.native))
}

@_alwaysEmitIntoClient
public static func pow(_ x: CGFloat, _ n: Int) -> CGFloat {
// TODO: this implementation isn't quite right for n so large that
// the conversion to `CGFloat` 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 CGFloat(NativeType.pow(x.native, n))
}

@_alwaysEmitIntoClient
public static func root(_ x: CGFloat, _ n: Int) -> CGFloat {
guard x >= 0 || n % 2 != 0 else { return .nan }
// TODO: this implementation isn't quite right for n so large that
// the conversion to `CGFloat` rounds.
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))
}

@_alwaysEmitIntoClient
public static func logGamma(_ x: CGFloat) -> CGFloat {
return CGFloat(NativeType.logGamma(x.native))
}

@_alwaysEmitIntoClient
public static func signGamma(_ x: CGFloat) -> FloatingPointSign {
if x >= 0 { return .plus }
let trunc = x.rounded(.towardZero)
if x == trunc { return .plus }
let halfTrunc = trunc/2
if halfTrunc == halfTrunc.rounded(.towardZero) { return .minus }
return .plus
}
}

//===----------------------------------------------------------------------===//
// tgmath
//===----------------------------------------------------------------------===//
Expand All @@ -529,10 +589,18 @@ BinaryFunctions = [
}%

%for ufunc in UnaryFunctions:
% if ufunc in ['rint','nearbyint']:
@available(swift, deprecated: 5.1, message: "Swift does not model dynamic rounding modes, use x.rounded(.toNearestOrEven) instead.")
@_transparent
public func ${ufunc}(_ x: CGFloat) -> CGFloat {
return x.rounded(.toNearestOrEven)
}
% else:
@_transparent
public func ${ufunc}(_ x: CGFloat) -> CGFloat {
return CGFloat(${ufunc}(x.native))
}
% end

%end

Expand Down
158 changes: 92 additions & 66 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,7 +14,7 @@ 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: "abs")
public func fabs<T: FloatingPoint>(_ x: T) -> T {
return x.magnitude
}
Expand Down Expand Up @@ -112,7 +112,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 +155,15 @@ 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'
]

# 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,60 +197,117 @@ 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
@_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)
}

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

#if (arch(i386) || arch(x86_64)) && !os(Windows)
@_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)
}

@_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

% for T, CT, f, bfunc in TypedBinaryFunctions():
% for T, CT, f in OverlayFloatTypes():
% if T == 'Float80':
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% end
@_transparent
public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
return ${T}(${bfunc}${f}(${CT}(lhs), ${CT}(rhs)))
public func atan2(_ y: ${T}, _ x: ${T}) -> ${T} {
return ${T}.atan2(y: y, x: x)
}

@_transparent
public func hypot(_ x: ${T}, _ y: ${T}) -> ${T} {
return ${T}.hypot(x, y)
}

@_transparent
public func pow(_ x: ${T}, _ y: ${T}) -> ${T} {
return ${T}.pow(x, y)
}

@_transparent
public func copysign(_ x: ${T}, _ y: ${T}) -> ${T} {
return ${T}(signOf: y, magnitudeOf: x)
}

@_transparent
public func fdim(_ x: ${T}, _ y: ${T}) -> ${T} {
return ${T}(fdim${f}(${CT}(x), ${CT}(y)))
}

@available(swift, deprecated: 5.1, message: "Use the .nextUp and .nextDown properties.")
@_transparent
public func nextafter(_ x: ${T}, _ y: ${T}) -> ${T} {
return y > x ? x.nextUp : (y < x ? x.nextDown : y)
}

@available(swift, deprecated: 5.1, message: "Use ${T}.minimum( ) or Swift.min( )")
@_transparent
public func fmin(_ x: ${T}, _ y: ${T}) -> ${T} {
return .minimum(x, y)
}

@available(swift, deprecated: 5.1, message: "Use ${T}.maximum( ) or Swift.max( )")
@_transparent
public func fmax(_ x: ${T}, _ y: ${T}) -> ${T} {
return .maximum(x, y)
}
% if T == 'Float80':
#endif
Expand All @@ -297,9 +325,7 @@ public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
% end
@_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 +352,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