public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Fix the inaccuracy of j0f/y0f/j1f/y1f
@ 2021-02-19  9:02 Paul Zimmermann
  2021-02-19 16:44 ` Michael Morrell
  2021-02-24 18:59 ` Adhemerval Zanella
  0 siblings, 2 replies; 10+ messages in thread
From: Paul Zimmermann @ 2021-02-19  9:02 UTC (permalink / raw)
  To: libc-alpha

       Hi,

I just sent a new version of patches to fix #14469, #14471, #14470, #14472.
Following Wilco's advice, this new version uses the "reduce_large" function
for argument reduction modulo pi/2.

If anyone is willing to perform exhaustive tests on some exotic platforms,
some code is available on
<https://members.loria.fr/PZimmermann/software/check_exhaustive-555.c>.
Warning: it takes about one hour on a 4-core computer for each function
and each rounding mode.

Paul

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-19  9:02 Fix the inaccuracy of j0f/y0f/j1f/y1f Paul Zimmermann
@ 2021-02-19 16:44 ` Michael Morrell
  2021-02-19 21:15   ` Joseph Myers
  2021-02-21  7:37   ` Paul Zimmermann
  2021-02-24 18:59 ` Adhemerval Zanella
  1 sibling, 2 replies; 10+ messages in thread
From: Michael Morrell @ 2021-02-19 16:44 UTC (permalink / raw)
  To: libc-alpha

I'm curious about something.  Where is it specified what the required accuracy is for a given math function?  Before I discovered the libm-test-ulps file, I would have expected a C library to be required to computed the exact result for any defined function (possibly allowing some inaccuracy if -ffast-math were specified).  I look through the POSIX spec, but couldn't find any place that mentioned an accuracy requirement.

    Michael

-----Original Message-----
From: Libc-alpha <libc-alpha-bounces@sourceware.org> On Behalf Of Paul Zimmermann
Sent: Friday, February 19, 2021 1:03 AM
To: libc-alpha@sourceware.org
Subject: Fix the inaccuracy of j0f/y0f/j1f/y1f

       Hi,

I just sent a new version of patches to fix #14469, #14471, #14470, #14472.
Following Wilco's advice, this new version uses the "reduce_large" function for argument reduction modulo pi/2.

If anyone is willing to perform exhaustive tests on some exotic platforms, some code is available on <https://members.loria.fr/PZimmermann/software/check_exhaustive-555.c>.
Warning: it takes about one hour on a 4-core computer for each function and each rounding mode.

