Skip to content

Cleanup tgmath wrappers. #15304

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

Merged
merged 2 commits into from
Mar 17, 2018
Merged
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
260 changes: 101 additions & 159 deletions stdlib/public/Platform/tgmath.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,88 @@ public func trunc<T: FloatingPoint>(_ x: T) -> T {
return x.rounded(.towardZero)
}

@_transparent
public func scalbn<T: FloatingPoint>(_ x: T, _ n : Int) -> T {
return T(sign: .plus, exponent: T.Exponent(n), significand: x)
}

@_transparent
public func modf<T: FloatingPoint>(_ x: T) -> (T, T) {
// inf/NaN: return canonicalized x, fractional part zero.
guard x.isFinite else { return (x+0, 0) }
let integral = trunc(x)
let fractional = x - integral
return (integral, fractional)
}

@_transparent
public func frexp<T: BinaryFloatingPoint>(_ x: T) -> (T, Int) {
guard x.isFinite else { return (x+0, 0) }
guard x != 0 else { return (x, 0) }
// The C stdlib `frexp` uses a different notion of significand / exponent
// than IEEE 754, so we need to adjust them by a factor of two.
return (x.significand / 2, Int(x.exponent + 1))
}

%for T in ['Float','Double']:
@available(swift, obsoleted: 4.2)
@_transparent
public func scalbn(_ x: ${T}, _ n : Int) -> ${T} {
return ${T}(sign: .plus, exponent: n, significand: x)
}

@available(swift, obsoleted: 4.2)
@_transparent
public func modf(_ x: ${T}) -> (${T}, ${T}) {
// inf/NaN: return canonicalized x, fractional part zero.
guard x.isFinite else { return (x+0, 0) }
let integral = trunc(x)
let fractional = x - integral
return (integral, fractional)
}

@available(swift, obsoleted: 4.2)
@_transparent
public func frexp(_ x: ${T}) -> (${T}, Int) {
guard x.isFinite else { return (x+0, 0) }
guard x != 0 else { return (x, 0) }
return (x.significand / 2, Int(x.exponent + 1))
}

@available(swift, deprecated: 4.2, renamed: "scalbn")
@_transparent
public func ldexp(_ x: ${T}, _ n : Int) -> ${T} {
return ${T}(sign: .plus, exponent: n, significand: x)
}

%end

// Floating-point properties that are exposed as functions in the C math
// library. Mark those function names unavailable and direct users to the
// properties instead.
@available(*, unavailable, message: "use the floatingPointClass property.")
public func fpclassify<T: FloatingPoint>(_ value: T) -> Int { fatalError() }

@available(*, unavailable, message: "use the isNormal property.")
public func isnormal<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }

@available(*, unavailable, message: "use the isFinite property.")
public func isfinite<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }

@available(*, unavailable, message: "use the isInfinite property.")
public func isinf<T: FloatingPoint>(_ value: T) -> Bool { fatalError() }

@available(*, unavailable, message: "use the isNaN property.")
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.")
public func ilogb<T: BinaryFloatingPoint>(_ x: T) -> Int {
return Int(x.exponent)
}

