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 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 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 262 quad_frnd(quad_floating_point *srcptr, quad_floating_point *dstptr, 263 unsigned int *status) 264 { 265 return(UNIMPLEMENTEDEXCEPTION); 266 } 267 268