public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Man page issues: logb, significand, cbrt, log2, log10, exp10
@ 2024-03-04 15:29 Wilco Dijkstra
  2024-03-05  8:14 ` Paul Zimmermann
  0 siblings, 1 reply; 9+ messages in thread
From: Wilco Dijkstra @ 2024-03-04 15:29 UTC (permalink / raw)
  To: mwelinder; +Cc: 'GNU C Library', Adhemerval Zanella

Hi,

> FWIW, it appears that the author of the glibc exp10 implementation
> agrees with me that the implementation is sub-standard:

As Adhemerval pointed out, that was not the implementation used in GLIBC.
The version that was used, wasn't perfect, but still better than MUSL:

> Compare with musl:
>
> https://github.com/rofl0r/musl/blob/master/src/math/exp10.c

The worst case error of MUSL is 4.14 ULP vs 2.01 ULP of the old GLIBC exp10 [1].

And the new exp10 in GLIBC is 0.513 ULP [2].

As I pointed out in the PR, it would be reasonable for compilers to convert
pow (10, x) into exp10 (x) when it is known there is a good implementation
available - in GLIBC, exp10 is both faster and slightly more accurate than pow.

Cheers,
Wilco

[1] https://members.loria.fr/PZimmermann/papers/glibc238-20230921.pdf
[2] https://members.loria.fr/PZimmermann/papers/accuracy.pdf

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-04 15:29 Man page issues: logb, significand, cbrt, log2, log10, exp10 Wilco Dijkstra
@ 2024-03-05  8:14 ` Paul Zimmermann
  0 siblings, 0 replies; 9+ messages in thread
From: Paul Zimmermann @ 2024-03-05  8:14 UTC (permalink / raw)
  To: Wilco Dijkstra; +Cc: mwelinder, libc-alpha, adhemerval.zanella

       Hi Wilco,

> The worst case error of MUSL is 4.14 ULP vs 2.01 ULP of the old GLIBC exp10 [1].
> 
> And the new exp10 in GLIBC is 0.513 ULP [2].

yes the new exp10 is more accurate, nice work!

> As I pointed out in the PR, it would be reasonable for compilers to convert
> pow (10, x) into exp10 (x) when it is known there is a good implementation
> available - in GLIBC, exp10 is both faster and slightly more accurate than pow.

ok at compile time, but there should be a way to disable this optimization,
for example if you want to compare pow(10,x) and exp10(x). (At run time
such a conversion would slow down the critical path of pow.)

Paul

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-03  2:02       ` Morten Welinder
  2024-03-03  2:21         ` Alejandro Colomar
