xref: /openbsd/sys/arch/hppa/spmath/fcnvff.c (revision 5b133f3f)
1 /*	$OpenBSD: fcnvff.c,v 1.8 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 /* @(#)fcnvff.c: Revision: 2.8.88.1 Date: 93/12/07 15:06:09 */
16 
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "cnv_float.h"
21 
22 /*
23  *  Single Floating-point to Double Floating-point
24  */
25 int
sgl_to_dbl_fcnvff(srcptr,null,dstptr,status)26 sgl_to_dbl_fcnvff(srcptr, null, dstptr, status)
27 	sgl_floating_point *srcptr, *null;
28 	dbl_floating_point *dstptr;
29 	unsigned int *status;
30 {
31 	register unsigned int src, resultp1, resultp2;
32 	register int src_exponent;
33 
34 	src = *srcptr;
35 	src_exponent = Sgl_exponent(src);
36 	Dbl_allp1(resultp1) = Sgl_all(src);  /* set sign of result */
37 	/*
38 	 * Test for NaN or infinity
39 	 */
40 	if (src_exponent == SGL_INFINITY_EXPONENT) {
41 		/*
42 		 * determine if NaN or infinity
43 		 */
44 		if (Sgl_iszero_mantissa(src)) {
45 			/*
46 			 * is infinity; want to return double infinity
47 			 */
48 			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
49 			Dbl_copytoptr(resultp1,resultp2,dstptr);
50 			return(NOEXCEPTION);
51 		}
52 		else {
53 			/*
54 			 * is NaN; signaling or quiet?
55 			 */
56 			if (Sgl_isone_signaling(src)) {
57 				/* trap if INVALIDTRAP enabled */
58 				if (Is_invalidtrap_enabled())
59 					return(INVALIDEXCEPTION);
60 				/* make NaN quiet */
61 				else {
62 					Set_invalidflag();
63 					Sgl_set_quiet(src);
64 				}
65 			}
66 			/*
67 			 * NaN is quiet, return as double NaN
68 			 */
69 			Dbl_setinfinity_exponent(resultp1);
70 			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
71 			Dbl_copytoptr(resultp1,resultp2,dstptr);
72 			return(NOEXCEPTION);
73 		}
74 	}
75 	/*
76 	 * Test for zero or denormalized
77 	 */
78 	if (src_exponent == 0) {
79 		/*
80 		 * determine if zero or denormalized
81 		 */
82 		if (Sgl_isnotzero_mantissa(src)) {
83 			/*
84 			 * is denormalized; want to normalize
85 			 */
86 			Sgl_clear_signexponent(src);
87 			Sgl_leftshiftby1(src);
88 			Sgl_normalize(src,src_exponent);
89 			Sgl_to_dbl_exponent(src_exponent,resultp1);
90 			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
91 		}
92 		else {
93 			Dbl_setzero_exponentmantissa(resultp1,resultp2);
94 		}
95 		Dbl_copytoptr(resultp1,resultp2,dstptr);
96 		return(NOEXCEPTION);
97 	}
98 	/*
99 	 * No special cases, just complete the conversion
100 	 */
101 	Sgl_to_dbl_exponent(src_exponent, resultp1);
102 	Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
103 	Dbl_copytoptr(resultp1,resultp2,dstptr);
104 	return(NOEXCEPTION);
105 }
106 
107 /*
108  *  Double Floating-point to Single Floating-point
109  */
110 int
dbl_to_sgl_fcnvff(srcptr,null,dstptr,status)111 dbl_to_sgl_fcnvff(srcptr, null, dstptr, status)
112 	dbl_floating_point *srcptr, *null;
113 	sgl_floating_point *dstptr;
114 	unsigned int *status;
115 {
116 	register unsigned int srcp1, srcp2, result;
117 	register int src_exponent, dest_exponent, dest_mantissa;
118 	register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
119 	register int lsb_odd = FALSE;
120 	int is_tiny;
121 
122 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
123 	src_exponent = Dbl_exponent(srcp1);
124 	Sgl_all(result) = Dbl_allp1(srcp1);  /* set sign of result */
125 	/*
126 	 * Test for NaN or infinity
127 	 */
128 	if (src_exponent == DBL_INFINITY_EXPONENT) {
129 		/*
130 		 * determine if NaN or infinity
131 		 */
132 		if (Dbl_iszero_mantissa(srcp1,srcp2)) {
133 			/*
134 			 * is infinity; want to return single infinity
135 			 */
136 			Sgl_setinfinity_exponentmantissa(result);
137 			*dstptr = result;
138 			return(NOEXCEPTION);
139 		}
140 		/*
141 		 * is NaN; signaling or quiet?
142 		 */
143 		if (Dbl_isone_signaling(srcp1)) {
144 			/* trap if INVALIDTRAP enabled */
145 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
146 			else {
147 				Set_invalidflag();
148 				/* make NaN quiet */
149 				Dbl_set_quiet(srcp1);
150 			}
151 		}
152 		/*
153 		 * NaN is quiet, return as single NaN
154 		 */
155 		Sgl_setinfinity_exponent(result);
156 		Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
157 		if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
158 		*dstptr = result;
159 		return(NOEXCEPTION);
160 	}
161 	/*
162 	 * Generate result
163 	 */
164 	Dbl_to_sgl_exponent(src_exponent,dest_exponent);
165 	if (dest_exponent > 0) {
166 		Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
167 		stickybit,lsb_odd);
168 	}
169 	else {
170 		if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
171 			Sgl_setzero_exponentmantissa(result);
172 			*dstptr = result;
173 			return(NOEXCEPTION);
174 		}
175 		if (Is_underflowtrap_enabled()) {
176 			Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
177 			guardbit,stickybit,lsb_odd);
178 		}
179 		else {
180 			/* compute result, determine inexact info,
181 			 * and set Underflowflag if appropriate
182 			 */
183 			Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
184 			dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
185 			is_tiny);
186 		}
187 	}
188 	/*
189 	 * Now round result if not exact
190 	 */
191 	if (inexact) {
192 		switch (Rounding_mode()) {
193 			case ROUNDPLUS:
194 				if (Sgl_iszero_sign(result)) dest_mantissa++;
195 				break;
196 			case ROUNDMINUS:
197 				if (Sgl_isone_sign(result)) dest_mantissa++;
198 				break;
199 			case ROUNDNEAREST:
200 				if (guardbit) {
201 				   if (stickybit || lsb_odd) dest_mantissa++;
202 				   }
203 		}
204 	}
205 	Sgl_set_exponentmantissa(result,dest_mantissa);
206 
207 	/*
208 	 * check for mantissa overflow after rounding
209 	 */
210 	if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
211 	    Sgl_isone_hidden(result)) dest_exponent++;
212 
213 	/*
214 	 * Test for overflow
215 	 */
216 	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
217 		/* trap if OVERFLOWTRAP enabled */
218 		if (Is_overflowtrap_enabled()) {
219 			/*
220 			 * Check for gross overflow
221 			 */
222 			if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
223 				return(UNIMPLEMENTEDEXCEPTION);
224 
225 			/*
226 			 * Adjust bias of result
227 			 */
228 			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
229 			*dstptr = result;
230 			if (inexact) {
231 			    if (Is_inexacttrap_enabled())
232 				return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
233 			    else
234 				Set_inexactflag();
235 			}
236 			return(OVERFLOWEXCEPTION);
237 		}
238 		Set_overflowflag();
239 		inexact = TRUE;
240 		/* set result to infinity or largest number */
241 		Sgl_setoverflow(result);
242 	}
243 	/*
244 	 * Test for underflow
245 	 */
246 	else if (dest_exponent <= 0) {
247 		/* trap if UNDERFLOWTRAP enabled */
248 		if (Is_underflowtrap_enabled()) {
249 			/*
250 			 * Check for gross underflow
251 			 */
252 			if (dest_exponent <= -(SGL_WRAP))
253 				return(UNIMPLEMENTEDEXCEPTION);
254 			/*
255 			 * Adjust bias of result
256 			 */
257 			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
258 			*dstptr = result;
259 			if (inexact) {
260 			    if (Is_inexacttrap_enabled())
261 				return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
262 			    else
263 				Set_inexactflag();
264 			}
265 			return(UNDERFLOWEXCEPTION);
266 		}
267 		 /*
268 		  * result is denormalized or signed zero
269 		  */
270 	       if (inexact && is_tiny) Set_underflowflag();
271 
272 	}
273 	else Sgl_set_exponent(result,dest_exponent);
274 	*dstptr = result;
275 	/*
276 	 * Trap if inexact trap is enabled
277 	 */
278 	if (inexact) {
279 		if (Is_inexacttrap_enabled())
280 			return(INEXACTEXCEPTION);
281 		else
282 			Set_inexactflag();
283 	}
284 	return(NOEXCEPTION);
285 }
286