dfrem.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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/dfrem.c $Revision: 1.1 $
  26. *
  27. * Purpose:
  28. * Double Precision Floating-point Remainder
  29. *
  30. * External Interfaces:
  31. * dbl_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 "dbl_float.h"
  42. /*
  43. * Double Precision Floating-point Remainder
  44. */
  45. int
  46. dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
  47. dbl_floating_point * dstptr, unsigned int *status)
  48. {
  49. register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
  50. register unsigned int resultp1, resultp2;
  51. register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
  52. register boolean roundup = FALSE;
  53. Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
  54. Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
  55. /*
  56. * check first operand for NaN's or infinity
  57. */
  58. if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
  59. if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
  60. if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
  61. /* invalid since first operand is infinity */
  62. if (Is_invalidtrap_enabled())
  63. return(INVALIDEXCEPTION);
  64. Set_invalidflag();
  65. Dbl_makequietnan(resultp1,resultp2);
  66. Dbl_copytoptr(resultp1,resultp2,dstptr);
  67. return(NOEXCEPTION);
  68. }
  69. }
  70. else {
  71. /*
  72. * is NaN; signaling or quiet?
  73. */
  74. if (Dbl_isone_signaling(opnd1p1)) {
  75. /* trap if INVALIDTRAP enabled */
  76. if (Is_invalidtrap_enabled())
  77. return(INVALIDEXCEPTION);
  78. /* make NaN quiet */
  79. Set_invalidflag();
  80. Dbl_set_quiet(opnd1p1);
  81. }
  82. /*
  83. * is second operand a signaling NaN?
  84. */
  85. else if (Dbl_is_signalingnan(opnd2p1)) {
  86. /* trap if INVALIDTRAP enabled */
  87. if (Is_invalidtrap_enabled())
  88. return(INVALIDEXCEPTION);
  89. /* make NaN quiet */
  90. Set_invalidflag();
  91. Dbl_set_quiet(opnd2p1);
  92. Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
  93. return(NOEXCEPTION);
  94. }
  95. /*
  96. * return quiet NaN
  97. */
  98. Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
  99. return(NOEXCEPTION);
  100. }
  101. }
  102. /*
  103. * check second operand for NaN's or infinity
  104. */
  105. if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
  106. if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
  107. /*
  108. * return first operand
  109. */
  110. Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
  111. return(NOEXCEPTION);
  112. }
  113. /*
  114. * is NaN; signaling or quiet?
  115. */
  116. if (Dbl_isone_signaling(opnd2p1)) {
  117. /* trap if INVALIDTRAP enabled */
  118. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  119. /* make NaN quiet */
  120. Set_invalidflag();
  121. Dbl_set_quiet(opnd2p1);
  122. }
  123. /*
  124. * return quiet NaN
  125. */
  126. Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
  127. return(NOEXCEPTION);
  128. }
  129. /*
  130. * check second operand for zero
  131. */
  132. if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
  133. /* invalid since second operand is zero */
  134. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  135. Set_invalidflag();
  136. Dbl_makequietnan(resultp1,resultp2);
  137. Dbl_copytoptr(resultp1,resultp2,dstptr);
  138. return(NOEXCEPTION);
  139. }
  140. /*
  141. * get sign of result
  142. */
  143. resultp1 = opnd1p1;
  144. /*
  145. * check for denormalized operands
  146. */
  147. if (opnd1_exponent == 0) {
  148. /* check for zero */
  149. if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
  150. Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
  151. return(NOEXCEPTION);
  152. }
  153. /* normalize, then continue */
  154. opnd1_exponent = 1;
  155. Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
  156. }
  157. else {
  158. Dbl_clear_signexponent_set_hidden(opnd1p1);
  159. }
  160. if (opnd2_exponent == 0) {
  161. /* normalize, then continue */
  162. opnd2_exponent = 1;
  163. Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
  164. }
  165. else {
  166. Dbl_clear_signexponent_set_hidden(opnd2p1);
  167. }
  168. /* find result exponent and divide step loop count */
  169. dest_exponent = opnd2_exponent - 1;
  170. stepcount = opnd1_exponent - opnd2_exponent;
  171. /*
  172. * check for opnd1/opnd2 < 1
  173. */
  174. if (stepcount < 0) {
  175. /*
  176. * check for opnd1/opnd2 > 1/2
  177. *
  178. * In this case n will round to 1, so
  179. * r = opnd1 - opnd2
  180. */
  181. if (stepcount == -1 &&
  182. Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
  183. /* set sign */
  184. Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
  185. /* align opnd2 with opnd1 */
  186. Dbl_leftshiftby1(opnd2p1,opnd2p2);
  187. Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
  188. opnd2p1,opnd2p2);
  189. /* now normalize */
  190. while (Dbl_iszero_hidden(opnd2p1)) {
  191. Dbl_leftshiftby1(opnd2p1,opnd2p2);
  192. dest_exponent--;
  193. }
  194. Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
  195. goto testforunderflow;
  196. }
  197. /*
  198. * opnd1/opnd2 <= 1/2
  199. *
  200. * In this case n will round to zero, so
  201. * r = opnd1
  202. */
  203. Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
  204. dest_exponent = opnd1_exponent;
  205. goto testforunderflow;
  206. }
  207. /*
  208. * Generate result
  209. *
  210. * Do iterative subtract until remainder is less than operand 2.
  211. */
  212. while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
  213. if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
  214. Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
  215. }
  216. Dbl_leftshiftby1(opnd1p1,opnd1p2);
  217. }
  218. /*
  219. * Do last subtract, then determine which way to round if remainder
  220. * is exactly 1/2 of opnd2
  221. */
  222. if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
  223. Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
  224. roundup = TRUE;
  225. }
  226. if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
  227. /* division is exact, remainder is zero */
  228. Dbl_setzero_exponentmantissa(resultp1,resultp2);
  229. Dbl_copytoptr(resultp1,resultp2,dstptr);
  230. return(NOEXCEPTION);
  231. }
  232. /*
  233. * Check for cases where opnd1/opnd2 < n
  234. *
  235. * In this case the result's sign will be opposite that of
  236. * opnd1. The mantissa also needs some correction.
  237. */
  238. Dbl_leftshiftby1(opnd1p1,opnd1p2);
  239. if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
  240. Dbl_invert_sign(resultp1);
  241. Dbl_leftshiftby1(opnd2p1,opnd2p2);
  242. Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
  243. }
  244. /* check for remainder being exactly 1/2 of opnd2 */
  245. else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
  246. Dbl_invert_sign(resultp1);
  247. }
  248. /* normalize result's mantissa */
  249. while (Dbl_iszero_hidden(opnd1p1)) {
  250. dest_exponent--;
  251. Dbl_leftshiftby1(opnd1p1,opnd1p2);
  252. }
  253. Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
  254. /*
  255. * Test for underflow
  256. */
  257. testforunderflow:
  258. if (dest_exponent <= 0) {
  259. /* trap if UNDERFLOWTRAP enabled */
  260. if (Is_underflowtrap_enabled()) {
  261. /*
  262. * Adjust bias of result
  263. */
  264. Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
  265. /* frem is always exact */
  266. Dbl_copytoptr(resultp1,resultp2,dstptr);
  267. return(UNDERFLOWEXCEPTION);
  268. }
  269. /*
  270. * denormalize result or set to signed zero
  271. */
  272. if (dest_exponent >= (1 - DBL_P)) {
  273. Dbl_rightshift_exponentmantissa(resultp1,resultp2,
  274. 1-dest_exponent);
  275. }
  276. else {
  277. Dbl_setzero_exponentmantissa(resultp1,resultp2);
  278. }
  279. }
  280. else Dbl_set_exponent(resultp1,dest_exponent);
  281. Dbl_copytoptr(resultp1,resultp2,dstptr);
  282. return(NOEXCEPTION);
  283. }