| /* 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 |