%{

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

# These functions have special implementations.
OtherFunctions = [
'fpclassify',
'isnormal', 'isfinite', 'isinf', 'isnan', 'signbit',
'modf', 'ldexp', 'frexp', 'ilogb', 'scalbn', 'lgamma',
'remquo', 'nan',
'jn', 'yn'
'scalbn', 'lgamma', 'remquo', 'nan', 'jn', 'yn'
]

# These functions are imported correctly as-is.
Expand Down Expand Up @@ -168,7 +246,7 @@ def TypedBinaryFunctions():
// Note these do not have a corresponding LLVM intrinsic
% for T, CT, f, ufunc in TypedUnaryFunctions():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% end
@_transparent
public func ${ufunc}(_ x: ${T}) -> ${T} {
Expand All @@ -185,7 +263,7 @@ public func ${ufunc}(_ x: ${T}) -> ${T} {
// Note these have a corresponding LLVM intrinsic
% for T, ufunc in TypedUnaryIntrinsicFunctions():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% end
@_transparent
public func ${ufunc}(_ x: ${T}) -> ${T} {
Expand All @@ -202,26 +280,26 @@ public func ${ufunc}(_ x: ${T}) -> ${T} {
// 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)
% end
% for T, CT, f in OverlayFloatTypes():
% if T == 'Float80':
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% end
@_transparent
public func ${ufunc}(_ x: ${T}) -> ${T} {
return ${T}(${ufunc}${f}(${CT}(x)))
}
% if T == 'Float80':
% if T == 'Float80':
#endif
% end
% end
% end
% end
% end
#endif

// Binary functions

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

% end

// Other functions
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@available(*, deprecated, message: "use the floatingPointClass property.")
public func fpclassify(_ value: ${T}) -> Int {
%if T == 'Double':
#if os(Linux) || os(Haiku)
return Int(__fpclassify(CDouble(value)))
#elseif os(Windows)
return Int(_dclass(CDouble(value)))
#else
return Int(__fpclassifyd(CDouble(value)))
#endif
%else:
#if os(Windows)
return Int(_${f}dclass(${CT}(value)))
#else
return Int(__fpclassify${f}(${CT}(value)))
#endif
%end
}

@available(*, unavailable, message: "use the isNormal property.")
public func isnormal(_ value: ${T}) -> Bool { return value.isNormal }

@available(*, unavailable, message: "use the isFinite property.")
public func isfinite(_ value: ${T}) -> Bool { return value.isFinite }

@available(*, unavailable, message: "use the isInfinite property.")
public func isinf(_ value: ${T}) -> Bool { return value.isInfinite }

@available(*, unavailable, message: "use the isNaN property.")
public func isnan(_ value: ${T}) -> Bool { return value.isNaN }

@available(*, unavailable, message: "use the sign property.")
public func signbit(_ value: ${T}) -> Int { return value.sign.rawValue }

% if T == 'Float80':
#endif
% end
% end

% # These are AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func modf(_ value: ${T}) -> (${T}, ${T}) {
var ipart = ${CT}(0)
let fpart = modf${f}(${CT}(value), &ipart)
return (${T}(ipart), ${T}(fpart))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ldexp(_ x: ${T}, _ n: Int) -> ${T} {
return ${T}(ldexp${f}(${CT}(x), Int32(n)))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func frexp(_ value: ${T}) -> (${T}, Int) {
var exp = Int32(0)
let frac = frexp${f}(${CT}(value), &exp)
return (${T}(frac), Int(exp))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% else:
// lgamma not avaialable on Windows, apparently?
#if !os(Windows)
% end
@_transparent
public func ilogb(_ x: ${T}) -> Int {
return Int(ilogb${f}(${CT}(x)) as Int32)
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func scalbn(_ x: ${T}, _ n: Int) -> ${T} {
return ${T}(scalbn${f}(${CT}(x), Int32(n)))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
@_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))
}
#elseif os(Windows)
// TODO(compnerd): implement
#else
% # On Darwin platforms the real lgamma_r is not imported
% # because it hides behind macro _REENTRANT.
% # This is not @transparent because _stdlib_lgamma() is not public.
public func lgamma(_ x: ${T}) -> (${T}, Int) {
var sign = Int32(0)
let value = withUnsafeMutablePointer(to: &sign) {
(signp: UnsafeMutablePointer<Int32>) -> ${CT} in
return _stdlib_lgamma${f}_r(${CT}(x), signp)
}
return (${T}(value), Int(sign))
}
#endif
% if T == 'Float80':
#endif
% end

% end

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

% for T, CT, f in OverlayFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
#if (arch(i386) || arch(x86_64)) && !os(Windows)
% end
@available(*, deprecated: 4.2, message:
"use ${T}(nan: ${T}.RawSignificand) instead.")
@_transparent
public func nan(_ tag: String) -> ${T} {
return ${T}(nan${f}(tag))
Expand Down
14 changes: 6 additions & 8 deletions stdlib/public/SwiftShims/LibcShims.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,15 @@ long double _stdlib_squareRootl(long double _self) {
}
#endif

// Apple's math.h does not declare lgamma_r() etc by default
// 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__)
SWIFT_RUNTIME_STDLIB_INTERNAL
float _stdlib_lgammaf_r(float x, int *psigngam);
SWIFT_RUNTIME_STDLIB_INTERNAL
double _stdlib_lgamma_r(double x, int *psigngam);
SWIFT_RUNTIME_STDLIB_INTERNAL
long double _stdlib_lgammal_r(long double x, int *psigngam);
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__)


// TLS - thread local storage

#if defined(__linux__)
Expand Down
21 changes: 0 additions & 21 deletions stdlib/public/stubs/LibcShims.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,27 +196,6 @@ void swift::_stdlib_setErrno(int value) {
}



#if defined(__APPLE__)

SWIFT_RUNTIME_STDLIB_INTERNAL
float swift::_stdlib_lgammaf_r(float x, int *psigngam) {
return lgammaf_r(x, psigngam);
}

SWIFT_RUNTIME_STDLIB_INTERNAL
double swift::_stdlib_lgamma_r(double x, int *psigngam) {
return lgamma_r(x, psigngam);
}

SWIFT_RUNTIME_STDLIB_INTERNAL
long double swift::_stdlib_lgammal_r(long double x, int *psigngam) {
return lgammal_r(x, psigngam);
}

#endif // defined(__APPLE__)


#if defined(_WIN32)
static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
"__swift_thread_key_t is not a DWORD");
Expand Down