| /* 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 = __builtin_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 = __builtin_nan (""); | |
| else if (__builtin_strcmp (n, "pow") == 0) | |
| { | |
| if (e->arg1 < 0) | |
| e->retval = __builtin_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 (__builtin_inf (), e->arg1); | |
| else | |
| e->retval = __builtin_inf (); | |
| } | |
| else | |
| return 0; | |
| } | |
| else if (__builtin_strcmp (n, "sqrt") == 0) | |
| { | |
| if (e->arg1 < 0) | |
| e->retval = __builtin_nan (""); | |
| else | |
| return 0; | |
| } | |
| else | |
| return 0; | |
| return 1; | |
| } | |
| #endif |