File Index
Files and directories
Sign in
FILE

sfrem.c

File preview with syntax highlighting.

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