xref: /netbsd/sys/arch/hppa/spmath/fcnvfx.c (revision c4a72b64)
1 /*	$NetBSD: fcnvfx.c,v 1.1 2002/06/05 01:04:25 fredette Exp $	*/
2 
3 /*	$OpenBSD: fcnvfx.c,v 1.5 2001/03/29 03:58:18 mickey Exp $	*/
4 
5 /*
6  * Copyright 1996 1995 by Open Software Foundation, Inc.
7  *              All Rights Reserved
8  *
9  * Permission to use, copy, modify, and distribute this software and
10  * its documentation for any purpose and without fee is hereby granted,
11  * provided that the above copyright notice appears in all copies and
12  * that both the copyright notice and this permission notice appear in
13  * supporting documentation.
14  *
15  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17  * FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  */
26 /*
27  * pmk1.1
28  */
29 /*
30  * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
31  *
32  * To anyone who acknowledges that this file is provided "AS IS"
33  * without any express or implied warranty:
34  *     permission to use, copy, modify, and distribute this file
35  * for any purpose is hereby granted without fee, provided that
36  * the above copyright notice and this notice appears in all
37  * copies, and that the name of Hewlett-Packard Company not be
38  * used in advertising or publicity pertaining to distribution
39  * of the software without specific, written prior permission.
40  * Hewlett-Packard Company makes no representations about the
41  * suitability of this software for any purpose.
42  */
43 
44 #include "../spmath/float.h"
45 #include "../spmath/sgl_float.h"
46 #include "../spmath/dbl_float.h"
47 #include "../spmath/cnv_float.h"
48 
49 /*
50  *  Single Floating-point to Single Fixed-point
51  */
52 /*ARGSUSED*/
53 int
54 sgl_to_sgl_fcnvfx(srcptr,dstptr,status)
55 
56 sgl_floating_point *srcptr;
57 int *dstptr;
58 unsigned int *status;
59 {
60 	register unsigned int src, temp;
61 	register int src_exponent, result;
62 	register int inexact = FALSE;
63 
64 	src = *srcptr;
65 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
66 
67 	/*
68 	 * Test for overflow
69 	 */
70 	if (src_exponent > SGL_FX_MAX_EXP) {
71 		/* check for MININT */
72 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
73 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
74 			/*
75 			 * Since source is a number which cannot be
76 			 * represented in fixed-point format, return
77 			 * largest (or smallest) fixed-point number.
78 			 */
79 			Sgl_return_overflow(src,dstptr);
80 		}
81 	}
82 	/*
83 	 * Generate result
84 	 */
85 	if (src_exponent >= 0) {
86 		temp = src;
87 		Sgl_clear_signexponent_set_hidden(temp);
88 		Int_from_sgl_mantissa(temp,src_exponent);
89 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
90 		else result = Sgl_all(temp);
91 
92 		/* check for inexact */
93 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
94 			inexact = TRUE;
95 			/*  round result  */
96 			switch (Rounding_mode()) {
97 			case ROUNDPLUS:
98 			     if (Sgl_iszero_sign(src)) result++;
99 			     break;
100 			case ROUNDMINUS:
101 			     if (Sgl_isone_sign(src)) result--;
102 			     break;
103 			case ROUNDNEAREST:
104 			     if (Sgl_isone_roundbit(src,src_exponent)) {
105 				if (Sgl_isone_stickybit(src,src_exponent)
106 				|| (Sgl_isone_lowmantissa(temp))) {
107 				   if (Sgl_iszero_sign(src)) result++;
108 				   else result--;
109 				}
110 			     }
111 			}
112 		}
113 	}
114 	else {
115 		result = 0;
116 
117 		/* check for inexact */
118 		if (Sgl_isnotzero_exponentmantissa(src)) {
119 			inexact = TRUE;
120 			/*  round result  */
121 			switch (Rounding_mode()) {
122 			case ROUNDPLUS:
123 			     if (Sgl_iszero_sign(src)) result++;
124 			     break;
125 			case ROUNDMINUS:
126 			     if (Sgl_isone_sign(src)) result--;
127 			     break;
128 			case ROUNDNEAREST:
129 			     if (src_exponent == -1)
130 				if (Sgl_isnotzero_mantissa(src)) {
131 				   if (Sgl_iszero_sign(src)) result++;
132 				   else result--;
133 				}
134 			}
135 		}
136 	}
137 	*dstptr = result;
138 	if (inexact) {
139 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
140 		else Set_inexactflag();
141 	}
142 	return(NOEXCEPTION);
143 }
144 
145 /*
146  *  Single Floating-point to Double Fixed-point
147  */
148 /*ARGSUSED*/
149 int
150 sgl_to_dbl_fcnvfx(srcptr,dstptr,status)
151 
152 sgl_floating_point *srcptr;
153 dbl_integer *dstptr;
154 unsigned int *status;
155 {
156 	register int src_exponent, resultp1;
157 	register unsigned int src, temp, resultp2;
158 	register int inexact = FALSE;
159 
160 	src = *srcptr;
161 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
162 
163 	/*
164 	 * Test for overflow
165 	 */
166 	if (src_exponent > DBL_FX_MAX_EXP) {
167 		/* check for MININT */
168 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
169 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
170 			/*
171 			 * Since source is a number which cannot be
172 			 * represented in fixed-point format, return
173 			 * largest (or smallest) fixed-point number.
174 			 */
175 			Sgl_return_overflow_dbl(src,dstptr);
176 		}
177 		Dint_set_minint(resultp1,resultp2);
178 		Dint_copytoptr(resultp1,resultp2,dstptr);
179 		return(NOEXCEPTION);
180 	}
181 	/*
182 	 * Generate result
183 	 */
184 	if (src_exponent >= 0) {
185 		temp = src;
186 		Sgl_clear_signexponent_set_hidden(temp);
187 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
188 		if (Sgl_isone_sign(src)) {
189 			Dint_setone_sign(resultp1,resultp2);
190 		}
191 
192 		/* check for inexact */
193 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
194 			inexact = TRUE;
195 			/*  round result  */
196 			switch (Rounding_mode()) {
197 			case ROUNDPLUS:
198 			     if (Sgl_iszero_sign(src)) {
199 				Dint_increment(resultp1,resultp2);
200 			     }
201 			     break;
202 			case ROUNDMINUS:
203 			     if (Sgl_isone_sign(src)) {
204 				Dint_decrement(resultp1,resultp2);
205 			     }
206 			     break;
207 			case ROUNDNEAREST:
208 			     if (Sgl_isone_roundbit(src,src_exponent))
209 				if (Sgl_isone_stickybit(src,src_exponent) ||
210 				(Dint_isone_lowp2(resultp2))) {
211 				   if (Sgl_iszero_sign(src)) {
212 				      Dint_increment(resultp1,resultp2);
213 				   }
214 				   else {
215 				      Dint_decrement(resultp1,resultp2);
216 				   }
217 				}
218 			}
219 		}
220 	}
221 	else {
222 		Dint_setzero(resultp1,resultp2);
223 
224 		/* check for inexact */
225 		if (Sgl_isnotzero_exponentmantissa(src)) {
226 			inexact = TRUE;
227 			/*  round result  */
228 			switch (Rounding_mode()) {
229 			case ROUNDPLUS:
230 			     if (Sgl_iszero_sign(src)) {
231 				Dint_increment(resultp1,resultp2);
232 			     }
233 			     break;
234 			case ROUNDMINUS:
235 			     if (Sgl_isone_sign(src)) {
236 				Dint_decrement(resultp1,resultp2);
237 			     }
238 			     break;
239 			case ROUNDNEAREST:
240 			     if (src_exponent == -1)
241 				if (Sgl_isnotzero_mantissa(src)) {
242 				   if (Sgl_iszero_sign(src)) {
243 				      Dint_increment(resultp1,resultp2);
244 				   }
245 				   else {
246 				      Dint_decrement(resultp1,resultp2);
247 				   }
248 				}
249 			}
250 		}
251 	}
252 	Dint_copytoptr(resultp1,resultp2,dstptr);
253 	if (inexact) {
254 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
255 		else Set_inexactflag();
256 	}
257 	return(NOEXCEPTION);
258 }
259 
260 /*
261  *  Double Floating-point to Single Fixed-point
262  */
263 /*ARGSUSED*/
264 int
265 dbl_to_sgl_fcnvfx(srcptr,dstptr,status)
266 
267 dbl_floating_point *srcptr;
268 int *dstptr;
269 unsigned int *status;
270 {
271 	register unsigned int srcp1,srcp2, tempp1,tempp2;
272 	register int src_exponent, result;
273 	register int inexact = FALSE;
274 
275 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
276 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
277 
278 	/*
279 	 * Test for overflow
280 	 */
281 	if (src_exponent > SGL_FX_MAX_EXP) {
282 		/* check for MININT */
283 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
284 			/*
285 			 * Since source is a number which cannot be
286 			 * represented in fixed-point format, return
287 			 * largest (or smallest) fixed-point number.
288 			 */
289 			Dbl_return_overflow(srcp1,srcp2,dstptr);
290 		}
291 	}
292 	/*
293 	 * Generate result
294 	 */
295 	if (src_exponent >= 0) {
296 		tempp1 = srcp1;
297 		tempp2 = srcp2;
298 		Dbl_clear_signexponent_set_hidden(tempp1);
299 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
300 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
301 			result = -Dbl_allp1(tempp1);
302 		else result = Dbl_allp1(tempp1);
303 
304 		/* check for inexact */
305 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
306 			inexact = TRUE;
307 			/*  round result  */
308 			switch (Rounding_mode()) {
309 			case ROUNDPLUS:
310 			     if (Dbl_iszero_sign(srcp1)) result++;
311 			     break;
312 			case ROUNDMINUS:
313 			     if (Dbl_isone_sign(srcp1)) result--;
314 			     break;
315 			case ROUNDNEAREST:
316 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
317 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
318 				(Dbl_isone_lowmantissap1(tempp1))) {
319 				   if (Dbl_iszero_sign(srcp1)) result++;
320 				   else result--;
321 				}
322 			}
323 			/* check for overflow */
324 			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
325 			    (Dbl_isone_sign(srcp1) && result > 0)) {
326 				Dbl_return_overflow(srcp1,srcp2,dstptr);
327 			}
328 		}
329 	}
330 	else {
331 		result = 0;
332 
333 		/* check for inexact */
334 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
335 			inexact = TRUE;
336 			/*  round result  */
337 			switch (Rounding_mode()) {
338 			case ROUNDPLUS:
339 			     if (Dbl_iszero_sign(srcp1)) result++;
340 			     break;
341 			case ROUNDMINUS:
342 			     if (Dbl_isone_sign(srcp1)) result--;
343 			     break;
344 			case ROUNDNEAREST:
345 			     if (src_exponent == -1)
346 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
347 				   if (Dbl_iszero_sign(srcp1)) result++;
348 				   else result--;
349 				}
350 			}
351 		}
352 	}
353 	*dstptr = result;
354 	if (inexact) {
355 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
356 		else Set_inexactflag();
357 	}
358 	return(NOEXCEPTION);
359 }
360 
361 /*
362  *  Double Floating-point to Double Fixed-point
363  */
364 /*ARGSUSED*/
365 int
366 dbl_to_dbl_fcnvfx(srcptr,dstptr,status)
367 
368 dbl_floating_point *srcptr;
369 dbl_integer *dstptr;
370 unsigned int *status;
371 {
372 	register int src_exponent, resultp1;
373 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
374 	register int inexact = FALSE;
375 
376 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
377 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
378 
379 	/*
380 	 * Test for overflow
381 	 */
382 	if (src_exponent > DBL_FX_MAX_EXP) {
383 		/* check for MININT */
384 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
385 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
386 			/*
387 			 * Since source is a number which cannot be
388 			 * represented in fixed-point format, return
389 			 * largest (or smallest) fixed-point number.
390 			 */
391 			Dbl_return_overflow_dbl(srcp1,srcp2,dstptr);
392 		}
393 	}
394 
395 	/*
396 	 * Generate result
397 	 */
398 	if (src_exponent >= 0) {
399 		tempp1 = srcp1;
400 		tempp2 = srcp2;
401 		Dbl_clear_signexponent_set_hidden(tempp1);
402 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
403 				       resultp1, resultp2);
404 		if (Dbl_isone_sign(srcp1)) {
405 			Dint_setone_sign(resultp1,resultp2);
406 		}
407 
408 		/* check for inexact */
409 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
410 			inexact = TRUE;
411 			/*  round result  */
412 			switch (Rounding_mode()) {
413 			case ROUNDPLUS:
414 			     if (Dbl_iszero_sign(srcp1)) {
415 				Dint_increment(resultp1,resultp2);
416 			     }
417 			     break;
418 			case ROUNDMINUS:
419 			     if (Dbl_isone_sign(srcp1)) {
420 				Dint_decrement(resultp1,resultp2);
421 			     }
422 			     break;
423 			case ROUNDNEAREST:
424 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
425 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
426 				(Dint_isone_lowp2(resultp2))) {
427 				   if (Dbl_iszero_sign(srcp1)) {
428 				      Dint_increment(resultp1,resultp2);
429 				   }
430 				   else {
431 				      Dint_decrement(resultp1,resultp2);
432 				   }
433 				}
434 			}
435 		}
436 	}
437 	else {
438 		Dint_setzero(resultp1,resultp2);
439 
440 		/* check for inexact */
441 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
442 			inexact = TRUE;
443 			/*  round result  */
444 			switch (Rounding_mode()) {
445 			case ROUNDPLUS:
446 			     if (Dbl_iszero_sign(srcp1)) {
447 				Dint_increment(resultp1,resultp2);
448 			     }
449 			     break;
450 			case ROUNDMINUS:
451 			     if (Dbl_isone_sign(srcp1)) {
452 				Dint_decrement(resultp1,resultp2);
453 			     }
454 			     break;
455 			case ROUNDNEAREST:
456 			     if (src_exponent == -1)
457 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
458 				   if (Dbl_iszero_sign(srcp1)) {
459 				      Dint_increment(resultp1,resultp2);
460 				   }
461 				   else {
462 				      Dint_decrement(resultp1,resultp2);
463 				   }
464 				}
465 			}
466 		}
467 	}
468 	Dint_copytoptr(resultp1,resultp2,dstptr);
469 	if (inexact) {
470 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
471 		else Set_inexactflag();
472 	}
473 	return(NOEXCEPTION);
474 }
475