sfrem.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  3. *
  4. * Floating-point emulation code
  5. * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2, or (at your option)
  10. * any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /*
  22. * BEGIN_DESC
  23. *
  24. * File:
  25. * @(#) pa/spmath/sfrem.c $Revision: 1.1 $
  26. *
  27. * Purpose:
  28. * Single Precision Floating-point Remainder
  29. *
  30. * External Interfaces:
  31. * sgl_frem(srcptr1,srcptr2,dstptr,status)
  32. *
  33. * Internal Interfaces:
  34. *
  35. * Theory:
  36. * <<please update with a overview of the operation of this file>>
  37. *
  38. * END_DESC
  39. */
  40. #include "float.h"
  41. #include "sgl_float.h"
  42. /*
  43. * Single Precision Floating-point Remainder
  44. */
  45. int
  46. sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
  47. sgl_floating_point * dstptr, unsigned int *status)
  48. {
  49. register unsigned int opnd1, opnd2, result;
  50. register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
  51. register boolean roundup = FALSE;
  52. opnd1 = *srcptr1;
  53. opnd2 = *srcptr2;
  54. /*
  55. * check first operand for NaN's or infinity
  56. */
  57. if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
  58. if (Sgl_iszero_mantissa(opnd1)) {
  59. if (Sgl_isnotnan(opnd2)) {
  60. /* invalid since first operand is infinity */
  61. if (Is_invalidtrap_enabled())
  62. return(INVALIDEXCEPTION);
  63. Set_invalidflag();
  64. Sgl_makequietnan(result);
  65. *dstptr = result;
  66. return(NOEXCEPTION);
  67. }
  68. }
  69. else {
  70. /*
  71. * is NaN; signaling or quiet?
  72. */
  73. if (Sgl_isone_signaling(opnd1)) {
  74. /* trap if INVALIDTRAP enabled */
  75. if (Is_invalidtrap_enabled())
  76. return(INVALIDEXCEPTION);
  77. /* make NaN quiet */
  78. Set_invalidflag();
  79. Sgl_set_quiet(opnd1);
  80. }
  81. /*
  82. * is second operand a signaling NaN?
  83. */
  84. else if (Sgl_is_signalingnan(opnd2)) {
  85. /* trap if INVALIDTRAP enabled */
  86. if (Is_invalidtrap_enabled())
  87. return(INVALIDEXCEPTION);
  88. /* make NaN quiet */
  89. Set_invalidflag();
  90. Sgl_set_quiet(opnd2);
  91. *dstptr = opnd2;
  92. return(NOEXCEPTION);
  93. }
  94. /*
  95. * return quiet NaN
  96. */
  97. *dstptr = opnd1;
  98. return(NOEXCEPTION);
  99. }
  100. }
  101. /*
  102. * check second operand for NaN's or infinity
  103. */
  104. if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
  105. if (Sgl_iszero_mantissa(opnd2)) {
  106. /*
  107. * return first operand
  108. */
  109. *dstptr = opnd1;
  110. return(NOEXCEPTION);
  111. }
  112. /*
  113. * is NaN; signaling or quiet?
  114. */
  115. if (Sgl_isone_signaling(opnd2)) {
  116. /* trap if INVALIDTRAP enabled */
  117. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  118. /* make NaN quiet */
  119. Set_invalidflag();
  120. Sgl_set_quiet(opnd2);
  121. }
  122. /*
  123. * return quiet NaN
  124. */
  125. *dstptr = opnd2;
  126. return(NOEXCEPTION);
  127. }
  128. /*
  129. * check second operand for zero
  130. */
  131. if (Sgl_iszero_exponentmantissa(opnd2)) {
  132. /* invalid since second operand is zero */
  133. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  134. Set_invalidflag();
  135. Sgl_makequietnan(result);
  136. *dstptr = result;
  137. return(NOEXCEPTION);
  138. }
  139. /*
  140. * get sign of result
  141. */
  142. result = opnd1;
  143. /*
  144. * check for denormalized operands
  145. */
  146. if (opnd1_exponent == 0) {
  147. /* check for zero */
  148. if (Sgl_iszero_mantissa(opnd1)) {
  149. *dstptr = opnd1;
  150. return(NOEXCEPTION);
  151. }
  152. /* normalize, then continue */
  153. opnd1_exponent = 1;
  154. Sgl_normalize(opnd1,opnd1_exponent);
  155. }
  156. else {
  157. Sgl_clear_signexponent_set_hidden(opnd1);
  158. }
  159. if (opnd2_exponent == 0) {
  160. /* normalize, then continue */
  161. opnd2_exponent = 1;
  162. Sgl_normalize(opnd2,opnd2_exponent);
  163. }
  164. else {
  165. Sgl_clear_signexponent_set_hidden(opnd2);
  166. }
  167. /* find result exponent and divide step loop count */
  168. dest_exponent = opnd2_exponent - 1;
  169. stepcount = opnd1_exponent - opnd2_exponent;
  170. /*
  171. * check for opnd1/opnd2 < 1
  172. */
  173. if (stepcount < 0) {
  174. /*
  175. * check for opnd1/opnd2 > 1/2
  176. *
  177. * In this case n will round to 1, so
  178. * r = opnd1 - opnd2
  179. */
  180. if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
  181. Sgl_all(result) = ~Sgl_all(result); /* set sign */
  182. /* align opnd2 with opnd1 */
  183. Sgl_leftshiftby1(opnd2);
  184. Sgl_subtract(opnd2,opnd1,opnd2);
  185. /* now normalize */
  186. while (Sgl_iszero_hidden(opnd2)) {
  187. Sgl_leftshiftby1(opnd2);
  188. dest_exponent--;
  189. }
  190. Sgl_set_exponentmantissa(result,opnd2);
  191. goto testforunderflow;
  192. }
  193. /*
  194. * opnd1/opnd2 <= 1/2
  195. *
  196. * In this case n will round to zero, so
  197. * r = opnd1
  198. */
  199. Sgl_set_exponentmantissa(result,opnd1);
  200. dest_exponent = opnd1_exponent;
  201. goto testforunderflow;
  202. }
  203. /*
  204. * Generate result
  205. *
  206. * Do iterative subtract until remainder is less than operand 2.
  207. */
  208. while (stepcount-- > 0 && Sgl_all(opnd1)) {
  209. if (Sgl_isnotlessthan(opnd1,opnd2))
  210. Sgl_subtract(opnd1,opnd2,opnd1);
  211. Sgl_leftshiftby1(opnd1);
  212. }
  213. /*
  214. * Do last subtract, then determine which way to round if remainder
  215. * is exactly 1/2 of opnd2
  216. */
  217. if (Sgl_isnotlessthan(opnd1,opnd2)) {
  218. Sgl_subtract(opnd1,opnd2,opnd1);
  219. roundup = TRUE;
  220. }
  221. if (stepcount > 0 || Sgl_iszero(opnd1)) {
  222. /* division is exact, remainder is zero */
  223. Sgl_setzero_exponentmantissa(result);
  224. *dstptr = result;
  225. return(NOEXCEPTION);
  226. }
  227. /*
  228. * Check for cases where opnd1/opnd2 < n
  229. *
  230. * In this case the result's sign will be opposite that of
  231. * opnd1. The mantissa also needs some correction.
  232. */
  233. Sgl_leftshiftby1(opnd1);
  234. if (Sgl_isgreaterthan(opnd1,opnd2)) {
  235. Sgl_invert_sign(result);
  236. Sgl_subtract((opnd2<<1),opnd1,opnd1);
  237. }
  238. /* check for remainder being exactly 1/2 of opnd2 */
  239. else if (Sgl_isequal(opnd1,opnd2) && roundup) {
  240. Sgl_invert_sign(result);
  241. }
  242. /* normalize result's mantissa */
  243. while (Sgl_iszero_hidden(opnd1)) {
  244. dest_exponent--;
  245. Sgl_leftshiftby1(opnd1);
  246. }
  247. Sgl_set_exponentmantissa(result,opnd1);
  248. /*
  249. * Test for underflow
  250. */
  251. testforunderflow:
  252. if (dest_exponent <= 0) {
  253. /* trap if UNDERFLOWTRAP enabled */
  254. if (Is_underflowtrap_enabled()) {
  255. /*
  256. * Adjust bias of result
  257. */
  258. Sgl_setwrapped_exponent(result,dest_exponent,unfl);
  259. *dstptr = result;
  260. /* frem is always exact */
  261. return(UNDERFLOWEXCEPTION);
  262. }
  263. /*
  264. * denormalize result or set to signed zero
  265. */
  266. if (dest_exponent >= (1 - SGL_P)) {
  267. Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
  268. }
  269. else {
  270. Sgl_setzero_exponentmantissa(result);
  271. }
  272. }
  273. else Sgl_set_exponent(result,dest_exponent);
  274. *dstptr = result;
  275. return(NOEXCEPTION);
  276. }