-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Atanh returning values slightly outside the specified error bound #570
Comments
Hey, thank you so much for the thorough issue report, it helps us a lot. We will try reproducing this inaccuracy and come back to you with more questions if we need. |
I built sleef with the configuration you posted here. When i link with an extended version of your program: int main(int argc, char **argv) {
double in = 8.0e-17;
double result = Sleef_atanhd1_u10purec(in);
printf("Result was %a \n", result);
if (result < in)
printf("Error!\n");
double reference_result = atanh(in);
printf("Reference Result was %a \n", reference_result);
} I obtain the following output:
In the documentation (https://sleef.org/2-references/libm/#sleef_atanh_u10), we advertise that the error bound for double-precision atanh functions is 1.0 ULP is what we see in this case. Note: I am using linux on x86 instead of windows, compiling with gcc-11 - there is a difference in our environment, so differences are possible. |
I observe the same output on my machine. In your program you compare against a reference value computed at double precision, but if you compare against a reference value computed at higher precision, the error is slightly more than 1.0ULP. I thought that ULP error was measured relative to the exact result, and I've been running my tests under that assumption and all the other functions have passed. I think a relevant portion of the docs is: Let me know if I've misunderstood the way that error is measured, and I'll close the issue. |
Hi, so I made an adaptation to the previous program I sent: int main(int argc, char **argv) {
double in = 8.0e-17;
double result = Sleef_atanhd1_u10purec(in);
printf("Result was %a \n", result);
if (result < in)
printf("Error!\n");
double reference_dp = atanh(in);
printf("Reference double precision result was %a \n", reference_dp);
double reference_ld = atanhl(in);
printf("Reference long double precision result was %a \n", reference_ld);
mpfr_t in_mpfr, out_mpfr;
mpfr_init2 (in_mpfr, 200);
mpfr_init2 (out_mpfr, 200);
mpfr_set_d (in_mpfr, in, GMP_RNDN);
mpfr_atanh(out_mpfr, in_mpfr, GMP_RNDN);
double reference_mpfr = mpfr_get_ld(out_mpfr, GMP_RNDN);
printf("Reference mpfr result was %a \n", reference_mpfr);
mpfr_clear (in_mpfr);
mpfr_clear (out_mpfr);
} And this is the output I obtain:
In this example I use mpfr_atanh (rounded to long double) and GLIBC’s atanhl as my high accuracy references, and still don't see more than 1.0ULP error. Could you let me know which high precision references you are using? |
Hi I've written an extended reproducer using MPFR as my reference. mpfr_prec_t GlobalPrecision = 200;
void PrintULPError(double approx, mpfr_srcptr reference)
{
// If you're worried about precision being lost here,
// convert approx and approxNudged to MPFR and perform the subtraction after,
// you'll get the same result
double approxNudged = nextafter(approx, INFINITY);
double ulp = approxNudged - approx;
// Compute error as (reference - approx) / ulp
mpfr_t err;
mpfr_init2(err, GlobalPrecision);
mpfr_sub_d(err, reference, approx, MPFR_RNDN);
mpfr_div_d(err, err, ulp, MPFR_RNDN);
mpfr_printf("ULP Error: %.20RDf", err);
mpfr_clear(err);
}
int main()
{
double x = 8e-17;
// Compute approx atanh(x)
double approx = Sleef_atanhd1_u10purec(x);
// Convert x to mpfr
mpfr_t xMpfr;
mpfr_init2(xMpfr, GlobalPrecision);
mpfr_set_d(xMpfr, x, MPFR_RNDN);
// Compute reference atanh(x)
mpfr_t reference;
mpfr_init2(reference, GlobalPrecision);
mpfr_atanh(reference, xMpfr, MPFR_RNDN);
// Display error
PrintULPError(approx, reference);
mpfr_clear(xMpfr);
mpfr_clear(reference);
} This is the output I observe
|
Hi, just letting you know we have been able to reproduce the issue. Currently deciding how to proceed about this, will follow up on this soon. |
After having a look at |
Describe the bug
The
Sleef_atanhd1_u10purec
function is returning values with an error of slightly more than 1ULP for arguments around 10^-17.I've also experienced similar issues with other atanh functions, such as
Sleef_atanhd4_u10avx2
. This may affect others also.Command lines and logs
I built SLEEF using
Configure log: CMakeConfigureLog.txt
Build log: cmake_build_log.txt
To Reproduce
Here's a minimal reproducer
The CMake used to build this example is
(I just hardcoded the paths to SLEEF for simplicity)
And I built using the commands
Expected behavior
I expected that "Error!" would not be printed to the console. Since atanh(x) > x for all positive x, by returning a value strictly less than x, it's produced a result more than 1ULP away from the exact value.
Environment
I'm more than happy to provide any other information you need.
The text was updated successfully, but these errors were encountered: