LWN: Comments on "Julia v1.10: Performance, a new parser, and more" https://lwn.net/Articles/958337/ This is a special feed containing comments posted to the individual LWN article titled "Julia v1.10: Performance, a new parser, and more". en-us Mon, 20 Oct 2025 09:05:09 +0000 Mon, 20 Oct 2025 09:05:09 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958571/ https://lwn.net/Articles/958571/ farnz <p>The IEEE arithmetic remainder function is <em>not</em> able to give an exact remainder when dividing by 2π; it can only give an exact remainder when the divisor's IEEE 754 representation is exact, and there is no exact, finite, representation of 2π (in any binary floating point system, not just in IEEE 754). You will thus, per IEEE 754's own rules, get an inexact remainder when you take the remainder after division by 2π, since you did not supply an exact representation of 2π to the remainder function. <p>In contrast, the real number 2 can be represented exactly in IEEE 754 floating point, and thus the remainder function will give you an exact result. This is, FWIW, the actual rationale given by P754 working group for the inclusion of <tt>sinPi</tt>, <tt>cosPi</tt> and <tt>atanPi</tt> in table 9.1; the only reason that IEEE 754 has traditionally omitted <tt>tanPi</tt>, <tt>acosPi</tt>, and <tt>asinPi</tt> is that these functions have problems where there's two or more valid output values for certain inputs, and there's arguments for both possible valid output values. Thu, 18 Jan 2024 10:22:27 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958569/ https://lwn.net/Articles/958569/ ianmcc <blockquote>it's a lot more challenging to reduce it to 0 to 2π without loss of accuracy.</blockquote> <p>That isn't true, in IEEE arithmetic the <tt>remainder</tt> function is exact, and very fast. In fact I don't think there is any performance advantage to taking a remainder modulo 2 compared with 2 pi. Thu, 18 Jan 2024 09:55:11 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958547/ https://lwn.net/Articles/958547/ anachronicnomad <div class="FormattedComment"> This is awesome! Exciting developments in Julia! <br> </div> Thu, 18 Jan 2024 01:41:54 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958470/ https://lwn.net/Articles/958470/ farnz <p>As a trivial example of when the *pi functions are useful, consider a case where your measurement is not in radians; for example, you have a measurement of 200° or 97 gon. The conversion from degrees to radians is multiply by π and divide by 180, while the conversion from gon to radians is multiply by π and divide by 200. In both cases, the *pi() functions help because it's incredibly cheap to reduce the argument to the range 0 to 2, whereas it's a lot more challenging to reduce it to 0 to 2π without loss of accuracy. Wed, 17 Jan 2024 14:41:41 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958469/ https://lwn.net/Articles/958469/ joib <div class="FormattedComment"> Again, the implementation of a trigonometric function can only work with the argument it's given. It can't know whether the argument is exact, or if not, how much error there is and how much error is acceptable in the output. And thus it has to do the best it can, assuming the argument is exact. For a quality implementation, that is; Of course an implementation can take the position that the input probably contains error, so why should it bother with being particularly accurate. But for some applications this isn't good enough.<br> <p> And yes, a particularly large argument to a trigonometric function probably implies that problem should be formulated in some other way. But again, the implementation of a trigonometric function can't know that, and the best it can do is to assume the argument is exact and calculate an answer that is as accurate as possible given that assumption.<br> <p> And yes, the x87 was notoriously bad with reducing large arguments. Thankfully those days are now past us, and most libc's AFAIK do argument reduction roughly per the famous(?) paper by Ng.<br> </div> Wed, 17 Jan 2024 14:31:27 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958462/ https://lwn.net/Articles/958462/ ianmcc Well, in ordinary cases (i.e. when the argument is close to 1), <tt>tanpi(x)</tt> and <tt>tan(pi*x)</tt> will have the same accuracy: <pre> println(tanpi(1/4)) println(tan(π/4)) Program stdout 0.9999999999999999 0.9999999999999999 </pre> The problem with trig functions with very large arguments is that the calculation is ill-conditioned, and roundoff error in the argument produces large errors in the result. That it is even possible to implement the trig functions so that the result only has +/- 1 ulp error for any input is non-obvious (and wasn't the case in the original 287 coprocessor), and while it is nice to have, in practice it isn't all that useful since you usually have at least 1 ulp error on the input as well and there is no way to avoid that 1 ulp error on input getting magnified into a large error on the output. <p>In fact the error in <tt>tanpi</tt> is bigger than it could be, since 1/4 + 2e20 is exactly represented as Float64, and the exact result of <tt>tanpi(1/4 + 2e20)</tt> is <tt>1.0</tt>, but Julia instead gives <tt>0.9999999999999999</tt>. So for example, if the result is used as input for another function, then that error can blow up, <pre> print(tanpi(tanpi(1/4 + 2e10) * 2e10 + 1/4)) Program stdout 0.999976031837428 </pre> although in principle all of the numbers here are exactly representable in Float64 and the exact result is 1.0. <p>If you need to calculate tan of numbers ~ 1e10 using double precision, and those numbers are calculated from some other function, then you ought to "not care" about errors in the result of order 1e-5. If you want the result to be more accurate then you need your input value to be specified to more digits than are available in double precision. <p>On order to rely on the special properties of <tt>tanpi(1/4 + 2e10)</tt> to produce 1.0 (+/- 1 ulp), the input number can't have been subject to any previous rounding. I've never seen a real-world example where that is the case (except trivial examples where the argument is a constant). Wed, 17 Jan 2024 12:56:37 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958460/ https://lwn.net/Articles/958460/ joib <div class="FormattedComment"> The big advantage of tanpi() and the other *pi() trigonometric functions is that argument reduction is easy and fast to do exactly. The standard trigonometric functions require the argument to be reduced by a multiple of pi, which requires a high-precision approximation of pi and arbitrary precision calculations which is slower and introduces possibilities of bugs and roundoff error accumulating unless the implementation is very carefully done (which historically hasn't really been the case in libc's although that has started to change).<br> <p> But of course an implementation can only calculate with whatever value is given to them. And yes, tan(x) is almost certainly going to be more accurate than calculating tanpi(x/pi). So the *pi() functions will only be useful if the argument you want to calculate needs to be multiplied by a multiple of pi (which per se isn't entirely uncommon).<br> </div> Wed, 17 Jan 2024 11:15:38 +0000 Julia v1.10: Performance, a new parser, and more https://lwn.net/Articles/958457/ https://lwn.net/Articles/958457/ ianmcc Its only sort-of true that the tanpi() function is more accurate for large arguments. Like most (all?) functions defined in IEEE that have a much smaller range than the input (trig functions, fmod, etc), it only has full accuracy when the argument is <b>exact</b>. In that example of calculating tanpi(1/4 + 2e10), fluctuations in the least significant digit of the argument still get amplified by 10 orders of magnitude, <pre> println(tanpi(1/4 + 2e10)) println(tanpi(nextfloat(1/4 + 2e10))) println(tanpi(prevfloat(1/4 + 2e10))) # Compilation provided by Compiler Explorer at https://godbolt.org/ Standard out: 0.9999999999999999 1.0000239687370587 0.999976031837428 </pre> <p>So it is only useful for this purpose if you can arrange that there is no rounding of the argument. Its exactly the same as if you wanted to calculate tan of (1/4 + 2e10) radians. The IEEE functions will give a result that is accurate to full precision, but calculating it as <tt>tanpi((1/4 + 2e10) / π)</tt> will only have ~5 digits of accuracy (-0.966688933802304, accurate to ~16 digits, for tan(1/4+2e10) versus -0.966687605232931, accurate to ~5 digits, for tanpi((1/4 + 2e10) / π)). <p>The bottom line is that if you want to calculate trig functions of very large arguments you need to know what you are doing, and using <tt>tanpi</tt> instead of <tt>tan</tt> isn't automatically going to help. Wed, 17 Jan 2024 10:19:45 +0000