minmaxf.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. minmaxf.c
  9. Abstract:
  10. This module implements fminf and fmaxf, which coupte the minimum and
  11. maximum of two values, respectively.
  12. Author:
  13. Evan Green 23-Mar-2017
  14. Environment:
  15. User Mode C Library
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "../libcp.h"
  21. #include "mathp.h"
  22. //
  23. // --------------------------------------------------------------------- Macros
  24. //
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. //
  32. // ----------------------------------------------- Internal Function Prototypes
  33. //
  34. //
  35. // -------------------------------------------------------------------- Globals
  36. //
  37. //
  38. // ------------------------------------------------------------------ Functions
  39. //
  40. LIBC_API
  41. float
  42. fminf (
  43. float FirstValue,
  44. float SecondValue
  45. )
  46. /*++
  47. Routine Description:
  48. This routine returns the minimum numeric value between the two given
  49. arguments. NaN arguments are treated as missing data. If one argument is
  50. NaN and the other is not, the numeric argument is returned.
  51. Arguments:
  52. FirstValue - Supplies the first value to consider.
  53. SecondValue - Supplies the second value to consider.
  54. Return Value:
  55. Returns the minimum of the two.
  56. --*/
  57. {
  58. FLOAT_PARTS FirstParts;
  59. FLOAT_PARTS SecondParts;
  60. FirstParts.Float = FirstValue;
  61. SecondParts.Float = SecondValue;
  62. //
  63. // Handle NaNs first.
  64. //
  65. if ((FirstParts.Ulong >> FLOAT_EXPONENT_SHIFT) == FLOAT_NAN_EXPONENT) {
  66. if ((FirstParts.Ulong & FLOAT_VALUE_MASK) != 0) {
  67. return SecondValue;
  68. }
  69. }
  70. if ((SecondParts.Ulong >> FLOAT_EXPONENT_SHIFT) == FLOAT_NAN_EXPONENT) {
  71. if ((SecondParts.Ulong & FLOAT_VALUE_MASK) != 0) {
  72. return FirstValue;
  73. }
  74. }
  75. //
  76. // Handle sign difference.
  77. //
  78. if (((FirstParts.Ulong ^ SecondParts.Ulong) & FLOAT_SIGN_BIT) != 0) {
  79. if ((FirstParts.Ulong & FLOAT_SIGN_BIT) != 0) {
  80. return SecondValue;
  81. }
  82. return FirstValue;
  83. }
  84. //
  85. // Okay, simply compare them.
  86. //
  87. if (FirstValue < SecondValue) {
  88. return FirstValue;
  89. }
  90. return SecondValue;
  91. }
  92. LIBC_API
  93. float
  94. fmaxf (
  95. float FirstValue,
  96. float SecondValue
  97. )
  98. /*++
  99. Routine Description:
  100. This routine returns the maximum numeric value between the two given
  101. arguments. NaN arguments are treated as missing data. If one argument is
  102. NaN and the other is not, the numeric argument is returned.
  103. Arguments:
  104. FirstValue - Supplies the first value to consider.
  105. SecondValue - Supplies the second value to consider.
  106. Return Value:
  107. Returns the maximum of the two.
  108. --*/
  109. {
  110. FLOAT_PARTS FirstParts;
  111. FLOAT_PARTS SecondParts;
  112. FirstParts.Float = FirstValue;
  113. SecondParts.Float = SecondValue;
  114. //
  115. // Handle NaNs first.
  116. //
  117. if ((FirstParts.Ulong >> FLOAT_EXPONENT_SHIFT) == FLOAT_NAN_EXPONENT) {
  118. if ((FirstParts.Ulong & FLOAT_VALUE_MASK) != 0) {
  119. return SecondValue;
  120. }
  121. }
  122. if ((SecondParts.Ulong >> FLOAT_EXPONENT_SHIFT) == FLOAT_NAN_EXPONENT) {
  123. if ((SecondParts.Ulong & FLOAT_VALUE_MASK) != 0) {
  124. return FirstValue;
  125. }
  126. }
  127. //
  128. // Handle sign difference.
  129. //
  130. if (((FirstParts.Ulong ^ SecondParts.Ulong) & FLOAT_SIGN_BIT) != 0) {
  131. if ((FirstParts.Ulong & FLOAT_SIGN_BIT) != 0) {
  132. return FirstValue;
  133. }
  134. return SecondValue;
  135. }
  136. //
  137. // Okay, simply compare them.
  138. //
  139. if (FirstValue > SecondValue) {
  140. return FirstValue;
  141. }
  142. return SecondValue;
  143. }
  144. //
  145. // --------------------------------------------------------- Internal Functions
  146. //