Releases: apple/swift-numerics
1.1.1: $Embedded support
This is a small patch release with a single change by new contributor @ebariaux to enable Swift Numerics to work in $Embedded contexts by suppressing the Encodable, Decodable, and CustomDebugStringConvertible conformances.
1.1: Relax
-
Expanded documentation and docc catalogs for ComplexModule and RealModule
-
“Relaxed arithmetic” bindings are added to the Real module. These allow you to write floating-point arithmetic that licenses the compiler to reassociate and form FMAs, which allows for much better performance in hot loops (e.g. if you are writing a signal-processing or linear algebra kernel in Swift). I expect that these will get nicer syntax sugar eventually, but I want the functionality to be available now, because it can make a huge difference in some cases. For arrays that fit into cache, on common hardware, relaxedSum below is an order of magnitude faster than strictSum, and often competitive with specialized libraries when optimization is enabled.
func strictSum(_ array: [Float]) -> Float { array.reduce(0, +) } import RealModule func relaxedSum(_ array: [Float]) -> Float { array.reduce(0, Relaxed.sum) }
-
The generic constraint on the Augmented arithmetic methods has been relaxed from
Real
toFloatingPoint
. This is more correct and makes the operations more broadly useful. Arguably,Augmented.sum(large:small:)
should be constrained toBinaryFloatingPoint
, because thefast2sum
algorithm doesn’t work in radix 10, but this would complicate generic call sites. Instead, it will dispatch to the unorderedsum(_:_:)
for decimal types, so that callers do not have to worry about this detail. -
There is a new algorithm for complex division when the inputs are poorly scaled such that the naïve approach would fail. This gives more accurate results than the old approach, and (importantly for some use cases) does not perturb results if the numerator and denominator are rescaled by the same power of two (up to the underflow boundary), and is more optimizable. Note that while it produces better results, the results will change for some inputs vis-à-vis what is seen on 1.0.x
-
Complex no longer conditionally conforms to Differentiable. Given that the Differentiation module has not formally stabilized, support for it will be moved onto a feature branch for now.
-
AlgebraicField has a
Magnitude: AlgebraicField
constraint. This is formally source-breaking. I do not expect it to actually matter for any real-world clients, which is why this isn’t a major-version release, but I want to make sure people are aware of it. Please speak up if it would have an effect that I’m overlooking. -
Complex has a new rawStorage property that directly vends the cartesian coordinates as a tuple. Previously they were available via underscored properties. These are mainly useful for interoperation with other languages, but are expected to be fairly niche outside of that use case.
As always, thanks for your feedback and contributions.
1.1
What's Changed
- The minimum supported Swift tools version is bumped to 5.9.
- Expanded documentation and docc catalogs for ComplexModule and RealModule
- The generic constraint on the Augmented arithmetic methods has been relaxed from Real to FloatingPoint. This is more correct and makes the operations more broadly useful. Formally, Augmented.sum(large:small:) should arguably be constrained to BinaryFloatingPoint, because the fast2sum algorithm doesn’t work in radix 10, but this would complicate generic call sites. Instead, it will dispatch to the unordered sum(::) for decimal types, so that callers do not have to worry about this detail. (Thanks to @markuswntr for contributing the
sum(_:_:)
implementation). - There is a new algorithm for complex division when the inputs are poorly scaled such that the naïve approach would fail. This gives more accurate results than the old approach, and (importantly for some use cases) does not perturb results if the numerator and denominator are rescaled by the same power of two (up to the underflow boundary), and is more optimizable. Note that while it produces better results, the results will change for some inputs vis-à-vis what is seen on 1.0.x
- Complex no longer conditionally conforms to Differentiable. Given that the Differentiation module has not formally stabilized, this seems appropriate.
- AlgebraicField has a Magnitude: AlgebraicField constraint. This is formally source-breaking. I do not expect it to actually matter for any real-world clients, which is why this isn’t a major-version release, but I want to make sure people are aware of it. Please speak up if it would have an effect that I’m overlooking.
- Complex has a new rawStorage property that directly vends the cartesian coordinates as a tuple. Previously they were available via underscored properties. These are mainly useful for interoperation with other languages, but are expected to be fairly niche outside of that use case.
1.0 maintenance + sendable Complex
This release contains the following changes to public modules:
- The
Complex
type is now conditionally Sendable - Explicitly links the system math library when building
RealModule
for Linux and Android (aa76ee5) pow(_: Real, _: Int)
edge cases are brought in line with the IEEE 754 (2008)powr
andpown
functions (e0ec0f5)
and the following bug fixes for the internal _TestSupport
module:
CMake build support for arm64/macOS
This release adds support for the CMake build in macOS on arm64. Thanks to @DanboDuan for the patch.
Differentiable cannot be stable
This tag contains no code changes, but clarifies in the readme that API defined in a conformance to Differentiable cannot be source-stable, because Differentiable itself is not stable. Thanks @rxwei for reminding me to clarify this.
Stable at last!
Welcome to the first stable release of Swift Numerics!
Not much has changed from 0.1.0, except that I'm declaring the API of RealModule and ComplexModule to be stable. There is some expanded documentation for the reciprocal
property on AlgebraicField
, including discussion of error bounds for Real
and Complex
types.
The only breaking change from 0.1.0 is that Augmented.fastTwoSum
and Augmented.twoProdFMA
have been deprecated and renamed Augmented.sum(large:small:)
and Augmented.product
. This change is not expected to effect many users, and the deprecation should make clear how to update your code if necessary. As always, raise a GitHub issue or post on the forums if you have questions.
Complex ... and yet Elementary
Howdy buckaroos! It's been a while since the last release, as I've been busy with some real-life stuff.
But now I'm back to the grindstone, and I've got a fun release for you. There's a bunch of cleanups and improvements from various contributors (@NevinBR and @markuswntr come to mind), but the big news is that Complex types now conform to the ElementaryFunctions protocol, which means that all your favorite math functions are available for complex types.
The branch cuts of these complex functions should generally match C and C++'s (because all implementations follow Kahan's standard paper on the subject), though the exact numerical results will be slightly different in general. Unlike the real functions, the complex elementary functions are all implemented in Swift--we don't delegate to the host system math library. This is because the general quality of <complex.h> implementations is significantly lower than <math.h> implementations, and some platforms (Windows) don't provide those operations at all. In general, I believe that the basic algorithms used by Swift Numerics for these operations are as good as (and often better) than what C libraries provide, but there is always a possibility of bugs, especially with new code. Don't hesitate to raise an issue if you see anything you suspect.
Special thanks to @compnerd for going above and beyond tracking down a Swift bug that held up this tag (and @eeckstein for fixing it!)
Xcode 12 support
This is a quick-fix release to address a bug reported with Float16 availability in Xcode 12 on Catalina. No puns, sorry 😂
This time will be different...iable?
Hey all, lots of updates in this release:
First, the big features:
-
Differentiable and Float16 support is live in Swift Numerics. These are protected behind swift version checks, so you'll only see them when you're building with a Swift 5.3 or later toolchain (because earlier toolchains don't have the necessary support). For Float16, you need to also be targeting a platform with support in the standard library (i.e. not macOS). For Differentiable, you need to be using a toolchain that was built with differentiable programming support enabled.
-
Approximate equality comparisons have been added for types conforming to Numeric when the associatedtype Magnitude conforms to FloatingPoint. This includes all of the Real types, but also includes Complex, and can be extended to lots of other useful types as well. The most basic use is:
a.isApproximatelyEqual(to: b)
which performs a comparison with default relative tolerance. You can manually specify an absolute or relative tolerance (or both), as well as a norm to use via overloads and optional arguments. Consult the doc comments for more information now, but I plan to write a more in-depth README for the feature in the coming weeks.
Two implementation details have also been added on Real
, which are useful for building out other parts of the library:
cosMinusOne(_ x: Self) -> Self
This is "justexpMinusOne(_:Self)
, but for cosine". It's a somewhat niche feature (and trivially implementable via the half-angle formula), but it turns out to be useful when building out ElementaryFunctions support for Complex types, so it seems to make good sense to make more broadly available._mulAdd(_ a: Self, _ b: Self, _ c: Self) -> Self
This is intended to use either an FMA or separate multiply and add to evaluatea*b + c
as efficiently as possible. This is a much more niche implementation detail, and the name is subject to change (hence the underscore), but it's useful enough to expose for anyone who wants to use it.
Speaking of ElementaryFunctions support for Complex types, that's something that's in progress now (#146). I'll be working through it over the next few weeks, and would love to have contributions. If you'd like to contribute, be sure to read the implementation goals. Simply borrowing from C or C++ implementations will probably not be sufficient for the goals we have and semantics defined for Complex, but you can use them as a starting point if you're willing to iterate with me a bit.
Thanks everyone!
Forums discussion here: https://forums.swift.org/t/0-0-7-release-notes/39680