@ 2024-03-04 12:17         ` Adhemerval Zanella Netto
  1 sibling, 0 replies; 9+ messages in thread
From: Adhemerval Zanella Netto @ 2024-03-04 12:17 UTC (permalink / raw)
  To: Morten Welinder, Alejandro Colomar
  Cc: linux-man, libc-alpha, jsm-csl, newbie-02



On 02/03/24 23:02, Morten Welinder wrote:
> Thanks.
> 
> There is (was?) already crlibm out there.
> https://core-math.gitlabpages.inria.fr/  No particular need for wheel
> reinvention here.
> 
> FWIW, it appears that the author of the glibc exp10 implementation
> agrees with me that the implementation is sub-standard:
> 
> https://codebrowser.dev/glibc/glibc/math/e_exp10.c.html

This code was not used by any port and we recently removed to avoid this
very issue [1]. The exp10 implementation used by all ports
is at sysdeps/ieee754/dbl-64/e_exp10.c (i386/m68k are exceptions and my
plan to eventually remove this implementation in favor the generic
one [2]).

And the exp10 implementation was recently improved [3], with the
author suggesting the worst-case error in round-to- should be
nearest to 0.513 ULP (I am not sure if he did some empirical testing
to verify this value, at least with libm-test-ulps the resuts are
bounded to 2 ulp max).

> 
> /* This is a very stupid and inprecise implementation. It'll get
> replaced sometime (soon?). */
> return __ieee754_exp (M_LN10 * arg);
> 
> 
> Compare with musl:
> 
> https://github.com/rofl0r/musl/blob/master/src/math/exp10.c
> 

[1] https://sourceware.org/git/?p=glibc.git;a=commit;h=9c61303ebbdc6e727c89591bff3229c9fbfa438b
[2] https://sourceware.org/pipermail/libc-alpha/2024-January/154107.html
[3] https://sourceware.org/git/?p=glibc.git;a=commit;h=63d0a35d5f223a3f4b68190567b7d4d44545bce5

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-03 12:21             ` Alejandro Colomar
@ 2024-03-03 22:26               ` Morten Welinder
  0 siblings, 0 replies; 9+ messages in thread
From: Morten Welinder @ 2024-03-03 22:26 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Vincent Lefevre, linux-man, libc-alpha, jsm-csl, newbie-02

Sorry to be a bit of a pain.

Some testing says that the average error from exp10 is 300-500 times
bigger than the average error from pow(10,.). This is consistent
across a large range of arguments.

The maximum error from pow(10,.) in the samples is 1ulp (relative to a
reference rounded value, so the true error is likely less). The
maximum error from exp10 in the samples is 2ulp.

This is not surprising given that exp10 starts out by introducing a
rounding error due to the multiplication before the call to exp.

I didn't bother looking, but it is almost certainly true that there
are arguments for which exp10 is better than pow(10,.).  However, the
numbers below imply that such arguments are very rare compared to the
other way around.


-------------------------- average ----- max
Binade -7      exp10: 0.3378           1
Binade -7  pow(10,.): 0.0007           1
Binade -6      exp10: 0.3429           2
Binade -6  pow(10,.): 0.0007           1
Binade -5      exp10: 0.3532           2
Binade -5  pow(10,.): 0.0008           1
Binade -4      exp10: 0.3774           2
Binade -4  pow(10,.): 0.0008           1
Binade -3      exp10: 0.4402           2
Binade -3  pow(10,.): 0.0010           1
Binade -2      exp10: 0.4118           2
Binade -2  pow(10,.): 0.0009           1
Binade -1      exp10: 0.4228           2
Binade -1  pow(10,.): 0.0009           1
Binade  0      exp10: 0.4204           2
Binade  0  pow(10,.): 0.0009           1
Binade  1      exp10: 0.4221           2
Binade  1  pow(10,.): 0.0009           1
Binade  2      exp10: 0.4204           2
Binade  2  pow(10,.): 0.0009           1
Binade  3      exp10: 0.4222           2
Binade  3  pow(10,.): 0.0009           1
Binade  4      exp10: 0.4209           2
Binade  4  pow(10,.): 0.0009           1
Binade  5      exp10: 0.4200           2
Binade  5  pow(10,.): 0.0009           1
Binade  6      exp10: 0.4210           2
Binade  6  pow(10,.): 0.0009           1
Binade  7      exp10: 0.4210           2
Binade  7  pow(10,.): 0.0009           1

Notes:
1. Only positive arguments tested.
2. powl (long double version of pow) is used as a reference.  I
double-checked with a double-double version of pow (good to about
100ish bits) that this does not matter.




#define _GNU_SOURCE   1
#include <stdio.h>
#include <math.h>
#include <stdint.h>


static uint64_t
murmur64 (uint64_t h)
{
  h ^= h >> 33;
  h *= 0xff51afd7ed558ccdll;
  h ^= h >> 33;
  h *= 0xc4ceb9fe1a85ec53ll;
  h ^= h >> 33;
  return h;
}

static double
exp10ref (double x)
{
  volatile double y = (double)(powl (10.0l, x));
  return y;
}

static double
exp10viapow (double x)
{
  return pow (10, x);
}


static void
test_binade (int b, double (*f) (double), const char *funcname)
{
  uint64_t h = 0x0123456701234567ll;

  double ulps = 0;
  double mulp = 0;
  int N = 1000000;

  for (int i = 0; i < N; i++) {
    h = murmur64 (h);

    double x = ldexp ((h & 0xfffffffffffffll) | 0x10000000000000ll, b - 52);

    double y = f (x);
    double yref = exp10ref (x);
    double dy = fabs (y - yref);

    double ulp = dy / (nextafter (yref, INFINITY) - yref);
    ulps += ulp;
    if (ulp > mulp) mulp = ulp;
  }

  printf ("Binade %2d %10s: %6.4f  %10.0f\n",
      b, funcname, ulps / N, mulp);
}


int
main ()
{
  for (int b = -7; b <= 7; b++) {
    test_binade (b, exp10, "exp10");
    test_binade (b, exp10viapow, "pow(10,.)");
  }

  return 0;
}

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-03 11:46           ` Vincent Lefevre
@ 2024-03-03 12:21             ` Alejandro Colomar
  2024-03-03 22:26               ` Morten Welinder
  0 siblings, 1 reply; 9+ messages in thread
From: Alejandro Colomar @ 2024-03-03 12:21 UTC (permalink / raw)
  To: Vincent Lefevre, Morten Welinder, linux-man, libc-alpha, jsm-csl,
	newbie-02

