1 /* Implement __kernel_standard_l.
2    Copyright (C) 2012-2016 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.
18 
19    Parts based on k_standard.c from fdlibm: */
20 
21 /* @(#)k_standard.c 5.1 93/09/24 */
22 /*
23  * ====================================================
24  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
25  *
26  * Developed at SunPro, a Sun Microsystems, Inc. business.
27  * Permission to use, copy, modify, and distribute this
28  * software is freely granted, provided that this notice
29  * is preserved.
30  * ====================================================
31  */
32 
33 #include <math.h>
34 #include "math_private.h"
35 #include <fenv.h>
36 #include <float.h>
37 #include <errno.h>
38 
39 
40 static double zero = 0.0;
41 
42 /* Handle errors for a libm function as specified by TYPE (see
43    comments in k_standard.c for details), with arguments X and Y,
44    returning the appropriate return value for that function.  */
45 
46 long double
__kernel_standard_l(long double x,long double y,int type)47 __kernel_standard_l (long double x, long double y, int type)
48 {
49   double dx, dy;
50   struct exception exc;
51   fenv_t env;
52 
53   feholdexcept (&env);
54   dx = x;
55   dy = y;
56   math_force_eval (dx);
57   math_force_eval (dy);
58   fesetenv (&env);
59 
60   switch (type)
61     {
62     case 221:
63       /* powl (x, y) overflow.  */
64       exc.arg1 = dx;
65       exc.arg2 = dy;
66       exc.type = OVERFLOW;
67       exc.name = (char *) "powl";
68       if (_LIB_VERSION == _SVID_)
69 	{
70 	  exc.retval = HUGE;
71 	  y *= 0.5;
72 	  if (x < zero && rint (y) != y)
73 	    exc.retval = -HUGE;
74 	}
75       else
76 	{
77 	  exc.retval = HUGE_VAL;
78 	  y *= 0.5;
79 	  if (x < zero && rint (y) != y)
80 	    exc.retval = -HUGE_VAL;
81 	}
82       if (_LIB_VERSION == _POSIX_)
83 	__set_errno (ERANGE);
84       else if (!matherr (&exc))
85 	__set_errno (ERANGE);
86       return exc.retval;
87 
88     case 222:
89       /* powl (x, y) underflow.  */
90       exc.arg1 = dx;
91       exc.arg2 = dy;
92       exc.type = UNDERFLOW;
93       exc.name = (char *) "powl";
94       exc.retval = zero;
95       y *= 0.5;
96       if (x < zero && rint (y) != y)
97 	exc.retval = -zero;
98       if (_LIB_VERSION == _POSIX_)
99 	__set_errno (ERANGE);
100       else if (!matherr (&exc))
101 	__set_errno (ERANGE);
102       return exc.retval;
103 
104     default:
105       return __kernel_standard (dx, dy, type);
106     }
107 }
108