w_scalb.c 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /***********************************************************************
  2. ** File: scalb.c
  3. **
  4. ** Contains: C source code for implementations of floating-point
  5. ** scalb functions defined in header <fp.h>. In
  6. ** particular, this file contains implementations of
  7. ** functions scalb and scalbl for double and long double
  8. ** formats on PowerPC platforms.
  9. **
  10. ** Written by: Jon Okada, SANEitation Engineer, ext. 4-4838
  11. **
  12. ** Copyright: © 1992 by Apple Computer, Inc., all rights reserved
  13. **
  14. ** Change History ( most recent first ):
  15. **
  16. ** 28 May 97 ali made an speed improvement for large n,
  17. ** removed scalbl.
  18. ** 12 Dec 92 JPO First created.
  19. **
  20. ***********************************************************************/
  21. #include <math.h>
  22. #include <endian.h>
  23. typedef union
  24. {
  25. struct {
  26. #if (__BYTE_ORDER == __BIG_ENDIAN)
  27. unsigned long int hi;
  28. unsigned long int lo;
  29. #else
  30. unsigned long int lo;
  31. unsigned long int hi;
  32. #endif
  33. } words;
  34. double dbl;
  35. } DblInHex;
  36. static const double twoTo1023 = 8.988465674311579539e307; // 0x1p1023
  37. static const double twoToM1022 = 2.225073858507201383e-308; // 0x1p-1022
  38. /***********************************************************************
  39. double scalb( double x, long int n ) returns its argument x scaled
  40. by the factor 2^m. NaNs, signed zeros, and infinities are propagated
  41. by this function regardless of the value of n.
  42. Exceptions: OVERFLOW/INEXACT or UNDERFLOW inexact may occur;
  43. INVALID for signaling NaN inputs ( quiet NaN returned ).
  44. Calls: none.
  45. ***********************************************************************/
  46. libm_hidden_proto(scalb)
  47. #ifdef _SCALB_INT
  48. double scalb ( double x, int n )
  49. #else
  50. double scalb ( double x, double n )
  51. #endif
  52. {
  53. DblInHex xInHex;
  54. xInHex.words.lo = 0UL; // init. low half of xInHex
  55. if ( n > 1023 )
  56. { // large positive scaling
  57. if ( n > 2097 ) // huge scaling
  58. return ( ( x * twoTo1023 ) * twoTo1023 ) * twoTo1023;
  59. while ( n > 1023 )
  60. { // scale reduction loop
  61. x *= twoTo1023; // scale x by 2^1023
  62. n -= 1023; // reduce n by 1023
  63. }
  64. }
  65. else if ( n < -1022 )
  66. { // large negative scaling
  67. if ( n < -2098 ) // huge negative scaling
  68. return ( ( x * twoToM1022 ) * twoToM1022 ) * twoToM1022;
  69. while ( n < -1022 )
  70. { // scale reduction loop
  71. x *= twoToM1022; // scale x by 2^( -1022 )
  72. n += 1022; // incr n by 1022
  73. }
  74. }
  75. /*******************************************************************************
  76. * -1022 <= n <= 1023; convert n to double scale factor. *
  77. *******************************************************************************/
  78. xInHex.words.hi = ( ( unsigned long ) ( n + 1023 ) ) << 20;
  79. return ( x * xInHex.dbl );
  80. }
  81. libm_hidden_def(scalb)