[PATCH] math: support platforms with limited FP rounding or exception support

Andreas Jaeger aj@suse.com
Thu May 17 11:34:00 GMT 2012


On 05/15/2012 06:30 PM, Chris Metcalf wrote:
> For some tests, just claim that fetestexcept() always returns true,
> so the rest of the test can be compiled.
>
> For libm-test, provide known bogus values for unsupported rounding
> modes, so fesetround() will return failure.
>
> Elsewhere, just add some #ifdefs to avoid code that uses particular
> FP exceptions if the exceptions aren't supported.
> ---
> With this change (and a one-line ports change to provide a value
> for __FE_UNDEFINED) I can generate the libm-test-ulps file for tile,
> which I will check in after this is committed.
>
> I deleted the tile ulps values for the fma tests, since they were crazily
> bad; sounds like I need to wait for bug 13304 to be fixed for tile to
> have working fma().
>
>   ChangeLog               |    9 +++++++++
>   math/bug-nextafter.c    |    6 ++++++
>   math/bug-nexttoward.c   |    6 ++++++
>   math/libm-test.inc      |   16 ++++++++++++++++
>   math/test-fenv.c        |    6 ++++++
>   math/test-misc.c        |    6 ++++++
>   stdlib/bug-getcontext.c |    4 ++++
>   7 files changed, 53 insertions(+), 0 deletions(-)
>
> diff --git a/ChangeLog b/ChangeLog
> index 3554d9e..6722060 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,12 @@
> +2012-05-15  Chris Metcalf<cmetcalf@tilera.com>
> +
> +	* math/libm-test.c: Support platforms without multiple rounding modes.
> +	* math/bug-nextafter.c: Support platforms without FP exceptions.
> +	* math/bug-nexttoward.c: Likewise.
> +	* math/test-fenv.c: Likewise.
> +	* math/test-misc.c: Likewise.
> +	* stdlib/bug-getcontext.c: Likewise.
> +
>   2012-05-14  Andreas Jaeger<aj@suse.de>
>
>   	* sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Remove unused
> diff --git a/math/bug-nextafter.c b/math/bug-nextafter.c
> index 1d21841..055335d 100644
> --- a/math/bug-nextafter.c
> +++ b/math/bug-nextafter.c
> @@ -4,6 +4,12 @@
>   #include<stdlib.h>
>   #include<stdio.h>
>
> +#if !defined(FE_OVERFLOW)&&  !defined(FE_UNDERFLOW)
> +/* If there's no support for the exceptions this test is checking,
> +   then just return success and allow the test to be compiled.  */
> +#define fetestexcept(e) 1
Indent:
# define

