logb.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #if defined(__ppc__)
  2. /*******************************************************************************
  3. * *
  4. * File logb.c, *
  5. * Functions logb. *
  6. * Implementation of logb for the PowerPC. *
  7. * *
  8. * Copyright © 1991 Apple Computer, Inc. All rights reserved. *
  9. * *
  10. * Written by Ali Sazegari, started on June 1991, *
  11. * *
  12. * August 26 1991: removed CFront Version 1.1d17 warnings. *
  13. * August 27 1991: no errors reported by the test suite. *
  14. * November 11 1991: changed CLASSEXTENDED to the macro CLASSIFY and *
  15. * + or - infinity to constants. *
  16. * November 18 1991: changed the macro CLASSIFY to CLASSEXTENDEDint to *
  17. * improve performance. *
  18. * February 07 1992: changed bit operations to macros ( object size is *
  19. * unchanged ). *
  20. * September24 1992: took the "#include support.h" out. *
  21. * December 03 1992: first rs/6000 port. *
  22. * August 30 1992: set the divide by zero for the zero argument case. *
  23. * October 05 1993: corrected the environment. *
  24. * October 17 1994: replaced all environmental functions with __setflm. *
  25. * May 28 1997: made speed improvements. *
  26. * April 30 2001: forst mac os x port using gcc. *
  27. * *
  28. ********************************************************************************
  29. * The C math library offers a similar function called "frexp". It is *
  30. * different in details from logb, but similar in spirit. This current *
  31. * implementation of logb follows the recommendation in IEEE Standard 854 *
  32. * which is different in its handling of denormalized numbers from the IEEE *
  33. * Standard 754. *
  34. *******************************************************************************/
  35. typedef union
  36. {
  37. struct {
  38. #if defined(__BIG_ENDIAN__)
  39. unsigned long int hi;
  40. unsigned long int lo;
  41. #else
  42. unsigned long int lo;
  43. unsigned long int hi;
  44. #endif
  45. } words;
  46. double dbl;
  47. } DblInHex;
  48. static const double twoTo52 = 4.50359962737049600e15; // 0x1p52
  49. static const double klTod = 4503601774854144.0; // 0x1.000008p52
  50. static const unsigned long int signMask = 0x80000000ul;
  51. static const DblInHex minusInf = {{ 0xFFF00000, 0x00000000 }};
  52. /*******************************************************************************
  53. ********************************************************************************
  54. * L O G B *
  55. ********************************************************************************
  56. *******************************************************************************/
  57. double logb ( double x )
  58. {
  59. DblInHex xInHex;
  60. long int shiftedExp;
  61. xInHex.dbl = x;
  62. shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20;
  63. if ( shiftedExp == 2047 )
  64. { // NaN or INF
  65. if ( ( ( xInHex.words.hi & signMask ) == 0 ) || ( x != x ) )
  66. return x; // NaN or +INF return x
  67. else
  68. return -x; // -INF returns +INF
  69. }
  70. if ( shiftedExp != 0 ) // normal number
  71. shiftedExp -= 1023; // unbias exponent
  72. else if ( x == 0.0 )
  73. { // zero
  74. xInHex.words.hi = 0x0UL; // return -infinity
  75. return ( minusInf.dbl );
  76. }
  77. else
  78. { // subnormal number
  79. xInHex.dbl *= twoTo52; // scale up
  80. shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20;
  81. shiftedExp -= 1075; // unbias exponent
  82. }
  83. if ( shiftedExp == 0 ) // zero result
  84. return ( 0.0 );
  85. else
  86. { // nonzero result
  87. xInHex.dbl = klTod;
  88. xInHex.words.lo += shiftedExp;
  89. return ( xInHex.dbl - klTod );
  90. }
  91. }
  92. #endif /* __ppc__ */