dp_fmax.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * IEEE754 floating point arithmetic
  4. * double precision: MIN{,A}.f
  5. * MIN : Scalar Floating-Point Minimum
  6. * MINA: Scalar Floating-Point argument with Minimum Absolute Value
  7. *
  8. * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
  9. * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
  10. *
  11. * MIPS floating point support
  12. * Copyright (C) 2015 Imagination Technologies, Ltd.
  13. * Author: Markos Chandras <markos.chandras@imgtec.com>
  14. */
  15. #include "ieee754dp.h"
  16. union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
  17. {
  18. COMPXDP;
  19. COMPYDP;
  20. EXPLODEXDP;
  21. EXPLODEYDP;
  22. FLUSHXDP;
  23. FLUSHYDP;
  24. ieee754_clearcx();
  25. switch (CLPAIR(xc, yc)) {
  26. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
  27. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
  28. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
  29. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
  30. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
  31. return ieee754dp_nanxcpt(y);
  32. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
  33. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
  34. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
  35. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
  36. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
  37. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
  38. return ieee754dp_nanxcpt(x);
  39. /*
  40. * Quiet NaN handling
  41. */
  42. /*
  43. * The case of both inputs quiet NaNs
  44. */
  45. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
  46. return x;
  47. /*
  48. * The cases of exactly one input quiet NaN (numbers
  49. * are here preferred as returned values to NaNs)
  50. */
  51. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
  52. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
  53. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
  54. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
  55. return x;
  56. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
  57. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
  58. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
  59. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
  60. return y;
  61. /*
  62. * Infinity and zero handling
  63. */
  64. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
  65. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
  66. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
  67. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
  68. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
  69. return xs ? y : x;
  70. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
  71. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
  72. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
  73. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
  74. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
  75. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
  76. return ys ? x : y;
  77. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
  78. return ieee754dp_zero(xs & ys);
  79. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
  80. DPDNORMX;
  81. fallthrough;
  82. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
  83. DPDNORMY;
  84. break;
  85. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
  86. DPDNORMX;
  87. }
  88. /* Finally get to do some computation */
  89. assert(xm & DP_HIDDEN_BIT);
  90. assert(ym & DP_HIDDEN_BIT);
  91. /* Compare signs */
  92. if (xs > ys)
  93. return y;
  94. else if (xs < ys)
  95. return x;
  96. /* Signs of inputs are equal, let's compare exponents */
  97. if (xs == 0) {
  98. /* Inputs are both positive */
  99. if (xe > ye)
  100. return x;
  101. else if (xe < ye)
  102. return y;
  103. } else {
  104. /* Inputs are both negative */
  105. if (xe > ye)
  106. return y;
  107. else if (xe < ye)
  108. return x;
  109. }
  110. /* Signs and exponents of inputs are equal, let's compare mantissas */
  111. if (xs == 0) {
  112. /* Inputs are both positive, with equal signs and exponents */
  113. if (xm <= ym)
  114. return y;
  115. return x;
  116. }
  117. /* Inputs are both negative, with equal signs and exponents */
  118. if (xm <= ym)
  119. return x;
  120. return y;
  121. }
  122. union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
  123. {
  124. COMPXDP;
  125. COMPYDP;
  126. EXPLODEXDP;
  127. EXPLODEYDP;
  128. FLUSHXDP;
  129. FLUSHYDP;
  130. ieee754_clearcx();
  131. switch (CLPAIR(xc, yc)) {
  132. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
  133. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
  134. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
  135. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
  136. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
  137. return ieee754dp_nanxcpt(y);
  138. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
  139. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
  140. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
  141. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
  142. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
  143. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
  144. return ieee754dp_nanxcpt(x);
  145. /*
  146. * Quiet NaN handling
  147. */
  148. /*
  149. * The case of both inputs quiet NaNs
  150. */
  151. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
  152. return x;
  153. /*
  154. * The cases of exactly one input quiet NaN (numbers
  155. * are here preferred as returned values to NaNs)
  156. */
  157. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
  158. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
  159. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
  160. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
  161. return x;
  162. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
  163. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
  164. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
  165. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
  166. return y;
  167. /*
  168. * Infinity and zero handling
  169. */
  170. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
  171. return ieee754dp_inf(xs & ys);
  172. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
  173. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
  174. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
  175. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
  176. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
  177. return x;
  178. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
  179. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
  180. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
  181. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
  182. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
  183. return y;
  184. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
  185. return ieee754dp_zero(xs & ys);
  186. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
  187. DPDNORMX;
  188. fallthrough;
  189. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
  190. DPDNORMY;
  191. break;
  192. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
  193. DPDNORMX;
  194. }
  195. /* Finally get to do some computation */
  196. assert(xm & DP_HIDDEN_BIT);
  197. assert(ym & DP_HIDDEN_BIT);
  198. /* Compare exponent */
  199. if (xe > ye)
  200. return x;
  201. else if (xe < ye)
  202. return y;
  203. /* Compare mantissa */
  204. if (xm < ym)
  205. return y;
  206. else if (xm > ym)
  207. return x;
  208. else if (xs == 0)
  209. return x;
  210. return y;
  211. }