Message ID | mcrsjilrm16.fsf@dhcp-172-18-216-180.mtv.corp.google.com |
---|---|
State | New |
Headers | show |
Ian Lance Taylor <iant@google.com> writes: > On SVID-based systems, when certain math functions encounter an > exceptional condition they call a magic function named matherr. That > function is permitted to change the result which the math functions will > return. a program is permitted to provide its own version of matherr. > > Solaris works this way and at least the Solaris version of matherr does > not act as Go, or an ordinary interpretation of the function, would > expect. E.g., calling acos on an out-of-range value will return 0 > rather than NaN. Unfortunately, this breaks the libgo build on Solaris 8 and 9: /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c: In function 'matherr': /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: error: 'NAN' undeclared (first use in this function) /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: note: each undeclared identifier is reported only once for each function it appears in /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:68:28: error: 'INFINITY' undeclared (first use in this function) make[4]: *** [go-matherr.lo] Error 1 I couldn't find an appproprite replacement in the system headers. Rainer
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes: > Ian Lance Taylor <iant@google.com> writes: > >> On SVID-based systems, when certain math functions encounter an >> exceptional condition they call a magic function named matherr. That >> function is permitted to change the result which the math functions will >> return. a program is permitted to provide its own version of matherr. >> >> Solaris works this way and at least the Solaris version of matherr does >> not act as Go, or an ordinary interpretation of the function, would >> expect. E.g., calling acos on an out-of-range value will return 0 >> rather than NaN. > > Unfortunately, this breaks the libgo build on Solaris 8 and 9: > > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c: In function 'matherr': > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: error: 'NAN' undeclared (first use in this function) > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: note: each undeclared identifier is reported only once for each function it appears in > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:68:28: error: 'INFINITY' undeclared (first use in this function) > make[4]: *** [go-matherr.lo] Error 1 > > I couldn't find an appproprite replacement in the system headers. Hmmm, INFINITY and NAN are in C99. Does it work to do something like #ifndef INFINITY #define INFINITY (1.0 / 0.0) #endif #ifndef NAN #define NAN (0.0 / 0.0) #endif ? Another possibility for NAN would to call nan(), if that is available. Ian
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes: > Ian Lance Taylor <iant@google.com> writes: > >> On SVID-based systems, when certain math functions encounter an >> exceptional condition they call a magic function named matherr. That >> function is permitted to change the result which the math functions will >> return. a program is permitted to provide its own version of matherr. >> >> Solaris works this way and at least the Solaris version of matherr does >> not act as Go, or an ordinary interpretation of the function, would >> expect. E.g., calling acos on an out-of-range value will return 0 >> rather than NaN. > > Unfortunately, this breaks the libgo build on Solaris 8 and 9: > > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c: In function 'matherr': > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: error: 'NAN' undeclared (first use in this function) > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:38:17: note: each undeclared identifier is reported only once for each function it appears in > /vol/gcc/src/hg/trunk/local/libgo/runtime/go-matherr.c:68:28: error: 'INFINITY' undeclared (first use in this function) > make[4]: *** [go-matherr.lo] Error 1 > > I couldn't find an appproprite replacement in the system headers. Oh, wait, we can use __builtin_inf and __builtin_nan. Ian
diff -r 596217515a77 libgo/Makefile.am --- a/libgo/Makefile.am Wed Feb 08 14:20:19 2012 -0800 +++ b/libgo/Makefile.am Wed Feb 08 14:22:22 2012 -0800 @@ -422,6 +422,7 @@ runtime/go-map-index.c \ runtime/go-map-len.c \ runtime/go-map-range.c \ + runtime/go-matherr.c \ runtime/go-nanotime.c \ runtime/go-now.c \ runtime/go-new-map.c \ diff -r 596217515a77 libgo/configure.ac --- a/libgo/configure.ac Wed Feb 08 14:20:19 2012 -0800 +++ b/libgo/configure.ac Wed Feb 08 14:22:22 2012 -0800 @@ -478,6 +478,11 @@ CFLAGS="$CFLAGS_hold" LIBS="$LIBS_hold" +LIBS_hold="$LIBS" +LIBS="$LIBS $MATH_LIBS" +AC_CHECK_FUNCS(matherr) +LIBS="$LIBS_hold" + AC_CACHE_CHECK([for __sync_bool_compare_and_swap_4], [libgo_cv_func___sync_bool_compare_and_swap_4], [AC_LINK_IFELSE([ @@ -566,6 +571,16 @@ STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset} AC_SUBST(STRUCT_EPOLL_EVENT_FD_OFFSET) +dnl See if struct exception is defined in <math.h>. +AC_CHECK_TYPE([struct exception], +[libgo_has_struct_exception=yes], +[libgo_has_struct_exception=no], +[#include <math.h>]) +if test "$libgo_has_struct_exception" = "yes"; then + AC_DEFINE(HAVE_STRUCT_EXCEPTION, 1, + [Define to 1 if <math.h> defines struct exception]) +fi + dnl See whether setcontext changes the value of TLS variables. AC_CACHE_CHECK([whether setcontext clobbers TLS variables], [libgo_cv_lib_setcontext_clobbers_tls], diff -r 596217515a77 libgo/runtime/go-matherr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgo/runtime/go-matherr.c Wed Feb 08 14:22:22 2012 -0800 @@ -0,0 +1,88 @@ +/* go-matherr.c -- a Go version of the matherr function. + + Copyright 2012 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +/* The gccgo version of the math library calls libc functions. On + some systems, such as Solaris, those functions will call matherr on + exceptional conditions. This is a version of matherr appropriate + for Go, one which returns the values that the Go math library + expects. This is fine for pure Go programs. For mixed Go and C + programs this will be problematic if the C programs themselves use + matherr. Normally the C version of matherr will override this, and + the Go code will just have to cope. If this turns out to be too + problematic we can change to run pure Go code in the math library + on systems that use matherr. */ + +#include <math.h> +#include <stdint.h> + +#include "config.h" + +#if defined(HAVE_MATHERR) && defined(HAVE_STRUCT_EXCEPTION) + +#define PI 3.14159265358979323846264338327950288419716939937510582097494459 + +int +matherr (struct exception* e) +{ + const char *n; + + if (e->type != DOMAIN) + return 0; + + n = e->name; + if (__builtin_strcmp (n, "acos") == 0 + || __builtin_strcmp (n, "asin") == 0) + e->retval = NAN; + else if (__builtin_strcmp (n, "atan2") == 0) + { + if (e->arg1 == 0 && e->arg2 == 0) + { + double nz; + + nz = -0.0; + if (__builtin_memcmp (&e->arg2, &nz, sizeof (double)) != 0) + e->retval = e->arg1; + else + e->retval = copysign (PI, e->arg1); + } + else + return 0; + } + else if (__builtin_strcmp (n, "log") == 0 + || __builtin_strcmp (n, "log10") == 0) + e->retval = NAN; + else if (__builtin_strcmp (n, "pow") == 0) + { + if (e->arg1 < 0) + e->retval = NAN; + else if (e->arg1 == 0 && e->arg2 == 0) + e->retval = 1.0; + else if (e->arg1 == 0 && e->arg2 < 0) + { + double i; + + if (modf (e->arg2, &i) == 0 && ((int64_t) i & 1) == 1) + e->retval = copysign (INFINITY, e->arg1); + else + e->retval = INFINITY; + } + else + return 0; + } + else if (__builtin_strcmp (n, "sqrt") == 0) + { + if (e->arg1 < 0) + e->retval = NAN; + else + return 0; + } + else + return 0; + + return 1; +} + +#endif