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
27int
28sgl_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
129int
130dbl_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
230int
231quad_frnd(srcptr, null, dstptr, status)
232	quad_floating_point *srcptr, *null, *dstptr;
233	unsigned int *status;
234{
235	return(UNIMPLEMENTEDEXCEPTION);
236}
237