-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[stdlib] Add **
and **=
for exponentiation
#36053
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
Conversation
@swift-ci Please test |
@swift-ci Please test Windows platform |
Neat. I think the question (for others to decide) is whether we'd want to add these shims to the standard library now (they'd have to stay forever). Personally, I think it's fine. Will have to think more about this whole precedence issue a little more on the forums. |
@@ -118,17 +117,17 @@ FloatingPoint.test("BinaryFloatingPoint/genericIntegerConversion") { | |||
FloatingPoint.test("BinaryFloatingPoint/genericFloatingPointConversion") { | |||
func convert< | |||
T: BinaryFloatingPoint, U: BinaryFloatingPoint | |||
>(exactly value: T, to: U.Type) -> U { U(exactly: value) } | |||
>(exactly value: T, to: U.Type) -> U? { U(exactly: value) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused what happened here. Did it always not compile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static func **= (_ lhs: inout Self, _ rhs: Self) { | ||
lhs = lhs ** rhs | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tricky thing about adding these for real (and @stephentyrone has said this in the forums) is that we then need to talk about whether the (Self, Self) -> Self
overloads should vend IEEE pow
(integral exponents get special treatment) or powr
(derived by considering only exp(rhs * log(lhs))
).
We would also need to consider if (Self, Int) -> Self
overloads need to be added at the same time (vending IEEE pown
), and if so whether they can appropriately be spelled with the same operator for two subtly different functions. The reason it'd have to be talked about now is, if we do decide to overload and choose powr
for the above (Self, Self) -> Self
overload, then for an integer literal exponent adding the overload later would silently change the behavior of existing code.
(My personal preference would be to use ** (Self, Self) -> Self
to vend pow
and ** (Self, Int) -> Self
to vend pown
, with a consideration for &**
to be added if needed for powr
. But I have to admit I haven't thought about it deeply.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swift Numerics uses __builtin_pow{,f,l}
for all pairs of pow(_:_:)
methods:
Clang also has:
__builtin_powi{,f,l}
operations, which may be IEEEpown
?__builtin_powf16
and__builtin_sqrtf16
, and some support for_Float16
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I think that's settled then...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correction: Swift Numerics uses a guard
statement, to implement pow(x, y)
as exp(y * log(x))
:
extension Double: Real {
public static func pow(_ x: Double, _ y: Double) -> Double {
guard x >= 0 else { return .nan }
return libm_pow(x, y)
}
}
So I think Clang/C99 is IEEE pow
? Swift Numerics is IEEE powr
and pown
?
Module | Test | Result | IEEE |
---|---|---|---|
Builtin | __builtin_pow(-2.0, 4.0) |
16.0 |
pow |
Darwin | pow(-2.0, 4.0) |
16.0 |
pow |
RealModule | Double.pow(-2.0, 4.0) |
.nan |
powr |
RealModule | Double.pow(-2.0, 4__) |
16.0 |
pown |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, conceptually, that would be how they're aligned then (there are some edge conditions where the IEEE-specified result of pow
and powr
differ (pow(1, .infinity)
being one example)).
I've opened #36072 to reinstate the floating-point tests. |
https://forums.swift.org/t/exponentiation-operator-and-precedence-group/44895
Follow-up to: #36041 and SR-14095