rintf.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*++
  2. Copyright (c) 2017 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. rintf.c
  9. Abstract:
  10. This module implements support for the round to nearest integral math
  11. functions.
  12. Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  13. Developed at SunPro, a Sun Microsystems, Inc. business.
  14. Permission to use, copy, modify, and distribute this
  15. software is freely granted, provided that this notice
  16. is preserved.
  17. Author:
  18. Chris Stevens 5-Jan-2017
  19. Environment:
  20. User Mode C Library
  21. --*/
  22. //
  23. // ------------------------------------------------------------------- Includes
  24. //
  25. #include "../libcp.h"
  26. #include "mathp.h"
  27. #include <fenv.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. #define RINT_ADJUSTMENT_EXP_19 0x40000000
  32. #define RINT_ADJUSTMENT_EXP_18 0x80000000
  33. #define RINT_ADJUSTMENT_HIGH 0x00020000
  34. #define RINT_ADJUSTMENT_LOW 0x40000000
  35. #define RINT_NEGATIVE_EXP_HIGH_MASK 0xfffe0000
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. //
  40. // ----------------------------------------------- Internal Function Prototypes
  41. //
  42. //
  43. // -------------------------------------------------------------------- Globals
  44. //
  45. //
  46. // ------------------------------------------------------------------ Functions
  47. //
  48. LIBC_API
  49. long
  50. lrintf (
  51. float Value
  52. )
  53. /*++
  54. Routine Description:
  55. This routine round the given value to the nearest integer, using the
  56. current rounding direction.
  57. Arguments:
  58. Value - Supplies the value to round into an integral.
  59. Return Value:
  60. Returns the nearest integer value.
  61. Returns an undefined value if the integer is NaN or out of range.
  62. --*/
  63. {
  64. fenv_t Environment;
  65. long Result;
  66. feholdexcept(&Environment);
  67. Result = (long)rintf(Value);
  68. if (fetestexcept(FE_INVALID) != 0) {
  69. feclearexcept(FE_INEXACT);
  70. }
  71. feupdateenv(&Environment);
  72. return Result;
  73. }
  74. LIBC_API
  75. long long
  76. llrintf (
  77. float Value
  78. )
  79. /*++
  80. Routine Description:
  81. This routine round the given value to the nearest integer, using the
  82. current rounding direction.
  83. Arguments:
  84. Value - Supplies the value to round into an integral.
  85. Return Value:
  86. Returns the nearest integer value.
  87. Returns an undefined value if the integer is NaN or out of range.
  88. --*/
  89. {
  90. fenv_t Environment;
  91. long long Result;
  92. feholdexcept(&Environment);
  93. Result = (long long)rintf(Value);
  94. if (fetestexcept(FE_INVALID) != 0) {
  95. feclearexcept(FE_INEXACT);
  96. }
  97. feupdateenv(&Environment);
  98. return Result;
  99. }
  100. LIBC_API
  101. float
  102. nearbyintf (
  103. float Value
  104. )
  105. /*++
  106. Routine Description:
  107. This routine round the given value to the nearest integer, using the
  108. current rounding direction. This routine does not raise an inexact
  109. exception.
  110. Arguments:
  111. Value - Supplies the value to round into an integral.
  112. Return Value:
  113. Returns the nearest integral value in the direction of the current rounding
  114. mode.
  115. NaN if the given value is NaN.
  116. Returns the value itself for +/- 0 and +/- Infinity.
  117. --*/
  118. {
  119. fenv_t Environment;
  120. float Result;
  121. fegetenv(&Environment);
  122. Result = rintf(Value);
  123. fesetenv(&Environment);
  124. return Result;
  125. }
  126. LIBC_API
  127. float
  128. rintf (
  129. float Value
  130. )
  131. /*++
  132. Routine Description:
  133. This routine converts the given value into the nearest integral in the
  134. direction of the current rounding mode.
  135. Arguments:
  136. Value - Supplies the value to round into an integral.
  137. Return Value:
  138. Returns the nearest integral value in the direction of the current rounding
  139. mode.
  140. NaN if the given value is NaN.
  141. Returns the value itself for +/- 0 and +/- Infinity.
  142. --*/
  143. {
  144. LONG Exponent;
  145. LONG Word;
  146. FLOAT_PARTS Parts;
  147. LONG SignBit;
  148. volatile float VolatileValue;
  149. Parts.Float = Value;
  150. Word = Parts.Ulong;
  151. SignBit = (ULONG)Word >> FLOAT_SIGN_BIT_SHIFT;
  152. Exponent = ((Word & FLOAT_EXPONENT_MASK) >> FLOAT_EXPONENT_SHIFT) -
  153. FLOAT_EXPONENT_BIAS;
  154. if (Exponent < 23) {
  155. if (Exponent < 0) {
  156. if ((Word & ~FLOAT_SIGN_BIT) == 0) {
  157. return Value;
  158. }
  159. Parts.Ulong = Word;
  160. VolatileValue = ClFloatTwo23[SignBit] + Parts.Float;
  161. Parts.Float = VolatileValue - ClFloatTwo23[SignBit];
  162. Word = Parts.Ulong;
  163. Parts.Ulong = (Word & ~FLOAT_SIGN_BIT) |
  164. (SignBit << FLOAT_SIGN_BIT_SHIFT);
  165. return Parts.Float;
  166. }
  167. Parts.Ulong = Word;
  168. VolatileValue = ClFloatTwo23[SignBit] + Parts.Float;
  169. Parts.Float = VolatileValue - ClFloatTwo23[SignBit];
  170. return Parts.Float;
  171. }
  172. //
  173. // Check for infinite or NaN.
  174. //
  175. if (Exponent ==
  176. ((FLOAT_EXPONENT_MASK >> FLOAT_EXPONENT_SHIFT) - FLOAT_EXPONENT_BIAS)) {
  177. return Value + Value;
  178. }
  179. //
  180. // The value is integral.
  181. //
  182. return Value;
  183. }
  184. //
  185. // --------------------------------------------------------- Internal Functions
  186. //