In order to better support writing numerical algorithms, we should provide bindings for <math.h>
-style elementary functions that are generic over scalar types (including allowance for future complex types) and SIMD vectors.
Motivation
BinaryFloatingPoint
(and the protocols it refines) provides a powerful set of abstractions for writing numerical code, but it does not include the transcendental operations defined by the C math library, which are instead imported by the platform overlay as a set of overloaded concrete free functions. This makes it impossible to write generic code that uses, say exp
or sin
without defining your own trampolines or converting everything to and from Double
, neither of which is very satisfying.
For example, suppose that we want to write a sigmoid function that works for any floating-point type. We "should" be able to write something like the following:
func sigmoid<T>(_ x: T) -> T where T: FloatingPoint {
return 1/(1 + exp(-x))
}
but that isn't valid, because the FloatingPoint
protocol only binds IEEE 754 operations, which exp
is not. Instead we can currently do something like:
return 1/(1 + T(exp(-Double(x))))
but that's messy, inefficient if T
is less precise than Double
, and inaccurate if T
is more precise than Double
. We can and should do better in Swift.
This issue has come up a few times in past discussion, and was recently mentioned in a fast.ai article about using Swift for numerical computing. I finally have a little bit of breathing room to tackle it, so I would like to push on getting this functionality into Swift 5.1. A link to the draft proposal can be found below, and I'll publish a full draft implementation in the next couple of days.