Paul

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-19 16:44 ` Michael Morrell
@ 2021-02-19 21:15   ` Joseph Myers
  2021-02-21  7:37   ` Paul Zimmermann
  1 sibling, 0 replies; 10+ messages in thread
From: Joseph Myers @ 2021-02-19 21:15 UTC (permalink / raw)
  To: Michael Morrell; +Cc: libc-alpha

On Fri, 19 Feb 2021, Michael Morrell wrote:

> I'm curious about something.  Where is it specified what the required 
> accuracy is for a given math function?  Before I discovered the 

If the relevant standards bind a function to an IEEE 754 operation (e.g. 
sqrt and fma) then, for IEEE formats, it needs to be correctly rounded 
(including correct exceptions, including being correct about whether 
"inexact" is raised or not, including being correct about the 
architecture-specific choice of whether tininess is detected before or 
after rounding; it may or may not always be correct regarding whether the 
underflow exception is signaled in the case of exact underflow, which does 
not raise the underflow flag and so can only be detected with traps 
enabled).

If the relevant standards do not bind a function to an IEEE 754 operation 
(most functions), glibc's accuracy goals are described in the manual 
("Errors in Math Functions").  The specific numerical limits on errors in 
ulps that are accepted in libm-test-ulps files - such that errors above 
those bounds are considered to be bugs in glibc - may be found in 
libm-test-support.c:init_max_error.  (Those are empirical bounds in that 
they were based on errors actually observed with glibc implementations and 
the glibc testsuite some time ago.  It would be reasonable to reduce them 
if we improve the implementations in glibc so that the largest error is 
smaller.  I expect a reduction of the bounds to 1 or 2 ulps for IEEE 
formats could be achieved without harming performance, although with 
significant effort involved to reduce error accumulation in various 
functions.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-19 16:44 ` Michael Morrell
  2021-02-19 21:15   ` Joseph Myers
@ 2021-02-21  7:37   ` Paul Zimmermann
  2021-02-23 19:07     ` Michael Morrell
  1 sibling, 1 reply; 10+ messages in thread
From: Paul Zimmermann @ 2021-02-21  7:37 UTC (permalink / raw)
  To: Michael Morrell; +Cc: libc-alpha

       Dear Michael,

> I'm curious about something.  Where is it specified what the required accuracy is for a given math function?  Before I discovered the libm-test-ulps file, I would have expected a C library to be required to computed the exact result for any defined function (possibly allowing some inaccuracy if -ffast-math were specified).  I look through the POSIX spec, but couldn't find any place that mentioned an accuracy requirement.

to complete Joseph's answer:

* the IEEE 754 standard (even in its latest revision from 2019) does not
  require "correct rounding" for the mathematical functions (except for
  sqrt). More precisely it defines "Additional mathematical operations"
  which shall return correctly rounded results, but these operations are
  not mandatory. This means that mathematical libraries can do whatever
  they want, and in practice they do [1].

* for GNU libc, the current requirement is an error of at most 9 ulps
  (units in last place) for all rounding modes. (In some cases this is
  16 ulps instead.) Any error larger than that is considered as a bug.
  For j0f/y0f/j1f/y1f, the maximal error is millions of ulps for those
  functions in GNU libc 2.33 [1]. My patch reduces that maximal error
  to 9 ulps.

* there is some discussion in the C standard to reserve names like cr_sin
  for correctly rounded functions. I have a project to implement such
  functions, and contribute them to any interested mathematical library.
  If you are interested in joining that project, please tell me.

Best regards,
Paul

[1] https://members.loria.fr/PZimmermann/papers/accuracy.pdf
[2] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf (7.31.8)
[3] https://members.loria.fr/PZimmermann/papers/coremath.pdf

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-21  7:37   ` Paul Zimmermann
@ 2021-02-23 19:07     ` Michael Morrell
  2021-02-23 19:34       ` Joseph Myers
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Morrell @ 2021-02-23 19:07 UTC (permalink / raw)
  To: Paul Zimmermann; +Cc: libc-alpha

Paul,

