xref: /openbsd/sys/arch/hppa/spmath/frnd.c (revision 5b133f3f)
1 /*	$OpenBSD: frnd.c,v 1.9 2023/03/08 04:43:07 guenther 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 int
sgl_frnd(srcptr,null,dstptr,status)28 sgl_frnd(srcptr, null, dstptr, status)
29 	sgl_floating_point *srcptr, *null, *dstptr;
30 	unsigned int *status;
31 {
32 	register unsigned int src, result;
33 	register int src_exponent;
34 	register int inexact = FALSE;
35 
36 	src = *srcptr;
37 	/*
38 	 * check source operand for NaN or infinity
39 	 */
40 	if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
41 		/*
42 		 * is signaling NaN?
43 		 */
44 		if (Sgl_isone_signaling(src)) {
45 			/* trap if INVALIDTRAP enabled */
46 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
47 			/* make NaN quiet */
48 			Set_invalidflag();
49 			Sgl_set_quiet(src);
50 		}
51 		/*
52 		 * return quiet NaN or infinity
53 		 */
54 		*dstptr = src;
55 		return(NOEXCEPTION);
56 	}
57 	/*
58 	 * Need to round?
59 	 */
60 	if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
61 		*dstptr = src;
62 		return(NOEXCEPTION);
63 	}
64 	/*
65 	 * Generate result
66 	 */
67 	if (src_exponent >= 0) {
68 		Sgl_clear_exponent_set_hidden(src);
69 		result = src;
70 		Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
71 		/* check for inexact */
72 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
73 			inexact = TRUE;
74 			/*  round result  */
75 			switch (Rounding_mode()) {
76 			case ROUNDPLUS:
77 			     if (Sgl_iszero_sign(src)) Sgl_increment(result);
78 			     break;
79 			case ROUNDMINUS:
80 			     if (Sgl_isone_sign(src)) Sgl_increment(result);
81 			     break;
82 			case ROUNDNEAREST:
83 			     if (Sgl_isone_roundbit(src,src_exponent))
84 				if (Sgl_isone_stickybit(src,src_exponent)
85 				|| (Sgl_isone_lowmantissa(result)))
86 					Sgl_increment(result);
87 			}
88 		}
89 		Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
90 		if (Sgl_isone_hiddenoverflow(result))
91 			Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
92 		else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
93 	}
94 	else {
95 		result = src;		/* set sign */
96 		Sgl_setzero_exponentmantissa(result);
97 		/* check for inexact */
98 		if (Sgl_isnotzero_exponentmantissa(src)) {
99 			inexact = TRUE;
100 			/*  round result  */
101 			switch (Rounding_mode()) {
102 			case ROUNDPLUS:
103 			     if (Sgl_iszero_sign(src))
104 				Sgl_set_exponent(result,SGL_BIAS);
105 			     break;
106 			case ROUNDMINUS:
107 			     if (Sgl_isone_sign(src))
108 				Sgl_set_exponent(result,SGL_BIAS);
109 			     break;
110 			case ROUNDNEAREST:
111 			     if (src_exponent == -1)
112 				if (Sgl_isnotzero_mantissa(src))
113 				   Sgl_set_exponent(result,SGL_BIAS);
114 			}
115 		}
116 	}
117 	*dstptr = result;
118 	if (inexact) {
119 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
120 		else Set_inexactflag();
121 	}
122 	return(NOEXCEPTION);
123 }
124 
125 /*
126  *  Double Floating-point Round to Integer
127  */
128 
129 int
dbl_frnd(srcptr,null,dstptr,status)130 dbl_frnd(srcptr, null, dstptr, status)
131 	dbl_floating_point *srcptr, *null, *dstptr;
132 	unsigned int *status;
133 {
134 	register unsigned int srcp1, srcp2, resultp1, resultp2;
135 	register int src_exponent;
136 	register int inexact = FALSE;
137 
138 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
139 	/*
140 	 * check source operand for NaN or infinity
141 	 */
142 	if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
143 		/*
144 		 * is signaling NaN?
145 		 */
146 		if (Dbl_isone_signaling(srcp1)) {
147 			/* trap if INVALIDTRAP enabled */
148 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
149 			/* make NaN quiet */
150 			Set_invalidflag();
151 			Dbl_set_quiet(srcp1);
152 		}
153 		/*
154 		 * return quiet NaN or infinity
155 		 */
156 		Dbl_copytoptr(srcp1,srcp2,dstptr);
157 		return(NOEXCEPTION);
158 	}
159 	/*
160 	 * Need to round?
161 	 */
162 	if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
163 		Dbl_copytoptr(srcp1,srcp2,dstptr);
164 		return(NOEXCEPTION);
165 	}
166 	/*
167 	 * Generate result
168 	 */
169 	if (src_exponent >= 0) {
170 		Dbl_clear_exponent_set_hidden(srcp1);
171 		resultp1 = srcp1;
172 		resultp2 = srcp2;
173 		Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
174 		/* check for inexact */
175 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
176 			inexact = TRUE;
177 			/*  round result  */
178 			switch (Rounding_mode()) {
179 			case ROUNDPLUS:
180 			     if (Dbl_iszero_sign(srcp1))
181 				Dbl_increment(resultp1,resultp2);
182 			     break;
183 			case ROUNDMINUS:
184 			     if (Dbl_isone_sign(srcp1))
185 				Dbl_increment(resultp1,resultp2);
186 			     break;
187 			case ROUNDNEAREST:
188 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
189 			      if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
190 				  || (Dbl_isone_lowmantissap2(resultp2)))
191 					Dbl_increment(resultp1,resultp2);
192 			}
193 		}
194 		Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
195 		if (Dbl_isone_hiddenoverflow(resultp1))
196 			Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
197 		else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
198 	}
199 	else {
200 		resultp1 = srcp1;  /* set sign */
201 		Dbl_setzero_exponentmantissa(resultp1,resultp2);
202 		/* check for inexact */
203 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
204 			inexact = TRUE;
205 			/*  round result  */
206 			switch (Rounding_mode()) {
207 			case ROUNDPLUS:
208 			     if (Dbl_iszero_sign(srcp1))
209 				Dbl_set_exponent(resultp1,DBL_BIAS);
210 			     break;
211 			case ROUNDMINUS:
212 			     if (Dbl_isone_sign(srcp1))
213 				Dbl_set_exponent(resultp1,DBL_BIAS);
214 			     break;
215 			case ROUNDNEAREST:
216 			     if (src_exponent == -1)
217 				if (Dbl_isnotzero_mantissa(srcp1,srcp2))
218 				   Dbl_set_exponent(resultp1,DBL_BIAS);
219 			}
220 		}
221 	}
222 	Dbl_copytoptr(resultp1,resultp2,dstptr);
223 	if (inexact) {
224 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
225 		else Set_inexactflag();
226 	}
227 	return(NOEXCEPTION);
228 }
229 
230 int
quad_frnd(srcptr,null,dstptr,status)231 quad_frnd(srcptr, null, dstptr, status)
232 	quad_floating_point *srcptr, *null, *dstptr;
233 	unsigned int *status;
234 {
235 	return(UNIMPLEMENTEDEXCEPTION);
236 }
237