I just switched some code over from tgmath.h
to SwiftNumerics.
When doing so, I was surprised by a cascade of test failures that could all be traced back to pow(Self, Self)
’s outright rejection of all negative bases:
XCTAssertEqual(pow(-3.0, 2.0), 9) // Failure: .nan
But looking at the source code, I cannot really tell if it is an accident or a deliberate design decision, because (1) the rejection is explicit and (2) there is a separate function for integral exponents. The source looks like this:
@_transparent public static func pow(_ x: Float, _ y: Float) -> Float {
guard x >= 0 else { return .nan } // [1]
return libm_powf(x, y)
}
@_transparent public static func pow(_ x: Float, _ n: Int) -> Float { // [2]
// [...]
}
I worked around it on the client side by wrapping it like this:
@inlinable public static func ↑ (base: Self, exponent: Self) -> Self {
if base >= 0 { // SwiftNumerics refuses to do negatives.
return Self.pow(base, exponent)
} else if let integer = Int(exactly: exponent) {
return Self.pow(base, integer)
} else {
// Allow SwiftNumerics to decide on the error:
return Self.pow(base, exponent)
}
}
So now I’m basically asking if a pull request to change it to the following would be welcome, or if it is intentionally not supposed to work that way for some reason:
@_transparent public static func pow(_ x: Float, _ y: Float) -> Float {
guard x >= 0 else {
guard let integer = Int(exactly: y) { return .nan }
return pow(x, integer)
}
return libm_powf(x, y)
}