Radians/Degrees/Turns in trig functions

Henry Baker <[email protected]>
Newsgroups gmane.comp.mathematics.maxima.general
Message-ID <[email protected]>
FYI --




I discuss a compiler issue below this reference:




https://www.computerenhance.com/p/turns-are-better-than-radians




[Full] Turns are Better than Radians




[From September, 2022]




Some time ago, much effort was expended to convince people to replace approximations of “pi” (3.14159…) with approximations of “tau” (6. 28318…).




If you’ve ever used these [multiples of pi] constants, the vast majority of what you wrote probably did something like this:




y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - 
    (cursor->get_height() / 2);




Notice what is going on here: the programmer has a value h which is already periodic on the range 0 to 1, but they multiply by tau because they need to call sin.




This may seem very sensible if that’s as far as you look. But what about the implementation of sin?




_PS256_CONST(cephes_FOPI, 1.27323954473516);
...
y = _mm256_mul_ps(x, *(v8sf*)_ps256_cephes_FOPI);




Again, not me making up an example - that’s from this commonly referenced AVX2 implementation of sin.




https://github.com/reyoung/avx_mathfun/blob/be617bbcf66993c4f7e7d267ed9926cd8e7d4f02/avx_mathfun.h#L346




What does this line do? It multiplies the input by the constant 1.27323954473516.




Which just so happens to be 4/pi.




So the calling code is doing this:




sin(h * 2 * pi)




but the library code immediately does this:




y = (4 / pi) * x




which means the calling code is multiplying by a factor of pi just so the library code can immediately divide it back out again. It’s literally a conversion to radians and back for no reason. If both programmers had just agreed not to use radians, and instead used the original [0, 1] domain that h was already on, both their jobs get simpler: the caller saves a multiply, while the library gets a simpler-to-understand, exact constant.




And the “exact” part is actually quite interesting. Not only do you pay for an extra multiply when you spuriously convert to radians, but it’s also worth noting that all common radian angles besides 0 are difficult to represent. Want to store 90 degrees in radians? No matter how many bits you use, it will never be exact.




So the [0, 1] range is not only more computationally efficient than radians, it is also more compact and precise when representing typical values that frequently occur in practical use.
---
[HBaker]




A couple of comments on the above blog:




1.  If one is calling a *hardware* sin/cos instruction, one is pretty much out of luck, unless the hardware supports sind/cosd, in which case, the multiples of pi are replaced by multiples/submultiples of the integer 360.




2.  So let's assume we're talking about SW sind/cosd.  Some compiler systems -- e.g. LLVM -- support full integration of library subroutines at *link* time ["LTO"], so presumably, the various multiples/submultiples of 360 will cancel out at compile/link time.  Furthermore, this cancellation is more likely to achieve the correct/precise result due to multiplication/division by 180 than by pi.




3. Note that sometimes too much cleverness -- i.e., "premature optimization" -- e.g., converting a float division into a multiplication by [an approximation to] its multiplicative inverse -- can get in the way of more powerful optimizations like LTO.














_______________________________________________
Maxima-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/maxima-discuss
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.