I would like to write some highly optimized generic functions in Swift 3 that work on any floating point type, so I came out with something like this, which works:
@inline(__always) public func radsToDegs<T: BinaryFloatingPoint>(_ angle: T) -> T {
let radsToDegsConstant: T = 180/T(M_PI)
return angle*radsToDegsConstant
}
let a: CGFloat = CGFloat(M_PI)
let b = 3.14
let c: Float = 3.14
let d: Double = 3.14
radsToDegs(a) // -> 180.0
radsToDegs(b) // -> 179.9087476710785
radsToDegs(c) // -> 179.9087
radsToDegs(d) // -> 179.9087476710785
But I would like to have the radsToDegsConstant precomputed, and the following code fails to compile for a good reason: it's due to the fact that radsToDegs is generic:
// error: type 'OptimizedConstants' cannot be nested in generic function 'radsToDegs'
@inline(__always) public func radsToDegs<T: BinaryFloatingPoint>(_ angle: T) -> T {
struct OptimizedConstants {
static let radsToDegsConstant: T = 180/T(M_PI)
}
return angle*OptimizedConstants.radsToDegsConstant
}
So my only remaining solution is to not go for a generic function, but instead extend just the type that I know I'm most interested in, and declare the computed constant outside the function:
private let radsToDegsConstant = 180/CGFloat(M_PI)
public extension CGFloat {
@inline(__always) public func radsToDegs() -> CGFloat {
return self*radsToDegsConstant
}
}
let x: CGFloat = CGFloat(M_PI)
x.radsToDegs() // 180.0
But I still wonder if the Swift compiler would be smart enough to avoid computing radsToDegsConstant each time the function it's called, on the former generic implementation.
So that's my question: is that optimized? Or is there a trick, or a compiler directive that I may use to still get both the benefits from the generic function and the precomputed value that the extension form delivers?