signbitd.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /* signbit() macro: Determine the sign bit of a floating-point number.
  2. Copyright (C) 2007-2023 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #include <config.h>
  14. /* Specification. */
  15. #include <math.h>
  16. #include <string.h>
  17. #include "isnand-nolibm.h"
  18. #include "float+.h"
  19. #ifdef gl_signbitd_OPTIMIZED_MACRO
  20. # undef gl_signbitd
  21. #endif
  22. int
  23. gl_signbitd (double arg)
  24. {
  25. #if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
  26. /* The use of a union to extract the bits of the representation of a
  27. 'long double' is safe in practice, despite of the "aliasing rules" of
  28. C99, because the GCC docs say
  29. "Even with '-fstrict-aliasing', type-punning is allowed, provided the
  30. memory is accessed through the union type."
  31. and similarly for other compilers. */
  32. # define NWORDS \
  33. ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
  34. union { double value; unsigned int word[NWORDS]; } m;
  35. m.value = arg;
  36. return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;
  37. #elif HAVE_COPYSIGN_IN_LIBC
  38. return copysign (1.0, arg) < 0;
  39. #else
  40. /* This does not do the right thing for NaN, but this is irrelevant for
  41. most use cases. */
  42. if (isnand (arg))
  43. return 0;
  44. if (arg < 0.0)
  45. return 1;
  46. else if (arg == 0.0)
  47. {
  48. /* Distinguish 0.0 and -0.0. */
  49. static double plus_zero = 0.0;
  50. double arg_mem = arg;
  51. return (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0);
  52. }
  53. else
  54. return 0;
  55. #endif
  56. }