Releases: apple/swift-numerics
Fenestration
There are a bunch of small changes in this release:
-
Added Windows support via CMake build system, contributed by @compnerd (special thanks for your patience!)
-
I removed the Complex benchmarks from the test targets. Semantically, benchmarks are not the same as tests, and we don't need these to run in the same conditions. Further, the Xcode benchmark infrastructure isn't quite what we want for these, and they don't work on Windows anyway, because clang does not support C complex multiplication or division on Windows. These benchmarks will return in the next release in the form of an executable target.
-
Complex<T> now conforms to Differentiable if you are using a toolchain that supports Differentiable programming and T is Differentiable. Thanks to @rxwei and @dan-zheng for their work on this.
-
Some documentation fixes for Complex fell out from work that @markuswntr has been doing on Quaternions (check out the Quaternions branch to play with it, and help review his PRs)
-
I fixed a bug in pow(Float/Double, Int) for exceptionally large exponents. It's unlikely that this ever caused any real problems, because it only occurs when the exponent is so large that the result should always be 0, 1, or infinity, but now we get the right answer for these cases.
A reminder that Float16 support is available on the swift-5.3 branch, which will be merged to master when swift-5.3 is released. When that happens, I will also create a LTS swift-5.2 branch to support older toolchains that do not have Float16 support.
Any questions or problems can be discussed on the GitHub repo or on the Swift Forums: https://forums.swift.org/t/0-0-6-release-notes/38146
I saw the Sign, and it opened up my mind
There are two changes in this release:
-
AlgebraicField
now refinesSignedNumeric
instead ofNumeric
. This should have no visible change for most users, because all conforming types (Float
,Double
,Float80
, andComplex
) already conform toSignedNumeric
. However, users who have code that is generic over theAlgebraicField
protocol can now use unary negation (or remove existing explicitSignedNumeric
constraints from that code). -
The
Real
andComplex
modules have been renamedRealModule
andComplexModule
. If you importNumerics
, then this change does not affect you. However, if you currently import eitherReal
orComplex
directly, you will need to update your import statements. (sorry!)This is not a change that I make lightly; I would very much prefer to avoid this sort of churn, even though Swift Numerics hasn't yet declared 1.0. However, there are real limitations of the current name lookup system, which prevents use of some nice patterns when a module name shadows a type.
E.g. with this change, a user who mostly only wants to work with complex doubles can do the following:
import ComplexModule typealias Complex = ComplexModule.Complex<Double> // Can now use the simpler name Complex for Complex<Double>: func foo(_ z: Complex) -> Complex { ... } // But can still get at the generic type when necessary: let a = ComplexModule.Complex<Float>
Any Swift Numerics module that might have this ambiguity will be suffixed with
Module
in the future (just like the pattern of protocols being suffixed withProtocol
when necessary to break ambiguity).
As always, if you have any questions or comments, there is a forums thread for discussing this release.
We will not be Fielding further questions at this time
There are two changes in this release to call out specifically:
-
Complex's conformance to Codable now uses an unkeyed container, so e.g.
.zero
gets encoded as[0,0]
in JSON instead of the old{"x":0, "y":0}
. -
There's a new protocol,
AlgebraicField
refiningNumeric
by adding the/
,/=
operators, and a.reciprocal: Self?
property. TheReal
protocol refines it andComplex<T>
conforms to it, allowing you to write code that is generic over them. There are some additional operations that it probably makes sense to add to this protocol (e.g. square root); I expect to add them gradually as needed.
I also want to draw special attention to a change that I expect to make in the next tag. In order to make certain use patterns simpler, I intend to give the Complex
module a name that doesn't conflict with the Complex
type. If you have opinions about this change, or suggestions for a naming pattern to adopt for modules in Swift Numerics, please weigh in on that thread.
If you have any questions, use this discussion thread on the Swift forums.
We have the power
In earlier releases, Real.pow(Self, Int)
simply called through to libm_pow
. This is generally acceptable on platforms with a decent math library, but gets some cases wrong for Float
and Double
when the exponent is so large that it would be rounded in conversion to Self
.
For example, consider Float.pow(-1, 0x1000001)
. Since the exponent is odd, the result should be -1
, but when we simply called libm_pow(-1, Float(0x1000001))
, the exponent was rounded to an even number, and the result was 1
.
This behavior is fixed in this release; in particular the parity of integer exponents is always preserved, so that we will not have sign errors like above. There is still additional work to be done on the Real.pow
implementations--especially to provide better support for platforms with suspect math libraries--but this is a significant improvement to these operations.
Complex API cleanup
There are two significant API changes to the Complex module in this release:
-
The
unsafeLengthSquared
property has been renamedlengthSquared
, because--while it can overflow or underflow--the result is always well-defined, and therefore does not lead to memory unsafety. The old property is still present, marked unavailable, so you should get a useful renaming message from the compiler or your IDE. The old property will be removed after a period of time. -
The
Complex(length:phase:)
initializer has been made non-optional. Instead it is now a precondition that the length must be either zero or infinite if phase is not finite. Updating code to account for this change should be quite straightforward, because you are unlikely to have been using the paths that could return nil previously. If you have any questions, please ask for assistance on the forums.
Linux testing improvements
Adds an empty Tests/LinuxMain.swift to fix building on Linux, and directs users to --enable-test-discovery for testing on Linux.
Initial tag
I haven't yet formally defined the release policy for this repo, but it's useful for SPM workflows to have a tag exist, so I'm cutting 0.0.0 with the first few rounds of bug fixes and cleanups from open source contributors.
Thanks to everyone who has jumped to contribute!