[-- Attachment #1: Type: text/plain, Size: 1977 bytes --]

Hi Vincent,

On Sun, Mar 03, 2024 at 12:46:00PM +0100, Vincent Lefevre wrote:
> On 2024-03-03 03:21:26 +0100, Alejandro Colomar wrote:
> > Maybe just add some headers to core-math, and package it as a
> > standalone library.
> 
> The issue is that it is not portable yet.

Well, one could package it just to the systems to which it is portable,
if that's useful.  That's why a standalone library has more chances of
being available soon than glibc.  You'd need to make it portable (and
other things) to put it in glibc; but if you say "here's libcore-math,
avaiable only in XXX systems", you could get distros to distribute it
already.  And then provide headers that don't clash with glibc, such as
<core-math/*.h> or whatever.

> 
> > > FWIW, it appears that the author of the glibc exp10 implementation
> > > agrees with me that the implementation is sub-standard:
> > > 
> > > https://codebrowser.dev/glibc/glibc/math/e_exp10.c.html
> > > 
> > > /* This is a very stupid and inprecise implementation. It'll get
> > > replaced sometime (soon?). */
> > > return __ieee754_exp (M_LN10 * arg);
> > 
> > Hmmm.  Still, it's simple.  If pow(10, x) is strictly better, maybe one
> > can prove it and send a patch.  Or for something better, it'll take more
> > work.
> 
> If by "strictly better", you mean that for each input, it returns a
> result that is at least as accurate as the one returned by the above
> expression, then, probably no. The reason is that the rounding errors
> in the above expression may partly compensate on a random basis. So,
> for some proportion of inputs, you'll actually get an accurate result.
> And unless pow is designed to be almost correctly rounded, it will
> probably be sometimes worse.

Then glibc's current code is good, I guess.  It's simple, and works for
most programs.

Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-03  2:21         ` Alejandro Colomar
@ 2024-03-03 11:46           ` Vincent Lefevre
  2024-03-03 12:21             ` Alejandro Colomar
  0 siblings, 1 reply; 9+ messages in thread
From: Vincent Lefevre @ 2024-03-03 11:46 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Morten Welinder, linux-man, libc-alpha, jsm-csl, newbie-02

On 2024-03-03 03:21:26 +0100, Alejandro Colomar wrote:
> Hi Morten,
> 
> On Sat, Mar 02, 2024 at 09:02:24PM -0500, Morten Welinder wrote:
> > Thanks.
> > 
> > There is (was?) already crlibm out there.
> > https://core-math.gitlabpages.inria.fr/  No particular need for wheel
> > reinvention here.
> 
> crlibm doesn't seem to exist anymore.

The sources are still available at more non-official mirror, but
it is no longer maintained.

> Maybe just add some headers to core-math, and package it as a
> standalone library.

The issue is that it is not portable yet.

> > FWIW, it appears that the author of the glibc exp10 implementation
> > agrees with me that the implementation is sub-standard:
> > 
> > https://codebrowser.dev/glibc/glibc/math/e_exp10.c.html
> > 
> > /* This is a very stupid and inprecise implementation. It'll get
> > replaced sometime (soon?). */
> > return __ieee754_exp (M_LN10 * arg);
> 
> Hmmm.  Still, it's simple.  If pow(10, x) is strictly better, maybe one
> can prove it and send a patch.  Or for something better, it'll take more
> work.

If by "strictly better", you mean that for each input, it returns a
result that is at least as accurate as the one returned by the above
expression, then, probably no. The reason is that the rounding errors
in the above expression may partly compensate on a random basis. So,
for some proportion of inputs, you'll actually get an accurate result.
And unless pow is designed to be almost correctly rounded, it will
probably be sometimes worse.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-03  2:02       ` Morten Welinder
@ 2024-03-03  2:21         ` Alejandro Colomar
  2024-03-03 11:46           ` Vincent Lefevre
  2024-03-04 12:17         ` Adhemerval Zanella Netto
  1 sibling, 1 reply; 9+ messages in thread
From: Alejandro Colomar @ 2024-03-03  2:21 UTC (permalink / raw)
  To: Morten Welinder; +Cc: linux-man, libc-alpha, jsm-csl, newbie-02

[-- Attachment #1: Type: text/plain, Size: 985 bytes --]

Hi Morten,

On Sat, Mar 02, 2024 at 09:02:24PM -0500, Morten Welinder wrote:
> Thanks.
> 
> There is (was?) already crlibm out there.
> https://core-math.gitlabpages.inria.fr/  No particular need for wheel
> reinvention here.

crlibm doesn't seem to exist anymore.  Maybe just add some headers to
core-math, and package it as a standalone library.

> FWIW, it appears that the author of the glibc exp10 implementation
> agrees with me that the implementation is sub-standard:
> 
> https://codebrowser.dev/glibc/glibc/math/e_exp10.c.html
> 
> /* This is a very stupid and inprecise implementation. It'll get
> replaced sometime (soon?). */
> return __ieee754_exp (M_LN10 * arg);

Hmmm.  Still, it's simple.  If pow(10, x) is strictly better, maybe one
can prove it and send a patch.  Or for something better, it'll take more
work.


Have a lovely night!
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
  2024-03-02 21:54     ` Alejandro Colomar
