Closed kargl closed 3 years ago
Here's the patch that was used to restore STRICT_ASSIGN().
diff --git a/src/math_private.h b/src/math_private.h index 17027d6..dcfe96f 100644 --- a/src/math_private.h +++ b/src/math_private.h @@ -203,10 +203,10 @@ do { \ } while (0) +#ifndef __FreeBSD__ //VBS #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) - -/* VBS +#else #ifdef FLT_EVAL_METHOD // Attempt to get strict C99 semantics for assignment with non-C99 compilers. #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 @@ -215,7 +215,7 @@ do { \ #define STRICT_ASSIGN(type, lval, rval) do { \ volatile type __lval; \ \ - if (sizeof(type) >= sizeof(double)) \ + if (sizeof(type) >= sizeof(long double)) \ (lval) = (rval); \ else { \ __lval = (rval); \ @@ -224,7 +224,7 @@ do { \ } while (0) #endif #endif -*/ +#endif /* * Common routine to process the arguments to nan(), nanf(), and nanl().
Having now tested exp2(x), it is clear that the STRICT_ASSIGN() macro in math_private.h should be restored to its definition when inherited from FreeBSD. It is needed for proper rounding. Testing 5 million values in the interval [1,8] with FreeBSD libm returns
./tlibm_libm -d -N 5 exp2 Interval tested for exp2: [1,8] count: 5000000 xm = 5.7284883456976692e+00, /* 0x4016e9f8, 0xd951278f */ libm = 5.3020866609967030e+01, /* 0x404a82ab, 0xc1cfb182 */ mpfr = 5.3020866609967037e+01, /* 0x404a82ab, 0xc1cfb183 */ ULP = 0.50264
The result with OpenLibm with no changes gives
./tlibm_olibm -d -N 5 exp2 Interval tested for exp2: [1,8] count: 5000000 xm = 6.9980477996095596e+00, /* 0x401bfe00, 0x3e0cabd9 */ libm = 1.2800008203401148e+02, /* 0x40600000, 0xac09acb0 */ mpfr = 1.2782691237307291e+02, /* 0x405ff4ec, 0x21dfc061 */ ULP = 12185731569919.41602
@kargl Can you open a PR here?
It would be great to get the accumulated improvements from msun back into openlibm, but it is far from easy to do something like that.
Viral, I'm not sure what you mean by opening a PR? Isn't this issues/215 a PR? There is a patch in my Sep 8, 2020 comment. [edited] PR means Problem Report to me. Do you mean Pull Request? Have no idea how to do that.
Haha - yes, I meant a Pull Request. I can convert your patch into a PR if you are not familiar with the process on github.
Testing openlibm's single argument float functions on i686-*-freebsd has revealed a significant problem with accuracy; especially for exp2f(). In the following, ULP1 is the max ULP recorded from exhaustive testing in the indicated interval when openlibm is built without change on i686-*-freebsd. ULP2 is recorded when STRICT_ASSIGN() in math_private.h is restored its original form obtained from FreeBSD. It is unclear why STRICT_ASSIGN() was changed. The starred (*) items in the table show the importance of volatile in STRICT_ASSIGN().
A deeper inspection of exp2f() shows the following results for the original unmodified openlibm.
After restoring STRICT_ASSIGN(), one has
Strictly (pun intended) speaking, this is an improvement. But, comparison exp2f() from FreeBSD libm shows
So, clearly openlibm is somewhat broken on i686-*-freebsd. This is attributed to the broken STRICT_ASSIGN(), and the use of -march=i686. If I change Make.inc to use -march=core2 or my CPU, then openlibm agrees with FreeBSD libm. A better method of choosing the -march seems to be desired.