github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/libgo/runtime/go-matherr.c (about)

     1  /* go-matherr.c -- a Go version of the matherr function.
     2  
     3     Copyright 2012 The Go Authors. All rights reserved.
     4     Use of this source code is governed by a BSD-style
     5     license that can be found in the LICENSE file.  */
     6  
     7  /* The gccgo version of the math library calls libc functions.  On
     8     some systems, such as Solaris, those functions will call matherr on
     9     exceptional conditions.  This is a version of matherr appropriate
    10     for Go, one which returns the values that the Go math library
    11     expects.  This is fine for pure Go programs.  For mixed Go and C
    12     programs this will be problematic if the C programs themselves use
    13     matherr.  Normally the C version of matherr will override this, and
    14     the Go code will just have to cope.  If this turns out to be too
    15     problematic we can change to run pure Go code in the math library
    16     on systems that use matherr.  */
    17  
    18  #include <math.h>
    19  #include <stdint.h>
    20  
    21  #include "config.h"
    22  
    23  #if defined(HAVE_MATHERR) && defined(HAVE_STRUCT_EXCEPTION)
    24  
    25  #define PI 3.14159265358979323846264338327950288419716939937510582097494459
    26  
    27  int
    28  matherr (struct exception* e)
    29  {
    30    const char *n;
    31  
    32    if (e->type != DOMAIN)
    33      return 0;
    34  
    35    n = e->name;
    36    if (__builtin_strcmp (n, "acos") == 0
    37        || __builtin_strcmp (n, "asin") == 0)
    38      e->retval = __builtin_nan ("");
    39    else if (__builtin_strcmp (n, "atan2") == 0)
    40      {
    41        if (e->arg1 == 0 && e->arg2 == 0)
    42  	{
    43  	  double nz;
    44  
    45  	  nz = -0.0;
    46  	  if (__builtin_memcmp (&e->arg2, &nz, sizeof (double)) != 0)
    47  	    e->retval = e->arg1;
    48  	  else
    49  	    e->retval = copysign (PI, e->arg1);
    50  	}
    51        else
    52  	return 0;
    53      }
    54    else if (__builtin_strcmp (n, "log") == 0
    55  	   || __builtin_strcmp (n, "log10") == 0)
    56      e->retval = __builtin_nan ("");
    57    else if (__builtin_strcmp (n, "pow") == 0)
    58      {
    59        if (e->arg1 < 0)
    60  	e->retval = __builtin_nan ("");
    61        else if (e->arg1 == 0 && e->arg2 == 0)
    62  	e->retval = 1.0;
    63        else if (e->arg1 == 0 && e->arg2 < 0)
    64  	{
    65  	  double i;
    66  
    67  	  if (modf (e->arg2, &i) == 0 && ((int64_t) i & 1) == 1)
    68  	    e->retval = copysign (__builtin_inf (), e->arg1);
    69  	  else
    70  	    e->retval = __builtin_inf ();
    71  	}
    72        else
    73  	return 0;
    74      }
    75    else if (__builtin_strcmp (n, "sqrt") == 0)
    76      {
    77        if (e->arg1 < 0)
    78  	e->retval = __builtin_nan ("");
    79        else
    80  	return 0;
    81      }
    82    else
    83      return 0;
    84  
    85    return 1;
    86  }
    87  
    88  #endif