@ 2024-03-03  2:02       ` Morten Welinder
  2024-03-03  2:21         ` Alejandro Colomar
  2024-03-04 12:17         ` Adhemerval Zanella Netto
  0 siblings, 2 replies; 9+ messages in thread
From: Morten Welinder @ 2024-03-03  2:02 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-man, libc-alpha, jsm-csl, newbie-02

Thanks.

There is (was?) already crlibm out there.
https://core-math.gitlabpages.inria.fr/  No particular need for wheel
reinvention here.

FWIW, it appears that the author of the glibc exp10 implementation
agrees with me that the implementation is sub-standard:

https://codebrowser.dev/glibc/glibc/math/e_exp10.c.html

/* This is a very stupid and inprecise implementation. It'll get
replaced sometime (soon?). */
return __ieee754_exp (M_LN10 * arg);


Compare with musl:

https://github.com/rofl0r/musl/blob/master/src/math/exp10.c

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

* Re: Man page issues: logb, significand, cbrt, log2, log10, exp10
       [not found]   ` <CANv4PNmMpiwfv5acr7U6VEVe7PE_AMTzkkpNoNN9jrtVzk_93Q@mail.gmail.com>
@ 2024-03-02 21:54     ` Alejandro Colomar
  2024-03-03  2:02       ` Morten Welinder
  0 siblings, 1 reply; 9+ messages in thread
From: Alejandro Colomar @ 2024-03-02 21:54 UTC (permalink / raw)
  To: Morten Welinder; +Cc: linux-man, libc-alpha, jsm-csl, newbie-02

[-- Attachment #1: Type: text/plain, Size: 2354 bytes --]

[CC += glibc, and those involved in the glibc bug report]

Hi Morten,

On Sat, Mar 02, 2024 at 04:17:36PM -0500, Morten Welinder wrote:
> I think what happens is that the compiler (not glibc) computes that
> exp10 for you and that the compiler happens to be more accurate.
> Here's what I get for the loop:
> 
>   for (int i = 1; i < 20; i++) {
>     printf ("%.20g\n", exp10 (i));
>   }
> 
> welinder@CarbonX1:~$ ./a.out
> 10
> 100
> 1000.0000000000001137
> 10000.000000000001819
> 100000
> 1000000
> 9999999.9999999981374
> 99999999.999999985099
> 999999999.99999988079
> 10000000000
> 100000000000
> 1000000000000
> 10000000000000
> 100000000000000
> 1000000000000000
> 10000000000000000
> 99999999999999984
> 1000000000000000000
> 10000000000000000000
> 
> Here's the bug report to go with this:
> https://sourceware.org/bugzilla/show_bug.cgi?id=28472
> Note comment 6.  It is clearly not a high-priority item for glibc.

Thanks for that link.

I agree with glibc that the standard specifies that these functions need
not be precise.  That lost precission probably results in better
performance.  Most programs won't care that these functions are
inaccurate.

If you need a correctly-rounded version of these functions, which is
perfectly reasonable, the right thing to ask is that libc implements
the cr_ version of these functions.

I also understand that adding functions to glibc isn't straightforward,
so glibc maintainers have reasons to not do it at the moment.  In fact,
lately I've been leaning towards thinking that libc is a huge monster to
which nothing more should be added, at all.

How about writing a new library --maybe call it libm-cr, maybe
libm-cr-pow, maybe libm-cr-exp10, depending on how extensive you want
it-- and add cr_exp10(3) to that library?  You could do that, and just
support the systems you need to support.  The effort would be certainly
smaller than adding the function to glibc.

Regarding the manual pages, I don't remember from the top of my head if
there's any page documenting that libm functions are imprecise.  I would
prefer documenting it in one place, rather than adding caveats to every
libm page.

> 
> M.

Have a lovely night!
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2024-03-05  8:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-04 15:29 Man page issues: logb, significand, cbrt, log2, log10, exp10 Wilco Dijkstra
2024-03-05  8:14 ` Paul Zimmermann
     [not found] <CANv4PNkVv_0eLgiSP3L_KfC-eZJaVLZ5AP1AGfD0GNrR5M4Hrg@mail.gmail.com>
     [not found] ` <ZeEnJB96mMC5bfBz@debian>
     [not found]   ` <CANv4PNmMpiwfv5acr7U6VEVe7PE_AMTzkkpNoNN9jrtVzk_93Q@mail.gmail.com>
2024-03-02 21:54     ` Alejandro Colomar
2024-03-03  2:02       ` Morten Welinder
2024-03-03  2:21         ` Alejandro Colomar
2024-03-03 11:46           ` Vincent Lefevre
2024-03-03 12:21             ` Alejandro Colomar
2024-03-03 22:26               ` Morten Welinder
2024-03-04 12:17         ` Adhemerval Zanella Netto

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).