You state that the IEEE 754 standard doesn't require correct rounding, but I don't see where it says that.  I see Section 9.2 ("Additional mathematical operations") and the list in Table 9.1 which seems to include most of the math functions in glibc (I notice that the Bessel functions like y0 aren't included) and these all must be correctly rounded.   I agree that a language may choose not to define all of the operations in 9.1, but that doesn't seem to give it the right to implement the function inaccurately.

 For functions not in Table 9.1 (e.g., erf, gamma, etc.) the IEEE 754 obviously doesn't impose any requirements but the C spec that you linked to doesn't seem to allow for any inaccuracies either.  For example, under section 7.12.8.1, it says "The erf functions compute the error function of x".   If there is no requirement to be correctly rounded, is a conforming implementation just allowed to always return 0 (which would be many ULPs off for most inputs)?

I also don't see a special case for "sqrt" that you indicate.  Why do you think that one is special?

By the way, I'm getting errors trying to access your PDFs that you list below.

A question about the cr_xxx functions.   Is the intent that the programmer would call these explicitly or perhaps the compiler would map "sin" to "cr_sin" if a flag like "-fcorrect-math" were used?  The latter would be friendlier I expect.

I really appreciate your help in improving my understanding here.

   Michael

-----Original Message-----
From: Paul Zimmermann <Paul.Zimmermann@inria.fr> 
Sent: Saturday, February 20, 2021 11:38 PM
To: Michael Morrell <mmorrell@tachyum.com>
Cc: libc-alpha@sourceware.org
Subject: Re: Fix the inaccuracy of j0f/y0f/j1f/y1f

       Dear Michael,

> I'm curious about something.  Where is it specified what the required accuracy is for a given math function?  Before I discovered the libm-test-ulps file, I would have expected a C library to be required to computed the exact result for any defined function (possibly allowing some inaccuracy if -ffast-math were specified).  I look through the POSIX spec, but couldn't find any place that mentioned an accuracy requirement.

to complete Joseph's answer:

* the IEEE 754 standard (even in its latest revision from 2019) does not
  require "correct rounding" for the mathematical functions (except for
  sqrt). More precisely it defines "Additional mathematical operations"
  which shall return correctly rounded results, but these operations are
  not mandatory. This means that mathematical libraries can do whatever
  they want, and in practice they do [1].

* for GNU libc, the current requirement is an error of at most 9 ulps
  (units in last place) for all rounding modes. (In some cases this is
  16 ulps instead.) Any error larger than that is considered as a bug.
  For j0f/y0f/j1f/y1f, the maximal error is millions of ulps for those
  functions in GNU libc 2.33 [1]. My patch reduces that maximal error
  to 9 ulps.

* there is some discussion in the C standard to reserve names like cr_sin
  for correctly rounded functions. I have a project to implement such
  functions, and contribute them to any interested mathematical library.
  If you are interested in joining that project, please tell me.

Best regards,
Paul

[1] https://members.loria.fr/PZimmermann/papers/accuracy.pdf
[2] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf (7.31.8) [3] https://members.loria.fr/PZimmermann/papers/coremath.pdf

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-23 19:07     ` Michael Morrell
@ 2021-02-23 19:34       ` Joseph Myers
  0 siblings, 0 replies; 10+ messages in thread
From: Joseph Myers @ 2021-02-23 19:34 UTC (permalink / raw)
  To: Michael Morrell; +Cc: Paul Zimmermann, libc-alpha

On Tue, 23 Feb 2021, Michael Morrell wrote:

> Paul,
> 
> You state that the IEEE 754 standard doesn't require correct rounding, 
> but I don't see where it says that.  I see Section 9.2 ("Additional 
> mathematical operations") and the list in Table 9.1 which seems to 
> include most of the math functions in glibc (I notice that the Bessel 
> functions like y0 aren't included) and these all must be correctly 
> rounded.  I agree that a language may choose not to define all of the 
> operations in 9.1, but that doesn't seem to give it the right to 
> implement the function inaccurately.

If you look at the current C2x draft N2596, 5.2.4.2.2 paragraph 8 says 
that the accuracy of the library functions is implementation-defined.  
Annex F says how C operations relate to operations defined in IEEE 754; 
the table in F.3 paragraph 1 includes an entry for sqrt, for example, so 
that corresponds to the IEEE squareRoot operation, but doesn't include 
most of the math.h functions; paragraph 20 gives the mapping for other 
functions and says that correct rounding is not required.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-19  9:02 Fix the inaccuracy of j0f/y0f/j1f/y1f Paul Zimmermann
  2021-02-19 16:44 ` Michael Morrell
@ 2021-02-24 18:59 ` Adhemerval Zanella
  2021-02-25 10:27   ` Paul Zimmermann
  1 sibling, 1 reply; 10+ messages in thread
From: Adhemerval Zanella @ 2021-02-24 18:59 UTC (permalink / raw)
  To: Paul Zimmermann, libc-alpha



On 19/02/2021 06:02, Paul Zimmermann wrote:
>        Hi,
> 
> I just sent a new version of patches to fix #14469, #14471, #14470, #14472.
> Following Wilco's advice, this new version uses the "reduce_large" function
> for argument reduction modulo pi/2.
> 
> If anyone is willing to perform exhaustive tests on some exotic platforms,
> some code is available on
> <https://members.loria.fr/PZimmermann/software/check_exhaustive-555.c>.
> Warning: it takes about one hour on a 4-core computer for each function
> and each rounding mode.
> 
> Paul
> 

Paul,

I have checked your set on different architectures (all of them after a
make regen-ulps):

aarch64-linux-gnu:
FAIL: math/test-float-j1
FAIL: math/test-float32-j1

powerpc-linux-gnu/powerpc-linux-gnu-power4:
FAIL: math/test-float-j1
FAIL: math/test-float32-j1
FAIL: math/test-ldouble-j1
FAIL: math/test-ldouble-y0
FAIL: math/test-ldouble-y1

powerpc64-linux-gnu:
FAIL: math/test-float-j1
FAIL: math/test-float32-j1
FAIL: math/test-ldouble-j1
FAIL: math/test-ldouble-y0
FAIL: math/test-ldouble-y1

s390x-linux-gnu:
FAIL: math/test-float-j1
FAIL: math/test-float32-j1

All of them are maximum ulps higher than what regen-ulps expects (below).
Interesting enough, for sparc64, sparc32, and armhf power4) the regenerated
maximum ulps are within 9 ulps.

Also, for powerpc-linux-gnu-power4, by removing the SET_RESTORE_ROUNDF
I see a slight improvement:

powerpc-linux-gnu-power4$ cat math/test-float-j1.out
testing float (without inline functions)
Failure: Test: j1 (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937245e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  9.0000
Failure: Test: j1_towardzero (0x6.874828p+4)
Result:
 is:         -5.85877605e-05  -0x1.eb7842p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.36557456e-11   0x1.800000p-35
 ulp       :  12.0000
 max.ulp   :  8.0000

Test suite completed:
  156 test cases plus 152 tests for exception flags and
    152 tests for errno executed.
  2 errors occurred.


---

aarch64-linux-gnu$ cat math/test-float-j1.out                                                                                                                              testing float (without inline functions)                                                                                                                                                                               Failure: Test: j1 (0x6.874828p+4)                                                                                                                                                                                      Result:                                                                                                                                                                                                                 is:         -5.85878515e-05  -0x1.eb7874p-15                                                                                                                                                                           should be:  -5.85878042e-05  -0x1.eb785ap-15                                                                                                                                                                           difference:  4.72937245e-11   0x1.a00000p-35                                                                                                                                                                           ulp       :  13.0000                                                                                                                                                                                                   max.ulp   :  9.0000                                                                                                                                                                                                   Failure: Test: j1_downward (0x6.874828p+4)                                                                                                                                                                             Result:                                                                                                                                                                                                                 is:         -5.85878516e-05  -0x1.eb7874p-15                                                                                                                                                                           should be:  -5.85878079e-05  -0x1.eb785cp-15                                                                                                                                                                           difference:  4.36557456e-11   0x1.800000p-35                                                                                                                                                                           ulp       :  12.0000                                                                                                                                                                                                   max.ulp   :  8.0000                                                                                                                                                                                                   Failure: Test: j1_towardzero (0x6.874828p+4)                                                                                                                                                                           Result:                                                                                                                                                                                                                 is:         -5.85878515e-05  -0x1.eb7874p-15                                                                                                                                                                           should be:  -5.85878042e-05  -0x1.eb785ap-15                                                                                                                                                                           difference:  4.72937244e-11   0x1.a00000p-35                                                                                                                                                                           ulp       :  13.0000                                                                                                                                                                                                   max.ulp   :  8.0000                                                                                                                                                                                                   Failure: Test: j1_upward (0x6.874828p+4)                                                                                                                                                                               Result:                                                                                                                                                                                                                 is:         -5.85878515e-05  -0x1.eb7874p-15                                                                                                                                                                           should be:  -5.85878042e-05  -0x1.eb785ap-15                                                                                                                                                                           difference:  4.72937245e-11   0x1.a00000p-35                                                                                                                                                                           ulp       :  13.0000                                                                                                                                                                                                   max.ulp   :  9.0000                                                                                                                                                                                                                                                                                                                                                                                                                          Test suite completed:                                                                                                                                                                                                    156 test cases plus 152 tests for exception flags and                                                                                                                                                                    152 tests for errno executed.                                                                                                                                                                                        4 errors occurred.                                                   

powerpc-linux-gnu-power4$ cat math/test-float-j1.out
testing float (without inline functions)
Failure: Test: j1 (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937245e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  9.0000
Failure: Test: j1_downward (0x6.874828p+4)
Result:
 is:         -5.85878516e-05  -0x1.eb7874p-15
 should be:  -5.85878079e-05  -0x1.eb785cp-15
 difference:  4.36557456e-11   0x1.800000p-35
 ulp       :  12.0000
 max.ulp   :  8.0000
Failure: Test: j1_towardzero (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937244e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  8.0000
Failure: Test: j1_upward (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937245e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  9.0000

Test suite completed:
  156 test cases plus 152 tests for exception flags and
    152 tests for errno executed.
  4 errors occurred.

s390x-linux-gnu> cat math/test-float-j1.out
testing float (without inline functions)
Failure: Test: j1 (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937245e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  9.0000
Failure: Test: j1_downward (0x6.874828p+4)
Result:
 is:         -5.85878516e-05  -0x1.eb7874p-15
 should be:  -5.85878079e-05  -0x1.eb785cp-15
 difference:  4.36557456e-11   0x1.800000p-35
 ulp       :  12.0000
 max.ulp   :  8.0000
Failure: Test: j1_towardzero (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937244e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  8.0000
Failure: Test: j1_upward (0x6.874828p+4)
Result:
 is:         -5.85878515e-05  -0x1.eb7874p-15
 should be:  -5.85878042e-05  -0x1.eb785ap-15
 difference:  4.72937245e-11   0x1.a00000p-35
 ulp       :  13.0000
 max.ulp   :  9.0000

Test suite completed:
  156 test cases plus 152 tests for exception flags and
    152 tests for errno executed.
  4 errors occurred.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-24 18:59 ` Adhemerval Zanella
@ 2021-02-25 10:27   ` Paul Zimmermann
  2021-02-25 11:24     ` Adhemerval Zanella
  0 siblings, 1 reply; 10+ messages in thread
From: Paul Zimmermann @ 2021-02-25 10:27 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

       Dear Adhemerval,

> I have checked your set on different architectures [...]

thank you, I can reproduce the failures on the GCC compile farm.
So far it is just due to some ranges around zeroes that are too
narrow. I guess it is due to the fact that computations on x86_64
are done using double extended precision. Btw is there a way to
disable that when building glibc?

Paul


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-25 10:27   ` Paul Zimmermann
@ 2021-02-25 11:24     ` Adhemerval Zanella
  2021-02-26  6:40       ` Paul Zimmermann
  0 siblings, 1 reply; 10+ messages in thread
From: Adhemerval Zanella @ 2021-02-25 11:24 UTC (permalink / raw)
  To: Paul Zimmermann; +Cc: libc-alpha



On 25/02/2021 07:27, Paul Zimmermann wrote:
>        Dear Adhemerval,
> 
>> I have checked your set on different architectures [...]
> 
> thank you, I can reproduce the failures on the GCC compile farm.
> So far it is just due to some ranges around zeroes that are too
> narrow. I guess it is due to the fact that computations on x86_64
> are done using double extended precision. Btw is there a way to
> disable that when building glibc?

Afaik -mfpmath=sse is the default for x86_64, so I am not sure the
extension precision on x86_64 s the culprit here.

I noted that cosf shows a better precision on x86_64 compared to
other architectures (based on glibc own ulp files), so it might
be the origin of the difference.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Fix the inaccuracy of j0f/y0f/j1f/y1f
  2021-02-25 11:24     ` Adhemerval Zanella
@ 2021-02-26  6:40       ` Paul Zimmermann
  0 siblings, 0 replies; 10+ messages in thread
From: Paul Zimmermann @ 2021-02-26  6:40 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

       Dear Adhemerval,

> Afaik -mfpmath=sse is the default for x86_64, so I am not sure the
> extension precision on x86_64 s the culprit here.

ok

> I noted that cosf shows a better precision on x86_64 compared to
> other architectures (based on glibc own ulp files), so it might
> be the origin of the difference.

indeed the Bessel functions depend in sincosf.

Paul

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-02-26  6:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-19  9:02 Fix the inaccuracy of j0f/y0f/j1f/y1f Paul Zimmermann
2021-02-19 16:44 ` Michael Morrell
2021-02-19 21:15   ` Joseph Myers
2021-02-21  7:37   ` Paul Zimmermann
2021-02-23 19:07     ` Michael Morrell
2021-02-23 19:34       ` Joseph Myers
2021-02-24 18:59 ` Adhemerval Zanella
2021-02-25 10:27   ` Paul Zimmermann
2021-02-25 11:24     ` Adhemerval Zanella
2021-02-26  6:40       ` Paul Zimmermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).