1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
5 * Floating-point emulation code
6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
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
);