<div dir="ltr"><div><div><div><div>update: <br><br></div>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° ..&lt; 90°, as opposed to 111 ULPs).<br><br></div><span style="font-family:monospace,monospace">Relative time (lower is better)<br><br></span></div><span style="font-family:monospace,monospace">_cos(_:) instrinsic       : 3.096<br></span></div><span style="font-family:monospace,monospace">pure Swift implementation : 3.165</span><div><div><div><br>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 <a href="https://github.com/kelvin13/swift-math/blob/d82e8b1df848879ba6ac6071883fde7f9a15c967/tests/output.txt">output dump</a> with input from −360° to +360°.<br><br></div><div>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.<br><br></div><div>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. &lt;<a href="https://github.com/kelvin13/swift-math">https://github.com/kelvin13/swift-math</a>&gt;<br></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Aug 3, 2017 at 7:32 PM, Taylor Swift <span dir="ltr">&lt;<a href="mailto:kelvin13ma@gmail.com" target="_blank">kelvin13ma@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Thu, Aug 3, 2017 at 7:12 PM, Karl Wagner via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><span><br><div><blockquote type="cite"><div>On 3. Aug 2017, at 13:04, Stephen Canon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_1380047297559233979m_2018249213978403257Apple-interchange-newline"><div><div style="word-wrap:break-word;line-break:after-white-space"><blockquote type="cite">On Aug 2, 2017, at 7:03 PM, Karl Wagner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br></blockquote><div><blockquote type="cite"><div><br class="m_1380047297559233979m_2018249213978403257Apple-interchange-newline"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">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.</span></div></blockquote><br></div><div>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.</div><div><br></div><div>– Steve</div></div>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br></div></blockquote></div><br></span><div>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.</div><div><br></div><div>The pure-Swift cosine implementation looks cool.</div></div></blockquote><div><br></div></span><div>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.<br></div><span class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>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.</div><div><br></div></div></blockquote><div><br></div></span><div>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.<br></div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div></div><div>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.</div><span class="m_1380047297559233979HOEnZb"><font color="#888888"><div><br></div></font></span></div></blockquote><div><br></div></span><div>The glibc/llvm functions are not generic. You cannot use _cos(_:) on a protocol type like <span style="font-family:monospace,monospace">BinaryFloatingPoint</span>. A pure Swift implementation would allow generic programming with trig and other math functions; right now anything beyond <span style="font-family:monospace,monospace">sqrt()</span> requires manual specialization.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><span class="m_1380047297559233979HOEnZb"><font color="#888888"><div></div><div>- Karl</div></font></span></div><span class=""><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></span></blockquote></div><br></div></div>
</blockquote></div><br></div>