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