Skip to content

Commit 57a4553

Browse files
SE-0246: Protocols and static functions (#23824)
This implements the protocols and static functions proposed in SE-0246, plus some initial test coverage. It also has some rough accompanying cleanup of tgmath. It does not include the globals (on scalars or SIMD types) nor does it deprecate much in tgmath.h.
1 parent 1ed77dc commit 57a4553

14 files changed

+896
-206
lines changed

stdlib/public/Darwin/CoreGraphics/CGFloat.swift.gyb

+52
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,58 @@ public func %=(lhs: inout CGFloat, rhs: CGFloat) {
509509
fatalError("%= is not available.")
510510
}
511511

512+
//===----------------------------------------------------------------------===//
513+
// Real conformance
514+
//===----------------------------------------------------------------------===//
515+
516+
%from SwiftMathFunctions import *
517+
518+
extension CGFloat: Real {
519+
% for func in ElementaryFunctions + RealFunctions:
520+
521+
@_alwaysEmitIntoClient
522+
public static func ${func.decl('CGFloat')} {
523+
return CGFloat(NativeType.${func.swiftName}(${func.params("", ".native")}))
524+
}
525+
% end
526+
527+
@_alwaysEmitIntoClient
528+
public static func pow(_ x: CGFloat, _ y: CGFloat) -> CGFloat {
529+
guard x >= 0 else { return .nan }
530+
return CGFloat(NativeType.pow(x.native, y.native))
531+
}
532+
533+
@_alwaysEmitIntoClient
534+
public static func pow(_ x: CGFloat, _ n: Int) -> CGFloat {
535+
// TODO: this implementation isn't quite right for n so large that
536+
// the conversion to `CGFloat` rounds. We could also consider using
537+
// a multiply-chain implementation for small `n`; this would be faster
538+
// for static `n`, but less accurate on platforms with a good `pow`
539+
// implementation.
540+
return CGFloat(NativeType.pow(x.native, n))
541+
}
542+
543+
@_alwaysEmitIntoClient
544+
public static func root(_ x: CGFloat, _ n: Int) -> CGFloat {
545+
guard x >= 0 || n % 2 != 0 else { return .nan }
546+
// TODO: this implementation isn't quite right for n so large that
547+
// the conversion to `CGFloat` rounds.
548+
return CGFloat(NativeType.root(x.native, n))
549+
}
550+
551+
@_alwaysEmitIntoClient
552+
public static func atan2(y: CGFloat, x: CGFloat) -> CGFloat {
553+
return CGFloat(NativeType.atan2(y: y.native, x: x.native))
554+
}
555+
556+
#if !os(Windows)
557+
@_alwaysEmitIntoClient
558+
public static func logGamma(_ x: CGFloat) -> CGFloat {
559+
return CGFloat(NativeType.logGamma(x.native))
560+
}
561+
#endif
562+
}
563+
512564
//===----------------------------------------------------------------------===//
513565
// tgmath
514566
//===----------------------------------------------------------------------===//

stdlib/public/Platform/tgmath.swift.gyb

+92-66
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -14,7 +14,7 @@ import SwiftShims
1414

1515
// Generic functions implementable directly on FloatingPoint.
1616
@_transparent
17-
@available(swift, deprecated: 4.2, renamed: "abs")
17+
@available(swift, deprecated: 4.2, obsoleted: 5.1, renamed: "abs")
1818
public func fabs<T: FloatingPoint>(_ x: T) -> T {
1919
return x.magnitude
2020
}
@@ -112,7 +112,7 @@ public func isnan<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
112112
@available(*, unavailable, message: "use the sign property.")
113113
public func signbit<T: FloatingPoint>(_ value: T) -> Int { fatalError() }
114114

115-
@available(swift, deprecated: 4.2, message: "use the exponent property.")
115+
@available(swift, deprecated: 4.2, obsoleted: 5.1, message: "use the exponent property.")
116116
public func ilogb<T: BinaryFloatingPoint>(_ x: T) -> Int {
117117
return Int(x.exponent)
118118
}
@@ -155,44 +155,15 @@ UnaryFunctions = [
155155
'acos', 'asin', 'atan', 'tan',
156156
'acosh', 'asinh', 'atanh', 'cosh', 'sinh', 'tanh',
157157
'expm1',
158-
'log1p', 'logb',
159-
'cbrt', 'erf', 'erfc', 'tgamma',
158+
'log1p',
159+
'erf', 'erfc',
160160
]
161161

162162
# These functions have a corresponding LLVM intrinsic
163-
# We call this intrinsic via the Builtin method so keep this list in
164-
# sync with core/BuiltinMath.swift.gyb
165163
UnaryIntrinsicFunctions = [
166-
'cos', 'sin',
167-
'exp', 'exp2',
168-
'log', 'log10', 'log2',
169-
'nearbyint', 'rint',
164+
'cos', 'sin', 'exp', 'exp2', 'log', 'log10', 'log2', 'nearbyint', 'rint'
170165
]
171166

172-
# (T, T) -> T
173-
BinaryFunctions = [
174-
'atan2', 'hypot', 'pow',
175-
'copysign', 'nextafter', 'fdim', 'fmax', 'fmin'
176-
]
177-
178-
# These functions have special implementations.
179-
OtherFunctions = [
180-
'scalbn', 'lgamma', 'remquo', 'nan', 'jn', 'yn'
181-
]
182-
183-
# These functions are imported correctly as-is.
184-
OkayFunctions = ['j0', 'j1', 'y0', 'y1']
185-
186-
# These functions are not supported for various reasons.
187-
UnhandledFunctions = [
188-
'math_errhandling', 'scalbln',
189-
'lrint', 'lround', 'llrint', 'llround', 'nexttoward',
190-
'isgreater', 'isgreaterequal', 'isless', 'islessequal',
191-
'islessgreater', 'isunordered', '__exp10',
192-
'__sincos', '__cospi', '__sinpi', '__tanpi', '__sincospi'
193-
]
194-
195-
196167
def AllFloatTypes():
197168
for bits in allFloatBits:
198169
yield floatName(bits), cFloatName(bits), cFuncSuffix(bits)
@@ -226,60 +197,117 @@ def TypedBinaryFunctions():
226197
% end
227198
@_transparent
228199
public func ${ufunc}(_ x: ${T}) -> ${T} {
229-
return ${T}(${ufunc}${f}(${CT}(x)))
200+
return ${T}.${ufunc}(x)
230201
}
231202
% if T == 'Float80':
232203
#endif
233204
% end
234205

235206
% end
207+
@_transparent
208+
public func cbrt(_ x: Float) -> Float {
209+
return Float.root(x, 3)
210+
}
211+
212+
@available(swift, deprecated: 5.1, message: "Use `x.exponent` or `floor(log2(x))`.")
213+
@_transparent
214+
public func logb(_ x: Float) -> Float {
215+
return Float.log2(x).rounded(.down)
216+
}
217+
218+
@_transparent
219+
public func tgamma(_ x: Float) -> Float {
220+
return Float.gamma(x)
221+
}
222+
223+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
224+
@_transparent
225+
public func cbrt(_ x: Float80) -> Float80 {
226+
return Float80.root(x, 3)
227+
}
228+
229+
@available(swift, deprecated: 5.1, message: "Use `x.exponent` or `floor(log2(x))`.")
230+
@_transparent
231+
public func logb(_ x: Float80) -> Float80 {
232+
return Float80.log2(x).rounded(.down)
233+
}
234+
235+
@_transparent
236+
public func tgamma(_ x: Float80) -> Float80 {
237+
return Float80.gamma(x)
238+
}
239+
#endif
236240

237-
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
238241
// Unary intrinsic functions
239242
// Note these have a corresponding LLVM intrinsic
240243
% for T, ufunc in TypedUnaryIntrinsicFunctions():
241244
% if T == 'Float80':
242245
#if (arch(i386) || arch(x86_64)) && !os(Windows)
243246
% end
247+
% if ufunc[-3:] != 'int':
244248
@_transparent
245249
public func ${ufunc}(_ x: ${T}) -> ${T} {
246-
return _${ufunc}(x)
250+
return ${T}.${ufunc}(x)
247251
}
248-
% if T == 'Float80':
249-
#endif
250-
% end
251-
252-
% end
253-
#else
254-
// FIXME: As of now, we cannot declare 64-bit (Double/CDouble) overlays here.
255-
// Since CoreFoundation also exports libc functions, they will conflict with
256-
// Swift overlays when building Foundation. For now, just like normal
257-
// UnaryFunctions, we define overlays only for OverlayFloatTypes.
258-
% for ufunc in UnaryIntrinsicFunctions:
259-
% for T, CT, f in OverlayFloatTypes():
260-
% if T == 'Float80':
261-
#if (arch(i386) || arch(x86_64)) && !os(Windows)
262-
% end
252+
% else:
253+
@available(swift, deprecated: 5.1, message: "Swift does not model dynamic rounding modes, use x.rounded(.toNearestOrEven) instead.")
263254
@_transparent
264255
public func ${ufunc}(_ x: ${T}) -> ${T} {
265-
return ${T}(${ufunc}${f}(${CT}(x)))
256+
return x.rounded(.toNearestOrEven)
266257
}
267-
% if T == 'Float80':
258+
% end
259+
% if T == 'Float80':
268260
#endif
269-
% end
270261
% end
262+
271263
% end
272-
#endif
273264

274265
// Binary functions
275-
276-
% for T, CT, f, bfunc in TypedBinaryFunctions():
266+
% for T, CT, f in OverlayFloatTypes():
277267
% if T == 'Float80':
278268
#if (arch(i386) || arch(x86_64)) && !os(Windows)
279269
% end
280270
@_transparent
281-
public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
282-
return ${T}(${bfunc}${f}(${CT}(lhs), ${CT}(rhs)))
271+
public func atan2(_ y: ${T}, _ x: ${T}) -> ${T} {
272+
return ${T}.atan2(y: y, x: x)
273+
}
274+
275+
@_transparent
276+
public func hypot(_ x: ${T}, _ y: ${T}) -> ${T} {
277+
return ${T}.hypot(x, y)
278+
}
279+
280+
@_transparent
281+
public func pow(_ x: ${T}, _ y: ${T}) -> ${T} {
282+
return ${T}.pow(x, y)
283+
}
284+
285+
@_transparent
286+
public func copysign(_ x: ${T}, _ y: ${T}) -> ${T} {
287+
return ${T}(signOf: y, magnitudeOf: x)
288+
}
289+
290+
@_transparent
291+
public func fdim(_ x: ${T}, _ y: ${T}) -> ${T} {
292+
return ${T}(fdim${f}(${CT}(x), ${CT}(y)))
293+
}
294+
295+
@available(swift, deprecated: 5.1, message: "Use the .nextUp and .nextDown properties.")
296+
@_transparent
297+
public func nextafter(_ x: ${T}, _ y: ${T}) -> ${T} {
298+
return y > x ? x.nextUp : (y < x ? x.nextDown : y)
299+
}
300+
301+
@available(swift, deprecated: 5.1, message: "Use ${T}.minimum( ) or Swift.min( )")
302+
@_transparent
303+
public func fmin(_ x: ${T}, _ y: ${T}) -> ${T} {
304+
return .minimum(x, y)
305+
}
306+
307+
@available(swift, deprecated: 5.1, message: "Use ${T}.maximum( ) or Swift.max( )")
308+
@_transparent
309+
public func fmax(_ x: ${T}, _ y: ${T}) -> ${T} {
310+
return .maximum(x, y)
283311
}
284312
% if T == 'Float80':
285313
#endif
@@ -297,9 +325,7 @@ public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
297325
% end
298326
@_transparent
299327
public func lgamma(_ x: ${T}) -> (${T}, Int) {
300-
var sign = Int32(0)
301-
let value = lgamma${f}_r(${CT}(x), &sign)
302-
return (${T}(value), Int(sign))
328+
return (${T}.logGamma(x), ${T}.signGamma(x) == .plus ? 1 : -1)
303329
}
304330
#endif
305331

@@ -326,8 +352,8 @@ public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
326352
% if T == 'Float80':
327353
#if (arch(i386) || arch(x86_64)) && !os(Windows)
328354
% end
329-
@available(swift, deprecated: 4.2, message:
330-
"use ${T}(nan: ${T}.RawSignificand) instead.")
355+
@available(swift, deprecated: 4.2, obsoleted: 5.1, message:
356+
"use ${T}(nan: ${T}.RawSignificand).")
331357
@_transparent
332358
public func nan(_ tag: String) -> ${T} {
333359
return ${T}(nan${f}(tag))

0 commit comments

Comments
 (0)