> +#endif
> +
>   float zero = 0.0;
>   float inf = INFINITY;
>
> diff --git a/math/bug-nexttoward.c b/math/bug-nexttoward.c
> index ff57e5e..f21f8d6 100644
> --- a/math/bug-nexttoward.c
> +++ b/math/bug-nexttoward.c
> @@ -4,6 +4,12 @@
>   #include<stdlib.h>
>   #include<stdio.h>
>
> +#if !defined(FE_OVERFLOW)&&  !defined(FE_UNDERFLOW)
> +/* If there's no support for the exceptions this test is checking,
> +   then just return success and allow the test to be compiled.  */
> +#define fetestexcept(e) 1
Use
# define
> +#endif
> +
>   float zero = 0.0;
>   float inf = INFINITY;
>
> diff --git a/math/libm-test.inc b/math/libm-test.inc
> index 5a38dbf..47bbd5f 100644
> --- a/math/libm-test.inc
> +++ b/math/libm-test.inc
> @@ -128,6 +128,22 @@
>   #include<string.h>
>   #include<argp.h>
>
> +/* Allow platforms without all rounding modes to test properly,
> +   assuming they provide an __FE_UNDEFINED in<bits/fenv.h>  which
> +   causes fesetround() to return failure.  */
> +#ifndef FE_TONEAREST
> +# define FE_TONEAREST	__FE_UNDEFINED
> +#endif
> +#ifndef FE_TOWARDZERO
> +# define FE_TOWARDZERO	__FE_UNDEFINED
> +#endif
> +#ifndef FE_UPWARD
> +# define FE_UPWARD	__FE_UNDEFINED
> +#endif
> +#ifndef FE_DOWNWARD
> +# define FE_DOWNWARD	__FE_UNDEFINED
> +#endif
> +
>   /* Possible exceptions */
>   #define NO_EXCEPTION			0x0
>   #define INVALID_EXCEPTION		0x1
> diff --git a/math/test-fenv.c b/math/test-fenv.c
> index 39c7c33..19e5415 100644
> --- a/math/test-fenv.c
> +++ b/math/test-fenv.c
> @@ -664,9 +664,11 @@ feholdexcept_tests (void)
>       }
>   #endif
>     test_exceptions ("feholdexcept_tests 0 test", NO_EXC, 0);
> +#ifdef FE_INVALID
>     feraiseexcept (FE_INVALID);
>     test_exceptions ("feholdexcept_tests FE_INVALID test",
>   		   INVALID_EXC, 0);
> +#endif
>     res = feupdateenv (&saved);
>     if (res != 0)
>       {
> @@ -684,7 +686,9 @@ feholdexcept_tests (void)
>     test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test",
>   		   DIVBYZERO_EXC | INVALID_EXC, 0);
>     feclearexcept (FE_ALL_EXCEPT);
> +#ifdef FE_INVALID
>     feraiseexcept (FE_INVALID);
> +#endif
>   #if defined FE_TONEAREST&&  defined FE_UPWARD
>     res = fesetround (FE_UPWARD);
>     if (res != 0)
> @@ -708,9 +712,11 @@ feholdexcept_tests (void)
>       }
>   #endif
>     test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC, 0);
> +#ifdef FE_INEXACT
>     feraiseexcept (FE_INEXACT);
>     test_exceptions ("feholdexcept_tests FE_INEXACT test",
>   		   INEXACT_EXC, 0);
> +#endif
>     res = feupdateenv (&saved2);
>     if (res != 0)
>       {
> diff --git a/math/test-misc.c b/math/test-misc.c
> index c0fe5f7..5adb50b 100644
> --- a/math/test-misc.c
> +++ b/math/test-misc.c
> @@ -1186,12 +1186,14 @@ main (void)
>     (void)&f2;
>     feclearexcept (FE_ALL_EXCEPT);
>     f2 += f1;
> +#if defined(FE_OVERFLOW)&&  defined(FE_INEXACT)
>     int fe = fetestexcept (FE_ALL_EXCEPT);
>     if (fe != (FE_OVERFLOW | FE_INEXACT))
>       {
>         printf ("float overflow test failed: %x\n", fe);
>         result = 1;
>       }
> +#endif
>
>     volatile double d1 = DBL_MAX;
>     volatile double d2 = DBL_MAX / 2;
> @@ -1199,12 +1201,14 @@ main (void)
>     (void)&d2;
>     feclearexcept (FE_ALL_EXCEPT);
>     d2 += d1;
> +#if defined(FE_OVERFLOW)&&  defined(FE_INEXACT)
>     fe = fetestexcept (FE_ALL_EXCEPT);
>     if (fe != (FE_OVERFLOW | FE_INEXACT))
>       {
>         printf ("double overflow test failed: %x\n", fe);
>         result = 1;
>       }
> +#endif
>
>   #ifndef NO_LONG_DOUBLE
>     volatile long double ld1 = LDBL_MAX;
> @@ -1213,6 +1217,7 @@ main (void)
>     (void)&ld2;
>     feclearexcept (FE_ALL_EXCEPT);
>     ld2 += ld1;
> +#if defined(FE_OVERFLOW)&&  defined(FE_INEXACT)
>     fe = fetestexcept (FE_ALL_EXCEPT);
>     if (fe != (FE_OVERFLOW | FE_INEXACT))
>       {
> @@ -1220,6 +1225,7 @@ main (void)
>         result = 1;
>       }
>   #endif
Please intend the #endif above - together with the corresponding if.

We write nested #ifs like:
#if ....
# if
# else
# endif
#endif

> +#endif
>
>   #if !defined NO_LONG_DOUBLE&&  LDBL_MANT_DIG == 113
>     volatile long double ld3 = 0x1.0000000000010000000100000001p+1;
> diff --git a/stdlib/bug-getcontext.c b/stdlib/bug-getcontext.c
> index 745aa1f..7db49c8 100644
> --- a/stdlib/bug-getcontext.c
> +++ b/stdlib/bug-getcontext.c
> @@ -9,6 +9,9 @@
>   static int
>   do_test (void)
>   {
> +#if FE_ALL_EXCEPT == 0
> +  printf("Skipping test; no support for FP exceptions.\n");
> +#else
>     int except_mask =  FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW;
>     int status = feenableexcept (except_mask);
>
> @@ -41,6 +44,7 @@ do_test (void)
>
>     printf("\nAt end fegetexcept() returned %d, expected: %d.\n",
>   	 mask, except_mask);
> +#endif
>     return 0;
>   }
>

This is ok after fixing the indenting issues I mentioned.

thanks,
Andreas
-- 
  Andreas Jaeger aj@{suse.com,opensuse.org} Twitter/Identica: jaegerandi
   SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
    GF: Jeff Hawn,Jennifer Guild,Felix Imendörffer,HRB16746 (AG Nürnberg)
     GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126



More information about the Libc-alpha mailing list