ceilfloor.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #if defined(__ppc__)
  2. /*******************************************************************************
  3. * *
  4. * File ceilfloor.c, *
  5. * Function ceil(x) and floor(x), *
  6. * Implementation of ceil and floor for the PowerPC. *
  7. * *
  8. * Copyright © 1991 Apple Computer, Inc. All rights reserved. *
  9. * *
  10. * Written by Ali Sazegari, started on November 1991, *
  11. * *
  12. * based on math.h, library code for Macintoshes with a 68881/68882 *
  13. * by Jim Thomas. *
  14. * *
  15. * W A R N I N G: This routine expects a 64 bit double model. *
  16. * *
  17. * December 03 1992: first rs6000 port. *
  18. * July 14 1993: comment changes and addition of #pragma fenv_access. *
  19. * May 06 1997: port of the ibm/taligent ceil and floor routines. *
  20. * April 11 2001: first port to os x using gcc. *
  21. * June 13 2001: replaced __setflm with in-line assembly *
  22. * *
  23. *******************************************************************************/
  24. #if !defined(__ppc__)
  25. #define asm(x)
  26. #endif
  27. static const double twoTo52 = 4503599627370496.0;
  28. static const unsigned long signMask = 0x80000000ul;
  29. typedef union
  30. {
  31. struct {
  32. #if defined(__BIG_ENDIAN__)
  33. unsigned long int hi;
  34. unsigned long int lo;
  35. #else
  36. unsigned long int lo;
  37. unsigned long int hi;
  38. #endif
  39. } words;
  40. double dbl;
  41. } DblInHex;
  42. /*******************************************************************************
  43. * Functions needed for the computation. *
  44. *******************************************************************************/
  45. /*******************************************************************************
  46. * Ceil(x) returns the smallest integer not less than x. *
  47. *******************************************************************************/
  48. double ceil ( double x )
  49. {
  50. DblInHex xInHex,OldEnvironment;
  51. register double y;
  52. register unsigned long int xhi;
  53. register int target;
  54. xInHex.dbl = x;
  55. xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x|
  56. target = ( xInHex.words.hi < signMask );
  57. if ( xhi < 0x43300000ul )
  58. /*******************************************************************************
  59. * Is |x| < 2.0^52? *
  60. *******************************************************************************/
  61. {
  62. if ( xhi < 0x3ff00000ul )
  63. /*******************************************************************************
  64. * Is |x| < 1.0? *
  65. *******************************************************************************/
  66. {
  67. if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case
  68. return ( x );
  69. else
  70. { // inexact case
  71. asm ("mffs %0" : "=f" (OldEnvironment.dbl));
  72. OldEnvironment.words.lo |= 0x02000000ul;
  73. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  74. if ( target )
  75. return ( 1.0 );
  76. else
  77. return ( -0.0 );
  78. }
  79. }
  80. /*******************************************************************************
  81. * Is 1.0 < |x| < 2.0^52? *
  82. *******************************************************************************/
  83. if ( target )
  84. {
  85. y = ( x + twoTo52 ) - twoTo52; // round at binary pt.
  86. if ( y < x )
  87. return ( y + 1.0 );
  88. else
  89. return ( y );
  90. }
  91. else
  92. {
  93. y = ( x - twoTo52 ) + twoTo52; // round at binary pt.
  94. if ( y < x )
  95. return ( y + 1.0 );
  96. else
  97. return ( y );
  98. }
  99. }
  100. /*******************************************************************************
  101. * |x| >= 2.0^52 or x is a NaN. *
  102. *******************************************************************************/
  103. return ( x );
  104. }
  105. /*******************************************************************************
  106. * Floor(x) returns the largest integer not greater than x. *
  107. *******************************************************************************/
  108. double floor ( double x )
  109. {
  110. DblInHex xInHex,OldEnvironment;
  111. register double y;
  112. register unsigned long int xhi;
  113. register long int target;
  114. xInHex.dbl = x;
  115. xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x|
  116. target = ( xInHex.words.hi < signMask );
  117. if ( xhi < 0x43300000ul )
  118. /*******************************************************************************
  119. * Is |x| < 2.0^52? *
  120. *******************************************************************************/
  121. {
  122. if ( xhi < 0x3ff00000ul )
  123. /*******************************************************************************
  124. * Is |x| < 1.0? *
  125. *******************************************************************************/
  126. {
  127. if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case
  128. return ( x );
  129. else
  130. { // inexact case
  131. asm ("mffs %0" : "=f" (OldEnvironment.dbl));
  132. OldEnvironment.words.lo |= 0x02000000ul;
  133. asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
  134. if ( target )
  135. return ( 0.0 );
  136. else
  137. return ( -1.0 );
  138. }
  139. }
  140. /*******************************************************************************
  141. * Is 1.0 < |x| < 2.0^52? *
  142. *******************************************************************************/
  143. if ( target )
  144. {
  145. y = ( x + twoTo52 ) - twoTo52; // round at binary pt.
  146. if ( y > x )
  147. return ( y - 1.0 );
  148. else
  149. return ( y );
  150. }
  151. else
  152. {
  153. y = ( x - twoTo52 ) + twoTo52; // round at binary pt.
  154. if ( y > x )
  155. return ( y - 1.0 );
  156. else
  157. return ( y );
  158. }
  159. }
  160. /*******************************************************************************
  161. * |x| >= 2.0^52 or x is a NaN. *
  162. *******************************************************************************/
  163. return ( x );
  164. }
  165. #endif /* __ppc__ */