s_rint.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*******************************************************************************
  2. ** File: rndint.c
  3. **
  4. ** Contains: C source code for implementations of floating-point
  5. ** functions which round to integral value or format, as
  6. ** defined in header <fp.h>. In particular, this file
  7. ** contains implementations of functions rint, nearbyint,
  8. ** rinttol, round, roundtol, trunc, modf and modfl. This file
  9. ** targets PowerPC or Power platforms.
  10. **
  11. ** Written by: A. Sazegari, Apple AltiVec Group
  12. ** Created originally by Jon Okada, Apple Numerics Group
  13. **
  14. ** Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved
  15. **
  16. ** Change History (most recent first):
  17. **
  18. ** 13 Jul 01 ram replaced --setflm calls with inline assembly
  19. ** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm
  20. ** definition.
  21. ** 1. removed double_t, put in double for now.
  22. ** 2. removed iclass from nearbyint.
  23. ** 3. removed wrong comments intrunc.
  24. ** 4.
  25. ** 13 May 97 ali made performance improvements in rint, rinttol, roundtol
  26. ** and trunc by folding some of the taligent ideas into this
  27. ** implementation. nearbyint is faster than the one in taligent,
  28. ** rint is more elegant, but slower by %30 than the taligent one.
  29. ** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c
  30. ** 15 Sep 94 ali Major overhaul and performance improvements of all functions.
  31. ** 20 Jul 94 PAF New faster version
  32. ** 16 Jul 93 ali Added the modfl function.
  33. ** 18 Feb 93 ali Changed the return value of fenv functions
  34. ** feclearexcept and feraiseexcept to their new
  35. ** NCEG X3J11.1/93-001 definitions.
  36. ** 16 Dec 92 JPO Removed __itrunc implementation to a
  37. ** separate file.
  38. ** 15 Dec 92 JPO Added __itrunc implementation and modified
  39. ** rinttol to include conversion from double
  40. ** to long int format. Modified roundtol to
  41. ** call __itrunc.
  42. ** 10 Dec 92 JPO Added modf (double) implementation.
  43. ** 04 Dec 92 JPO First created.
  44. **
  45. *******************************************************************************/
  46. #include <limits.h>
  47. #include <math.h>
  48. #include <endian.h>
  49. #define SET_INVALID 0x01000000UL
  50. typedef union
  51. {
  52. struct {
  53. #if (__BYTE_ORDER == __BIG_ENDIAN)
  54. unsigned long int hi;
  55. unsigned long int lo;
  56. #else
  57. unsigned long int lo;
  58. unsigned long int hi;
  59. #endif
  60. } words;
  61. double dbl;
  62. } DblInHex;
  63. static const unsigned long int signMask = 0x80000000ul;
  64. static const double twoTo52 = 4503599627370496.0;
  65. static const double doubleToLong = 4503603922337792.0; // 2^52
  66. static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }};
  67. static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }};
  68. /*******************************************************************************
  69. * *
  70. * The function rint rounds its double argument to integral value *
  71. * according to the current rounding direction and returns the result in *
  72. * double format. This function signals inexact if an ordered return *
  73. * value is not equal to the operand. *
  74. * *
  75. ********************************************************************************
  76. * *
  77. * This function calls: fabs. *
  78. * *
  79. *******************************************************************************/
  80. /*******************************************************************************
  81. * First, an elegant implementation. *
  82. ********************************************************************************
  83. *
  84. *double rint ( double x )
  85. * {
  86. * double y;
  87. *
  88. * y = twoTo52.fval;
  89. *
  90. * if ( fabs ( x ) >= y ) // huge case is exact
  91. * return x;
  92. * if ( x < 0 ) y = -y; // negative case
  93. * y = ( x + y ) - y; // force rounding
  94. * if ( y == 0.0 ) // zero results mirror sign of x
  95. * y = copysign ( y, x );
  96. * return ( y );
  97. * }
  98. ********************************************************************************
  99. * Now a bit twidling version that is about %30 faster. *
  100. *******************************************************************************/
  101. double rint ( double x )
  102. {
  103. DblInHex argument;
  104. register double y;
  105. unsigned long int xHead;
  106. register long int target;
  107. argument.dbl = x;
  108. xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
  109. target = ( argument.words.hi < signMask ); // flags positive sign
  110. if ( xHead < 0x43300000ul )
  111. /*******************************************************************************
  112. * Is |x| < 2.0^52? *
  113. *******************************************************************************/
  114. {
  115. if ( xHead < 0x3ff00000ul )
  116. /*******************************************************************************
  117. * Is |x| < 1.0? *
  118. *******************************************************************************/
  119. {
  120. if ( target )
  121. y = ( x + twoTo52 ) - twoTo52; // round at binary point
  122. else
  123. y = ( x - twoTo52 ) + twoTo52; // round at binary point
  124. if ( y == 0.0 )
  125. { // fix sign of zero result
  126. if ( target )
  127. return ( 0.0 );
  128. else
  129. return ( -0.0 );
  130. }
  131. return y;
  132. }
  133. /*******************************************************************************
  134. * Is 1.0 < |x| < 2.0^52? *
  135. *******************************************************************************/
  136. if ( target )
  137. return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt.
  138. else
  139. return ( ( x - twoTo52 ) + twoTo52 );
  140. }
  141. /*******************************************************************************
  142. * |x| >= 2.0^52 or x is a NaN. *
  143. *******************************************************************************/
  144. return ( x );
  145. }