copysignl.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* s_copysignl.c -- long double version of s_copysign.c.
  2. * Conversion to long double by Ulrich Drepper,
  3. * Cygnus Support, drepper@cygnus.com.
  4. */
  5. /*
  6. * ====================================================
  7. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  8. *
  9. * Developed at SunPro, a Sun Microsystems, Inc. business.
  10. * Permission to use, copy, modify, and distribute this
  11. * software is freely granted, provided that this notice
  12. * is preserved.
  13. * ====================================================
  14. */
  15. /*
  16. * copysignl(long double x, long double y)
  17. * copysignl(x,y) returns a value with the magnitude of x and
  18. * with the sign bit of y.
  19. */
  20. #include <endian.h>
  21. #include <stdint.h>
  22. #if __FLOAT_WORD_ORDER == BIG_ENDIAN
  23. typedef union
  24. {
  25. long double value;
  26. struct
  27. {
  28. int sign_exponent:16;
  29. unsigned int empty:16;
  30. uint32_t msw;
  31. uint32_t lsw;
  32. } parts;
  33. } ieee_long_double_shape_type;
  34. #endif
  35. #if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
  36. typedef union
  37. {
  38. long double value;
  39. struct
  40. {
  41. uint32_t lsw;
  42. uint32_t msw;
  43. int sign_exponent:16;
  44. unsigned int empty:16;
  45. } parts;
  46. } ieee_long_double_shape_type;
  47. #endif
  48. /* Get int from the exponent of a long double. */
  49. #define GET_LDOUBLE_EXP(exp,d) \
  50. do { \
  51. ieee_long_double_shape_type ge_u; \
  52. ge_u.value = (d); \
  53. (exp) = ge_u.parts.sign_exponent; \
  54. } while (0)
  55. /* Set exponent of a long double from an int. */
  56. #define SET_LDOUBLE_EXP(d,exp) \
  57. do { \
  58. ieee_long_double_shape_type se_u; \
  59. se_u.value = (d); \
  60. se_u.parts.sign_exponent = (exp); \
  61. (d) = se_u.value; \
  62. } while (0)
  63. long double copysignl(long double x, long double y);
  64. libc_hidden_proto(copysignl);
  65. long double copysignl(long double x, long double y)
  66. {
  67. uint32_t es1,es2;
  68. GET_LDOUBLE_EXP(es1,x);
  69. GET_LDOUBLE_EXP(es2,y);
  70. SET_LDOUBLE_EXP(x,(es1&0x7fff)|(es2&0x8000));
  71. return x;
  72. }
  73. libc_hidden_def(copysignl);