s_trunc.c 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #include <limits.h>
  2. #include <math.h>
  3. #include <endian.h>
  4. typedef union
  5. {
  6. struct {
  7. #if (__BYTE_ORDER == __BIG_ENDIAN)
  8. unsigned long int hi;
  9. unsigned long int lo;
  10. #else
  11. unsigned long int lo;
  12. unsigned long int hi;
  13. #endif
  14. } words;
  15. double dbl;
  16. } DblInHex;
  17. static const unsigned long int signMask = 0x80000000ul;
  18. static const double twoTo52 = 4503599627370496.0;
  19. /*******************************************************************************
  20. * *
  21. * The function trunc truncates its double argument to integral value *
  22. * and returns the result in double format. This function signals *
  23. * inexact if an ordered return value is not equal to the operand. *
  24. * *
  25. *******************************************************************************/
  26. libm_hidden_proto(trunc)
  27. double trunc ( double x )
  28. {
  29. DblInHex argument,OldEnvironment;
  30. register double y;
  31. register unsigned long int xhi;
  32. register long int target;
  33. argument.dbl = x;
  34. xhi = argument.words.hi & 0x7fffffffUL; // xhi <- high half of |x|
  35. target = ( argument.words.hi < signMask ); // flag positive sign
  36. if ( xhi < 0x43300000ul )
  37. /*******************************************************************************
  38. * Is |x| < 2.0^53? *
  39. *******************************************************************************/
  40. {
  41. if ( xhi < 0x3ff00000ul )
  42. /*******************************************************************************
  43. * Is |x| < 1.0? *
  44. *******************************************************************************/
  45. {
  46. if ( ( xhi | argument.words.lo ) != 0ul )
  47. { // raise deserved INEXACT
  48. __asm__ ("mffs %0" : "=f" (OldEnvironment.dbl));
  49. OldEnvironment.words.lo |= 0x02000000ul;
  50. __asm__ ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  51. }
  52. if ( target ) // return properly signed zero
  53. return ( 0.0 );
  54. else
  55. return ( -0.0 );
  56. }
  57. /*******************************************************************************
  58. * Is 1.0 < |x| < 2.0^52? *
  59. *******************************************************************************/
  60. if ( target )
  61. {
  62. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  63. if ( y > x )
  64. return ( y - 1.0 );
  65. else
  66. return ( y );
  67. }
  68. else
  69. {
  70. y = ( x - twoTo52 ) + twoTo52; // round at binary point.
  71. if ( y < x )
  72. return ( y + 1.0 );
  73. else
  74. return ( y );
  75. }
  76. }
  77. /*******************************************************************************
  78. * Is |x| >= 2.0^52 or x is a NaN. *
  79. *******************************************************************************/
  80. return ( x );
  81. }
  82. libm_hidden_def(trunc)