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