Skip to content

Commit ddf70fa

Browse files
Cleanup tgmath wrappers. (#15304)
* Cleanup tgmath wrappers. - Remove special-case gyb logic for lgamma on Darwin; the symbols we need are always present, even if not visible in the headers, so we only need a prototype. - Add some deprecations for symbols that have direct stdlib analogues. - Make some operations generic on [Binary]FloatingPoint, where they can map to the protocols instead of calling libm. - Mark ldexp(Float/Double) renamed to scalbn; for binary formats these are identical functions, and we don't really want to use these names for hypothetical future Decimal support, as they're not Swifty.
1 parent 931d06d commit ddf70fa

File tree

3 files changed

+107
-188
lines changed

3 files changed

+107
-188
lines changed

stdlib/public/Platform/tgmath.swift.gyb

Lines changed: 101 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,88 @@ public func trunc<T: FloatingPoint>(_ x: T) -> T {
5959
return x.rounded(.towardZero)
6060
}
6161

62+
@_transparent
63+
public func scalbn<T: FloatingPoint>(_ x: T, _ n : Int) -> T {
64+
return T(sign: .plus, exponent: T.Exponent(n), significand: x)
65+
}
66+
67+
@_transparent
68+
public func modf<T: FloatingPoint>(_ x: T) -> (T, T) {
69+
// inf/NaN: return canonicalized x, fractional part zero.
70+
guard x.isFinite else { return (x+0, 0) }
71+
let integral = trunc(x)
72+
let fractional = x - integral
73+
return (integral, fractional)
74+
}
75+
76+
@_transparent
77+
public func frexp<T: BinaryFloatingPoint>(_ x: T) -> (T, Int) {
78+
guard x.isFinite else { return (x+0, 0) }
79+
guard x != 0 else { return (x, 0) }
80+
// The C stdlib `frexp` uses a different notion of significand / exponent
81+
// than IEEE 754, so we need to adjust them by a factor of two.
82+
return (x.significand / 2, Int(x.exponent + 1))
83+
}
84+
85+
%for T in ['Float','Double']:
86+
@available(swift, obsoleted: 4.2)
87+
@_transparent
88+
public func scalbn(_ x: ${T}, _ n : Int) -> ${T} {
89+
return ${T}(sign: .plus, exponent: n, significand: x)
90+
}
91+
92+
@available(swift, obsoleted: 4.2)
93+
@_transparent
94+
public func modf(_ x: ${T}) -> (${T}, ${T}) {
95+
// inf/NaN: return canonicalized x, fractional part zero.
96+
guard x.isFinite else { return (x+0, 0) }
97+
let integral = trunc(x)
98+
let fractional = x - integral
99+
return (integral, fractional)
100+
}
101+
102+
@available(swift, obsoleted: 4.2)
103+
@_transparent
104+
public func frexp(_ x: ${T}) -> (${T}, Int) {
105+
guard x.isFinite else { return (x+0, 0) }
106+
guard x != 0 else { return (x, 0) }
107+
return (x.significand / 2, Int(x.exponent + 1))
108+
}
109+
110+
@available(swift, deprecated: 4.2, renamed: "scalbn")
111+
@_transparent
112+
public func ldexp(_ x: ${T}, _ n : Int) -> ${T} {
113+
return ${T}(sign: .plus, exponent: n, significand: x)
114+
}
115+
116+
%end
117+
118+
// Floating-point properties that are exposed as functions in the C math
119+
// library. Mark those function names unavailable and direct users to the
120+
// properties instead.
121+
@available(*, unavailable, message: "use the floatingPointClass property.")
122+
public func fpclassify<T: FloatingPoint>(_ value: T) -> Int { fatalError() }
123+
124+
@available(*, unavailable, message: "use the isNormal property.")
125+
public func isnormal<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
126+
127+
@available(*, unavailable, message: "use the isFinite property.")
128+
public func isfinite<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
129+
130+
@available(*, unavailable, message: "use the isInfinite property.")
131+
public func isinf<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
132+
133+
@available(*, unavailable, message: "use the isNaN property.")
134+
public func isnan<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }
135+
136+
@available(*, unavailable, message: "use the sign property.")
137+
public func signbit<T: FloatingPoint>(_ value: T) -> Int { fatalError() }
138+
139+
@available(swift, deprecated: 4.2, message: "use the exponent property.")
140+
public func ilogb<T: BinaryFloatingPoint>(_ x: T) -> Int {
141+
return Int(x.exponent)
142+
}
143+
62144
%{
63145

64146
# Don't need 64-bit (Double/CDouble) overlays. The ordinary C imports work fine.
@@ -119,11 +201,7 @@ BinaryFunctions = [
119201

120202
# These functions have special implementations.
121203
OtherFunctions = [
122-
'fpclassify',
123-
'isnormal', 'isfinite', 'isinf', 'isnan', 'signbit',
124-
'modf', 'ldexp', 'frexp', 'ilogb', 'scalbn', 'lgamma',
125-
'remquo', 'nan',
126-
'jn', 'yn'
204+
'scalbn', 'lgamma', 'remquo', 'nan', 'jn', 'yn'
127205
]
128206

129207
# These functions are imported correctly as-is.
@@ -168,7 +246,7 @@ def TypedBinaryFunctions():
168246
// Note these do not have a corresponding LLVM intrinsic
169247
% for T, CT, f, ufunc in TypedUnaryFunctions():
170248
% if T == 'Float80':
171-
#if arch(i386) || arch(x86_64)
249+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
172250
% end
173251
@_transparent
174252
public func ${ufunc}(_ x: ${T}) -> ${T} {
@@ -185,7 +263,7 @@ public func ${ufunc}(_ x: ${T}) -> ${T} {
185263
// Note these have a corresponding LLVM intrinsic
186264
% for T, ufunc in TypedUnaryIntrinsicFunctions():
187265
% if T == 'Float80':
188-
#if arch(i386) || arch(x86_64)
266+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
189267
% end
190268
@_transparent
191269
public func ${ufunc}(_ x: ${T}) -> ${T} {
@@ -202,26 +280,26 @@ public func ${ufunc}(_ x: ${T}) -> ${T} {
202280
// Swift overlays when building Foundation. For now, just like normal
203281
// UnaryFunctions, we define overlays only for OverlayFloatTypes.
204282
% for ufunc in UnaryIntrinsicFunctions:
205-
% for T, CT, f in OverlayFloatTypes():
206-
% if T == 'Float80':
207-
#if arch(i386) || arch(x86_64)
208-
% end
283+
% for T, CT, f in OverlayFloatTypes():
284+
% if T == 'Float80':
285+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
286+
% end
209287
@_transparent
210288
public func ${ufunc}(_ x: ${T}) -> ${T} {
211289
return ${T}(${ufunc}${f}(${CT}(x)))
212290
}
213-
% if T == 'Float80':
291+
% if T == 'Float80':
214292
#endif
215-
% end
216-
% end
293+
% end
294+
% end
217295
% end
218296
#endif
219297

220298
// Binary functions
221299

222300
% for T, CT, f, bfunc in TypedBinaryFunctions():
223301
% if T == 'Float80':
224-
#if arch(i386) || arch(x86_64)
302+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
225303
% end
226304
@_transparent
227305
public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
@@ -233,166 +311,28 @@ public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
233311

234312
% end
235313

236-
// Other functions
237-
% for T, CT, f in AllFloatTypes():
238-
% if T == 'Float80':
239-
#if arch(i386) || arch(x86_64)
240-
% end
241-
@available(*, deprecated, message: "use the floatingPointClass property.")
242-
public func fpclassify(_ value: ${T}) -> Int {
243-
%if T == 'Double':
244-
#if os(Linux) || os(Haiku)
245-
return Int(__fpclassify(CDouble(value)))
246-
#elseif os(Windows)
247-
return Int(_dclass(CDouble(value)))
248-
#else
249-
return Int(__fpclassifyd(CDouble(value)))
250-
#endif
251-
%else:
252-
#if os(Windows)
253-
return Int(_${f}dclass(${CT}(value)))
254-
#else
255-
return Int(__fpclassify${f}(${CT}(value)))
256-
#endif
257-
%end
258-
}
259-
260-
@available(*, unavailable, message: "use the isNormal property.")
261-
public func isnormal(_ value: ${T}) -> Bool { return value.isNormal }
262-
263-
@available(*, unavailable, message: "use the isFinite property.")
264-
public func isfinite(_ value: ${T}) -> Bool { return value.isFinite }
265-
266-
@available(*, unavailable, message: "use the isInfinite property.")
267-
public func isinf(_ value: ${T}) -> Bool { return value.isInfinite }
268-
269-
@available(*, unavailable, message: "use the isNaN property.")
270-
public func isnan(_ value: ${T}) -> Bool { return value.isNaN }
271-
272-
@available(*, unavailable, message: "use the sign property.")
273-
public func signbit(_ value: ${T}) -> Int { return value.sign.rawValue }
274-
275-
% if T == 'Float80':
276-
#endif
277-
% end
278-
% end
279-
280-
% # These are AllFloatTypes not OverlayFloatTypes because of the tuple return.
281-
% for T, CT, f in AllFloatTypes():
282-
% if T == 'Float80':
283-
#if arch(i386) || arch(x86_64)
284-
% end
285-
@_transparent
286-
public func modf(_ value: ${T}) -> (${T}, ${T}) {
287-
var ipart = ${CT}(0)
288-
let fpart = modf${f}(${CT}(value), &ipart)
289-
return (${T}(ipart), ${T}(fpart))
290-
}
291-
% if T == 'Float80':
292-
#endif
293-
% end
294-
295-
% end
296-
297-
% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
298-
% for T, CT, f in AllFloatTypes():
299-
% if T == 'Float80':
300-
#if arch(i386) || arch(x86_64)
301-
% end
302-
@_transparent
303-
public func ldexp(_ x: ${T}, _ n: Int) -> ${T} {
304-
return ${T}(ldexp${f}(${CT}(x), Int32(n)))
305-
}
306-
% if T == 'Float80':
307-
#endif
308-
% end
309-
310-
% end
311-
312314
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
313315
% for T, CT, f in AllFloatTypes():
314316
% if T == 'Float80':
315-
#if arch(i386) || arch(x86_64)
316-
% end
317-
@_transparent
318-
public func frexp(_ value: ${T}) -> (${T}, Int) {
319-
var exp = Int32(0)
320-
let frac = frexp${f}(${CT}(value), &exp)
321-
return (${T}(frac), Int(exp))
322-
}
323-
% if T == 'Float80':
324-
#endif
325-
% end
326-
327-
% end
328-
329-
% # This is AllFloatTypes not OverlayFloatTypes because of the Int return.
330-
% for T, CT, f in AllFloatTypes():
331-
% if T == 'Float80':
332-
#if arch(i386) || arch(x86_64)
317+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
318+
% else:
319+
// lgamma not avaialable on Windows, apparently?
320+
#if !os(Windows)
333321
% end
334322
@_transparent
335-
public func ilogb(_ x: ${T}) -> Int {
336-
return Int(ilogb${f}(${CT}(x)) as Int32)
337-
}
338-
% if T == 'Float80':
339-
#endif
340-
% end
341-
342-
% end
343-
344-
% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
345-
% for T, CT, f in AllFloatTypes():
346-
% if T == 'Float80':
347-
#if arch(i386) || arch(x86_64)
348-
% end
349-
@_transparent
350-
public func scalbn(_ x: ${T}, _ n: Int) -> ${T} {
351-
return ${T}(scalbn${f}(${CT}(x), Int32(n)))
352-
}
353-
% if T == 'Float80':
354-
#endif
355-
% end
356-
357-
% end
358-
359-
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
360-
% for T, CT, f in AllFloatTypes():
361-
% if T == 'Float80':
362-
#if arch(i386) || arch(x86_64)
363-
% end
364-
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
365-
@_transparent
366323
public func lgamma(_ x: ${T}) -> (${T}, Int) {
367324
var sign = Int32(0)
368325
let value = lgamma${f}_r(${CT}(x), &sign)
369326
return (${T}(value), Int(sign))
370327
}
371-
#elseif os(Windows)
372-
// TODO(compnerd): implement
373-
#else
374-
% # On Darwin platforms the real lgamma_r is not imported
375-
% # because it hides behind macro _REENTRANT.
376-
% # This is not @transparent because _stdlib_lgamma() is not public.
377-
public func lgamma(_ x: ${T}) -> (${T}, Int) {
378-
var sign = Int32(0)
379-
let value = withUnsafeMutablePointer(to: &sign) {
380-
(signp: UnsafeMutablePointer<Int32>) -> ${CT} in
381-
return _stdlib_lgamma${f}_r(${CT}(x), signp)
382-
}
383-
return (${T}(value), Int(sign))
384-
}
385328
#endif
386-
% if T == 'Float80':
387-
#endif
388-
% end
389329

390330
% end
391331

392332
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
393333
% for T, CT, f in AllFloatTypes():
394334
% if T == 'Float80':
395-
#if arch(i386) || arch(x86_64)
335+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
396336
% end
397337
@_transparent
398338
public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
@@ -408,8 +348,10 @@ public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
408348

409349
% for T, CT, f in OverlayFloatTypes():
410350
% if T == 'Float80':
411-
#if arch(i386) || arch(x86_64)
351+
#if (arch(i386) || arch(x86_64)) && !os(Windows)
412352
% end
353+
@available(*, deprecated: 4.2, message:
354+
"use ${T}(nan: ${T}.RawSignificand) instead.")
413355
@_transparent
414356
public func nan(_ tag: String) -> ${T} {
415357
return ${T}(nan${f}(tag))

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,15 @@ long double _stdlib_squareRootl(long double _self) {
182182
}
183183
#endif
184184

185-
// Apple's math.h does not declare lgamma_r() etc by default
185+
// Apple's math.h does not declare lgamma_r() etc by default, but they're
186+
// unconditionally exported by libsystem_m.dylib in all OS versions that
187+
// support Swift development; we simply need to provide declarations here.
186188
#if defined(__APPLE__)
187-
SWIFT_RUNTIME_STDLIB_INTERNAL
188-
float _stdlib_lgammaf_r(float x, int *psigngam);
189-
SWIFT_RUNTIME_STDLIB_INTERNAL
190-
double _stdlib_lgamma_r(double x, int *psigngam);
191-
SWIFT_RUNTIME_STDLIB_INTERNAL
192-
long double _stdlib_lgammal_r(long double x, int *psigngam);
189+
float lgammaf_r(float x, int *psigngam);
190+
double lgamma_r(double x, int *psigngam);
191+
long double lgammal_r(long double x, int *psigngam);
193192
#endif // defined(__APPLE__)
194193

195-
196194
// TLS - thread local storage
197195

198196
#if defined(__linux__)

stdlib/public/stubs/LibcShims.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -196,27 +196,6 @@ void swift::_stdlib_setErrno(int value) {
196196
}
197197

198198

199-
200-
#if defined(__APPLE__)
201-
202-
SWIFT_RUNTIME_STDLIB_INTERNAL
203-
float swift::_stdlib_lgammaf_r(float x, int *psigngam) {
204-
return lgammaf_r(x, psigngam);
205-
}
206-
207-
SWIFT_RUNTIME_STDLIB_INTERNAL
208-
double swift::_stdlib_lgamma_r(double x, int *psigngam) {
209-
return lgamma_r(x, psigngam);
210-
}
211-
212-
SWIFT_RUNTIME_STDLIB_INTERNAL
213-
long double swift::_stdlib_lgammal_r(long double x, int *psigngam) {
214-
return lgammal_r(x, psigngam);
215-
}
216-
217-
#endif // defined(__APPLE__)
218-
219-
220199
#if defined(_WIN32)
221200
static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
222201
"__swift_thread_key_t is not a DWORD");

0 commit comments

Comments
 (0)