math.rs icon indicating copy to clipboard operation
math.rs copied to clipboard

Results from math.rs and glibc are different

Open anatol opened this issue 8 years ago • 4 comments

math.rs library looks promising and can used as a template for Rust float functions implementation. In this case performance and correctness are 2 extremely important properties. I checked some functions and found that most of them work well, but cos shows incorrect results. Here is an example:

cos(2.0) gives following results:

libm:     -0.4161468365471424
math.rs:  -0.4161468365471425
google:   -0.41614683654
ruby:     -0.4161468365471424

math.rs result is slightly different from what libm returns.

anatol avatar Feb 16 '17 04:02 anatol

Most likely because the implementation wasn’t copied from glibc. The current implementation in math.rs acknowledges it is not too accurate for example here. Moreover, I suspect glibc just calls a hardware instruction to calculate cosine making this a comparison between hardware instruction and software implementation and not two software implementations. It may very well be that glibc’s software implementation is not very good either.

If there’s a possibility to contribute a more correct, properly licensed version (MIT/Apache), by all means please do so.

(for the reference, less rounded result of cos(2.) is -0.41614683654714238699756822950076218976600077107554489075, so glibc/hardware is clearly more correct here).

nagisa avatar Feb 16 '17 06:02 nagisa

It seems that glibc calculates sine and cosine in software: https://stackoverflow.com/questions/12485190/calling-fsincos-instruction-in-llvm-slower-than-calling-libc-sin-cos-functions#24470801.

tbu- avatar Feb 26 '17 11:02 tbu-

So I’ve redone the test suite to quick-check and there’s a number of functions that do not match the glibc output exactly:

  • sin, cos, tan – trigonometry functions, which I’ve already acknowledged to be inaccurate;
  • exp – significantly wrong (I must have done a mistake somewhere);
  • sqrtf, expf – 1 ulp, most likely because these are calculated with sqrt/exp and then cast to f32;
  • llroundf, lroundf – seems like a wrong shift;
  • hypot, hypotf – mismatch of NaN bit-pattern for undefined result (i.e. not something to be worried about);
  • logb, logbf, scalbn, scalbnf – mistakes/UBs/different constants around special cases, I think;
  • ilogb, ilogbf – different value for the FP_ILOGBNAN constant.

nagisa avatar Feb 26 '17 18:02 nagisa

It might worth to integrate math unit tests from libc-test project http://repo.or.cz/libc-test.git/tree/HEAD:/src/math

anatol avatar Apr 04 '17 04:04 anatol