xref: /openbsd/sys/arch/hppa/spmath/frnd.c (revision 17df1aa7)
1 /*	$OpenBSD: frnd.c,v 1.8 2003/04/10 17:27:58 mickey Exp $	*/
2 /*
3   (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4   To anyone who acknowledges that this file is provided "AS IS"
5   without any express or implied warranty:
6       permission to use, copy, modify, and distribute this file
7   for any purpose is hereby granted without fee, provided that
8   the above copyright notice and this notice appears in all
9   copies, and that the name of Hewlett-Packard Company not be
10   used in advertising or publicity pertaining to distribution
11   of the software without specific, written prior permission.
12   Hewlett-Packard Company makes no representations about the
13   suitability of this software for any purpose.
14 */
15 /* @(#)frnd.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:24 */
16 
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "quad_float.h"
21 #include "cnv_float.h"
22 
23 /*
24  *  Single Floating-point Round to Integer
25  */
26 
27 /*ARGSUSED*/
28 int
29 sgl_frnd(srcptr, null, dstptr, status)
30 	sgl_floating_point *srcptr, *null, *dstptr;
31 	unsigned int *status;
32 {
33 	register unsigned int src, result;
34 	register int src_exponent;
35 	register int inexact = FALSE;
36 
37 	src = *srcptr;
38 	/*
39 	 * check source operand for NaN or infinity
40 	 */
41 	if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
42 		/*
43 		 * is signaling NaN?
44 		 */
45 		if (Sgl_isone_signaling(src)) {
46 			/* trap if INVALIDTRAP enabled */
47 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
48 			/* make NaN quiet */
49 			Set_invalidflag();
50 			Sgl_set_quiet(src);
51 		}
52 		/*
53 		 * return quiet NaN or infinity
54 		 */
55 		*dstptr = src;
56 		return(NOEXCEPTION);
57 	}
58 	/*
59 	 * Need to round?
60 	 */
61 	if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
62 		*dstptr = src;
63 		return(NOEXCEPTION);
64 	}
65 	/*
66 	 * Generate result
67 	 */
68 	if (src_exponent >= 0) {
69 		Sgl_clear_exponent_set_hidden(src);
70 		result = src;
71 		Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
72 		/* check for inexact */
73 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
74 			inexact = TRUE;
75 			/*  round result  */
76 			switch (Rounding_mode()) {
77 			case ROUNDPLUS:
78 			     if (Sgl_iszero_sign(src)) Sgl_increment(result);
79 			     break;
80 			case ROUNDMINUS:
81 			     if (Sgl_isone_sign(src)) Sgl_increment(result);
82 			     break;
83 			case ROUNDNEAREST:
84 			     if (Sgl_isone_roundbit(src,src_exponent))
85 				if (Sgl_isone_stickybit(src,src_exponent)
86 				|| (Sgl_isone_lowmantissa(result)))
87 					Sgl_increment(result);
88 			}
89 		}
90 		Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
91 		if (Sgl_isone_hiddenoverflow(result))
92 			Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
93 		else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
94 	}
95 	else {
96 		result = src;		/* set sign */
97 		Sgl_setzero_exponentmantissa(result);
98 		/* check for inexact */
99 		if (Sgl_isnotzero_exponentmantissa(src)) {
100 			inexact = TRUE;
101 			/*  round result  */
102 			switch (Rounding_mode()) {
103 			case ROUNDPLUS:
104 			     if (Sgl_iszero_sign(src))
105 				Sgl_set_exponent(result,SGL_BIAS);
106 			     break;
107 			case ROUNDMINUS:
108 			     if (Sgl_isone_sign(src))
109 				Sgl_set_exponent(result,SGL_BIAS);
110 			     break;
111 			case ROUNDNEAREST:
112 			     if (src_exponent == -1)
113 				if (Sgl_isnotzero_mantissa(src))
114 				   Sgl_set_exponent(result,SGL_BIAS);
115 			}
116 		}
117 	}
118 	*dstptr = result;
119 	if (inexact) {
120 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
121 		else Set_inexactflag();
122 	}
123 	return(NOEXCEPTION);
124 }
125 
126 /*
127  *  Double Floating-point Round to Integer
128  */
129 
130 /*ARGSUSED*/
131 int
132 dbl_frnd(srcptr, null, dstptr, status)
133 	dbl_floating_point *srcptr, *null, *dstptr;
134 	unsigned int *status;
135 {
136 	register unsigned int srcp1, srcp2, resultp1, resultp2;
137 	register int src_exponent;
138 	register int inexact = FALSE;
139 
140 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
141 	/*
142 	 * check source operand for NaN or infinity
143 	 */
144 	if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
145 		/*
146 		 * is signaling NaN?
147 		 */
148 		if (Dbl_isone_signaling(srcp1)) {
149 			/* trap if INVALIDTRAP enabled */
150 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
151 			/* make NaN quiet */
152 			Set_invalidflag();
153 			Dbl_set_quiet(srcp1);
154 		}
155 		/*
156 		 * return quiet NaN or infinity
157 		 */
158 		Dbl_copytoptr(srcp1,srcp2,dstptr);
159 		return(NOEXCEPTION);
160 	}
161 	/*
162 	 * Need to round?
163 	 */
164 	if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
165 		Dbl_copytoptr(srcp1,srcp2,dstptr);
166 		return(NOEXCEPTION);
167 	}
168 	/*
169 	 * Generate result
170 	 */
171 	if (src_exponent >= 0) {
172 		Dbl_clear_exponent_set_hidden(srcp1);
173 		resultp1 = srcp1;
174 		resultp2 = srcp2;
175 		Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
176 		/* check for inexact */
177 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
178 			inexact = TRUE;
179 			/*  round result  */
180 			switch (Rounding_mode()) {
181 			case ROUNDPLUS:
182 			     if (Dbl_iszero_sign(srcp1))
183 				Dbl_increment(resultp1,resultp2);
184 			     break;
185 			case ROUNDMINUS:
186 			     if (Dbl_isone_sign(srcp1))
187 				Dbl_increment(resultp1,resultp2);
188 			     break;
189 			case ROUNDNEAREST:
190 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
191 			      if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
192 				  || (Dbl_isone_lowmantissap2(resultp2)))
193 					Dbl_increment(resultp1,resultp2);
194 			}
195 		}
196 		Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
197 		if (Dbl_isone_hiddenoverflow(resultp1))
198 			Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
199 		else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
200 	}
201 	else {
202 		resultp1 = srcp1;  /* set sign */
203 		Dbl_setzero_exponentmantissa(resultp1,resultp2);
204 		/* check for inexact */
205 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
206 			inexact = TRUE;
207 			/*  round result  */
208 			switch (Rounding_mode()) {
209 			case ROUNDPLUS:
210 			     if (Dbl_iszero_sign(srcp1))
211 				Dbl_set_exponent(resultp1,DBL_BIAS);
212 			     break;
213 			case ROUNDMINUS:
214 			     if (Dbl_isone_sign(srcp1))
215 				Dbl_set_exponent(resultp1,DBL_BIAS);
216 			     break;
217 			case ROUNDNEAREST:
218 			     if (src_exponent == -1)
219 				if (Dbl_isnotzero_mantissa(srcp1,srcp2))
220 				   Dbl_set_exponent(resultp1,DBL_BIAS);
221 			}
222 		}
223 	}
224 	Dbl_copytoptr(resultp1,resultp2,dstptr);
225 	if (inexact) {
226 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
227 		else Set_inexactflag();
228 	}
229 	return(NOEXCEPTION);
230 }
231 
232 /*ARGSUSED*/
233 int
234 quad_frnd(srcptr, null, dstptr, status)
235 	quad_floating_point *srcptr, *null, *dstptr;
236 	unsigned int *status;
237 {
238 	return(UNIMPLEMENTEDEXCEPTION);
239 }
240