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