TrigonometricFloatingPoint/MathFloatingPoint protocol?

update:

I’ve managed to improve the algorithm to the point where it’s arguably more
accurate than Glibc.cos(_:), and runs just as fast. Removing one term makes
the Swift implementation faster than _cos(_:), but worses the divergence by
like 23% (137 ULPs from 0° ..< 90°, as opposed to 111 ULPs).

Relative time (lower is better)

_cos(_:) instrinsic : 3.096
pure Swift implementation : 3.165

Almost everywhere the pure Swift implementation is within ±1 ULP of the
Glibc/llvm implementation. Adding more terms to the approximation actually
worsens the divergence, so I guess we are in the range where we have to
start talking about error in the Glibc implementation as well. Here’s an output
dump
<https://github.com/kelvin13/swift-math/blob/d82e8b1df848879ba6ac6071883fde7f9a15c967/tests/output.txt&gt;
with input from −360° to +360°.

The _cos(_:) intrinsic seems to be asymmetric across the positive and
negative halves of the function, which causes the divergence to rise to
about 3–5 ULPs on the far side of the unit circle. This could be due to
rounding differences in the arguments, since π/2 and 3π/2 are impossible to
represent in floating point. However I don’t know which implementation is
“wrong” here. The Swift one gives the “right” output for all special
angles; i.e. cos(90°) == 0, cos(60°) == 0.5, etc , whereas _cos(_:) gives
slightly fuzzy values.

If anyone wants to try it, I put the cosine implementation in an actual
module on github; and the given benchmark numbers are for cross-module
calls. <https://github.com/kelvin13/swift-math&gt;

···

On Thu, Aug 3, 2017 at 7:32 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Thu, Aug 3, 2017 at 7:12 PM, Karl Wagner via swift-evolution < > swift-evolution@swift.org> wrote:

On 3. Aug 2017, at 13:04, Stephen Canon via swift-evolution < >> swift-evolution@swift.org> wrote:

On Aug 2, 2017, at 7:03 PM, Karl Wagner via swift-evolution < >> swift-evolution@swift.org> wrote:

It’s important to remember that computers are mathematical machines, and
some functions which are implemented in hardware on essentially every
platform (like sin/cos/etc) are definitely best implemented as compiler
intrinsics.

sin/cos/etc are implemented in software, not hardware. x86 does have the
FSIN/FCOS instructions, but (almost) no one actually uses them to implement
the sin( ) and cos( ) functions; they are a legacy curiosity, both too slow
and too inaccurate for serious use today. There are no analogous
instructions on ARM or PPC.

– Steve
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hah that’s pretty cool; I think I learned in EE years ago that it was
implemented with a lookup table inside the CPU and never bothered to
question it.

The pure-Swift cosine implementation looks cool.

I’m pretty sure it can be improved greatly, at least for Double.
Unfortunately performance falls off a cliff for Float for some reason, i
don’t know why.

As for the larger discussion about a Swift maths library: in general,
it’s hard for any new Swift-only package to get off the ground without a
more comprehensive package manager. The current version doesn’t support
most of the Swift projects being worked on every day. Swift is also still a
relatively young language - the new integer protocols have never even
shipped in a stable release. Considering where we are, it’s not really
surprising that most of the Swift maths libraries are still a bit
rudimentary; I expect they will naturally evolve and develop in time, the
way open-source code does.

Most of the SPM’s limitations have workarounds, the problem is it’s just
not very convenient, i.e. local and non-git dependencies. Other features
like gyb, I’m not sure if it’s a good idea to bring to the SPM. gyb is a
band-aid over deeper limitations of the language.

It’s also worth considering that our excellent bridging with C removes
some of the impetus to rewrite all your battle-tested maths code in Swift.
The benefits are not obvious; the stage is set for pioneers to experiment
and show the world why they should be writing their maths code in Swift.

The glibc/llvm functions are not generic. You cannot use _cos(_:) on a
protocol type like BinaryFloatingPoint. A pure Swift implementation would
allow generic programming with trig and other math functions; right now
anything beyond sqrt() requires manual specialization.

- Karl

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution