File Index
Files and directories
Sign in
FILE

dfrem.c

File preview with syntax highlighting.

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