1 | /* Implement __kernel_standard_l. |
---|---|

2 | Copyright (C) 2012-2019 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-barriers.h> |

35 | #include <math-svid-compat.h> |

36 | #include <fenv.h> |

37 | #include <float.h> |

38 | #include <errno.h> |

39 | |

40 | |

41 | #if LIBM_SVID_COMPAT |

42 | |

43 | static double zero = 0.0; |

44 | |

45 | /* Handle errors for a libm function as specified by TYPE (see |

46 | comments in k_standard.c for details), with arguments X and Y, |

47 | returning the appropriate return value for that function. */ |

48 | |

49 | long double |

50 | __kernel_standard_l (long double x, long double y, int type) |

51 | { |

52 | double dx, dy; |

53 | struct exception exc; |

54 | fenv_t env; |

55 | |

56 | feholdexcept (&env); |

57 | dx = x; |

58 | dy = y; |

59 | math_force_eval (dx); |

60 | math_force_eval (dy); |

61 | fesetenv (&env); |

62 | |

63 | switch (type) |

64 | { |

65 | case 221: |

66 | /* powl (x, y) overflow. */ |

67 | exc.arg1 = dx; |

68 | exc.arg2 = dy; |

69 | exc.type = OVERFLOW; |

70 | exc.name = (char *) "powl"; |

71 | if (_LIB_VERSION == _SVID_) |

72 | { |

73 | exc.retval = HUGE; |

74 | y *= 0.5; |

75 | if (x < zero && rintl (y) != y) |

76 | exc.retval = -HUGE; |

77 | } |

78 | else |

79 | { |

80 | exc.retval = HUGE_VAL; |

81 | y *= 0.5; |

82 | if (x < zero && rintl (y) != y) |

83 | exc.retval = -HUGE_VAL; |

84 | } |

85 | if (_LIB_VERSION == _POSIX_) |

86 | __set_errno (ERANGE); |

87 | else if (!matherr (&exc)) |

88 | __set_errno (ERANGE); |

89 | return exc.retval; |

90 | |

91 | case 222: |

92 | /* powl (x, y) underflow. */ |

93 | exc.arg1 = dx; |

94 | exc.arg2 = dy; |

95 | exc.type = UNDERFLOW; |

96 | exc.name = (char *) "powl"; |

97 | exc.retval = zero; |

98 | y *= 0.5; |

99 | if (x < zero && rintl (y) != y) |

100 | exc.retval = -zero; |

101 | if (_LIB_VERSION == _POSIX_) |

102 | __set_errno (ERANGE); |

103 | else if (!matherr (&exc)) |

104 | __set_errno (ERANGE); |

105 | return exc.retval; |

106 | |

107 | default: |

108 | return __kernel_standard (dx, dy, type); |

109 | } |

110 | } |

111 | #endif |

112 |