Skip to content

Commit ab75577

Browse files
committed
[stdlib] Teach abs(_:) to use magnitude when it can.
Within the (single) implementation of abs(_:), dynamically check whether the numeric type and its `Magnitude` are of the same type and, if so, return the result of `magnitude`. This ensures that we do the right thing with respect to (e.g.) floating point values like -0.0, without resorting to overloading of abs(_:).
1 parent 85d488d commit ab75577

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

stdlib/public/core/Integers.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ extension SignedNumeric {
333333
/// - Returns: The absolute value of `x`.
334334
@inlinable
335335
public func abs<T : SignedNumeric & Comparable>(_ x: T) -> T {
336+
if T.self == T.Magnitude.self {
337+
return unsafeBitCast(x.magnitude, to: T.self)
338+
}
339+
336340
return x < (0 as T) ? -x : x
337341
}
338342

test/stdlib/FloatingPoint.swift.gyb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,11 @@ extension FloatingPoint {
413413
public var isQuietNaN: Bool { return isNaN && !isSignalingNaN }
414414
}
415415

416+
func genericAbs<T: SignedNumeric & Comparable>(_ x: T) -> T {
417+
return abs(x)
418+
}
419+
420+
416421
%for Self in ['Float', 'Double', 'Float80']:
417422
% if Self == 'Float80':
418423
#if !os(Windows) && (arch(i386) || arch(x86_64))
@@ -533,6 +538,12 @@ FloatingPoint.test("${Self}.significandWidth") {
533538
expectEqual(0, ${Self}(2).significandWidth)
534539
expectEqual(1, ${Self}(3).significandWidth)
535540
}
541+
542+
FloatingPoint.test("${Self}.absNegativeZero") {
543+
expectEqual(abs(${Self}(-0.0)), ${Self}(0.0))
544+
expectEqual(genericAbs(${Self}(-0.0)), ${Self}(0.0))
545+
}
546+
536547
% if Self == 'Float80':
537548
#endif
538549
% end

0 commit comments

Comments
 (0)