frexpldexp.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #if defined(__ppc__)
  2. /*******************************************************************************
  3. * *
  4. * File frexpldexp.c, *
  5. * Functions frexp(x) and ldexp(x), *
  6. * Implementation of frexp and ldexp functions for the PowerPC. *
  7. * *
  8. * Copyright © 1991 Apple Computer, Inc. All rights reserved. *
  9. * *
  10. * Written by Ali Sazegari, started on January 1991, *
  11. * *
  12. * W A R N I N G: This routine expects a 64 bit double model. *
  13. * *
  14. * December03 1992: first rs6000 implementation. *
  15. * October 05 1993: added special cases for NaN and ° in frexp. *
  16. * May 27 1997: improved the performance of frexp by eliminating the *
  17. * switch statement. *
  18. * June 13 2001: (ram) rewrote frexp to eliminate calls to scalb and *
  19. * logb. *
  20. * *
  21. *******************************************************************************/
  22. #include <limits.h>
  23. #include <math.h>
  24. static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
  25. typedef union
  26. {
  27. struct {
  28. #if defined(__BIG_ENDIAN__)
  29. unsigned long int hi;
  30. unsigned long int lo;
  31. #else
  32. unsigned long int lo;
  33. unsigned long int hi;
  34. #endif
  35. } words;
  36. double dbl;
  37. } DblInHex;
  38. double ldexp ( double value, int exp )
  39. {
  40. if ( exp > SHRT_MAX )
  41. exp = SHRT_MAX;
  42. else if ( exp < -SHRT_MAX )
  43. exp = -SHRT_MAX;
  44. return scalb ( value, exp );
  45. }
  46. double frexp ( double value, int *eptr )
  47. {
  48. DblInHex argument;
  49. unsigned long int valueHead;
  50. argument.dbl = value;
  51. valueHead = argument.words.hi & 0x7fffffffUL; // valueHead <- |x|
  52. *eptr = 0;
  53. if ( valueHead >= 0x7ff00000 || ( valueHead | argument.words.lo ) == 0 )
  54. return value; // 0, inf, or NaN
  55. if ( valueHead < 0x00100000 )
  56. { // denorm
  57. argument.dbl = two54 * value;
  58. valueHead = argument.words.hi &0x7fffffff;
  59. *eptr = -54;
  60. }
  61. *eptr += ( valueHead >> 20 ) - 1022;
  62. argument.words.hi = ( argument.words.hi & 0x800fffff ) | 0x3fe00000;
  63. return argument.dbl;
  64. }
  65. #endif /* __ppc__ */