w_scalbl.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <math.h>
  16. #include "math_private.h"
  17. #if defined(__UCLIBC_HAS_FENV__)
  18. #include <errno.h>
  19. #endif
  20. #if !defined __NO_LONG_DOUBLE_MATH
  21. # if defined(__UCLIBC_HAS_FENV__)
  22. static long double
  23. __attribute__ ((noinline))
  24. sysv_scalbl (long double x, long double fn)
  25. {
  26. long double z = (long double) __ieee754_scalb ((double) x, (double) fn);
  27. if (__builtin_expect (isinf (z), 0))
  28. {
  29. if (isfinite (x))
  30. return __kernel_standard_l (x, fn, 232); /* scalb overflow */
  31. else
  32. __set_errno (ERANGE);
  33. }
  34. else if (__builtin_expect (z == 0.0L, 0) && z != x)
  35. return __kernel_standard_l (x, fn, 233); /* scalb underflow */
  36. return z;
  37. }
  38. # endif /* __UCLIBC_HAS_FENV__ */
  39. /* Wrapper scalbl */
  40. long double
  41. scalbl (long double x, long double fn)
  42. {
  43. # if defined(__UCLIBC_HAS_FENV__)
  44. if (__builtin_expect (_LIB_VERSION == _SVID_, 0))
  45. return sysv_scalbl (x, fn);
  46. else
  47. {
  48. long double z = (long double) __ieee754_scalb ((double) x, (double) fn);
  49. if (__builtin_expect (!isfinite (z) || z == 0.0L, 0))
  50. {
  51. if (isnan (z))
  52. {
  53. if (!isnan (x) && !isnan (fn))
  54. __set_errno (EDOM);
  55. }
  56. else if (isinf (z))
  57. {
  58. if (!isinf (x) && !isinf (fn))
  59. __set_errno (ERANGE);
  60. }
  61. else
  62. {
  63. /* z == 0. */
  64. if (x != 0.0L && !isinf (fn))
  65. __set_errno (ERANGE);
  66. }
  67. }
  68. return z;
  69. }
  70. # else
  71. return (long double) __ieee754_scalb ((double) x, (double) fn);
  72. # endif /* __UCLIBC_HAS_FENV__ */
  73. }
  74. #endif /* __NO_LONG_DOUBLE_MATH */