1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
5 * Floating-point emulation code
12 * @(#) pa/spmath/dfrem.c $Revision: 1.1 $
15 * Double Precision Floating-point Remainder
17 * External Interfaces:
18 * dbl_frem(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
23 * <<please update with a overview of the operation of this file>>
31 #include "dbl_float.h"
34 * Double Precision Floating-point Remainder
38 dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
39 dbl_floating_point * dstptr, unsigned int *status)
41 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
42 register unsigned int resultp1, resultp2;
43 register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
44 register boolean roundup = FALSE;
46 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
47 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
49 * check first operand for NaN's or infinity
51 if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
52 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
53 if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
54 /* invalid since first operand is infinity */
55 if (Is_invalidtrap_enabled())
56 return(INVALIDEXCEPTION);
58 Dbl_makequietnan(resultp1,resultp2);
59 Dbl_copytoptr(resultp1,resultp2,dstptr);
65 * is NaN; signaling or quiet?
67 if (Dbl_isone_signaling(opnd1p1)) {
68 /* trap if INVALIDTRAP enabled */
69 if (Is_invalidtrap_enabled())
70 return(INVALIDEXCEPTION);
73 Dbl_set_quiet(opnd1p1);
76 * is second operand a signaling NaN?
78 else if (Dbl_is_signalingnan(opnd2p1)) {
79 /* trap if INVALIDTRAP enabled */
80 if (Is_invalidtrap_enabled())
81 return(INVALIDEXCEPTION);
84 Dbl_set_quiet(opnd2p1);
85 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
91 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
96 * check second operand for NaN's or infinity
98 if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
99 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
101 * return first operand
103 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
107 * is NaN; signaling or quiet?
109 if (Dbl_isone_signaling(opnd2p1)) {
110 /* trap if INVALIDTRAP enabled */
111 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
114 Dbl_set_quiet(opnd2p1);
119 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
123 * check second operand for zero
125 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
126 /* invalid since second operand is zero */
127 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
129 Dbl_makequietnan(resultp1,resultp2);
130 Dbl_copytoptr(resultp1,resultp2,dstptr);
140 * check for denormalized operands
142 if (opnd1_exponent == 0) {
144 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
145 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
148 /* normalize, then continue */
150 Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
153 Dbl_clear_signexponent_set_hidden(opnd1p1);
155 if (opnd2_exponent == 0) {
156 /* normalize, then continue */
158 Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
161 Dbl_clear_signexponent_set_hidden(opnd2p1);
164 /* find result exponent and divide step loop count */
165 dest_exponent = opnd2_exponent - 1;
166 stepcount = opnd1_exponent - opnd2_exponent;
169 * check for opnd1/opnd2 < 1
173 * check for opnd1/opnd2 > 1/2
175 * In this case n will round to 1, so
178 if (stepcount == -1 &&
179 Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
181 Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
182 /* align opnd2 with opnd1 */
183 Dbl_leftshiftby1(opnd2p1,opnd2p2);
184 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
187 while (Dbl_iszero_hidden(opnd2p1)) {
188 Dbl_leftshiftby1(opnd2p1,opnd2p2);
191 Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
192 goto testforunderflow;
197 * In this case n will round to zero, so
200 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
201 dest_exponent = opnd1_exponent;
202 goto testforunderflow;
208 * Do iterative subtract until remainder is less than operand 2.
210 while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
211 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
212 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
214 Dbl_leftshiftby1(opnd1p1,opnd1p2);
217 * Do last subtract, then determine which way to round if remainder
218 * is exactly 1/2 of opnd2
220 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
221 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
224 if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
225 /* division is exact, remainder is zero */
226 Dbl_setzero_exponentmantissa(resultp1,resultp2);
227 Dbl_copytoptr(resultp1,resultp2,dstptr);
232 * Check for cases where opnd1/opnd2 < n
234 * In this case the result's sign will be opposite that of
235 * opnd1. The mantissa also needs some correction.
237 Dbl_leftshiftby1(opnd1p1,opnd1p2);
238 if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
239 Dbl_invert_sign(resultp1);
240 Dbl_leftshiftby1(opnd2p1,opnd2p2);
241 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
243 /* check for remainder being exactly 1/2 of opnd2 */
244 else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
245 Dbl_invert_sign(resultp1);
248 /* normalize result's mantissa */
249 while (Dbl_iszero_hidden(opnd1p1)) {
251 Dbl_leftshiftby1(opnd1p1,opnd1p2);
253 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
259 if (dest_exponent <= 0) {
260 /* trap if UNDERFLOWTRAP enabled */
261 if (Is_underflowtrap_enabled()) {
263 * Adjust bias of result
265 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
266 /* frem is always exact */
267 Dbl_copytoptr(resultp1,resultp2,dstptr);
268 return(UNDERFLOWEXCEPTION);
271 * denormalize result or set to signed zero
273 if (dest_exponent >= (1 - DBL_P)) {
274 Dbl_rightshift_exponentmantissa(resultp1,resultp2,
278 Dbl_setzero_exponentmantissa(resultp1,resultp2);
281 else Dbl_set_exponent(resultp1,dest_exponent);
282 Dbl_copytoptr(resultp1,resultp2,dstptr);