1 /* Copyright (C) 2011-2016 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
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 #include <math.h>
20 #include "math_private.h"
21 #if defined(__UCLIBC_HAS_FENV__)
22 #include <errno.h>
23 #endif
24 
25 #if !defined __NO_LONG_DOUBLE_MATH
26 # if defined(__UCLIBC_HAS_FENV__)
27 static long double
28 __attribute__ ((noinline))
sysv_scalbl(long double x,long double fn)29 sysv_scalbl (long double x, long double fn)
30 {
31   long double z = (long double) __ieee754_scalb ((double) x, (double) fn);
32 
33   if (__builtin_expect (isinf (z), 0))
34     {
35       if (isfinite (x))
36 	return __kernel_standard_l (x, fn, 232); /* scalb overflow */
37       else
38 	__set_errno (ERANGE);
39     }
40   else if (__builtin_expect (z == 0.0L, 0) && z != x)
41     return __kernel_standard_l (x, fn, 233); /* scalb underflow */
42 
43   return z;
44 }
45 # endif /* __UCLIBC_HAS_FENV__ */
46 
47 /* Wrapper scalbl */
48 long double
scalbl(long double x,long double fn)49 scalbl (long double x, long double fn)
50 {
51 # if defined(__UCLIBC_HAS_FENV__)
52   if (__builtin_expect (_LIB_VERSION == _SVID_, 0))
53     return sysv_scalbl (x, fn);
54   else
55     {
56       long double z = (long double) __ieee754_scalb ((double) x, (double) fn);
57 
58       if (__builtin_expect (!isfinite (z) || z == 0.0L, 0))
59 	{
60 	  if (isnan (z))
61 	    {
62 	      if (!isnan (x) && !isnan (fn))
63 		__set_errno (EDOM);
64 	    }
65 	  else if (isinf (z))
66 	    {
67 	      if (!isinf (x) && !isinf (fn))
68 		__set_errno (ERANGE);
69 	    }
70 	  else
71 	    {
72 	      /* z == 0.  */
73 	      if (x != 0.0L && !isinf (fn))
74 		__set_errno (ERANGE);
75 	    }
76 	}
77       return z;
78     }
79 # else
80     return (long double) __ieee754_scalb ((double) x, (double) fn);
81 # endif /* __UCLIBC_HAS_FENV__ */
82 }
83 #endif /* __NO_LONG_DOUBLE_MATH */
84