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/sfrem.c $Revision: 1.1 $
15 * Single Precision Floating-point Remainder
17 * External Interfaces:
18 * sgl_frem(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
23 * <<please update with a overview of the operation of this file>>
31 #include "sgl_float.h"
34 * Single Precision Floating-point Remainder
38 sgl_frem (sgl_floating_point
* srcptr1
, sgl_floating_point
* srcptr2
,
39 sgl_floating_point
* dstptr
, unsigned int *status
)
41 register unsigned int opnd1
, opnd2
, result
;
42 register int opnd1_exponent
, opnd2_exponent
, dest_exponent
, stepcount
;
43 register boolean roundup
= FALSE
;
48 * check first operand for NaN's or infinity
50 if ((opnd1_exponent
= Sgl_exponent(opnd1
)) == SGL_INFINITY_EXPONENT
) {
51 if (Sgl_iszero_mantissa(opnd1
)) {
52 if (Sgl_isnotnan(opnd2
)) {
53 /* invalid since first operand is infinity */
54 if (Is_invalidtrap_enabled())
55 return(INVALIDEXCEPTION
);
57 Sgl_makequietnan(result
);
64 * is NaN; signaling or quiet?
66 if (Sgl_isone_signaling(opnd1
)) {
67 /* trap if INVALIDTRAP enabled */
68 if (Is_invalidtrap_enabled())
69 return(INVALIDEXCEPTION
);
75 * is second operand a signaling NaN?
77 else if (Sgl_is_signalingnan(opnd2
)) {
78 /* trap if INVALIDTRAP enabled */
79 if (Is_invalidtrap_enabled())
80 return(INVALIDEXCEPTION
);
95 * check second operand for NaN's or infinity
97 if ((opnd2_exponent
= Sgl_exponent(opnd2
)) == SGL_INFINITY_EXPONENT
) {
98 if (Sgl_iszero_mantissa(opnd2
)) {
100 * return first operand
106 * is NaN; signaling or quiet?
108 if (Sgl_isone_signaling(opnd2
)) {
109 /* trap if INVALIDTRAP enabled */
110 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
113 Sgl_set_quiet(opnd2
);
122 * check second operand for zero
124 if (Sgl_iszero_exponentmantissa(opnd2
)) {
125 /* invalid since second operand is zero */
126 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
128 Sgl_makequietnan(result
);
139 * check for denormalized operands
141 if (opnd1_exponent
== 0) {
143 if (Sgl_iszero_mantissa(opnd1
)) {
147 /* normalize, then continue */
149 Sgl_normalize(opnd1
,opnd1_exponent
);
152 Sgl_clear_signexponent_set_hidden(opnd1
);
154 if (opnd2_exponent
== 0) {
155 /* normalize, then continue */
157 Sgl_normalize(opnd2
,opnd2_exponent
);
160 Sgl_clear_signexponent_set_hidden(opnd2
);
163 /* find result exponent and divide step loop count */
164 dest_exponent
= opnd2_exponent
- 1;
165 stepcount
= opnd1_exponent
- opnd2_exponent
;
168 * check for opnd1/opnd2 < 1
172 * check for opnd1/opnd2 > 1/2
174 * In this case n will round to 1, so
177 if (stepcount
== -1 && Sgl_isgreaterthan(opnd1
,opnd2
)) {
178 Sgl_all(result
) = ~Sgl_all(result
); /* set sign */
179 /* align opnd2 with opnd1 */
180 Sgl_leftshiftby1(opnd2
);
181 Sgl_subtract(opnd2
,opnd1
,opnd2
);
183 while (Sgl_iszero_hidden(opnd2
)) {
184 Sgl_leftshiftby1(opnd2
);
187 Sgl_set_exponentmantissa(result
,opnd2
);
188 goto testforunderflow
;
193 * In this case n will round to zero, so
196 Sgl_set_exponentmantissa(result
,opnd1
);
197 dest_exponent
= opnd1_exponent
;
198 goto testforunderflow
;
204 * Do iterative subtract until remainder is less than operand 2.
206 while (stepcount
-- > 0 && Sgl_all(opnd1
)) {
207 if (Sgl_isnotlessthan(opnd1
,opnd2
))
208 Sgl_subtract(opnd1
,opnd2
,opnd1
);
209 Sgl_leftshiftby1(opnd1
);
212 * Do last subtract, then determine which way to round if remainder
213 * is exactly 1/2 of opnd2
215 if (Sgl_isnotlessthan(opnd1
,opnd2
)) {
216 Sgl_subtract(opnd1
,opnd2
,opnd1
);
219 if (stepcount
> 0 || Sgl_iszero(opnd1
)) {
220 /* division is exact, remainder is zero */
221 Sgl_setzero_exponentmantissa(result
);
227 * Check for cases where opnd1/opnd2 < n
229 * In this case the result's sign will be opposite that of
230 * opnd1. The mantissa also needs some correction.
232 Sgl_leftshiftby1(opnd1
);
233 if (Sgl_isgreaterthan(opnd1
,opnd2
)) {
234 Sgl_invert_sign(result
);
235 Sgl_subtract((opnd2
<<1),opnd1
,opnd1
);
237 /* check for remainder being exactly 1/2 of opnd2 */
238 else if (Sgl_isequal(opnd1
,opnd2
) && roundup
) {
239 Sgl_invert_sign(result
);
242 /* normalize result's mantissa */
243 while (Sgl_iszero_hidden(opnd1
)) {
245 Sgl_leftshiftby1(opnd1
);
247 Sgl_set_exponentmantissa(result
,opnd1
);
253 if (dest_exponent
<= 0) {
254 /* trap if UNDERFLOWTRAP enabled */
255 if (Is_underflowtrap_enabled()) {
257 * Adjust bias of result
259 Sgl_setwrapped_exponent(result
,dest_exponent
,unfl
);
261 /* frem is always exact */
262 return(UNDERFLOWEXCEPTION
);
265 * denormalize result or set to signed zero
267 if (dest_exponent
>= (1 - SGL_P
)) {
268 Sgl_rightshift_exponentmantissa(result
,1-dest_exponent
);
271 Sgl_setzero_exponentmantissa(result
);
274 else Sgl_set_exponent(result
,dest_exponent
);